Merge branch 'dev_jupyter' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_jupyter
commit
c8e270d0d1
@ -0,0 +1,124 @@
|
|||||||
|
$(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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 导入学生
|
||||||
|
var $importDisciplineModal = $('.modal.admin-import-discipline-modal');
|
||||||
|
var $importDisciplineForm = $importDisciplineModal.find('form.admin-import-discipline-form');
|
||||||
|
|
||||||
|
$importDisciplineModal.on('show.bs.modal', function(){
|
||||||
|
resetFileInputFunc($importDisciplineModal.find('.upload-file-input'));
|
||||||
|
$importDisciplineModal.find('.file-names').html('选择文件');
|
||||||
|
$importDisciplineModal.find('.upload-file-input').trigger('click');
|
||||||
|
});
|
||||||
|
$importDisciplineModal.on('change', '.upload-file-input', function(e){
|
||||||
|
var file = $(this)[0].files[0];
|
||||||
|
$importDisciplineModal.find('.file-names').html(file ? file.name : '请选择文件');
|
||||||
|
});
|
||||||
|
|
||||||
|
var importDisciplineFormValid = function(){
|
||||||
|
if($importDisciplineForm.find('input[name="file"]').val() == undefined || $importDisciplineForm.find('input[name="file"]').val().length == 0){
|
||||||
|
$importDisciplineForm.find('.error').html('请选择文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var buildResultMessage = function(data){
|
||||||
|
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
|
||||||
|
|
||||||
|
return messageHtml;
|
||||||
|
};
|
||||||
|
|
||||||
|
$importDisciplineModal.on('click', '.submit-btn', function(){
|
||||||
|
$importDisciplineForm.find('.error').html('');
|
||||||
|
|
||||||
|
if (importDisciplineFormValid()) {
|
||||||
|
$('body').mLoading({ text: '正在导入...' });
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
url: '/admins/import_disciplines',
|
||||||
|
data: new FormData($importDisciplineForm[0]),
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
success: function(data){
|
||||||
|
$('body').mLoading('destroy');
|
||||||
|
$importDisciplineModal.modal('hide');
|
||||||
|
|
||||||
|
showMessageModal(buildResultMessage(data), function(){
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function(res){
|
||||||
|
$('body').mLoading('destroy');
|
||||||
|
var data = res.responseJSON;
|
||||||
|
$importDisciplineForm.find('.error').html(data.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
@ -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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +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,10 @@
|
|||||||
|
class Admins::ImportDisciplinesController < Admins::BaseController
|
||||||
|
def create
|
||||||
|
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
|
result = Admins::ImportDisciplineService.call(params[:file].to_io)
|
||||||
|
render_ok(result)
|
||||||
|
rescue Admins::ImportDisciplineService::Error => ex
|
||||||
|
render_error(ex)
|
||||||
|
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, user_id: current_user.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
|
@ -0,0 +1,6 @@
|
|||||||
|
class DisciplinesController < ApplicationController
|
||||||
|
|
||||||
|
def index
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,85 @@
|
|||||||
|
class ExaminationBanksController < ApplicationController
|
||||||
|
include PaginateHelper
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_exam, except: [:index, :create]
|
||||||
|
before_action :edit_auth, only: [:update, :destroy, :set_public]
|
||||||
|
|
||||||
|
def index
|
||||||
|
exams = ExaminationBankQuery.call(params)
|
||||||
|
@exams_count = exams.size
|
||||||
|
@exams = paginate exams.includes(:user, :examination_items)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@items = @exam.examination_items
|
||||||
|
@single_questions = @items.where(item_type: "SINGLE")
|
||||||
|
@multiple_questions = @items.where(item_type: "MULTIPLE")
|
||||||
|
@judgement_questions = @items.where(item_type: "JUDGMENT")
|
||||||
|
@program_questions = @items.where(item_type: "PROGRAM")
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
exam = ExaminationBank.new(user: current_user)
|
||||||
|
# 保存试卷基础信息
|
||||||
|
exam = ExaminationBanks::SaveExaminationBankService.call(exam, form_params)
|
||||||
|
|
||||||
|
# 将试题篮中的试题发送到试卷,试卷的题目与试题独立
|
||||||
|
current_user.item_baskets.includes(:item_bank).each do |basket|
|
||||||
|
item = basket.item_bank
|
||||||
|
if item.present?
|
||||||
|
new_item = ExaminationItem.new(examination_bank: exam, item_bank: item, name: item.name, item_type: item.item_type,
|
||||||
|
difficulty: item.difficulty, score: basket.score, position: basket.position)
|
||||||
|
new_item.save!
|
||||||
|
item.increment!(:quotes)
|
||||||
|
|
||||||
|
if item.item_type == "PROGRAM"
|
||||||
|
new_hack = item.container.fork
|
||||||
|
new_item.update_attributes!(container: new_hack)
|
||||||
|
else
|
||||||
|
new_item.examination_item_analysis.create!(analysis: item.analysis)
|
||||||
|
item.item_choices.each do |choice|
|
||||||
|
new_item.examination_item_choices << ExaminationItemChoice.new(choice_text: choice.choice_text, is_answer: choice.is_answer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
current_user.item_baskets.destroy_all
|
||||||
|
end
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@exam.destroy!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_public
|
||||||
|
tip_exception(-1, "该试卷已公开") if @exam.public?
|
||||||
|
@exam.update_attributes!(public: 1)
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def form_params
|
||||||
|
params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_exam
|
||||||
|
@exam = ExaminationBank.find_by!(id: params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_auth
|
||||||
|
current_user.admin_or_business? || @exam.user == current_user
|
||||||
|
end
|
||||||
|
end
|
@ -1,14 +1,58 @@
|
|||||||
class LibrariesController < ApplicationController
|
class ItemBanksController < ApplicationController
|
||||||
include PaginateHelper
|
include PaginateHelper
|
||||||
|
before_action :require_login
|
||||||
|
before_action :find_item, except: [:index, :create]
|
||||||
|
before_action :edit_auth, only: [:update, :destroy, :set_public]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
default_sort('updated_at', 'desc')
|
items = ItemBankQuery.call(params)
|
||||||
|
@items_count = items.size
|
||||||
@items = ItemBankQuery.call(params)
|
@items = paginate items.includes(:item_analysis, :user, :container)
|
||||||
@items = paginate courses.includes(:school, :students, :attachments, :homework_commons, teacher: :user_extension)
|
@item_basket_ids = current_user.item_baskets.pluck(:item_bank_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
item = ItemBank.new(user: current_user)
|
||||||
|
ItemBanks::SaveItemService.call(item, form_params)
|
||||||
|
render_ok
|
||||||
|
rescue ApplicationService::Error => ex
|
||||||
|
render_error(ex.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
ItemBanks::SaveItemService.call(@item, form_params)
|
||||||
|
render_ok
|
||||||
|
rescue ApplicationService::Error => ex
|
||||||
|
render_error(ex.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@item.destroy!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_public
|
||||||
|
tip_exception(-1, "该试题已公开") if @item.public?
|
||||||
|
@item.update_attributes!(public: 1)
|
||||||
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_item
|
||||||
|
@item = ItemBank.find_by!(id: params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_auth
|
||||||
|
current_user.admin_or_business? || @item.user == current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
def form_params
|
||||||
|
params.permit(:discipline_id, :sub_discipline_id, :item_type, :difficulty, :name, :analysis, tag_discipline_id: [], choices: %i[choice_text is_answer])
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
@ -0,0 +1,90 @@
|
|||||||
|
class ItemBasketsController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :validate_score, only: [:set_score, :batch_set_score]
|
||||||
|
helper_method :current_basket
|
||||||
|
|
||||||
|
def index
|
||||||
|
@item_baskets = current_user.item_baskets
|
||||||
|
@single_questions = @item_baskets.where(item_type: "SINGLE")
|
||||||
|
@multiple_questions = @item_baskets.where(item_type: "MULTIPLE")
|
||||||
|
@judgement_questions = @item_baskets.where(item_type: "JUDGMENT")
|
||||||
|
@program_questions = @item_baskets.where(item_type: "PROGRAM")
|
||||||
|
end
|
||||||
|
|
||||||
|
def basket_list
|
||||||
|
@single_questions_count = current_user.item_baskets.where(item_type: "SINGLE").count
|
||||||
|
@multiple_questions_count = current_user.item_baskets.where(item_type: "MULTIPLE").count
|
||||||
|
@judgement_questions_count = current_user.item_baskets.where(item_type: "JUDGMENT").count
|
||||||
|
@completion_questions_count = current_user.item_baskets.where(item_type: "COMPLETION").count
|
||||||
|
@subjective_questions_count = current_user.item_baskets.where(item_type: "SUBJECTIVE").count
|
||||||
|
@practical_questions_count = current_user.item_baskets.where(item_type: "PRACTICAL").count
|
||||||
|
@program_questions_count = current_user.item_baskets.where(item_type: "PROGRAM").count
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
ItemBaskets::SaveItemBasketService.call(current_user, create_params)
|
||||||
|
render_ok
|
||||||
|
rescue ApplicationService::Error => ex
|
||||||
|
render_error(ex.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
item = current_user.item_baskets.find_by!(item_bank_id: params[:id])
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
current_user.item_baskets.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1")
|
||||||
|
item.destroy!
|
||||||
|
end
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_item_type
|
||||||
|
baskets = ItemBasket.where(item_type: params[:item_type])
|
||||||
|
baskets.destroy_all
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_score
|
||||||
|
current_basket.update_attributes!(score: params[:score])
|
||||||
|
@questions_score = current_user.item_baskets.where(item_type: current_basket.item_type).pluck(:score).sum
|
||||||
|
@all_score = current_user.item_baskets.pluck(:score).sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def batch_set_score
|
||||||
|
current_user.item_baskets.where(item_type: params[:item_type]).update_all(score: params[:score])
|
||||||
|
@questions_score = current_user.item_baskets.where(item_type: params[:item_type]).pluck(:score).sum
|
||||||
|
@all_score = current_user.item_baskets.pluck(:score).sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def adjust_position
|
||||||
|
same_items = current_user.item_baskets.where(item_type: current_basket.item_type)
|
||||||
|
max_position = same_items.size
|
||||||
|
tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
if params[:position].to_i > current_basket.position
|
||||||
|
same_items.where("position > #{current_basket.position} and position <= #{params[:position].to_i}").update_all("position=position-1")
|
||||||
|
current_basket.update_attributes!(position: params[:position])
|
||||||
|
elsif params[:position].to_i < current_basket.position
|
||||||
|
same_items.where("position < #{current_basket.position} and position >= #{params[:position].to_i}").update_all("position=position+1")
|
||||||
|
current_basket.update_attributes!(position: params[:position])
|
||||||
|
else
|
||||||
|
return normal_status(-1, "排序无变化")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_params
|
||||||
|
params.permit(item_ids: [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_basket
|
||||||
|
@_current_basket = current_user.item_baskets.find_by!(id: params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_score
|
||||||
|
tip_exception("分值不能为空") unless params[:score].present?
|
||||||
|
tip_exception("分值需大于0") unless params[:score].to_f > 0
|
||||||
|
end
|
||||||
|
end
|
@ -1,4 +1,10 @@
|
|||||||
class MainController < ApplicationController
|
class MainController < ApplicationController
|
||||||
|
skip_before_action :check_sign
|
||||||
|
|
||||||
|
def first_stamp
|
||||||
|
render :json => { status: 0, message: Time.now.to_i }
|
||||||
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render file: 'public/react/build/index.html', :layout => false
|
render file: 'public/react/build/index.html', :layout => false
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
class TagDisciplinesController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
|
||||||
|
def create
|
||||||
|
sub_discipline = SubDiscipline.find_by!(id: params[:sub_discipline_id])
|
||||||
|
tag_discipline = TagDiscipline.create!(name: params[:name].to_s.strip, sub_discipline: sub_discipline, user_id: current_user.id)
|
||||||
|
render_ok({tag_discipline_id: tag_discipline.id})
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
class ExaminationBanks::SaveExamForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :discipline_id, :sub_discipline_id, :difficulty, :name, :duration, :tag_discipline_id
|
||||||
|
|
||||||
|
validates :discipline_id, presence: true
|
||||||
|
validates :sub_discipline_id, presence: true
|
||||||
|
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
|
||||||
|
validates :name, presence: true, length: { maximum: 60 }
|
||||||
|
validate :validate_duration
|
||||||
|
|
||||||
|
def validate_duration
|
||||||
|
raise '时长应为大于0的整数' if duration.present? && duration.to_i < 1
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,33 @@
|
|||||||
|
class ItemBanks::SaveItemForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :discipline_id, :sub_discipline_id, :item_type, :difficulty, :name, :analysis, :tag_discipline_id, :choices
|
||||||
|
|
||||||
|
validates :discipline_id, presence: true
|
||||||
|
validates :sub_discipline_id, presence: true
|
||||||
|
validates :item_type, presence: true, inclusion: {in: %W(SINGLE MULTIPLE JUDGMENT COMPLETION SUBJECTIVE PRACTICAL PROGRAM)}
|
||||||
|
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
|
||||||
|
validates :name, presence: true, length: { maximum: 1000 }
|
||||||
|
validates :analysis, length: { maximum: 1000 }
|
||||||
|
|
||||||
|
def validate!
|
||||||
|
super
|
||||||
|
return unless errors.blank?
|
||||||
|
choices.each { |item| SubForm.new(item).validate! } if %W(SINGLE MULTIPLE JUDGMENT).include?(item_type)
|
||||||
|
return unless errors.blank?
|
||||||
|
if [0, 2].include?(item_type) && choices.pluck(:is_answer).select{|item| item == 1}.length > 1
|
||||||
|
raise("正确答案只能有一个")
|
||||||
|
elsif item_type == 1 && choices.pluck(:is_answer).select{|item| item == 1}.length <= 1
|
||||||
|
raise("多选题至少有两个正确答案")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class SubForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :choice_text, :is_answer
|
||||||
|
|
||||||
|
validates :choice_text, presence: true, length: { maximum: 100 }
|
||||||
|
validates :is_answer, presence: true, inclusion: {in: 0..1}, numericality: { only_integer: true }
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,16 @@
|
|||||||
|
class Admins::ImportDisciplineExcel < BaseImportXlsx
|
||||||
|
DisciplineData = Struct.new(:discipline_name, :sub_discipline_name)
|
||||||
|
|
||||||
|
def read_each(&block)
|
||||||
|
sheet.each_row_streaming(pad_cells: true, offset: 2) do |row|
|
||||||
|
data = row.map(&method(:cell_value))[1..2]
|
||||||
|
block.call DisciplineData.new(*data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cell_value(obj)
|
||||||
|
obj&.cell_value
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,20 @@
|
|||||||
|
# 作业的一键评阅
|
||||||
|
class HomeworkBatchCommentJob < ApplicationJob
|
||||||
|
queue_as :default
|
||||||
|
|
||||||
|
def perform(comment, hidden_comment, work_ids, homework_id, user_id)
|
||||||
|
# Do something later
|
||||||
|
homework = HomeworkCommon.find_by(id: homework_id)
|
||||||
|
return if homework.blank?
|
||||||
|
|
||||||
|
attrs = %i[student_work_id challenge_id user_id comment hidden_comment batch_comment created_at updated_at]
|
||||||
|
|
||||||
|
same_attrs = {challenge_id: 0, user_id: user_id, comment: comment, hidden_comment: hidden_comment, batch_comment: 1}
|
||||||
|
|
||||||
|
ShixunWorkComment.bulk_insert(*attrs) do |worker|
|
||||||
|
work_ids.each do |work_id|
|
||||||
|
worker.add same_attrs.merge(student_work_id: work_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
class Discipline < ApplicationRecord
|
||||||
|
has_many :sub_disciplines, dependent: :destroy
|
||||||
|
|
||||||
|
has_many :shixun_sub_disciplines, -> { where("shixun = 1") }, class_name: "SubDiscipline"
|
||||||
|
has_many :subject_sub_disciplines, -> { where("subject = 1") }, class_name: "SubDiscipline"
|
||||||
|
has_many :question_sub_disciplines, -> { where("question = 1") }, class_name: "SubDiscipline"
|
||||||
|
end
|
@ -0,0 +1,17 @@
|
|||||||
|
class ExaminationBank < ApplicationRecord
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :sub_discipline
|
||||||
|
|
||||||
|
has_many :tag_discipline_containers, as: :container, dependent: :destroy
|
||||||
|
has_many :tag_disciplines, through: :tag_discipline_containers
|
||||||
|
|
||||||
|
has_many :examination_items, dependent: :destroy
|
||||||
|
|
||||||
|
def question_count
|
||||||
|
examination_items.size
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_score
|
||||||
|
examination_items.pluck(:score).sum
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,27 @@
|
|||||||
|
class ExaminationItem < ApplicationRecord
|
||||||
|
enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
|
||||||
|
|
||||||
|
belongs_to :examination_bank, touch: true
|
||||||
|
belongs_to :item_bank, optional: true
|
||||||
|
|
||||||
|
has_many :examination_item_choices, dependent: :destroy
|
||||||
|
has_one :examination_item_analysis, dependent: :destroy
|
||||||
|
belongs_to :container, polymorphic: true, optional: true
|
||||||
|
|
||||||
|
def analysis
|
||||||
|
examination_item_analysis&.analysis
|
||||||
|
end
|
||||||
|
|
||||||
|
def item_choices
|
||||||
|
examination_item_choices
|
||||||
|
end
|
||||||
|
|
||||||
|
def public
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
def quotes
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,3 @@
|
|||||||
|
class ExaminationItemAnalysis < ApplicationRecord
|
||||||
|
belongs_to :examination_item
|
||||||
|
end
|
@ -0,0 +1,3 @@
|
|||||||
|
class ExaminationItemChoice < ApplicationRecord
|
||||||
|
belongs_to :examination_item
|
||||||
|
end
|
@ -1,11 +1,20 @@
|
|||||||
class ItemBank < ApplicationRecord
|
class ItemBank < ApplicationRecord
|
||||||
# difficulty: 1 简单 2 适中 3 困难
|
# difficulty: 1 简单 2 适中 3 困难
|
||||||
# item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程
|
|
||||||
enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
|
enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
|
||||||
|
# item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
belongs_to :sub_discipline
|
||||||
|
|
||||||
has_one :item_analysis, dependent: :destroy
|
has_one :item_analysis, dependent: :destroy
|
||||||
has_many :item_choices, dependent: :destroy
|
has_many :item_choices, dependent: :destroy
|
||||||
has_many :item_baskets, dependent: :destroy
|
has_many :item_baskets, dependent: :destroy
|
||||||
|
has_many :tag_discipline_containers, as: :container, dependent: :destroy
|
||||||
|
has_many :tag_disciplines, through: :tag_discipline_containers
|
||||||
|
|
||||||
|
belongs_to :container, polymorphic: true, optional: true
|
||||||
|
|
||||||
|
def analysis
|
||||||
|
item_analysis&.analysis
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,14 @@
|
|||||||
class ItemBasket < ApplicationRecord
|
class ItemBasket < ApplicationRecord
|
||||||
|
enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
|
||||||
|
|
||||||
belongs_to :item_bank
|
belongs_to :item_bank
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
|
def all_score
|
||||||
|
User.current.item_baskets.map(&:score).sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def question_count
|
||||||
|
User.current.item_baskets.size
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
class SubDiscipline < ApplicationRecord
|
||||||
|
belongs_to :discipline
|
||||||
|
has_many :tag_disciplines, dependent: :destroy
|
||||||
|
has_one :hack
|
||||||
|
|
||||||
|
has_many :shixun_tag_disciplines, -> { where("shixun = 1") }, class_name: "TagDiscipline"
|
||||||
|
has_many :subject_tag_disciplines, -> { where("subject = 1") }, class_name: "TagDiscipline"
|
||||||
|
has_many :question_tag_disciplines, -> { where("question = 1") }, class_name: "TagDiscipline"
|
||||||
|
end
|
@ -0,0 +1,11 @@
|
|||||||
|
class TagDiscipline < ApplicationRecord
|
||||||
|
belongs_to :sub_discipline
|
||||||
|
belongs_to :user, optional: true
|
||||||
|
has_many :tag_discipline_containers, dependent: :destroy
|
||||||
|
|
||||||
|
validates_presence_of :name
|
||||||
|
|
||||||
|
def discipline
|
||||||
|
sub_discipline&.discipline
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,5 @@
|
|||||||
|
class TagDisciplineContainer < ApplicationRecord
|
||||||
|
belongs_to :tag_discipline
|
||||||
|
|
||||||
|
belongs_to :container, polymorphic: true, optional: true
|
||||||
|
end
|
@ -0,0 +1,32 @@
|
|||||||
|
class ExaminationBankQuery < ApplicationQuery
|
||||||
|
include CustomSortable
|
||||||
|
attr_reader :params
|
||||||
|
|
||||||
|
sort_columns :updated_at, default_by: :updated_at, default_direction: :desc, default_table: 'examination_banks'
|
||||||
|
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
if params[:public].to_i == 1
|
||||||
|
exams = ExaminationBank.where(public: 1)
|
||||||
|
elsif params[:public].to_i == 0
|
||||||
|
exams = ExaminationBank.where(user_id: User.current.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:tag_discipline_id].present?
|
||||||
|
exams = exams.joins(:tag_discipline_containers).where(tag_discipline_containers: {tag_discipline_id: params[:tag_discipline_id]})
|
||||||
|
elsif params[:sub_discipline_id].present?
|
||||||
|
exams = exams.where(sub_discipline_id: params[:sub_discipline_id])
|
||||||
|
elsif params[:discipline_id].present?
|
||||||
|
exams = exams.joins(:sub_discipline).where(sub_disciplines: {discipline_id: params[:discipline_id]})
|
||||||
|
end
|
||||||
|
|
||||||
|
exams = exams.where(difficulty: params[:difficulty].to_i) if params[:difficulty].present?
|
||||||
|
|
||||||
|
exams = exams.where("name like ?", "%#{params[:keyword].strip}%") if params[:keyword].present?
|
||||||
|
|
||||||
|
custom_sort(exams, params[:sort_by], params[:sort_direction])
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,37 @@
|
|||||||
|
class ItemBankQuery < ApplicationQuery
|
||||||
|
include CustomSortable
|
||||||
|
attr_reader :params
|
||||||
|
|
||||||
|
sort_columns :updated_at, default_by: :updated_at, default_direction: :desc, default_table: 'item_banks'
|
||||||
|
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
if params[:public].to_i == 1
|
||||||
|
items = ItemBank.where(public: 1)
|
||||||
|
elsif params[:public].to_i == 0
|
||||||
|
items = ItemBank.where(user_id: User.current.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:tag_discipline_id].present?
|
||||||
|
items = items.joins(:tag_discipline_containers).where(tag_discipline_containers: {tag_discipline_id: params[:tag_discipline_id]})
|
||||||
|
elsif params[:sub_discipline_id].present?
|
||||||
|
items = items.where(sub_discipline_id: params[:sub_discipline_id])
|
||||||
|
elsif params[:discipline_id].present?
|
||||||
|
items = items.joins(:sub_discipline).where(sub_disciplines: {discipline_id: params[:discipline_id]})
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:oj_status].present? && params[:item_type] == "PROGRAM"
|
||||||
|
items = items.joins("join hacks on hacks.id=item_banks.container_id and item_banks.container_type='Hack'").where(hacks: {status: params[:oj_status]})
|
||||||
|
end
|
||||||
|
|
||||||
|
items = items.where(item_type: params[:item_type]) if params[:item_type].present?
|
||||||
|
items = items.where(difficulty: params[:difficulty].to_i) if params[:difficulty].present?
|
||||||
|
|
||||||
|
items = items.where("name like ?", "%#{params[:keyword].strip}%") if params[:keyword].present?
|
||||||
|
|
||||||
|
custom_sort(items, params[:sort_by], params[:sort_direction])
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,52 @@
|
|||||||
|
class Admins::ImportDisciplineService < ApplicationService
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
|
attr_reader :file, :result
|
||||||
|
|
||||||
|
def initialize(file)
|
||||||
|
@file = file
|
||||||
|
@result = { success: 0, fail: [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, '文件不存在' if file.blank?
|
||||||
|
|
||||||
|
excel = Admins::ImportDisciplineExcel.new(file)
|
||||||
|
excel.read_each(&method(:save_discipline))
|
||||||
|
|
||||||
|
result
|
||||||
|
rescue ApplicationImport::Error => ex
|
||||||
|
raise Error, ex.message
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def save_discipline(data)
|
||||||
|
count = 0
|
||||||
|
discipline_name = data.discipline_name.to_s.strip
|
||||||
|
sub_discipline_name = data.sub_discipline_name.to_s.strip
|
||||||
|
|
||||||
|
return unless discipline_name.present?
|
||||||
|
discipline = Discipline.find_by(name: discipline_name)
|
||||||
|
if discipline.blank?
|
||||||
|
discipline = Discipline.create!(name: discipline_name)
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if sub_discipline_name.present?
|
||||||
|
sub_discipline = SubDiscipline.find_by(name: discipline_name, discipline: discipline)
|
||||||
|
if sub_discipline.blank?
|
||||||
|
SubDiscipline.create!(name: sub_discipline_name, discipline: discipline)
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result[:success] += count
|
||||||
|
rescue Exception => ex
|
||||||
|
fail_data = data.as_json
|
||||||
|
fail_data[:data] = fail_data.values.join(',')
|
||||||
|
fail_data[:message] = ex.message
|
||||||
|
|
||||||
|
result[:fail] << fail_data
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,30 @@
|
|||||||
|
class ExaminationBanks::SaveExaminationBankService < ApplicationService
|
||||||
|
attr_reader :exam, :params
|
||||||
|
|
||||||
|
def initialize(exam, params)
|
||||||
|
@exam = exam
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
ExaminationBanks::SaveExamForm.new(params).validate!
|
||||||
|
|
||||||
|
exam.name = params[:name].to_s.strip
|
||||||
|
exam.difficulty = params[:difficulty]
|
||||||
|
exam.duration = params[:duration].present? ? params[:duration].to_i : nil
|
||||||
|
exam.sub_discipline_id = params[:sub_discipline_id]
|
||||||
|
exam.save!
|
||||||
|
|
||||||
|
# 知识点的创建
|
||||||
|
new_tag_discipline_ids = params[:tag_discipline_id] || []
|
||||||
|
old_tag_discipline_ids = exam.tag_discipline_containers.pluck(:tag_discipline_id)
|
||||||
|
delete_tag_discipline_ids = old_tag_discipline_ids - new_tag_discipline_ids
|
||||||
|
create_tag_discipline_ids = new_tag_discipline_ids - old_tag_discipline_ids
|
||||||
|
exam.tag_discipline_containers.where(tag_discipline_id: delete_tag_discipline_ids).destroy_all
|
||||||
|
create_tag_discipline_ids.each do |tag_id|
|
||||||
|
exam.tag_discipline_containers << TagDisciplineContainer.new(tag_discipline_id: tag_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
exam
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,58 @@
|
|||||||
|
class ItemBanks::SaveItemService < ApplicationService
|
||||||
|
attr_reader :item, :params
|
||||||
|
|
||||||
|
def initialize(item, params)
|
||||||
|
@item = item
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
new_record = item.new_record?
|
||||||
|
raise("不能更改题型") if !new_record && item.item_type != params[:item_type]
|
||||||
|
ItemBanks::SaveItemForm.new(params).validate!
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
item.item_type = params[:item_type] if new_record
|
||||||
|
item.difficulty = params[:difficulty]
|
||||||
|
item.sub_discipline_id = params[:sub_discipline_id]
|
||||||
|
item.name = params[:name].to_s.strip
|
||||||
|
item.save!
|
||||||
|
|
||||||
|
analysis = item.item_analysis || ItemAnalysis.new(item_bank_id: item.id)
|
||||||
|
analysis.analysis = params[:analysis].blank? ? nil : params[:analysis].strip
|
||||||
|
analysis.save
|
||||||
|
|
||||||
|
# 知识点的创建
|
||||||
|
new_tag_discipline_ids = params[:tag_discipline_id]
|
||||||
|
old_tag_discipline_ids = item.tag_discipline_containers.pluck(:tag_discipline_id)
|
||||||
|
delete_tag_discipline_ids = old_tag_discipline_ids - new_tag_discipline_ids
|
||||||
|
create_tag_discipline_ids = new_tag_discipline_ids - old_tag_discipline_ids
|
||||||
|
item.tag_discipline_containers.where(tag_discipline_id: delete_tag_discipline_ids).destroy_all
|
||||||
|
create_tag_discipline_ids.each do |tag_id|
|
||||||
|
item.tag_discipline_containers << TagDisciplineContainer.new(tag_discipline_id: tag_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
# 选项的创建
|
||||||
|
if %W(SINGLE MULTIPLE JUDGMENT).include?(item.item_type)
|
||||||
|
old_choices = item.item_choices
|
||||||
|
new_choices = params[:choices]
|
||||||
|
|
||||||
|
new_choices.each_with_index do |choice, index|
|
||||||
|
choice_item = old_choices[index] || ItemChoice.new(item_bank_id: item.id)
|
||||||
|
choice_item.choice_text = choice[:choice_text]
|
||||||
|
choice_item.is_answer = choice[:is_answer]
|
||||||
|
choice_item.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
if old_choices.length > new_choices.length
|
||||||
|
old_choices[new_choices.length..(old_choices.length-1)].each do |old_choice|
|
||||||
|
old_choice.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
item
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,47 @@
|
|||||||
|
class ItemBaskets::SaveItemBasketService < ApplicationService
|
||||||
|
attr_reader :user, :params
|
||||||
|
|
||||||
|
def initialize(user, params)
|
||||||
|
@user = user
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise("请选择试题") if params[:item_ids].blank?
|
||||||
|
|
||||||
|
# 只能选用公共题库或是自己的题库
|
||||||
|
items = ItemBank.where(public: 1).or(ItemBank.where(user_id: user.id))
|
||||||
|
|
||||||
|
# 已选到过试题篮的不重复选用
|
||||||
|
item_ids = params[:item_ids] - user.item_baskets.pluck(:item_bank_id)
|
||||||
|
items.where(id: item_ids).each do |item|
|
||||||
|
new_item = ItemBasket.new(user_id: user.id, item_bank_id: item.id, item_type: item.item_type)
|
||||||
|
new_item.score = item_score item.item_type
|
||||||
|
new_item.position = item_position item.item_type
|
||||||
|
new_item.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def item_score item_type
|
||||||
|
if user.item_baskets.where(item_type: item_type).last.present?
|
||||||
|
score = user.item_baskets.where(item_type: item_type).last.score
|
||||||
|
else
|
||||||
|
score =
|
||||||
|
case item_type
|
||||||
|
when "SINGLE", "MULTIPLE", "JUDGMENT"
|
||||||
|
5
|
||||||
|
when "PROGRAM"
|
||||||
|
10
|
||||||
|
else
|
||||||
|
5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
score
|
||||||
|
end
|
||||||
|
|
||||||
|
def item_position item_type
|
||||||
|
user.item_baskets.where(item_type: item_type).last&.position.to_i + 1
|
||||||
|
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,17 @@
|
|||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('课程方向', admins_disciplines_path) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container discipline-list-form rig">
|
||||||
|
<div class="flex-1">
|
||||||
|
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-discipline-modal' } %>
|
||||||
|
</div>
|
||||||
|
<%= javascript_void_link '导入数据', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-import-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' %>
|
||||||
|
<%= render partial: 'admins/disciplines/shared/import_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">×</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">×</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,30 @@
|
|||||||
|
<div class="modal fade admin-import-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="admin-import-discipline-form" enctype="multipart/form-data">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">文件</span>
|
||||||
|
</div>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" name="file" class="upload-file-input" id="import-discipline-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
|
||||||
|
<label class="custom-file-label file-names" for="import-discipline-input">选择文件</label>
|
||||||
|
</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,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>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue