commit
e47c7aec0f
@ -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,22 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-examination-authentications-index-page').length > 0) {
|
||||
var $searchFrom = $('.examination-authentication-list-form');
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
|
||||
$searchFrom.on('click', '.search-form-tab', function(){
|
||||
var $link = $(this);
|
||||
|
||||
$searchFrom.find('input[name="keyword"]').val('');
|
||||
$searchFrom.find('select[name="status"]').val('processed');
|
||||
|
||||
if($link.data('value') === 'processed'){
|
||||
$('.batch-action-container').hide();
|
||||
$searchFrom.find('.status-filter').show();
|
||||
} else {
|
||||
$('.batch-action-container').show();
|
||||
$searchFrom.find('.status-filter').hide();
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,22 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-item-authentications-index-page').length > 0) {
|
||||
var $searchFrom = $('.item-authentication-list-form');
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
|
||||
$searchFrom.on('click', '.search-form-tab', function(){
|
||||
var $link = $(this);
|
||||
|
||||
$searchFrom.find('input[name="keyword"]').val('');
|
||||
$searchFrom.find('select[name="status"]').val('processed');
|
||||
|
||||
if($link.data('value') === 'processed'){
|
||||
$('.batch-action-container').hide();
|
||||
$searchFrom.find('.status-filter').show();
|
||||
} else {
|
||||
$('.batch-action-container').show();
|
||||
$searchFrom.find('.status-filter').hide();
|
||||
$searchFrom.find('select[name="status"]').val('pending');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -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,2 @@
|
||||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
@ -0,0 +1,3 @@
|
||||
// Place all the styles related to the edu_datas controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
@ -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,30 @@
|
||||
class Admins::ExaminationAuthenticationsController < Admins::BaseController
|
||||
def index
|
||||
params[:status] ||= 'pending'
|
||||
params[:sort_direction] = params[:status] == 'pending' ? 'asc' : 'desc'
|
||||
|
||||
applies = Admins::ApplyItemBankQuery.call(params.merge(type: "ExaminationBank"))
|
||||
|
||||
@applies = paginate applies.preload(user: { user_extension: [:school, :department] })
|
||||
end
|
||||
|
||||
def agree
|
||||
ActiveRecord::Base.transaction do
|
||||
exam = ExaminationBank.find current_apply.container_id
|
||||
current_apply.update!(status: 1)
|
||||
exam.update!(public: 0)
|
||||
end
|
||||
render_success_js
|
||||
end
|
||||
|
||||
def refuse
|
||||
current_apply.update!(status: 2)
|
||||
render_success_js
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_apply
|
||||
@_current_apply ||= ApplyAction.find(params[:id])
|
||||
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,34 @@
|
||||
class Admins::ItemAuthenticationsController < Admins::BaseController
|
||||
def index
|
||||
params[:status] ||= 'pending'
|
||||
params[:sort_direction] = params[:status] == 'pending' ? 'asc' : 'desc'
|
||||
|
||||
applies = Admins::ApplyItemBankQuery.call(params.merge(type: "ItemBank"))
|
||||
|
||||
@applies = paginate applies.preload(user: { user_extension: [:school, :department] })
|
||||
end
|
||||
|
||||
def show
|
||||
@item = ItemBank.find current_apply.container_id
|
||||
end
|
||||
|
||||
def agree
|
||||
ActiveRecord::Base.transaction do
|
||||
item = ItemBank.find current_apply.container_id
|
||||
current_apply.update!(status: 1)
|
||||
item.update!(public: 0)
|
||||
end
|
||||
render_success_js
|
||||
end
|
||||
|
||||
def refuse
|
||||
current_apply.update!(status: 2)
|
||||
render_success_js
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_apply
|
||||
@_current_apply ||= ApplyAction.find(params[:id])
|
||||
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,29 @@
|
||||
class EduDatasController < ApplicationController
|
||||
before_action :find_game
|
||||
skip_before_action :user_setup
|
||||
skip_before_action :setup_laboratory
|
||||
# layout :false
|
||||
include GitHelper
|
||||
|
||||
# params[:game_id]
|
||||
def game
|
||||
@shixun = @challenge.shixun
|
||||
@shixun_env = @shixun.mirror_name
|
||||
@shixun_tags = @challenge.challenge_tags.map(&:name)
|
||||
end
|
||||
|
||||
def code_lines
|
||||
path = @challenge.path
|
||||
myshixun = @game.myshixun
|
||||
# content = git_fle_content(myshixun.repo_path, path) || ""
|
||||
@content = {"content":"#coding=utf-8\n\n#请在此处添加代码完成输出“Hello Python”,注意要区分大小写!\n###### Begin ######\n\n\n\n###### End ######\n\n"}
|
||||
@content[:content].include?("Begin")
|
||||
end
|
||||
|
||||
private
|
||||
def find_game
|
||||
game_id = params[:game_id]
|
||||
@game = Game.find(game_id)
|
||||
@challenge = @game.challenge
|
||||
end
|
||||
end
|
@ -0,0 +1,78 @@
|
||||
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
|
||||
new_item.new_item(item, exam, basket.score, basket.position)
|
||||
end
|
||||
end
|
||||
|
||||
current_user.item_baskets.destroy_all
|
||||
end
|
||||
render_ok
|
||||
rescue ApplicationService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def edit; end
|
||||
|
||||
def update
|
||||
ExaminationBanks::SaveExaminationBankService.call(@exam, form_params)
|
||||
render_ok
|
||||
rescue ApplicationService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@exam.destroy!
|
||||
render_ok
|
||||
end
|
||||
|
||||
def set_public
|
||||
tip_exception(-1, "该试卷已公开") if @exam.public?
|
||||
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank").exists?
|
||||
ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id)
|
||||
# @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
|
@ -0,0 +1,84 @@
|
||||
class ExaminationItemsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :validate_score, only: [:set_score, :batch_set_score]
|
||||
before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type]
|
||||
before_action :find_item, except: [:create, :batch_set_score, :delete_item_type]
|
||||
before_action :edit_auth
|
||||
|
||||
def create
|
||||
ExaminationItems::SaveItemService.call(current_user, create_params, @exam)
|
||||
render_ok
|
||||
rescue ApplicationService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
ActiveRecord::Base.transaction do
|
||||
@exam.examination_items.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
|
||||
items = @exam.examination_items.where(item_type: params[:item_type])
|
||||
items.destroy_all
|
||||
render_ok
|
||||
end
|
||||
|
||||
def set_score
|
||||
@item.update_attributes!(score: params[:score])
|
||||
@questions_score = @exam.examination_items.where(item_type: @item.item_type).pluck(:score).sum
|
||||
@all_score = @exam.examination_items.pluck(:score).sum
|
||||
render_ok({questions_score: @questions_score, all_score: @all_score})
|
||||
end
|
||||
|
||||
def batch_set_score
|
||||
@exam.examination_items.where(item_type: params[:item_type]).update_all(score: params[:score])
|
||||
@questions_score = @exam.examination_items.where(item_type: params[:item_type]).pluck(:score).sum
|
||||
@all_score = @exam.examination_items.pluck(:score).sum
|
||||
render_ok({questions_score: @questions_score, all_score: @all_score})
|
||||
end
|
||||
|
||||
def adjust_position
|
||||
same_items = @exam.examination_items.where(item_type: @item.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 > @item.position
|
||||
same_items.where("position > #{@item.position} and position <= #{params[:position].to_i}").update_all("position=position-1")
|
||||
@item.update_attributes!(position: params[:position])
|
||||
elsif params[:position].to_i < @item.position
|
||||
same_items.where("position < #{@item.position} and position >= #{params[:position].to_i}").update_all("position=position+1")
|
||||
@item.update_attributes!(position: params[:position])
|
||||
else
|
||||
return normal_status(-1, "排序无变化")
|
||||
end
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_exam
|
||||
@exam = ExaminationBank.find_by!(id: params[:exam_id])
|
||||
end
|
||||
|
||||
def create_params
|
||||
params.permit(item_ids: [])
|
||||
end
|
||||
|
||||
def find_item
|
||||
@item = ExaminationItem.find_by!(id: params[:id])
|
||||
@exam = @item.examination_bank
|
||||
end
|
||||
|
||||
def validate_score
|
||||
tip_exception("分值不能为空") unless params[:score].present?
|
||||
tip_exception("分值需大于0") unless params[:score].to_f > 0
|
||||
end
|
||||
|
||||
def edit_auth
|
||||
current_user.admin_or_business? || @exam.user == current_user
|
||||
end
|
||||
end
|
@ -1,14 +1,60 @@
|
||||
class LibrariesController < ApplicationController
|
||||
class ItemBanksController < ApplicationController
|
||||
include PaginateHelper
|
||||
before_action :require_login
|
||||
before_action :find_item, except: [:index, :create]
|
||||
before_action :edit_auth, only: [:update, :destroy, :set_public]
|
||||
|
||||
def index
|
||||
default_sort('updated_at', 'desc')
|
||||
|
||||
@items = ItemBankQuery.call(params)
|
||||
@items = paginate courses.includes(:school, :students, :attachments, :homework_commons, teacher: :user_extension)
|
||||
items = ItemBankQuery.call(params)
|
||||
@items_count = items.size
|
||||
@items = paginate items.includes(:item_analysis, :user, :container)
|
||||
@item_basket_ids = current_user.item_baskets.pluck(:item_bank_id)
|
||||
end
|
||||
|
||||
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?
|
||||
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @item.id, container_type: 'ItemBank').exists?
|
||||
ApplyAction.create!(container_id: @item.id, container_type: 'ItemBank', user_id: current_user.id)
|
||||
# @item.update_attributes!(public: 1)
|
||||
render_ok
|
||||
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
|
@ -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,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,2 @@
|
||||
module EduDatasHelper
|
||||
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, -> {order(position: :asc)}, dependent: :destroy
|
||||
|
||||
def question_count
|
||||
examination_items.size
|
||||
end
|
||||
|
||||
def total_score
|
||||
examination_items.pluck(:score).sum
|
||||
end
|
||||
end
|
@ -0,0 +1,45 @@
|
||||
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
|
||||
|
||||
# 题库复制
|
||||
def new_item item, exam, score, position
|
||||
attributes = {examination_bank: exam, item_bank: item, name: item.name, item_type: item.item_type,
|
||||
difficulty: item.difficulty, score: score, position: position}
|
||||
self.update!(attributes)
|
||||
item.increment!(:quotes)
|
||||
|
||||
if item.item_type == "PROGRAM"
|
||||
new_hack = item.container.fork
|
||||
self.update!(container: new_hack)
|
||||
else
|
||||
ExaminationItemAnalysis.create!(analysis: item.analysis, examination_item_id: self.id)
|
||||
item.item_choices.each do |choice|
|
||||
examination_item_choices << ExaminationItemChoice.new(choice_text: choice.choice_text, is_answer: choice.is_answer)
|
||||
end
|
||||
end
|
||||
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,52 @@
|
||||
class ItemBank < ApplicationRecord
|
||||
# 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 }
|
||||
# item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :sub_discipline, optional: true
|
||||
|
||||
has_one :item_analysis, dependent: :destroy
|
||||
has_many :item_choices, 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
|
||||
|
||||
def type_string
|
||||
result = case item_type
|
||||
when "SINGLE"
|
||||
"单选题"
|
||||
when "MULTIPLE"
|
||||
"多选题"
|
||||
when "JUDGMENT"
|
||||
"判断题"
|
||||
when "COMPLETION"
|
||||
"填空题"
|
||||
when "SUBJECTIVE"
|
||||
"简答题"
|
||||
when "PRACTICAL"
|
||||
"实训题"
|
||||
when "PROGRAM"
|
||||
"编程题"
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def difficulty_string
|
||||
result = case difficulty
|
||||
when 1
|
||||
"简单"
|
||||
when 2
|
||||
"适中"
|
||||
when 3
|
||||
"困难"
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,14 @@
|
||||
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 :user
|
||||
|
||||
def all_score
|
||||
User.current.item_baskets.map(&:score).sum
|
||||
end
|
||||
|
||||
def question_count
|
||||
User.current.item_baskets.size
|
||||
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,34 @@
|
||||
class Admins::ApplyItemBankQuery < ApplicationQuery
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :updated_at, default_by: :updated_at, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
applies = ApplyAction.where(container_type: params[:type].presence || "ItemBank")
|
||||
|
||||
status =
|
||||
case params[:status]
|
||||
when 'pending' then 0
|
||||
when 'processed' then [1, 2]
|
||||
when 'agreed' then 1
|
||||
when 'refused' then 2
|
||||
else 0
|
||||
end
|
||||
applies = applies.where(status: status) if status.present?
|
||||
|
||||
# 关键字模糊查询
|
||||
keyword = params[:keyword].to_s.strip
|
||||
if keyword.present?
|
||||
applies = applies.joins(user: { user_extension: :school })
|
||||
.where('CONCAT(lastname,firstname) LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%")
|
||||
end
|
||||
|
||||
custom_sort(applies, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
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,50 @@
|
||||
class ExaminationItems::SaveItemService < ApplicationService
|
||||
attr_reader :user, :params, :exam
|
||||
|
||||
def initialize(user, params, exam)
|
||||
@user = user
|
||||
@params = params
|
||||
@exam = exam
|
||||
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] - exam.examination_items.pluck(:item_bank_id)
|
||||
items.where(id: item_ids).each do |item|
|
||||
ActiveRecord::Base.transaction do
|
||||
item_score = item_score item.item_type
|
||||
item_position = item_position item.item_type
|
||||
new_item = ExaminationItem.new
|
||||
new_item.new_item(item, exam, item_score, item_position)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def item_score item_type
|
||||
if exam.examination_items.where(item_type: item_type).last.present?
|
||||
score = exam.examination_items.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
|
||||
exam.examination_items.where(item_type: item_type).last&.position.to_i + 1
|
||||
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>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue