Merge branch 'dev_local' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_local

dev_local_2
jingquan huang 5 years ago
commit 1ea42891e9

@ -1,6 +1,7 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-identity-authentications-index-page').length > 0) {
var $searchFrom = $('.identity-authentication-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this);
@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('.status-filter').show();
} else {
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
}

@ -1,6 +1,7 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-professional-authentications-index-page').length > 0) {
var $searchFrom = $('.professional-authentication-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this);
@ -12,6 +13,7 @@ $(document).on('turbolinks:load', function() {
$searchFrom.find('.status-filter').show();
} else {
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
}

@ -0,0 +1,20 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-shixun-authorizations-index-page').length > 0) {
var $searchFrom = $('.shixun-authorization-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this);
$searchFrom.find('input[name="keyword"]').val('');
$searchFrom.find('select[name="status"]').val('processed');
if($link.data('value') === 'processed'){
$searchFrom.find('.status-filter').show();
} else {
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
}
})

@ -0,0 +1,20 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-subject-authorizations-index-page').length > 0) {
var $searchFrom = $('.subject-authorization-list-form');
$searchFrom.find('select[name="status"]').val('pending');
$searchFrom.on('click', '.search-form-tab', function(){
var $link = $(this);
$searchFrom.find('input[name="keyword"]').val('');
$searchFrom.find('select[name="status"]').val('processed');
if($link.data('value') === 'processed'){
$searchFrom.find('.status-filter').show();
} else {
$searchFrom.find('.status-filter').hide();
$searchFrom.find('select[name="status"]').val('pending');
}
});
}
})

@ -0,0 +1,9 @@
.admins-shixun-authorizations-index-page {
.shixun-authorization-list-container {
span {
&.apply-status-1 { color: #28a745; }
&.apply-status-2 { color: #dc3545; }
&.apply-status-3 { color: #6c757d; }
}
}
}

@ -0,0 +1,9 @@
.admins-subject-authorizations-index-page {
.subject-authorization-list-container {
span {
&.apply-status-1 { color: #28a745; }
&.apply-status-2 { color: #dc3545; }
&.apply-status-3 { color: #6c757d; }
}
}
}

@ -0,0 +1,48 @@
class Admins::ShixunAuthorizationsController < Admins::BaseController
def index
params[:status] ||= 'pending'
applies = ApplyAction.where(container_type: 'ApplyShixun')
status =
case params[:status]
when 'pending' then 0
when 'processed' then [1, 2]
when 'agreed' then 1
when 'refused' then 2
else 0
end
applies = applies.where(status: status) if status.present?
# 关键字模糊查询
keyword = params[:keyword].to_s.strip
if keyword.present?
applies = applies.joins('JOIN shixuns ON shixuns.id = apply_actions.container_id')
.where('shixuns.name LIKE :keyword', keyword: "%#{keyword}%")
end
applies = applies.order(updated_at: :desc)
@applies = paginate applies.includes(user: :user_extension)
shixun_ids = @applies.map(&:container_id)
@shixun_map = Shixun.where(id: shixun_ids).each_with_object({}) { |s, h| h[s.id] = s }
end
def agree
Admins::ShixunAuths::AgreeApplyService.call(current_apply, current_user)
render_success_js
end
def refuse
Admins::ShixunAuths::RefuseApplyService.call(current_apply, current_user, params)
render_success_js
end
private
def current_apply
@_current_apply ||= ApplyAction.where(container_type: 'ApplyShixun').find(params[:id])
end
end

@ -0,0 +1,49 @@
class Admins::SubjectAuthorizationsController < Admins::BaseController
def index
params[:status] ||= 'pending'
applies = ApplyAction.where(container_type: 'ApplySubject')
status =
case params[:status]
when 'pending' then 0
when 'processed' then [1, 2]
when 'agreed' then 1
when 'refused' then 2
else 0
end
applies = applies.where(status: status) if status.present?
# 关键字模糊查询
keyword = params[:keyword].to_s.strip
if keyword.present?
applies = applies.joins('JOIN subjects ON subjects.id = apply_actions.container_id')
.where('subjects.name LIKE :keyword', keyword: "%#{keyword}%")
end
applies = applies.order(updated_at: :desc)
@applies = paginate applies.includes(user: :user_extension)
subject_ids = @applies.map(&:container_id)
@subject_map = Subject.where(id: subject_ids).each_with_object({}) { |s, h| h[s.id] = s }
@challenge_count_map = Challenge.joins(shixun: :stage_shixuns).where(st: 0, stage_shixuns: { subject_id: subject_ids}).group('subject_id').count
end
def agree
Admins::SubjectAuths::AgreeApplyService.call(current_apply, current_user)
render_success_js
end
def refuse
Admins::SubjectAuths::RefuseApplyService.call(current_apply, current_user, params)
render_success_js
end
private
def current_apply
@_current_apply ||= ApplyAction.where(container_type: 'ApplySubject').find(params[:id])
end
end

@ -74,6 +74,7 @@ class ChallengesController < ApplicationController
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end
end
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
end
rescue Exception => e
raise ActiveRecord::Rollback
@ -95,6 +96,7 @@ class ChallengesController < ApplicationController
@challenge.update_column(:modify_time, Time.now)
end
@challenge_choose.update_attributes(chooce_params)
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
# 单选多选题的更新
category = @challenge_choose.standard_answer.length > 1 ? 2 : 1
@challenge_choose.update_column(:category, category)
@ -208,6 +210,9 @@ class ChallengesController < ApplicationController
# 测试集的
@shixun.myshixuns.update_all(:system_tip => 0)
end
if params[:challenge][:show_type].to_i == -1
@challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil)
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)

@ -2,7 +2,7 @@ module Admins::ErrorRescueHandler
extend ActiveSupport::Concern
included do
rescue_from Exception, Educoder::TipException do |e|
rescue_from Exception do |e|
raise e if Rails.env.development?
Util.logger_error e

@ -28,7 +28,7 @@ module Admins::RenderHelper
def internal_server_error
respond_to do |format|
format.html { render 'admins/shared/500' }
format.js { render_js_error(message) }
format.js { render_js_error('系统错误') }
format.json { render status: 500, json: { message: '系统错误' } }
end
end

@ -13,8 +13,8 @@ class GamesController < ApplicationController
def show
uid_logger("--games show start")
# 防止评测中途ajaxE被取消;3改成0是为了处理首次进入下一关的问题
@game.update_attribute(:status, 0) if @game.status == 1
@game.update_attributes(status: 0, open_time: Time.now) if @game.status == 3
update_game_parameter(@game)
game_challenge = Challenge.base_attrs.find(@game.challenge_id)
# 选择题类型的实训关卡总分
@ -739,7 +739,7 @@ class GamesController < ApplicationController
experience = 0
game_status = @game.status
had_done = @game.had_done
game_challenge = Challenge.select([:id, :score, :position, :shixun_id, :web_route]).find(@game.challenge_id)
game_challenge = Challenge.select([:id, :score, :position, :shixun_id, :web_route, :show_type]).find(@game.challenge_id)
if params[:resubmit].blank? # 非重新评测
if game_status == 2 # 通关
@ -765,9 +765,10 @@ class GamesController < ApplicationController
testset_detail max_query_index.to_i, game_challenge
# 处理生成图片类型文件
picture = (@game.picture_path.nil? ? 0 : @game.id)
picture = (game_challenge.show_type.to_i == -1 || @game.picture_path.nil?) ? 0 : @game.id
# 针对web类型的实训
web_route = game_challenge.try(:web_route)
mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first
@ -964,4 +965,13 @@ class GamesController < ApplicationController
nil
end
end
# 更新关卡状态和一些学习进度
def update_game_parameter game
game.update_attribute(:status, 0) if game.status == 1
game.update_attributes(status: 0, open_time: Time.now) if game.status == 3
# 开启实训更新myshixuns的时间方便跟踪用于的学习进度。
game.myshixun.update_column(:updated_at, Time.now)
end
end

@ -101,8 +101,9 @@ class SubjectsController < ApplicationController
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
# 用户获取的实训标签
# @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq
@user_tags = user_shixun_tags challenge_ids, @user.id
@my_subject_progress = @subject.my_subject_progress
# 用户进展
user_subject_progress(challenge_ids)
end
def new
@ -436,4 +437,33 @@ class SubjectsController < ApplicationController
tip_exception("403", "")
end
end
# 用户进展和获取的标签
def user_subject_progress challenge_ids
pass_games = Game.select(:id, :cost_time, :challenge_id).where(status: 2, user_id: current_user.id, challenge_id: challenge_ids) if current_user.logged?
@all_score = Challenge.where(id: challenge_ids).sum(:score)
# 如果没有通关的,没必要再继续统计了
if pass_games.blank?
@my_score = 0
@learned = 0
@time = 0
@user_tags = []
else
pass_challenge_ids = pass_games.map(&:challenge_id)
subject_challenge_count = @subject.shixuns.sum(:challenges_count)
# 用户通关获得的标签
@user_tags = ChallengeTag.where(challenge_id: pass_challenge_ids).pluck(:name)
# 用户学习进度
@learned =
subject_challenge_count == 0 ? 0 :
((pass_challenge_ids.size.to_f / subject_challenge_count).round(2) * 100).to_i
# 用户通关分数
@my_score = Challenge.where(id: pass_challenge_ids).pluck(:score).sum
@time = pass_games.map(&:cost_time).sum
end
end
end

@ -1,8 +1,16 @@
# 申请消息
class ApplyAction < ApplicationRecord
belongs_to :user
has_many :tidings, :as => :container, :dependent => :destroy
after_create :send_tiding
def status_text
I18n.t!("apply_action.status.#{status}")
rescue I18n::MissingTranslationData
nil
end
def send_tiding
if container_type == 'TrialAuthorization' && status == 1
tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System',

@ -40,16 +40,18 @@ class Challenge < ApplicationRecord
## 选择题总分
def choose_score
self.challenge_chooses.pluck(:score).sum
self.score
#self.challenge_chooses.pluck(:score).sum
end
# 关卡总分
def all_score
if self.st == 1
self.choose_score
else
self.score
end
self.score
# if self.st == 1
# self.choose_score
# else
# self.score
# end
end
# 开启挑战

@ -31,7 +31,7 @@ class Game < ApplicationRecord
# 根据得分比例来算实际得分(试卷、实训作业)
def real_score score
((final_score < 0 ? 0 : final_score).to_f / challenge.all_score) * score
((final_score < 0 ? 0 : final_score).to_f / challenge.score) * score
end
# 判断实训是否全部通关

@ -192,11 +192,7 @@ class Shixun < ApplicationRecord
# 实训关卡的总分(由于大部分是实践题,因此没关联查choose表)
# 提前加载问题由于选择题比较少所以几乎不会触发选择题的查询所以没必要提前载入choose_score
def all_score
sum = 0
challenges.each do |challenge|
sum += challenge.st == 0 ? challenge.score : challenge.choose_score
end
sum
self.challenges.pluck(:score).sum
end
### fork 数量

@ -83,7 +83,7 @@ class Subject < ApplicationRecord
def my_subject_progress
my_challenge_count = Game.joins(:challenge).where(user_id: User.current.id, status: 2, challenges: {shixun_id: shixuns.published_closed}).
pluck(:challenge_id).uniq.size
pluck(:challenge_id).uniq.size
count = self.subject_challenge_count == 0 ? 0 : ((my_challenge_count.to_f / self.subject_challenge_count).round(2) * 100).to_i
end

@ -0,0 +1,43 @@
class Admins::ShixunAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :shixun
def initialize(apply, user)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
shixun.update!(status: 2, publish_time: Time.now)
# 奖励金币、经验
reward_grade_and_experience!
deal_tiding!
end
end
private
def reward_grade_and_experience!
score = shixun.all_score
shixun_creator = shixun.user
RewardGradeService.call(shixun_creator, container_id: shixun.id, container_type: 'shixunPublish', score: score)
Experience.create!(user_id: shixun_creator.id, container_id: shixun.id, container_type: 'shixunPublish', score: score)
shixun_creator.update_column(:experience, shixun_creator.experience.to_i + score)
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 1, tiding_type: 'System')
end
end

@ -0,0 +1,35 @@
class Admins::ShixunAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :shixun, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
shixun.update!(status: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 2, tiding_type: 'System')
end
end

@ -0,0 +1,30 @@
class Admins::SubjectAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :subject
def initialize(apply, user)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
subject.update!(status: 2, publish_time: Time.now)
deal_tiding!
end
end
private
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 1, tiding_type: 'System')
end
end

@ -0,0 +1,35 @@
class Admins::SubjectAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :subject, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
subject.update!(status: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 2, tiding_type: 'System')
end
end

@ -41,6 +41,8 @@
<%= sidebar_item_group('#apply-review-submenu', '审核', icon: 'gavel') do %>
<li><%= sidebar_item(admins_identity_authentications_path, '实名认证', icon: 'id-card-o', controller: 'admins-identity_authentications') %></li>
<li><%= sidebar_item(admins_professional_authentications_path, '职业认证', icon: 'drivers-license', controller: 'admins-professional_authentications') %></li>
<li><%= sidebar_item(admins_shixun_authorizations_path, '实训发布', icon: 'object-ungroup', controller: 'admins-shixun_authorizations') %></li>
<li><%= sidebar_item(admins_subject_authorizations_path, '实践课程发布', icon: 'object-group', controller: 'admins-subject_authorizations') %></li>
<% end %>
</li>

@ -4,4 +4,7 @@ setTimeout(function() {
if ($('.admin-alert-container button.close').length > 0) {
$('.admin-alert-container button.close').trigger('click');
}
}, 2000)
}, 5000)
$(".admin-body-container").animate({
scrollTop: 0
}, 200);

@ -0,0 +1,32 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('实训发布') %>
<% end %>
<div class="box search-form-container flex-column mb-0 pb-0 shixun-authorization-list-form">
<ul class="nav nav-tabs w-100 search-form-tabs">
<li class="nav-item">
<%= link_to '待审批', admins_shixun_authorizations_path(status: :pending), remote: true, 'data-value': 'pending',
class: "nav-link search-form-tab #{params[:status] == 'pending' ? 'active' : ''}" %>
</li>
<li class="nav-item">
<%= link_to '已审批', admins_shixun_authorizations_path(status: :processed), remote: true, 'data-value': 'processed',
class: "nav-link search-form-tab #{params[:status] != 'pending' ? 'active' : ''}" %>
</li>
</ul>
<%= form_tag(admins_shixun_authorizations_path(unsafe_params), method: :get, class: 'form-inline search-form justify-content-end mt-3', remote: true) do %>
<div class="form-group status-filter" style="<%= params[:status] != 'pending' ? '' : 'display: none;' %>">
<label for="status">审核状态:</label>
<% status_options = [['全部', 'processed'], ['已同意', 'agreed'], ['已拒绝', 'refused']] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3') %>
<% end %>
</div>
<div class="box shixun-authorization-list-container">
<%= render(partial: 'admins/shixun_authorizations/shared/list', locals: { applies: @applies, shixun_map: @shixun_map }) %>
</div>
<%= render(partial: 'admins/shared/admin_common_refuse_modal') %>

@ -0,0 +1 @@
$('.shixun-authorization-list-container').html("<%= j( render partial: 'admins/shixun_authorizations/shared/list', locals: { applies: @applies, shixun_map: @shixun_map } ) %>");

@ -0,0 +1,60 @@
<% is_processed = params[:status].to_s != 'pending' %>
<table class="table table-hover text-center shixun-authorization-list-table">
<thead class="thead-light">
<tr>
<th width="8%">头像</th>
<th width="14%">创建者</th>
<th width="28%" class="text-left">实训名称</th>
<th width="12%">任务数</th>
<th width="16%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="8%">状态</th>
<% else %>
<th width="22%">操作</th>
<% end %>
</tr>
</thead>
<tbody>
<% if applies.present? %>
<% applies.each do |apply| %>
<% user = apply.user %>
<% shixun = shixun_map[apply.container_id] %>
<tr class="shixun-authorization-item shixun-authorization-<%= apply.id %>">
<td>
<%= link_to "/users/#{user.login}", class: 'shixun-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
<% end %>
</td>
<td><%= user.real_name %></td>
<td class="text-left">
<%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %>
<%= overflow_hidden_span shixun.name, width: 300 %>
<% end %>
</td>
<td><%= shixun.challenges_count %></td>
<td><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.reason, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<% else %>
<td class="action-container">
<%= agree_link '同意', agree_admins_shixun_authorization_path(apply, element: ".shixun-authorization-#{apply.id}"), 'data-confirm': '确认审核通过?' %>
<%= javascript_void_link('拒绝', class: 'action refuse-action',
data: {
toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id,
url: refuse_admins_shixun_authorization_path(apply, element: ".shixun-authorization-#{apply.id}")
}) %>
</td>
<% end %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: applies } %>

@ -0,0 +1,33 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('实践课程发布') %>
<% end %>
<div class="box search-form-container flex-column mb-0 pb-0 subject-authorization-list-form">
<ul class="nav nav-tabs w-100 search-form-tabs">
<li class="nav-item">
<%= link_to '待审批', admins_subject_authorizations_path(status: :pending), remote: true, 'data-value': 'pending',
class: "nav-link search-form-tab #{params[:status] == 'pending' ? 'active' : ''}" %>
</li>
<li class="nav-item">
<%= link_to '已审批', admins_subject_authorizations_path(status: :processed), remote: true, 'data-value': 'processed',
class: "nav-link search-form-tab #{params[:status] != 'pending' ? 'active' : ''}" %>
</li>
</ul>
<%= form_tag(admins_subject_authorizations_path(unsafe_params), method: :get, class: 'form-inline search-form justify-content-end mt-3', remote: true) do %>
<div class="form-group status-filter" style="<%= params[:status] != 'pending' ? '' : 'display: none;' %>">
<label for="status">审核状态:</label>
<% status_options = [['全部', 'processed'], ['已同意', 'agreed'], ['已拒绝', 'refused']] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '实训课程名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3') %>
<% end %>
</div>
<div class="box subject-authorization-list-container">
<%= render(partial: 'admins/subject_authorizations/shared/list',
locals: { applies: @applies, subject_map: @subject_map, challenge_count_map: @challenge_count_map }) %>
</div>
<%= render(partial: 'admins/shared/admin_common_refuse_modal') %>

@ -0,0 +1 @@
$('.subject-authorization-list-container').html("<%= j( render partial: 'admins/subject_authorizations/shared/list', locals: { applies: @applies, subject_map: @subject_map, challenge_count_map: @challenge_count_map } ) %>");

@ -0,0 +1,64 @@
<% is_processed = params[:status].to_s != 'pending' %>
<table class="table table-hover text-center subject-authorization-list-table">
<thead class="thead-light">
<tr>
<th width="8%">头像</th>
<th width="10%">创建者</th>
<th width="28%" class="text-left">实践课程名称</th>
<th width="6%">阶段数</th>
<th width="6%">实训数</th>
<th width="6%">关卡数</th>
<th width="14%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="8%">状态</th>
<% else %>
<th width="22%">操作</th>
<% end %>
</tr>
</thead>
<tbody>
<% if applies.present? %>
<% applies.each do |apply| %>
<% user = apply.user %>
<% subject = subject_map[apply.container_id] %>
<tr class="subject-authorization-item subject-authorization-<%= apply.id %>">
<td>
<%= link_to "/users/#{user.login}", class: 'subject-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
<img src="/images/<%= url_to_avatar(user) %>" class="rounded-circle" width="40" height="40" />
<% end %>
</td>
<td><%= user.real_name %></td>
<td class="text-left">
<%= link_to "/paths/#{subject.id}", target: '_blank' do %>
<%= overflow_hidden_span subject.name, width: 300 %>
<% end %>
</td>
<td><%= subject.stages_count %></td>
<td><%= subject.shixuns_count %></td>
<td><%= challenge_count_map.fetch(subject.id, 0) %></td>
<td><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
<% if is_processed %>
<td class="text-secondary"><%= overflow_hidden_span apply.reason, width: 140 %></td>
<td><span class="apply-status-<%= apply.status %>"><%= apply.status_text %></span></td>
<% else %>
<td class="action-container">
<%= agree_link '同意', agree_admins_subject_authorization_path(apply, element: ".subject-authorization-#{apply.id}"), 'data-confirm': '确认审核通过?' %>
<%= javascript_void_link('拒绝', class: 'action refuse-action',
data: {
toggle: 'modal', target: '.admin-common-refuse-modal', id: apply.id,
url: refuse_admins_subject_authorization_path(apply, element: ".subject-authorization-#{apply.id}")
}) %>
</td>
<% end %>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: applies } %>

@ -13,7 +13,7 @@ if @challenges.present?
json.position challenge.position
json.st challenge.st
json.name challenge.subject
json.score challenge.all_score
json.score challenge.score
json.passed_count challenge.user_passed_count
json.playing_count challenge.playing_count
json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)

@ -20,10 +20,20 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选
#TODO: 旧版本来一个题只有一个标准答案的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置..
standard_answer_b = standard_answers_array.join("").include?(a.choice_position.to_s)
user_answer_b = user_answer.include?(a.id)
choice_text = a.choice_text
if question.question_type == 2
if choice_text == "对"
choice_text = "正确"
end
if choice_text == "错"
choice_text = "错误"
end
end
json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现
json.choice_id a.id
# json.choice_text (edit_type.present? || question.question_type == 2) ? a.choice_text : "#{(index+65).chr}.#{a.choice_text}"
json.choice_text a.choice_text
json.choice_text choice_text
json.choice_position a.choice_position
if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题2为空白试卷即标准答案和用户答案都不显示3为用户开始答题的显示4为老师评阅试卷或学生在截止后查看试卷
json.standard_boolean standard_answer_b
@ -36,6 +46,14 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选
if exercise_type == 1 || exercise_type == 4 #1为老师4为试卷截止且答案公开的情况
json.standard_answer standard_answers_array
if question.question_type == 2 #返回答案的文字
standard_text = standard_answers_array.first.to_i == 1 ? "正确" : "错误"
else
array_text_answer = []
standard_answers_array.each{|a| array_text_answer.push((a+64).chr)}
standard_text = array_text_answer.join("")
end
json.standard_answer_show standard_text
end
if exercise_type == 3 || exercise_type == 4
json.user_answer user_answer

@ -14,8 +14,8 @@ end
# 我的进展
json.progress do
json.my_score @subject.my_subject_score
json.all_score @subject.all_score
json.learned @subject.my_subject_progress
json.time @subject.my_consume_time
json.my_score @my_score
json.all_score @all_score
json.learned @learned
json.time @time
end

@ -55,6 +55,8 @@ Rails.application.configure do
# Suppress logger output for asset requests.
config.assets.quiet = true
# config.assets.prefix = '/dev-assets'
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true

@ -11,4 +11,4 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules')
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
Rails.application.config.assets.precompile += %w( admin.js admin.scss )
Rails.application.config.assets.precompile += %w( admin.js admin.css )

@ -0,0 +1,7 @@
zh-CN:
apply_action:
status:
'0': '待处理'
'1': '已同意'
'2': '已拒绝'
'3': '已撤销'

@ -774,6 +774,18 @@ Rails.application.routes.draw do
post :refuse
end
end
resources :shixun_authorizations, only: [:index] do
member do
post :agree
post :refuse
end
end
resources :subject_authorizations, only: [:index] do
member do
post :agree
post :refuse
end
end
end
#git 认证回调

@ -0,0 +1,10 @@
class ModifyChallnegeScoreForChoose < ActiveRecord::Migration[5.2]
def change
challenges = Challenge.where(st: 1)
challenges.find_each do |c|
puts(c.id)
score = c.challenge_chooses.sum(:score)
c.update_column(:score, score)
end
end
end

@ -0,0 +1 @@
{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-21T15:10:12+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="}},"assets":{"admin.js":"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js","admin.css":"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js","application.css":"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css"}}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

@ -30,7 +30,8 @@ module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map",
// 开启调试
// 开启调试
devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -119,7 +119,7 @@ em.vertical-line{display: inline-block;width: 2px;background: #999;height: 10px}
.tag-green .tag-name{display: block;width: auto;
/*background-image: url("/images/educoder/tag1.png");*/
background: rgba(000,000,000,0.56);
border: 1px solid #fff;
border: 1px solid rgba(255,255,255,0.56);
border-radius: 3px;
font-size: 12px;
/*opacity: 0.56;*/
@ -446,8 +446,8 @@ table.text-file{}
/*-------------------------------实训路径-------------------------------*/
.path-head{width: 100%;height: 300px;background-image: url("/images/educoder/path.png");
background-color: #081C4B;
background-size: cover;
background-color: #000a4f;
/*background-size: cover;*/
background-position: center;
background-repeat: no-repeat;
}

@ -236,8 +236,7 @@ $(function(){
if(dragging) {
clickX = e.pageX || e.originalEvent.touches[0].pageX;;
if(clickX > leftOffset+0&&clickX<leftOffset+1600) {
console.log('resize')
//console.log(1);
// console.log('resize')
lab.css('left', clickX - 7 - leftOffset + 'px');
$("#game_left_contents").width( clickX-leftOffset + 'px');
nextW2 = clickX-leftOffset;
@ -314,10 +313,16 @@ $(function(){
window.top.__updateWebsshRows && window.top.__updateWebsshRows(rows)
}
window.refresh_editor_monaco = function(height) {
console.log('refresh_editor_monaco')
if (window.editor_monaco) {
height && $('#codetab_con_1').height(height)
window.editor_monaco.layout();
}
// if ($('#game_operate_action').width() < 720) {
// $('#game_operate_action .time_limit').hide()
// } else {
// $('#game_operate_action .time_limit').show()
// }
}
// end;
//解決IE瀏覽器大小改變時webssh佈局變亂。

@ -195,7 +195,30 @@ function generateNewIndexJsp() {
let cdnHost = 'https://shixun.educoder.net'
cdnHost = 'https://ali-cdn.educoder.net'
cdnHost = ''
var result = data.replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
var mainRegex = /<script type="text\/javascript" src="\/react\/build\/.\/static\/js\/main.([a-zA-Z0-9]{8,}).js"><\/script>/
var matchResult = data.match(mainRegex)
var code = `
<script>
(function() {
var _host = '/react/build/'
/**/
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/'
}
document.write('<script type="text/javascript" src="' + _host + 'js/js_min_all.js"><\\/script>');
document.write('<script type="text/javascript" src="' + _host + 'static/js/main.${matchResult[1]}.js"><\\/script>');
})()
</script>
`
var jsMinAllRegex = /<script type="text\/javascript" src="\/js\/js_min_all.js"><\/script>/
// <script type="text/javascript" src="/js/js_min_all.js"></script>
var result = data
.replace(jsMinAllRegex, code)
// .replace('/js/js_min_all.js', `${cdnHost}/react/build/js/js_min_all.js?v=${newVersion}`)
// .replace('/js/js_min_all_2.js', `${cdnHost}/react/build/js/js_min_all_2.js?v=${newVersion}`)
// ${cdnHost} 加了cdn后这个文件里的字体文件加载会有跨域的报错 ../fonts/fontawesome-webfont.eot
@ -204,10 +227,11 @@ function generateNewIndexJsp() {
.replace('/css/iconfont.css', `${cdnHost}/react/build/css/iconfont.css?v=${newVersion}`)
.replace(/\/js\/create_kindeditor.js/g, `${cdnHost}/react/build/js/create_kindeditor.js?v=${newVersion}`)
.replace(mainRegex, '')
// .replace('/react/build/./static/css/main', `${cdnHost}/react/build/./static/css/main`)
// .replace('/react/build/./static/js/main', `${cdnHost}/react/build/./static/js/main`)
.replace(/https:\/\/testeduplus2.educoder.net/g, '');
// .replace(/https:\/\/testeduplus2.educoder.net/g, '');
// .replace(/http:\/\/testbdweb.educoder.net/g, '');
// .replace('/css/css_min_all.css', '/react/build/css/css_min_all.css');

@ -55,6 +55,10 @@ html, body {
.markdown-body p {
white-space: pre-wrap;
}
/* https://www.educoder.net/courses/2346/group_homeworks/34405/question */
.renderAsHtml.markdown-body p {
white-space: inherit;
}
/* resize */
.editormd .CodeMirror {
border-right: none !important;

@ -1,4 +1,5 @@
import React, {Component} from 'react';
import './public-path';
import logo from './logo.svg';
import './App.css';
import {LocaleProvider} from 'antd'

@ -9,6 +9,7 @@ export function markdownToHTML(oldContent, selector) {
window.$('#md_div').html('')
// markdown to html
if (selector && oldContent && oldContent.startsWith('<p')) { // 普通html处理
window.$('#' + selector).addClass('renderAsHtml')
window.$('#' + selector).html(oldContent)
} else {
try {

@ -1,4 +1,5 @@
import React,{ Component } from "react";
import { ConditionToolTip } from 'educoder'
class AttachmentsList extends Component{
constructor(props){
@ -11,15 +12,19 @@ class AttachmentsList extends Component{
{
attachments.map((item,key)=>{
return(
<p key={key}>
<a className="color-grey">
<p key={key} className="clearfix mb3">
<a className="color-grey fl">
<i className="font-14 color-green iconfont icon-fujian mr8"></i>
</a>
{
item.is_pdf && item.is_pdf == true ?
<a href={item.url} className="mr12" length="58" target="_blank">{item.title}</a>
<ConditionToolTip title={item.title} condition={item.title && item.title.length > 30 }>
<a href={item.url} className="mr12 fl task-hide" length="58" target="_blank" style={{"maxWidth":"432px"}}>{item.title}</a>
</ConditionToolTip>
:
<a href={item.url} className="mr12" length="58">{item.title}</a>
<ConditionToolTip title={item.title} condition={item.title && item.title.length > 30 }>
<a href={item.url} className="mr12 fl task-hide" length="58" style={{"maxWidth":"432px"}}>{item.title}</a>
</ConditionToolTip>
}
<span className="color-grey mt2 color-grey-6 font-12">{item.filesize}</span>
</p>

@ -129,12 +129,16 @@ class Fileslistitem extends Component{
.catch(function (error) {
console.log(error);
});
}
}
eventStop = (event) =>{
event.stopPropagation()
}
render(){
const { checkBox,
discussMessage,
discussMessage,index
} = this.props;
return(
@ -190,9 +194,9 @@ class Fileslistitem extends Component{
white-space:nowrap
}
`}</style>
<div className="clearfix ds pr contentSection">
<h6>
<span className="fl mr12 mt3">
<div className="clearfix ds pr contentSection" style={{cursor : this.props.isAdmin ? "pointer" : "default"}} onClick={() => window.$(`.sourceitem${index} input`).click() }>
<h6 onClick={(event)=>this.eventStop(event)}>
<span className={`sourceitem${index} fl mr12 mt3`}>
{checkBox}
</span>
{
@ -283,16 +287,15 @@ class Fileslistitem extends Component{
</span>
</span>
{this.props.isAdmin?
<span className={"fr mrf2 mr10"}>
<span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
<a className="btn colorblue"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mrf2 mr10"}>
<span className={"fr mrf2 mr10"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<a className="btn colorblue"

@ -10,6 +10,8 @@ import Selectsetting from "../coursesPublic/SelectSetting";
import HomeworkModal from "../coursesPublic/HomeworkModal";
import Fileslistitem from './Fileslistitem';
import Titlesearchsection from '../common/titleSearch/TitleSearchSection';
import NoneData from "../coursesPublic/NoneData";
import _ from 'lodash'
import './style.css';
import '../css/members.css';
import moment from 'moment';
@ -474,7 +476,16 @@ class Fileslists extends Component{
}
onItemClick = (item) => {
const checkBoxValues = this.state.checkBoxValues.slice(0);
const index = checkBoxValues.indexOf(item.id);
if (index != -1) {
_.remove(checkBoxValues, (listItem)=> listItem === item.id)
} else {
checkBoxValues.push(item.id);
}
this.onCheckBoxChange(checkBoxValues)
}
PaginationTask=(page)=>{
let {search,order,selectpage,checkAllValue,checkBoxValues}=this.state;
@ -787,7 +798,7 @@ class Fileslists extends Component{
showSearchInput={true}
></Titlesearchsection>
{this.props.isAdmin()? <div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}>
{this.props.isAdmin()? files===undefined?'' :files.length===0? "":<div className="mt20 edu-back-white padding20-30" style={{display:this.props.isAdmin()||this.props.isStudent()?"":"none"}}>
<div className="clearfix">
{this.props.isAdmin()? <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>:""}
<div className="studentList_operation_ul">
@ -897,7 +908,7 @@ class Fileslists extends Component{
{ files&&files.map((item, index) => {
return (
<div className="mt20 edu-back-white padding02010" key={index}>
<div className="mt20 edu-back-white padding02010" key={index} onClick={()=>this.onItemClick(item)}>
<div className="clearfix">
<div key={index}>
<Fileslistitem
@ -909,7 +920,8 @@ class Fileslists extends Component{
checkBox={this.props.isAdmin()?<Checkbox value={item.id} key={item.id}></Checkbox>:""}
Settingtypes={(id)=>this.Settingtypes(id)}
coursesId={this.props.match.params.coursesId}
updatafiledfun={()=>this.updatafiled()}
updatafiledfun={()=>this.updatafiled()}
index={index}
></Fileslistitem>
</div>
</div>
@ -948,21 +960,23 @@ class Fileslists extends Component{
/>:""}
</div>
<div className="alltask edu-back-white"
style={
{
display: files===undefined?'none' :files.length===0? 'block' : 'none'
}
}
>
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p></div>
</div>
{
files===undefined?'' :files.length===0?<NoneData></NoneData>:""
}
</React.Fragment>
)
}
}
export default Fileslists;
{/*<div className="alltask"*/}
{/*style={*/}
{/*{*/}
{/*display: files===undefined?'none' :files.length===0? 'block' : 'none'*/}
{/*}*/}
{/*}*/}
{/*>*/}
{/*<div className="edu-tab-con-box clearfix edu-txt-center">*/}
{/*<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />*/}
{/*<p className="edu-nodata-p mb20">暂时还没有相关数据哦!</p></div>*/}
{/*</div>*/}

@ -376,10 +376,15 @@ class BoardsNew extends Component{
dropdownRender={menu => (
<div>
{menu}
<Divider style={{ margin: '4px 0' }} />
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
<Icon type="plus" /> 添加目录
</div>
{
isAdmin &&
<React.Fragment>
<Divider style={{ margin: '4px 0' }} />
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
<Icon type="plus" /> 添加目录
</div>
</React.Fragment>
}
</div>
)}
>

@ -24,7 +24,7 @@ import '../../forums/RightSection.css'
import './TopicDetail.css'
import '../common/courseMessage.css'
import { Pagination, Tooltip } from 'antd'
import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder'
import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml , setImagesUrl } from 'educoder'
import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
import CBreadcrumb from '../common/CBreadcrumb'
import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment
@ -57,6 +57,7 @@ class TopicDetail extends Component {
pageCount: 1,
comments: [],
goldRewardDialogOpen: false,
author:undefined
}
}
componentDidMount() {
@ -85,7 +86,8 @@ class TopicDetail extends Component {
memo: Object.assign({}, {
...response.data.data,
replies_count: response.data.data.total_replies_count
}, {...this.state.memo})
}, {...this.state.memo}),
author:response.data.data.author
}, () => {
})
@ -514,7 +516,7 @@ class TopicDetail extends Component {
render() {
const { match, history } = this.props
const { recommend_shixun, current_user,author_info } = this.props;
const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state;
const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count , author } = this.state;
const messageId = match.params.topicId
if (this.state.memoLoading || !current_user) {
return <div className="edu-back-white" id="forum_index_list"></div>
@ -599,51 +601,54 @@ class TopicDetail extends Component {
}
</div>
<div className="color-grey-9 clearfix">
<span className="fl" style={{marginTop: "2px"}}>{moment(memo.created_on).fromNow()} 发布</span>
<div className="fr">
</div>
</div>
<div className="color-grey-9 clearfix">
<span className="fl" style={{marginTop: '4px'}}>
{/* { current_user.admin && <Tooltip title={ "" }>
<span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}>
<i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i>
</span>
</Tooltip> } */}
<Tooltip title={"浏览数"}>
<span className={`noteDetailNum `} style={{paddingLeft: '0px'}}>
<i className="iconfont icon-liulanyan mr5"></i>
<span style={{ top: "1px", position: "relative" }}>{memo.visits || '1'}</span>
</span>
</Tooltip>
{ !!memo.total_replies_count &&
<Tooltip title={"回复数"}>
<a href="javascript:void(0)" className="noteDetailNum">
<i className="iconfont icon-huifu1 mr5" onClick={this.showCommentInput}></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.total_replies_count }</span>
</a>
</Tooltip>
}
{!!memo.praises_count &&
<Tooltip title={"点赞数"}>
<span className={`noteDetailNum `} style={{}}>
<i className="iconfont icon-dianzan-xian mr5"></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.praises_count }</span>
<div className="df mt20">
<img src={setImagesUrl(`/images/${author && author.image_url}`)} className="radius mr10 mt2" width="40px" height="40px"/>
<div className="flex1">
<div className="color-grey-9 lineh-20">
<span class="color-grey-3 mr20 fl" style={{"fontWeight":"400"}}>{author && author.name}</span>
<span className="fl">{moment(memo.created_on).fromNow()} 发布</span>
</div>
<div className="color-grey-9 clearfix">
<span className="fl" style={{marginTop: '4px'}}>
{/* { current_user.admin && <Tooltip title={ "" }>
<span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}>
<i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i>
</span>
</Tooltip>
</Tooltip> } */}
<Tooltip title={"浏览数"}>
<span className={`noteDetailNum `} style={{paddingLeft: '0px'}}>
<i className="iconfont icon-liulanyan mr5"></i>
<span style={{ top: "1px", position: "relative" }}>{memo.visits || '1'}</span>
</span>
</Tooltip>
{ !!memo.total_replies_count &&
<Tooltip title={"回复数"}>
<a href="javascript:void(0)" className="noteDetailNum">
<i className="iconfont icon-huifu1 mr5" onClick={this.showCommentInput}></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.total_replies_count }</span>
</a>
</Tooltip>
}
</span>
<div className="fr">
{/* || current_user.user_id === author_info.user_id */}
<a className={`task-hide fr return_btn color-grey-6 ${ current_user && (isAdmin
) ? '': 'no_mr'} `} onClick={() => this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id})) } >
返回
</a>
</div>
{!!memo.total_praises_count &&
<Tooltip title={"点赞数"}>
<span className={`noteDetailNum `} style={{}}>
<i className="iconfont icon-dianzan-xian mr5"></i>
<span style={{ top: "2px", position: "relative" }}>{ memo.total_praises_count }</span>
</span>
</Tooltip>
}
</span>
<div className="fr">
{/* || current_user.user_id === author_info.user_id */}
<a className={`task-hide fr return_btn color-grey-6 ${ current_user && (isAdmin
) ? '': 'no_mr'} `} onClick={() => this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id})) } >
返回
</a>
</div>
</div>
</div>
</div>
</div>

@ -363,9 +363,9 @@ class Boards extends Component{
<FilesListItem></FilesListItem> */}
{isAdmin && <div className="mt20 edu-back-white padding20-30">
<div className="clearfix">
{isAdmin && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>}
{messages&&messages.length == 0?"": isAdmin && <div className="mt20 edu-back-white padding20-30">
<div className="clearfix">
{isAdmin&&<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>}
<div className="studentList_operation_ul">
{ !!isAdmin &&
<React.Fragment>

@ -15,7 +15,7 @@ import WorkDetailPageHeader from './common/WorkDetailPageHeader'
import CommonWorkAppraiseReply from './reply/CommonWorkAppraiseReply'
import Example from './TestHooks'
import CommonWorkAppraiseReviseAttachments from './CommonWorkAppraiseReviseAttachments'
import LeaderIcon from './common/LeaderIcon'
const { Option} = Select;
const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm;
@ -88,6 +88,14 @@ class CommonWorkAppraise extends Component{
console.log(error)
})
}
componentDidUpdate(prevProps, prevState) {
if (this.props.match.params.studentWorkId != prevProps.match.params.studentWorkId) {
this.getWork();
this.getReviseAttachments()
this.commonWorkAppraiseReply && this.commonWorkAppraiseReply.fetchAllComments()
}
}
componentDidMount() {
this.getWork();
this.getReviseAttachments()
@ -156,12 +164,13 @@ class CommonWorkAppraise extends Component{
attachments, homework_id, project_info, work_members, is_evaluation,
description, update_user_name, update_time, commit_time, author_name,
revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login,
Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype
Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype, is_leader_work
} =this.state;
let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id;
let studentWorkId=this.props.match.params.studentWorkId;
const isAdmin = this.props.isAdmin()
return(
<WorkDetailPageHeader
{...this.props} {...this.state}
@ -251,12 +260,27 @@ class CommonWorkAppraise extends Component{
{is_evaluation != true && work_members && !!work_members.length && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}>
<div className={"color-grey-6 mb10"}>
其他组员
全部组员
</div>
<div className={"ml20"}>
{work_members.map((item, index) => {
return item.user_name + ' '
})}
<div className={"ml20 color-grey-6"}>
<div className="">
当前组员{author_name} {is_leader_work && <LeaderIcon small={true} ></LeaderIcon>}
</div>
<div>
其他组员
{work_members.map((item, index) => {
return <React.Fragment>
{isAdmin ?
<a className={`color-blue ${index == 0 ? '' : 'ml10'}`} href="javascript:void(0)"
onClick={() => this.props.toWorkDetailPage(this.props.match.params, null, item.work_id)}
>
{item.user_name}
</a> : <span className={`${index == 0 ? '' : 'ml10'}`} >{item.user_name}</span>}
{item.is_leader && <LeaderIcon small={true} ></LeaderIcon>}
</React.Fragment>
})}
</div>
</div>
</div>
}
@ -266,6 +290,7 @@ class CommonWorkAppraise extends Component{
{/* task_type={datalist&&datalist.task_type} */}
<CommonWorkAppraiseReply {...this.props} task_id={studentWorkId}
onReplySuccess={this.onReplySuccess} {...this.state}
wrappedComponentRef={(ref) => {this.commonWorkAppraiseReply = ref}}
></CommonWorkAppraiseReply>
</div>

@ -15,7 +15,7 @@ import WorkDetailPageHeader from './common/WorkDetailPageHeader'
import PublishRightnow from './PublishRightnow'
import ModulationModal from "../coursesPublic/ModulationModal";
import AccessoryModal from "../coursesPublic/AccessoryModal";
import LeaderIcon from './common/LeaderIcon'
const { Option} = Select;
const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm;
@ -97,7 +97,12 @@ function buildColumns(that, student_works, studentData) {
}} title={text && text.length > 5 ? text : ''}>
{/* <Tooltip placement="bottom" title={text}>
</Tooltip> */}
{text}
{record.is_leader ?
<div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center'}}>
<div >{text}</div>
<LeaderIcon></LeaderIcon>
</div>
: <React.Fragment>{text}</React.Fragment>}
</div>
),
}]

@ -91,7 +91,7 @@ class CommonWorkQuestion extends Component{
{/* 内容区 */}
<div className="padding40 memoContent new_li">
<MarkdownToHtml content={description} selector="work_content"></MarkdownToHtml>
<MarkdownToHtml content={description} selector="work_content" className="mb10"></MarkdownToHtml>
{ attachments && attachments.map((item) => {
return ( <div className="color-grey">

@ -128,7 +128,7 @@ class UseBank extends Component{
})
}
onSave = () => {
debugger
const { checkBoxValues } = this.state;
const { object_type } = this.props
if(checkBoxValues.length==0){

@ -0,0 +1,19 @@
import React,{Component} from "React";
export default function LeaderIcon(props = {}) {
let icon = null;
if (props.small) {
icon = <div className="font-8 blueFull Actionbtn" style={{
height: '14px',
'line-height': '14px',
width: '24px',
padding: 0,
'margin-top': '-2px',
'margin-left': '2px',
'vertical-align': 'middle', }}>组长</div>
} else {
icon = <div className="font-8 blueFull Actionbtn" style={{ height: '16px', 'line-height': '16px', width: '30px'}}>组长</div>
}
return icon
}

@ -85,8 +85,7 @@ class WorkDetailPageHeader extends Component{
background: #fff;
}
.workDetailPageHeader .summaryname {
line-height: 20px;
margin-top: 13px;
line-height:30px
}
`}</style>
<CBreadcrumb items={[
@ -99,18 +98,18 @@ class WorkDetailPageHeader extends Component{
// { name: childModuleName }
]}></CBreadcrumb>
<div style={{ width:'100%',height:'52px'}} >
<span className=" fl color-black summaryname" style={{height: 'auto'}}>
<div className="clearfix mt20 mb20" >
<span className=" fl color-black summaryname">
{homework_name}
{/* <Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link> */}
</span>
<CoursesListType
typelist={homework_status}
typesylename={"mt12"}
typesylename={"mt3"}
/>
{category && <a className="color-grey-6 fr font-16 ml30 mt7 mr20" onClick={this.goback} style={{ marginRight: '26px'}}>返回</a>}
{category && <a className="color-grey-6 fr font-16 ml30 mr30 lineh-25" onClick={this.goback}>返回</a>}
{this.props.update_atta &&
<React.Fragment>

@ -143,7 +143,9 @@ class commonWork extends Component{
this.setState({
order:e.key==="all"?"":e.key,
page:1,
isSpin:true
isSpin:true,
checkBoxValues:[],
checkAll:false
})
let {search}=this.state;
this.getList(1,search,e.key==="all"?"":e.key);

@ -750,7 +750,8 @@ class Coursesleftnav extends Component{
{/*分班*/}
{item.type==="course_group"?<div onClick={e=>this.Navmodalnames(e,2,"course_group",item.id)}>添加分班</div>:""}
{/*分班*/}
{item.type==="course_group"?<div onClick={e=>this.Navmodalnames(e,5,"editname",item.id,item.name)}>重命名</div>: <div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}></div>}
{/*{item.type==="course_group"? :""}*/}
<div onClick={e=>this.Navmodalnames(e,3,"editname",item.id,item.name)}>重命名</div>
<div onClick={e=>this.edithidden(e,item.id)}>隐藏</div>
<div onClick={e=>this.editSetup(e,item.id)}>置顶</div>

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import {getImageUrl} from 'educoder';
import { getImageUrl , getUrl } from 'educoder';
class NoneData extends Component{
constructor(props) {
@ -9,7 +9,20 @@ class NoneData extends Component{
const { style } = this.props;
return(
<div className="edu-tab-con-box clearfix edu-txt-center" style={style}>
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/>
<style>
{`
.edu-tab-con-box{
padding:100px 0px;
}
.ant-modal-body .edu-tab-con-box{
padding:0px!important;
}
img.edu-nodata-img{
margin: 40px auto 20px;
}
`}
</style>
<img className="edu-nodata-img mb20" src={getUrl("/images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p>
</div>
)

@ -180,11 +180,13 @@ class PathModal extends Component{
}else{
// this.homeworkstart
//调用立即发布弹窗
// this.props.showNotification(response.data.message)
this.props.hidecouseShixunModal();
this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
this.props.updataleftNavfun()
// this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
// this.props.showNotification("选用成功")
// this.props.showNotification(response.data.message)
// this.props.homeworkupdatalists(Coursename,page,order);
this.props.homeworkupdatalists(this.props.Coursename,this.props.page,this.props.order);
}
// if(response.status===200) {

@ -186,7 +186,8 @@ class ShixunModal extends Component{
// this.props.showNotification(response.data.message)
}else{
this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
// this.props.courseshomeworkstart(response.data.category_id,response.data.homework_ids)
this.props.homeworkupdatalists(this.props.Coursename,this.props.page,this.props.order);
this.props.hidecouseShixunModal()
}
this.setState({

@ -171,7 +171,20 @@ class Exercise extends Component{
checkAllValue: checkedValues.length == exercises.length
})
}
// 全选or反选
onItemClick = (item) => {
const checkBoxValues = this.state.checkBoxValues.slice(0);
const index = checkBoxValues.indexOf(item.id);
if (index != -1) {
_.remove(checkBoxValues, (listItem)=> listItem === item.id)
} else {
checkBoxValues.push(item.id)
}
this.onCheckBoxChange(checkBoxValues)
}
// 全选or反选
onCheckAll = (e) => {
this.setState({
checkAllValue: e.target.checked
@ -507,7 +520,7 @@ class Exercise extends Component{
</div>
</div>
<Spin size="large" spinning={this.state.isSpin}>
{this.props.isAdmin()?<div className="mt20 mb20 edu-back-white padding20-30">
{this.props.isAdmin()?exercises && exercises.length ===0?"":<div className="mt20 mb20 edu-back-white padding20-30">
<div className="clearfix">
<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} </Checkbox>
<div className="studentList_operation_ul">
@ -559,9 +572,9 @@ class Exercise extends Component{
{...this.props}
{...this.state}
item={item}
key={key}
index={key}
onItemClick={this.onItemClick}
checkBox={<Checkbox value={item.id} key={item.id}
// onClick={() => this.onItemClick(item)}
></Checkbox>}
></ExerciseListItem>
)

@ -52,17 +52,17 @@ class ExerciseListItem extends Component{
})
}
render(){
let{item,checkBox}=this.props;
let{item,checkBox,index}=this.props;
let {coursesId,Id}=this.props.match.params
const IsAdmin =this.props.isAdmin();
const IsStudent =this.props.isStudent();
// console.log(this.props.current_user.user_id)
return(
<div className="workList_Item" style={{padding:"30px"}}>
<div className="workList_Item" style={{cursor : IsAdmin ? "pointer" : "default",padding:"30px" }} onClick={() => window.$(`.exerciseitem${index} input`).click() }>
{
IsAdmin &&
<span className="fl mr12">
IsAdmin &&
<span className={`exerciseitem${index} fl mr12`}>
{checkBox}
</span>
}
@ -96,20 +96,20 @@ class ExerciseListItem extends Component{
{/*<Link to={`/courses/${coursesId}/exercises/${item.id}/exercises/student_exercise_list?tab=0`} className="fl font-16 font-bd mt2 color-grey-3 task-hide" style={{"maxWidth":"600px"}}>{item.exercise_name}</Link>*/}
{
this.props.isAdmin()? <a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580"
this.props.isAdmin()? <Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580"
title={item.exercise_name}
href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:""
to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
}
{
this.props.isStudent()?
<a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:""
<Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
}
{
this.props.isNotMember()? item.lock_status === 0 ?
<span className="fl mt3 font-16 font-bd color-dark comnonwidth580" title={item.exercise_name}>{item.exercise_name}</span>
: <a className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</a>:""
: <Link className="fl font-16 font-bd mt2 color-grey-3 task-hide comnonwidth580" title={item.exercise_name} to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=0`}>{item.exercise_name}</Link>:""
}
{
@ -165,8 +165,8 @@ class ExerciseListItem extends Component{
{ IsAdmin &&<div className="homepagePostSetting" style={{"right":"-17px","top":"51px","display":"block","width":"100px"}}>
<a className="btn colorblue font-16" href={`/courses/${coursesId}/exercises/${item.id}/edit`}>编辑</a>
<a className="btn colorblue ml20 font-16" href={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=3`}>设置</a>
<Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/edit`}>编辑</Link>
<Link className="btn colorblue ml20 font-16" to={`/courses/${coursesId}/exercises/${item.id}/student_exercise_list?tab=3`}>设置</Link>
</div> }
</p>
@ -193,7 +193,7 @@ class ExerciseListItem extends Component{
<div className="homepagePostSetting" style={{"right":"0px","top":"62px","position":"absolute","display":"block"}}>
{item.current_status ===0&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>继续答题</Link></li>:
item.current_status ===1&&item.exercise_status>1? <li> <Link className="btn colorblue font-16" to={`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`}>查看答题</Link></li>:
item.current_status ===2&&item.exercise_status>1? <li> <a className="btn colorblue ml20 font-16" onClick={()=>this.setgameexercise(`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`)}>开始答题</a></li>:""}
item.current_status ===2&&item.exercise_status>1? <li> <a className="btn colorblue ml20 font-16" onClick={()=>this.setgameexercise(`/courses/${coursesId}/exercises/${item.id}/users/${this.props.current_user.login}`)}>开始答题</a></li>:""}
</div>
}
</div>

@ -541,6 +541,18 @@ class ExerciseReviewAndAnswer extends Component{
.inputNumber30 .ant-input-number-input-wrap .ant-input-number-input{
height: 28px;
}
.setRadioStyle{
width:100%;
cursor:pointer;
}
.setRadioStyle span:last-child{
flex:1;
display:flex;
}
.setRadioStyle .ant-radio,.setRadioStyle .ant-checkbox{
height:16px;
margin-top:2px;
}
`}</style>
{/*<p style={{height:"60px"}}></p>*/}
<Modals

@ -44,19 +44,19 @@ class Multiple extends Component{
console.log(questionType);
return(
<div className="pl30 pr30 singleDisplay">
<Checkbox.Group disabled={ user_exercise_status == 1 ? true : false } onChange={this.saveId} value={questionType.user_answer}>
<Checkbox.Group className="with100" disabled={ user_exercise_status == 1 ? true : false } onChange={this.saveId} value={questionType.user_answer}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = `${tagArray[key]}.`
return(
<p className="clearfix mb15 df">
<Checkbox className="fl lineh-15 df mr8 mt2" value={item.choice_id} key={item.choice_id}>{prefix}</Checkbox>
{/* <span class="fl lineh-20 mt1"></span> */}
{/* <span style={{display:"inline-block"}} className="markdown-body " dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
<MarkdownToHtml content={item.choice_text} selector={'multiple_' + (this.props.index + 1) + (key + 1)}
className="" style={{display:"inline-block"}}
></MarkdownToHtml>
<Checkbox className="lineh-15 df mr8 setRadioStyle" value={item.choice_id}>
<span className="fl mr3 lineh-20">{prefix}</span>
<MarkdownToHtml content={item.choice_text} selector={'multiple_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block"}}
></MarkdownToHtml>
</Checkbox>
</p>
)
})

@ -40,18 +40,18 @@ class single extends Component{
let isJudge = questionType.question_type == 2
return(
<div className="pl30 pr30 singleDisplay">
<Radio.Group disabled={ user_exercise_status == 1 ? true : false } value={questionType.user_answer[0]} onChange={this.changeItem}>
<Radio.Group className="with100" disabled={ user_exercise_status == 1 ? true : false } value={questionType.user_answer[0]} onChange={this.changeItem}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = isJudge ? undefined : `${tagArray[key]}.`
return(
<p className={parseInt(questionType.question_type) == 0 ? "clearfix mb15 df" : "fl mr40 df"}>
<Radio className="fl lineh-20" value={item.choice_id}>{prefix}</Radio>
{/* <span className="fl lineh-20 mr3 "></span> */}
{/* <span style={{display:"inline-block", 'margin-top': '-1px'}} className="markdown-body fl " dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
<MarkdownToHtml content={item.choice_text} selector={'single_' + (this.props.index + 1) + (key + 1)}
className="fl" style={{display:"inline-block", 'margin-top': '-1px'}}
></MarkdownToHtml>
<p className={parseInt(questionType.question_type) == 0 ? "clearfix mb15" : "fl mr40"}>
<Radio className="df lineh-20 setRadioStyle" value={item.choice_id}>
<span className="fl mr3">{prefix}</span>
<MarkdownToHtml content={item.choice_text} selector={'single_' + (this.props.index + 1) + (key + 1)}
className="flex1" style={{display:"inline-block", 'margin-top': '-1px'}}
></MarkdownToHtml>
</Radio>
</p>
)
})

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

Loading…
Cancel
Save