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

dev_jupyter
杨树林 5 years ago
commit 0a33fc8cfe

2
.gitignore vendored

@ -43,7 +43,7 @@
/public/react/config/stats.json
/public/react/stats.json
/public/react/.idea/*
/public/h5build
/public/npm-debug.log
# avatars

@ -1,31 +1,42 @@
$(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');
$(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
}
}
});
$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');
$modal.on('click', '.submit-btn', submit_edit_form);
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
$form.find("#discipline_name").keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_edit_form();
return false;
}
});
}
function submit_edit_form() {
$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-repertoire-modal', function(){
var $modal = $('.modal.admin-edit-repertoire-modal');
var $form = $modal.find('form.admin-edit-repertoire-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'repertoire[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()
});
}
});
});
});

@ -1,31 +1,43 @@
$(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');
$(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
}
}
});
$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');
$modal.on('click', '.submit-btn', submit_edit_form);
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
$form.find("#sub_discipline_name").keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_edit_form();
return false;
}
});
}
function submit_edit_form() {
$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-repertoire-modal', function(){
var $modal = $('.modal.admin-edit-sub-repertoire-modal');
var $form = $modal.find('form.admin-edit-sub-repertoire-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'sub_repertoire[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()
});
}
});
});
});

@ -1,31 +1,42 @@
$(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');
$(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
}
}
});
$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');
$modal.on('click', '.submit-btn', submit_edit_form);
if ($form.valid()) {
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
$form.find("#tag_discipline_name").keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_edit_form();
return false;
}
});
}
function submit_edit_form() {
$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-repertoire-modal', function(){
var $modal = $('.modal.admin-edit-tag-repertoire-modal');
var $form = $modal.find('form.admin-edit-tag-repertoire-form');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
'tag_repertoire[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-repertoires-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-repertoire-modal');
var $form = $modal.find('form.admin-create-repertoire-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);
}
});
}
});
$(".repertoire-list-container").on("change", '.repertoire-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/repertoires/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -0,0 +1,74 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-salesmans-index-page').length > 0) {
// ============= 添加销售人员 ==============
var $addMemberModal = $('.admin-add-salesman-customer-user-modal');
var $addMemberForm = $addMemberModal.find('.admin-add-salesman-customer-user-form');
var $memberSelect = $addMemberModal.find('.salesman-user-select');
// var $salesmanIdInput = $addMemberForm.find('input[name="salesman_id"]')
$addMemberModal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var salesmanId = $link.data('salesman-id');
$salesmanIdInput.val(salesmanId);
$memberSelect.select2('val', ' ');
});
$memberSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的销售姓名',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/admins/users',
dataType: 'json',
data: function(params){
return { name: params.term };
},
processResults: function(data){
return { results: data.users }
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.hidden_phone + "</span></span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
$addMemberModal.on('click', '.submit-btn', function(){
$addMemberForm.find('.error').html('');
// var salesmanId = $salesmanIdInput.val();
var memberIds = $memberSelect.val();
if (memberIds && memberIds.length > 0) {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/salesman_customers/batch_add',
data: { user_ids: memberIds },
success: function(){
$.notify({ message: '创建成功' });
$addMemberModal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
} else {
$addMemberModal.modal('hide');
}
});
}
});

@ -0,0 +1,99 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-salesmans-index-page').length > 0) {
// ============= 添加销售人员 ==============
var $addMemberModal = $('.admin-add-salesman-user-modal');
var $addMemberForm = $addMemberModal.find('.admin-add-salesman-user-form');
var $memberSelect = $addMemberModal.find('.salesman-user-select');
// var $salesmanIdInput = $addMemberForm.find('input[name="salesman_id"]')
$addMemberModal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
// var salesmanId = $link.data('salesman-id');
// $salesmanIdInput.val(salesmanId);
$memberSelect.select2('val', ' ');
});
$memberSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的销售姓名',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/admins/users',
dataType: 'json',
data: function(params){
return { name: params.term };
},
processResults: function(data){
return { results: data.users }
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.hidden_phone + "</span></span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
$addMemberModal.on('click', '.submit-btn', function(){
$addMemberForm.find('.error').html('');
// var salesmanId = $salesmanIdInput.val();
var memberIds = $memberSelect.val();
if (memberIds && memberIds.length > 0) {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/salesmans/batch_add',
data: { user_ids: memberIds },
success: function(){
$.notify({ message: '创建成功' });
$addMemberModal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
} else {
$addMemberModal.modal('hide');
}
});
$(".salesman-list-container").on("change", '.salesman-sync-course', function () {
var s_id = $(this).attr("data-id");
var json = {};
$.ajax({
url: "/admins/salesmans/" + s_id + "/update_sync_course",
type: "POST",
dataType:'script',
data: json
})
});
$(".salesman-list-container").on("change", '.salesman-sync-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/salesmans/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -30,9 +30,23 @@ $(document).on('turbolinks:load', function() {
type: "PUT",
dataType:'script',
data: json
})
});
});
$(".shixun-settings-list-container").on("change", '.repertoire-setting-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/shixun_settings/" + s_id + "/update_tag_repertoires",
type: "POST",
dataType:'script',
data: json
});
});
$("select#settings-tag-choosed").select2({
placeholder: "请选择分类",
allowClear: true

@ -1,65 +1,76 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-sub-disciplines-index-page').length > 0) {
$(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"]');
// ============== 新建 ===============
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
}
}
});
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
$modal.on('click', '.submit-btn', submit_create_form);
if ($form.valid()) {
var url = $form.data('url');
$nameInput.keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_create_form();
return false;
}
});
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
function submit_create_form() {
$form.find('.error').html('');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
if ($form.valid()) {
var url = $form.data('url');
$(".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
});
});
}
$.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-sub-repertoires-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-sub-repertoire-modal');
var $form = $modal.find('form.admin-create-sub-repertoire-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-repertoire-list-container").on("change", '.sub-repertoire-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_repertoires/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -0,0 +1,71 @@
$(document).on('turbolinks:load', function () {
if ($('body.admins-subject-settings-index-page').length > 0) {
var $form = $('.subject-setting-list-form');
// ************** 学校选择 *************
$form.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};
},
processResults: function (data) {
return {results: data.schools}
}
},
templateResult: function (item) {
if (!item.id || item.id === '') return item.text;
return item.name;
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
$(".subject-setting-list-container").on("change", '.subject-setting-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/subject_settings/" + s_id,
type: "PUT",
dataType:'script',
data: json
})
});
// 清空
$form.on('click', '.clear-btn', function () {
$form.find('select[name="status"]').val('');
$form.find('.school-select').val('').trigger('change');
$form.find('input[name="keyword"]').val('');
$form.find('#homepage_show').attr('checked', false);
$form.find('#excellent').attr('checked', false);
$form.find('input[type="submit"]').trigger('click');
});
// 上传图片
$('.modal.admin-upload-file-modal').on('upload:success', function (e, data) {
if(data.suffix == '_qrcode'){
var $imageElement = $('.subject-weapp-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
} else {
var $imageElement = $('.subject-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
}
});
}
});

@ -37,22 +37,8 @@ $(document).on('turbolinks:load', function () {
$form.find('#homepage_show').attr('checked', false);
$form.find('#excellent').attr('checked', false);
$form.find('input[type="submit"]').trigger('click');
})
// 上传图片
$('.modal.admin-upload-file-modal').on('upload:success', function (e, data) {
if(data.suffix == '_qrcode'){
var $imageElement = $('.subject-weapp-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
} else {
var $imageElement = $('.subject-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
}
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.subject-list-container').on('click', doElement, function () {

@ -1,65 +1,76 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-tag-disciplines-index-page').length > 0) {
$(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"]');
// ============== 新建 ===============
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
}
}
});
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
$modal.on('click', '.submit-btn', submit_create_form);
if ($form.valid()) {
var url = $form.data('url');
$nameInput.keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_create_form();
return false;
}
});
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
function submit_create_form() {
$form.find('.error').html('');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
if ($form.valid()) {
var url = $form.data('url');
$(".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
});
});
}
$.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,65 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-tag-repertoires-index-page').length > 0) {
// ============== 新建 ===============
var $modal = $('.modal.admin-create-tag-repertoire-modal');
var $form = $modal.find('form.admin-create-tag-repertoire-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-repertoire-list-container").on("change", '.tag-repertoire-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_repertoires/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
}
});

@ -167,7 +167,7 @@ class AccountsController < ApplicationController
end
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
# 参数type为事件类型 1注册2忘记密码
# 参数type为事件类型 1注册2忘记密码3绑定
def valid_email_and_phone
check_mail_and_phone_valid(params[:login], params[:type])
end

@ -16,19 +16,23 @@ class Admins::DisciplinesController < Admins::BaseController
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)
begin
if params[:discipline] && params[:discipline][:name]
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
sub.update_attributes!(setting_params)
end
end
rescue Exception => e
@message = e.message
end
@disciplines = Discipline.all
end

@ -0,0 +1,36 @@
class Admins::RepertoiresController < Admins::BaseController
def index
@repertoires = Repertoire.all
end
def edit
@repertoire = current_repertoire
end
def update
Rails.logger.info("#################--------")
if params[:repertoire] && params[:repertoire][:name].present?
name = params[:repertoire][:name].to_s.strip
current_repertoire.update_attributes!(name: name)
end
@repertoires = Repertoire.all
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if Repertoire.where(name: name).exists?
Repertoire.create!(name: name)
render_ok
end
def destroy
@repertoire_id = params[:id]
current_repertoire.destroy!
end
private
def current_repertoire
@_current_repertoire = Repertoire.find params[:id]
end
end

@ -0,0 +1,13 @@
class Admins::SalesmanCustomersController < Admins::BaseController
before_action :set_salesman
def index
@customers = @salesman.salesman_customers.includes(:user, :school)
end
private
def set_salesman
@salesman = Salesman.find params[:salesman_id]
end
end

@ -0,0 +1,29 @@
class Admins::SalesmansController < Admins::BaseController
before_action :set_salesman, except: [:index, :batch_add]
def index
@salesmans = Salesman.all
end
def destroy
@salesman.destroy!
end
# 批量增加销售人员
def batch_add
salesman_user_ids = Salesman.where(id: params[:user_ids]).pluck(:user_id)
user_ids = params[:user_ids] - salesman_user_ids
user_ids.each do |user_id|
user = User.find_by(id: user_id)
next if user.blank?
Salesman.create!(user_id: user.id, name: user.real_name)
end
render_ok
end
private
def set_salesman
@salesman = Salesman.find params[:id]
end
end

@ -47,21 +47,23 @@ class Admins::ShixunSettingsController < Admins::BaseController
@shixun = Shixun.find_by(id:params[:id])
@page_no = params[:page_no] || "1"
@shixun_tags = TagRepertoire.order("name asc").pluck(:name,:id)
tag_ids = params[:tag_repertoires]
if tag_ids.present?
@shixun&.shixun_tag_repertoires.delete_all
tag_repertoire_ids = @shixun&.tag_repertoires&.pluck(:id)
tag_ids.each do |id|
unless tag_repertoire_ids.include?(id)
tag_repertoire = @shixun.shixun_tag_repertoires.new(shixun_id:@shixun.id,tag_repertoire_id:id)
tag_repertoire.save!
end
end
else
unless @shixun.update_attributes(setting_params)
redirect_to admins_shixun_settings_path
flash[:danger] = "更新失败"
end
unless @shixun.update_attributes(setting_params)
redirect_to admins_shixun_settings_path
flash[:danger] = "更新失败"
end
end
def update_tag_repertoires
shixun = Shixun.find_by(id:params[:id])
tag_repertoire_ids = params[:tag_repertoires] || []
tag_ids = tag_repertoire_ids.reject(&:blank?).map(&:to_i)
old_tag_ids = shixun.shixun_tag_repertoires.pluck(:tag_repertoire_id)
new_ids = tag_ids - old_tag_ids
delete_ids = old_tag_ids - tag_ids
tag_params = new_ids.map{|sub| {tag_repertoire_id: sub}}
ActiveRecord::Base.transaction do
shixun.shixun_tag_repertoires.where(tag_repertoire_id: delete_ids).destroy_all
shixun.shixun_tag_repertoires.create!(tag_params)
end
end
@ -133,6 +135,6 @@ class Admins::ShixunSettingsController < Admins::BaseController
def setting_params
params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,
:code_hidden,:vip,:page_no,:id, :is_wechat_support, tag_repertoires:[])
:code_hidden,:vip,:page_no,:id, :is_wechat_support)
end
end

@ -7,6 +7,7 @@ class Admins::SubDisciplinesController < Admins::BaseController
def create
name = params[:name].to_s.strip
return render_error('名称不能为空') if name.blank?
return render_error('名称重复') if current_discipline.sub_disciplines.where(name: name).exists?
SubDiscipline.create!(name: name, discipline_id: current_discipline.id)
render_ok
@ -17,16 +18,20 @@ class Admins::SubDisciplinesController < Admins::BaseController
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)
begin
if params[:sub_discipline] && params[:sub_discipline][:name]
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
rescue Exception => e
@message = e.message
end
@sub_disciplines = current_sub_discipline.discipline&.sub_disciplines
end

@ -0,0 +1,45 @@
class Admins::SubRepertoiresController < Admins::BaseController
def index
@repertoire = current_repertoire
@sub_repertoires = current_repertoire.sub_repertoires
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if current_repertoire.sub_repertoires.where(name: name).exists?
SubRepertoire.create!(name: name, repertoire_id: current_repertoire.id)
render_ok
end
def edit
@sub_repertoire = current_sub_repertoire
end
def update
if params[:sub_repertoire] && params[:sub_repertoire][:name].present?
name = params[:sub_repertoire][:name].to_s.strip
current_sub_repertoire.update_attributes!(name: name)
end
@sub_repertoires = current_sub_repertoire.repertoire&.sub_repertoires
end
def destroy
@sub_repertoire_id = params[:id]
current_sub_repertoire.destroy!
end
private
def current_sub_repertoire
@_current_sub_repertoire = SubRepertoire.find params[:id]
end
def current_repertoire
@_current_repertoire = Repertoire.find params[:repertoire_id]
end
def setting_params
params.permit(:shixun, :subject, :question)
end
end

@ -0,0 +1,29 @@
class Admins::SubjectSettingsController < Admins::BaseController
def index
default_sort('created_at', 'desc')
subjects = Admins::SubjectQuery.call(params)
@sub_disciplines = SubDiscipline.where(subject: 1).pluck(:name,:id)
@subjects = paginate subjects.includes(:repertoire, :subject_level_system, :sub_disciplines)
end
def update
sub_discipline_ids = params[:sub_disciplines] || []
sub_ids = sub_discipline_ids.reject(&:blank?).map(&:to_i)
old_sub_ids = current_subject.sub_discipline_containers.pluck(:sub_discipline_id)
new_ids = sub_ids - old_sub_ids
delete_ids = old_sub_ids - sub_ids
sub_params = new_ids.map{|sub| {sub_discipline_id: sub}}
ActiveRecord::Base.transaction do
current_subject.sub_discipline_containers.where(sub_discipline_id: delete_ids).destroy_all
current_subject.sub_discipline_containers.create!(sub_params)
end
end
private
def current_subject
@_current_subject ||= Subject.find(params[:id])
end
end

@ -3,7 +3,7 @@ class Admins::SubjectsController < Admins::BaseController
default_sort('created_at', 'desc')
subjects = Admins::SubjectQuery.call(params)
@subjects = paginate subjects.includes(:repertoire, :subject_level_system, user: { user_extension: :school })
@subjects = paginate subjects.includes(user: { user_extension: :school })
end
def edit
@ -14,7 +14,7 @@ class Admins::SubjectsController < Admins::BaseController
current_subject.update!(update_params)
flash[:success] = '保存成功'
redirect_to admins_subjects_path
redirect_to admins_subject_settings_path
end
def destroy

@ -17,11 +17,15 @@ class Admins::TagDisciplinesController < Admins::BaseController
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)
begin
if params[:tag_discipline] && params[:tag_discipline][:name]
name = params[:tag_discipline][:name].to_s.strip
current_tag_discipline.update_attributes!(name: name)
else
current_tag_discipline.update_attributes!(setting_params)
end
rescue Exception => e
@message = e.message
end
@tag_disciplines = current_tag_discipline.sub_discipline&.tag_disciplines
end

@ -0,0 +1,43 @@
class Admins::TagRepertoiresController < Admins::BaseController
def index
@sub_repertoire = current_sub_repertoire
@tag_repertoires = current_sub_repertoire.tag_repertoires
end
def create
name = params[:name].to_s.strip
return render_error('名称重复') if current_sub_repertoire.tag_repertoires.where(name: name).exists?
TagRepertoire.create!(name: name, sub_repertoire_id: current_sub_repertoire.id)
render_ok
end
def edit
@tag_repertoire = current_tag_repertoire
end
def update
if params[:tag_repertoire] && params[:tag_repertoire][:name].present?
name = params[:tag_repertoire][:name].to_s.strip
current_tag_repertoire.update_attributes!(name: name)
end
@tag_repertoires = current_tag_repertoire.sub_repertoire&.tag_repertoires
end
def destroy
@tag_repertoire_id = params[:id]
current_tag_repertoire.destroy!
end
private
def current_sub_repertoire
@_current_sub_repertoire = SubRepertoire.find params[:sub_repertoire_id]
end
def current_tag_repertoire
@_current_tag_repertoire = TagRepertoire.find params[:id]
end
end

@ -92,7 +92,7 @@ class ApplicationController < ActionController::Base
# 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码
# params[:type] 1: 注册2忘记密码3绑定
def check_mail_and_phone_valid login, type
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/ ||
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
@ -104,6 +104,8 @@ class ApplicationController < ActionController::Base
tip_exception(-2, "该手机号码或邮箱已被注册")
elsif type.to_i == 2 && user.nil?
tip_exception(-2, "该手机号码或邮箱未注册")
elsif type.to_i == 3 && user.present?
tip_exception(-2, "该手机号码或邮箱已绑定")
end
sucess_status
end
@ -218,7 +220,7 @@ class ApplicationController < ActionController::Base
# 未授权的捕捉407弹试用申请弹框
def require_login
#6.13 -hs
tip_exception(401, "..") unless User.current.logged?
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
# 异常提醒
@ -306,7 +308,7 @@ class ApplicationController < ActionController::Base
end
if !User.current.logged? && Rails.env.development?
User.current = User.find 1
User.current = User.find 8686
end
@ -632,7 +634,8 @@ class ApplicationController < ActionController::Base
end
def paginate(relation)
limit = (params[:limit].to_i.zero? || params[:limit].to_i > 20) ? 20 : params[:limit].to_i
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
offset = (page - 1) * limit
@ -643,6 +646,8 @@ class ApplicationController < ActionController::Base
end
end
def strf_time(time)
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
end

@ -17,9 +17,11 @@ class AttachmentsController < ApplicationController
redirect_to @file.cloud_url and return
end
pdf_attachment = params[:disposition] || "attachment"
if pdf_attachment == "inline"
type_attachment = params[:disposition] || "attachment"
if type_attachment == "inline"
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
elsif type_attachment == "MP4"
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
else
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
end
@ -202,4 +204,31 @@ class AttachmentsController < ApplicationController
end
end
def send_file_with_range(path, options = {})
logger.info("########request.headers: #{request.headers}")
logger.info("########request.headers: #{File.exist?(path)}")
if File.exist?(path)
size = File.size(path)
logger.info("########request.headers: #{request.headers}")
if !request.headers["Range"]
status_code = 200 # 200 OK
offset = 0
length = File.size(path)
else
status_code = 206 # 206 Partial Content
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
offset = bytes.begin
length = bytes.end - bytes.begin
end
response.header["Accept-Ranges"] = "bytes"
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
response.header["status"] = status_code
send_data IO.binread(path, length, offset), options
else
raise ActionController::MissingFile, "Cannot read file #{path}."
end
end
end

@ -181,7 +181,7 @@ class ChallengesController < ApplicationController
begin
ActiveRecord::Base.transaction do
tab = params[:tab].to_i
@challenge.update_attributes(challenge_params)
@challenge.update_attributes!(challenge_params)
if tab == 0 && @challenge.st == 0
@challenge.challenge_tags.delete_all
if params[:challenge_tag].present?
@ -211,7 +211,7 @@ class ChallengesController < ApplicationController
# last 末尾匹配, full: 全完匹配
logger.info("set: #{set}; match_rule : #{set[:match_rule]}")
match_rule = set[:match_rule] == 'last' ? 'last' : 'full'
TestSet.create(:challenge_id => @challenge.id,
TestSet.create!(:challenge_id => @challenge.id,
:input => "#{set[:input]}",
:output => "#{set[:output]}",
:is_public => params_hidden[index],
@ -227,8 +227,11 @@ class ChallengesController < ApplicationController
@challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil)
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
logger.info("############shixun_publiced:#{@shixun.public == 0}")
if @shixun.public == 0
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
# TODO:
# if path != params[:challenge][:path]
# shixun_modify_status_without_publish(@shixun, 1)
@ -237,9 +240,9 @@ class ChallengesController < ApplicationController
end
end
rescue => e
logger_error("##update_challenges: ##{e.message}")
tip_exception("更新失败!")
rescue Exception => e
logger.error("##update_challenges: ##{e.message}")
tip_exception("#{e.message}")
end
end
@ -262,7 +265,7 @@ class ChallengesController < ApplicationController
params[:challenge_answer].each_with_index do |answer, index|
# 内容为空不保存
next if answer[:contents].blank?
ChallengeAnswer.create(name: answer[:name], contents: answer[:contents],
ChallengeAnswer.create!(name: answer[:name], contents: answer[:contents],
level: index+1, score: answer[:score], challenge_id: @challenge.id)
end
end

@ -136,22 +136,22 @@ class CollegesController < ApplicationController
private
def require_login
return if User.current.logged?
redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
end
# def require_login
# return if User.current.logged?
#
# redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
# end
def check_college_present!
return if current_college.present?
redirect_to '/404'
tip_exception(404, "")
end
def check_manage_permission!
return if can_manage_college?
redirect_to '/403'
tip_exception(403, "")
end
def can_manage_college?
@ -160,7 +160,7 @@ class CollegesController < ApplicationController
return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师
# return true if current_school.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
false
tip_exception(403, "")
end
def current_school

@ -6,12 +6,17 @@ module ControllerRescueHandler
Util.logger_error e
render json: {status: -1, message: e.message}
end
rescue_from ActiveRecord::StatementInvalid do |e|
Util.logger_error e
render json: {status: -1, message: "接口数据异常"}
end
# rescue_from ActionView::MissingTemplate, with: :object_not_found
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from Educoder::TipException, with: :tip_show
rescue_from ::ActionView::MissingTemplate, with: :missing_template
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from ActionController::ParameterMissing, with: :render_parameter_missing
# form validation error
rescue_from ActiveModel::ValidationError do |ex|
render_error(ex.model.errors.full_messages.join(','))
@ -19,5 +24,9 @@ module ControllerRescueHandler
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
# rescue_from RuntimeError do |ex|
# Util.logger_error "#######ex:#{ex}"
# render_error(ex.message)
# end
end
end

@ -16,7 +16,7 @@ module LoginHelper
:expires => 1.month.from_now,
:path => '/',
:secure => false,
:httponly => true
:httponly => false
}
if edu_setting('cookie_domain').present?
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))

@ -1,6 +1,7 @@
class CoursesController < ApplicationController
include MessagesHelper
include ExportHelper
include CustomSortable
# model validation error
rescue_from ActiveRecord::RecordInvalid do |ex|
@ -23,8 +24,8 @@ class CoursesController < ApplicationController
:course_group_list, :set_course_group, :change_course_admin, :change_course_teacher,
:delete_course_teacher, :teacher_application_review, :students, :all_course_groups,
:transfer_to_course_group, :delete_from_course, :search_users, :add_students_by_search,
:base_info, :get_historical_courses, :create_group_by_importing_file,
:attahcment_category_list,:export_member_scores_excel, :duplicate_course,
:base_info, :get_historical_courses, :create_group_by_importing_file, :course_videos,
:attahcment_category_list,:export_member_scores_excel, :duplicate_course, :delete_course_video,
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course,
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs,
@ -100,6 +101,23 @@ class CoursesController < ApplicationController
@courses = @courses.preload(:school, :none_hidden_course_modules, teacher: :user_extension)
end
def course_videos
logger.info("########[#{@course}")
videos = @course.videos
videos = custom_sort(videos, params[:sort_by], params[:sort_direction])
@count = videos.count
@videos = paginate videos
end
def delete_course_video
video = Video.find_by(id: params[:video_id])
tip_exception(404, "找不到资源") if video.blank?
tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?)
video.destroy!
AliyunVod::Service.delete_video([video.uuid]) rescue nil
render_ok
end
def visits_plus_one
new_visits = @course.visits + 1
@course.update_visits(new_visits)
@ -377,6 +395,7 @@ class CoursesController < ApplicationController
def destroy
if @course.is_delete == 0
@course.delete!
Tiding.where(belong_container: @course).update_all(is_delete: 1)
Tiding.create!(user_id: current_user.id, trigger_user_id: current_user.id, container_id: @course.id,
container_type: 'DeleteCourse', tiding_type: 'System', belong_container: @course, extra: @course.name)
normal_status(0, "成功")
@ -1146,6 +1165,7 @@ class CoursesController < ApplicationController
if existing_student.present?
# 如果在该课堂已经存在学生身份,且邀请码为分班邀请码,则将其直接加入分班
existing_student.update!(course_group_id: course_group.id) if course_group.present?
message = "您已是课堂成员"
else
correspond_teacher_exist = current_user.none_admin_teacher_of_course? course
new_student = CourseMember.new(user_id: current_user.id, course_id: course.id, role: 4)
@ -1156,8 +1176,8 @@ class CoursesController < ApplicationController
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
student_role = 1
end
student_role = 1
end
# 创建教师身份
@ -1194,9 +1214,9 @@ class CoursesController < ApplicationController
teacher_role = 1
end
if teacher_role && student_role
if (teacher_role && student_role) || message.to_s == "您已是课堂成员"
render json: { status: 0, message: message, course_id: course.id}
elsif student_role
elsif student_role.to_i == 1
render json: { status: 0, message: "加入成功", course_id: course.id}
else
normal_status(message)

File diff suppressed because it is too large Load Diff

@ -1168,7 +1168,7 @@ class ExercisesController < ApplicationController
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id", group_id) #试卷所分班的全部人数
exercise_students = @course_all_members.course_find("course_group_id", group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end

@ -368,6 +368,7 @@ class HomeworkCommonsController < ApplicationController
ActiveRecord::Base.transaction do
begin
@homework = HomeworkCommon.new(homework_params)
@homework.reference_answer = params[:reference_answer].to_s.strip
@homework.homework_type = @homework_type
@homework.user_id = current_user.id
@homework.course_id = @course.id
@ -417,6 +418,7 @@ class HomeworkCommonsController < ApplicationController
ActiveRecord::Base.transaction do
begin
@homework.update_attributes!(homework_params)
@homework.reference_answer = params[:reference_answer].to_s.strip
if @homework.homework_type == "group"
homework_detail_group = @homework.homework_detail_group
@ -497,7 +499,7 @@ class HomeworkCommonsController < ApplicationController
# tip_exception("challenge_id参数的长度与challenge_score参数的长度不匹配") if
# params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length
sum_challenge_score = params[:challenge_settings].pluck(:challenge_score).reject(&:blank?).map{|score| score.to_f}.sum
sum_challenge_score = params[:challenge_settings].pluck(:challenge_score).reject(&:blank?)&.map{|score| score.to_f}.sum
total_score = params[:work_efficiency] ? (params[:eff_score].to_f + sum_challenge_score) : sum_challenge_score
tip_exception("分值之和必须等于总分值:#{params[:total_score]}") if params[:total_score].to_f.round(2) != total_score.to_f.round(2)
@ -910,7 +912,7 @@ class HomeworkCommonsController < ApplicationController
def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
group_ids = params[:group_ids]&.reject(&:blank?)&.map(&:to_i)
if params[:detail].blank?
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
@ -918,7 +920,7 @@ class HomeworkCommonsController < ApplicationController
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
else
tip_exception("缺少分班截止时间参数") if params[:group_end_times].blank?
group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time}
group_end_times = params[:group_end_times].reject(&:blank?)&.map{|time| time.to_time}
tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
group_end_times.each do |time|
tip_exception("分班截止时间不能早于当前时间") if time <= Time.now
@ -1049,7 +1051,7 @@ class HomeworkCommonsController < ApplicationController
homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings)
course_students = @course.students
charge_group_ids = @course.charge_group_ids(current_user)
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
group_ids = params[:group_ids]&.reject(&:blank?)&.map(&:to_i)
end_groups = charge_group_ids & group_ids if group_ids
begin
@ -1404,8 +1406,8 @@ class HomeworkCommonsController < ApplicationController
end
def homework_params
tip_exception("name参数不能为空") if params[:name].blank?
tip_exception("description参数不能为空") if params[:description].blank?
tip_exception("标题不能为空") if params[:name].blank?
tip_exception("内容不能为空") if params[:description].blank?
params.require(:homework_common).permit(:name, :description, :reference_answer)
end

@ -0,0 +1,69 @@
class LiveLinksController < ApplicationController
before_action :require_login
before_action :find_course, only: [:index, :create]
before_action :user_course_identity, :teacher_allowed, only: [:create]
before_action :edit_auth, only: [:edit, :update]
before_action :delete_auth, only: [:destroy]
def index
lives = @course.live_links
order_str = "on_status desc, live_time desc"
@total_count = lives.size
@my_live_id = @course.live_links.find_by(user_id: current_user.id)&.id
# order_str = "live_links.id = #{@my_live_id} desc, #{order_str}" if @my_live_id.present?
lives = lives.order("#{order_str}")
@lives = paginate lives.includes(user: :user_extension)
end
def create
on_status = params[:live_time].present? && params[:live_time].to_time <= Time.now ? 1 : 0
@course.live_links.create!(create_params.merge(user_id: current_user.id, on_status: on_status))
render_ok
end
def edit
@live = current_live
end
def update
if params[:on_status]
tip_exception("请勿重复开启") if current_live.on_status && params[:on_status].to_i == 1
ActiveRecord::Base.transaction do
current_live.update!(on_status: params[:on_status])
# 开启时发送消息,关闭直播时删除对应的消息
if params[:on_status].to_i == 1
LivePublishJob.perform_later(current_live.id)
end
end
else
on_status = params[:live_time].present? && params[:live_time].to_time <= Time.now ? 1 : 0
current_live.update!(create_params.merge(on_status: on_status))
end
render_ok
end
def destroy
current_live.destroy!
render_ok
end
private
def create_params
params.permit(:url, :description, :course_name, :platform, :live_time, :duration)
end
def current_live
@_current_live = LiveLink.find params[:id]
end
def edit_auth
tip_exception(403, "无权限操作") unless current_user.id == current_live.user_id || current_user.admin_or_business?
end
def delete_auth
tip_exception(403, "无权限操作") unless current_user.id == current_live.user_id || current_user.admin?
end
end

@ -8,6 +8,27 @@ class MainController < ApplicationController
end
def index
render file: 'public/react/build/index.html', :layout => false
domain_session = params[:_educoder_session]
if domain_session
uid_logger("main start domain_session is #{domain_session}")
if cookies[:_educoder_session] != domain_session
cookies[:_educoder_session] = nil
cookies[:_educoder_session] = domain_session
end
uid_logger("main start is #{cookies[:_educoder_session]}")
end
if params[:path] && params[:path]&.include?("educoderh5") && params[:path].split("/").first == "educoderh5"
render file: 'public/h5build/index.html', :layout => false
# TODO: 这块之后需要整合到上面去或者架构重新变化统一跳转到index后再路由分发
elsif params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
render file: 'public/h5educoderbuild/index.html', :layout => false
else
render file: 'public/react/build/index.html', :layout => false
end
end
end

@ -270,7 +270,9 @@ class MyshixunsController < ApplicationController
uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end
# 隐藏代码文件 和 VNC的都不需要走版本库
unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?)
vnc = @myshixun.shixun&.vnc
unless @hide_code || (vnc && params[:evaluate].present?)
# 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
@ -280,8 +282,8 @@ class MyshixunsController < ApplicationController
else
params[:content]
end
uid_logger_dubug("###11222333####{content}")
uid_logger_dubug("###222333####{last_content}")
uid_logger_dubug("content_#{@myshixun.identifier}: #{content}")
uid_logger_dubug("###last_content_#{@myshixun.identifier}####{last_content}")
if content != last_content
@content_modified = 1
@ -291,6 +293,7 @@ class MyshixunsController < ApplicationController
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
uid_logger_dubug("112233#{author_name}")
uid_logger_dubug("112233#{author_email}")
uid_logger_dubug("daiao_debug_#{@myshixun.identifier}: #{@repo_path}: #{path}; #{message}; #{content}; ")
@content = GitService.update_file(repo_path: @repo_path,
file_path: path,
message: message,

@ -1,13 +1,13 @@
class PollQuestionsController < ApplicationController
before_action :require_login, :check_auth
before_action :get_poll,only:[:new,:create]
before_action :get_poll_question,except: [:new,:create]
before_action :get_poll, only: [:new, :create]
before_action :get_poll_question, except: [:new, :create]
before_action :is_course_teacher
before_action :get_poll_questions_count,only:[:create]
before_action :get_poll_question_answers,only:[:edit,:update]
before_action :check_poll_status,only: [:new,:create,:delete_answer,:destroy]
before_action :validates_params,only:[:create,:update]
before_action :validates_update_params,only: [:update]
before_action :get_poll_questions_count, only: [:create]
before_action :get_poll_question_answers, only: [:edit, :update]
before_action :check_poll_status, only: [:new, :create, :delete_answer, :destroy]
before_action :validates_params, only: [:create, :update]
before_action :validates_update_params, only: [:update]
def new
@ -25,54 +25,48 @@ class PollQuestionsController < ApplicationController
# 创建题目和选择的答案
def create
ActiveRecord::Base.transaction do
begin
poll_options = {
:question_title => params[:question_title],
:question_type => params[:question_type],
:is_necessary => params[:is_necessary].to_i,
:question_number => @poll_ques_count + 1,
:max_choices => params[:max_choices] || nil,
:min_choices => params[:min_choices] || nil
}
@poll_question = @poll.poll_questions.new(poll_options)
poll_options = {
:question_title => params[:question_title],
:question_type => params[:question_type],
:is_necessary => params[:is_necessary].to_i,
:question_number => @poll_ques_count + 1,
:max_choices => params[:max_choices] || nil,
:min_choices => params[:min_choices] || nil
}
@poll_question = @poll.poll_questions.new(poll_options)
if params[:insert_id].present? #插入问题时那么从插入的这个id以后的question_num都将要+1
insert_poll = @poll.poll_questions.find_by(id: params[:insert_id])
if insert_poll.present? #如果该问题存在的话,意思是如果是第一题,那么就不存在插入
ques_num = insert_poll.question_number.to_i
@poll_question.question_number = ques_num + 1 #更新了问题的位置
@poll.poll_questions.insert_question(ques_num).update_all("question_number = question_number + 1")
end
if params[:insert_id].present? #插入问题时那么从插入的这个id以后的question_num都将要+1
insert_poll = @poll.poll_questions.find_by(id: params[:insert_id])
if insert_poll.present? #如果该问题存在的话,意思是如果是第一题,那么就不存在插入
ques_num = insert_poll.question_number.to_i
@poll_question.question_number = ques_num + 1 #更新了问题的位置
@poll.poll_questions.insert_question(ques_num).update_all("question_number = question_number + 1")
end
if @poll_question.save!
if params[:question_type] != 3
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
# 新增选择题答案选择的选项
(1..p_answer.count).each do |i|
answer = p_answer[i-1] # 传入的答案的内容
question_option = {
:answer_position => i,
:answer_text => answer
}
poll_answers = @poll_question.poll_answers.new question_option
poll_answers.save!
end
# 新增答案的其他选项
if p_other_answer
question_option = {
:answer_position => p_answer.count + 1,
:answer_text => ''
}
poll_answers = @poll_question.poll_answers.new question_option
poll_answers.save!
end
end
if @poll_question.save!
if params[:question_type] != 3
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
# 新增选择题答案选择的选项
(1..p_answer.count).each do |i|
answer = p_answer[i - 1] # 传入的答案的内容
question_option = {
:answer_position => i,
:answer_text => answer
}
poll_answers = @poll_question.poll_answers.new question_option
poll_answers.save!
end
# 新增答案的其他选项
if p_other_answer
question_option = {
:answer_position => p_answer.count + 1,
:answer_text => ''
}
poll_answers = @poll_question.poll_answers.new question_option
poll_answers.save!
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("问卷的问题创建失败!")
raise ActiveRecord::Rollback
end
end
end
@ -103,61 +97,55 @@ class PollQuestionsController < ApplicationController
def update
ActiveRecord::Base.transaction do
begin
if @poll_question.question_type < 3 #当为单选题或多选题时
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
p_answer_count = p_answer.count
@poll_question.poll_answers.each do |an|
if (p_answer_count < @poll_current_answers) && (p_answer_count..@poll_current_answers).to_a.include?(an.answer_position)
an.destroy
end
if @poll_question.question_type < 3 #当为单选题或多选题时
p_answer = params[:question_answers]
p_other_answer = params[:question_other_answer]
p_answer_count = p_answer.count
@poll_question.poll_answers.each do |an|
if (p_answer_count < @poll_current_answers) && (p_answer_count..@poll_current_answers).to_a.include?(an.answer_position)
an.destroy
end
(1..p_answer_count).each do |i|
answer = @poll_question.poll_answers.find_answer_by_custom("answer_position",i).first
if answer # 判断该位置的answer是否存在存在则更新.不存在则跳到下一步
answer.answer_text = p_answer[i-1]
answer.answer_position = i
answer.save!
else
answer_options = {
:answer_position => i,
:answer_text => p_answer[i-1]
}
@poll_question.poll_answers.new answer_options
end
end
(1..p_answer_count).each do |i|
answer = @poll_question.poll_answers.find_answer_by_custom("answer_position", i).first
if answer # 判断该位置的answer是否存在存在则更新.不存在则跳到下一步
answer.answer_text = p_answer[i - 1]
answer.answer_position = i
answer.save!
else
answer_options = {
:answer_position => i,
:answer_text => p_answer[i - 1]
}
@poll_question.poll_answers.new answer_options
end
if p_other_answer #判断答案的其他选项是否存在
other_answer = @poll_question.poll_answers.find_answer_by_custom("answer_text","").first
if other_answer.blank?
question_option = {
:answer_position => p_answer_count + 1,
:answer_text => ''
}
@poll_question.poll_answers.new question_option
else
other_answer.answer_position = p_answer_count + 1
other_answer.save!
end
end
if p_other_answer #判断答案的其他选项是否存在
other_answer = @poll_question.poll_answers.find_answer_by_custom("answer_text", "").first
if other_answer.blank?
question_option = {
:answer_position => p_answer_count + 1,
:answer_text => ''
}
@poll_question.poll_answers.new question_option
else
other_answer.answer_position = p_answer_count + 1
other_answer.save!
end
end
@poll_question.update!(poll_questions_params)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("更新失败")
raise ActiveRecord::Rollback
end
@poll_question.update!(poll_questions_params)
end
end
def delete_answer
ActiveRecord::Base.transaction do
begin
answer_d_id = params[:answer_no].to_i # 答案的当前位置
answer_d_id = params[:answer_no].to_i # 答案的当前位置
poll_answers = @poll_question.poll_answers
delete_answer = poll_answers.find_by(answer_position: answer_d_id)
left_answers = poll_answers.where("answer_position > ?",answer_d_id)
left_answers = poll_answers.where("answer_position > ?", answer_d_id)
left_answers.update_all("answer_position = answer_position - 1") if left_answers
if delete_answer.destroy
@ -175,7 +163,7 @@ class PollQuestionsController < ApplicationController
def destroy
ActiveRecord::Base.transaction do
begin
question_d_id = @poll_question.question_number.to_i #问题的当前位置
question_d_id = @poll_question.question_number.to_i #问题的当前位置
poll_questions = @poll.poll_questions
left_questions = poll_questions.insert_question(question_d_id)
left_questions.update_all("question_number = question_number - 1") if left_questions
@ -192,11 +180,11 @@ class PollQuestionsController < ApplicationController
ActiveRecord::Base.transaction do
begin
opr = params[:opr]
current_q_p = @poll_question.question_number.to_i #问题的当前位置
current_q_p = @poll_question.question_number.to_i #问题的当前位置
if @poll.polls_status.to_i == 1
if opr.present?
if opr.to_s == "up"
last_q_p = @poll.poll_questions.find_by(question_number: (current_q_p-1)) #当前问题的前一个问题
last_q_p = @poll.poll_questions.find_by(question_number: (current_q_p - 1)) #当前问题的前一个问题
if last_q_p.present?
@poll_question.update!(question_number: (current_q_p - 1))
last_q_p.update!(question_number: current_q_p) # 重新获取当前问题的位置
@ -205,7 +193,7 @@ class PollQuestionsController < ApplicationController
normal_status(-1, "移动失败,已经是第一个问题了!")
end
elsif opr.to_s == "down"
next_q_p = @poll.poll_questions.find_by(question_number: (current_q_p+1)) #当前问题的后一个问题
next_q_p = @poll.poll_questions.find_by(question_number: (current_q_p + 1)) #当前问题的后一个问题
if next_q_p.present?
@poll_question.update!(question_number: (current_q_p + 1))
next_q_p.update!(question_number: current_q_p)
@ -219,7 +207,7 @@ class PollQuestionsController < ApplicationController
normal_status(-1, "移动失败,请输入参数")
end
else
normal_status(-1,"已发布的不能移动问题")
normal_status(-1, "已发布的不能移动问题")
end
rescue Exception => e
uid_logger_error(e.message)
@ -231,7 +219,7 @@ class PollQuestionsController < ApplicationController
private
def poll_questions_params
params.require(:poll_question).permit(:question_title,:question_type,:is_necessary,:question_number,:max_choices,:min_choices)
params.require(:poll_question).permit(:question_title, :question_type, :is_necessary, :question_number, :max_choices, :min_choices)
end
def validates_params
@ -242,12 +230,12 @@ class PollQuestionsController < ApplicationController
normal_status(-1, "最小可选不能大于最大可选!")
elsif params[:question_answers].present? && (params[:max_choices].to_i > params[:question_answers].count)
normal_status(-1, "选择题的最大可选项不能大于答案数!")
elsif [1,3].include?(params[:question_type]) && (params[:max_choices].to_i > 0 || params[:min_choices].to_i > 0)
elsif [1, 3].include?(params[:question_type]) && (params[:max_choices].to_i > 0 || params[:min_choices].to_i > 0)
normal_status(-1, "单选题或主观题不能有最大或最小选择数!")
elsif params[:question_type] == 3 && (params[:question_answers] || params[:question_other_answer])
normal_status(-1, "主观问题不需要可选答案!")
elsif params[:question_type] != 3
if params[:question_answers].present? && params[:question_answers].select{|answer| answer.blank?}.count > 0
if params[:question_answers].present? && params[:question_answers].select {|answer| answer.blank?}.count > 0
normal_status(-1, "选项不能有空值!")
elsif params[:question_other_answer].present? && !params[:question_other_answer].blank?
normal_status(-1, "其他选项不能有值!")
@ -262,11 +250,11 @@ class PollQuestionsController < ApplicationController
def validates_update_params
question_a_count = params[:question_answers].present? ? params[:question_answers].count : 0
question_o_count = params[:question_other_answer].present? ? params[:question_other_answer].count : 0
normal_status(-1, "已发布的问卷不允许增删答案!") if (((question_a_count+question_o_count) != @poll_current_answers) && (@poll.polls_status.to_i != 1))
normal_status(-1, "已发布的问卷不允许增删答案!") if (((question_a_count + question_o_count) != @poll_current_answers) && (@poll.polls_status.to_i != 1))
end
def get_poll
@poll = Poll.find_by(id:params[:poll_id])
@poll = Poll.find_by(id: params[:poll_id])
if @poll.blank?
tip_exception(404)
end
@ -283,7 +271,7 @@ class PollQuestionsController < ApplicationController
def get_poll_question
@poll_question = PollQuestion.find_by(id: params[:id])
if @poll_question.present?
@poll = Poll.find_by(id:@poll_question.poll_id)
@poll = Poll.find_by(id: @poll_question.poll_id)
else
tip_exception(404)
end
@ -305,7 +293,7 @@ class PollQuestionsController < ApplicationController
tip_exception(404)
else
@identity = current_user.course_identity(@course)
normal_status(-1, "权限不够") unless(@course.present? && @identity < Course::STUDENT) #课堂存在,且当前用户为教师/管理员
normal_status(-1, "权限不够") unless (@course.present? && @identity < Course::STUDENT) #课堂存在,且当前用户为教师/管理员
end
end
end

@ -5,120 +5,114 @@ class PollVotesController < ApplicationController
before_action :check_answer_in_question
def create #每一次答案的点击,请求一次
begin
question_votes = @poll_question.poll_votes
question_type = @poll_question.question_type
question_answer_id = params[:poll_answer_id] ? params[:poll_answer_id] : -1 #该答案的id
question_answer_text = params[:vote_text].present? ? params[:vote_text] : nil #其他选项的内容
user_votes = question_votes.find_current_vote("user_id",current_user.id) #当前用户的答案,可能有多个
# 当前用户的当前答案,如果已存在,当再次点击的时候,取消答案,即删除该答案
current_vote_text = nil
def create #每一次答案的点击,请求一次
question_votes = @poll_question.poll_votes
question_type = @poll_question.question_type
question_answer_id = params[:poll_answer_id] ? params[:poll_answer_id] : -1 #该答案的id
question_answer_text = params[:vote_text].present? ? params[:vote_text] : nil #其他选项的内容
user_votes = question_votes.find_current_vote("user_id", current_user.id) #当前用户的答案,可能有多个
# 当前用户的当前答案,如果已存在,当再次点击的时候,取消答案,即删除该答案
current_vote_text = nil
# if user_votes.find_vote_text.present?
# current_vote_text = user_votes.find_vote_text.first
# end
# if user_votes.find_vote_text.present?
# current_vote_text = user_votes.find_vote_text.first
# end
vote_answer_params = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => question_answer_id,
:vote_text => question_answer_text
}
#begin
if question_type == 1
if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建
current_user_answer = user_votes.first
if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录
current_user_answer.destroy
PollVote.create!(vote_answer_params)
else
vote_answer_params = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => question_answer_id,
:vote_text => question_answer_text
}
#begin
if question_type == 1
if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建
current_user_answer = user_votes.first
if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录
current_user_answer.destroy
PollVote.create!(vote_answer_params)
else
if question_answer_text.present?
current_user_answer.update!(vote_text: question_answer_text)
end
if question_answer_text.present?
current_user_answer.update!(vote_text: question_answer_text)
end
else
PollVote.create!(vote_answer_params)
end
elsif question_type == 2 #多选题的话答案应该是1个以上
question_answer_ids = params[:poll_answer_id] ? params[:poll_answer_id] : [] #该答案的id
if question_answer_ids.present?
if question_answer_text.present? #有文字输入,但是不存在其他选项的
ques_vote_id = question_answer_ids.map(&:to_i).max
ques_vote = user_votes.find_by(poll_answer_id: ques_vote_id)
if ques_vote.present?
ques_vote.update!(vote_text: question_answer_text)
else
answer_option = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => ques_vote_id,
:vote_text => question_answer_text
}
PollVote.create!(answer_option)
# 重新取一次poll_votes
user_votes = @poll_question.poll_votes.find_current_vote("user_id",current_user.id)
end
# if current_vote_text.present? #已有其他输入文字的选项
# current_vote_text.update_attribute("vote_text", question_answer_text)
# else
#
# end
else
PollVote.create!(vote_answer_params)
end
elsif question_type == 2 #多选题的话答案应该是1个以上
question_answer_ids = params[:poll_answer_id] ? params[:poll_answer_id] : [] #该答案的id
if question_answer_ids.present?
if question_answer_text.present? #有文字输入,但是不存在其他选项的
ques_vote_id = question_answer_ids.map(&:to_i).max
ques_vote = user_votes.find_by(poll_answer_id: ques_vote_id)
if ques_vote.present?
ques_vote.update!(vote_text: question_answer_text)
else
answer_option = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => ques_vote_id,
:vote_text => question_answer_text
}
PollVote.create!(answer_option)
# 重新取一次poll_votes
user_votes = @poll_question.poll_votes.find_current_vote("user_id", current_user.id)
end
# if current_vote_text.present? #已有其他输入文字的选项
# current_vote_text.update_attribute("vote_text", question_answer_text)
# else
#
# end
end
ea_ids = user_votes.pluck(:poll_answer_id)
common_answer_ids = question_answer_ids & ea_ids #已经存在的试卷选项id
new_ids = question_answer_ids - common_answer_ids # 新增的id
old_ids = ea_ids - common_answer_ids #没有选择的,则删掉
if new_ids.size > 0
new_ids.each do |e|
answer_option = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => e,
:vote_text => nil
}
ex_a = PollVote.new(answer_option)
ex_a.save!
end
ea_ids = user_votes.pluck(:poll_answer_id)
common_answer_ids = question_answer_ids & ea_ids #已经存在的试卷选项id
new_ids = question_answer_ids - common_answer_ids # 新增的id
old_ids = ea_ids - common_answer_ids #没有选择的,则删掉
if new_ids.size > 0
new_ids.each do |e|
answer_option = {
:user_id => current_user.id,
:poll_question_id => @poll_question.id,
:poll_answer_id => e,
:vote_text => nil
}
ex_a = PollVote.new(answer_option)
ex_a.save!
end
if old_ids.size > 0
ea_answer = user_votes.find_current_vote("poll_answer_id",old_ids)
ea_answer.destroy_all
end
else
user_votes.destroy_all
end
else #主观题的输入
# current_vote_text = user_votes.find_vote_text
if user_votes.present?
user_votes.first.update!(vote_text: question_answer_text)
# if question_answer_text.present?
# user_votes.first.update_attribute("vote_text", question_answer_text)
# else
# user_votes.destroy_all
# end
else
PollVote.create!(vote_answer_params)
if old_ids.size > 0
ea_answer = user_votes.find_current_vote("poll_answer_id", old_ids)
ea_answer.destroy_all
end
else
user_votes.destroy_all
end
@current_question_number = @poll_question.question_number
@current_question_necessary = @poll_question.is_necessary
#问答记录存在,且有值,才会有返回值。
@current_question_status = 0
new_user_votes = question_votes.where(user_id: current_user.id)
if new_user_votes.present?
vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size
vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size
if vote_text_count > 0 || vote_answer_id > 0
@current_question_status = 1
end
else #主观题的输入
# current_vote_text = user_votes.find_vote_text
if user_votes.present?
user_votes.first.update!(vote_text: question_answer_text)
# if question_answer_text.present?
# user_votes.first.update_attribute("vote_text", question_answer_text)
# else
# user_votes.destroy_all
# end
else
PollVote.create!(vote_answer_params)
end
end
@current_question_number = @poll_question.question_number
@current_question_necessary = @poll_question.is_necessary
#问答记录存在,且有值,才会有返回值。
@current_question_status = 0
new_user_votes = question_votes.where(user_id: current_user.id)
if new_user_votes.present?
vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size
vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size
if vote_text_count > 0 || vote_answer_id > 0
@current_question_status = 1
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
@ -128,14 +122,14 @@ class PollVotesController < ApplicationController
def get_poll_question
@poll_question = PollQuestion.find_by_id(params[:poll_question_id])
if @poll_question.blank?
normal_status(-1,"问卷试题不存在!")
normal_status(-1, "问卷试题不存在!")
else
@poll = @poll_question.poll
@course = @poll.course
if @poll.blank?
normal_status(-1,"问卷不存在!")
normal_status(-1, "问卷不存在!")
elsif @course.blank?
normal_status(-1,"课堂不存在!")
normal_status(-1, "课堂不存在!")
end
end
end
@ -146,7 +140,7 @@ class PollVotesController < ApplicationController
question_type = @poll_question&.question_type
if (question_type == 1) && params[:poll_answer_id].blank?
normal_status(-1,"答案ID错误!")
normal_status(-1, "答案ID错误!")
elsif question_type == 2
user_vote_count = params[:poll_answer_id].size
if @poll_question.max_choices.present?
@ -155,10 +149,10 @@ class PollVotesController < ApplicationController
question_max_choices = 0
end
if question_max_choices > 0 && (user_vote_count > question_max_choices)
normal_status(-1,"多选题答案超过最大限制!")
normal_status(-1, "多选题答案超过最大限制!")
end
elsif (poll_user.present? && poll_user.commit_status == 1) || poll_user_status == 3
normal_status(-1,"已提交/已结束的问卷不允许修改!")
normal_status(-1, "已提交/已结束的问卷不允许修改!")
end
end

File diff suppressed because it is too large Load Diff

@ -26,7 +26,7 @@ class ShixunsController < ApplicationController
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
before_action :shixun_marker, only: [:new, :create]
before_action :validate_wachat_support, only: [:shixun_exec]
#before_action :validate_wachat_support, only: [:shixun_exec]
skip_before_action :check_sign, only: [:download_file]
## 获取课程列表
@ -475,7 +475,7 @@ class ShixunsController < ApplicationController
if params[:shixun][:vnc]
shixun_params.merge(vnc_evaluate: 1)
else
shixun_params
shixun_params.merge(vnc_evaluate: 0)
end
@shixun.update_attributes!(update_params)
end
@ -1187,11 +1187,11 @@ private
md5.hexdigest
end
def validate_wachat_support
if (params[:wechat].present? && !@shixun.is_wechat_support?)
tip_exception(-5, "..")
end
end
# def validate_wachat_support
#
# if (params[:wechat].present? && !@shixun.is_wechat_support?)
# tip_exception(-5, "..")
# end
# end
end

@ -72,7 +72,7 @@ class SubjectsController < ApplicationController
end
# 排序
order_str = reorder == "publish_time" ? "status = 2 desc, publish_time asc" : "updated_at desc"
order_str = (reorder == "publish_time" ? "homepage_show desc, excellent desc, status = 2 desc, publish_time asc" : "homepage_show desc, excellent desc, updated_at desc")
@subjects = @subjects.reorder(order_str)
end
@ -242,13 +242,13 @@ class SubjectsController < ApplicationController
## 云上实验室过滤
@courses = @courses.where(id: current_laboratory.all_courses)
@none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id)
@none_shixun_ids = @subject.shixuns.joins(:shixun_schools).where("school_id != #{current_user.user_extension.try(:school_id).to_i}").where(use_scope: 1).pluck(:id)
end
def send_to_course
@course = Course.find_by!(id: params[:course_id])
stages = @subject.stages.where(id: @subject.stage_shixuns.where(shixun_id: params[:shixun_ids]).pluck(:stage_id))
stages = @subject.stages.where(id: @subject.stage_shixuns.where(shixun_id: params[:shixun_ids]).pluck(:stage_id)).reorder("stages.position DESC")
order_ids = params[:shixun_ids].size > 0 ? params[:shixun_ids].reverse.join(',') : -1
course_module = @course.course_modules.where(module_type: "shixun_homework").first
homework_ids = []
@ -259,7 +259,8 @@ class SubjectsController < ApplicationController
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
stage.shixuns.no_jupyter.where(id: params[:shixun_ids], status: 2).each do |shixun|
shixuns = stage.shixuns.no_jupyter.published.where(id: params[:shixun_ids]).reorder("field(shixuns.id, #{order_ids})")
shixuns.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user
homework_ids << homework.id
end

@ -2,8 +2,6 @@ class TagDisciplinesController < ApplicationController
before_action :require_login
def create
tip_exception("请输入知识点") if params[:name].blank?
tip_exception("输入字符长度限制在15个以内") if params[:name].length > 15
sub_discipline = SubDiscipline.find_by!(id: params[:sub_discipline_id])
tip_exception("重复的知识点") if sub_discipline.tag_disciplines.exists?(name: params[:name].to_s.strip)
tag_discipline = TagDiscipline.create!(name: params[:name].to_s.strip, sub_discipline: sub_discipline, user_id: current_user.id)

@ -5,7 +5,7 @@ class TidingsController < ApplicationController
after_action :update_onclick_time!, only: [:index]
def index
tidings = current_user.tidings
tidings = current_user.tidings.visible
@onclick_time = current_user.click_time
tiding_types =
@ -19,8 +19,9 @@ class TidingsController < ApplicationController
end
tidings = tidings.where(tiding_type: tiding_types) if tiding_types.present?
tidings = tidings.where(container_type: 'JoinCourse') if params[:type] == 'course_apply'
@course_apply_count = tidings.where("created_at > '#{@onclick_time}'").where(container_type: 'JoinCourse').count
tidings = tidings.where(container_type: 'JoinCourse', status: 0) if params[:type] == 'course_apply'
# @course_apply_count = tidings.where("created_at > '#{@onclick_time}'").where(container_type: 'JoinCourse', status: 0).count
@course_apply_count = tidings.where(container_type: 'JoinCourse', status: 0).count
tidings = tidings.where(container_type: 'ProjectPackage') if params[:type] == 'project_package'

@ -13,7 +13,7 @@ class Users::VideosController < Users::BaseController
end
def update
return render_error('该状态下不能编辑视频信息') unless current_video.published?
return render_error('该状态下不能编辑视频信息') unless (current_video.published? || current_video.course_videos.present?)
current_video.update!(title: params[:title])
@ -39,6 +39,13 @@ class Users::VideosController < Users::BaseController
@videos = paginate videos
end
def get_video_data
start_time = params[:start_time].to_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
end_time = params[:end_time].to_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
result = AliyunVod::Service.video_data(current_video.uuid, start_time, end_time)
render :json => {data: result}
end
def batch_publish
Videos::BatchPublishService.call(observed_user, batch_publish_params)
render_ok
@ -50,6 +57,14 @@ class Users::VideosController < Users::BaseController
def current_video
@_current_video ||= observed_user.videos.find_by(id: params[:id])
if @_current_video.nil?
video = Video.find_by(id: params[:id])
if video.course_videos.present?
video
end
else
@_current_video
end
end
def search_params
@ -57,6 +72,6 @@ class Users::VideosController < Users::BaseController
end
def batch_publish_params
params.permit(videos: %i[video_id title])
params.permit(videos: %i[video_id title course_id])
end
end

@ -52,7 +52,7 @@ class UsersController < ApplicationController
def attachment_show
file_name = params[:file_name]
path = params[:path]
path = params[:path] || edu_setting('attachment_folder')
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
:type => 'game',
:disposition => 'attachment' #inline can open in browser

@ -0,0 +1,26 @@
class Weapps::ChallengesController < Weapps::BaseController
before_action :require_login
before_action :set_challenge
def is_play
# 关卡有展示效果 || 选择题 || jupyter实训 || vnc || 隐藏代码窗口 || html+css实训
# @challenge.show_type != -1 || @challenge.st == 1 || @shixun.is_jupyter? || @shixun.vnc ||
# @shixun.hide_code? || (@shixun.small_mirror_name & ["Css", "Html", "Web"]).present?
play = @challenge.st == 1 || @shixun.is_jupyter? || @shixun.vnc ||
@shixun.hide_code? || (@shixun.small_mirror_name & ["Css", "Html", "Web"]).present?
if play
normal_status(-5, "该关卡暂不支持小程序")
else
render_ok
end
end
private
def set_challenge
@challenge = Challenge.find_by!(id: params[:id])
@shixun = @challenge.shixun
end
end

@ -1,7 +1,8 @@
class Weapps::CoursesController < Weapps::BaseController
before_action :require_login
before_action :set_course, :user_course_identity, except: [:create]
before_action :check_account, only: [:create]
before_action :set_course, except: [:create, :check_invite_code]
before_action :user_course_identity, except: [:basic_info, :create, :check_invite_code]
before_action :check_account, only: [:create, :check_invite_code]
before_action :teacher_allowed, only: [:edit, :update]
before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers]
@ -9,19 +10,23 @@ class Weapps::CoursesController < Weapps::BaseController
# return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher?
course = Course.new(tea_id: current_user.id)
Weapps::CreateCourseService.call(course, course_params)
render_ok
render_ok(id: course.id)
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def basic_info
@course = current_course
end
def edit
@course = current_course
end
def update
Weapps::UpdateCourseService.call(current_course, update_course_params)
render_ok
course = Weapps::UpdateCourseService.call(current_course, update_course_params)
render_ok(id: course.id)
end
def show
@ -33,6 +38,23 @@ class Weapps::CoursesController < Weapps::BaseController
@categories = current_course.shixun_course_modules.first&.course_second_categories
end
def check_invite_code
tip_exception(-1, "邀请码不能为空") if params[:invite_code].blank?
invite_code = params[:invite_code]
course = Course.find_by(invite_code: invite_code, is_delete: 0, invite_code_halt: 0)
course_group = CourseGroup.find_by(invite_code: invite_code)
if course.blank?
tip_exception(-1, "邀请码无效") if course_group.blank?
course = Course.find_by(id: course_group.course_id, is_delete: 0, invite_code_halt: 0)
tip_exception(-1, "邀请码无效") if course.blank?
end
tip_exception(-1, "课堂已结束,无法加入") if course.is_end
render_ok
end
# 教师列表
def teachers
@course = current_course
@ -179,11 +201,11 @@ class Weapps::CoursesController < Weapps::BaseController
private
def course_params
params.permit(:name, :course_list_name, :credit, course_module_types: [])
params.permit(:name, :course_list_name, :credit, :end_date, course_module_types: [])
end
def update_course_params
params.permit(:name, :course_list_name, :credit)
params.permit(:name, :course_list_name, :credit, :end_date)
end
def current_course

@ -17,7 +17,13 @@ class Weapps::SessionsController < Weapps::BaseController
# session[:wechat_user_extra].delete(:nickName)
# 绑定微信号
OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
# open_user = OpenUsers::Wechat.find_by(uid: session_unionid)
# if open_user.present? && open_user.user_id.nil?
# open_user.update!(user_id: user.id)
# els
if user.wechat_open_user.blank?
OpenUsers::Wechat.create!(user: user, uid: session_unionid)
end
successful_authentication(user)
end

@ -0,0 +1,15 @@
class Weapps::ShixunListsController < ApplicationController
before_action :require_login
def index
results = Weapps::ShixunSearchService.call(search_params, current_laboratory)
@total_count = results.size
@results = paginate results
end
private
def search_params
params.permit(:keyword, :type, :page, :limit, :order, :status, :diff, :sort, :no_jupyter)
end
end

@ -0,0 +1,28 @@
class Weapps::SubjectsController < Weapps::BaseController
before_action :require_login
before_action :find_subject, except: [:index]
# 首页
def index
subjects = Weapps::SubjectQuery.call(current_laboratory, params)
@subject_count = subjects.map(&:id).size
@subjects = paginate subjects
end
# 详情
def show
# 合作团队
Rails.logger.info("##########subject: #{@subject.id}")
@members = @subject.subject_members.includes(:user)
shixuns = @subject.shixuns.published.pluck(:id)
challenge_ids = Challenge.where(shixun_id: shixuns).pluck(:id)
# 实训路径中的所有实训标签
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
end
private
def find_subject
@subject = Subject.find(params[:id])
end
end

@ -0,0 +1,16 @@
class Weapps::UnbindAccountsController < Weapps::BaseController
before_action :require_login
def show
@user = current_user
end
def destroy
open_user = OpenUsers::Wechat.find_by!(user_id: current_user.id)
session[:unionid] = open_user.uid
open_user.destroy!
UserAction.create(action_id: current_user.id, action_type: "UnbindWechat", user_id: current_user.id, :ip => request.remote_ip)
logout_user
render_ok
end
end

@ -321,6 +321,10 @@ module TidingDecorator
I18n.t(locale_format(parent_container_type)) % container&.exercise_name
end
def live_link_content
I18n.t(locale_format) % container&.course_name
end
def student_graduation_topic_content
I18n.t(locale_format) % container&.graduation_topic.try(:name)
end

@ -7,8 +7,6 @@ class ItemBanks::SaveItemForm
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, too_long: "不能超过1000个字符" }
validates :analysis, length: { maximum: 1000, too_long: "不能超过1000个字符" }
def validate!
super
@ -27,7 +25,6 @@ class ItemBanks::SaveItemForm
attr_accessor :choice_text, :is_answer
validates :choice_text, presence: true, length: { maximum: 500, too_long: "不能超过500个字符" }
validates :is_answer, presence: true, inclusion: {in: 0..1}, numericality: { only_integer: true }
end
end

@ -2,7 +2,7 @@ class Weapps::CreateCourseForm
include ActiveModel::Model
attr_accessor :course
attr_accessor :name, :course_list_name, :credit, :course_module_types
attr_accessor :name, :course_list_name, :credit, :course_module_types, :end_date
validates :name, presence: true
validates :course_list_name, presence: true

@ -2,7 +2,7 @@ class Weapps::UpdateCourseForm
include ActiveModel::Model
attr_accessor :course
attr_accessor :name, :course_list_name, :credit
attr_accessor :name, :course_list_name, :credit, :end_date
validates :name, presence: true
validates :course_list_name, presence: true

@ -65,6 +65,8 @@ module CoursesHelper
"/courses/#{course.id}/course_groups"
when "statistics"
"/courses/#{course.id}/statistics"
when "video"
"/courses/#{course.id}/course_videos"
end
end
@ -126,6 +128,8 @@ module CoursesHelper
course.informs.count
when "online_learning"
course.shixuns.count
when "video"
course.course_videos.count + course.live_links.count
end
end

@ -171,10 +171,10 @@ module HomeworkCommonsHelper
{status: status, time: time}
end
# 作品数统计type 1 已提交 0 未提交
# 作品数统计type 1 已提交 0 未提交 2 所有
def studentwork_count homework_common, type, member
student_works = homework_common.teacher_works(member)
type == 1 ? student_works.where("work_status != 0").size : student_works.where(work_status: 0).size
type == 2 ? student_works.size : (type == 1 ? student_works.where("work_status != 0").size : student_works.where(work_status: 0).size)
end
# 上次查重的时间

@ -152,7 +152,7 @@ module ShixunsHelper
challenge_program_name = []
shixun.challenges.map(&:exec_path).each do |exec_path|
challenge_program_name << "\"#{exec_path}\""
if shixun.main_mirror_name == "Java"
if shixun.main_mirror_name == "Java" || shixun.main_mirror_name == "Openjdk10/VNC"
if exec_path.nil? || exec_path.split("src/")[1].nil?
source = "\"\""
else

@ -1,15 +1,16 @@
module Weapps::CoursesHelper
require 'chinese_pinyin'
def teacher_list teachers
def teacher_list teachers, user_course_identity
data = []
teachers.each do |teacher|
if teacher.user.present?
teacher_user = teacher.user
name = teacher_user.real_name
role = teacher.role == "CREATOR" ? "管理员" : teacher.role == "PROFESSOR" ? "教师" : "助教"
member_roles = user_course_identity < Course::ASSISTANT_PROFESSOR ? teacher_user.course_role(teacher.course) : []
item = {name: name, course_member_id: teacher.id, login: teacher_user.login, user_id: teacher.user_id, role: role,
school: teacher_user.school_name, image_url: url_to_avatar(teacher_user)}
school: teacher_user.school_name, image_url: url_to_avatar(teacher_user), member_roles: member_roles}
pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0]
letter = first_letter first_char
@ -28,15 +29,16 @@ module Weapps::CoursesHelper
end
def student_list students, excellent
def student_list students, excellent, user_course_identity
data = []
students.each do |student|
if student.user.present?
student_user = student.user
name = student_user.real_name
phone = excellent ? "" : student_user.hidden_phone
member_roles = user_course_identity < Course::ASSISTANT_PROFESSOR ? student_user.course_role(student.course) : []
item = {name: name, course_member_id: student.id, login: student_user.login, user_id: student.user_id,
student_id: student_user.student_id, image_url: url_to_avatar(student_user), phone: phone}
student_id: student_user.student_id, image_url: url_to_avatar(student_user), phone: phone, member_roles: member_roles}
pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0]
letter = first_letter first_char

@ -0,0 +1,27 @@
# 直播开启的消息通知
class LivePublishJob < ApplicationJob
queue_as :notify
def perform(live_id)
live = LiveLink.find_by(id: live_id)
return if live.blank? || live.course.blank?
course = live.course
attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type
belong_container_id belong_container_type viewed tiding_type created_at updated_at
]
same_attrs = {
trigger_user_id: live.user_id, container_id: live.id, container_type: 'LiveLink',
parent_container_id: live.id, parent_container_type: 'LiveLink',
belong_container_id: live.course_id, belong_container_type: 'Course',
viewed: 0, tiding_type: 'LiveLink'
}
Tiding.bulk_insert(*attrs) do |worker|
course.students.pluck(:user_id).each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

@ -37,4 +37,19 @@ module AliyunVod::Service::VideoManage
result
end
# 视频播放数据
def video_data(video_id, start_time, end_time)
params = {
Action: 'DescribePlayVideoStatis',
VideoId: video_id,
StartTime: start_time,
EndTime: end_time,
}.merge(base_params)
puts params
result = request(:post, params)
result
end
end

@ -4,4 +4,5 @@ module CustomRegexp
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
end

@ -28,7 +28,7 @@ class Challenge < ApplicationRecord
scope :fields_for_list, -> { select([:id, :subject, :st, :score, :position, :shixun_id]) }
validates :task_pass, length: { maximum: 10000, too_long: "不能超过10000个字符" }
validates :task_pass, length: { maximum: 35000, too_long: "不能超过35000个字符" }
after_commit :create_diff_record

@ -3,7 +3,7 @@ class ChallengeAnswer < ApplicationRecord
belongs_to :challenge
has_many :game_answers, :dependent => :destroy
validates :contents, length: { maximum: 5000 , too_long: "不能超过5000个字符"}
validates :contents, length: { maximum: 25000 , too_long: "不能超过25000个字符"}
def view_answer_time(user_id)
game_answers.where(user_id: user_id).last&.view_time

@ -4,6 +4,6 @@ class ChallengeChoose < ApplicationRecord
has_many :challenge_tags, :dependent => :destroy
has_many :challenge_questions, dependent: :destroy
validates :subject, length: { maximum: 1000, too_long: "不能超过1000个字符" }
validates :subject, length: { maximum: 25000, too_long: "不能超过25000个字符" }
end

@ -81,6 +81,13 @@ class Course < ApplicationRecord
# 老版的members弃用 现用course_members
has_many :members
# 视频
has_many :course_videos, dependent: :destroy
has_many :videos, through: :course_videos
# 直播
has_many :live_links, dependent: :destroy
validate :validate_sensitive_string
scope :hidden, ->(is_hidden = true) { where(is_hidden: is_hidden) }
@ -206,7 +213,7 @@ class Course < ApplicationRecord
end
def all_course_module_types
%w[activity announcement online_learning shixun_homework common_homework group_homework exercise attachment course_group graduation poll board statistics]
%w[activity announcement online_learning shixun_homework common_homework group_homework exercise attachment course_group graduation poll board statistics video]
end
def get_course_module_by_type(type)
@ -406,6 +413,7 @@ class Course < ApplicationRecord
when 'exercise' then '试卷'
when 'poll' then '问卷'
when 'attachment' then '资源'
when 'video' then '视频直播'
when 'board' then '讨论'
when 'course_group' then '分班'
when 'statistics' then '统计'
@ -425,9 +433,10 @@ class Course < ApplicationRecord
when 'exercise' then 8
when 'poll' then 9
when 'attachment' then 10
when 'board' then 11
when 'course_group' then 12
when 'statistics' then 13
when 'video' then 11
when 'board' then 12
when 'course_group' then 13
when 'statistics' then 14
else 100
end
end

@ -0,0 +1,4 @@
class CourseVideo < ApplicationRecord
belongs_to :course
belongs_to :video
end

@ -4,4 +4,7 @@ class Discipline < ApplicationRecord
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"
validates_presence_of :name
end

@ -35,7 +35,7 @@ class HomeworkCommon < ApplicationRecord
# 学生的查重情况
has_many :homework_review_results, :dependent => :destroy
validates :name, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :name, presence: true, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :description, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :explanation, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :reference_answer, length: { maximum: 15000, too_long: "不能超过15000个字符" }

@ -1,3 +1,4 @@
class ItemAnalysis < ApplicationRecord
belongs_to :item_bank, touch: true
validates :analysis, length: { maximum: 5000, too_long: "不能超过5000个字符" }
end

@ -13,6 +13,7 @@ class ItemBank < ApplicationRecord
has_many :tag_disciplines, through: :tag_discipline_containers
belongs_to :container, polymorphic: true, optional: true
validates :name, presence: true, length: { maximum: 1000, too_long: "不能超过1000个字符" }
def analysis
item_analysis&.analysis

@ -1,3 +1,5 @@
class ItemChoice < ApplicationRecord
belongs_to :item_bank, touch: true
validates :choice_text, presence: true, length: { maximum: 500, too_long: "不能超过500个字符" }
end

@ -0,0 +1,21 @@
class LiveLink < ApplicationRecord
belongs_to :course
belongs_to :user
has_many :tidings, as: :container, dependent: :destroy
# validates :url, format: { with: CustomRegexp::URL, message: "必须为网址超链接" }
validates :description, length: { maximum: 100, too_long: "不能超过100个字符" }
validates :course_name, presence: true
validates :platform, presence: true
# validates :live_time, presence: true
validates :duration, numericality: { only_integer: true, greater_than: 0}, allow_blank: true
def op_auth?
user == User.current || User.current.admin_or_business?
end
def delete_auth?
user == User.current || User.current.admin?
end
end

@ -8,6 +8,7 @@ class MirrorRepository < ApplicationRecord
scope :published_mirror, -> { where(status: [1,2,3,5]) }
scope :published_main_mirror, -> { published_mirror.where(main_type: 1) }
scope :published_small_mirror, -> { published_mirror.where(main_type: 0) }
scope :small_mirror, -> { where(main_type: 0) }
def deletable?
status != 1 && !shixun_mirror_repositories.exists?

@ -0,0 +1,7 @@
class Salesman < ApplicationRecord
belongs_to :user
# 渠道
has_many :salesman_channels, dependent: :destroy
# 客户
has_many :salesman_customers, dependent: :destroy
end

@ -0,0 +1,3 @@
class SalesmanChannel < ApplicationRecord
belongs_to :salesman, :touch => true, counter_cache: true
end

@ -0,0 +1,22 @@
class SalesmanCustomer < ApplicationRecord
belongs_to :salesman, :touch => true, counter_cache: true
belongs_to :school
belongs_to :user
def name
user.real_name
end
def school_name
school.name
end
def courses_count
CourseMember.where(user_id: id).teachers_and_admin.count
end
def shixuns_count
ShixunMember.where(user_id: id, role: [1, 2]).count
end
end

@ -171,7 +171,8 @@ class Shixun < ApplicationRecord
# 实训对应的镜像小类别名(已选)
def small_mirror_name
mirror_repositories.published_small_mirror.map(&:type_name)
names = mirror_repositories.small_mirror.map(&:type_name)
names.blank? ? [] : names
end
def small_mirror_id

@ -111,6 +111,7 @@ class StudentWork < ApplicationRecord
# 作品总体评价
def overall_appraisal
return "--" if work_status == 0
case (self.work_score.to_f / homework_common.total_score).round(2)
when (0.90..1.00)
'优秀'

@ -1,9 +1,13 @@
class SubDiscipline < ApplicationRecord
belongs_to :discipline
has_many :tag_disciplines, dependent: :destroy
has_many :sub_discipline_containers, 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"
validates_presence_of :name
end

@ -0,0 +1,5 @@
class SubDisciplineContainer < ApplicationRecord
belongs_to :sub_discipline
belongs_to :container, polymorphic: true, optional: true, touch: true
end

@ -30,6 +30,8 @@ class Subject < ApplicationRecord
has_many :subject_course_records, dependent: :destroy
has_many :subject_shixun_infos, dependent: :destroy
has_many :subject_user_infos, dependent: :destroy
has_many :sub_discipline_containers, as: :container, dependent: :destroy
has_many :sub_disciplines, through: :sub_discipline_containers
validates :name, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :description, length: { maximum: 8000, too_long: "不能超过8000个字符" }
@ -63,6 +65,10 @@ class Subject < ApplicationRecord
excellent ? CourseMember.where(role: 4, course_id: courses.pluck(:id)).pluck(:user_id).length : shixuns.pluck(:myshixuns_count).sum
end
def myshixuns_count
shixuns.pluck(:myshixuns_count).sum
end
def all_score
subject_shixun_score + subject_shixun_choose_score
end

@ -4,6 +4,7 @@ class TagDiscipline < ApplicationRecord
has_many :tag_discipline_containers, dependent: :destroy
validates_presence_of :name
validates :name, length: { maximum: 15, too_long: "不能超过15个字符" }
def discipline
sub_discipline&.discipline

@ -1,7 +1,7 @@
class TestSet < ApplicationRecord
# match_rule: 匹配规则: full 完全匹配, last 末尾匹配
#
validates :input, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :output, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :input, length: { maximum: 65000, too_long: "不能超过65000个字符" }
validates :output, length: { maximum: 65000, too_long: "不能超过65000个字符" }
end

@ -7,6 +7,8 @@ class Tiding < ApplicationRecord
has_many :attachments, as: :container
scope :visible, -> { where(is_delete: 0) }
def identifier
value = nil

@ -4,6 +4,7 @@ class Video < ApplicationRecord
belongs_to :user
has_many :video_applies, dependent: :destroy
has_many :course_videos, dependent: :destroy
has_one :processing_video_apply, -> { where(status: :pending) }, class_name: 'VideoApply'
aasm(:status) do
@ -33,4 +34,8 @@ class Video < ApplicationRecord
transitions from: :uploading, to: :uploaded
end
end
def video_play_duration
(play_duration / (60*60.0)).ceil
end
end

@ -0,0 +1,37 @@
class Weapps::SubjectQuery < ApplicationQuery
include CustomSortable
attr_reader :params
def initialize(current_laboratory, params)
@current_laboratory = current_laboratory
@params = params
end
def call
subjects = @current_laboratory.subjects.unhidden.visible
# 课程体系的过滤
if params[:sub_discipline_id].present?
subjects = subjects.joins(:sub_disciplines).where(sub_disciplines: {id: params[:sub_discipline_id]})
elsif params[:discipline_id].present?
subjects = subjects.joins(:sub_disciplines).where(sub_disciplines: {discipline_id: params[:discipline_id]})
else
subjects = subjects.joins(:sub_discipline_containers).where(sub_discipline_containers: {container_type: "Subject"})
end
subjects = subjects.left_joins(:shixuns).select('subjects.id, subjects.name, subjects.excellent, subjects.stages_count, subjects.status, subjects.homepage_show,
subjects.shixuns_count, subjects.updated_at, IFNULL(sum(shixuns.myshixuns_count), 0) myshixuns_count')
.group('subjects.id').order("subjects.homepage_show #{sort_type}, #{order_type} #{sort_type}")
subjects
end
private
def order_type
params[:order] || "updated_at"
end
def sort_type
params[:sort] || "desc"
end
end

@ -36,10 +36,10 @@ class Admins::ImportCourseMemberService < ApplicationService
member = course.course_members.find_by(user_id: user.id, role: data.role.to_i)
# 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班
if member.present? && member.role == 'STUDENT' && course_group && member.course_group_id != course_group&.id
member.update!(course_group_id: course_group&.id)
if member.present? && member.role == 'STUDENT' && course_group && member.course_group_id != course_group&.id.to_i
member.update!(course_group_id: course_group&.id.to_i)
elsif member.blank?
course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id)
course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id.to_i)
extra =
case data.role.to_i
when 2 then 9

@ -60,7 +60,7 @@ class Subjects::CopySubjectService < ApplicationService
shixun = stage_shixun.shixun
to_shixun = Shixun.new
to_shixun.attributes = shixun.attributes.dup.except('id', 'user_id', 'identifier', 'homepage_show',
'use_scope', 'averge_star', 'myshixuns_count', 'challenges_count', "public")
'use_scope', 'averge_star', 'myshixuns_count', 'challenges_count')
to_shixun.identifier = Util::UUID.generate_identifier(Shixun, 8)
to_shixun.user_id = user.id
if laboratory

@ -22,7 +22,7 @@ class Subjects::CourseUsedInfoService < ApplicationService
# choice_shixun_frequency: 选用该课程实训的次数
course_info = []
schools.find_in_batches do |s|
Parallel.each(s) do |school|
s.each do |school|
name = school.name
course_count = school.course_count
student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size

@ -11,7 +11,7 @@ class Subjects::ShixunUsedInfoService < ApplicationService
position = stage.position
shixuns = stage.shixuns.includes(myshixuns: :games, homework_commons: :course)
shixuns.find_in_batches(batch_size: 1000) do |s|
Parallel.each_with_index(s, in_processes: 2) do |shixun, index|
s.each_with_index do |shixun, index|
stage = "#{position}-#{index+1}"
name = shixun.name
myshixuns = shixun.myshixuns

@ -13,7 +13,7 @@ class Subjects::UserUsedInfoService < ApplicationService
users_info = []
users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2}, users: {is_test: false})
users.find_in_batches(batch_size: 500) do |u|
Parallel.each(u, in_processes: 2) do |user|
u.each do |user|
myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)}
name = "#{user.lastname}#{user.firstname}"
passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size

@ -11,22 +11,38 @@ class Videos::BatchPublishService < ApplicationService
def call
video_params = Array.wrap(params[:videos]).compact
return if video_params.blank?
Rails.logger.info("#####video_course: #{video_params}")
video_ids = []
ActiveRecord::Base.transaction do
video_params.each do |param|
video = user.videos.find_by(uuid: param[:video_id])
Rails.logger.info("video.processing_video_apply:#{video}")
Rails.logger.info("video.processing_video_apply:#{video.blank? || video.processing_video_apply}")
next if video.blank? || video.processing_video_apply.present?
raise Error, '视频还未上传完成' if video.vod_uploading?
video.title = param[:title].to_s.strip.presence || video.title
video.apply_publish
if param[:course_id].present?
video.status = "published"
end
video.save!
video.video_applies.create!
if param[:course_id].present?
video.video_applies.create!(status: "agreed")
else
video.video_applies.create!
end
video_ids << video.id
# 如果是课堂上传则创建课堂记录
Rails.logger.info("#####param: #{ param[:course_id]}")
if param[:course_id].present?
video.course_videos.create!(course_id: param[:course_id])
end
end
end

@ -20,6 +20,9 @@ class Videos::DispatchCallbackService < ApplicationService
return if video.cover_url.present?
video.update!(cover_url: params['CoverUrl'])
when 'TranscodeComplete' then # 转码完成
return if video.play_url.present?
video.update!(play_url: params['FileUrl'])
end
rescue => ex

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save