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

dev_jupyter
daiao 5 years ago
commit f77f03d366

@ -61,5 +61,64 @@ $(document).on('turbolinks:load', function() {
data: json 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,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

@ -1,5 +1,8 @@
class ExaminationBanksController < ApplicationController class ExaminationBanksController < ApplicationController
include PaginateHelper
before_action :require_login before_action :require_login
before_action :find_exam, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public]
def index def index
exams = ExaminationBankQuery.call(params) exams = ExaminationBankQuery.call(params)
@ -43,9 +46,32 @@ class ExaminationBanksController < ApplicationController
end 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 private
def form_params def form_params
params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: []) params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: [])
end 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 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,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

@ -2,8 +2,11 @@
<% add_admin_breadcrumb('课程方向', admins_disciplines_path) %> <% add_admin_breadcrumb('课程方向', admins_disciplines_path) %>
<% end %> <% end %>
<div class="box search-form-container discipline-list-form"> <div class="box search-form-container discipline-list-form rig">
<%= javascript_void_link '新增', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-discipline-modal' } %> <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>
<div class="box admin-list-container discipline-list-container"> <div class="box admin-list-container discipline-list-container">
@ -11,3 +14,4 @@
</div> </div>
<%= render 'admins/disciplines/shared/create_discipline_modal' %> <%= render 'admins/disciplines/shared/create_discipline_modal' %>
<%= render partial: 'admins/disciplines/shared/import_discipline_modal' %>

@ -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">&times;</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>

@ -1,4 +1,4 @@
json.(item, :id, :name, :item_type, :difficulty, :public, :quotes) json.(item, :name, :item_type, :difficulty, :public, :quotes)
json.analysis item.analysis json.analysis item.analysis
json.choices item.item_choices do |choice| json.choices item.item_choices do |choice|
json.choice_text choice.choice_text json.choice_text choice.choice_text

@ -1,4 +1,5 @@
json.items @items.each do |item| json.items @items.each do |item|
json.id item.id
json.partial! "item_banks/item", locals: {item: item} json.partial! "item_banks/item", locals: {item: item}
json.update_time item.updated_at&.strftime("%Y-%m-%d %H:%M") json.update_time item.updated_at&.strftime("%Y-%m-%d %H:%M")
json.choosed @item_basket_ids.include?(item.id) json.choosed @item_basket_ids.include?(item.id)

@ -77,7 +77,9 @@ Rails.application.routes.draw do
end end
resources :examination_banks do resources :examination_banks do
member do
post :set_public
end
end end
resources :hacks, path: :problems, param: :identifier do resources :hacks, path: :problems, param: :identifier do
@ -1075,6 +1077,7 @@ Rails.application.routes.draw do
post :reset_login_times post :reset_login_times
end end
end end
resource :import_disciplines, only: [:create]
resource :import_users, only: [:create] resource :import_users, only: [:create]
resource :import_course_members, only: [:create] resource :import_course_members, only: [:create]
resources :user_statistics, only: [:index] do resources :user_statistics, only: [:index] do

@ -177,7 +177,7 @@ class Paperreview extends Component {
</Breadcrumb> </Breadcrumb>
</div> </div>
<Paperreview_item {...this.state} {...this.props}> <Paperreview_item {...this.state} {...this.props} getdata={(data)=>this.props.getdata(data)}>
</Paperreview_item> </Paperreview_item>

@ -75,8 +75,83 @@ class Paperreview_item extends Component {
} }
onDragEnd=(result)=>{ onDragEnd=(result)=>{
console.log("拖拽成功了");
console.log(result); const ids=this.props.single_questions.questions[result.source.index].id;
const positions=this.props.single_questions.questions[result.destination.index].position;
const url=`/item_baskets/${ids}/adjust_position.json`
var data={
position:positions
}
axios.post(url, data)
.then((result) => {
if (result.data.status == 0) {
this.props.showNotification(`拖动成功`);
this.props.getdata({});
}
}).catch((error) => {
console.log(error);
})
}
onDragEnds=(result)=>{
const ids=this.props.multiple_questions.questions[result.source.index].id;
const positions=this.props.multiple_questions.questions[result.destination.index].position;
const url=`/item_baskets/${ids}/adjust_position.json`
var data={
position:positions
}
axios.post(url, data)
.then((result) => {
if (result.data.status == 0) {
this.props.showNotification(`拖动成功`);
this.props.getdata({});
}
}).catch((error) => {
console.log(error);
})
}
onDragEndss=(result)=>{
const ids=this.props.judgement_questions.questions[result.source.index].id;
const positions=this.props.judgement_questions.questions[result.destination.index].position;
const url=`/item_baskets/${ids}/adjust_position.json`
var data={
position:positions
}
axios.post(url, data)
.then((result) => {
if (result.data.status == 0) {
this.props.showNotification(`拖动成功`);
this.props.getdata({});
}
}).catch((error) => {
console.log(error);
})
}
onDragEndsss=(result)=>{
const ids=this.props.judgement_questions.questions[result.source.index].id;
const positions=this.props.judgement_questions.questions[result.destination.index].position;
const url=`/item_baskets/${ids}/adjust_position.json`
var data={
position:positions
}
axios.post(url, data)
.then((result) => {
if (result.data.status == 0) {
this.props.showNotification(`拖动成功`);
this.props.getdata({});
}
}).catch((error) => {
console.log(error);
})
} }
render() { render() {
@ -173,12 +248,45 @@ class Paperreview_item extends Component {
<div className="scd">删除</div> <div className="scd">删除</div>
<div className="szdfd">设置得分</div> <div className="szdfd">设置得分</div>
</div> </div>
{
multiple_questions&&multiple_questions.questions.map((object, index) => { <DragDropContext onDragEnd={this.onDragEnds} >
return ( <Droppable droppableId={"0"}>
<Paperreview_single objectsingle={object}></Paperreview_single> {(provided, snapshot) => (
) <div
})} ref={provided.innerRef}
{...provided.droppableProps}
className={""}
onScroll={this.contentViewScrolledit}
>
{
multiple_questions&&multiple_questions.questions.map((object, index) => {
return (
<Draggable
key={object.id}
draggableId={object.id}
index={index}
className={""}
>
{(provided, snapshot) => (
<div
key={index}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Paperreview_single objectsingle={object}></Paperreview_single>
</div>
)}
</Draggable>
)
})
}
</div>
)}
</Droppable>
</DragDropContext>
</div> </div>
</div> </div>
@ -202,13 +310,44 @@ class Paperreview_item extends Component {
<div className="scd">删除</div> <div className="scd">删除</div>
<div className="szdfd">设置得分</div> <div className="szdfd">设置得分</div>
</div> </div>
{
judgement_questions&&judgement_questions.questions.map((object, index) => {
return (
<Paperreview_single objectsingle={object}></Paperreview_single>
)
})}
<DragDropContext onDragEnd={this.onDragEndss} >
<Droppable droppableId={"0"}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={""}
onScroll={this.contentViewScrolledit}
>
{
judgement_questions&&judgement_questions.questions.map((object, index) => {
return (
<Draggable
key={object.id}
draggableId={object.id}
index={index}
className={""}
>
{(provided, snapshot) => (
<div
key={index}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Paperreview_single objectsingle={object}></Paperreview_single>
</div>
)}
</Draggable>
)
})
}
</div>
)}
</Droppable>
</DragDropContext>
</div> </div>
</div> </div>
:"" :""
@ -238,12 +377,44 @@ class Paperreview_item extends Component {
<div className="scd">删除</div> <div className="scd">删除</div>
<div className="szdfd">设置得分</div> <div className="szdfd">设置得分</div>
</div> </div>
{ <DragDropContext onDragEnd={this.onDragEndsss} >
program_questions&&program_questions.questions.map((object, index) => { <Droppable droppableId={"0"}>
return ( {(provided, snapshot) => (
<Paperreview_single objectsingle={object}></Paperreview_single> <div
) ref={provided.innerRef}
})} {...provided.droppableProps}
className={""}
onScroll={this.contentViewScrolledit}
>
{
program_questions&&program_questions.questions.map((object, index) => {
return (
<Draggable
key={object.id}
draggableId={object.id}
index={index}
className={""}
>
{(provided, snapshot) => (
<div
key={index}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Paperreview_single objectsingle={object}></Paperreview_single>
</div>
)}
</Draggable>
)
})
}
</div>
)}
</Droppable>
</DragDropContext>
</div> </div>
</div> </div>

Loading…
Cancel
Save