Merge branches 'dev_aliyun' and 'dev_item_bank' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_item_bank
commit
ed235ca509
@ -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)
|
||||||
|
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,77 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
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)
|
||||||
|
if new_item.save!
|
||||||
|
item.increment!(:quotes)
|
||||||
|
if item.item_choices.present?
|
||||||
|
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
|
||||||
|
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)
|
||||||
@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
|
@ -0,0 +1,12 @@
|
|||||||
|
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 }
|
||||||
|
validates :duration, numericality: { only_integer: true, greater_than: 0 }
|
||||||
|
|
||||||
|
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,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,6 @@
|
|||||||
|
class ExaminationItem < ApplicationRecord
|
||||||
|
belongs_to :examination_bank, touch: true
|
||||||
|
belongs_to :item_bank, optional: true
|
||||||
|
|
||||||
|
has_many :examination_item_choices, dependent: :destroy
|
||||||
|
end
|
@ -0,0 +1,3 @@
|
|||||||
|
class ExaminationItemChoice < ApplicationRecord
|
||||||
|
belongs_to :examination_item
|
||||||
|
end
|
@ -1,11 +1,18 @@
|
|||||||
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
|
||||||
|
|
||||||
|
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,8 @@
|
|||||||
|
class TagDiscipline < ApplicationRecord
|
||||||
|
belongs_to :sub_discipline
|
||||||
|
has_many :tag_discipline_containers, dependent: :destroy
|
||||||
|
|
||||||
|
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,33 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
items = items.where(item_type: params[:item_type].to_i) 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]
|
||||||
|
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 0, 1, 2
|
||||||
|
5
|
||||||
|
when 6
|
||||||
|
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>
|
@ -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">×</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">×</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">×</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">×</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') %>");
|
@ -0,0 +1,35 @@
|
|||||||
|
case params[:source]
|
||||||
|
when 'subject'
|
||||||
|
disciplines = Discipline.where(subject: 1).includes(subject_sub_disciplines: :subject_tag_disciplines)
|
||||||
|
json.disciplines disciplines do |dis|
|
||||||
|
json.(dis, :id, :name)
|
||||||
|
json.sub_disciplines dis.subject_sub_disciplines do |sub|
|
||||||
|
json.(sub, :id, :name)
|
||||||
|
json.tag_disciplines sub.subject_tag_disciplines do |tag|
|
||||||
|
json.(tag, :id, :name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when 'shixun'
|
||||||
|
disciplines = Discipline.where(shixun: 1).includes(shixun_sub_disciplines: :shixun_tag_disciplines)
|
||||||
|
json.disciplines disciplines do |dis|
|
||||||
|
json.(dis, :id, :name)
|
||||||
|
json.sub_disciplines dis.shixun_sub_disciplines do |sub|
|
||||||
|
json.(sub, :id, :name)
|
||||||
|
json.tag_disciplines sub.shixun_tag_disciplines do |tag|
|
||||||
|
json.(tag, :id, :name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when 'question'
|
||||||
|
disciplines = Discipline.where(question: 1).includes(question_sub_disciplines: :question_tag_disciplines)
|
||||||
|
json.disciplines disciplines do |dis|
|
||||||
|
json.(dis, :id, :name)
|
||||||
|
json.sub_disciplines dis.question_sub_disciplines do |sub|
|
||||||
|
json.(sub, :id, :name)
|
||||||
|
json.tag_disciplines sub.question_tag_disciplines do |tag|
|
||||||
|
json.(tag, :id, :name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,11 @@
|
|||||||
|
json.exams @exams.each do |exam|
|
||||||
|
json.(exam, :id, :name, :difficulty, :quotes)
|
||||||
|
json.question_count exam.question_count
|
||||||
|
json.total_score exam.total_score
|
||||||
|
json.update_time exam.updated_at&.strftime("%Y-%m-%d %H:%M")
|
||||||
|
json.author do
|
||||||
|
json.login exam.user&.login
|
||||||
|
json.name exam.user&.full_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
json.exam_count @exams_count
|
@ -0,0 +1,6 @@
|
|||||||
|
json.(item, :name, :item_type, :difficulty, :public, :quotes)
|
||||||
|
json.analysis item.analysis
|
||||||
|
json.choices item.item_choices do |choice|
|
||||||
|
json.choice_text choice.choice_text
|
||||||
|
json.is_answer choice.is_answer
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
json.discipline do
|
||||||
|
json.(@item.sub_discipline&.discipline, :id, :name)
|
||||||
|
end
|
||||||
|
json.sub_discipline do
|
||||||
|
json.(@item.sub_discipline, :id, :name)
|
||||||
|
end
|
||||||
|
json.tag_disciplines @item.tag_disciplines do |tag|
|
||||||
|
json.(tag, :id, :name)
|
||||||
|
end
|
||||||
|
json.(@item, :id, :name, :item_type, :difficulty)
|
||||||
|
json.analysis @item.analysis
|
||||||
|
json.choices @item.item_choices do |choice|
|
||||||
|
json.choice_text choice.choice_text
|
||||||
|
json.is_answer choice.is_answer
|
||||||
|
end
|
@ -0,0 +1,11 @@
|
|||||||
|
json.items @items.each do |item|
|
||||||
|
json.id item.id
|
||||||
|
json.partial! "item_banks/item", locals: {item: item}
|
||||||
|
json.update_time item.updated_at&.strftime("%Y-%m-%d %H:%M")
|
||||||
|
json.choosed @item_basket_ids.include?(item.id)
|
||||||
|
json.author do
|
||||||
|
json.login item.user&.login
|
||||||
|
json.name item.user&.full_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
json.items_count @items_count
|
@ -0,0 +1,7 @@
|
|||||||
|
json.single_questions_count @single_questions_count
|
||||||
|
json.multiple_questions_count @multiple_questions_count
|
||||||
|
json.judgement_questions_count @judgement_questions_count
|
||||||
|
json.completion_questions_count @completion_questions_count
|
||||||
|
json.subjective_questions_count @subjective_questions_count
|
||||||
|
json.practical_questions_count @practical_questions_count
|
||||||
|
json.program_questions_count @program_questions_count
|
@ -0,0 +1,3 @@
|
|||||||
|
json.status 0
|
||||||
|
json.questions_score @questions_score
|
||||||
|
json.all_score @all_score
|
@ -0,0 +1,38 @@
|
|||||||
|
json.single_questions do
|
||||||
|
json.questions @single_questions.each do |question|
|
||||||
|
json.(question, :id, :position, :score, :item_type)
|
||||||
|
json.partial! "item_banks/item", locals: {item: question.item_bank}
|
||||||
|
end
|
||||||
|
json.questions_score @single_questions.map(&:score).sum
|
||||||
|
json.questions_count @single_questions.size
|
||||||
|
end
|
||||||
|
|
||||||
|
json.multiple_questions do
|
||||||
|
json.questions @multiple_questions.each do |question|
|
||||||
|
json.(question, :id, :position, :score, :item_type)
|
||||||
|
json.partial! "item_banks/item", locals: {item: question.item_bank}
|
||||||
|
end
|
||||||
|
json.questions_score @multiple_questions.map(&:score).sum
|
||||||
|
json.questions_count @multiple_questions.size
|
||||||
|
end
|
||||||
|
|
||||||
|
json.judgement_questions do
|
||||||
|
json.questions @judgement_questions.each do |question|
|
||||||
|
json.(question, :id, :position, :score, :item_type)
|
||||||
|
json.partial! "item_banks/item", locals: {item: question.item_bank}
|
||||||
|
end
|
||||||
|
json.questions_score @judgement_questions.map(&:score).sum
|
||||||
|
json.questions_count @judgement_questions.size
|
||||||
|
end
|
||||||
|
|
||||||
|
json.program_questions do
|
||||||
|
json.questions @program_questions.each do |question|
|
||||||
|
json.(question, :id, :position, :score, :item_type)
|
||||||
|
json.partial! "item_banks/item", locals: {item: question.item_bank}
|
||||||
|
end
|
||||||
|
json.questions_score @program_questions.map(&:score).sum
|
||||||
|
json.questions_count @program_questions.size
|
||||||
|
end
|
||||||
|
|
||||||
|
json.all_score @item_baskets.map(&:score).sum
|
||||||
|
json.all_questions_count @item_baskets.size
|
@ -0,0 +1,3 @@
|
|||||||
|
json.status 0
|
||||||
|
json.questions_score @questions_score
|
||||||
|
json.all_score @all_score
|
@ -0,0 +1,7 @@
|
|||||||
|
class MigrateItemBankColumn < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_column :item_banks, :curriculum_id
|
||||||
|
remove_column :item_banks, :curriculum_direction_id
|
||||||
|
add_column :item_banks, :sub_repertoire_id, :integer, index: true
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
class ChangeItemBankPublicDefault < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
change_column_default :item_banks, :public, 0
|
||||||
|
change_column_default :item_banks, :quotes, 0
|
||||||
|
change_column_default :item_banks, :difficulty, 1
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
class AddPositionScoreToBasket < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :item_baskets, :position, :integer, default: 0
|
||||||
|
add_column :item_baskets, :score, :float, default: 0
|
||||||
|
add_column :item_baskets, :item_type, :integer, default: 0
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,12 @@
|
|||||||
|
class CreateDisciplines < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :disciplines do |t|
|
||||||
|
t.string :name
|
||||||
|
t.boolean :subject
|
||||||
|
t.boolean :shixun
|
||||||
|
t.boolean :question
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,13 @@
|
|||||||
|
class CreateSubDisciplines < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :sub_disciplines do |t|
|
||||||
|
t.references :discipline, index: true
|
||||||
|
t.string :name
|
||||||
|
t.boolean :subject
|
||||||
|
t.boolean :shixun
|
||||||
|
t.boolean :question
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,13 @@
|
|||||||
|
class CreateTagDisciplines < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :tag_disciplines do |t|
|
||||||
|
t.references :sub_discipline, index: true
|
||||||
|
t.string :name
|
||||||
|
t.boolean :subject
|
||||||
|
t.boolean :shixun
|
||||||
|
t.boolean :question
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,6 @@
|
|||||||
|
class MigrateItemBankTagColumn < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_column :item_banks, :sub_repertoire_id
|
||||||
|
add_column :item_banks, :sub_discipline_id, :integer, index: true
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,13 @@
|
|||||||
|
class CreateTagDisciplineContainers < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :tag_discipline_containers do |t|
|
||||||
|
t.references :tag_discipline, index: true
|
||||||
|
t.integer :container_id
|
||||||
|
t.string :container_type
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :tag_discipline_containers, [:container_type, :container_id], name: "index_on_container"
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
class MigrateDisciplinesDefault < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
change_column_default :disciplines, :subject, from: nil, to: 1
|
||||||
|
change_column_default :disciplines, :shixun, from: nil, to: 1
|
||||||
|
change_column_default :disciplines, :question, from: nil, to: 1
|
||||||
|
|
||||||
|
change_column_default :sub_disciplines, :subject, from: nil, to: 1
|
||||||
|
change_column_default :sub_disciplines, :shixun, from: nil, to: 1
|
||||||
|
change_column_default :sub_disciplines, :question, from: nil, to: 1
|
||||||
|
|
||||||
|
change_column_default :tag_disciplines, :subject, from: nil, to: 1
|
||||||
|
change_column_default :tag_disciplines, :shixun, from: nil, to: 1
|
||||||
|
change_column_default :tag_disciplines, :question, from: nil, to: 1
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
class CreateExaminationBanks < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :examination_banks do |t|
|
||||||
|
t.string :name
|
||||||
|
t.integer :difficulty, default: 1
|
||||||
|
t.references :user, index: true
|
||||||
|
t.boolean :public, default: 0
|
||||||
|
t.integer :quotes, default: 0
|
||||||
|
t.references :sub_discipline, index: true
|
||||||
|
t.integer :duration
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
class CreateExaminationItems < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :examination_items do |t|
|
||||||
|
t.references :examination_bank, index: true
|
||||||
|
t.references :item_bank, index: true
|
||||||
|
t.string :name
|
||||||
|
t.integer :item_type, default: 0
|
||||||
|
t.integer :difficulty, default: 1
|
||||||
|
t.float :score, default: 0
|
||||||
|
t.integer :position, default: 0
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,11 @@
|
|||||||
|
class CreateExaminationItemChoices < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :examination_item_choices do |t|
|
||||||
|
t.references :examination_item, index: true
|
||||||
|
t.text :choice_text
|
||||||
|
t.boolean :is_answer, default: 0
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddSubDisciplineIdForHacks < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :hacks, :sub_discipline_id, :integer
|
||||||
|
end
|
||||||
|
end
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue