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 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 calculate_total_score current_competition
end end
end end
@ -174,6 +174,7 @@ class Admins::CompetitionStagesController < Admins::BaseController
end end
def calculate_total_score competition def calculate_total_score competition
competition.competition_scores.where(competition_stage_id: 0).destroy_all
competition.competition_teams.each do |team| competition.competition_teams.each do |team|
total_score = 0 total_score = 0
total_time = 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_score += stage_score.try(:score).to_f * stage.score_rate
total_time += stage_score.try(:cost_time).to_i total_time += stage_score.try(:cost_time).to_i
end end
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, 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) competition_stage_id: 0, score: total_score, cost_time: total_time)
end end
end end
end
end end

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

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

@ -11,9 +11,9 @@ class Competitions::CertificatesController < Competitions::BaseController
end end
def team 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_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 prize = team.competition_prize_users.first.competition_prize
filename = "#{current_competition.name}-#{prize.name}-#{team.name}.pdf" 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) @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 != '获奖证书' } @modules = @modules.select { |mod| mod.name != '获奖证书' }
end end
end end

@ -44,6 +44,12 @@ class Competitions::CompetitionsController < Competitions::BaseController
def common_header def common_header
@competition = current_competition @competition = current_competition
@competition_modules = @competition.unhidden_competition_modules @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 @user = current_user
current_competition.increment!(:visits) current_competition.increment!(:visits)
@ -113,6 +119,8 @@ class Competitions::CompetitionsController < Competitions::BaseController
@competition = current_competition @competition = current_competition
if params[:stage_id] if params[:stage_id]
@stage = @competition.competition_stages.find_by(id: 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 end
@records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i}) @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! before_action :require_prize_user!
def show 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 if @leader
@bank_account = self_prizes.find(&:leader?).extra @bank_account = self_prizes.find(&:leader?).extra
@bank_account_editable = self_prizes.select(&:leader?).all?(&:pending?) @bank_account_editable = self_prizes.select(&:leader?).all?(&:pending?)

@ -1084,14 +1084,23 @@ class ExercisesController < ApplicationController
@shixun_undo = 0 @shixun_undo = 0
@ques_undo = 0 @ques_undo = 0
ex_answer_time = @exercise.time.to_i ex_answer_time = @exercise.time.to_i
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) @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
end 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| @exercise_questions.each do |q|
if q.question_type == Exercise::PRACTICAL #当为实训题时 if q.question_type == Exercise::PRACTICAL #当为实训题时
user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id) 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) answer_deduction = challenge.challenge_answers.where("level <= #{@answer.level}").sum(:score)
@game.update_attributes!(:answer_open => answer_open, :answer_deduction => answer_deduction) @game.update_attributes!(:answer_open => answer_open, :answer_deduction => answer_deduction)
end end
GameAnswer.create!(challenge_answer_id: @answer.id, user_id: current_user.id, game_id: @game.id, view_time: Time.now)
rescue Exception => e rescue Exception => e
uid_logger_error("#######金币扣除异常: #{e.message}") uid_logger_error("#######金币扣除异常: #{e.message}")
@ -317,6 +318,7 @@ class GamesController < ApplicationController
@game.update_attributes!(:answer_open => 1, :answer_deduction => 100) @game.update_attributes!(:answer_open => 1, :answer_deduction => 100)
end end
@challenge_chooses = @challenge.challenge_chooses @challenge_chooses = @challenge.challenge_chooses
GameAnswer.create!(user_id: current_user.id, game_id: @game.id, view_time: Time.now)
rescue Exception => e rescue Exception => e
uid_logger_error("#######金币扣除异常: #{e.message}") uid_logger_error("#######金币扣除异常: #{e.message}")
raise ActiveRecord::Rollback raise ActiveRecord::Rollback

@ -125,6 +125,9 @@ class MessagesController < ApplicationController
@message.message_detail_attributes = {content: params[:content]} @message.message_detail_attributes = {content: params[:content]}
@message.save! @message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name) 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 rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
@ -201,4 +204,10 @@ class MessagesController < ApplicationController
def message_params def message_params
params.require(:message).permit(:subject, :sticky) params.require(:message).permit(:subject, :sticky)
end 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 end

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

@ -5,7 +5,7 @@ class SubjectsController < ApplicationController
before_action :find_subject, except: [:index, :create, :new, :append_to_stage] before_action :find_subject, except: [:index, :create, :new, :append_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish, before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish,
:search_members, :add_subject_members, :statistics, :shixun_report, :school_report, :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 ApplicationHelper
include SubjectsHelper include SubjectsHelper
@ -264,6 +264,12 @@ class SubjectsController < ApplicationController
end end
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 def search_members
tip_exception("搜索内容不能为空") unless params[:search] tip_exception("搜索内容不能为空") unless params[:search]
page = params[:page] || 1 page = params[:page] || 1

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

@ -142,6 +142,9 @@ module ExercisesHelper
right_users_count = 0 right_users_count = 0
#该问题的正确率 #该问题的正确率
if ex.question_type == Exercise::MULTIPLE #多选题 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 right_user_ids = user_ids
standard_answer.each do |choice_position| standard_answer.each do |choice_position|
standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id 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 if ex_time > 0
exercise_user = exercise.exercise_users.find_by(user_id:user.id) exercise_user = exercise.exercise_users.find_by(user_id:user.id)
time_mill = ex_time * 60 #转为秒 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 = exercise_user&.start_at.present? ? exercise_user.start_at.to_i : 0
#用户未开始答题时即exercise_user_start为0 #用户未开始答题时即exercise_user_start为0
if exercise_user_start == 0 if exercise_user_start == 0

@ -11,4 +11,8 @@ module MyshixunsHelper
nil nil
end end
end end
def view_answer_time game, user_id
game.game_answers.where(user_id: user_id).last&.view_time
end
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', authorize_url: '/oauth2.0/authorize',
token_url: '/oauth2.0/token' token_url: '/oauth2.0/token'
} }
option :token_params, { parse: :query }
def request_phase def request_phase
super super
@ -21,7 +22,17 @@ module OmniAuth
end end
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 info do
{ {
@ -35,15 +46,10 @@ module OmniAuth
{ raw_info: user_info } { raw_info: user_info }
end end
def raw_info
access_token.options[:mode] = :query
@raw_info ||= access_token.get('/oauth2.0/me').parsed
end
def user_info def user_info
access_token.options[:mode] = :query access_token.options[:mode] = :query
params = { oauth_consumer_key: options.client_id, openid: raw_info['openid'], format: 'json' } param = { oauth_consumer_key: options[:client_id], openid: uid, format: 'json' }
@user_info ||= access_token.get('/user/get_user_info', params: params) @user_info ||= access_token.get('/user/get_user_info', params: param, parse: :json).parsed
end end
end end
end end

@ -7,4 +7,11 @@ class UserMailer < ApplicationMailer
@code = code @code = code
mail(to: mail, subject: '验证你的电子邮件') mail(to: mail, subject: '验证你的电子邮件')
end 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 end

@ -1,4 +1,9 @@
class ChallengeAnswer < ApplicationRecord class ChallengeAnswer < ApplicationRecord
default_scope { order("challenge_answers.level asc") } default_scope { order("challenge_answers.level asc") }
belongs_to :challenge 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 end

@ -7,6 +7,30 @@ class CompetitionPrize < ApplicationRecord
enumerize :category, in: %i[bonus unset] 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 def self.member_suffix
'_member' '_member'
end end

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

@ -15,7 +15,7 @@ class Game < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :challenge belongs_to :challenge
has_one :run_code_message, :dependent => :destroy has_one :run_code_message, :dependent => :destroy
has_many :game_answers, :dependent => :destroy
#全部关卡数 #全部关卡数
scope :ch_games, lambda { |challenge_id| where(challenge_id:challenge_id) } 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 def en_role
is_teacher? ? 'teacher' : 'member' is_teacher? ? 'teacher' : 'member'
end end
def user_name
user&.real_name
end
end end

@ -1,7 +1,8 @@
class Admins::ApproveCompetitionPrizeUserService < ApplicationService class Admins::ApproveCompetitionPrizeUserService < ApplicationService
attr_reader :prize_user, :approver attr_reader :competition, :prize_user, :approver
def initialize(prize_user, approver) def initialize(prize_user, approver)
@competition = prize_user.competition
@prize_user = prize_user @prize_user = prize_user
@approver = approver @approver = approver
end end
@ -10,17 +11,25 @@ class Admins::ApproveCompetitionPrizeUserService < ApplicationService
raise Error, '请勿重复审批' if prize_user.approved? raise Error, '请勿重复审批' if prize_user.approved?
raise Error, '该用户未认证完成' unless prize_user.user_certified? raise Error, '该用户未认证完成' unless prize_user.user_certified?
prize = prize_user.competition_prize
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
prize_user.approve prize_user.approve
prize_user.approver = approver prize_user.approver = approver
prize_user.approved_at = Time.now prize_user.approved_at = Time.now
prize_user.save! 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 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 end
end end

@ -77,10 +77,11 @@ class Admins::CheckShixunMirrorsService < ApplicationService
@_bridge_images ||= begin @_bridge_images ||= begin
url = EduSetting.get('cloud_bridge') url = EduSetting.get('cloud_bridge')
res = Faraday.get(url) 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 rescue => e
Rails.logger.error("get response failed ! #{e.message}") Rails.logger.error("get response failed ! #{e.message}")
raise Error, '实训云平台繁忙繁忙等级84' raise Error, '实训云平台繁忙繁忙等级84'

@ -10,7 +10,7 @@ class Competitions::SavePrizeTeamAccountService < ApplicationService
def call def call
Competitions::SavePrizeTeamAccountForm.new(params).validate! 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) raise Error, '审批通过后不能修改' if prize_leaders.exists?(status: :approved)

@ -28,7 +28,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
user.create_user_extension!(gender: gender) user.create_user_extension!(gender: gender)
# 下载头像 # 下载头像
avatar_path = Util::FileManage.source_disk_filename(user) 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 end
new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], extra: params.dig('extra', 'raw_info')) new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], 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, autoRefresh: true,
smartIndent: true,//智能换行 smartIndent: true,//智能换行
styleActiveLine: true, styleActiveLine: true,
lineWrapping: true,
lint: true, lint: true,
readOnly: "nocursor" readOnly: "nocursor"
}); });

@ -14,6 +14,11 @@
<td><%= display_text prize_user.approver&.real_name %></td> <td><%= display_text prize_user.approver&.real_name %></td>
<td class="action-container"> <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? %> <% if prize_user.pending? %>
<%= link_to('审批通过', approve_admins_competition_competition_prize_user_path(prize_user.competition, prize_user), <%= link_to('审批通过', approve_admins_competition_competition_prize_user_path(prize_user.competition, prize_user),
data: { confirm: '确认审批通过吗?' }, data: { confirm: '确认审批通过吗?' },

@ -513,7 +513,9 @@
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">奖项配置</span> <span class="flex-1">奖项配置</span>
<% 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' %> <%= 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? %> <% if @competition.finished? && !@competition.competition_prize_users.exists? %>
<%= javascript_void_link '生成获奖记录', class: 'btn btn-primary btn-sm ml-2 generate-prize-user-action' %> <%= 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 json.bank_account_editable @bank_account_editable
end end
json.all_certified current_user.all_certified?
json.personal_certifications do json.personal_certifications do
json.array! @self_prizes do |prize_user| 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
end end
json.team_certifications do json.team_certifications do
json.array! @team_prizes do |team| 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
end end

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

@ -3,7 +3,7 @@ json.author do
end end
json.id message.id 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.time time_from_now(message.created_at)
json.hidden message.hidden json.hidden message.hidden
# 主贴与子贴不一致 # 主贴与子贴不一致

@ -6,4 +6,6 @@ json.array! @games do |game|
json.identifier get_game_identifier(@shixun.task_pass, game, @identity) 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_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.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 end

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

@ -12,6 +12,7 @@ json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager json.allow_visit @subject.status > 1 || @is_manager
json.allow_add_member @is_manager json.allow_add_member @is_manager
json.is_creator @is_creator json.is_creator @is_creator
json.cover url_to_avatar(@subject)
if @subject.excellent if @subject.excellent
json.has_start @subject.has_course_start? 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.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 = {} oauth_config = {}
begin begin
@ -13,5 +17,5 @@ rescue => ex
end end
Rails.application.config.middleware.use OmniAuth::Builder do 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 end

@ -6,6 +6,8 @@ Rails.application.routes.draw do
get 'attachments/download/:id', to: 'attachments#show' get 'attachments/download/:id', to: 'attachments#show'
get 'attachments/download/:id/:filename', 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 resources :edu_settings
scope '/api' do scope '/api' do
@ -289,6 +291,7 @@ Rails.application.routes.draw do
post :down_member_position post :down_member_position
get :right_banner get :right_banner
post :appointment post :appointment
post :update_team_title
end end
collection do 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])) -->
out+=this.renderer.em(this.output(cap[2]||cap[1]), cap.input) 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");*/ /*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没识别的问题 // b(i[1].replace(/^ *| *\| *$/g,"")) --> i[1].replace(/^ *| *\| *$/g, "").split(/ *\| */) table没识别的问题
// header.length===a.align.length --> header.length table没识别的问题 // header.length===a.align.length --> header.length table没识别的问题
// 2个table b(a.cells[p],a.header.length) -> a.cells[p].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */) // 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 // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map", // devtool: "cheap-module-eval-source-map",
// 开启调试 // 开启调试
//devtool: "source-map", // 开启调试 // devtool: "source-map", // 开启调试
// These are the "entry points" to our application. // These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle. // 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. // The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -222,6 +222,12 @@
<div class="code-name">&amp;#xe693;</div> <div class="code-name">&amp;#xe693;</div>
</li> </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"> <li class="dib">
<span class="icon iconfont">&#xe63c;</span> <span class="icon iconfont">&#xe63c;</span>
<div class="name">礼物</div> <div class="name">礼物</div>
@ -324,6 +330,12 @@
<div class="code-name">&amp;#xe678;</div> <div class="code-name">&amp;#xe678;</div>
</li> </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"> <li class="dib">
<span class="icon iconfont">&#xe608;</span> <span class="icon iconfont">&#xe608;</span>
<div class="name">喇叭</div> <div class="name">喇叭</div>
@ -1718,6 +1730,15 @@
</div> </div>
</li> </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"> <li class="dib">
<span class="icon iconfont icon-gift"></span> <span class="icon iconfont icon-gift"></span>
<div class="name"> <div class="name">
@ -1871,6 +1892,15 @@
</div> </div>
</li> </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"> <li class="dib">
<span class="icon iconfont icon-laba"></span> <span class="icon iconfont icon-laba"></span>
<div class="name"> <div class="name">
@ -3740,6 +3770,14 @@
<div class="code-name">#icon-renzhengxinxi</div> <div class="code-name">#icon-renzhengxinxi</div>
</li> </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"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-gift"></use> <use xlink:href="#icon-gift"></use>
@ -3876,6 +3914,14 @@
<div class="code-name">#icon-dashujucunchu</div> <div class="code-name">#icon-dashujucunchu</div>
</li> </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"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-laba"></use> <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": "e693",
"unicode_decimal": 59027 "unicode_decimal": 59027
}, },
{
"icon_id": "1214792",
"name": "关注",
"font_class": "weibiaoti105",
"unicode": "e6c0",
"unicode_decimal": 59072
},
{ {
"icon_id": "1221889", "icon_id": "1221889",
"name": "礼物", "name": "礼物",
@ -348,6 +355,13 @@
"unicode": "e678", "unicode": "e678",
"unicode_decimal": 59000 "unicode_decimal": 59000
}, },
{
"icon_id": "1901672",
"name": "关注",
"font_class": "guanzhu",
"unicode": "e6c5",
"unicode_decimal": 59077
},
{ {
"icon_id": "1941293", "icon_id": "1941293",
"name": "喇叭", "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="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" /> <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="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" /> <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="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" /> <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。 1、 安装node v6.9.x此安装包含了node和npm。
2、 安装cnpm命令行 npm install -g cnpm --registry=https://registry.npm.taobao.org 2、 安装cnpm命令行 npm install -g cnpm --registry=https://registry.npm.taobao.org

@ -173,7 +173,7 @@ function copyPublicFolder() {
}); });
} }
// 给build脚本增加的方法对其生成的index.html做一些文本替换以及cdn处理
function generateNewIndexJsp() { function generateNewIndexJsp() {
// var combinedStream = CombinedStream.create(); // var combinedStream = CombinedStream.create();
var filePath = paths.appBuild + '/index.html'; 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,9 +59,15 @@ const _origin = window.location.origin;
currentPage currentPage
comments comments
buttonText 发送按钮 显示文本
showRewardButton 是否显示奖励按钮 showRewardButton 是否显示奖励按钮
showHiddenButton 是否显示隐藏按钮 showHiddenButton 是否显示隐藏按钮
onlySuperAdminCouldHide 只有超级管理员才显示隐藏取消隐藏
isChildCommentPagination 是否子回复分页
loadMoreChildComments function 加载所有子回复
接口 接口
deleteComment 删除 deleteComment 删除
onPaginationChange 翻页变化 onPaginationChange 翻页变化
@ -402,6 +408,7 @@ class Comments extends Component {
</Tooltip> </Tooltip>
</span> </span>
</p> </p>
{/* __useKindEditor暂时没用到了TODO 可以去掉 */}
{ window.__useKindEditor ? <CommentItemKEEditor showReplyEditorFlag={showReplyEditorFlag} { window.__useKindEditor ? <CommentItemKEEditor showReplyEditorFlag={showReplyEditorFlag}
currentReplyComment={currentReplyComment} currentReplyComment={currentReplyComment}
item={item} item={item}

@ -1503,7 +1503,7 @@ class PersonModal extends Component {
color: "#D0021B", color: "#D0021B",
fontSize: "12px", fontSize: "12px",
marginTop: "9px" 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", color: "#D0021B",
fontSize: "12px", fontSize: "12px",
marginTop: "9px" marginTop: "9px"
}}>战队队员{GetenrollmentAPI.member_staff.minimum}-{GetenrollmentAPI.member_staff.maximum},{Thecurrentnumberstu}</p> }}>战队成员需{GetenrollmentAPI.member_staff.minimum}-{GetenrollmentAPI.member_staff.maximum},{Thecurrentnumberstu}</p>
: "" : ""
) : ) :

@ -3,9 +3,10 @@ import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Row, Col,Button, Menu, Icon
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import {markdownToHTML,getImageUrl} from 'educoder'; import {markdownToHTML,getImageUrl} from 'educoder';
import CompetitionContents from './CompetitionContents'; import CompetitionContents from './CompetitionCommonChild/CompetitionContents';
import CompetitionContentsChart from './CompetitionContentsChart'; import CompetitionContentsChart from './CompetitionCommonChild/CompetitionContentsChart';
import CompetitionContentsMd from './CompetitionContentsMd'; import CompetitionContentsMd from './CompetitionCommonChild/CompetitionContentsMd';
import CompetitionContentspdf from './CompetitionCommonChild/CompetitionContentspdf';
import './CompetitionCommon.css'; import './CompetitionCommon.css';
@ -15,14 +16,15 @@ class CompetitionCommon extends Component{
constructor(props) { constructor(props) {
super(props) super(props)
this.state={ this.state={
data:undefined, data: undefined,
bannerdata:undefined, bannerdata: undefined,
module_type:undefined, module_type: undefined,
mdContentdata:undefined, mdContentdata: undefined,
chart_rules:undefined, chart_rules: undefined,
Competitionedittype:false, Competitionedittype: false,
chartdata:undefined, chartdata: undefined,
has_url:false 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=()=>{ getbannerdata=()=>{
let menuid=this.props.location.search.replace('?menu=', ''); let menuid=this.props.location.search.replace('?menu=', '');
let url=`/competitions/${this.props.match.params.identifier}/common_header.json`; let url=`/competitions/${this.props.match.params.identifier}/common_header.json`;
axios.get(url).then((response) => { axios.get(url).then((response) => {
if(response.status===200){ if(response.status===200){
this.setState({ this.setState({
data:response.data, data: response.data,
thiskeys:menuid===undefined||menuid===""?response.data.competition_modules[0].id:menuid thiskeys: menuid === undefined || menuid === "" ? response.data.competition_modules[0].id : menuid,
mode: response.data.mode
}) })
if(menuid===undefined||menuid===""){ if(menuid===undefined||menuid===""){
this.getrightdata( this.getrightdata(
@ -80,13 +106,15 @@ class CompetitionCommon extends Component{
console.log(error) console.log(error)
}) })
if(this.props.user&&this.props.user.login!= ""){ //this.props.user 有可能为空
if (this.props.user && this.props.user.login != "") {
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`; const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => { axios.get((zul)).then((result) => {
if (result) { if (result) {
if (result.data) { if (result.data) {
this.setState({ this.setState({
signupdata:result.data signupdata: result.data
}) })
} }
} }
@ -98,7 +126,7 @@ class CompetitionCommon extends Component{
} }
getrightdatas=(e)=>{ getrightdatas=(e)=>{
let keys=parseInt(e.key); let keys = parseInt(e.key);
this.getlistdata(keys) this.getlistdata(keys)
this.props.history.replace(`?menu=${keys}`); this.props.history.replace(`?menu=${keys}`);
} }
@ -127,7 +155,7 @@ class CompetitionCommon extends Component{
if(response.status===200){ if(response.status===200){
this.setState({ this.setState({
chart_rules:response.data, 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
}) })
@ -145,7 +173,7 @@ class CompetitionCommon extends Component{
// return // return
// } // }
this.getnewchartdata(typeid,listkey) this.getnewchartdata(typeid, listkey)
if(has_url===false){ if(has_url===false){
let url=`${module_url}`; let url=`${module_url}`;
@ -167,7 +195,7 @@ class CompetitionCommon extends Component{
console.log(error) console.log(error)
}) })
}else{ }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.location.href= module_url
window.open(module_url) window.open(module_url)
}else{ }else{
@ -187,7 +215,7 @@ class CompetitionCommon extends Component{
Competitionedit=()=>{ Competitionedit=()=>{
this.setState({ this.setState({
Competitionedittype:true Competitionedittype: true
}) })
} }
@ -218,7 +246,7 @@ class CompetitionCommon extends Component{
// 以学生身份调用加入课堂 进入课堂首页 // 以学生身份调用加入课堂 进入课堂首页
let url="/courses/apply_to_join_course.json" let url="/courses/apply_to_join_course.json"
axios.post(url, { axios.post(url, {
invite_code:data.invite_code, invite_code: data.invite_code,
student:1 student:1
} }
).then((response) => { ).then((response) => {
@ -229,9 +257,43 @@ class CompetitionCommon extends Component{
} }
} }
}else{ }else{
if (url === "personal") {
this.Personalregistration()
} else {
this.props.history.replace(url); 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)=>{ Competitioncallback=(key)=>{
this.setState({ this.setState({
@ -252,34 +314,38 @@ class CompetitionCommon extends Component{
} }
render() { render() {
let {data,thiskeys,Competitionedittype}=this.state; let {data, module_type, Competitionedittype, signupdata} = this.state;
return ( return (
data===undefined?"":<div className={"educontent clearfix mt20 "}> data===undefined?"":<div className={"educontent clearfix mt20 "}>
<Breadcrumb separator=">"> <Breadcrumb separator=">">
<Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item> <Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item>
<Breadcrumb.Item>{data&&data.name}</Breadcrumb.Item> <Breadcrumb.Item>{data && data.name}</Breadcrumb.Item>
</Breadcrumb> </Breadcrumb>
<div className={"mt10 relative"}> <div className={"mt10 relative"}>
<Row className={"CompetitionCommonbanner"}> <Row className={"CompetitionCommonbanner"}>
{data.competition_status==="nearly_published"? {data.competition_status === "nearly_published" ?
data && data.permission.editable === true ? "" : data && data.permission.editable === true ? "" :
<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""} <div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""}
<img className={"Commonimg"} <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`):""} /> 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"}> <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)}/> <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>
<Col className={"CompetitionCommonbannerfont"} span={9}> <Col className={"CompetitionCommonbannerfont"} span={9}>
<Col className={data&&data.name.length>15?"competitionbannerdiv mt30":"competitionbannerdiv mt30"}>{data&&data.name}</Col> <Col
className={data && data.name.length > 15 ? "competitionbannerdiv mt30" : "competitionbannerdiv mt30"}>{data && data.name}</Col>
<Col className={"competitionbannerdiv mt10"}> <Col className={"competitionbannerdiv mt10"}>
<Col className={"Competitioncolor9b"}>竞赛时间<span className={"color000"}>{data&&data.start_time}{data&&data.end_time}</span></Col> <Col className={"Competitioncolor9b"}>竞赛时间<span
className={"color000"}>{data && data.start_time}{data && data.end_time}</span></Col>
{/*<Col></Col>*/} {/*<Col></Col>*/}
</Col> </Col>
@ -298,18 +364,21 @@ class CompetitionCommon extends Component{
<Row gutter={16}> <Row gutter={16}>
<Col className="gutter-row" span={6}> <Col className="gutter-row" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">¥{data&&data.bonus}</div> <div
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">¥{data && data.bonus}</div>
</Col> </Col>
<Col className="gutter-row ml20 rankbeicenter" span={6}> <Col className="gutter-row ml20 rankbeicenter" span={6}>
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">{data.competition_status==="nearly_published"?"--":data&&data.visits_count}</div> <div
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">{data.competition_status === "nearly_published" ? "--" : data && data.visits_count}</div>
</Col> </Col>
<Col className="gutter-row rankbeicenter" span={6}> <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> <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> </Col>
</Row> </Row>
</Col> </Col>
{data.competition_status==="ended"?<style> {data.competition_status === "ended" ? <style>
{ {
` `
.Competitionfontsize22{ .Competitionfontsize22{
@ -318,7 +387,7 @@ class CompetitionCommon extends Component{
} }
` `
} }
</style>:<style> </style> : <style>
{ {
` `
.Competitionfontsize22{ .Competitionfontsize22{
@ -330,27 +399,34 @@ class CompetitionCommon extends Component{
} }
</style>} </style>}
<Col className={"competitionbannerdiv mt20"}> <Col className={"competitionbannerdiv mt20"}>
{data.competition_status==="ended"? {data.competition_status === "ended" ?
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}> <Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
已结束 已结束
</Button>:data.enroll_end===true?<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" ? "未发布" : "报名截止"} {data.competition_status === "nearly_published" ? "未发布" : "报名截止"}
</Button>: </Button> :
data.competition_status==="progressing"?<Button type="primary" block className={"Competitionfontsize22"}> data.competition_status === "progressing" ?
{data.mode===2?<a onClick={()=>this.gotocourse()}>立即报名</a>:<a onClick={()=>this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}></a>} <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>:""} </Button>:""}
</Col> </Col>
<Col className={"mt10 Competitionfontsize16"}>{data&&data.enroll_end_time===null?"":`报名截止时间:${data&&data.enroll_end_time}`}</Col> <Col
className={"mt10 Competitionfontsize16"}>{data && data.enroll_end_time === null ? "" : `报名截止时间:${data && data.enroll_end_time}`}</Col>
</Col> </Col>
</Row> </Row>
</div> </div>
<Layout className={'teamsLayout mt40'}> <Layout className={'teamsLayout mt40'}>
<Sider> <Sider>
<Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]} onClick={(e)=>this.getrightdatas(e)}> <Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]}
{data&&data.competition_modules.map((item,key)=>{ onClick={(e) => this.getrightdatas(e)}>
if(item.module_type!="enroll"){ {data && data.competition_modules.map((item, key) => {
return( if (item.module_type != "enroll") {
return (
<Menu.Item key={item.id}> <Menu.Item key={item.id}>
{/*{item.has_url===false?<span*/} {/*{item.has_url===false?<span*/}
{/*// onClick={()=>this.getrightdata(item.id,item.module_type,item.module_url,item.has_url)}*/} {/*// onClick={()=>this.getrightdata(item.id,item.module_type,item.module_url,item.has_url)}*/}
@ -365,32 +441,44 @@ class CompetitionCommon extends Component{
} }
})} })}
</Menu> </Menu>
{/*<Menu mode="inline" className="CompetitionMenu" onClick={(e)=>this.isdownloadpdf(e)}>*/}
{/*<Menu.Item>*/}
{/*<a>证书下载</a>*/}
{/*</Menu.Item>*/}
{/*</Menu>*/}
</Sider> </Sider>
<Layout className={"teamsLayoutleft CompetitionContents mb30"}> {module_type === "certificate" ? "" : <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
{this.state.module_type==="chart"?Competitionedittype===false?<CompetitionContentsChart {this.state.module_type === "chart" ? Competitionedittype === false ? <CompetitionContentsChart
{...this.props} {...this.props}
{...this.state} {...this.state}
Competitionedit={()=>this.Competitionedit()} Competitionedit={() => this.Competitionedit()}
Competitioncallback={(e)=>this.Competitioncallback(e)} Competitioncallback={(e) => this.Competitioncallback(e)}
/>:"":Competitionedittype===false?<CompetitionContents /> : "" : Competitionedittype === false ? <CompetitionContents
Competitionedit={()=>this.Competitionedit()} Competitionedit={() => this.Competitionedit()}
{...this.props} {...this.props}
{...this.state} {...this.state}
/>:""} /> : ""}
{/*<CompetitionContentsChart*/} {/*<CompetitionContentsChart*/}
{/*{...this.props}*/} {/*{...this.props}*/}
{/*{...this.state}*/} {/*{...this.state}*/}
{/*/>*/} {/*/>*/}
{Competitionedittype===true?<CompetitionContentsMd {Competitionedittype === true ? <CompetitionContentsMd
hideCompetitionedit={()=>this.hideCompetitionedit()} hideCompetitionedit={() => this.hideCompetitionedit()}
getlistdata={(keys,listkey)=>this.getlistdata(keys,listkey)} getlistdata={(keys, listkey) => this.getlistdata(keys, listkey)}
Competitioncallback={(e)=>this.Competitioncallback(e)} Competitioncallback={(e) => this.Competitioncallback(e)}
{...this.props} {...this.props}
{...this.state} {...this.state}
/>:""} /> : ""}
</Layout> </Layout>}
{module_type === "certificate" ? <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
<CompetitionContentspdf
{...this.props}
{...this.state}
/>
</Layout> : ""}
</Layout> </Layout>
</div> </div>

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs} from 'antd'; import {Button, Card, Row, Col ,Upload,Icon,message,Tabs} from 'antd';
import axios from 'axios'; import axios from 'axios';
import {getImageUrl,getUrl,appendFileSizeToUploadFileAll,appendFileSizeToUploadFile} from 'educoder'; import {getImageUrl,getUrl,appendFileSizeToUploadFileAll,appendFileSizeToUploadFile} from 'educoder';
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
const { TabPane } = Tabs; const { TabPane } = Tabs;
class CompetitionContentsMd extends Component{ class CompetitionContentsMd extends Component{
constructor(props) { 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> } </Tooltip> }
{/* toWorkDetailPage */} {/* toWorkDetailPage */}
{/* /courses/"+courseId+"/common_homeworks/"+workId+ '/' + record.id +"/appraise */} {/* /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> </div>

@ -78,6 +78,19 @@ export function RouteHOC(options = {}) {
window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`); 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) => { toNewPage = (courseId) => {
const secondName = this.getModuleName() const secondName = this.getModuleName()
this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`) this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
@ -149,7 +162,6 @@ export function RouteHOC(options = {}) {
} }
render() { render() {
const { snackbarOpen} = this.state; const { snackbarOpen} = this.state;
return ( return (
@ -160,7 +172,7 @@ export function RouteHOC(options = {}) {
toNewPage={this.toNewPage} toNewPage={this.toNewPage}
toListPage={this.toListPage} toListPage={this.toListPage}
toWorkDetailPage={this.toWorkDetailPage} toWorkDetailPage={this.toWorkDetailPage}
toWorkDetailPage2={this.toWorkDetailPage2}
toWorkPostPage={this.toWorkPostPage} toWorkPostPage={this.toWorkPostPage}
toWorkListPage={this.toWorkListPage} toWorkListPage={this.toWorkListPage}
toWorkAnswerPage={this.toWorkAnswerPage} toWorkAnswerPage={this.toWorkAnswerPage}

@ -458,6 +458,7 @@ class Listofworksstudentone extends Component {
: :
<a style={{textAlign: "center"}} <a style={{textAlign: "center"}}
className="color-blue" className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a> onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
} }
@ -810,6 +811,7 @@ class Listofworksstudentone extends Component {
: :
<a style={{textAlign: "center"}} <a style={{textAlign: "center"}}
className="color-blue" className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a> onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
} }
@ -1175,6 +1177,7 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> : record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> :
<span> <span>
<a style={{textAlign: "center"}} className="color-blue" <a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>查看</a> onClick={() => this.Viewstudenttraininginformationt(record)}>查看</a>
</span> </span>
) )
@ -1505,6 +1508,7 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> : record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> :
<span> <span>
<a style={{textAlign: "center"}} className="color-blue" <a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a> onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a>
</span> </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) => { Viewstudenttraininginformationt = (e) => {
// console.log("Viewstudenttraininginformation"); // console.log("Viewstudenttraininginformation");

@ -160,44 +160,18 @@ class Statistics extends Component{
derivefun=(url)=>{ derivefun=(url)=>{
let{group_ids}=this.state; let{group_ids}=this.state;
let data={ let list=group_ids;
group_id:group_ids let urllist="";
} if(list!=undefined&&list.length!=0)
axios.get(url,{params: list.map((item,key)=>{
data, if(key===0){
paramsSerializer: function(params) { urllist=`group_id[]=${item}`
return qs.stringify(params, {arrayFormat: 'brackets'}) }else{
} urllist=urllist+`&group_id[]=${item}`
}).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) })
}); this.props.slowDownload(`${url}?${urllist}`);
} }

@ -147,7 +147,9 @@ class ShixunsHome extends Component {
nextArrow={<CustomNextArrow />} nextArrow={<CustomNextArrow />}
prevArrow={<CustomPrevArrow />} prevArrow={<CustomPrevArrow />}
autoplay autoplay
autoplaySpeed={4500}
animation={false} animation={false}
pauseOnHover={true}
style={{width:"100%"}} style={{width:"100%"}}
arrowPos="outer"> arrowPos="outer">
{homedatalist.images_url.map((item, index) => ( {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 TPIContextProvider
tpi主要的state容器主要接口`/tasks/${stageId}.json`一次性获取所有tpi首屏展示所需要的信息除了代码内容。 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}` `/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 axios from 'axios';
import TPMRightSection from "../../tpm/component/TPMRightSection"; import TPMRightSection from "../../tpm/component/TPMRightSection";
import styled from "styled-components"; import styled from "styled-components";
import Modifytext from './Modifytext';
const getItemStyle = (isDragging, draggableStyle) => ({ const getItemStyle = (isDragging, draggableStyle) => ({
// change background colour if dragging // change background colour if dragging
background: isDragging ? '#dceeff' : '', background: isDragging ? '#dceeff' : '',
@ -87,7 +87,9 @@ class PathDetailIndex extends Component{
dataquerys:{}, dataquerys:{},
MenuItemsindex:1, MenuItemsindex:1,
MenuItemsindextype:0, MenuItemsindextype:0,
qrcode_img:null qrcode_img: null,
team_title: "教学团队",
modify: false,
} }
this.onDragEnd = this.onDragEnd.bind(this); this.onDragEnd = this.onDragEnd.bind(this);
@ -256,6 +258,7 @@ class PathDetailIndex extends Component{
progress:result.data.progress, progress:result.data.progress,
members:result.data.members, members:result.data.members,
items: getItems(result.data.members.length), items: getItems(result.data.members.length),
team_title: result.data.team_title
}) })
}).catch((error)=>{ }).catch((error)=>{
@ -321,6 +324,7 @@ class PathDetailIndex extends Component{
progress:result.data.progress, progress:result.data.progress,
members:result.data.members, members:result.data.members,
items: getItems(result.data.members.length), items: getItems(result.data.members.length),
team_title: result.data.team_title
}) })
}).catch((error)=>{ }).catch((error)=>{
@ -458,6 +462,50 @@ class PathDetailIndex extends Component{
console.log(error) 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(){ render(){
this.updatamakedown("shixuns_propaedeutics"); this.updatamakedown("shixuns_propaedeutics");
@ -475,7 +523,9 @@ class PathDetailIndex extends Component{
tags, tags,
qrcode_img, qrcode_img,
MenuItemsindex, MenuItemsindex,
MenuItemsindextype MenuItemsindextype,
team_title,
modify
} = this.state } = this.state
@ -540,7 +590,7 @@ class PathDetailIndex extends Component{
</div> </div>
<div className="with35 fr pl20"> <div className="with35 fr pl20">
{qrcode_img===null?"":<div className="edu-back-white newmustlearn mb10"> {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 className="font-16 color181818">优惠报名扫码入群</div>
</div>} </div>}
<div className="edu-back-white mustlearn mb10"> <div className="edu-back-white mustlearn mb10">
@ -613,7 +663,19 @@ class PathDetailIndex extends Component{
{ {
members ===undefined ?"":members === null ?"": members ===undefined ?"":members === null ?"":
<div className="teacherTeam edu-back-white clearfix" id="subject_members"> <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===undefined?
members && members.map((item,key)=>{ members && members.map((item,key)=>{

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

@ -28,6 +28,8 @@ const Option = Select.Option;
const RadioGroup = Radio.Group; const RadioGroup = Radio.Group;
const { TextArea } = Input;
function create_editorMD(id, width, high, placeholder, imageUrl, callback) { function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
var editorName = window.editormd(id, { var editorName = window.editormd(id, {
width: width, width: width,
@ -1155,19 +1157,22 @@ export default class TPMevaluation extends Component {
</a> </a>
</Tooltip> </Tooltip>
</p> </p>
<textarea className="textareavalue mb15" name="test_set[input][]" <TextArea className="textareavalue mb15" name="test_set[input][]"
placeholder="输入" placeholder="输入"
value={item.input} value={item.input}
id={"textareavalue"+key} id={"textareavalue"+key}
autoHeight="true"
autoSize={{ minRows: 3, maxRows: 5 }}
onInput={(e)=>this.evaluationoninputvalue(e,key,"sr")} onInput={(e)=>this.evaluationoninputvalue(e,key,"sr")}
></textarea> ></TextArea>
<textarea className="textareavalue" name="test_set[output][]" <TextArea className="textareavalue" name="test_set[output][]"
placeholder="预期输出" placeholder="预期输出"
value={item.output} value={item.output}
id={key+"textareavalue"} id={key+"textareavalue"}
autoHeight="true" autoHeight="true"
autoSize={{ minRows: 3, maxRows: 5 }}
onInput={(e)=>this.evaluationoninputvalue(e,key,"yq")} onInput={(e)=>this.evaluationoninputvalue(e,key,"yq")}
></textarea> ></TextArea>
<div className="clearfix lineh-30"> <div className="clearfix lineh-30">
<span className="fl mr10 color-grey-6">匹配规则</span> <span className="fl mr10 color-grey-6">匹配规则</span>
<RadioGroup className="fl" value={item.match_rule} onChange={(e)=>this.changeEvaluationRule(e,key)}> <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 { Form, Button, Input, Radio, Select, Tooltip, Icon, AutoComplete } from 'antd'
import ApplyForAddOrgModal from '../modal/ApplyForAddOrgModal' import ApplyForAddOrgModal from '../modal/ApplyForAddOrgModal'
import ApplyForAddChildOrgModal from '../modal/ApplyForAddChildOrgModal' import ApplyForAddChildOrgModal from '../modal/ApplyForAddChildOrgModal'
import AccountBasicEditItem from './AccountBasicEditItem';
import axios from 'axios' import axios from 'axios'
import { identityMap } from './AccountBasic' import { identityMap } from './AccountBasic'
const RadioGroup = Radio.Group; const RadioGroup = Radio.Group;
@ -282,7 +283,9 @@ class AccountBasic extends Component {
getDepartments=(e,flag)=>{ getDepartments=(e,flag)=>{
let arr=this.state.schoolList.filter(function(item){ 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 (!arr[0]) {
if (!e) { 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) => { addOrgSuccess = (name) => {
// const schoolList = this.state.schoolList.slice(0) // const schoolList = this.state.schoolList.slice(0)
@ -407,6 +397,19 @@ class AccountBasic extends Component {
} }
callback(`请输入真实姓名,最大限制${MAX_NAME_LENGTH}个字符`); 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() { render() {
let{ let{
@ -422,10 +425,17 @@ class AccountBasic extends Component {
}=this.state; }=this.state;
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
let{ basicInfo }=this.props let{ basicInfo }=this.props
let common = {
// 已职业认证的账户不能修改职业,学校/单位,院系/部门产品还未确定先默认为false--可以更改 changeJob:this.changeJob,
// basicInfo && basicInfo.professional_certification == "certified" filterList:this.filterList,
const professionalFlag = false; 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合并了 // form合并了
const propsWithoutForm = Object.assign({}, this.props) const propsWithoutForm = Object.assign({}, this.props)
@ -599,177 +609,22 @@ class AccountBasic extends Component {
<City></City> <City></City>
)} )}
</Form.Item> </Form.Item>
<div className="clearfix"> <AccountBasicEditItem
<Form.Item identity={identity}
label="职业" getFieldDecorator = {getFieldDecorator}
className="formItemInline fl" professionalFlag = {professionalFlag}
> basicInfo = {basicInfo}
{getFieldDecorator('job', { {...this.props}
rules: [{ {...this.state}
initialValue:"teacher", {...common}
required: true, form={this.props.form}
message: '请先选择职业', filterSchoolList={filterSchoolList}
}], filterDepartments={filterDepartments}
})( departmentsName={departmentsName}
<Select style={{width:"190px",marginRight:"20px"}} onChange={this.changeJob} disabled={professionalFlag}> school={school}
<Option value="teacher">教师</Option> department_id={this.state.department_id}
<Option value="student">学生</Option> departments={departments}
<Option value="professional">专业人士</Option> ></AccountBasicEditItem>
</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>
}
{/* htmlType="submit" */} {/* htmlType="submit" */}
{/* <Form.Item> {/* <Form.Item>
<div className="clearfix mt30 mb30"> */} <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 } {...this.props }
onOk={this.onOk} onOk={this.onOk}
okText="保存" okText="保存"
className="applyForModal courseNormalForm" className="applyForModal courseNormalForm styleForapply"
> >
<style>{` <style>{`
.applyForModal .ant-form-item-label { .applyForModal .ant-form-item-label {
@ -86,7 +86,7 @@ class ApplyForAddChildOrgModal extends Component{
.applyForModal .ant-form-item-label label { .applyForModal .ant-form-item-label label {
color: #979797 color: #979797
} }
.applyForModal .formItemInline .ant-form-item-control-wrapper { .styleForapply .formItemInline .ant-form-item-control-wrapper {
width: 390px; width: 390px;
} }
`}</style> `}</style>

@ -1,15 +1,19 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { message, Icon, Input, Form, Upload} from "antd"; import { message, Icon, Input, Form, Upload,Radio ,Tooltip} from "antd";
import axios from 'axios' import axios from 'axios'
import ModalWrapper from "../../courses/common/ModalWrapper" import ModalWrapper from "../../courses/common/ModalWrapper"
import { City, getUploadActionUrl, getImageUrl, ImageLayer2, getUploadActionUrlOfAuth } from 'educoder' import { City, getUploadActionUrl, getImageUrl, ImageLayer2, getUploadActionUrlOfAuth ,ConditionToolTip } from 'educoder'
import '../account/common.css' import '../account/common.css'
import AccountBasicEditItem from '../account/AccountBasicEditItem'
import ApplyForAddOrgModal from './ApplyForAddOrgModal'
import ApplyForAddChildOrgModal from './ApplyForAddChildOrgModal'
import authImg from '../../../images/account/auth.png' import authImg from '../../../images/account/auth.png'
import jobImg from '../../../images/account/job.png' import jobImg from '../../../images/account/job.png'
const { TextArea } = Input; const RadioGroup = Radio.Group;
const Dragger = Upload.Dragger; const Dragger = Upload.Dragger;
const MAX_NAME_LENGTH = 10
function getBase64(img, callback) { function getBase64(img, callback) {
const reader = new FileReader(); const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result)); reader.addEventListener('load', () => callback(reader.result));
@ -26,16 +30,232 @@ function beforeUpload(file) {
} }
return isJPG && isLt2M; return isJPG && isLt2M;
} }
export function getHiddenName(name) {
if (!name) return ''
let len=parseInt(name.length)-1;
let str="";
for(var i = 0; i < len; i++){ str += "*"; }
const newName = name.substr(0,1)+str;
return newName
}
class RealNameCertificationModal extends Component{ class RealNameCertificationModal extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
identity:"teacher",
departmentsName:undefined,
filterSchoolList:undefined,
filterDepartments :undefined,
school:undefined,
school_id:undefined,
department_id:undefined,
schoolList:undefined,
departments:undefined,
showRealName:true,
} }
} }
componentDidMount() { componentDidMount() {
console.log("RealNameCertificationModal");
console.log(this.props.basicInfo);
if(this.props.basicInfo){
this.setValue(this.props.basicInfo);
this.getSchoolList(this.props.basicInfo);
}
}
setValue=(basicInfo)=>{
if(basicInfo){
this.props.form.setFieldsValue({
nickname:basicInfo.nickname,
name:!basicInfo.show_realname ? this.hideRealName(basicInfo.name) : basicInfo.name,
sex:String(basicInfo.gender),
job:basicInfo.identity,
org:basicInfo.school_name,
// city:[basicInfo.location,basicInfo.location_city]
})
setTimeout(() => {
// 等显示后再set
this.props.form.setFieldsValue({
job:basicInfo.identity,
student_No:basicInfo.student_id,
org2:basicInfo.department_name,
job1:basicInfo && basicInfo.identity=="teacher" ? basicInfo.technical_title:"教授",
job2:basicInfo && basicInfo.identity=="professional" ? basicInfo.technical_title:"企业管理者",
})
}, 100)
//if(basicInfo.nickname){
this.setState({
forDisable: true,
nameLength:basicInfo.nickname?basicInfo.nickname.length:0,
showRealName:basicInfo.show_realname,
realName: basicInfo.name,
identity:basicInfo.identity,
school_id:basicInfo.school_id,
department_id:basicInfo.department_id
})
//}
}
}
getSchoolList=(basicInfo, selectedName)=>{
let url=`/schools/for_option.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
schoolList:result.data.schools
})
if (selectedName) {
let school_id
result.data.schools.reverse().some( item => {
if (item.name == selectedName) {
school_id = item.id
return true;
}
})
this.props.form.setFieldsValue({
org: selectedName
})
this.setState({
school_id,
school: selectedName
}, () => {
this.filterList(selectedName)
})
} else if(basicInfo && basicInfo.school_name){
this.setState({
school:basicInfo.school_name,
filterSchoolList:this.state.schoolList.filter(function(item){
return item.name.indexOf(basicInfo.school_name)>-1;
})
})
this.getDepartments(basicInfo.school_name,false);
} }
}
}).catch((error)=>{
console.log(error);
})
}
// 将名字隐藏起来
hideRealName=(name)=>{
this.setState({ realName: name })
const newName = getHiddenName(name)
this.props.form.setFieldsValue({
name: newName
})
return newName
}
getDepartments=(e,flag)=>{
let arr=this.state.schoolList.filter(function(item){
if(item.name.indexOf(e) > -1){
return item.name;
}
});
if (!arr[0]) {
if (!e) {
this.setState({
filterSchoolList: []
})
}
// 没找到学校,清空部门
this.setState({
departments: [],
filterDepartments: [],
departmentsName: '',
school_id: '',
department_id: '',
})
this.this_school_id = ''
this.props.form.setFieldsValue({
org2: ''
})
return;
}
this.props.form.setFieldsValue({
org: arr[0].name
})
this.filterList(e)
// 保存选择的学校id
this.this_school_id = arr[0].id
this.setState({
school_id: arr[0].id,
school:e,
})
this._getDepartments(arr[0].id, flag)
}
_getDepartments = (schoolId, flag, selectedName) => {
let url=`/schools/${schoolId || this.state.school_id}/departments/for_option.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
departments:result.data.departments,
filterDepartments:result.data.departments
})
if (selectedName) {
let department_id
result.data.departments.reverse().some( item => {
if (item.name == selectedName) {
department_id = item.id
return true;
}
})
this.props.form.setFieldsValue({
org2: selectedName
})
this.setState({
department_id,
// school: selectedName
})
} else if(result.data.departments && result.data.departments.length>0 && flag==true){
// 切换学校后,部门默认选择第一个
this.props.form.setFieldsValue({
org2:result.data.departments[0].name
})
this.setState({
department_id: result.data.departments[0].id
})
}else if(result.data.departments && result.data.departments.length == 0 && flag==true){
this.props.form.setFieldsValue({
org2:''
})
}
}
}).catch((error)=>{
console.log(error);
})
}
filterList =(e)=>{
const inputVal = e.trim()
let arr=[];
if(inputVal){
arr= this.state.schoolList.filter(function(item){
return item.name.indexOf(inputVal)>-1;
});
this.props.form.setFieldsValue({
org: inputVal
})
this.setState({
school: inputVal,
filterSchoolList: arr
})
} else {
this.setState({
school: '',
})
}
// else{
// let {school}=this.state;
// arr= this.state.schoolList.filter(function(item){
// return item.name.indexOf(school)>-1;
// });
// }
}
setVisible = (visible) => { setVisible = (visible) => {
this.refs.modalWrapper.setVisible(visible) this.refs.modalWrapper.setVisible(visible)
} }
@ -43,6 +263,7 @@ class RealNameCertificationModal extends Component{
onSendOk = () => { onSendOk = () => {
this.props.form.validateFieldsAndScroll((err, values) => { this.props.form.validateFieldsAndScroll((err, values) => {
console.log(values); console.log(values);
console.log(this.state.department_id);
if(!err){ if(!err){
let{imageUrl2}=this.state; let{imageUrl2}=this.state;
let{current_user,basicInfo}=this.props; let{current_user,basicInfo}=this.props;
@ -52,30 +273,52 @@ class RealNameCertificationModal extends Component{
// 实名认证 // 实名认证
let url = `/users/accounts/${current_user && current_user.login}/authentication_apply.json` let url = `/users/accounts/${current_user && current_user.login}/authentication_apply.json`
axios.post((url),{ axios.post((url),{
name:basicInfo.name, name:values.name,
gender:parseInt(values.sex),
id_number:values.credentials id_number:values.credentials
}).then((result)=>{ }).then((result)=>{
if(result){ if(result){
this.props.showNotification("申请已提交,请等待审核!"); this.props.showNotification("申请已提交,请等待审核!");
try {
this.props.getBasicInfo(); this.props.getBasicInfo();
} catch (e) {
}
try {
this.props.Getdata();
} catch (e) {
}
this.setVisible(false); this.setVisible(false);
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
}) })
}else{ }else{
// 职业认证 // 职业认证
// console.log(values.job == "student" ? values.student_No : values.job == "teacher" ? values.job1 : values.job2);
let url = `/users/accounts/${current_user && current_user.login}/professional_auth_apply.json` let url = `/users/accounts/${current_user && current_user.login}/professional_auth_apply.json`
axios.post((url),{ axios.post((url),{
school_id:basicInfo && basicInfo.school_id, school_id:this.state.school_id,
department_id:basicInfo && basicInfo.department_id, department_id:this.state.department_id,
identity:basicInfo && basicInfo.identity, identity:this.state.identity,
extra:basicInfo && basicInfo.identity == "student" ? basicInfo.student_id:basicInfo.technical_title extra: values.job == "student" ? values.student_No : values.job == "teacher" ? values.job1 : values.job2
}).then((result)=>{ }).then((result)=>{
if(result){ if(result){
this.props.showNotification("申请已提交,请等待审核!"); this.props.showNotification("申请已提交,请等待审核!");
try {
this.props.getBasicInfo(); this.props.getBasicInfo();
} catch (e) {
}
try {
this.props.Getdata();
} catch (e) {
}
this.setVisible(false); this.setVisible(false);
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
@ -119,16 +362,123 @@ class RealNameCertificationModal 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:"企业管理者",
})
}
}
// 选择学校(获取对应学校的学院、部门)
changeList=(e)=>{
this.getDepartments(e.trim(),true);
}
showApplyForAddOrgModal = () => {
this.applyForAddOrgForm.setVisible(true)
}
showApplyForAddChildOrgModal = () => {
let{school,schoolList}=this.state;
let arr=schoolList.filter(function(item){
return item.name == school;
});
if(arr.length > 0){
this.applyForAddChildOrgForm.setVisible(true)
}else{
this.props.showNotification("请先选择正确的单位或者学校!");
}
}
addOrgSuccess = (name) => {
// const schoolList = this.state.schoolList.slice(0)
// schoolList.push({ id: schoolList.length + 2000, name: name})
// this.setState({ schoolList })
this.getSchoolList(this.props.basicInfo, name);
this.props.form.setFieldsValue({
org: name
})
}
addChildOrgSuccess = (deptName) => {
this._getDepartments(this.state.school_id, false, deptName);
}
// 隐藏或显示真实姓名
showOrHide=(flag)=>{
const name = this.props.form.getFieldsValue().name || this.props.basicInfo.name
this.setState({
showRealName:flag==true?false:true
})
if(flag==true){ // 隐藏真实姓名
this.hideRealName(name);
}else{ // 显示
this.props.form.setFieldsValue({
name: this.state.realName
})
}
}
// 选择部门、学院
changeDepartment=(e)=>{
let arr = this.state.departments && this.state.departments.filter ? this.state.departments.filter(function(item){
return item.name == e;
}) : [];
if (!arr[0]) {
this.setState({
department_id: '',
departmentsName: e,
filterDepartments: [],
})
this.this_department_id = ''
return;
}
this.this_department_id = arr[0].id
this.setState({
departmentsName:e,
department_id: arr[0].id,
})
}
render(){ render(){
const { course_lists, checkBoxValues, searchValue, loading, imageUrl, imageUrl2 } = this.state const { course_lists, checkBoxValues, searchValue, loading, imageUrl, imageUrl2,
identity,
departmentsName ,
filterSchoolList ,
filterDepartments ,
school,
department_id,
departments,
school_id,
showRealName
} = this.state
const { moduleName } = this.props const { moduleName } = this.props
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
let {certification}=this.props; let {certification}=this.props;
// /api/users/accounts/${this.props.current_user.login}/auth_attachment.json // /api/users/accounts/${this.props.current_user.login}/auth_attachment.json
// 已职业认证的账户不能修改职业,学校/单位,院系/部门true为disable
const professionalFlag = basicInfo && basicInfo.professional_certification == "certified" ;
let{ basicInfo }=this.props
let common={
changeJob:this.changeJob,
filterList:this.filterList,
changeList:this.changeList,
changeDepartment:this.changeDepartment,
showApplyForAddOrgModal:this.showApplyForAddOrgModal,
showApplyForAddChildOrgModal:this.showApplyForAddChildOrgModal
}
const uploadProps2 = { const uploadProps2 = {
name: 'image', name: 'image',
data:{type:certification == 1 ? "real_name" : "professional"}, data: {type: certification == 1 ? "real_name" : "professional"},
multiple: true, multiple: true,
showUploadList: false, showUploadList: false,
// https://newweb.educoder.net // https://newweb.educoder.net
@ -136,18 +486,33 @@ class RealNameCertificationModal extends Component{
className: 'idPic-uploader', className: 'idPic-uploader',
onChange: this.handleChange2, onChange: this.handleChange2,
}; };
// form合并了
const propsWithoutForm = Object.assign({}, this.props)
delete propsWithoutForm.form
return( return(
<div>
<ApplyForAddOrgModal ref="applyForAddOrgModal" wrappedComponentRef={(form) => this.applyForAddOrgForm = form} schoolName={school}
{...propsWithoutForm} addOrgSuccess={this.addOrgSuccess}
></ApplyForAddOrgModal>
<ApplyForAddChildOrgModal ref="applyForAddChildOrgModal" schoolName={school} schoolId={school_id} departmentName={departmentsName}
{...propsWithoutForm}
wrappedComponentRef={(form) => this.applyForAddChildOrgForm = form}
addChildOrgSuccess={this.addChildOrgSuccess}
></ApplyForAddChildOrgModal>
<ModalWrapper <ModalWrapper
ref="modalWrapper" ref="modalWrapper"
title={ title={
certification && certification==1? certification && certification == 1 ?
<span><i className="iconfont icon-shenfenrenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span>: <span><i className="iconfont icon-shenfenrenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span>:
<span><i className="iconfont icon-zhiyerenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span> <span><i className="iconfont icon-zhiyerenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span>
} }
{...this.props } {...this.props }
{...this.state}
onOk={this.onOk} onOk={this.onOk}
okText="保存" okText="保存"
className="applyForModal certificationModal courseNormalForm" className="applyForModal certificationModal courseNormalForm"
width="660px"
bottomRender={ bottomRender={
certification && certification == 1? certification && certification == 1?
<div className="bottomRender"> <div className="bottomRender">
@ -202,9 +567,9 @@ class RealNameCertificationModal extends Component{
.certificationModal .ant-modal-body{ .certificationModal .ant-modal-body{
padding:20px; padding:20px;
} }
.certificationModal .formItemInline .ant-form-item-control-wrapper { // .certificationModal .formItemInline .ant-form-item-control-wrapper {
width: 448px; // width: 448px;
} // }
span.idPic-uploader { span.idPic-uploader {
margin-right:20px; margin-right:20px;
height:110px; height:110px;
@ -255,16 +620,77 @@ class RealNameCertificationModal extends Component{
align-items: center; align-items: center;
display: -webkit-flex; display: -webkit-flex;
} }
.formItemInline.ant-form-item {
display: -ms-flexbox;
display: flex;
}
.formItemInline {
display: flex;
margin-bottom: 10px;
position: relative;
}
.formItemInline .ant-form-explain{ .formItemInline .ant-form-explain{
position:absolute; position:absolute;
bottom:-20px; bottom:-20px;
left:0px; left:0px;
width:100%; width:100%;
} }
.yslgraduainputedit{
width:295px;
}
`}</style> `}</style>
<Form onSubmit={this.handleSubmit}> <Form onSubmit={this.handleSubmit}>
{ {certification && certification == 1 ?
certification && certification ==1 && <div>
<Form.Item
label="姓名"
className="formItemInline"
>
{basicInfo && basicInfo.authentication == 'uncertified' ? <React.Fragment>{getFieldDecorator('name', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: `请输入真实姓名,最大限制${MAX_NAME_LENGTH}个字符`,
validator: this.checkNameLength
}],
})(
<Input placeholder={`请输入真实姓名,最大限制${MAX_NAME_LENGTH}个字符`} className="yslgraduainputedit" disabled={!showRealName && this.state.forDisable == true } addonAfter={
<i className={showRealName?"iconfont icon-xianshi font-18 color-blue":"iconfont icon-yincang font-18 color-blue"}
onClick={()=>this.showOrHide(showRealName)}></i>
}></Input>
)}
<span>{ showRealName ? '(显示:平台将显示您的真实姓名)' : '(隐藏:平台将显示你的昵称)' }</span>
</React.Fragment> :
<div className="df" style={{}}>
<Tooltip title="已完成实名认证,不能修改">
<span className="mr8" >{showRealName ? this.props.basicInfo.name : getHiddenName(this.props.basicInfo.name)}</span>
</Tooltip>
<i className={showRealName?"iconfont icon-xianshi font-18 color-blue":"iconfont icon-yincang font-18 color-blue"}
onClick={()=>this.showOrHide(showRealName)}></i>
<span>{ showRealName ? '(显示:平台将显示您的真实姓名)' : '(隐藏:平台将显示你的昵称)' }</span>
</div>
}
</Form.Item>
<Form.Item
label="性别"
className="formItemInline resetSexStyle"
>
{getFieldDecorator('sex', {
rules: [{
required: true,
message: '请选择性别',
}],
})(
<RadioGroup>
<ConditionToolTip title="已完成实名认证,不能修改" condition={basicInfo.authentication != 'uncertified'} >
<Radio value="0" disabled={basicInfo.authentication != 'uncertified'}></Radio>
<Radio value="1" disabled={basicInfo.authentication != 'uncertified'}></Radio>
</ConditionToolTip>
</RadioGroup>
)}
</Form.Item>
<Form.Item <Form.Item
label="证件号:" label="证件号:"
className="formItemInline" className="formItemInline"
@ -279,14 +705,29 @@ class RealNameCertificationModal extends Component{
<Input placeholder="请输入证件号" ></Input> <Input placeholder="请输入证件号" ></Input>
)} )}
</Form.Item> </Form.Item>
}
<div style={{ marginLeft: '18px' }}>
<div>
<span style={{color: '#999999'}}>{ certification && certification == 1 ? "身份证(人像面)上传":"职业证照片上传" }</span>
<span style={{color: '#FF6800'}}>png/jpg/bmp格式不超过2MB</span>
</div> </div>
:
<div className="df mt20" style={{ justifyContent: 'center' }} > <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={department_id}
departments={departments}
></AccountBasicEditItem>
}
<div className="mt15" style={{ marginLeft: '18px' }}>
<div className="df">
<span style={{color: '#999999'}}>{ certification && certification == 1 ? "身份证上传:":"职业证上传:" }</span>
<div className="df ml10" style={{ justifyContent: 'center' }} >
<span className="idPic-uploader demoImg"> <span className="idPic-uploader demoImg">
<img src={`${certification == 1 ? authImg : jobImg}`} alt="avatar" style={{ maxHeight: '110px'}}/> <img src={`${certification == 1 ? authImg : jobImg}`} alt="avatar" style={{ maxHeight: '110px'}}/>
</span> </span>
@ -305,21 +746,25 @@ class RealNameCertificationModal extends Component{
} }
</Dragger> </Dragger>
</div> </div>
<div className="df mt10 color-grey-9" style={{ justifyContent: 'center' }} > </div>
<span className="fl mr20 edu-txt-center" style={{width:"160px"}}>示例图片</span> <div className="df mt10 color-grey-9">
<span className="fl edu-txt-center mr20" style={{width:"160px"}}> <span className="fl edu-txt-center" style={{width:"200px",marginLeft:"65px"}}>
<p>示例图片</p>
<p className="font-12" style={{color: '#FF6800'}}>png/jpg/bmp格式不超过2MB</p>
</span>
<span className="fl edu-txt-center" style={{width:"160px"}}>
<ImageLayer2 parentSel={'#imageLayerBtn'} parentSel={'#imageLayerBtn'} <ImageLayer2 parentSel={'#imageLayerBtn'} parentSel={'#imageLayerBtn'}
></ImageLayer2> ></ImageLayer2>
<a href="javascript:void(0)" id="imageLayerBtn" src={imageUrl || imageUrl2} className="color-orange" style={{borderBottom:"1px solid #ff6800"}}>查看大图</a> <a href="javascript:void(0)" id="imageLayerBtn" src={imageUrl || imageUrl2} className="color-orange" style={{borderBottom:"1px solid #ff6800"}}>查看大图</a>
</span> </span>
</div> </div>
</div> </div>
</Form> </Form>
</ModalWrapper> </ModalWrapper>
</div>
) )
} }
} }

@ -280,21 +280,21 @@ class Infos extends Component{
} }
></Route> ></Route>
{/* 实训 */} {/* 实训项目 */}
<Route exact path="/users/:username/shixuns" <Route exact path="/users/:username/shixuns"
render={ render={
(props) => (<InfosShixun {...this.props} {...props} {...this.state} {..._commonProps}/>) (props) => (<InfosShixun {...this.props} {...props} {...this.state} {..._commonProps}/>)
} }
></Route> ></Route>
{/* 实训课程 */} {/* 实践课程 */}
<Route exact path="/users/:username/paths" <Route exact path="/users/:username/paths"
render={ render={
(props) => (<InfosPath {...this.props} {...props} {...this.state} {..._commonProps}/>) (props) => (<InfosPath {...this.props} {...props} {...this.state} {..._commonProps}/>)
} }
></Route> ></Route>
{/* 项目 */} {/* 开发项目 */}
<Route exact path="/users/:username/projects" <Route exact path="/users/:username/projects"
render={ render={
(props) => (<InfosProject {...this.props} {...props} {...this.state} {..._commonProps}/>) (props) => (<InfosProject {...this.props} {...props} {...this.state} {..._commonProps}/>)
@ -317,7 +317,6 @@ class Infos extends Component{
></Route> ></Route>
<Route exact path="/users/:username" <Route exact path="/users/:username"
render={ render={
(props) => (<InfosCourse {...this.props} {...props} {...this.state} {..._commonProps}/>) (props) => (<InfosCourse {...this.props} {...props} {...this.state} {..._commonProps}/>)

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder'; import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; 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 Loadable from 'react-loadable';
import Loading from '../../../Loading'; import Loading from '../../../Loading';
import axios from 'axios'; import axios from 'axios';
@ -20,7 +20,8 @@ class InfosCourse extends Component{
status:undefined, status:undefined,
page:1, page:1,
per_page:16, per_page:16,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined, totalCount:undefined,
data:undefined, data:undefined,
isSpin:false isSpin:false
@ -31,27 +32,35 @@ class InfosCourse extends Component{
this.setState({ this.setState({
isSpin:true isSpin:true
}) })
let{category,status,page}=this.state; let {category, status, page, sort_by, sort_direction} = this.state;
this.getCourses(category,status,page); 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`; let url=`/users/${this.props.match.params.username}/courses.json`;
axios.get((url),{params:{ axios.get((url),{params:{
category, category,
status, status,
page, page,
sort_by,
sort_direction,
per_page: this.props.is_current && category && page ==1?17:16 per_page: this.props.is_current && category && page ==1?17:16
}}).then((result)=>{ }}).then((result)=>{
if(result){ if(result){
console.log("请求成功");
this.setState({ this.setState({
totalCount:result.data.count, totalCount:result.data.count,
data:result.data, data:result.data,
sort_direction: sort_direction,
sort_by: sort_by,
isSpin:false isSpin:false
}) })
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
this.setState({
isSpin: false
})
}) })
} }
@ -62,8 +71,8 @@ class InfosCourse extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{status}=this.state; let {status, sort_by, sort_direction} = this.state;
this.getCourses(cate,status,1); this.getCourses(cate, status, 1, sort_by, sort_direction);
} }
//切换状态 //切换状态
changeStatus=(status)=>{ changeStatus=(status)=>{
@ -72,8 +81,8 @@ class InfosCourse extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{category}=this.state; let {category, sort_by, sort_direction} = this.state;
this.getCourses(category,status,1); this.getCourses(category, status, 1, sort_by, sort_direction);
} }
//切换页数 //切换页数
changePage=(page)=>{ changePage=(page)=>{
@ -81,8 +90,8 @@ class InfosCourse extends Component{
page, page,
isSpin:true isSpin:true
}) })
let{category,status}=this.state; let {category, status, sort_by, sort_direction} = this.state;
this.getCourses(category,status,page); 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(){ render(){
let{ let{
category, category,
@ -99,31 +141,167 @@ class InfosCourse extends Component{
page, page,
data, data,
totalCount, totalCount,
isSpin isSpin,
sort_by,
sort_direction
} = this.state; } = this.state;
let is_current=this.props.is_current; let is_current=this.props.is_current;
// console.log(this.props.current_user&&this.props.current_user.user_identity==="学生") // 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( return(
<div className="educontent"> <div className="educontent">
<Spin size="large" spinning={isSpin}> <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 "> <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 ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li> href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</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> </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 && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="processing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("processing")}>正在进行</a></li> onClick={() => this.changeStatus()}
<li className={status=="end" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("end")}>已结束</a></li> 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> </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="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> </p>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix"> <div className="square-list clearfix">
{/* 289 */} {/* 289 */}
{ {

@ -168,23 +168,82 @@ class InfosPackage extends Component{
modalSave={this.state.ModalSave} modalSave={this.state.ModalSave}
/> />
<Spin size="large" spinning={isSpin}> <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 "> <div className="white-panel edu-back-white pt20 pb20 clearfix ">
<li className={category ? "" : "active"}><a onClick={()=>this.changeCategory()}>全部</a></li> <li className={category ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
<li className={category=="manage" ? "active" : ""}><a onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li> href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category=="bidden" ? "active" : ""}><a onClick={()=>this.changeCategory("bidden")}>{is_current ? "我":"TA"}参与的</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> </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"? category=="manage"?
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a
<li className={status=="unpublished" ? "active" : ""}><a onClick={()=>this.changeStatus("unpublished")}>未发布</a></li> onClick={() => this.changeStatus()} className="w32">全部</a></li>
<li className={status=="bidding" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding")}>竞标中</a></li> <li className={status == "unpublished " ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
<li className={status=="finished" ? "active" : ""}><a onClick={()=>this.changeStatus("finished")}>已完成</a></li> 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>: category=="bidden"?
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a
<li className={status=="bidding_lost" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding_lost")}>未中标</a></li> onClick={() => this.changeStatus()} className="w32">全部</a></li>
<li className={status=="bidding_won" ? "active" : ""}><a onClick={()=>this.changeStatus("bidding_won")}>已中标</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>:"" </div>:""
} }
<p className="pl25 pr25 clearfix font-12 mb20 mt20"> <p className="pl25 pr25 clearfix font-12 mb20 mt20">

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder'; import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; 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 Loadable from 'react-loadable';
import Loading from '../../../Loading'; import Loading from '../../../Loading';
import NoneData from '../../courses/coursesPublic/NoneData' import NoneData from '../../courses/coursesPublic/NoneData'
@ -19,11 +19,11 @@ class InfosPath extends Component{
this.state={ this.state={
category:undefined, category:undefined,
page:1, page:1,
sort_by:'time',
status:undefined, status:undefined,
per_page:16, per_page:16,
isSpin:false, isSpin:false,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined, totalCount:undefined,
data:undefined data:undefined
} }
@ -33,28 +33,34 @@ class InfosPath extends Component{
this.setState({ this.setState({
isSpin:true isSpin:true
}) })
let{category,status,sort_by,page,per_page}=this.state; let {category, status, sort_by, page, per_page, sort_direction} = this.state;
this.getCourses(category,status,sort_by,page,per_page); 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`; let url=`/users/${this.props.match.params.username}/subjects.json`;
axios.get((url),{params:{ axios.get((url),{params:{
category, category,
status, status,
sort_by, sort_by,
page, page,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16 per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{ }}).then((result)=>{
if(result){ if(result){
this.setState({ this.setState({
totalCount:result.data.count, totalCount:result.data.count,
data:result.data, data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false isSpin:false
}) })
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
this.setState({
isSpin: false
})
}) })
} }
@ -66,18 +72,18 @@ class InfosPath extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{sort_by}=this.state; let {sort_by, sort_direction} = this.state;
this.getCourses(cate,undefined,sort_by,1); this.getCourses(cate, undefined, sort_by, 1, sort_direction);
} }
// 切换状态 // 切换状态
changeStatus=(status)=>{ changeStatus=(status)=>{
let{category,sort_by}=this.state; let {category, sort_by, sort_direction} = this.state;
this.setState({ this.setState({
status, status,
page:1, page:1,
isSpin:true isSpin:true
}) })
this.getCourses(category,status,sort_by,1); this.getCourses(category, status, sort_by, 1, sort_direction);
} }
//切换页数 //切换页数
changePage=(page)=>{ changePage=(page)=>{
@ -85,8 +91,8 @@ class InfosPath extends Component{
page, page,
isSpin:true isSpin:true
}) })
let{category,sort_by,status}=this.state; let {category, sort_by, status, sort_direction} = this.state;
this.getCourses(category,status,sort_by,page); this.getCourses(category, status, sort_by, page, sort_direction);
} }
// 进入课堂 // 进入课堂
@ -101,15 +107,49 @@ class InfosPath extends Component{
sort_by:sort, sort_by:sort,
isSpin:true isSpin:true
}) })
let{category,status,page}=this.state; let {category, status, page, sort_direction} = this.state;
this.getCourses(category,status,sort,page); 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(){ render(){
let{ let{
category, category,
status, status,
sort_by, sort_by,
sort_direction,
page, page,
data, data,
totalCount, totalCount,
@ -117,35 +157,172 @@ class InfosPath extends Component{
} = this.state; } = this.state;
let isStudent = this.props.isStudent(); let isStudent = this.props.isStudent();
let is_current=this.props.is_current; 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( return(
<div className="educontent"> <div className="educontent">
<Spin size="large" spinning={isSpin}> <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 "> <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 ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li> href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</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> </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 && category && category == "manage" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="editing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("editing")}>编辑中</a></li> onClick={() => this.changeStatus()}
<li className={status=="applying" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("applying")}>待审核</a></li> className="w32">全部</a></li>
<li className={status=="published" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("published")}>已发布</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> </div>
} }
{ {
category && category == "study" && is_current && category && category == "study" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="unfinished" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("unfinished")}>未完成</a></li> onClick={() => this.changeStatus()}
<li className={status=="finished" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("finished")}>已完成</a></li> 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>
} }
<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="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> </div>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix"> <div className="square-list clearfix">
{/* 295 */} {/* 295 */}
{ {

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { SnackbarHOC } from 'educoder'; import { SnackbarHOC } from 'educoder';
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; 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 axios from 'axios';
import NoneData from '../../courses/coursesPublic/NoneData' import NoneData from '../../courses/coursesPublic/NoneData'
import {getImageUrl} from 'educoder'; import {getImageUrl} from 'educoder';
@ -16,7 +16,8 @@ class InfosProject extends Component{
status:undefined, status:undefined,
page:1, page:1,
per_page:16, per_page:16,
sort_by: "updated_on",
sort_direction: "desc",
totalCount:undefined, totalCount:undefined,
data:undefined, data:undefined,
isSpin:false isSpin:false
@ -27,16 +28,18 @@ class InfosProject extends Component{
this.setState({ this.setState({
isSpin:true isSpin:true
}) })
let{category,status,page}=this.state; let {category, status, page, sort_by, sort_direction} = this.state;
this.getCourses(category,status,page); 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`; let url=`/users/${this.props.match.params.username}/projects.json`;
axios.get((url),{params:{ axios.get((url),{params:{
category, category,
status, status,
page, page,
sort_by,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16 per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{ }}).then((result)=>{
if(result){ if(result){
@ -49,6 +52,8 @@ class InfosProject extends Component{
this.setState({ this.setState({
totalCount:result.data.count, totalCount:result.data.count,
data:result.data, data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false isSpin:false
}) })
} }
@ -56,6 +61,9 @@ class InfosProject extends Component{
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
this.setState({
isSpin: false
})
}) })
} }
@ -66,8 +74,9 @@ class InfosProject extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{status}=this.state; let {status, sort_by, sort_direction} = this.state;
this.getCourses(cate,status,1); this.getCourses(cate, status, 1, sort_by,
sort_direction);
} }
//切换状态 //切换状态
changeStatus=(status)=>{ changeStatus=(status)=>{
@ -76,8 +85,12 @@ class InfosProject extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{category}=this.state; let {
this.getCourses(category,status,1); category, sort_by,
sort_direction
} = this.state;
this.getCourses(category, status, 1, sort_by,
sort_direction);
} }
//切换页数 //切换页数
changePage=(page)=>{ changePage=(page)=>{
@ -85,8 +98,12 @@ class InfosProject extends Component{
page, page,
isSpin:true isSpin:true
}) })
let{category,status}=this.state; let {
this.getCourses(category,status,page); 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(){ render(){
let{ let{
category, category,
@ -103,32 +151,164 @@ class InfosProject extends Component{
page, page,
data, data,
totalCount, totalCount,
isSpin isSpin,
sort_by,
sort_direction
} = this.state; } = this.state;
let isStudent = this.props.isStudent(); let isStudent = this.props.isStudent();
let is_current=this.props.is_current; 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( return(
<div className="educontent"> <div className="educontent">
<Spin size="large" spinning={isSpin}> <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 "> <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 ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li> href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</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> </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 && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="publicly" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("publicly")}>公开</a></li> onClick={() => this.changeStatus()}
<li className={status=="personal" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("personal")}>私有</a></li> 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> </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="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> </p>
<style>
{
`
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
`
}
</style>
<div className="square-list clearfix"> <div className="square-list clearfix">
{/* 289 */} {/* 289 */}
{ {
@ -174,17 +354,17 @@ class InfosProject extends Component{
<div className="edu-txt-center course-bottom"> <div className="edu-txt-center course-bottom">
<div className="inline color-grey-6"> <div className="inline color-grey-6">
{ {
item.members_count> 0 && item.members_count > 0 &&
<span className="mr10 ml10 fl squareIconSpan"> <span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-chengyuan fl mr3" data-tip-down="成员"></i>{item.members_count}</span> <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"> <span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-issue fl mr3" data-tip-down="issues数"></i>{item.issues_count}</span> <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"> <span className="mr10 ml10 fl squareIconSpan">
<i className="iconfont icon-banbenku fl mr3" data-tip-down="版本库"></i>{item.changesets_count}</span> <i className="iconfont icon-banbenku fl mr3" data-tip-down="版本库"></i>{item.changesets_count}</span>
} }

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Pagination , Spin } from 'antd'; import {Pagination, Spin, Dropdown, Menu} from 'antd';
import NoneData from '../../courses/coursesPublic/NoneData' import NoneData from '../../courses/coursesPublic/NoneData'
import axios from 'axios'; import axios from 'axios';
@ -16,11 +16,11 @@ class InfosShixun extends Component{
this.state={ this.state={
category:undefined, category:undefined,
page:1, page:1,
sort_by:'time',
status:undefined, status:undefined,
per_page:16, per_page:16,
isSpin:false, isSpin:false,
sort_by: "updated_at",
sort_direction: "desc",
totalCount:undefined, totalCount:undefined,
data:undefined data:undefined
} }
@ -30,28 +30,40 @@ class InfosShixun extends Component{
this.setState({ this.setState({
isSpin:true isSpin:true
}) })
let{category,status,sort_by,page}=this.state; let {category, status, sort_by, page, sort_direction} = this.state;
this.getCourses(category,status,sort_by,page); 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`; let url=`/users/${this.props.match.params.username}/shixuns.json`;
axios.get((url),{params:{ axios.get((url),{params:{
category, category,
status, status,
sort_by, sort_by,
page, page,
sort_direction,
per_page:this.props.is_current && category && page ==1?17:16 per_page:this.props.is_current && category && page ==1?17:16
}}).then((result)=>{ }}).then((result)=>{
if(result){ if(result){
console.log("请求数据成功");
console.log(sort_by);
this.setState({ this.setState({
totalCount:result.data.count, totalCount:result.data.count,
data:result.data, data:result.data,
sort_by: sort_by,
sort_direction: sort_direction,
isSpin:false isSpin:false
}) })
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
this.setState({
isSpin: false
})
}) })
} }
@ -63,8 +75,8 @@ class InfosShixun extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{sort_by}=this.state; let {sort_by, sort_direction} = this.state;
this.getCourses(cate,undefined,sort_by,1); this.getCourses(cate, undefined, sort_by, 1, sort_direction);
} }
// 切换状态 // 切换状态
changeStatus=(status)=>{ changeStatus=(status)=>{
@ -73,8 +85,8 @@ class InfosShixun extends Component{
page:1, page:1,
isSpin:true isSpin:true
}) })
let{category,sort_by}=this.state; let {category, sort_by, sort_direction} = this.state;
this.getCourses(category,status,sort_by,1); this.getCourses(category, status, sort_by, 1, sort_direction);
} }
//切换页数 //切换页数
changePage=(page)=>{ changePage=(page)=>{
@ -82,8 +94,8 @@ class InfosShixun extends Component{
page, page,
isSpin:true isSpin:true
}) })
let{category,sort_by,status}=this.state; let {category, sort_by, status, sort_direction} = this.state;
this.getCourses(category,status,sort_by,page); this.getCourses(category, status, sort_by, page, sort_direction);
} }
// 进入课堂 // 进入课堂
@ -98,8 +110,39 @@ class InfosShixun extends Component{
sort_by:sort, sort_by:sort,
isSpin:true isSpin:true
}) })
let{category,status,page}=this.state; let {category, status, page, sort_direction} = this.state;
this.getCourses(category,status,sort,page); 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(){ render(){
@ -110,47 +153,171 @@ class InfosShixun extends Component{
page, page,
data, data,
totalCount, totalCount,
sort_direction,
isSpin isSpin
} = this.state; } = this.state;
let is_current=this.props.is_current; 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( return(
<div className="educontent"> <div className="educontent">
<Spin size="large" spinning={isSpin}> <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 "> <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 ? " font-16 whitepanelyslli" : "active font-16 whitepanelyslli"}><a
<li className={category=="manage" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("manage")}>{is_current ? "我":"TA"}管理的</a></li> href="javascript:void(0)" onClick={() => this.changeCategory()} className="font-16 w32">全部</a></li>
<li className={category=="study" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeCategory("study")}>{is_current ? "我":"TA"}学习的</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> </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 && category && category == "manage" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="editing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("editing")}>编辑中</a></li> onClick={() => this.changeStatus()}
<li className={status=="applying" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("applying")}>待审核</a></li> className="w32">全部</a></li>
<li className={status=="published" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("published")}>已发布</a></li> <li className={status == "editing" ? "active whitepanelysllisyt" : "whitepanelysllisyt"}><a
<li className={status=="closed" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("closed")}>已关闭</a></li> 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> </div>
} }
{ {
category && category == "study" && is_current && category && category == "study" && is_current &&
<div className="edu-back-white padding20-30 clearfix secondNav bor-top-greyE"> <div className="edu-back-white padding20-30 clearfix secondNavs bor-top-greyE">
<li className={status ? "" : "active"}><a href="javascript:void(0)" onClick={()=>this.changeStatus()}>全部</a></li> <li className={status ? "whitepanelyslliss" : "active whitepanelyslliss"}><a href="javascript:void(0)"
<li className={status=="processing" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("processing")}>未通关</a></li> onClick={() => this.changeStatus()}
<li className={status=="passed" ? "active" : ""}><a href="javascript:void(0)" onClick={()=>this.changeStatus("passed")}>已通关</a></li> 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>
} }
<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="fl color-grey-9">共参与{totalCount}{category?category=="manage"?"发布":"学习":"实训"}</span>
<div className="fr"> <sapn className="relativef fr"
<li className="drop_down"> style={{
<span className="color-grey-9 font-12">{sort_by=="time"?"时间最新":"语言类别"}</span><i className="iconfont icon-xiajiantou font-12 ml2 color-grey-6"></i> display: "flex",
<ul className="drop_down_normal"> flexDirection: "column",
<li onClick={()=>this.changeOrder("time")}>时间最新</li> height: "40px",
<li onClick={()=>this.changeOrder("language")}>语言类别</li> lineHeight: "40px",
</ul> }}
</li> >
</div> <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> </div>
<style> <style>
{ {
@ -160,6 +327,7 @@ class InfosShixun extends Component{
left: 10px; left: 10px;
bottom: 100px; bottom: 100px;
} }
.square-list{width: 100%;box-sizing: border-box;margin-top:10px}
` `
} }
</style> </style>

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

Loading…
Cancel
Save