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

yslnewtiku
杨树林 5 years ago
commit 8939d873e1

@ -0,0 +1,65 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-disciplines-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-discipline-modal');
var $form = $modal.find('form.admin-create-discipline-form');
var $nameInput = $form.find('input[name="name"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if ($form.valid()) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
$(".discipline-list-container").on("change", '.discipline-source-form', function () {
var s_id = $(this).attr("data-id");
var s_value = $(this).val();
var s_name = $(this).attr("name");
var json = {};
json[s_name] = s_value;
$.ajax({
url: "/admins/disciplines/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -0,0 +1,31 @@
$(document).on('turbolinks:load', function() {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-discipline-modal', function(){
var $modal = $('.modal.admin-edit-discipline-modal');
var $form = $modal.find('form.admin-edit-discipline-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'discipline[name]': {
required: true,
maxlength: 20
}
}
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
}
});
});
});

@ -0,0 +1,31 @@
$(document).on('turbolinks:load', function() {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-sub-discipline-modal', function(){
var $modal = $('.modal.admin-edit-sub-discipline-modal');
var $form = $modal.find('form.admin-edit-sub-discipline-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'sub_discipline[name]': {
required: true,
maxlength: 20
}
}
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
}
});
});
});

@ -0,0 +1,31 @@
$(document).on('turbolinks:load', function() {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-tag-discipline-modal', function(){
var $modal = $('.modal.admin-edit-tag-discipline-modal');
var $form = $modal.find('form.admin-edit-tag-discipline-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'tag_discipline[name]': {
required: true,
maxlength: 20
}
}
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
}
});
});
});

@ -0,0 +1,65 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-sub-disciplines-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-sub-discipline-modal');
var $form = $modal.find('form.admin-create-sub-discipline-form');
var $nameInput = $form.find('input[name="name"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if ($form.valid()) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
$(".sub-discipline-list-container").on("change", '.sub-discipline-source-form', function () {
var s_id = $(this).attr("data-id");
var s_value = $(this).val();
var s_name = $(this).attr("name");
var json = {};
json[s_name] = s_value;
$.ajax({
url: "/admins/sub_disciplines/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -0,0 +1,65 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-tag-disciplines-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-tag-discipline-modal');
var $form = $modal.find('form.admin-create-tag-discipline-form');
var $nameInput = $form.find('input[name="name"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if ($form.valid()) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
$(".tag-discipline-list-container").on("change", '.tag-discipline-source-form', function () {
var s_id = $(this).attr("data-id");
var s_value = $(this).val();
var s_name = $(this).attr("name");
var json = {};
json[s_name] = s_value;
$.ajax({
url: "/admins/tag_disciplines/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -1,6 +1,49 @@
class Admins::DisciplinesController < Admins::BaseController
def index
@disciplines = Discipline.all
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if Discipline.where(name: name).exists?
Discipline.create!(name: name)
render_ok
end
def edit
@discipline = current_discipline
end
def update
if params[:discipline] && params[:discipline][:name].present?
name = params[:discipline][:name].to_s.strip
current_discipline.update_attributes!(name: name)
else
ActiveRecord::Base.transaction do
current_discipline.update_attributes!(setting_params)
current_discipline.sub_disciplines.each do |sub|
sub.tag_disciplines.each do |tag|
tag.update_attributes!(setting_params)
end
sub.update_attributes!(setting_params)
end
end
end
@disciplines = Discipline.all
end
def destroy
@discipline_id = params[:id]
current_discipline.destroy!
end
private
def current_discipline
@_current_discipline = Discipline.find params[:id]
end
def setting_params
params.permit(:shixun, :subject, :question)
end
end

@ -0,0 +1,52 @@
class Admins::SubDisciplinesController < Admins::BaseController
def index
@discipline = current_discipline
@sub_disciplines = current_discipline.sub_disciplines
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if current_discipline.sub_disciplines.where(name: name).exists?
SubDiscipline.create!(name: name, discipline_id: current_discipline.id)
render_ok
end
def edit
@sub_discipline = current_sub_discipline
end
def update
if params[:sub_discipline] && params[:sub_discipline][:name].present?
name = params[:sub_discipline][:name].to_s.strip
current_sub_discipline.update_attributes!(name: name)
else
ActiveRecord::Base.transaction do
current_sub_discipline.update_attributes!(setting_params)
current_sub_discipline.tag_disciplines.each do |tag|
tag.update_attributes!(setting_params)
end
end
end
@sub_disciplines = current_sub_discipline.discipline&.sub_disciplines
end
def destroy
@sub_discipline_id = params[:id]
current_sub_discipline.destroy!
end
private
def current_sub_discipline
@_current_sub_discipline = SubDiscipline.find params[:id]
end
def current_discipline
@_current_discipline = Discipline.find params[:discipline_id]
end
def setting_params
params.permit(:shixun, :subject, :question)
end
end

@ -0,0 +1,47 @@
class Admins::TagDisciplinesController < Admins::BaseController
def index
@sub_discipline = current_sub_discipline
@tag_disciplines = current_sub_discipline.tag_disciplines
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if current_sub_discipline.tag_disciplines.where(name: name).exists?
TagDiscipline.create!(name: name, sub_discipline_id: current_sub_discipline.id)
render_ok
end
def edit
@tag_discipline = current_tag_discipline
end
def update
if params[:tag_discipline] && params[:tag_discipline][:name].present?
name = params[:tag_discipline][:name].to_s.strip
current_tag_discipline.update_attributes!(name: name)
else
current_tag_discipline.update_attributes!(setting_params)
end
@tag_disciplines = current_tag_discipline.sub_discipline&.tag_disciplines
end
def destroy
@tag_discipline_id = params[:id]
current_tag_discipline.destroy!
end
private
def current_sub_discipline
@_current_sub_discipline = SubDiscipline.find params[:sub_discipline_id]
end
def current_tag_discipline
@_current_tag_discipline = TagDiscipline.find params[:id]
end
def setting_params
params.permit(:shixun, :subject, :question)
end
end

@ -3,8 +3,8 @@ class HackUserLastestCodesController < ApplicationController
before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, :sync_code,
:listen_result, :result, :submit_records, :restore_initial_code]
before_action :update_user_hack_status, only: [:code_debug, :code_submit]
before_action :require_auth_identity, only: [:update_code, :restore_initial_code, :sync_code]
before_action :require_manager_identity, only: [:update_code]
#before_action :require_auth_identity, only: [:restore_initial_code, :sync_code]
before_action :require_manager_identity, only: [:show, :update_code, :restore_initial_code, :sync_code]
def show
@my_hack.update_attribute(:submit_status, 0) if @my_hack.submit_status == 1

@ -1,6 +1,6 @@
class HackSet < ApplicationRecord
#validates :input, presence: { message: "测试集输入不能为空" }
validates :output, presence: { message: "测试集输出不能为空" }
#validates :output, presence: { message: "测试集输出不能为空" }
validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同"
# 编程题测试集
belongs_to :hack

@ -1,3 +1,7 @@
class TagDiscipline < ApplicationRecord
belongs_to :sub_discipline
def discipline
sub_discipline&.discipline
end
end

@ -0,0 +1,2 @@
$.notify({ message: '删除成功' });
$(".discipline-item-<%= @discipline_id %>").remove();

@ -0,0 +1,2 @@
$('.admin-modal-container').html("<%= j( render partial: 'admins/disciplines/shared/edit_discipline_modal', locals: { discipline: @discipline } ) %>");
$('.modal.admin-edit-discipline-modal').modal('show');

@ -0,0 +1,13 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('课程方向', admins_disciplines_path) %>
<% end %>
<div class="box search-form-container discipline-list-form">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-discipline-modal' } %>
</div>
<div class="box admin-list-container discipline-list-container">
<%= render(partial: 'admins/disciplines/shared/list') %>
</div>
<%= render 'admins/disciplines/shared/create_discipline_modal' %>

@ -0,0 +1,28 @@
<div class="modal fade admin-create-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">新建课程方向</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-create-discipline-form" data-url="<%= admins_disciplines_path %>">
<div class="form-group d-flex">
<label for="new_mirror_id" class="col-form-label">名称:</label>
<div class="w-75 d-flex flex-column">
<%= text_field_tag(:name, nil, class: 'form-control', placeholder: '请输入名称') %>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,23 @@
<div class="modal fade admin-edit-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">编辑课程方向</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for([:admins, discipline], html: { class: 'admin-edit-discipline-form' }, defaults: { wrapper_html: { class: 'offset-md-1 col-md-10' } }) do |f| %>
<%= f.input :name, as: :string, label: '名称' %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,33 @@
<table class="table table-hover text-center discipline-list-table">
<thead class="thead-light">
<tr>
<th width="6%">序号</th>
<th width="54%" class="text-left">课程方向</th>
<th width="8%">实践课程</th>
<th width="8%">实训</th>
<th width="8%">题库</th>
<th width="16%">操作</th>
</tr>
</thead>
<tbody>
<% if @disciplines.present? %>
<% @disciplines.each_with_index do |discipline, index| %>
<tr class="discipline-item discipline-item-<%= discipline.id %>">
<td><%= index + 1 %></td>
<td class="text-left">
<span><%= link_to discipline.name, admins_sub_disciplines_path(discipline_id: discipline), :title => discipline.name %></span>
</td>
<td><%= check_box_tag :subject,!discipline.subject,discipline.subject,remote:true,data:{id:discipline.id},class:"discipline-source-form" %></td>
<td><%= check_box_tag :shixun,!discipline.shixun,discipline.shixun,remote:true,data:{id:discipline.id},class:"discipline-source-form" %></td>
<td><%= check_box_tag :question,!discipline.question,discipline.question,remote:true,data:{id:discipline.id},class:"discipline-source-form" %></td>
<td>
<%= link_to '编辑', edit_admins_discipline_path(discipline), remote: true, class: 'action' %>
<%= delete_link '删除', admins_discipline_path(discipline, element: ".discipline-item-#{discipline.id}"), class: 'delete-discipline-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>

@ -0,0 +1,2 @@
$('.modal.admin-edit-discipline-modal').modal("hide");
$(".discipline-list-container").html("<%= j(render :partial => 'admins/disciplines/shared/list') %>");

@ -0,0 +1,2 @@
$.notify({ message: '删除成功' });
$(".sub-discipline-item-<%= @sub_discipline_id %>").remove();

@ -0,0 +1,2 @@
$('.admin-modal-container').html("<%= j( render partial: 'admins/sub_disciplines/shared/edit_sub_discipline_modal', locals: { sub_discipline: @sub_discipline } ) %>");
$('.modal.admin-edit-sub-discipline-modal').modal('show');

@ -0,0 +1,14 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('课程方向', admins_disciplines_path) %>
<% add_admin_breadcrumb(@discipline.name) %>
<% end %>
<div class="box search-form-container sub-discipline-list-form">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-sub-discipline-modal' } %>
</div>
<div class="box admin-list-container sub-discipline-list-container">
<%= render(partial: 'admins/sub_disciplines/shared/list') %>
</div>
<%= render 'admins/sub_disciplines/shared/create_sub_discipline_modal' %>

@ -0,0 +1,28 @@
<div class="modal fade admin-create-sub-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">新建课程</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-create-sub-discipline-form" data-url="<%= admins_sub_disciplines_path(discipline_id: @discipline) %>">
<div class="form-group d-flex">
<label for="new_mirror_id" class="col-form-label">名称:</label>
<div class="w-75 d-flex flex-column">
<%= text_field_tag(:name, nil, class: 'form-control', placeholder: '请输入名称') %>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,23 @@
<div class="modal fade admin-edit-sub-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">编辑课程</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for([:admins, sub_discipline], html: { class: 'admin-edit-sub-discipline-form' }, defaults: { wrapper_html: { class: 'offset-md-1 col-md-10' } }) do |f| %>
<%= f.input :name, as: :string, label: '名称' %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,33 @@
<table class="table table-hover text-center sub-discipline-list-table">
<thead class="thead-light">
<tr>
<th width="6%">序号</th>
<th width="54%" class="text-left">课程</th>
<th width="8%">实践课程</th>
<th width="8%">实训</th>
<th width="8%">题库</th>
<th width="16%">操作</th>
</tr>
</thead>
<tbody>
<% if @sub_disciplines.present? %>
<% @sub_disciplines.each_with_index do |sub, index| %>
<tr class="sub-discipline-item sub-discipline-item-<%= sub.id %>">
<td><%= index + 1 %></td>
<td class="text-left">
<span><%= link_to sub.name, admins_tag_disciplines_path(sub_discipline_id: sub), :title => sub.name %></span>
</td>
<td><%= check_box_tag :subject,!sub.subject,sub.subject,disabled:!sub.discipline&.subject,remote:true,data:{id:sub.id},class:"sub-discipline-source-form" %></td>
<td><%= check_box_tag :shixun,!sub.shixun,sub.shixun,disabled:!sub.discipline&.shixun,remote:true,data:{id:sub.id},class:"sub-discipline-source-form" %></td>
<td><%= check_box_tag :question,!sub.question,sub.question,disabled:!sub.discipline&.question,remote:true,data:{id:sub.id},class:"sub-discipline-source-form" %></td>
<td>
<%= link_to '编辑', edit_admins_sub_discipline_path(sub), remote: true, class: 'action' %>
<%= delete_link '删除', admins_sub_discipline_path(sub, element: ".sub-discipline-item-#{sub.id}"), class: 'delete-sub-discipline-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>

@ -0,0 +1,2 @@
$('.modal.admin-edit-sub-discipline-modal').modal("hide");
$(".sub-discipline-list-container").html("<%= j(render :partial => 'admins/sub_disciplines/shared/list') %>");

@ -0,0 +1,2 @@
$.notify({ message: '删除成功' });
$(".tag-discipline-item-<%= @tag_discipline_id %>").remove();

@ -0,0 +1,2 @@
$('.admin-modal-container').html("<%= j( render partial: 'admins/tag_disciplines/shared/edit_tag_discipline_modal', locals: { tag_discipline: @tag_discipline } ) %>");
$('.modal.admin-edit-tag-discipline-modal').modal('show');

@ -0,0 +1,15 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('课程方向', admins_disciplines_path) %>
<% add_admin_breadcrumb(@sub_discipline&.discipline&.name, admins_sub_disciplines_path(discipline_id: @sub_discipline&.discipline_id)) %>
<% add_admin_breadcrumb(@sub_discipline.name) %>
<% end %>
<div class="box search-form-container tag-discipline-list-form">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-tag-discipline-modal' } %>
</div>
<div class="box admin-list-container tag-discipline-list-container">
<%= render(partial: 'admins/tag_disciplines/shared/list') %>
</div>
<%= render 'admins/tag_disciplines/shared/create_tag_discipline_modal' %>

@ -0,0 +1,28 @@
<div class="modal fade admin-create-tag-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">新建知识点</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-create-tag-discipline-form" data-url="<%= admins_tag_disciplines_path(sub_discipline_id: @sub_discipline) %>">
<div class="form-group d-flex">
<label for="new_mirror_id" class="col-form-label">名称:</label>
<div class="w-75 d-flex flex-column">
<%= text_field_tag(:name, nil, class: 'form-control', placeholder: '请输入名称') %>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,23 @@
<div class="modal fade admin-edit-tag-discipline-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">编辑知识点</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for([:admins, tag_discipline], html: { class: 'admin-edit-tag-discipline-form' }, defaults: { wrapper_html: { class: 'offset-md-1 col-md-10' } }) do |f| %>
<%= f.input :name, as: :string, label: '名称' %>
<div class="error text-danger"></div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,40 @@
<table class="table table-hover text-center tag-discipline-list-table">
<thead class="thead-light">
<tr>
<th width="6%">序号</th>
<th width="54%" class="text-left">知识点</th>
<th width="8%">实践课程</th>
<th width="8%">实训</th>
<th width="8%">题库</th>
<th width="16%">操作</th>
</tr>
</thead>
<tbody>
<% if @tag_disciplines.present? %>
<% @tag_disciplines.each_with_index do |tag, index| %>
<tr class="tag-discipline-item tag-discipline-item-<%= tag.id %>">
<td><%= index + 1 %></td>
<td class="text-left"><%= tag.name %></td>
<td>
<% disabled = !(tag.sub_discipline&.subject && tag.discipline&.subject) %>
<%= check_box_tag :subject,!tag.subject,tag.subject,disabled:disabled,remote:true,data:{id:tag.id},class:"tag-discipline-source-form" %>
</td>
<td>
<% disabled = !(tag.sub_discipline&.shixun && tag.discipline&.shixun) %>
<%= check_box_tag :shixun,!tag.shixun,tag.shixun,disabled:disabled,remote:true,data:{id:tag.id},class:"tag-discipline-source-form" %>
</td>
<td>
<% disabled = !(tag.sub_discipline&.question && tag.discipline&.question) %>
<%= check_box_tag :question,!tag.question,tag.question,disabled:disabled,remote:true,data:{id:tag.id},class:"tag-discipline-source-form" %>
</td>
<td>
<%= link_to '编辑', edit_admins_tag_discipline_path(tag), remote: true, class: 'action' %>
<%= delete_link '删除', admins_tag_discipline_path(tag, element: ".tag-discipline-item-#{tag.id}"), class: 'delete-tag-discipline-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>

@ -0,0 +1,2 @@
$('.modal.admin-edit-tag-discipline-modal').modal("hide");
$(".tag-discipline-list-container").html("<%= j(render :partial => 'admins/tag_disciplines/shared/list') %>");

@ -1261,9 +1261,9 @@ Rails.application.routes.draw do
resources :projects, only: [:index, :destroy]
resources :disciplines, only: [:index, :create, :update, :destroy] do
end
resources :disciplines, only: [:index, :create, :edit, :update, :destroy]
resources :sub_disciplines, only: [:index, :create, :edit, :update, :destroy]
resources :tag_disciplines, only: [:index, :create, :edit, :update, :destroy]
end
namespace :cooperative do

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,14 +4,14 @@
* @Github:
* @Date: 2019-12-17 17:32:55
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-24 17:27:41
* @LastEditTime : 2019-12-26 11:11:57
*/
import './index.scss';
import React, { useState } from 'react';
import { Form, Button, Input } from 'antd';
import QuillForEditor from '../../quillForEditor';
// import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'
import {formatDelta} from './util';
// import {formatDelta} from './util';
const FormItem = Form.Item;
function CommentForm (props) {
@ -68,8 +68,9 @@ function CommentForm (props) {
const content = ctx;
props.form.setFieldsValue({'comment': ''});
setCtx('');
const _html = formatDelta(content.ops);
onSubmit && onSubmit(_html);
// const _html = formatDelta(content.ops);
console.log('保存的内容=====》》》》', content);
onSubmit && onSubmit(JSON.stringify(content));
}
});
}

@ -4,14 +4,19 @@
* @Github:
* @Date: 2019-12-17 17:35:17
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-25 14:53:41
* @LastEditTime : 2019-12-26 11:30:32
*/
import './index.scss';
import 'quill/dist/quill.core.css'; // 核心样式
import 'quill/dist/quill.snow.css'; // 有工具栏
import 'quill/dist/quill.bubble.css'; // 无工具栏
import 'katex/dist/katex.min.css'; // katex 表达式样式
import React, { useState } from 'react';
import CommentIcon from './CommentIcon';
import { getImageUrl, CNotificationHOC } from 'educoder'
import { Icon } from 'antd';
import CommentForm from './CommentForm';
import QuillForEditor from '../../quillForEditor';
function CommentItem ({
isAdmin,
@ -81,9 +86,19 @@ function CommentItem ({
};
// 评论内容
const commentCtx = (ctx) => (
<p className="item-ctx" dangerouslySetInnerHTML={{ __html: ctx}}></p>
);
const commentCtx = (ctx) => {
let _ctx = null;
try {
_ctx = JSON.parse(ctx);
} catch (e) {
_ctx = ctx;
}
return (
<QuillForEditor
readOnly={true}
value={_ctx}
/>
)};
// 加载更多
const handleOnLoadMore = (len) => {
@ -182,6 +197,13 @@ function CommentItem ({
type={!hidden ? "xianshi" : 'yincang1'}
iconClick={() => handleShowOrHide(id, !hidden ? 1 : 0)}
/>
<CommentIcon
style={{ display: can_delete ? 'inline-block' : 'none'}}
className='comment-icon-margin'
type={'shanchu'}
iconClick={() => deleteComment(id)}
/>
{/* 回复 */}
<CommentIcon
className='comment-icon-margin'

@ -64,10 +64,12 @@ $ml: 20px;
}
.item-ctx{
position: relative;
line-height: $lh22;
font-size: $fz12;
color: #333;
margin-top: 10px;
vertical-align: top;
}
.comment_icon_area{
display: flex;

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-24 08:51:25
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-24 10:45:44
* @LastEditTime : 2019-12-26 09:30:11
*/
export const formatDelta = (deltas) => {
@ -22,6 +22,8 @@ export const formatDelta = (deltas) => {
keys.forEach(key => {
text = operate(text, key, element['attributes'][key]);
});
} else if (element['insert']['formula']) {
text = element['insert']['formula'];
}
} else {
const image = element['insert']['image'];
@ -42,7 +44,7 @@ export const formatDelta = (deltas) => {
formatted.push(text);
});
console.log(formatted);
return formatted.join('');
}
@ -53,7 +55,7 @@ export const formatDelta = (deltas) => {
*/
export const operate = (text, key, value) => {
let operatedText = null;
debugger;
switch (key) {
case 'bold':
operatedText = `<strong>${text}</strong>`;
@ -68,7 +70,7 @@ export const operate = (text, key, value) => {
operatedText = `<u>${text}</u>`;
break;
case 'link':
operatedText = `<a href="${value}" target="blank">${text}</a>`;
operatedText = `<a href="${value}" style="color: #5091ff; text-decoration: underline;" target="bland">${text}</a>`;
break;
default:
operatedText = text;

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-12-18 08:49:30
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 16:07:37
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 10:22:26
*/
import './index.scss';
import 'quill/dist/quill.core.css'; // 核心样式
@ -32,7 +32,8 @@ function QuillForEditor ({
style = {},
wrapStyle = {},
showUploadImage,
onContentChange
onContentChange,
// getQuillContent
}) {
// toolbar 默认值
const defaultConfig = [
@ -54,8 +55,8 @@ function QuillForEditor ({
// 文本内容变化时
const handleOnChange = content => {
// console.log('编辑器内容====》》》》', content);
onContentChange && onContentChange(content);
// getQuillContent && getQuillContent(quill);
onContentChange && onContentChange(content, quill);
};
const renderOptions = options || defaultConfig;

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-27 16:02:36
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 14:37:39
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 15:17:28
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
@ -23,7 +23,7 @@ const ControlSetting = (props) => {
submitLoading,
identifier,
excuteState,
showOrHideControl,
// showOrHideControl,
commitTestRecordDetail,
changeLoadingState,
changeSubmitLoadingStatus,

@ -31,6 +31,14 @@
opacity: 0;
}
}
.ant-tabs-bar{
padding: 0;
}
.ant-tabs-nav .ant-tabs-tab{
padding: 12px 0px;
}
}
@ -52,7 +60,7 @@
z-index: 20;
height: 56px;
padding-right: 20px;
padding-left: 10px;
padding-left: 5px;
background: rgba(18,28,36,1);
// background:rgba(48,48,48,1);
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-28 08:44:54
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-25 11:42:10
* @LastEditTime : 2019-12-26 08:51:21
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -80,6 +80,13 @@ function ExecResult (props) {
</React.Fragment>
);
} else if (state === 4){
return (
<p className={'result_info_style'}>
{/* 系统繁忙,请稍后重试 */}
{error_msg}
</p>
)
} else if (state === 3) {
return (
<p className={'result_info_style'}>
系统繁忙请稍后重试

@ -41,7 +41,7 @@
}
}
.flex_l{
padding: 0 10px 0 20px;
padding: 0 10px 0 10px;
color: #fff;
}
.flex_r{

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-27 15:02:52
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 20:07:11
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 15:19:34
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
@ -155,7 +155,7 @@ function MyMonacoEditor (props, ref) {
onClick={handleUpdateNotice}
>
{/* <Icon type="bell" /> */}
<MyIcon type="iconxiaoxi1" />
<MyIcon type="iconxiaoxi1" style={{fontSize: '18px'}}/>
</Badge>
</Tooltip>
<Tooltip
@ -166,7 +166,7 @@ function MyMonacoEditor (props, ref) {
className="flex_normal"
onClick={handleRestoreCode}
type="iconzaicizairu"
style={{ display: identifier ? 'inline-block' : 'none'}}
style={{ display: identifier ? 'inline-block' : 'none', fontSize: '18px'}}
/>
{/* <span onClick={handleRestoreCode} className="flex_normal" style={{ display: identifier ? 'inline-block' : 'none'}}>{renderRestore}</span> */}
</Tooltip>
@ -174,7 +174,7 @@ function MyMonacoEditor (props, ref) {
placement="bottom"
title="设置"
>
<MyIcon className='code-icon' type="iconshezhi" onClick={handleShowDrawer}/>
<MyIcon className='code-icon' type="iconshezhi" onClick={handleShowDrawer} style={{fontSize: '18px'}}/>
</Tooltip>
</div>
<MonacoEditor

@ -26,6 +26,18 @@
color: #666;
}
}
.margin,
.margin-view-overlays,
.current-line{
width: 40px !important;
}
.monaco-editor .margin-view-overlays .line-numbers{
text-align: center;
}
.monaco-scrollable-element{
left: 40px !important;
}
}
.setting_drawer{

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-21 09:19:38
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 17:32:10
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 15:33:01
*/
import './index.scss';
import React from 'react';
@ -17,7 +17,7 @@ const { TextArea } = Input;
const FormItem = Form.Item;
const AddTestDemo = (props) => {
const {
key,
// key,
// onSubmitTest,
onDeleteTest,
testCase,

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-20 10:35:40
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 16:53:55
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 16:00:57
*/
import './index.scss';
// import 'katex/dist/katex.css';
@ -222,10 +222,16 @@ class EditTab extends React.Component {
}
// 描述信息变化时
const handleContentChange = (content) => {
const handleContentChange = (content, quill) => {
console.log('描述信息为: ', content);
// 保存获取的描述信息至redux中
this.handleChangeDescription(content);
// if (quill.getText())
console.log('========>>>>>', quill.getText().length);
if (quill.getText().length === 1) {
this.handleChangeDescription('');
} else {
// 保存获取的描述信息至redux中
this.handleChangeDescription(content);
}
}
// 编辑器配置信息
const quillConfig = [

@ -58,7 +58,7 @@ function LeftPane (props) {
<ul className={'add_editor_list_area'}>
{ renderNavItem }
</ul>
<div className="comp_ctx">
<div className="comp_ctx" style={{ height: 'calc(100vh - 177px)' }}>
{ renderComp }
</div>
</React.Fragment>

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-12-01 10:18:35
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 11:38:15
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 13:51:40
*/
import './index.scss';
import React from 'react';
@ -25,15 +25,15 @@ function RightPane (props, ref) {
// let timer = null;
// 代码改变时,保存
const handleCodeChange = (updateCode) => {
// 保存用户输入的代码
// if (!timer) {
// timer = setInterval(() => {
// clearInterval(timer);
// timer = null;
// if (updateCode) {
// console.log('调用更新代码------>>>>>>', updateCode);
// }
// }, 3000);
// if (props.identifier) {
// // 保存用户输入的代码
// if (!timer) {
// timer = setInterval(() => {
// clearInterval(timer);
// timer = null;
// }, 3000);
// }
// }
saveOjFormCode(updateCode);
}

@ -41,7 +41,7 @@
}
}
.flex_l{
padding: 0 10px 0 20px;
padding: 0 10px 0 10px;
color: #fff;
}
.flex_r{

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-12-04 08:36:21
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 20:05:57
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 14:04:16
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -15,6 +15,7 @@ import { Link } from 'react-router-dom';
import MonacoEditor from '@monaco-editor/react';
import { connect } from 'react-redux';
// import { getImageUrl } from 'educoder';
import { withRouter } from 'react-router'
import actions from '../../../redux/actions';
import CONST from '../../../constants';
import UserInfo from '../components/userInfo';
@ -53,6 +54,12 @@ function RecordDetail (props) {
}
}, [recordDetail]);
const handleReturn = (identifier) => {
if (identifier) {
saveEditorCodeForDetail('');
props.history.push(`/myproblems/${identifier}`);
}
}
return (
<div className="record_detail_area">
<div className="record_detail_header">
@ -67,8 +74,9 @@ function RecordDetail (props) {
<span>{detail.name || 'test'}</span>
</div>
<div className={'study_quit'}>
<Button style={{ visibility: identifier ? 'visible' : 'hidden'}}>
<Link to={`/myproblems/${identifier}`}>返回该题</Link>
<Button style={{ visibility: identifier ? 'visible' : 'hidden'}} onClick={() => handleReturn(identifier)}>
返回该题
{/* <Link to={`/myproblems/${identifier}`}>返回该题</Link> */}
</Button>
</div>
</div>
@ -89,7 +97,7 @@ function RecordDetail (props) {
语言: <span className="status_label_sub">{detail.language}</span>
</span>
<span className="status_label" style={{ visibility: detail.status === 0 ? 'visible' : 'hidden'}}>
执行用时: <span className="status_label_sub">{`${detail.execute_time && (+detail.execute_time * 1000)}ms`}</span>
执行用时: <span className="status_label_sub">{`${detail.execute_time && Number(detail.execute_time * 1000).toFixed(2)}ms`}</span>
</span>
</div>
<div className="result_error_area">
@ -134,7 +142,7 @@ const mapDispatchToProps = (dispatch) => ({
saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code))
});
export default connect(
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(RecordDetail);
)(RecordDetail));

@ -148,8 +148,9 @@
}
.Resizer {
position: relative;
background: #000;
opacity: 0.2;
// opacity: 0.2;
z-index: 1;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-23 10:53:19
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 14:54:39
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-26 15:02:12
*/
import './index.scss';
import React, { useEffect, useState } from 'react';
@ -25,9 +25,9 @@ function StudentStudy (props) {
const [hasUpdate, setHasUpdate] = useState(true);
const {
// hack,
hack,
userInfo,
hack_identifier,
// hack_identifier,
// user_program_identifier,
restoreInitialCode,
changeShowOrHideControl
@ -85,13 +85,13 @@ function StudentStudy (props) {
// }
// });
}
const _hack_id = hack_identifier || fromStore('hack_identifier');
// const _hack_id = hack_identifier || fromStore('hack_identifier');
// 处理编辑
const handleClickEditor = () => {
const handleClickEditor = (identifier) => {
if (!identifier) return;
changeShowOrHideControl(false);
props.saveEditorCodeForDetail();
props.history.push(`/problems/${_hack_id}/edit`);
props.history.push(`/problems/${identifier}/edit`);
props.clearOjForUserReducer();
}
// 处理退出
@ -115,13 +115,13 @@ function StudentStudy (props) {
</div> */}
<UserInfo userInfo={userInfo}/>
<div className={'study_name'}>
<span>乘积最大序列 {hasUpdate}</span>
<span>{hack.name}</span>
</div>
<div className={'study_quit'}>
{/* to={`/problems/${_hack_id}/edit`} */}
<span
style={{ display: userInfo.hack_manager ? 'inline-block' : 'none' }}
onClick={handleClickEditor}
onClick={() => handleClickEditor(hack.identifier)}
className={`quit-btn`}
>
<Icon type="form" className="quit-icon"/> 编辑

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 09:49:35
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-25 10:55:44
* @LastEditTime : 2019-12-26 10:43:45
*/
import './index.scss';
import React, { useEffect, useState } from 'react';

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:35:46
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-23 10:55:28
* @LastEditTime : 2019-12-26 15:45:28
*/
import types from './actionTypes';
import CONST from '../../constants';
@ -58,7 +58,8 @@ const maps = {
// 非空校验
const emptyValidate = (key, value) => {
if ([undefined, '', null].includes(value)) {
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
if (!reg.test(value)) {
return {
[key]: {
validateStatus: 'error',
@ -472,7 +473,7 @@ export const testCaseInputChange = (value, index) => {
const bool = testCases.some((item, i) => {
if (i !== index) {
if (item['input'] === value) {
_errMsg=`与测试用例${index}的输入值重复了,请重新填写`;
_errMsg=`与测试用例${i + 1}的输入值重复了,请重新填写`;
}
return item['input'] === value;
} else {
@ -566,4 +567,4 @@ export const updateOpenTestCaseIndex = (value) => {
type: types.UPDATE_OPEN_TESTCASE_INDEX,
payload: value
}
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:41:48
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-25 17:09:53
* @LastEditTime : 2019-12-26 13:39:41
*/
import types from "../actions/actionTypes";
import { Base64 } from 'js-base64';
@ -111,7 +111,7 @@ const ojForUserReducer = (state = initialState, action) => {
userCodeTab: action.payload
}
case types.GET_COMMIT_RECORD_DETAIL_BY_ID:
tempDetail = action.payload;
tempDetail = action.payload.data;
if (tempDetail['error_msg']) {
tempDetail['error_msg'] = Base64.decode(tempDetail['error_msg']);
}

Loading…
Cancel
Save