Merge branch 'dev_aliyun' into dev_cxt2

dev_cxt2
cxt 5 years ago
commit 21fc99b8e2

@ -60,7 +60,7 @@ class Admins::CompetitionStagesController < Admins::BaseController
end
# 如果计算的是最后一个阶段,则同时计算总成绩(只有一个阶段则不需计算)
if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size != 0
if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size > 1
calculate_total_score current_competition
end
end
@ -174,6 +174,7 @@ class Admins::CompetitionStagesController < Admins::BaseController
end
def calculate_total_score competition
competition.competition_scores.where(competition_stage_id: 0).destroy_all
competition.competition_teams.each do |team|
total_score = 0
total_time = 0
@ -183,8 +184,11 @@ class Admins::CompetitionStagesController < Admins::BaseController
total_score += stage_score.try(:score).to_f * stage.score_rate
total_time += stage_score.try(:cost_time).to_i
end
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
competition_stage_id: 0, score: total_score, cost_time: total_time)
unless team.competition_scores.exists?(competition_id: competition.id, competition_stage_id: 0)
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
competition_stage_id: 0, score: total_score, cost_time: total_time)
end
end
end
end

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

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

@ -11,9 +11,9 @@ class Competitions::CertificatesController < Competitions::BaseController
end
def team
team = CompetitionTeam.find(id: params[:id])
team = CompetitionTeam.find(params[:id])
return render_forbidden unless team.team_members.exists?(user_id: current_user.id)
return render_not_found unless team.certificate_exist?
return render_not_found unless team.certificate_exists?
prize = team.competition_prize_users.first.competition_prize
filename = "#{current_competition.name}-#{prize.name}-#{team.name}.pdf"

@ -7,7 +7,7 @@ class Competitions::CompetitionModulesController < Competitions::BaseController
@modules = current_competition.unhidden_competition_modules.order(position: :asc)
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.competition_prize_users.exists?(user: current_user)
if !current_user.logged? || !current_competition.finished? || !current_competition.competition_prize_users.exists?(user: current_user)
@modules = @modules.select { |mod| mod.name != '获奖证书' }
end
end

@ -44,6 +44,12 @@ class Competitions::CompetitionsController < Competitions::BaseController
def common_header
@competition = current_competition
@competition_modules = @competition.unhidden_competition_modules
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.finished? || !current_competition.competition_prize_users.exists?(user: current_user)
@competition_modules = @competition_modules.select { |mod| mod.name != '获奖证书' }
end
@user = current_user
current_competition.increment!(:visits)
@ -113,6 +119,8 @@ class Competitions::CompetitionsController < Competitions::BaseController
@competition = current_competition
if params[:stage_id]
@stage = @competition.competition_stages.find_by(id: params[:stage_id])
elsif @competition.competition_stages.count == 1
@stage = @competition.competition_stages.take
end
@records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})

@ -2,9 +2,9 @@ class Competitions::PrizesController < Competitions::BaseController
before_action :require_prize_user!
def show
self_prizes = current_competition.competition_prize_users.where(user_id: current_user.id).includes(:competition_team)
self_prizes = current_competition.competition_prize_users.where(user_id: current_user.id).includes(:competition_team).order(:competition_prize_id)
@leader = self_prizes.any?(&:leader?) # 是否为队长
@leader = self_prizes.any?{ |prize_user| prize_user.leader? && prize_user.competition_prize.category == 'bonus' } # 是否为队长并且有奖金奖励
if @leader
@bank_account = self_prizes.find(&:leader?).extra
@bank_account_editable = self_prizes.select(&:leader?).all?(&:pending?)

@ -1084,14 +1084,23 @@ class ExercisesController < ApplicationController
@shixun_undo = 0
@ques_undo = 0
ex_answer_time = @exercise.time.to_i
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
if ex_answer_time > 0
exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
if exercise_end_time.present?
ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
@ex_end_time = ex_end_times + ex_answer_time.minutes
end
if ex_answer_time > 0 #有剩余时间的时候
user_left_time = get_exercise_left_time(@exercise,current_user)
@ex_end_time = Time.now + user_left_time.to_i.seconds
else
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
end
# @ex_end_time = @exercise.get_exercise_end_time(current_user.id)
# if ex_answer_time > 0
# left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到
# if left_answer_time < @ex_end_time
# exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
# if exercise_end_time.present?
# ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
# @ex_end_time = ex_end_times + ex_answer_time.minutes
# end
# end
# end
@exercise_questions.each do |q|
if q.question_type == Exercise::PRACTICAL #当为实训题时
user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id)

@ -290,6 +290,7 @@ class GamesController < ApplicationController
answer_deduction = challenge.challenge_answers.where("level <= #{@answer.level}").sum(:score)
@game.update_attributes!(:answer_open => answer_open, :answer_deduction => answer_deduction)
end
GameAnswer.create!(challenge_answer_id: @answer.id, user_id: current_user.id, game_id: @game.id, view_time: Time.now)
rescue Exception => e
uid_logger_error("#######金币扣除异常: #{e.message}")
@ -317,6 +318,7 @@ class GamesController < ApplicationController
@game.update_attributes!(:answer_open => 1, :answer_deduction => 100)
end
@challenge_chooses = @challenge.challenge_chooses
GameAnswer.create!(user_id: current_user.id, game_id: @game.id, view_time: Time.now)
rescue Exception => e
uid_logger_error("#######金币扣除异常: #{e.message}")
raise ActiveRecord::Rollback

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

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

@ -5,7 +5,7 @@ class SubjectsController < ApplicationController
before_action :find_subject, except: [:index, :create, :new, :append_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish,
:search_members, :add_subject_members, :statistics, :shixun_report, :school_report,
:up_member_position, :down_member_position]
:up_member_position, :down_member_position, :update_team_title]
include ApplicationHelper
include SubjectsHelper
@ -264,6 +264,12 @@ class SubjectsController < ApplicationController
end
end
def update_team_title
tip_exception("team_title参数不能为空") if params[:team_title].blank?
@subject.update_attributes!(team_title: params[:team_title])
normal_status("更新成功")
end
def search_members
tip_exception("搜索内容不能为空") unless params[:search]
page = params[:page] || 1

@ -39,9 +39,11 @@ module CompetitionsHelper
stages = []
statistic_stages = competition.competition_stages.where("score_rate > 0")
end_time = competition.max_stage_end_time || competition.end_time
if end_time && end_time < Time.now
stages << {id: nil, name: statistic_stages.size > 1 ? "总排行榜" : "排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time}
unless statistic_stages.size == 1
end_time = competition.max_stage_end_time || competition.end_time
if end_time && end_time < Time.now
stages << {id: nil, name: statistic_stages.size > 1 ? "总排行榜" : "排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time}
end
end
statistic_stages.each do |stage|

@ -142,6 +142,9 @@ module ExercisesHelper
right_users_count = 0
#该问题的正确率
if ex.question_type == Exercise::MULTIPLE #多选题
if standard_answer.size == 1 #以前的多选题答案存在一个表里
standard_answer = standard_answer.first.to_s.split("").map(&:to_i)
end
right_user_ids = user_ids
standard_answer.each do |choice_position|
standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id
@ -896,7 +899,8 @@ module ExercisesHelper
if ex_time > 0
exercise_user = exercise.exercise_users.find_by(user_id:user.id)
time_mill = ex_time * 60 #转为秒
exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_end_time = exercise.get_exercise_end_time(user.id) #没有考虑分班的情况
# exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_user_start = exercise_user&.start_at.present? ? exercise_user.start_at.to_i : 0
#用户未开始答题时即exercise_user_start为0
if exercise_user_start == 0

@ -11,4 +11,8 @@ module MyshixunsHelper
nil
end
end
def view_answer_time game, user_id
game.game_answers.where(user_id: user_id).last&.view_time
end
end

@ -0,0 +1,5 @@
module PdfkitHelper
def download_image(url)
'data:image/png;base64,' + Base64.encode64(open(url) { |io| io.read })
end
end

@ -0,0 +1,19 @@
# 生成竞赛个人证书Job
class GenerateCompetitionPersonalCertificateJob < ApplicationJob
queue_as :default
def perform(prize_user_id)
@prize_user = CompetitionPrizeUser.find_by(id: prize_user_id)
return if @prize_user.blank? || @prize_user.certificate_exist?
template = @prize_user.user.is_teacher? ? 'teacher' : 'personal'
file = File.open(Rails.root.join("app/templates/competition_certificates/#{template}.html.erb"))
html = ERB.new(file.read).result(binding)
kit = PDFKit.new(html, page_width: 842, page_height: 595)
path = @prize_user.certificate_path
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless File.directory?(dir)
kit.to_pdf(path)
end
end

@ -0,0 +1,24 @@
# 生成竞赛团体证书Job
class GenerateCompetitionTeamCertificateJob < ApplicationJob
queue_as :default
def perform(competition_team_id)
@team = CompetitionTeam.find_by(id: competition_team_id)
@prize = @team&.competition_prize_users&.first&.competition_prize
return if @team.blank? || !@prize.team_certificate_exists? || @team.certificate_exists?
members = @team.team_members.includes(user: :user_extension).to_a
@member_names = members.select { |m| !m.user.is_teacher? }.map(&:user_name).join('、')
@teacher_names = members.select { |m| m.user.is_teacher? }.map(&:user_name).join('、')
file = File.open(Rails.root.join("app/templates/competition_certificates/team.html.erb"))
html = ERB.new(file.read).result(binding)
kit = PDFKit.new(html, page_width: 842, page_height: 595)
path = @team.certificate_path
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless File.directory?(dir)
kit.to_pdf(path)
end
end

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

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

@ -1,4 +1,9 @@
class ChallengeAnswer < ApplicationRecord
default_scope { order("challenge_answers.level asc") }
belongs_to :challenge
has_many :game_answers, :dependent => :destroy
def view_answer_time(user_id)
game_answers.where(user_id: user_id).last&.view_time
end
end

@ -7,6 +7,30 @@ class CompetitionPrize < ApplicationRecord
enumerize :category, in: %i[bonus unset]
def member_certificate_exists?
Util::FileManage.exists?(self, self.class.member_suffix)
end
def teacher_certificate_exists?
Util::FileManage.exists?(self, self.class.teacher_suffix)
end
def team_certificate_exists?
Util::FileManage.exists?(self, self.class.team_suffix)
end
def member_certificate_path
Util::FileManage.source_disk_filename(self, self.class.member_suffix)
end
def teacher_certificate_path
Util::FileManage.source_disk_filename(self, self.class.teacher_suffix)
end
def team_certificate_path
Util::FileManage.source_disk_filename(self, self.class.team_suffix)
end
def self.member_suffix
'_member'
end

@ -25,7 +25,7 @@ class CompetitionPrizeUser < ApplicationRecord
delegate :bank, :second_bank, :card_no, to: :extra, allow_nil: true
def user_certified?
user.certification? && user.professional_certification?
user.authentication? && user.professional_certification?
end
def certificate_exist?

@ -15,7 +15,7 @@ class Game < ApplicationRecord
belongs_to :user
belongs_to :challenge
has_one :run_code_message, :dependent => :destroy
has_many :game_answers, :dependent => :destroy
#全部关卡数
scope :ch_games, lambda { |challenge_id| where(challenge_id:challenge_id) }

@ -0,0 +1,5 @@
class GameAnswer < ApplicationRecord
belongs_to :user
belongs_to :game
belongs_to :challenge_answer
end

@ -13,4 +13,8 @@ class TeamMember < ApplicationRecord
def en_role
is_teacher? ? 'teacher' : 'member'
end
def user_name
user&.real_name
end
end

@ -1,26 +1,35 @@
class Admins::ApproveCompetitionPrizeUserService < ApplicationService
attr_reader :prize_user, :approver
attr_reader :competition, :prize_user, :approver
def initialize(prize_user, approver)
@prize_user = prize_user
@approver = approver
@competition = prize_user.competition
@prize_user = prize_user
@approver = approver
end
def call
raise Error, '请勿重复审批' if prize_user.approved?
raise Error, '该用户未认证完成' unless prize_user.user_certified?
prize = prize_user.competition_prize
ActiveRecord::Base.transaction do
prize_user.approve
prize_user.approver = approver
prize_user.approved_at = Time.now
prize_user.save!
if prize_user.competition_team.all_prize_approved?
# TODO: 生成团队证书
# 生成个人证书
# 是老师并且教师证书模板存在 或者是学生而且个人证书模板存在
if (prize_user.user.is_teacher? && prize.teacher_certificate_exists?) ||
(!prize_user.user.is_teacher? && prize.member_certificate_exists?)
GenerateCompetitionPersonalCertificateJob.perform_later(prize_user.id)
end
# TODO: 生成个人证书
# 生成团队证书
if !competition.personal? && prize_user.competition_team.all_prize_approved? && prize.team_certificate_exists?
GenerateCompetitionTeamCertificateJob.perform_later(prize_user.competition_team.id)
end
end
end
end

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

@ -10,7 +10,7 @@ class Competitions::SavePrizeTeamAccountService < ApplicationService
def call
Competitions::SavePrizeTeamAccountForm.new(params).validate!
prize_leaders = competition.competition_prize_users.where(competition.competition_prize_users)
prize_leaders = competition.competition_prize_users.where(user_id: user.id, leader: true)
raise Error, '审批通过后不能修改' if prize_leaders.exists?(status: :approved)

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

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize_user.competition_prize.member_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p><%= @prize_user.user.school_name %> <%= @prize_user.user.real_name %>(学号 <%= @prize_user.user.student_id %></p>
<p style="padding-left:2em;line-height: 1.8">
荣获第二届“<b>全国高校绿色计算大赛</b>”( <%= @prize_user.competition.sub_title %> )“<b>全国<%= @prize_user.competition_prize.name %></b>”。
<br/>特发此证,以资鼓励。
</p>
</div>
</div>
</body>
</html>

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize_user.competition_prize.teacher_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p><%= @prize_user.user.school_name %> <%= @prize_user.user.real_name %> 老师:</p>
<p style="text-indent:2em;line-height: 1.8;margin-bottom: 0px;">
在第二届“<b>全国高校绿色计算大赛</b>”(<%= @prize_user.competition.sub_title %>)中,带领学生团队 表现突出,成绩优异,荣获“<b>优秀指导教师</b>”称号。
</p>
<p style="text-indent:2em;line-height: 1.8;margin-top: 0px;">特发此证,以资鼓励。</p>
</div>
</div>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize.team_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p style="text-indent:2em;line-height: 1.8;margin-bottom: 0px;">
<%= @member_names %>(指导老师:<%= @teacher_names %> 在第二届“<b>全国高校绿色计算大赛</b>”(<%= @prize.competition.sub_title %>)中成绩突出,荣获“<b>团体 <%= @prize.name %></b>”。
</p>
<p style="text-indent:2em;line-height: 1.8;margin-top: 0px;">特发此证,以资鼓励。</p>
</div>
</div>
</body>
</html>

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

@ -14,6 +14,11 @@
<td><%= display_text prize_user.approver&.real_name %></td>
<td class="action-container">
<% if prize_user.leader? && prize_user.competition_prize.category == 'bonus' %>
<% bank_content = [prize_user.extra&.[]('bank'), prize_user.extra&.[]('second_bank'), prize_user.extra&.[]('card_no')].compact.join('<br>').presence || '无' %>
<%= javascript_void_link('查看银行账户', data: { toggle: 'tooltip', title: bank_content.html_safe, html: true, placement: 'left', trigger: 'click' }) %>
<% end %>
<% if prize_user.pending? %>
<%= link_to('审批通过', approve_admins_competition_competition_prize_user_path(prize_user.competition, prize_user),
data: { confirm: '确认审批通过吗?' },

@ -513,7 +513,9 @@
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">奖项配置</span>
<%= link_to '新增奖项', new_admins_competition_competition_prize_path(@competition), remote: true, class: 'btn btn-primary btn-sm add-competition-prize-btn' %>
<% unless @competition.competition_prize_users.exists? %>
<%= link_to '新增奖项', new_admins_competition_competition_prize_path(@competition), remote: true, class: 'btn btn-primary btn-sm add-competition-prize-btn' %>
<% end %>
<% if @competition.finished? && !@competition.competition_prize_users.exists? %>
<%= javascript_void_link '生成获奖记录', class: 'btn btn-primary btn-sm ml-2 generate-prize-user-action' %>

@ -5,15 +5,16 @@ if @leader
json.bank_account_editable @bank_account_editable
end
json.all_certified current_user.all_certified?
json.personal_certifications do
json.array! @self_prizes do |prize_user|
json.url personal_competitions_certificate_path(current_competition, prize_user)
json.url personal_competition_certificate_path(current_competition.identifier, prize_user)
end
end
json.team_certifications do
json.array! @team_prizes do |team|
json.url team_competitions_certificate_path(current_competition, team)
json.url team_competition_certificate_path(current_competition.identifier, team)
end
end

@ -7,6 +7,7 @@ json.message do
json.answer_id answer.id
json.answer_name answer.name
json.answer_score answer.score
json.view_time answer.view_answer_time(current_user.id)
# 高层级不给答案
if @power || @game.answer_open >= index
json.answer_contents answer.contents

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

@ -6,4 +6,6 @@ json.array! @games do |game|
json.identifier get_game_identifier(@shixun.task_pass, game, @identity)
json.get_gold game.user_get_gold_and_experience(@shixun.status, challenge)[0]
json.get_experience game.user_get_gold_and_experience(@shixun.status, challenge)[1]
json.view_answer_time view_answer_time(game, current_user.id)
json.finished_time game.end_time
end

@ -5,6 +5,8 @@ json.members @members do |member|
json.role member.role
end
json.team_title @subject.team_title
# 技能标签
json.tags @tags do |tag|
unless tag.blank?

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

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

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

@ -6,6 +6,8 @@ Rails.application.routes.draw do
get 'attachments/download/:id', to: 'attachments#show'
get 'attachments/download/:id/:filename', to: 'attachments#show'
get 'auth/qq/callback', to: 'oauth/qq#create'
get 'auth/failure', to: 'oauth/base#auth_failure'
resources :edu_settings
scope '/api' do
@ -289,6 +291,7 @@ Rails.application.routes.draw do
post :down_member_position
get :right_banner
post :appointment
post :update_team_title
end
collection do

@ -0,0 +1,13 @@
class CreateGameAnswers < ActiveRecord::Migration[5.2]
def change
create_table :game_answers do |t|
t.references :challenge_answer
t.references :user
t.references :game
t.datetime :view_time
t.timestamps
end
end
end

@ -0,0 +1,5 @@
class AddIndexForGameAnswers < ActiveRecord::Migration[5.2]
def change
add_index :game_answers, [:challenge_answer_id, :user_id], :unique => true
end
end

@ -0,0 +1,5 @@
class AddTeamTitleToSubjects < ActiveRecord::Migration[5.2]
def change
add_column :subjects, :team_title, :string, default: "教学团队"
end
end

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

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

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

@ -32,7 +32,7 @@ module.exports = {
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map",
// 开启调试
//devtool: "source-map", // 开启调试
// devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
@ -153,8 +153,8 @@ module.exports = {
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
// This is a feature of `babel-loader` for webpack (not Babel itself).
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

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

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 308 KiB

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

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

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

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

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

@ -1503,7 +1503,7 @@ class PersonModal extends Component {
color: "#D0021B",
fontSize: "12px",
marginTop: "9px"
}}>战队导师为{GetenrollmentAPI.teacher_staff.minimum}-{GetenrollmentAPI.teacher_staff.maximum},{Thecurrentnumber}</p>
}}>导师{GetenrollmentAPI.teacher_staff.minimum}-{GetenrollmentAPI.teacher_staff.maximum},{Thecurrentnumber}</p>
: ""
) :
@ -1518,7 +1518,7 @@ class PersonModal extends Component {
color: "#D0021B",
fontSize: "12px",
marginTop: "9px"
}}>战队队员{GetenrollmentAPI.member_staff.minimum}-{GetenrollmentAPI.member_staff.maximum},{Thecurrentnumberstu}</p>
}}>战队成员需{GetenrollmentAPI.member_staff.minimum}-{GetenrollmentAPI.member_staff.maximum},{Thecurrentnumberstu}</p>
: ""
) :
@ -1551,4 +1551,4 @@ class PersonModal extends Component {
}
}
export default PersonModal;
export default PersonModal;

@ -3,9 +3,10 @@ import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Row, Col,Button, Menu, Icon
import { Link } from 'react-router-dom';
import axios from 'axios';
import {markdownToHTML,getImageUrl} from 'educoder';
import CompetitionContents from './CompetitionContents';
import CompetitionContentsChart from './CompetitionContentsChart';
import CompetitionContentsMd from './CompetitionContentsMd';
import CompetitionContents from './CompetitionCommonChild/CompetitionContents';
import CompetitionContentsChart from './CompetitionCommonChild/CompetitionContentsChart';
import CompetitionContentsMd from './CompetitionCommonChild/CompetitionContentsMd';
import CompetitionContentspdf from './CompetitionCommonChild/CompetitionContentspdf';
import './CompetitionCommon.css';
@ -15,14 +16,15 @@ class CompetitionCommon extends Component{
constructor(props) {
super(props)
this.state={
data:undefined,
bannerdata:undefined,
module_type:undefined,
mdContentdata:undefined,
chart_rules:undefined,
Competitionedittype:false,
chartdata:undefined,
has_url:false
data: undefined,
bannerdata: undefined,
module_type: undefined,
mdContentdata: undefined,
chart_rules: undefined,
Competitionedittype: false,
chartdata: undefined,
has_url: false,
signupdata: undefined
}
}
@ -46,14 +48,38 @@ class CompetitionCommon extends Component{
}
}
componentDidUpdate = (prevProps) => {
if (prevProps.user != this.props.user) {
console.log("componentDidUpdatess");
console.log(this.props.user);
if (this.props.user && this.props.user.login != "") {
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => {
if (result) {
if (result.data) {
this.setState({
signupdata: result.data
})
}
}
}).catch((error) => {
//console.log(error);
})
}
}
}
//获取头部信息
getbannerdata=()=>{
let menuid=this.props.location.search.replace('?menu=', '');
let url=`/competitions/${this.props.match.params.identifier}/common_header.json`;
axios.get(url).then((response) => {
if(response.status===200){
this.setState({
data:response.data,
thiskeys:menuid===undefined||menuid===""?response.data.competition_modules[0].id:menuid
data: response.data,
thiskeys: menuid === undefined || menuid === "" ? response.data.competition_modules[0].id : menuid,
mode: response.data.mode
})
if(menuid===undefined||menuid===""){
this.getrightdata(
@ -80,27 +106,29 @@ class CompetitionCommon extends Component{
console.log(error)
})
if(this.props.user&&this.props.user.login!= ""){
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => {
if (result) {
if (result.data) {
this.setState({
signupdata:result.data
})
}
}
}).catch((error) => {
//console.log(error);
})
}
//this.props.user 有可能为空
if (this.props.user && this.props.user.login != "") {
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => {
if (result) {
if (result.data) {
this.setState({
signupdata: result.data
})
}
}
}).catch((error) => {
//console.log(error);
})
}
}
getrightdatas=(e)=>{
let keys=parseInt(e.key);
this.getlistdata(keys)
this.props.history.replace(`?menu=${keys}`);
let keys = parseInt(e.key);
this.getlistdata(keys)
this.props.history.replace(`?menu=${keys}`);
}
getlistdata=(keys,listkey)=>{
@ -127,7 +155,7 @@ class CompetitionCommon extends Component{
if(response.status===200){
this.setState({
chart_rules:response.data,
tabkey:tabkey===undefined?response.data.stages[0].id===null?"0":`${response.data.stages[0].id}`:tabkey
tabkey: tabkey === undefined ? response.data.stages[0].id === null ? "0" : `${response.data.stages[0].id}` : tabkey
})
@ -142,10 +170,10 @@ class CompetitionCommon extends Component{
// if(typeid==="enroll"){
// this.props.history.replace(`/competitions/${this.props.match.params.identifier}/enroll`);
// return
// return
// }
this.getnewchartdata(typeid,listkey)
this.getnewchartdata(typeid, listkey)
if(has_url===false){
let url=`${module_url}`;
@ -167,11 +195,11 @@ class CompetitionCommon extends Component{
console.log(error)
})
}else{
if(module_url.substring(0,7)=='http://'||module_url.substring(0,8)=='https://') {
if (module_url.substring(0, 7) == 'http://' || module_url.substring(0, 8) == 'https://') {
// window.location.href= module_url
window.open(module_url)
window.open(module_url)
}else{
window.open(`https://${module_url}`)
window.open(`https://${module_url}`)
// window.location.href=;
}
return
@ -186,9 +214,9 @@ class CompetitionCommon extends Component{
}
Competitionedit=()=>{
this.setState({
Competitionedittype:true
})
this.setState({
Competitionedittype: true
})
}
hideCompetitionedit=()=>{
@ -215,10 +243,10 @@ class CompetitionCommon extends Component{
if(data.member_of_course===true){
this.props.history.replace(`/courses/${data.course_id}`);
}else{
// 以学生身份调用加入课堂 进入课堂首页
// 以学生身份调用加入课堂 进入课堂首页
let url="/courses/apply_to_join_course.json"
axios.post(url, {
invite_code:data.invite_code,
invite_code: data.invite_code,
student:1
}
).then((response) => {
@ -229,12 +257,46 @@ class CompetitionCommon extends Component{
}
}
}else{
this.props.history.replace(url);
if (url === "personal") {
this.Personalregistration()
} else {
this.props.history.replace(url);
}
}
}
Personalregistration = () => {
let {signupdata} = this.state;
let urls = `/competitions/${this.props.match.params.identifier}/enroll`;
if (signupdata.enroll_ended === true) {
//已截止
this.props.showNotification(`报名已截止`);
return;
}
if (signupdata.enrolled === true) {
this.props.showNotification(`你已经报名,不能重复报名!`);
return;
}
const url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`;
axios.post(url).then((response) => {
if (response) {
if (response.data) {
this.props.showNotification(`报名成功,预祝您夺得桂冠!`);
this.props.history.replace(urls);
}
}
}).catch((error) => {
});
}
Competitioncallback=(key)=>{
this.setState({
this.setState({
tabkey:key
})
let url=`/competitions/${this.props.match.params.identifier}/charts.json`;
@ -252,146 +314,172 @@ class CompetitionCommon extends Component{
}
render() {
let {data,thiskeys,Competitionedittype}=this.state;
let {data, module_type, Competitionedittype, signupdata} = this.state;
return (
data===undefined?"":<div className={"educontent clearfix mt20 "}>
<Breadcrumb separator=">">
<Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item>
<Breadcrumb.Item>{data&&data.name}</Breadcrumb.Item>
</Breadcrumb>
<div className={"mt10 relative"}>
<Row className={"CompetitionCommonbanner"}>
{data.competition_status==="nearly_published"?
data && data.permission.editable === true ? "" :
<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""}
<img className={"Commonimg"}
src={data.competition_status==="ended"?getImageUrl(`images/educoder/competitions/groups1.png`):data.competition_status==="nearly_published"?getImageUrl(`images/educoder/competitions/groups2.png`):data.competition_status==="progressing"?getImageUrl(`images/educoder/competitions/groups3.png`):""} />
<Col span={15} className={"Commonimgbox"}>
<img className={"image_urlbox"} src={data===undefined?getImageUrl(`images/educoder/competitions/mainbanner.jpg`):data.avatar_url===null?getImageUrl(`images/educoder/competitions/mainbanner.jpg`):getImageUrl(data.avatar_url)}/>
<Breadcrumb separator=">">
<Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item>
<Breadcrumb.Item>{data && data.name}</Breadcrumb.Item>
</Breadcrumb>
<div className={"mt10 relative"}>
<Row className={"CompetitionCommonbanner"}>
{data.competition_status === "nearly_published" ?
data && data.permission.editable === true ? "" :
<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""}
<img className={"Commonimg"}
src={data.competition_status === "ended" ? getImageUrl(`images/educoder/competitions/groups1.png`) : data.competition_status === "nearly_published" ? getImageUrl(`images/educoder/competitions/groups2.png`) : data.competition_status === "progressing" ? getImageUrl(`images/educoder/competitions/groups3.png`) : ""}/>
<Col span={15} className={"Commonimgbox"}>
<img className={"image_urlbox"}
src={data === undefined ? getImageUrl(`images/educoder/competitions/mainbanner.jpg`) : data.avatar_url === null ? getImageUrl(`images/educoder/competitions/mainbanner.jpg`) : getImageUrl(data.avatar_url)}/>
</Col>
<Col className={"CompetitionCommonbannerfont"} span={9}>
<Col
className={data && data.name.length > 15 ? "competitionbannerdiv mt30" : "competitionbannerdiv mt30"}>{data && data.name}</Col>
<Col className={"competitionbannerdiv mt10"}>
<Col className={"Competitioncolor9b"}>竞赛时间<span
className={"color000"}>{data && data.start_time}{data && data.end_time}</span></Col>
{/*<Col></Col>*/}
</Col>
<Col className={"CompetitionCommonbannerfont"} span={9}>
<Col className={data&&data.name.length>15?"competitionbannerdiv mt30":"competitionbannerdiv mt30"}>{data&&data.name}</Col>
<Col className={"competitionbannerdiv mt10"}>
<Col className={"Competitioncolor9b"}>竞赛时间<span className={"color000"}>{data&&data.start_time}{data&&data.end_time}</span></Col>
{/*<Col></Col>*/}
<Col className={"competitionbannerdiv mt10"}>
<Row gutter={16}>
<Col className="gutter-row" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">奖金</div>
</Col>
<Col className="gutter-row ml20 rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">浏览数</div>
</Col>
<Col className="gutter-row rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">报名数</div>
</Col>
</Row>
<Col className={"competitionbannerdiv mt10"}>
<Row gutter={16}>
<Col className="gutter-row" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">奖金</div>
</Col>
<Col className="gutter-row ml20 rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">浏览数</div>
</Col>
<Col className="gutter-row rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">报名数</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">¥{data&&data.bonus}</div>
</Col>
<Col className="gutter-row ml20 rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">{data.competition_status==="nearly_published"?"--":data&&data.visits_count}</div>
</Col>
<Col className="gutter-row rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516" onClick={data.competition_status==="nearly_published"?"":()=>this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}>{data.competition_status==="nearly_published"?"--":data&&data.member_count}</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={6}>
<div
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">¥{data && data.bonus}</div>
</Col>
<Col className="gutter-row ml20 rankbeicenter" span={6}>
<div
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">{data.competition_status === "nearly_published" ? "--" : data && data.visits_count}</div>
</Col>
<Col className="gutter-row rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516"
onClick={data.competition_status === "nearly_published" ? "" : () => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}>{data.competition_status === "nearly_published" ? "--" : data && data.member_count}</div>
</Col>
</Row>
</Col>
{data.competition_status==="ended"?<style>
{
`
{data.competition_status === "ended" ? <style>
{
`
.Competitionfontsize22{
height: 50px;
border-radius: 4px;
}
`
}
</style>:<style>
{
`
}
</style> : <style>
{
`
.Competitionfontsize22{
height: 50px;
background: rgba(76,172,255,1);
border-radius: 4px;
}
`
}
</style>}
<Col className={"competitionbannerdiv mt20"}>
{data.competition_status==="ended"?
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
已结束
</Button>:data.enroll_end===true?<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
{data.competition_status === "nearly_published" ? "未发布" : "报名截止"}
</Button>:
data.competition_status==="progressing"?<Button type="primary" block className={"Competitionfontsize22"}>
{data.mode===2?<a onClick={()=>this.gotocourse()}>立即报名</a>:<a onClick={()=>this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}></a>}
}
</style>}
<Col className={"competitionbannerdiv mt20"}>
{data.competition_status === "ended" ?
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
已结束
</Button> : data.enroll_end === true ?
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
{data.competition_status === "nearly_published" ? "未发布" : "报名截止"}
</Button> :
data.competition_status === "progressing" ?
<Button type="primary" block className={"Competitionfontsize22"}>
{data.mode === 2 ?
<a onClick={() => this.gotocourse()}>立即报名</a> : signupdata && signupdata.personal === true ?
<a onClick={() => this.gotocourse("personal")}>立即报名</a> : <a
onClick={() => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}>立即报名</a>}
</Button>:""}
</Col>
<Col className={"mt10 Competitionfontsize16"}>{data&&data.enroll_end_time===null?"":`报名截止时间:${data&&data.enroll_end_time}`}</Col>
</Col>
</Row>
</div>
<Layout className={'teamsLayout mt40'}>
<Sider>
<Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]} onClick={(e)=>this.getrightdatas(e)}>
{data&&data.competition_modules.map((item,key)=>{
if(item.module_type!="enroll"){
return(
<Menu.Item key={item.id}>
{/*{item.has_url===false?<span*/}
{/*// onClick={()=>this.getrightdata(item.id,item.module_type,item.module_url,item.has_url)}*/}
{/*>{item.name}</span>:<a*/}
{/*// target="_blank"*/}
{/*href={item.module_url}*/}
{/*// onClick={()=>this.getrightdata(item.id,item.module_type)}*/}
{/*>{item.name}</a>}*/}
<a>{item.name}</a>
</Menu.Item>
)
}
})}
</Menu>
</Sider>
<Layout className={"teamsLayoutleft CompetitionContents mb30"}>
{this.state.module_type==="chart"?Competitionedittype===false?<CompetitionContentsChart
{...this.props}
{...this.state}
Competitionedit={()=>this.Competitionedit()}
Competitioncallback={(e)=>this.Competitioncallback(e)}
/>:"":Competitionedittype===false?<CompetitionContents
Competitionedit={()=>this.Competitionedit()}
{...this.props}
{...this.state}
/>:""}
{/*<CompetitionContentsChart*/}
{/*{...this.props}*/}
{/*{...this.state}*/}
{/*/>*/}
{Competitionedittype===true?<CompetitionContentsMd
hideCompetitionedit={()=>this.hideCompetitionedit()}
getlistdata={(keys,listkey)=>this.getlistdata(keys,listkey)}
Competitioncallback={(e)=>this.Competitioncallback(e)}
{...this.props}
{...this.state}
/>:""}
</Layout>
</Layout>
<Col
className={"mt10 Competitionfontsize16"}>{data && data.enroll_end_time === null ? "" : `报名截止时间:${data && data.enroll_end_time}`}</Col>
</Col>
</Row>
</div>
<Layout className={'teamsLayout mt40'}>
<Sider>
<Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]}
onClick={(e) => this.getrightdatas(e)}>
{data && data.competition_modules.map((item, key) => {
if (item.module_type != "enroll") {
return (
<Menu.Item key={item.id}>
{/*{item.has_url===false?<span*/}
{/*// onClick={()=>this.getrightdata(item.id,item.module_type,item.module_url,item.has_url)}*/}
{/*>{item.name}</span>:<a*/}
{/*// target="_blank"*/}
{/*href={item.module_url}*/}
{/*// onClick={()=>this.getrightdata(item.id,item.module_type)}*/}
{/*>{item.name}</a>}*/}
<a>{item.name}</a>
</Menu.Item>
)
}
})}
</Menu>
{/*<Menu mode="inline" className="CompetitionMenu" onClick={(e)=>this.isdownloadpdf(e)}>*/}
{/*<Menu.Item>*/}
{/*<a>证书下载</a>*/}
{/*</Menu.Item>*/}
{/*</Menu>*/}
</Sider>
{module_type === "certificate" ? "" : <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
{this.state.module_type === "chart" ? Competitionedittype === false ? <CompetitionContentsChart
{...this.props}
{...this.state}
Competitionedit={() => this.Competitionedit()}
Competitioncallback={(e) => this.Competitioncallback(e)}
/> : "" : Competitionedittype === false ? <CompetitionContents
Competitionedit={() => this.Competitionedit()}
{...this.props}
{...this.state}
/> : ""}
{/*<CompetitionContentsChart*/}
{/*{...this.props}*/}
{/*{...this.state}*/}
{/*/>*/}
{Competitionedittype === true ? <CompetitionContentsMd
hideCompetitionedit={() => this.hideCompetitionedit()}
getlistdata={(keys, listkey) => this.getlistdata(keys, listkey)}
Competitioncallback={(e) => this.Competitioncallback(e)}
{...this.props}
{...this.state}
/> : ""}
</Layout>}
{module_type === "certificate" ? <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
<CompetitionContentspdf
{...this.props}
{...this.state}
/>
</Layout> : ""}
</Layout>
</div>

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs} from 'antd';
import axios from 'axios';
import {getImageUrl,getUrl,appendFileSizeToUploadFileAll,appendFileSizeToUploadFile} from 'educoder';
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
const { TabPane } = Tabs;
class CompetitionContentsMd extends Component{
constructor(props) {

@ -0,0 +1,57 @@
import React, { Component } from 'react';
import {Tabs} from 'antd';
import axios from 'axios';
import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder';
import CompetitionContentspdfdownload from './CompetitionContentspdfChild/CompetitionContentspdfdownload';
import CompetitionContentspdfpeopledata from './CompetitionContentspdfChild/CompetitionContentspdfpeopledata';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
const { TabPane } = Tabs;
class CompetitionContentspdf extends Component{
constructor(props) {
super(props)
this.state={
Tabskey:"1"
}
}
componentDidMount(){
window.document.title = '竞赛';
}
Competitioncallback=(key)=>{
this.setState({
Tabskey:key
})
}
render() {
return (
<div className={"fr"}>
<div className={"mb100 "}>
<Tabs defaultActiveKey="1" onChange={(e) => this.Competitioncallback(e)} activeKey={this.state.Tabskey}>
<TabPane tab="获奖证书下载" key="1" >
{this.state.Tabskey==="1"?<CompetitionContentspdfdownload
{...this.props}
{...this.state}
Competitioncallback={(e)=>this.Competitioncallback(e)}
/>:""}
</TabPane>
<TabPane tab="完善个人信息" key="2">
{this.state.Tabskey==="2"?<CompetitionContentspdfpeopledata
{...this.props}
{...this.state}
/>:""}
</TabPane>
</Tabs>
</div>
</div>
)
}
}
export default CompetitionContentspdf;

@ -0,0 +1,215 @@
import React, {Component} from 'react';
import {Button, Layout, Input, Form} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import mycompetotionchild from './mycompetotionchild.css';
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
import '../../../../courses/css/Courses.css'
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
class Bankcardnumberverification extends Component {
constructor(props) {
super(props)
this.state = {
basicInfo: {},
updating: '',
secondsFlag: false,
seconds: 60,
phonebool: false,
emailbool: false,
formationdata: [],
bank_account_editable: false,
leader: false,
bank_account: undefined,
certification: 1
}
}
componentDidMount() {
window.document.title = '竞赛';
// console.log("3获取用户信息");
// console.log(this.props)
//初始化值
if (this.props.bank_account) {
this.props.form.setFieldsValue({
openingbank: this.props.bank_account.bank,
subbranch: this.props.bank_account.second_bank,
subbranchs: this.props.bank_account.card_no,
})
}
}
yhBankstrue = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let url = `/competitions/${this.props.match.params.identifier}/prize_leader_account.json`;
axios.patch(url, {
bank: values.openingbank,
second_bank: values.subbranchs,
card_no: values.subbranch
})
.then((result) => {
try {
if (result.data.status == 0) {
// console.log(JSON.stringify(result));
this.props.showNotification(`提交成功,等待审核!`);
this.props.getdata();
this.props.GetawardinformationAPI();
}
} catch (e) {
}
}).catch((error) => {
console.log(error);
})
}
})
}
render() {
const {getFieldDecorator} = this.props.form;
const {updating, seconds, secondsFlag, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
return (
<div>
<div className="flexdirections mt36">
<p className="fontcolorsyslhei font-16">//开户行及银行卡号</p>
<p className="fontcolorsyslhui font-14 ml11">为保障奖金的及时发放请队长如实填写你名下的银行卡信息</p>
</div>
<div className="ml38">
<style>{`
.flexRow {
padding: 20px 0;
}
.flexRow .name {
margin-left: 12px;
color: #666666;
text-align: center;
flex: 0 0 100px;
}
.flexRow .description {
margin-left: 10px;
flex: 1;
color: #CDCDCD;
}
.description span {
margin-right: 20px;
color: #05101A;
}
.flexRow .status {
width: 100px;
color: #28AC7F;
text-align: right;
}
.flexTable .flexTable {
border-bottom: 1px solid #EBEBEB;
}
.settingFormsy label{
color: #666666;
font-size: 14px !important ;
}
.settingFormsy input {
width: 340px;
height: 40px;
}
.settingFormsy input.validateInput {
width: 220px;
}
.settingFormsy .formItemInline button {
width: 110px;
margin-left: 10px;
}
.settingFormsy .ant-form-item-label {
width: 60px;
text-align: left;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-22px;
left:0px;
width:100%;
}
.yslzxueshi .ant-input{
height: 40px !important;
width: 276px !important
}
// class="ant-col ant-form-item-label"
`}</style>
<div className="settingFormsy">
<React.Fragment>
<Form>
<Form.Item
label="开户行:"
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('openingbank', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入开户行',
}],
})(
<Input placeholder={`例如:中国工商银行`}></Input>
)}
</Form.Item>
<Form.Item
label="支行:"
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('subbranch', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入支行',
}],
})(
<Input placeholder={`例如:长沙天河支行`}></Input>
)}
</Form.Item>
<Form.Item
label="账号:"
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('subbranchs', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入账号',
}],
})(
<Input placeholder={`请填写银行卡账号`}></Input>
)}
</Form.Item>
<div className="flexdirections yslzxueshi ml38 mt34">
<p className="fontcolorsyslhui1 font-14 w300 myysllineheight myyslminwidth"></p>
<div className="myyslminwidth276 flexdirections">
{/*<div className="buttongo mycompitcursor" onClick={()=>this.yhBanksfalse()}><p className="fontwenzi mycompitcursor" >取消</p></div>*/}
<Button type="primary" onClick={() => this.yhBankstrue()}>确定</Button>
</div>
</div>
</Form>
</React.Fragment>
</div>
</div>
</div>
)
}
}
const Bankcardnumberverifications = Form.create({name: 'Bankcardnumberverification'})(Bankcardnumberverification);
export default Bankcardnumberverifications;

@ -0,0 +1,24 @@
.pdfdownload {
max-width: 791px;
height: 40px;
background: rgba(249, 249, 249, 1);
line-height: 40px;
padding-left: 15px;
}
.pdfpicture {
font-size: 16px;
color: rgba(0, 0, 0, 1);
}
.pdfdownloadfont4CACFF {
color: #4CACFF !important;
}
.pdfdownloadfont00CC5F {
color: #00CC5F;
}
.pdfdownloadfontFF6602 {
color: #FF6602;
}

@ -0,0 +1,205 @@
import React, { Component } from 'react';
import {Button,Layout,Row, Col,Divider,Table} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import './CompetitionContentspdfdownload.css';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
class CompetitionContentspdfdownload extends Component{
constructor(props) {
super(props)
this.state={
data:undefined,
teams:undefined
}
}
componentDidMount(){
window.document.title = '竞赛';
let url=`/competitions/${this.props.match.params.identifier}/prize.json`;
axios.get(url).then((response) => {
if(response.status===200){
let datas=response.data.teams;
if(datas.length>0){
datas.map((item,key)=>{
let lista=item.team_members;
if(lista.length>0){
console.log(lista)
lista.map((i,k)=>{
i["bank_account"]=item.bank_account;
})
}
})
}
this.setState({
data:response.data,
teams:datas,
})
}
}).catch((error) => {
console.log(error)
})
}
render() {
let {data,teams}=this.state;
const columns = [
{
title: '角色',
dataIndex: 'type',
key: 'type',
render: (text, record) => (
<span>
{record.role}
</span>
),
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
render: (text, record) => (
<span>
{record.name}
</span>
),
},
{
title: '实名认证',
dataIndex: 'namecertify',
key: 'namecertify',
render: (text, record) => (
<span>
{record.real_name_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.real_name_auth==="authing"?<span className={"pdfdownloadfontFF6602"}></span>:record.real_name_auth==="not_authed"?<span className={"color-red"}></span>:""}
</span>
),
},
{
title: '职业认证',
key: 'certify',
dataIndex: 'certify',
render: (text, record) => (
<span>
{record.professional_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.professional_auth==="authing"?<span className={"pdfdownloadfontFF6602"}></span>:record.professional_auth==="not_authed"?<span className={"color-red"}></span>:""}
</span>
),
},
{
title: '手机绑定',
key: 'mobile',
dataIndex: 'mobile',
render: (text, record) => (
<span>
{record.phone_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}></span>}
</span>
),
},
{
title: '邮箱绑定',
key: 'mail',
dataIndex: 'mail',
render: (text, record) => (
<span>
{record.email_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}></span>}
</span>
),
},
{
title: '开户行及银行卡号信息(队长填写)',
key: 'idcard',
dataIndex: 'idcard',
render: (value, record, index) => {
if (index === 0&&record.bank_account!=null) {
return {
children: <span>{record.bank_account.bank + record.bank_account.second_bank + record.bank_account.card_no}</span>,
};
}
},
},
];
let people=[ { url: '/api/competitions/xxxxx/certificates/1/personal' },
{ url: '/api/competitions/xxxxx/certificates/2/personal' },]
return (
<React.Fragment>
<Row>
<Col className={"pdfdownload"}>温馨提示填写的个人信息经审批后将提供个人获奖证书下载团队队员信息全部审批后将提供团队获奖证书下载</Col>
</Row>
<Row className={"mt30"}>
<Col className={"pdfpicture"}>证书情况</Col>
</Row>
<Row className={"mt30"}>
<Col>个人证书{data&&data.personal_certifications.length===0&&data&&data.all_certified===false?
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span><a className={"pdfdownloadfont4CACFF"} onClick={()=>this.props.Competitioncallback("2")}></a></span></span>:
data&&data.personal_certifications.length===0&&data&&data.all_certified===true?
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span></span></span>:
data&&data.personal_certifications.map((item,key)=>{
return(
<span className={"mr10"} key={key}>
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
</span>
)
})}</Col>
</Row>
<Row className={"mt30"}>
<Col>团队证书
{data&&data.team_certifications.length===0?<span className={"pdfpicture font-14"}>暂未生成</span>
:data&&data.team_certifications.map((item,key)=>{
return(
<span className={"mr10"} key={key}>
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
</span>
)
})}
</Col>
</Row>
<Divider />
<style>
{
`
.pdfdownloadTable .ant-table-column-title{
color:#000;
}
.pdfdownloadTable .ant-table-tbody > tr > td{
color:#666666;
border-bottom: 1px solid transparent;
}
.pdfdownloadTable .ant-table-thead > tr > th, .ant-table-tbody > tr > td{
text-align: center;
}
`
}
</style>
{teams&&teams.map((item,key)=>{
return(
<Row className={"mt30"} key={key}>
<Col className={"pdfpicture mb20"}>{item.name}战队信息填报概况</Col>
<Table columns={columns} dataSource={item.team_members} className={"pdfdownloadTable"} pagination={false}/>
</Row>
)
})
}
</React.Fragment>
)
}
}
export default CompetitionContentspdfdownload;

@ -0,0 +1,530 @@
import React, {Component} from 'react';
import {Button, Layout, Input, Form} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import mycompetotionchild from './mycompetotionchild.css';
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
import '../../../../courses/css/Courses.css'
import RealNameCertificationModal from "../../../../user/modal/RealNameCertificationModal";
import Phonenumberverifications from './Phonenumberverification';
import Mailboxvalidations from './Mailboxvalidation'
import Bankcardnumberverifications from './Bankcardnumberverification'
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
class CompetitionContentspdfpeopledata extends Component {
constructor(props) {
super(props)
this.state = {
basicInfo: {},
updating: '',
secondsFlag: false,
seconds: 60,
phonebool: false,
emailbool: false,
formationdata: [],
bank_account_editable: false,
leader: false,
bank_account: undefined,
certification: 1
}
}
componentDidMount() {
window.document.title = '竞赛';
console.log("获取用户信息");
console.log(this.props);
this.getdata();
this.GetawardinformationAPI();
}
GetawardinformationAPI = () => {
let url = `/competitions/${this.props.match.params.identifier}/prize.json`;
axios.get(url).then((result) => {
if (result.data) {
this.setState({
formationdata: result.data.formationdata,
bank_account_editable: result.data.bank_account_editable, //队长是否可以编辑
leader: result.data.leader, //是否是队长
bank_account: result.data.bank_account, //队长银行卡号信息
})
}
}).catch((error) => {
console.log(error);
})
}
getdata = () => {
this.setState({
certification: 3
})
let url = `/users/accounts/${this.props.current_user.login}.json`;
axios.get(url).then((result) => {
if (result.data) {
if (result.data && result.data.base_info_completed == false) {
this.props.history.push(`/account/profile/edit`);
}
// "authentication": "uncertified", // "uncertified" | "applying" | "certified"
this.setState({
basicInfo: Object.assign({}, {...result.data}, {
avatar_url: `${result.data.avatar_url}`,
gender: result.data.gender == null || result.data.gender == undefined ? 0 : result.data.gender
}),
certification: 3
})
}
}).catch((error) => {
console.log(error);
})
};
// 绑定手机
onPhoneSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let {login} = this.props.current_user;
let reg = /^1\d{10}$/;
if (reg.test(values.phone)) {
let url = `/users/accounts/${login}/phone_bind.json`
axios.post((url), {
phone: values.phone,
code: values.phoneValidateCode
}).then((result) => {
if (result) {
this.props.showNotification("手机号码绑定成功!");
this.setState({
phonebool: false
})
this.getdata();
}
}).catch((error) => {
console.log(error);
})
} else {
this.props.showNotification("请输入有效的11位手机号码");
}
}
})
}
// 绑定邮箱
onEmailSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let {login} = this.props.current_user;
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (reg.test(values.email)) {
let url = `/users/accounts/${login}/email_bind.json`
axios.post((url), {
email: values.email,
code: values.emailValidateCode
}).then((result) => {
if (result) {
this.props.showNotification("邮箱地址绑定成功!");
this.setState({
emailbool: false
})
this.getdata();
}
}).catch((error) => {
console.log(error);
})
} else {
this.props.showNotification("请输入正确的邮箱地址");
}
}
})
}
//取消编辑
hideUpdating = (i) => {
if (i === 1) {
this.setState({
phonebool: false
})
} else if (i === 2) {
this.setState({
emailbool: false
})
} else if (i === 3) {
}
}
// 获取验证码
getCode = (index) => {
let url = `/accounts/get_verification_code.json`
let login = '';
let values = this.props.form.getFieldsValue();
if (index == 3) {
//绑定手机号码
login = values.phone;
let reg = /^1\d{10}$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的手机号码`);
return;
}
} else if (index == 4) {
// 绑定邮箱
login = values.email;
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的邮箱地址`);
return;
}
}
let type = index;
if (!login) {
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
return;
}
axios.get((url), {
params: {
login, type
}
}).then((result) => {
if (result) {
// 倒计时
this.setState({
secondsFlag: true
})
this.remainTime();
}
}).catch((error) => {
console.log(error);
})
}
// 获取验证码倒计时
remainTime = () => {
this.setState({
seconds: 60
})
this.timer = setInterval(() => {
let {seconds} = this.state;
let s = parseInt(seconds) - 1;
if (s > -1) {
this.setState({
seconds: s
})
} else {
this.setState({
secondsFlag: false
})
clearInterval(this.timer);
}
}, 1000)
}
phonebools = () => {
this.setState({
phonebool: true
})
}
emailbools = () => {
console.log("点击了邮箱");
this.setState({
emailbool: true
})
}
//立即认证
checkBasicInfo = (index) => {
if (this.state.basicInfo.base_info_completed == true) {
this.showRealNameCertificationModal(index)
} else {
try {
this.props.confirm({
okText: `立即完善`,
content: `请先完善基本信息`,
onOk: () => {
this.props.history.push('/account/profile/edit')
}
})
} catch (e) {
this.props.history.push(`/account/profile/edit`);
}
}
}
showRealNameCertificationModal = (index) => {
this.setState({
certification: index,
}, () => {
if (index == 1) {
this.realNameCertificationModal1.setVisible(true)
} else if (index == 2) {
this.realNameCertificationModal2.setVisible(true)
}
})
}
//绑定银行确认
yhBankstrue = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let url = `/competitions/${this.props.match.params.identifier}/prize_leader_account.json`;
axios.patch(url, {
bank: values.openingbank,
second_bank: values.subbranchs,
card_no: values.subbranch
})
.then((result) => {
try {
if (result.data.status == 0) {
// console.log(JSON.stringify(result));
this.props.showNotification(`提交成功成功`);
this.getdata();
this.GetawardinformationAPI();
}
} catch (e) {
}
}).catch((error) => {
console.log(error);
})
}
})
}
//取消认证弹框
onCancel = () => {
this.getdata();
}
//撤销认证
Cancellationofapplication = (index) => {
let url = ""
if (index === 1) {
url = `/users/accounts/${this.props.user.user_id}/authentication_apply.json`;
} else if (index === 2) {
url = `/users/accounts/${this.props.user.user_id}/professional_auth_apply.json`;
}
axios.delete(url)
.then((response) => {
try {
if (response.data.status == 0) {
if (index === 1) {
this.props.showNotification('撤销实名认证成功')
} else if (index === 2) {
this.props.showNotification('撤销职业认证成功')
}
this.getdata();
}
} catch (e) {
}
})
.catch(function (error) {
console.log(error);
});
}
render() {
const {updating, seconds, secondsFlag, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
return (
<div className="flexdidirectionss mt17">
{this.state.certification === 1 ?
<RealNameCertificationModal {...this.props} {...this.state} basicInfo={this.state.basicInfo}
wrappedComponentRef={(form) => this.realNameCertificationModal1 = form}
certification={certification}
Getdata={() => this.getdata()}
onCancel={() => this.onCancel()}
></RealNameCertificationModal> : ""}
{this.state.certification === 2 ?
<RealNameCertificationModal {...this.props} {...this.state} basicInfo={this.state.basicInfo}
wrappedComponentRef={(form) => this.realNameCertificationModal2 = form}
certification={certification}
Getdata={() => this.getdata()}
onCancel={() => this.onCancel()}
></RealNameCertificationModal> : ""}
<div className="flexdirections ">
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span></span>
</p>
{basicInfo && basicInfo.authentication == "uncertified" ?
<p className="fontcolorsyslhui font-14 w200">通过实名认证后才能获得证书</p> : ""
}
{basicInfo && basicInfo.authentication == "uncertified" ?
<p className="fontcolorsysllan font-14 ml3 mycompitcursor"
onClick={() => this.checkBasicInfo(1)}>立即认证</p> : ""
}
</div>
<div className="flexdirections ml38 mt23">
<p className="fontcolorsyslhui1">姓名</p>
<p className="fontcolorsyslhei flexdirections">{basicInfo && basicInfo.name}
{
basicInfo && basicInfo.authentication == "uncertified" ? "" :
basicInfo && basicInfo.authentication == "applying" ?
<p className="flexdirections"><p className="iconfont icon-tishi colorgreenorg font-14 ml20"></p><p
className="colorgreenorg font-14 ml6">待审核</p><p
className="fontcolorsysllan borcolors font-12 w64 mycompitcursor"
onClick={() => this.Cancellationofapplication(1)}>撤销认证</p></p>
:
<p className="flexdirections">
<p className="iconfont icon-wancheng colorgreenlight font-14 ml20"></p><p
className="colorgreenlight font-14 ml6">已认证</p>
</p>
}
</p>
</div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1">性别</p>
<p className="fontcolorsyslhei"> {basicInfo && basicInfo.gender == 0 ? "男" : "女"}</p>
</div>
<div className="flexdirections mt36 ">
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span></span>
</p>
{
basicInfo && basicInfo.professional_certification == "uncertified" ?
<p className="fontcolorsyslhui font-14 w200">通过职业认证后才能获得证书</p>
: ""}
{
basicInfo && basicInfo.professional_certification == "uncertified" ?
<p className="fontcolorsysllan font-14 ml3 mycompitcursor" onClick={() => this.checkBasicInfo(2)}>立即认证</p>
: ""}
</div>
<div className="flexdirections ml38 mt23">
<p className="fontcolorsyslhui1">职业</p>
<p
className="fontcolorsyslhei flexdirections">{basicInfo && basicInfo.identity && identityMap[basicInfo.identity]}
{
basicInfo && basicInfo.professional_certification == "uncertified" ?
"" :
basicInfo && basicInfo.professional_certification == "applying" ?
<p className="flexdirections">
<p className="iconfont icon-tishi colorgreenorg font-14 ml20"></p><p
className="colorgreenorg font-14 ml6">待审核</p><p
className="fontcolorsysllan borcolors font-12 w64 mycompitcursor ml6"
onClick={() => this.Cancellationofapplication(2)}>撤销认证</p>
</p>
:
<p className="flexdirections">
<p className="iconfont icon-wancheng colorgreenlight font-14 ml20"></p><p
className="colorgreenlight font-14 ml6">已认证</p>
<p className="fontcolorsysllan borcolors font-12 w64 mycompitcursor ml6"
onClick={() => this.checkBasicInfo(2)}>重新认证</p>
</p>
}
</p>
</div>
<div className="flexdirections ml38 mt19">
<p
className="fontcolorsyslhui1">{basicInfo && basicInfo.technical_title ? "职称:" : ""}{basicInfo && basicInfo.student_id ? "学号:" : ""}</p>
<p className="fontcolorsyslhei">{basicInfo && (basicInfo.technical_title || basicInfo.student_id)}</p>
</div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1">学校</p>
<p className="fontcolorsyslhei">{basicInfo && basicInfo.school_name}</p>
</div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1">院系</p>
<p className="fontcolorsyslhei"> {basicInfo && basicInfo.department_name}</p>
</div>
<div className="flexdirections mt36 ">
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span></span>
</p>
</div>
<div className="flexdirections ml38 mt23">
<p className="fontcolorsyslhui1 w60 ">手机号</p>
{
basicInfo && basicInfo.phone ?
<p className="fontcolorsyslhei w200 ">{basicInfo && basicInfo.phone}</p>
:
<p className="fontcolorsysljin w200 ">未绑定</p>
}
<p className="fontcolorsysllan mycompitcursor"
onClick={() => this.phonebools()}>{basicInfo && basicInfo.phone ? (phonebool === false ? "更换" : "") : (phonebool === false ? "立即绑定" : "")}</p>
</div>
{/*手机号绑定*/}
{
phonebool === true ?
<Phonenumberverifications {...this.props} {...this.state} basicInfo={this.state.basicInfo}
hideUpdating={(i) => this.hideUpdating(i)}
getdata={() => this.getdata()}></Phonenumberverifications>
: ""
}
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1 w60">Email</p>
<p className="fontcolorsyslhei w200">{basicInfo && basicInfo.mail}</p>
<p className="fontcolorsysllan mycompitcursor"
onClick={() => this.emailbools()}>{basicInfo && basicInfo.mail ? (emailbool === false ? "更换" : "") : (emailbool === false ? "立即绑定" : "")}</p>
</div>
{
emailbool === false ? "" :
<Mailboxvalidations {...this.props} {...this.state} basicInfo={this.state.basicInfo}
hideUpdating={(i) => this.hideUpdating(i)}
getdata={() => this.getdata()}></Mailboxvalidations>
}
{
leader === true ?
<div>
{
bank_account_editable === true ?
<Bankcardnumberverifications {...this.props} {...this.state} basicInfo={this.state.basicInfo}
hideUpdating={(i) => this.hideUpdating(i)}
getdata={() => this.getdata()}
GetawardinformationAPI={() => this.GetawardinformationAPI()}
bank_account={this.state.bank_account}
></Bankcardnumberverifications>
:
<div>
<div className="flexdirections mt36">
<p className="fontcolorsyslhei font-16">//开户行及银行卡号</p>
<p className="fontcolorsyslhui font-14 ml11">为保障奖金的及时发放请队长如实填写你名下的银行卡信息</p>
</div>
{
bank_account && bank_account ?
<div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1 w56">开户行</p>
<p className="fontcolorsyslhei">{bank_account && bank_account.bank}</p>
</div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1 w56" style={{textAlign: "right"}}>支行</p>
<p className="fontcolorsyslhei">{bank_account && bank_account.second_bank}</p>
</div>
<div className="flexdirections ml38 mt19">
<p className="fontcolorsyslhui1 w56" style={{textAlign: "right"}}>账号</p>
<p className="fontcolorsyslhei"> {bank_account && bank_account.card_no}</p>
</div>
</div>
:
""
}
</div>
}
</div>
: ""
}
</div>
)
}
}
export default CompetitionContentspdfpeopledata;

@ -0,0 +1,270 @@
import React, {Component} from 'react';
import {Button, Layout, Input, Form} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import mycompetotionchild from './mycompetotionchild.css';
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
import '../../../../courses/css/Courses.css'
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
class Mailboxvalidation extends Component {
constructor(props) {
super(props)
this.state = {
basicInfo: {},
updating: '',
secondsFlag: false,
seconds: 60,
phonebool: false,
emailbool: false,
formationdata: [],
bank_account_editable: false,
leader: false,
bank_account: undefined,
certification: 1
}
}
componentDidMount() {
window.document.title = '竞赛';
// console.log("3获取用户信息");
// console.log(this.props);
}
// 绑定邮箱
onEmailSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let {login} = this.props.current_user;
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (reg.test(values.email)) {
let url = `/users/accounts/${login}/email_bind.json`
axios.post((url), {
email: values.email,
code: values.emailValidateCode
}).then((result) => {
if (result) {
this.props.showNotification("邮箱地址绑定成功!");
this.hideUpdating(2);
this.props.getdata();
}
}).catch((error) => {
console.log(error);
})
} else {
this.props.showNotification("请输入正确的邮箱地址");
}
}
})
}
//取消编辑
hideUpdating = (i) => {
if (i === 1) {
this.props.hideUpdating(1);
} else if (i === 2) {
this.props.hideUpdating(2);
} else if (i === 3) {
}
}
// 获取验证码
getCode = (index) => {
let url = `/accounts/get_verification_code.json`
let login = '';
let values = this.props.form.getFieldsValue();
if (index == 3) {
//绑定手机号码
login = values.phone;
let reg = /^1\d{10}$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的手机号码`);
return;
}
} else if (index == 4) {
// 绑定邮箱
login = values.email;
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的邮箱地址`);
return;
}
}
let type = index;
if (!login) {
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
return;
}
axios.get((url), {
params: {
login, type
}
}).then((result) => {
if (result) {
// 倒计时
this.setState({
secondsFlag: true
})
this.remainTime();
}
}).catch((error) => {
console.log(error);
})
}
// 获取验证码倒计时
remainTime = () => {
this.setState({
seconds: 60
})
this.timer = setInterval(() => {
let {seconds} = this.state;
let s = parseInt(seconds) - 1;
if (s > -1) {
this.setState({
seconds: s
})
} else {
this.setState({
secondsFlag: false
})
clearInterval(this.timer);
}
}, 1000)
}
phonebools = () => {
this.setState({
phonebool: true
})
}
emailbools = () => {
console.log("点击了邮箱");
this.setState({
emailbool: true
})
}
render() {
const {getFieldDecorator} = this.props.form;
const {updating, seconds, secondsFlag, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
console.log(emailbool);
return (
<div>
<style>{`
.flexRow {
padding: 20px 0;
}
.flexRow .name {
margin-left: 12px;
color: #666666;
text-align: center;
flex: 0 0 100px;
}
.flexRow .description {
margin-left: 10px;
flex: 1;
color: #CDCDCD;
}
.description span {
margin-right: 20px;
color: #05101A;
}
.flexRow .status {
width: 100px;
color: #28AC7F;
text-align: right;
}
.flexTable .flexTable {
border-bottom: 1px solid #EBEBEB;
}
.settingForm label{
color: #666666;
font-size: 14px !important ;
}
.settingForm input {
width: 340px;
height: 40px;
}
.settingForm input.validateInput {
width: 220px;
}
.settingForm .formItemInline button {
width: 110px;
margin-left: 10px;
}
.settingForm .ant-form-item-label {
text-align: left;
width: 84px;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-22px;
left:0px;
width:100%;
}
`}</style>
<div className="settingForm ml38">
<React.Fragment>
<Form>
<Form.Item
label="邮箱地址"
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('email', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: basicInfo && basicInfo.mail ? '请输入要更换的新邮箱地址' : '请输入邮箱地址',
}],
})(
<Input placeholder={`${basicInfo && basicInfo.mail ? '请输入要更换的新邮箱地址' : '请输入邮箱地址'}`}></Input>
)}
</Form.Item>
<Form.Item
label="邮箱验证码"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('emailValidateCode', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入邮箱收到的验证码',
}],
})(
<Input placeholder="请输入邮箱收到的验证码" className="validateInput"></Input>
)}
<Button type="primary" disabled={secondsFlag} onClick={() => this.getCode(4)}>
{!secondsFlag ? "获取验证码" : `重新发送${seconds}s`}</Button>
</Form.Item>
<div className="mb20" style={{marginLeft: '204px'}}>
<Button type="primary" onClick={() => this.onEmailSubmit()}>确定</Button>
<Button type="primary grayBtn" style={{marginLeft: '20px'}}
onClick={() => this.hideUpdating(2)}>取消</Button>
</div>
</Form>
</React.Fragment>
</div>
</div>
)
}
}
const Mailboxvalidations = Form.create({name: 'Mailboxvalidation'})(Mailboxvalidation);
export default Mailboxvalidations;

@ -0,0 +1,262 @@
import React, {Component} from 'react';
import {Button, Layout, Input, Form} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import mycompetotionchild from './mycompetotionchild.css';
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
import '../../../../courses/css/Courses.css'
import RealNameCertificationModal from "../../../../user/modal/RealNameCertificationModal";
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
class Phonenumberverification extends Component {
constructor(props) {
super(props)
this.state = {
updating: '',
secondsFlag: false,
seconds: 60,
phonebool: false,
emailbool: false,
formationdata: [],
bank_account_editable: false,
leader: false,
bank_account: undefined,
certification: 1
}
}
componentDidMount() {
window.document.title = '竞赛';
// console.log("获取用户信息");
// console.log(this.props);
}
// 绑定手机
onPhoneSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let {login} = this.props.current_user;
let reg = /^1\d{10}$/;
if (reg.test(values.phone)) {
let url = `/users/accounts/${login}/phone_bind.json`
axios.post((url), {
phone: values.phone,
code: values.phoneValidateCode
}).then((result) => {
if (result) {
this.props.showNotification("手机号码绑定成功!");
this.props.hideUpdating()
this.props.getdata();
}
}).catch((error) => {
console.log(error);
})
} else {
this.props.showNotification("请输入有效的11位手机号码");
}
}
})
}
//取消编辑
hideUpdating = (i) => {
if (i === 1) {
this.props.hideUpdating(1);
} else if (i === 2) {
this.props.hideUpdating(2);
} else if (i === 3) {
}
}
// 获取验证码
getCode = (index) => {
let url = `/accounts/get_verification_code.json`
let login = '';
let values = this.props.form.getFieldsValue();
if (index == 3) {
//绑定手机号码
login = values.phone;
let reg = /^1\d{10}$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的手机号码`);
return;
}
} else if (index == 4) {
// 绑定邮箱
login = values.email;
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (reg.test(login) == false) {
this.props.showNotification(`请先输入正确的邮箱地址`);
return;
}
}
let type = index;
if (!login) {
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
return;
}
axios.get((url), {
params: {
login, type
}
}).then((result) => {
if (result) {
// 倒计时
this.setState({
secondsFlag: true
})
this.remainTime();
}
}).catch((error) => {
console.log(error);
})
}
// 获取验证码倒计时
remainTime = () => {
this.setState({
seconds: 60
})
this.timer = setInterval(() => {
let {seconds} = this.state;
let s = parseInt(seconds) - 1;
if (s > -1) {
this.setState({
seconds: s
})
} else {
this.setState({
secondsFlag: false
})
clearInterval(this.timer);
}
}, 1000)
}
phonebools = () => {
this.setState({
phonebool: true
})
}
render() {
const {getFieldDecorator} = this.props.form;
const {updating, seconds, secondsFlag, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
const {basicInfo} = this.props
console.log(emailbool);
return (
<div>
<style>{`
.flexRow {
padding: 20px 0;
}
.flexRow .name {
margin-left: 12px;
color: #666666;
text-align: center;
flex: 0 0 100px;
}
.flexRow .description {
margin-left: 10px;
flex: 1;
color: #CDCDCD;
}
.description span {
margin-right: 20px;
color: #05101A;
}
.flexRow .status {
width: 100px;
color: #28AC7F;
text-align: right;
}
.flexTable .flexTable {
border-bottom: 1px solid #EBEBEB;
}
.settingForm label{
color: #666666;
font-size: 14px !important ;
}
.settingForm input {
width: 340px;
height: 40px;
}
.settingForm input.validateInput {
width: 220px;
}
.settingForm .formItemInline button {
width: 110px;
margin-left: 10px;
}
.settingForm .ant-form-item-label {
text-align: left;
width: 84px;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-22px;
left:0px;
width:100%;
}
`}</style>
<div className="settingForm ml38">
<React.Fragment>
<Form>
<Form.Item
label="你的手机号"
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('phone', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: `请输入要${basicInfo.phone ? '更换' : '绑定'}的手机号码`,
}],
})(
<Input placeholder={`请输入要${basicInfo.phone ? '更换' : '绑定'}的手机号码`}></Input>
)}
</Form.Item>
<Form.Item
label="手机验证码"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('phoneValidateCode', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入手机获取的验证码',
}],
})(
<Input placeholder="请输入手机获取的验证码" className="validateInput"></Input>
)}
<Button type="primary" disabled={secondsFlag} onClick={() => this.getCode(3)}>
{!secondsFlag ? "获取验证码" : `重新发送${seconds}s`}
</Button>
</Form.Item>
<div className="mb20" style={{marginLeft: '204px'}}>
<Button type="primary" onClick={() => this.onPhoneSubmit()}>确定</Button>
<Button type="primary grayBtn" style={{marginLeft: '20px'}}
onClick={() => this.hideUpdating(1)}>取消</Button>
</div>
</Form>
</React.Fragment>
</div>
</div>
)
}
}
const Phonenumberverifications = Form.create({name: 'Phonenumberverification'})(Phonenumberverification);
export default Phonenumberverifications;

@ -0,0 +1,314 @@
/*
*/
.flexdirectionjust {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.directstwebkitflex {
display: flex;
display: -webkit-flex;
flex-direction: column;
align-items: center;
}
.diredisplayitflex {
display: flex;
display: -webkit-flex;
align-items: center;
}
/*垂直布局*/
/*
*/
.flexdirection {
display: flex;
flex-direction: row;
}
.flexdirections {
display: flex;
flex-direction: initial;
}
/*
*/
/*靠右侧八 七 六 五 四 三 二 一*/
.flexdirectionss {
display: flex;
flex-direction: row-reverse;
}
/*
*/
.flexdidirectionss {
display: flex;
flex-direction: column;
}
/*
*/
.flexdidireverses {
display: flex;
flex-direction: column-reverse;
}
.fontcolorsysl {
color: #FF0000
}
.fontcolorsyslhei {
color: #000000
}
.fontcolorsyslhui {
color: #888888
}
.fontcolorsyslhui1 {
color: #666666;
}
.fontcolorsysllan {
color: #4CACFF
}
.fontcolorsysljin {
color: #DD7600
}
.w200 {
width: 200px;
}
.w64 {
width: 64px;
}
.w60 {
width: 60px;
}
.w98 {
width: 98px;
}
.myysllineheight {
line-height: 40px;
}
.myyslminwidth {
min-width: 60px;
}
.myyslminwidth276 {
width: 276px;
}
.buttongo {
background: #E7E7E7;
border: 1px solid #E7E7E7;
width: 60px;
height: 30px;
border-radius: 4px;
color: #999999;
font-size: 16px;
}
.buttongo2 {
background: #4CACFF;
border: 1px solid #4CACFF;
width: 64px;
height: 32px;
border-radius: 4px;
color: #FFFFFF;
font-size: 16px;
}
.fontwenzi {
text-align: center;
line-height: 30px;
}
.mt17 {
margin-top: 17px;
}
.mt36 {
margin-top: 36px;
}
.mt23 {
margin-top: 23px;
}
.mt19 {
margin-top: 19px;
}
.mt23 {
margin-top: 23px;
}
.mt34 {
margin-top: 34px;
}
.ml11 {
margin-left: 11px;
}
.ml38 {
margin-left: 38px;
}
.ml7 {
margin-left: 7px;
}
.colorgreenlight {
color: #6EC76E
}
.colorgreenorg {
color: #FF7300;
}
.borcolors {
border: 1px solid #4CACFF;
text-align: center;
}
.mycompitcursor {
cursor: pointer;
}
.basicForm {
background: #fff;
padding: 30px;
margin-bottom: 10px;
box-sizing: border-box;
width: 100%;
min-height: 390px;
}
.basicForm .title {
font-size: 16px;
padding-left: 30px;
margin-bottom: 10px;
}
.flexTable {
display: flex;
flex-direction: column;
}
.flexRow {
display: flex;
}
.mb15 {
margin-bottom: 15px !important;
}
/* BUTTOn */
.ant-btn {
border-radius: 2px;
}
button.ant-btn.ant-btn-primary.grayBtn {
background: #CBCBCB;
border-color: #CBCBCB;
}
.borderBottom {
border-bottom: 1px solid #4CACFF;
}
/* form ---------------- START */
.formItemInline {
display: flex;
}
.formItemInline .ant-form-item-control-wrapper {
display: inline-block;
}
.hideRequireTag .ant-form-item-required:before {
display: none;
}
/* .basicForm .ant-form-item-label {
width: 100px;
padding-right: 10px;
}
.basicForm .ant-form-item-label label {
color: #979797
} */
.courseNormalForm .ant-select-show-search {
height: 40px;
}
.courseNormalForm .ant-select-auto-complete.ant-select .ant-input {
height: 40px;
}
.courseNormalForm .ant-select-search__field__mirror {
height: 40px;
}
.courseNormalForm .ant-input-lg {
height: 40px;
}
.courseNormalForm .ant-select-selection--single {
height: 40px;
}
.courseNormalForm .ant-select-auto-complete.ant-select .ant-select-selection--single {
height: 40px
}
.courseNormalForm .ant-input-affix-wrapper {
height: 40px;
}
/* 职业 */
.courseNormalForm .ant-select-selection-selected-value {
line-height: 38px
}
.courseNormalForm input {
height: 40px;
}
.w300 {
width: 300px;
}
.w56 {
width: 56px;
}

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

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

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

@ -160,44 +160,18 @@ class Statistics extends Component{
derivefun=(url)=>{
let{group_ids}=this.state;
let data={
group_id:group_ids
}
axios.get(url,{params:
data,
paramsSerializer: function(params) {
return qs.stringify(params, {arrayFormat: 'brackets'})
}
}).then((response)=>{
if(response === undefined){
return
}
if(response.data.status&&response.data.status===-1){
this.props.showNotification(response.data.message);
}else if(response.data.status&&response.data.status===-2){
// if(response.data.message === "100"){
// // 已超出文件导出的上限数量100 ),建议:
//
// this.setState({
// DownloadType:true,
// DownloadMessageval:100
// })
// }else {
// //因附件资料超过500M
// this.setState({
// DownloadType:true,
// DownloadMessageval:500
// })
// }
this.props.showNotification(response.data.message);
}else {
// this.props.showNotification(`正在下载中`);
// window.open("/api"+url, '_blank');
this.props.slowDownload(url);
}
}).catch((error) => {
console.log(error)
});
let list=group_ids;
let urllist="";
if(list!=undefined&&list.length!=0)
list.map((item,key)=>{
if(key===0){
urllist=`group_id[]=${item}`
}else{
urllist=urllist+`&group_id[]=${item}`
}
})
this.props.slowDownload(`${url}?${urllist}`);
}

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

@ -1,3 +1,131 @@
state说明
tasks详情接口
allowed_unlock 为true时才允许非管理员用户解锁隐藏测试集
discusses_count 总评论数
challenge 实训关卡信息
exec_time --
modify_time --
path 关卡文件路径
position 第几关
praises_count 点赞数
score 分数
shixun_id
st 0-编程题 1-选择题
subject 关卡名称
task_pass 过关任务
web_route --
game 为每一个用户独立创建的实训关卡对应的信息
accuracy --
answer_deduction--
answer_open --
challenge_id
cost_time 通关耗时
created_at
end_time
evaluate_count
final_score
id
identifier
modify_time
myshixun_id
open_time
picture_path
resubmit_identifier
retry_status
star
status 2-已通关
test_sets_view true-测试集已解锁
updated_at
user_id
game_count 关卡数
git_url 仓库地址vnc会用到
has_answer
is_teacher 是否是老师 初始化被赋值到 user.is_teacher
last_compile_output
mirror_name 镜像名称 TPIMonaco会用到这个属性来判断当前关卡使用的什么语言 见 mirror2LanguageMap
myshixun
commit_id: "80cb6fc55a14bdd64a9c99913f416966238ed3de"
created_at: "2019-07-26T09:00:31.000+08:00"
git_url: null
gpid: null
id: 542543
identifier: "ns53g8vfeo" 有些接口会用到
is_public: true
modify_time: "2017-11-02T18:12:23.000+08:00"
onclick_time: "2019-07-26T09:00:31.000+08:00"
repo_name: "p15478209/ns53g8vfeo20190726090031"
reset_time: "2017-10-25T09:33:03.000+08:00"
shixun_id: 61
status: 0
system_tip: true (如果修改了测试集 || 修改了代码) && system_tip为true 也就是下面代码为true时才显示更新通知弹框
const showUpdateButton = (tpm_cases_modified || needUpdateScript) && myshixun.system_tip === true;
updated_at: "2019-11-05T10:58:35.000+08:00"
user_id: 24731
myshixun_manager: true
next_game: "so7ijzqe63a9" 下一关identifier
praise_count: 120 点赞数
prev_game: "bxg5w9uonhts" 上一关identifier
record_onsume_time: 0.296 上一次评测耗时 初始化被赋值到newResData.record = newResData.record_onsume_time
sets_error_count: 0 失败测试集数量
shixun
authentication: false
averge_star: 4.9
can_copy: false
challenges_count: 4 关卡数
closer_id: null
code_edit_permission: false 是否允许修改代码
code_hidden: false 是否隐藏文件目录按钮
created_at: "2017-06-09T11:32:16.000+08:00"
end_time: null
excute_time: null
exec_time: 25
forbid_copy: false forbid_copy ? "不允许学员复制和粘贴代码" : "允许学员复制和粘贴代码"
fork_from: null
git_url: "educoder/uznmbg54"
gpid: 2448
hidden: false
hide_code: false 是否隐藏代码tab
homepage_show: true
id: 61
identifier: "uznmbg54"
image_text: null
language: "Python3.6" !!
major_id: 635
mirror_script_id: null
modify_time: "2017-11-02T18:12:23.000+08:00"
multi_webssh: false 多命令行tab
myshixuns_count: 9655 学员数
name: "Python表达式问题求解※"
opening_time: null
pod_life: 0
publish_time: "2017-09-01T10:37:49.000+08:00"
repo_name: "educoder/uznmbg54"
reset_time: "2017-10-25T09:33:03.000+08:00"
sigle_training: false
status: 2 shixun.status >= 2 实训已发布 shixun.status <= 1 模拟实战
task_pass: task_pass ? "允许学员跳关挑战" : "不允许学员跳关挑战"
test_set_permission: true test_set_permission ? "允许学员通过金币解锁查看测试集内容" : "不允许学员通过金币解锁查看测试集内容"
trainee: 1
updated_at: "2019-10-11T08:50:59.000+08:00"
use_scope: 0
user_id: 3039
users_count: 4
visits: 69699
webssh: 1 是否显示命令行tab
st 0-编程题 1-选择题
test_sets 测试集
test_sets_count: 1
time_limit: 25 game_status.json轮训次数
tomcat_url: "http://47.96.157.89" web类型实训可以打开展现一个测试服务用来查看评测结果 const webDisplayUrl = `${tomcat_url}:${data.port}/${path}`
tpm_cases_modified: false 参考system_tip属性
tpm_modified: true 参考system_tip属性
user 当前关卡所属用户的信息
user_praise 当前用户是否点赞
-------------- -------------- -------------- -------------- -------------- -------------- -------------- -------------- --------------
TPIContextProvider
tpi主要的state容器主要接口`/tasks/${stageId}.json`一次性获取所有tpi首屏展示所需要的信息除了代码内容。
接口返回的内容包括
@ -20,3 +148,55 @@ TPIContextProvider
代码内容通过以下接口获取:
`/tasks/${game.identifier}/rep_content.json?path=${path}&status=${status}&retry=${isRetry ? 1 : 0}`
层次结构
TPIContextProvider
page/Index
Header
TaskListContainer
TaskList 左侧划出的任务列表
MainContentContainer
MainContent
LeftViewContainer 左侧区域
LeftView
ChooseAnswerView 选择题答案
CommentContainer
Comments 评论列表
CodeEvaluateMultiLevelAnswerUnlock 多级别解锁
// 看设置是vnc or 代码 or 选择题
CodeRepositoryViewContainer for VNC
VNCContainer
CodeEvaluateView 代码评测结果
VNCDisplay vnc显示
ActionView 评测按钮区
|| CodeRepositoryViewContainer 代码显示区
WebSSHTimer ssh倒计时
TPIMonaco monaco编辑器
|| ChooseRepositoryView 选择题显示区
// 看设置,是代码 or 选择题
CodeEvaluateView
|| ChooseEvaluateView
ActionView 评测按钮区
没用的文件
LeftNav.js
AnswerListContainer.js left 他人解答
TPI SSH
命令行的js资源都位于这个目录/react/public/js/jsFromMiddleLayer/base64.js
/page/main/CodeRepositoryView.js文件中open_webssh.json接口返回后会根据代码区试图大小计算ssh视图的大小同样的逻辑在js_min_all中也有
var h = $("#games_repository_contents").height() - $("#top_repository").height() - repositoryTabHeight;
这里有个对应的issue https://www.trustie.net/issues/25279
这里是要判断特殊的屏幕(公司dell笔记本可重现),针对这些情况处理,加高命令行的高度
ps js_min_all中搜`$("#games_repository_contents").height()`可以找到相关代码
VNCDisplay
使用的github上的代码 https://github.com/novnc/noVNC/

@ -0,0 +1,169 @@
import React, {Component} from 'react';
import {Button, Layout, Input, Form} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
class Modifytext extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {
}
//重新输入教学模式
Modifytext = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const url = `/paths/${this.props.pathid}/update_team_title.json`;
axios.post(url, {
team_title: values.teachingteam
}).then((response) => {
console.log(response);
if (response) {
if (response.data) {
if (response.data.status === 0) {
try {
this.props.showNotification("修改成功!");
} catch (e) {
}
try {
this.props.modifysy(2);
} catch (e) {
}
}
}
}
}).catch((error) => {
console.log(error)
})
}
})
}
render() {
const {getFieldDecorator} = this.props.form;
return (
<div>
<div className="ml38">
<style>{`
.flexRow {
padding: 20px 0;
}
.flexRow .name {
margin-left: 12px;
color: #666666;
text-align: center;
flex: 0 0 100px;
}
.flexRow .description {
margin-left: 10px;
flex: 1;
color: #CDCDCD;
}
.description span {
margin-right: 20px;
color: #05101A;
}
.flexRow .status {
width: 100px;
color: #28AC7F;
text-align: right;
}
.flexTable .flexTable {
border-bottom: 1px solid #EBEBEB;
}
.settingFormsy label{
color: #666666;
font-size: 14px !important ;
}
.settingFormsy input {
width: 275px;
height: 32px;
}
.settingFormsy input.validateInput {
width: 220px;
}
.settingFormsy .formItemInline button {
width: 110px;
margin-left: 10px;
}
.settingFormsy .ant-form-item-label {
width: 60px;
text-align: left;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-22px;
left:0px;
width:100%;
}
.yslzxueshi .ant-input{
height: 40px !important;
width: 276px !important
}
// class="ant-col ant-form-item-label"
`}</style>
<div className="settingFormsy">
<React.Fragment>
<Form>
<div style={{
display: "flex",
flexDirection: "initial",
lineHeight: " 51px",
}}>
<Form.Item
label=""
className="formItemInline hideRequireTag mb20 mt20"
>
{getFieldDecorator('teachingteam', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入模式',
}],
})(
<Input placeholder={`例如:教学团队`}></Input>
)}
</Form.Item>
<div className="flexdirections yslzxueshi ml38 ">
<p className="fontcolorsyslhui1 font-14 myysllineheight myyslminwidth"></p>
<div className=" flexdirections ml10">
{/*<div className="buttongo mycompitcursor" onClick={()=>this.yhBanksfalse()}><p className="fontwenzi mycompitcursor" >取消</p></div>*/}
<Button type="primary" onClick={() => this.Modifytext()}>确定</Button>
</div>
</div>
</div>
</Form>
</React.Fragment>
</div>
</div>
</div>
)
}
}
const Modifytexts = Form.create({name: 'Modifytext'})(Modifytext);
export default Modifytexts;

@ -12,7 +12,7 @@ import Modals from '../../modals/Modals';
import axios from 'axios';
import TPMRightSection from "../../tpm/component/TPMRightSection";
import styled from "styled-components";
import Modifytext from './Modifytext';
const getItemStyle = (isDragging, draggableStyle) => ({
// change background colour if dragging
background: isDragging ? '#dceeff' : '',
@ -87,7 +87,9 @@ class PathDetailIndex extends Component{
dataquerys:{},
MenuItemsindex:1,
MenuItemsindextype:0,
qrcode_img:null
qrcode_img: null,
team_title: "教学团队",
modify: false,
}
this.onDragEnd = this.onDragEnd.bind(this);
@ -256,6 +258,7 @@ class PathDetailIndex extends Component{
progress:result.data.progress,
members:result.data.members,
items: getItems(result.data.members.length),
team_title: result.data.team_title
})
}).catch((error)=>{
@ -321,6 +324,7 @@ class PathDetailIndex extends Component{
progress:result.data.progress,
members:result.data.members,
items: getItems(result.data.members.length),
team_title: result.data.team_title
})
}).catch((error)=>{
@ -458,6 +462,50 @@ class PathDetailIndex extends Component{
console.log(error)
})
}
modifysy = (i) => {
if (i === 1) {
this.setState({
modify: true
})
} else if (i === 2) {
this.setState({
modify: false
})
let righturl = "/paths/" + this.props.match.params.pathId + "/right_banner.json";
axios.get(righturl).then((result) => {
if (result.data.status === 407 || result.data.status === 401) {
debugger
return;
}
if (result.data.status === 403) {
debugger
// window.location.href = "/403";
return;
}
this.setState({
// detailInfoList:result.data,
tags: result.data.tags,
progress: result.data.progress,
members: result.data.members,
items: getItems(result.data.members.length),
team_title: result.data.team_title
})
}).catch((error) => {
console.log(error);
})
}
}
setteam_title(name) {
this.setState({
team_title: name
})
}
render(){
this.updatamakedown("shixuns_propaedeutics");
@ -475,7 +523,9 @@ class PathDetailIndex extends Component{
tags,
qrcode_img,
MenuItemsindex,
MenuItemsindextype
MenuItemsindextype,
team_title,
modify
} = this.state
@ -540,7 +590,7 @@ class PathDetailIndex extends Component{
</div>
<div className="with35 fr pl20">
{qrcode_img===null?"":<div className="edu-back-white newmustlearn mb10">
<img src={getImageUrl(`${qrcode_img}`)} />
<img src={`${qrcode_img}`} />
<div className="font-16 color181818">优惠报名扫码入群</div>
</div>}
<div className="edu-back-white mustlearn mb10">
@ -613,7 +663,19 @@ class PathDetailIndex extends Component{
{
members ===undefined ?"":members === null ?"":
<div className="teacherTeam edu-back-white clearfix" id="subject_members">
<p className="font-16 clearfix">教学团队</p>
{
detailInfoList === undefined ? "" : detailInfoList.allow_add_member === true ?
(
modify === false ?
<p className="font-16 clearfix" onDoubleClick={() => this.modifysy(1)}>{team_title}</p>
:
<Modifytext {...this.props} {...this.state} pathid={this.props.match.params.pathId}
modifysy={(i) => this.modifysy(i)}
setteam_title={(name) => this.setteam_title(name)}></Modifytext>
)
: ""
}
{ members===undefined?
members && members.map((item,key)=>{
@ -712,4 +774,4 @@ class PathDetailIndex extends Component{
)
}
}
export default PathDetailIndex;
export default PathDetailIndex;

@ -132,6 +132,7 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback, initV
// Or return editormd.toolbarModes[name]; // full, simple, mini
// Using "||" set icons align right.
const icons = ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"];
// 试卷处用到的填空题新增按钮
if (__that.props.showNullButton) {
icons.push('nullBtton')
}
@ -228,12 +229,14 @@ export default class TPMMDEditor extends Component {
const imageUrl = `/api/attachments.json`;
// 创建editorMd
let react_id = `react_${_id}`;
// 将实例存到了window
window[react_id] = this
const answers_editormd = create_editorMD(_id, '100%', this.props.height, _placeholder, imageUrl, (_editorName) => {
const __editorName = _editorName;
react_id = `react_${__editorName.id}`;
const that = window[react_id]
// 一个延迟的recreate或resize不加这段代码md初始化可能会出现样式问题
setTimeout(() => {
if (that.props.needRecreate == true) {
__editorName.recreate() // 注意 必须在setValue之前触发不然会清空
@ -268,6 +271,7 @@ export default class TPMMDEditor extends Component {
that.props.onCMBeforeChange(cm,change)
})
that.answers_editormd = __editorName;
// 这里应该可以去掉了,方便调试加的
window[__editorName.id+'_'] = __editorName;
}, initValue, this.onEditorChange,this.props.watch, {
noStorage: this.props.noStorage,
@ -276,6 +280,7 @@ export default class TPMMDEditor extends Component {
}, this);
}
// 用在form里时validate失败时出现一个红色边框
showError = () => {
this.setState({showError: true})
}

@ -28,6 +28,8 @@ const Option = Select.Option;
const RadioGroup = Radio.Group;
const { TextArea } = Input;
function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
var editorName = window.editormd(id, {
width: width,
@ -1155,19 +1157,22 @@ export default class TPMevaluation extends Component {
</a>
</Tooltip>
</p>
<textarea className="textareavalue mb15" name="test_set[input][]"
<TextArea className="textareavalue mb15" name="test_set[input][]"
placeholder="输入"
value={item.input}
id={"textareavalue"+key}
autoHeight="true"
autoSize={{ minRows: 3, maxRows: 5 }}
onInput={(e)=>this.evaluationoninputvalue(e,key,"sr")}
></textarea>
<textarea className="textareavalue" name="test_set[output][]"
></TextArea>
<TextArea className="textareavalue" name="test_set[output][]"
placeholder="预期输出"
value={item.output}
id={key+"textareavalue"}
autoHeight="true"
autoSize={{ minRows: 3, maxRows: 5 }}
onInput={(e)=>this.evaluationoninputvalue(e,key,"yq")}
></textarea>
></TextArea>
<div className="clearfix lineh-30">
<span className="fl mr10 color-grey-6">匹配规则</span>
<RadioGroup className="fl" value={item.match_rule} onChange={(e)=>this.changeEvaluationRule(e,key)}>

@ -4,6 +4,7 @@ import { SnackbarHOC, getImageUrl, City, ConditionToolTip } from 'educoder';
import { Form, Button, Input, Radio, Select, Tooltip, Icon, AutoComplete } from 'antd'
import ApplyForAddOrgModal from '../modal/ApplyForAddOrgModal'
import ApplyForAddChildOrgModal from '../modal/ApplyForAddChildOrgModal'
import AccountBasicEditItem from './AccountBasicEditItem';
import axios from 'axios'
import { identityMap } from './AccountBasic'
const RadioGroup = Radio.Group;
@ -282,7 +283,9 @@ class AccountBasic extends Component {
getDepartments=(e,flag)=>{
let arr=this.state.schoolList.filter(function(item){
return item.name == e;
if(item.name.indexOf(e) > -1){
return item.name;
}
});
if (!arr[0]) {
if (!e) {
@ -354,20 +357,7 @@ class AccountBasic extends Component {
})
}
// 切换职称
changeJob=(e)=>{
this.setState({
identity:e
})
let {basicInfo}=this.props;
if(basicInfo){
this.props.form.setFieldsValue({
job1:basicInfo && basicInfo.identity=="teacher" ? basicInfo.technical_title:"教授",
job2:basicInfo && basicInfo.identity=="professional" ? basicInfo.technical_title:"企业管理者",
})
}
}
addOrgSuccess = (name) => {
// const schoolList = this.state.schoolList.slice(0)
@ -407,6 +397,19 @@ class AccountBasic extends Component {
}
callback(`请输入真实姓名,最大限制${MAX_NAME_LENGTH}个字符`);
}
// 切换职称
changeJob=(e)=>{
this.setState({
identity:e
})
let {basicInfo}=this.props;
if(basicInfo){
this.props.form.setFieldsValue({
job1:basicInfo && basicInfo.identity=="teacher" ? basicInfo.technical_title:"教授",
job2:basicInfo && basicInfo.identity=="professional" ? basicInfo.technical_title:"企业管理者",
})
}
}
render() {
let{
@ -422,10 +425,17 @@ class AccountBasic extends Component {
}=this.state;
const { getFieldDecorator } = this.props.form;
let{ basicInfo }=this.props
// 已职业认证的账户不能修改职业,学校/单位,院系/部门产品还未确定先默认为false--可以更改
// basicInfo && basicInfo.professional_certification == "certified"
const professionalFlag = false;
let common = {
changeJob:this.changeJob,
filterList:this.filterList,
changeList:this.changeList,
searchDepartment:this.searchDepartment,
changeDepartment:this.changeDepartment,
showApplyForAddOrgModal:this.showApplyForAddOrgModal,
showApplyForAddChildOrgModal:this.showApplyForAddChildOrgModal
}
// 已职业认证的账户不能修改职业,学校/单位,院系/部门true为disable
const professionalFlag = basicInfo && basicInfo.professional_certification == "certified" ;
// form合并了
const propsWithoutForm = Object.assign({}, this.props)
@ -599,177 +609,22 @@ class AccountBasic extends Component {
<City></City>
)}
</Form.Item>
<div className="clearfix">
<Form.Item
label="职业"
className="formItemInline fl"
>
{getFieldDecorator('job', {
rules: [{
initialValue:"teacher",
required: true,
message: '请先选择职业',
}],
})(
<Select style={{width:"190px",marginRight:"20px"}} onChange={this.changeJob} disabled={professionalFlag}>
<Option value="teacher">教师</Option>
<Option value="student">学生</Option>
<Option value="professional">专业人士</Option>
</Select>
)}
</Form.Item>
{
identity && identity=="student" &&
<Form.Item
label=""
className="formItemInline fl"
style={{ 'margin-top': '3px'}}
// style={{display:identity && identity=="student" ? "block":"none"}}
>
{getFieldDecorator('student_No', {
rules: [{
required: true,
message: '请先输入学号',
}],
})(
<Input type="text" placeholder="请输入学号" style={{width:"190px"}} disabled={professionalFlag}></Input>
)}
</Form.Item>
}
{
identity && identity=="teacher" &&
<Form.Item
label=""
className="formItemInline fl"
// style={{display:identity && identity=="teacher" ? "block":"none"}}
>
{getFieldDecorator('job1', {
rules: [{
initialValue:"教授",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}} disabled={professionalFlag}>
<Option value="教授">教授</Option>
<Option value="副教授">副教授</Option>
<Option value="讲师">讲师</Option>
<Option value="助教">助教</Option>
</Select>
)}
</Form.Item>
}
{
identity && identity=="professional" &&
<Form.Item
label=""
className="formItemInline fl mb0"
// style={{display:identity && identity=="professional" ? "block":"none"}}
>
{getFieldDecorator('job2', {
rules: [{
initialValue:"企业管理者",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}} disabled={professionalFlag}>
<Option value="企业管理者">企业管理者</Option>
<Option value="部门管理者">部门管理者</Option>
<Option value="高级工程师">高级工程师</Option>
<Option value="工程师">工程师</Option>
<Option value="助理工程师">助理工程师</Option>
</Select>
)}
</Form.Item>
}
</div>
<Form.Item
label="学校/单位"
className="formItemInline mb0"
>
{getFieldDecorator('org', {
rules: [{
// initialValue: this.state.cityDefaultValue,
// type: 'array',
required: true,
message: '请先选择学校/单位',
// 做不了输入时和submit时都会执行这里
// validator: (rule, value, callback) => {
// if (this.this_school_id) {
// callback();
// return;
// }
// callback('请先选择学校/单位');
// }
}],
})(
<AutoComplete width={400} showSearch onSearch={this.filterList} onChange={this.changeList} disabled={professionalFlag}>
{
filterSchoolList && filterSchoolList.map((item,key)=>{
return(<Option value={item.name} key={item.id}>{item.name}</Option>)
})
}
</AutoComplete>
)}
</Form.Item>
{!filterSchoolList || (filterSchoolList && filterSchoolList.length==0 )&& school &&
<div style={{marginLeft: '113px',height:"20px",lineHeight:"20px"}}>
<span>
<span style={{color: '#CDCDCD'}}>未找到包含{school}的高校</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddOrgModal}>申请新增</span>
</span>
</div>
}
<Form.Item
label="院系/部门"
className="formItemInline mb0"
style={{ 'margin-top': '10px'}}
>
{getFieldDecorator('org2', {
rules: [{
// initialValue: this.state.cityDefaultValue,
// type: 'array',
required: true,
message: '请先选择院系/部门',
// validator: (rule, value, callback) => {
// if (this.this_department_id) {
// callback();
// return;
// }
// callback('请先选择院系/部门');
// }
}],
})(
<AutoComplete width={400} showSearch onSearch={this.searchDepartment} onChange={this.changeDepartment} disabled={professionalFlag}>
{
filterDepartments && filterDepartments.map((item,key)=>{
return(
<Option value={item.name} key={item.name}>{item.name}</Option>
)
})
}
</AutoComplete>
)}
</Form.Item>
{
filterDepartments != undefined && ( (filterDepartments && filterDepartments.length==0 )
|| (departmentsName == '' && !this.state.department_id
&& (!departments || departments.length == 0) )) &&
<div style={{marginLeft: '113px',height:"20px",lineHeight:"20px"}}>
<span>
<span style={{color: '#CDCDCD'}}>{departmentsName ? `未找到包含“${departmentsName}”的院系/部门` : '未找到院系'}</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddChildOrgModal}>申请新增</span>
</span>
</div>
}
<AccountBasicEditItem
identity={identity}
getFieldDecorator = {getFieldDecorator}
professionalFlag = {professionalFlag}
basicInfo = {basicInfo}
{...this.props}
{...this.state}
{...common}
form={this.props.form}
filterSchoolList={filterSchoolList}
filterDepartments={filterDepartments}
departmentsName={departmentsName}
school={school}
department_id={this.state.department_id}
departments={departments}
></AccountBasicEditItem>
{/* htmlType="submit" */}
{/* <Form.Item>
<div className="clearfix mt30 mb30"> */}

@ -0,0 +1,199 @@
import React, { Component } from 'react';
import { SnackbarHOC, getImageUrl, City, ConditionToolTip } from 'educoder';
import { Form, Button, Input, Radio, Select, Tooltip, Icon, AutoComplete } from 'antd'
const RadioGroup = Radio.Group;
const Option = Select.Option;
class AccpimtBasicEditItem extends Component {
constructor(props){
super(props);
}
render(){
let {
professionalFlag ,
getFieldDecorator ,
identity ,
filterSchoolList ,
filterDepartments,
departmentsName,
school,
departments,
department_id
} = this.props
return(
<div>
<div className="clearfix mt10">
<Form.Item
label="职业"
className="formItemInline fl"
>
{getFieldDecorator('job', {
rules: [{
initialValue:"teacher",
required: true,
message: '请先选择职业',
}],
})(
<Select style={{width:"190px",marginRight:"20px"}} onChange={(e)=>this.props.changeJob(e)} disabled={professionalFlag}>
<Option value="teacher">教师</Option>
<Option value="student">学生</Option>
<Option value="professional">专业人士</Option>
</Select>
)}
</Form.Item>
{
identity && identity=="student" &&
<Form.Item
label=""
className="formItemInline fl"
style={{ 'margin-top': '3px'}}
// style={{display:identity && identity=="student" ? "block":"none"}}
>
{getFieldDecorator('student_No', {
rules: [{
required: true,
message: '请先输入学号',
}],
})(
<Input type="text" placeholder="请输入学号" style={{width:"190px"}} disabled={professionalFlag}></Input>
)}
</Form.Item>
}
{
identity && identity=="teacher" &&
<Form.Item
label=""
className="formItemInline fl"
// style={{display:identity && identity=="teacher" ? "block":"none"}}
>
{getFieldDecorator('job1', {
rules: [{
initialValue:"教授",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}} disabled={professionalFlag}>
<Option value="教授">教授</Option>
<Option value="副教授">副教授</Option>
<Option value="讲师">讲师</Option>
<Option value="助教">助教</Option>
</Select>
)}
</Form.Item>
}
{
identity && identity=="professional" &&
<Form.Item
label=""
className="formItemInline fl mb0"
// style={{display:identity && identity=="professional" ? "block":"none"}}
>
{getFieldDecorator('job2', {
rules: [{
initialValue:"企业管理者",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}} disabled={professionalFlag}>
<Option value="企业管理者">企业管理者</Option>
<Option value="部门管理者">部门管理者</Option>
<Option value="高级工程师">高级工程师</Option>
<Option value="工程师">工程师</Option>
<Option value="助理工程师">助理工程师</Option>
</Select>
)}
</Form.Item>
}
</div>
<Form.Item
label="学校/单位"
className="formItemInline mb0"
>
{getFieldDecorator('org', {
rules: [{
// initialValue: this.state.cityDefaultValue,
// type: 'array',
required: true,
message: '请先选择学校/单位',
// 做不了输入时和submit时都会执行这里
// validator: (rule, value, callback) => {
// if (this.this_school_id) {
// callback();
// return;
// }
// callback('请先选择学校/单位');
// }
}],
})(
<AutoComplete width={400} showSearch onSearch={this.props.filterList} onChange={this.props.changeList} disabled={professionalFlag}>
{
filterSchoolList && filterSchoolList.map((item,key)=>{
return(<Option value={item.name} key={item.id}>{item.name}</Option>)
})
}
</AutoComplete>
)}
</Form.Item>
{!filterSchoolList || (filterSchoolList && filterSchoolList.length==0 )&& school &&
<div style={{marginLeft: '113px',height:"20px",lineHeight:"20px"}}>
<span>
<span style={{color: '#CDCDCD'}}>未找到包含{school}的高校</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.props.showApplyForAddOrgModal}>申请新增</span>
</span>
</div>
}
<Form.Item
label="院系/部门"
className="formItemInline mb0"
style={{ 'margin-top': '10px'}}
>
{getFieldDecorator('org2', {
rules: [{
// initialValue: this.state.cityDefaultValue,
// type: 'array',
required: true,
message: '请先选择院系/部门',
// validator: (rule, value, callback) => {
// if (this.this_department_id) {
// callback();
// return;
// }
// callback('请先选择院系/部门');
// }
}],
})(
<AutoComplete width={400} showSearch onSearch={this.props.searchDepartment} onChange={this.props.changeDepartment} disabled={professionalFlag}>
{
filterDepartments && filterDepartments.map((item,key)=>{
return(
<Option value={item.name} key={item.name}>{item.name}</Option>
)
})
}
</AutoComplete>
)}
</Form.Item>
{
filterDepartments != undefined && ( (filterDepartments && filterDepartments.length==0 )
|| (departmentsName == '' && ! department_id
&& (!departments || departments.length == 0) )) &&
<div style={{marginLeft: '113px',height:"20px",lineHeight:"20px"}}>
<span>
<span style={{color: '#CDCDCD'}}>{departmentsName ? `未找到包含“${departmentsName}”的院系/部门` : '未找到院系'}</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.props.showApplyForAddChildOrgModal}>申请新增</span>
</span>
</div>
}
</div>
)
}
}
export default AccpimtBasicEditItem;

@ -76,7 +76,7 @@ class ApplyForAddChildOrgModal extends Component{
{...this.props }
onOk={this.onOk}
okText="保存"
className="applyForModal courseNormalForm"
className="applyForModal courseNormalForm styleForapply"
>
<style>{`
.applyForModal .ant-form-item-label {
@ -86,7 +86,7 @@ class ApplyForAddChildOrgModal extends Component{
.applyForModal .ant-form-item-label label {
color: #979797
}
.applyForModal .formItemInline .ant-form-item-control-wrapper {
.styleForapply .formItemInline .ant-form-item-control-wrapper {
width: 390px;
}
`}</style>

@ -148,7 +148,7 @@ class Infos extends Component{
}).catch((error)=>{
console.log(error)
})
}
changeType=(e)=>{
this.setState({
@ -165,7 +165,7 @@ class Infos extends Component{
axios.post(url).then((result)=>{
if(result){
// this.setState(
// (prevState) => ({
// (prevState) => ({
// data : update(prevState.data, {attendance_signed: {$set: true} })
// })
// )
@ -225,7 +225,7 @@ class Infos extends Component{
}
render(){
let {
let {
data ,
is_edit,
sign,
@ -243,7 +243,7 @@ class Infos extends Component{
currentLogin = this.props.current_user.login;
}
const _commonProps = {
is_current: isCurrent,
is_current: isCurrent,
login: currentLogin
}
return(
@ -254,16 +254,16 @@ class Infos extends Component{
{
isRenders && <Trialapplication {...this.props} {...this.state} Cancel={() => this.cancelModulationModels()}/>
}
<InfosBanner
{...this.props}
{...this.state}
<InfosBanner
{...this.props}
{...this.state}
{..._commonProps}
signFor={this.signFor}
followPerson={this.followPerson}
></InfosBanner>
<Switch {...this.props}>
{/* --------------------------------------------------------------------- */}
{/* 题库 */}
<Route exact path="/users/:username/topics/:topicstype"
@ -274,27 +274,27 @@ class Infos extends Component{
{/* 课堂 */}
{/* http://localhost:3007/courses/1309/homework/9300/setting */}
<Route exact path="/users/:username/courses"
render={
<Route exact path="/users/:username/courses"
render={
(props) => (<InfosCourse {...this.props} {...props} {...this.state} {..._commonProps}/>)
}
></Route>
{/* 实训 */}
{/* 实训项目 */}
<Route exact path="/users/:username/shixuns"
render={
(props) => (<InfosShixun {...this.props} {...props} {...this.state} {..._commonProps}/>)
}
></Route>
{/* 实训课程 */}
{/* 实践课程 */}
<Route exact path="/users/:username/paths"
render={
(props) => (<InfosPath {...this.props} {...props} {...this.state} {..._commonProps}/>)
}
></Route>
{/* 项目 */}
{/* 开发项目 */}
<Route exact path="/users/:username/projects"
render={
(props) => (<InfosProject {...this.props} {...props} {...this.state} {..._commonProps}/>)
@ -317,17 +317,16 @@ class Infos extends Component{
></Route>
<Route exact path="/users/:username"
render={
<Route exact path="/users/:username"
render={
(props) => (<InfosCourse {...this.props} {...props} {...this.state} {..._commonProps}/>)
}
></Route>
</Switch>
</Switch>
</div>
)
}
}
// CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC))
export default (Infos) ;
export default (Infos) ;

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {Tooltip,Menu,Pagination,Spin} from 'antd';
import {Tooltip, Menu, Pagination, Spin, Dropdown} from 'antd';
import Loadable from 'react-loadable';
import Loading from '../../../Loading';
import axios from 'axios';
@ -20,7 +20,8 @@ class InfosCourse extends Component{
status:undefined,
page:1,
per_page:16,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined,
data:undefined,
isSpin:false
@ -31,27 +32,35 @@ class InfosCourse extends Component{
this.setState({
isSpin:true
})
let{category,status,page}=this.state;
this.getCourses(category,status,page);
let {category, status, page, sort_by, sort_direction} = this.state;
this.getCourses(category, status, page, sort_by, sort_direction);
}
getCourses=(category,status,page)=>{
getCourses = (category, status, page, sort_by, sort_direction) => {
let url=`/users/${this.props.match.params.username}/courses.json`;
axios.get((url),{params:{
category,
status,
page,
sort_by,
sort_direction,
per_page: this.props.is_current && category && page ==1?17:16
}}).then((result)=>{
if(result){
console.log("请求成功");
this.setState({
totalCount:result.data.count,
data:result.data,
sort_direction: sort_direction,
sort_by: sort_by,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin: false
})
})
}
@ -62,8 +71,8 @@ class InfosCourse extends Component{
page:1,
isSpin:true
})
let{status}=this.state;
this.getCourses(cate,status,1);
let {status, sort_by, sort_direction} = this.state;
this.getCourses(cate, status, 1, sort_by, sort_direction);
}
//切换状态
changeStatus=(status)=>{
@ -72,8 +81,8 @@ class InfosCourse extends Component{
page:1,
isSpin:true
})
let{category}=this.state;
this.getCourses(category,status,1);
let {category, sort_by, sort_direction} = this.state;
this.getCourses(category, status, 1, sort_by, sort_direction);
}
//切换页数
changePage=(page)=>{
@ -81,8 +90,8 @@ class InfosCourse extends Component{
page,
isSpin:true
})
let{category,status}=this.state;
this.getCourses(category,status,page);
let {category, status, sort_by, sort_direction} = this.state;
this.getCourses(category, status, page, sort_by, sort_direction);
}
// 进入课堂
@ -92,6 +101,39 @@ class InfosCourse extends Component{
}
}
updatedlist(sort_by) {
//按照什么样子排序
this.setState({
isSpin: true
});
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, 1, sort_by, "desc");
}
updatedlists(sort_directions, i) {
// console.log("updatedlistssort_direction");
// console.log(sort_direction);
// console.log(i);
//是否是倒序
this.setState({
isSpin: true
});
let {category, status, page, sort_by, sort_direction} = this.state;
let sort_directiony = sort_directions;
if (sort_directions === "asc") {
if (sort_directions === sort_direction) {
sort_directiony = "desc"
}
} else if (sort_directions === "desc") {
if (sort_directions === sort_direction) {
sort_directiony = "asc"
}
}
this.getCourses(category, status, page, sort_by, sort_directiony);
}
render(){
let{
category,
@ -99,31 +141,167 @@ class InfosCourse extends Component{
page,
data,
totalCount,
isSpin
isSpin,
sort_by,
sort_direction
} = this.state;
let is_current=this.props.is_current;
// console.log(this.props.current_user&&this.props.current_user.user_identity==="学生")
const menu = (
<Menu>
<Menu.Item onClick={() => this.updatedlist("updated_at")}>
最新动态
</Menu.Item>
<Menu.Item onClick={() => this.updatedlist("created_at")}>
最新创建
</Menu.Item>
</Menu>
);
console.log("InfosCourse");
console.log(status);
return(
<div className="educontent">
<Spin size="large" spinning={isSpin}>
<style>
{
`
.whitepanelyslli {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelyslliss {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelysllis {
width: 66px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.whitepanelysllisyt {
width: 60px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
color: #4CACFF;
}
`
}
</style>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeCategory()}>全部</a></li>
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</a></li>
<li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category == "manage" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("manage")}
className="font-16 w66">{is_current ? "我" : "TA"}管理的</a></li>
<li className={category == "study" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("study")}
className="font-16 w66">{is_current ? "我" : "TA"}学习的</a></li>
</div>
<style>
{
` .secondNavs li {
color: #676767;
/* margin: 0px 20px; */
float: left;
}
.secondNavs li a:hover{
color: #4CACFF
}
.secondNavs li.active a{
color: #4CACFF
}
`
}
</style>
{
is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="processing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("processing")}>正在进行</a></li>
<li className={status=="end" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("end")}>已结束</a></li>
is_current &&
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className="w32">全部</a></li>
<li className={status == "processing" ? "active whitepanelysllis" : "whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("processing")} className="w66">正在进行</a></li>
<li className={status == "end" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("end")} className="w66">已结束</a></li>
</div>
}
<p className="pl25 pr25 clearfix font-12 mb20 mt20">
<p className="pl25 pr25 clearfix font-12 " style={{
lineHeight: "41px",
}}>
<span className="fl color-grey-9">共参与{totalCount}{category?category=="manage"?"发布":"学习":"课堂"}</span>
<span className="fr color-grey-9">时间最新</span>
<sapn className="relativef fr"
style={{
display: "flex",
flexDirection: "column",
height: "40px",
lineHeight: "40px",
}}
>
<span
style={{
flexDirection: "column",
textAlign: "center",
height: "10px",
lineHeight: "10px",
display: "table",
marginTop: "9px",
}}
>
<i className={sort_direction === "asc" ?
"iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"}
onClick={() => this.updatedlists("asc", 1)}></i>
</span>
<span
style={{
flexDirection: "column",
height: "10px",
lineHeight: "10px",
textAlign: "center",
display: "table",
}}
>
<i className={sort_direction === "desc" ?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"}
onClick={() => this.updatedlists("desc", 2)}></i>
</span>
</sapn>
<Dropdown overlay={menu}>
<span className="fr color-grey-9 mr10 pointer " style={{
display: "flex",
flexDirection: "initial",
}}>
<span>{sort_by === "updated_at" ? '最新动态' : sort_by === "created_at" ? '最新创建' : ""}</span>
</span>
</Dropdown>
</p>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix">
{/* 289 */}
{
@ -138,7 +316,7 @@ class InfosCourse extends Component{
return(
<div className="square-Item" onClick={()=>this.turnToCourses(`${item.first_category_url}`,item.can_visited)} style={{"cursor": "pointer",height:"289px"}}>
{
item.is_public == 1 &&
item.is_public == 1 &&
<React.Fragment>
<div className={key == 0 ?"publicpart orangeBlack":"publicpart"}></div>
<span className="smalltrangle"></span>
@ -152,7 +330,7 @@ class InfosCourse extends Component{
<p className="font-14 color-white">非成员不能访问</p>
</div>:""
}
<div className="substance">
<p className="subName font-16">
<span>{item.name}</span>
@ -171,14 +349,14 @@ class InfosCourse extends Component{
</span>:""}
{
item.members_count > 0 &&
item.members_count > 0 &&
<Tooltip placement="bottom" title="成员">
<span className="fl ml10 mr10 squareIconSpan">
<i className="iconfont icon-chengyuan fl mr3" data-tip-down="成员"></i>{item.members_count}</span>
</Tooltip>
}
{
item.homework_commons_count > 0 &&
item.homework_commons_count > 0 &&
<Tooltip placement="bottom" title="作业">
<span className="fl ml10 mr10 squareIconSpan">
<i className="iconfont icon-zuoye fl mr3" data-tip-down="作业"></i>{item.homework_commons_count}</span>
@ -199,7 +377,7 @@ class InfosCourse extends Component{
}
</div>
{
totalCount > 15 &&
totalCount > 15 &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={totalCount} onChange={this.changePage} pageSize={16} current={page}/>
</div>
@ -209,4 +387,4 @@ class InfosCourse extends Component{
)
}
}
export default InfosCourse;
export default InfosCourse;

@ -168,23 +168,82 @@ class InfosPackage extends Component{
modalSave={this.state.ModalSave}
/>
<Spin size="large" spinning={isSpin}>
<style>
{
`
.whitepanelyslli {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelyslliss {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelysllis {
width: 66px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
color: #4CACFF;
}
`
}
</style>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a onClick={()=>this.changeCategory()}>全部</a></li>
<li className={category=="manage" ? "active" : ""}><a onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li>
<li className={category=="bidden" ? "active" : ""}><a onClick={()=>this.changeCategory("bidden")}>{is_current ? "我":"TA"}参与的</a></li>
<li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category == "manage" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("manage")}
className="font-16 w66">{is_current ? "我" : "TA"}管理的</a></li>
<li className={category == "study" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("study")}
className="font-16 w66">{is_current ? "我" : "TA"}学习的</a></li>
</div>
<style>
{
` .secondNavs li {
color: #676767;
/* margin: 0px 20px; */
float: left;
}
.secondNavs li a:hover{
color: #4CACFF
}
.secondNavs li.active a{
color: #4CACFF
}
`
}
</style>
{
category=="manage"?
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="unpublished" ? "active" : ""}><a onClick={()=>this.changeStatus("unpublished")}>未发布</a></li>
<li className={status=="bidding" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding")}>竞标中</a></li>
<li className={status=="finished" ? "active" : ""}><a onClick={()=>this.changeStatus("finished")}>已完成</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a
onClick={() => this.changeStatus()} className="w32">全部</a></li>
<li className={status == "unpublished " ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
onClick={() => this.changeStatus("unpublished")} className="w60">未发布</a></li>
<li className={status == "bidding" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
onClick={() => this.changeStatus("bidding")} className="w60">竞标中</a></li>
<li className={status == "finished" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
onClick={() => this.changeStatus("finished")} className="w60">已完成</a></li>
</div>: category=="bidden"?
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="bidding_lost" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding_lost")}>未中标</a></li>
<li className={status=="bidding_won" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding_won")}>已中标</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a
onClick={() => this.changeStatus()} className="w32">全部</a></li>
<li className={status == "bidding_lost" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
onClick={() => this.changeStatus("bidding_lost")} className="w60">未中标</a></li>
<li className={status == "bidding_won" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
onClick={() => this.changeStatus("bidding_won")} className="w60">已中标</a></li>
</div>:""
}
<p className="pl25 pr25 clearfix font-12 mb20 mt20">
@ -289,4 +348,4 @@ class InfosPackage extends Component{
)
}
}
export default InfosPackage;
export default InfosPackage;

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {Tooltip,Menu,Pagination, Spin} from 'antd';
import {Tooltip, Menu, Pagination, Spin, Dropdown} from 'antd';
import Loadable from 'react-loadable';
import Loading from '../../../Loading';
import NoneData from '../../courses/coursesPublic/NoneData'
@ -19,11 +19,11 @@ class InfosPath extends Component{
this.state={
category:undefined,
page:1,
sort_by:'time',
status:undefined,
per_page:16,
isSpin:false,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined,
data:undefined
}
@ -33,28 +33,34 @@ class InfosPath extends Component{
this.setState({
isSpin:true
})
let{category,status,sort_by,page,per_page}=this.state;
this.getCourses(category,status,sort_by,page,per_page);
let {category, status, sort_by, page, per_page, sort_direction} = this.state;
this.getCourses(category, status, sort_by, page, sort_direction);
}
getCourses=(category,status,sort_by,page,per_page)=>{
getCourses = (category, status, sort_by, page, sort_direction) => {
let url=`/users/${this.props.match.params.username}/subjects.json`;
axios.get((url),{params:{
category,
status,
sort_by,
page,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{
if(result){
this.setState({
totalCount:result.data.count,
data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin: false
})
})
}
@ -66,18 +72,18 @@ class InfosPath extends Component{
page:1,
isSpin:true
})
let{sort_by}=this.state;
this.getCourses(cate,undefined,sort_by,1);
let {sort_by, sort_direction} = this.state;
this.getCourses(cate, undefined, sort_by, 1, sort_direction);
}
// 切换状态
changeStatus=(status)=>{
let{category,sort_by}=this.state;
let {category, sort_by, sort_direction} = this.state;
this.setState({
status,
page:1,
isSpin:true
})
this.getCourses(category,status,sort_by,1);
this.getCourses(category, status, sort_by, 1, sort_direction);
}
//切换页数
changePage=(page)=>{
@ -85,8 +91,8 @@ class InfosPath extends Component{
page,
isSpin:true
})
let{category,sort_by,status}=this.state;
this.getCourses(category,status,sort_by,page);
let {category, sort_by, status, sort_direction} = this.state;
this.getCourses(category, status, sort_by, page, sort_direction);
}
// 进入课堂
@ -101,15 +107,49 @@ class InfosPath extends Component{
sort_by:sort,
isSpin:true
})
let{category,status,page}=this.state;
this.getCourses(category,status,sort,page);
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, sort, page, sort_direction);
}
//切换种类
updatedlist(sort_by) {
//按照什么样子排序
this.setState({
isSpin: true
});
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, sort_by, 1, "desc");
}
//排序
updatedlists(sort_directions) {
//是否是倒序
this.setState({
isSpin: true
});
let {category, status, page, sort_by, sort_direction} = this.state;
let sort_directiony = sort_directions;
if (sort_directions === "asc") {
if (sort_directions === sort_direction) {
sort_directiony = "desc"
}
} else if (sort_directions === "desc") {
if (sort_directions === sort_direction) {
sort_directiony = "asc"
}
}
this.getCourses(category, status, sort_by, page, sort_directiony);
}
render(){
let{
category,
status,
sort_by,
sort_direction,
page,
data,
totalCount,
@ -117,35 +157,172 @@ class InfosPath extends Component{
} = this.state;
let isStudent = this.props.isStudent();
let is_current=this.props.is_current;
const menu = (
<Menu>
<Menu.Item onClick={() => this.updatedlist("updated_at")}>
最近更新
</Menu.Item>
<Menu.Item onClick={() => this.updatedlist("created_at")}>
最新创建
</Menu.Item>
</Menu>
);
return(
<div className="educontent">
<Spin size="large" spinning={isSpin}>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeCategory()}>全部</a></li>
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</a></li>
</div>
<style>
{
`
.whitepanelyslli {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelyslliss {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelysllis {
width: 66px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.whitepanelysllisyt {
width: 60px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
color: #4CACFF;
}
`
}
</style>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category == "manage" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("manage")}
className="font-16 w66">{is_current ? "我" : "TA"}管理的</a></li>
<li className={category == "study" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("study")}
className="font-16 w66">{is_current ? "我" : "TA"}学习的</a></li>
</div>
<style>
{
` .secondNavs li {
color: #676767;
/* margin: 0px 20px; */
float: left;
}
.secondNavs li a:hover{
color: #4CACFF
}
.secondNavs li.active a{
color: #4CACFF
}
`
}
</style>
{
category && category == "manage" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="editing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("editing")}>编辑中</a></li>
<li className={status=="applying" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("applying")}>待审核</a></li>
<li className={status=="published" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("published")}>已发布</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className="w32">全部</a></li>
<li className={status == "editing" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("editing")} className="w60">编辑中</a></li>
<li className={status == "applying" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("applying")} className="w60">待审核</a></li>
<li className={status == "published" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("published")} className="w60">已发布</a></li>
</div>
}
{
category && category == "study" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="unfinished" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("unfinished")}>未完成</a></li>
<li className={status=="finished" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("finished")}>已完成</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className="w32">全部</a></li>
<li className={status == "unfinished" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("unfinished")} className="w60">未完成</a></li>
<li className={status == "finished" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("finished")} className="w60">已完成</a></li>
</div>
}
<div className="pl25 pr25 clearfix font-12 mb20 mt20">
<div className="pl25 pr25 clearfix font-12 " style={{
lineHeight: "41px",
}}>
<span className="fl color-grey-9">共参与{totalCount}{category?category=="manage"?"发布":"学习":"实践课程"}</span>
<span className="fr color-grey-9">时间最新</span>
<sapn className="relativef fr"
style={{
display: "flex",
flexDirection: "column",
height: "40px",
lineHeight: "40px",
}}
>
<span
style={{
flexDirection: "column",
textAlign: "center",
height: "10px",
lineHeight: "10px",
display: "table",
marginTop: "9px",
}}
>
<i className={sort_direction === "asc" ?
"iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"}
onClick={() => this.updatedlists("asc")}></i>
</span>
<span
style={{
flexDirection: "column",
height: "10px",
lineHeight: "10px",
textAlign: "center",
display: "table",
}}
>
<i className={sort_direction === "desc" ?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"}
onClick={() => this.updatedlists("desc")}></i>
</span>
</sapn>
<Dropdown overlay={menu}>
<span className="fr color-grey-9 mr10 pointer " style={{
display: "flex",
flexDirection: "initial",
}}>
<span>{sort_by === "updated_at" ? '最近更新' : sort_by === "created_at" ? '最新创建' : ""}</span>
</span>
</Dropdown>
</div>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix">
{/* 295 */}
{
@ -163,7 +340,7 @@ class InfosPath extends Component{
item.tag && <div className="tag-green"><span className="tag-name">{item.tag}</span>
{/*<img src={setImagesUrl("images/educoder/tag2.png")} className="fl"/>*/}
</div>
}
}
<a href="javascript:void(0)" className="square-img"><img alt="Subject12" src={getImageUrl(`${item.image_url}`)}/></a>
<div className="square-main">
<p className="task-hide">
@ -190,7 +367,7 @@ class InfosPath extends Component{
}
</div>
{
totalCount > 15 &&
totalCount > 15 &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={totalCount} onChange={this.changePage} pageSize={16} current={page}/>
</div>
@ -200,4 +377,4 @@ class InfosPath extends Component{
)
}
}
export default InfosPath;
export default InfosPath;

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {Tooltip,Pagination,Spin} from 'antd';
import {Tooltip, Pagination, Spin, Dropdown, Menu} from 'antd';
import axios from 'axios';
import NoneData from '../../courses/coursesPublic/NoneData'
import {getImageUrl} from 'educoder';
@ -16,7 +16,8 @@ class InfosProject extends Component{
status:undefined,
page:1,
per_page:16,
sort_by: "updated_on",
sort_direction: "desc",
totalCount:undefined,
data:undefined,
isSpin:false
@ -27,16 +28,18 @@ class InfosProject extends Component{
this.setState({
isSpin:true
})
let{category,status,page}=this.state;
this.getCourses(category,status,page);
let {category, status, page, sort_by, sort_direction} = this.state;
this.getCourses(category, status, page, sort_by, sort_direction);
}
getCourses=(category,status,page)=>{
getCourses = (category, status, page, sort_by, sort_direction) => {
let url=`/users/${this.props.match.params.username}/projects.json`;
axios.get((url),{params:{
category,
status,
page,
sort_by,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{
if(result){
@ -49,6 +52,8 @@ class InfosProject extends Component{
this.setState({
totalCount:result.data.count,
data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false
})
}
@ -56,6 +61,9 @@ class InfosProject extends Component{
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin: false
})
})
}
@ -66,8 +74,9 @@ class InfosProject extends Component{
page:1,
isSpin:true
})
let{status}=this.state;
this.getCourses(cate,status,1);
let {status, sort_by, sort_direction} = this.state;
this.getCourses(cate, status, 1, sort_by,
sort_direction);
}
//切换状态
changeStatus=(status)=>{
@ -76,8 +85,12 @@ class InfosProject extends Component{
page:1,
isSpin:true
})
let{category}=this.state;
this.getCourses(category,status,1);
let {
category, sort_by,
sort_direction
} = this.state;
this.getCourses(category, status, 1, sort_by,
sort_direction);
}
//切换页数
changePage=(page)=>{
@ -85,8 +98,12 @@ class InfosProject extends Component{
page,
isSpin:true
})
let{category,status}=this.state;
this.getCourses(category,status,page);
let {
category, status, sort_by,
sort_direction
} = this.state;
this.getCourses(category, status, page, sort_by,
sort_direction);
}
// 进入项目
@ -96,6 +113,37 @@ class InfosProject extends Component{
}
}
//切换种类
updatedlist(sort_by) {
//按照什么样子排序
this.setState({
isSpin: true
});
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, 1, sort_by, "desc");
}
//排序
updatedlists(sort_directions) {
//是否是倒序
this.setState({
isSpin: true
});
let {category, status, page, sort_by, sort_direction} = this.state;
let sort_directiony = sort_directions;
if (sort_directions === "asc") {
if (sort_directions === sort_direction) {
sort_directiony = "desc"
}
} else if (sort_directions === "desc") {
if (sort_directions === sort_direction) {
sort_directiony = "asc"
}
}
this.getCourses(category, status, page, sort_by, sort_directiony);
}
render(){
let{
category,
@ -103,36 +151,168 @@ class InfosProject extends Component{
page,
data,
totalCount,
isSpin
isSpin,
sort_by,
sort_direction
} = this.state;
let isStudent = this.props.isStudent();
let is_current=this.props.is_current;
console.log(data)
const menu = (
<Menu>
<Menu.Item onClick={() => this.updatedlist("updated_on")}>
最新动态
</Menu.Item>
<Menu.Item onClick={() => this.updatedlist("created_on")}>
最新创建
</Menu.Item>
</Menu>
);
return(
<div className="educontent">
<Spin size="large" spinning={isSpin}>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeCategory()}>全部</a></li>
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</a></li>
</div>
<style>
{
`
.whitepanelyslli {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelyslliss {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelysllis {
width: 66px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.whitepanelysllisyt {
width: 60px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
color: #4CACFF;
}
`
}
</style>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category == "manage" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("manage")}
className="font-16 w66">{is_current ? "我" : "TA"}管理的</a></li>
<li className={category == "study" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("study")}
className="font-16 w66">{is_current ? "我" : "TA"}学习的</a></li>
</div>
<style>
{
` .secondNavs li {
color: #676767;
/* margin: 0px 20px; */
float: left;
}
.secondNavs li a:hover{
color: #4CACFF
}
.secondNavs li.active a{
color: #4CACFF
}
`
}
</style>
{
is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="publicly" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("publicly")}>公开</a></li>
<li className={status=="personal" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("personal")}>私有</a></li>
is_current &&
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className=" w32">全部</a></li>
<li className={status == "publicly" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("publicly")} className=" w60">公开</a></li>
<li className={status == "personal" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("personal")} className=" w60">私有</a></li>
</div>
}
<p className="pl25 pr25 clearfix font-12 mb20 mt20">
<p className="pl25 pr25 clearfix font-12 " style={{
lineHeight: "41px",
}}>
<span className="fl color-grey-9">共参与{totalCount}{category?category=="manage"?"发布":"学习":"项目"}</span>
<span className="fr color-grey-9">时间最新</span>
<sapn className="relativef fr"
style={{
display: "flex",
flexDirection: "column",
height: "40px",
lineHeight: "40px",
}}
>
<span
style={{
flexDirection: "column",
textAlign: "center",
height: "10px",
lineHeight: "10px",
display: "table",
marginTop: "9px",
}}
>
<i className={sort_direction === "asc" ?
"iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"}
onClick={() => this.updatedlists("asc")}></i>
</span>
<span
style={{
flexDirection: "column",
height: "10px",
lineHeight: "10px",
textAlign: "center",
display: "table",
}}
>
<i className={sort_direction === "desc" ?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"}
onClick={() => this.updatedlists("desc")}></i>
</span>
</sapn>
<Dropdown overlay={menu}>
<span className="fr color-grey-9 mr10 pointer " style={{
display: "flex",
flexDirection: "initial",
}}>
<span>{sort_by === "updated_on" ? '最近更新' : sort_by === "created_on" ? '最新创建' : ""}</span>
</span>
</Dropdown>
</p>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix">
{/* 289 */}
{
page == 1 && is_current && this.props.current_user && !category && this.props.current_user.user_identity != "学生" ?
page == 1 && is_current && this.props.current_user && !category && this.props.current_user.user_identity != "学生" ?
<Create href={`${this.props.Headertop && this.props.Headertop.old_url}/projects/new`} name={"新建开发项目"} index="4" Createtype={"projects"}
{...this.props} {...this.state}
></Create>:""
@ -174,17 +354,17 @@ class InfosProject extends Component{
<div className="edu-txt-center course-bottom">
<div className="inline color-grey-6">
{
item.members_count> 0 &&
item.members_count > 0 &&
<span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-chengyuan fl mr3" data-tip-down="成员"></i>{item.members_count}</span>
}
{
item.issues_count> 0 &&
item.issues_count > 0 &&
<span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-issue fl mr3" data-tip-down="issues数"></i>{item.issues_count}</span>
}
{
item.changesets_count> 0 &&
item.changesets_count > 0 &&
<span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-banbenku fl mr3" data-tip-down="版本库"></i>{item.changesets_count}</span>
}
@ -196,7 +376,7 @@ class InfosProject extends Component{
}
</div>
{
totalCount > 15 &&
totalCount > 15 &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={totalCount} onChange={this.changePage} pageSize={16} current={page}/>
</div>
@ -206,4 +386,4 @@ class InfosProject extends Component{
)
}
}
export default InfosProject;
export default InfosProject;

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Pagination , Spin } from 'antd';
import {Pagination, Spin, Dropdown, Menu} from 'antd';
import NoneData from '../../courses/coursesPublic/NoneData'
import axios from 'axios';
@ -16,11 +16,11 @@ class InfosShixun extends Component{
this.state={
category:undefined,
page:1,
sort_by:'time',
status:undefined,
per_page:16,
isSpin:false,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined,
data:undefined
}
@ -30,28 +30,40 @@ class InfosShixun extends Component{
this.setState({
isSpin:true
})
let{category,status,sort_by,page}=this.state;
this.getCourses(category,status,sort_by,page);
let {category, status, sort_by, page, sort_direction} = this.state;
this.getCourses(category, status, sort_by, page, sort_direction);
}
getCourses=(category,status,sort_by,page)=>{
getCourses = (category, status, sort_by, page, sort_direction) => {
// console.log("请求数据成功");
// console.log("getCourses");
// console.log(sort_by);
// console.log(sort_direction);
let url=`/users/${this.props.match.params.username}/shixuns.json`;
axios.get((url),{params:{
category,
status,
sort_by,
page,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{
if(result){
console.log("请求数据成功");
console.log(sort_by);
this.setState({
totalCount:result.data.count,
data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin: false
})
})
}
@ -63,8 +75,8 @@ class InfosShixun extends Component{
page:1,
isSpin:true
})
let{sort_by}=this.state;
this.getCourses(cate,undefined,sort_by,1);
let {sort_by, sort_direction} = this.state;
this.getCourses(cate, undefined, sort_by, 1, sort_direction);
}
// 切换状态
changeStatus=(status)=>{
@ -73,8 +85,8 @@ class InfosShixun extends Component{
page:1,
isSpin:true
})
let{category,sort_by}=this.state;
this.getCourses(category,status,sort_by,1);
let {category, sort_by, sort_direction} = this.state;
this.getCourses(category, status, sort_by, 1, sort_direction);
}
//切换页数
changePage=(page)=>{
@ -82,8 +94,8 @@ class InfosShixun extends Component{
page,
isSpin:true
})
let{category,sort_by,status}=this.state;
this.getCourses(category,status,sort_by,page);
let {category, sort_by, status, sort_direction} = this.state;
this.getCourses(category, status, sort_by, page, sort_direction);
}
// 进入课堂
@ -98,8 +110,39 @@ class InfosShixun extends Component{
sort_by:sort,
isSpin:true
})
let{category,status,page}=this.state;
this.getCourses(category,status,sort,page);
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, sort, page, sort_direction);
}
//切换种类
updatedlist(sort_by) {
//按照什么样子排序
this.setState({
isSpin: true
});
let {category, status, page, sort_direction} = this.state;
this.getCourses(category, status, sort_by, 1, "desc");
}
//排序
updatedlists(sort_directions) {
//是否是倒序
this.setState({
isSpin: true
});
let {category, status, page, sort_by, sort_direction} = this.state;
let sort_directiony = sort_directions;
if (sort_directions === "asc") {
if (sort_directions === sort_direction) {
sort_directiony = "desc"
}
} else if (sort_directions === "desc") {
if (sort_directions === sort_direction) {
sort_directiony = "asc"
}
}
this.getCourses(category, status, sort_by, page, sort_directiony);
}
render(){
@ -110,47 +153,171 @@ class InfosShixun extends Component{
page,
data,
totalCount,
sort_direction,
isSpin
} = this.state;
let is_current=this.props.is_current;
const menu = (
<Menu>
<Menu.Item onClick={() => this.updatedlist("updated_at")}>
最新动态
</Menu.Item>
<Menu.Item onClick={() => this.updatedlist("created_at")}>
语言类别
</Menu.Item>
</Menu>
);
return(
<div className="educontent">
<Spin size="large" spinning={isSpin}>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeCategory()}>全部</a></li>
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</a></li>
</div>
<style>
{
`
.whitepanelyslli {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelyslliss {
width: 32px !important;
height: 48px !important;
line-height: 46px !important;
}
.whitepanelysllis {
width: 66px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.whitepanelysllisyt {
width: 60px !important;
height: 48px !important;
line-height: 46px !important;
margin-left: 40px !important;
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
color: #4CACFF;
}
`
}
</style>
<div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category == "manage" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("manage")}
className="font-16 w66">{is_current ? "我" : "TA"}管理的</a></li>
<li className={category == "study" ? "active font-16 whitepanelysllis" : "font-16 whitepanelysllis"}><a
href="javascript:void(0)" onClick={() => this.changeCategory("study")}
className="font-16 w66">{is_current ? "我" : "TA"}学习的</a></li>
</div>
<style>
{
` .secondNavs li {
color: #676767;
/* margin: 0px 20px; */
float: left;
}
.secondNavs li a:hover{
color: #4CACFF
}
.secondNavs li.active a{
color: #4CACFF
}
`
}
</style>
{
category && category == "manage" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="editing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("editing")}>编辑中</a></li>
<li className={status=="applying" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("applying")}>待审核</a></li>
<li className={status=="published" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("published")}>已发布</a></li>
<li className={status=="closed" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("closed")}>已关闭</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className="w32">全部</a></li>
<li className={status == "editing" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("editing")} className="w60">编辑中</a></li>
<li className={status == "applying" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("applying")} className="w60">待审核</a></li>
<li className={status == "published" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("published")} className="w60">已发布</a></li>
<li className={status == "closed" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("closed")} className="w60">已关闭</a></li>
</div>
}
{
category && category == "study" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li>
<li className={status=="processing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("processing")}>未通关</a></li>
<li className={status=="passed" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("passed")}>已通关</a></li>
<div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
onClick={() => this.changeStatus()}
className="w32">全部</a></li>
<li className={status == "processing" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("processing")} className="w60">未通关</a></li>
<li className={status == "passed" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
href="javascript:void(0)" onClick={() => this.changeStatus("passed")} className="w60">已通关</a></li>
</div>
}
<div className="pl25 pr25 clearfix font-12 mb20 mt20">
<div className="pl25 pr25 clearfix font-12 " style={{
lineHeight: "41px",
}}>
<span className="fl color-grey-9">共参与{totalCount}{category?category=="manage"?"发布":"学习":"实训"}</span>
<div className="fr">
<li className="drop_down">
<span className="color-grey-9 font-12">{sort_by=="time"?"时间最新":"语言类别"}</span><i className="iconfont icon-xiajiantou font-12 ml2 color-grey-6"></i>
<ul className="drop_down_normal">
<li onClick={()=>this.changeOrder("time")}>时间最新</li>
<li onClick={()=>this.changeOrder("language")}>语言类别</li>
</ul>
</li>
</div>
<sapn className="relativef fr"
style={{
display: "flex",
flexDirection: "column",
height: "40px",
lineHeight: "40px",
}}
>
<span
style={{
flexDirection: "column",
textAlign: "center",
height: "10px",
lineHeight: "10px",
display: "table",
marginTop: "9px",
}}
>
<i className={sort_direction === "asc" ?
"iconfont icon-sanjiaoxing-up font-12 color-blue h10 " : "iconfont icon-sanjiaoxing-up font-12 h10"}
onClick={() => this.updatedlists("asc")}></i>
</span>
<span
style={{
flexDirection: "column",
height: "10px",
lineHeight: "10px",
textAlign: "center",
display: "table",
}}
>
<i className={sort_direction === "desc" ?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue h10" : "iconfont icon-sanjiaoxing-down font-12 yslbottomsj h10"}
onClick={() => this.updatedlists("desc")}></i>
</span>
</sapn>
<Dropdown overlay={menu}>
<span className="fr color-grey-9 mr10 pointer " style={{
display: "flex",
flexDirection: "initial",
}}>
<span>{sort_by === "updated_at" ? '最新动态' : sort_by === "created_at" ? '语言类别' : ""}</span>
</span>
</Dropdown>
</div>
<style>
{
@ -160,13 +327,14 @@ class InfosShixun extends Component{
left: 10px;
bottom: 100px;
}
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix">
{/* 298 */}
{
page == 1 && is_current && !category && this.props.current_user && this.props.current_user.user_identity != "学生" ?
page == 1 && is_current && !category && this.props.current_user && this.props.current_user.user_identity != "学生" ?
<Create href={"/shixuns/new"} name={"新建实训"} index="2"></Create>:""
}
{
@ -201,7 +369,7 @@ class InfosShixun extends Component{
}
</div>
{
totalCount > 15 &&
totalCount > 15 &&
<div className="mt30 mb50 edu-txt-center">
<Pagination showQuickJumper total={totalCount} onChange={this.changePage} pageSize={16} current={page}/>
</div>
@ -211,4 +379,4 @@ class InfosShixun extends Component{
)
}
}
export default InfosShixun;
export default InfosShixun;

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

Loading…
Cancel
Save