Merge branches 'dev_aliyun' and 'dev_new_shixunsrepository' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_new_shixunsrepository

 Conflicts:
	public/react/src/modules/tpm/TPMIndex.js
dev_new_shixunsrepository
杨树明 5 years ago
commit f022a8139e

2
.gitignore vendored

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

@ -49,6 +49,8 @@ gem 'rqrcode_png'
gem 'acts-as-taggable-on', '~> 6.0' gem 'acts-as-taggable-on', '~> 6.0'
gem 'omniauth-cas'
group :development, :test do group :development, :test do
gem 'rspec-rails', '~> 3.8' gem 'rspec-rails', '~> 3.8'
end end

@ -120,5 +120,19 @@ $(document).on('turbolinks:load', function() {
}); });
} }
}); });
// ------------ 上移/下移 -------------
$('.discipline-list-container').on('click', ".move-action", function () {
var $doAction = $(this);
var disciplineId = $doAction.data('id');
var opr = $doAction.data('opr');
$.ajax({
url: '/admins/disciplines/' + disciplineId + '/adjust_position',
method: 'POST',
dataType: 'script',
data: {opr: opr}
});
});
} }
}); });

@ -1,31 +1,42 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function () {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-discipline-modal', function(){ $('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-discipline-modal', function () {
var $modal = $('.modal.admin-edit-discipline-modal'); var $modal = $('.modal.admin-edit-discipline-modal');
var $form = $modal.find('form.admin-edit-discipline-form'); var $form = $modal.find('form.admin-edit-discipline-form');
$form.validate({ $form.validate({
errorElement: 'span', errorElement: 'span',
errorClass: 'danger text-danger', errorClass: 'danger text-danger',
rules: { rules: {
'discipline[name]': { 'discipline[name]': {
required: true, required: true,
maxlength: 20 maxlength: 20
} }
} }
}); });
$modal.on('click', '.submit-btn', function(){ $modal.on('click', '.submit-btn', submit_edit_form);
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) { $form.find("#discipline_name").keydown(function (e) {
$.ajax({ var ev = e || event;
method: 'PATCH', var keycode = ev.which || ev.keyCode;
dataType: 'script', if (keycode == 13) {
url: url, submit_edit_form();
data: $form.serialize() 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() { $(document).on('turbolinks:load', function () {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-sub-discipline-modal', function(){ $('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-sub-discipline-modal', function () {
var $modal = $('.modal.admin-edit-sub-discipline-modal'); var $modal = $('.modal.admin-edit-sub-discipline-modal');
var $form = $modal.find('form.admin-edit-sub-discipline-form'); var $form = $modal.find('form.admin-edit-sub-discipline-form');
$form.validate({ $form.validate({
errorElement: 'span', errorElement: 'span',
errorClass: 'danger text-danger', errorClass: 'danger text-danger',
rules: { rules: {
'sub_discipline[name]': { 'sub_discipline[name]': {
required: true, required: true,
maxlength: 20 maxlength: 20
} }
} }
}); });
$modal.on('click', '.submit-btn', function(){ $modal.on('click', '.submit-btn', submit_edit_form);
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) { $form.find("#sub_discipline_name").keydown(function (e) {
$.ajax({ var ev = e || event;
method: 'PATCH', var keycode = ev.which || ev.keyCode;
dataType: 'script', if (keycode == 13) {
url: url, submit_edit_form();
data: $form.serialize() 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() { $(document).on('turbolinks:load', function () {
$('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-tag-discipline-modal', function(){ $('.admin-modal-container').on('show.bs.modal', '.modal.admin-edit-tag-discipline-modal', function () {
var $modal = $('.modal.admin-edit-tag-discipline-modal'); var $modal = $('.modal.admin-edit-tag-discipline-modal');
var $form = $modal.find('form.admin-edit-tag-discipline-form'); var $form = $modal.find('form.admin-edit-tag-discipline-form');
$form.validate({ $form.validate({
errorElement: 'span', errorElement: 'span',
errorClass: 'danger text-danger', errorClass: 'danger text-danger',
rules: { rules: {
'tag_discipline[name]': { 'tag_discipline[name]': {
required: true, required: true,
maxlength: 20 maxlength: 20
} }
} }
}); });
$modal.on('click', '.submit-btn', function(){ $modal.on('click', '.submit-btn', submit_edit_form);
$form.find('.error').html('');
var url = $form.attr('action');
if ($form.valid()) { $form.find("#tag_discipline_name").keydown(function (e) {
$.ajax({ var ev = e || event;
method: 'PATCH', var keycode = ev.which || ev.keyCode;
dataType: 'script', if (keycode == 13) {
url: url, submit_edit_form();
data: $form.serialize() 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,119 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-salesman-channels-index-page').length > 0) {
// ============= 添加销售人员 ==============
var $addMemberModal = $('.admin-add-salesman-channel-user-modal');
var $addMemberForm = $addMemberModal.find('.admin-add-salesman-channel-user-form');
var $memberSelect = $addMemberModal.find('.salesman-channel-user-select');
var $form = $addMemberModal.find('form.admin-add-salesman-user-form');
// 搜索
var searchscForm = $(".saleman-channel-list-form .search-form");
$addMemberModal.on('show.bs.modal', function(event){
$memberSelect.select2('val', ' ');
});
$memberSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的单位',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/admins/schools',
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 '';
return $("<span>" + item.name + "</span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.name || '';
}
});
$addMemberModal.on('click', '.submit-btn', function(){
$addMemberForm.find('.error').html('');
// var salesmanId = $salesmanIdInput.val();
var memberIds = $memberSelect.val();
if (memberIds && memberIds.length > 0) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$addMemberModal.modal('hide');
searchscForm.find('input[name="keyword"]').val('');
setTimeout(function(){
submitForm();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$addMemberForm.find('.error').html(data.message);
}
});
} else {
$addMemberModal.modal('hide');
}
});
// 清空
searchscForm.on('click', '.clear-btn', function () {
searchscForm.find('.start_date').val('');
searchscForm.find('.end_date').val('').trigger('change');
searchscForm.find('input[name="keyword"]').val('');
});
// 时间跨度
var baseOptions = {
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd',
startDate: '2017-04-01'
};
var defineDateRangeSelect = function(element){
var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, baseOptions);
$(element).datepicker(options);
$(element).find('.start-date').datepicker().on('changeDate', function(e){
$(element).find('.end-date').datepicker('setStartDate', e.date);
});
};
defineDateRangeSelect('.grow-date-input-daterange');
// 区间搜索
searchscForm.on('click', ".search-btn", function(){
submitForm();
});
var submitForm = function(){
var url = searchscForm.data('search-form-url');
var form = searchscForm;
$.ajax({
url: url,
data: form.serialize(),
dataType: "script"
})
};
}
});

@ -0,0 +1,82 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-salesman-customers-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-customer-user-select');
var $salesmanIdInput = $('.salesman-customer-list-form').find(".btn-primary");
$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: { salesman_id: $salesmanIdInput.data("salesman-id"), user_ids: memberIds },
success: function(){
$.notify({ message: '创建成功' });
$addMemberModal.modal('hide');
setTimeout(function(){
listForm();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
} else {
$addMemberModal.modal('hide');
}
});
var listForm = function(){
$.ajax({
url: '/admins/salesman_customers?salesman_id='+ $salesmanIdInput.data("salesman-id"),
dataType: "script"
});
};
}
});

@ -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", type: "PUT",
dataType:'script', dataType:'script',
data: json 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({ $("select#settings-tag-choosed").select2({
placeholder: "请选择分类", placeholder: "请选择分类",
allowClear: true allowClear: true

@ -1,65 +1,89 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function () {
if ($('body.admins-sub-disciplines-index-page').length > 0) { if ($('body.admins-sub-disciplines-index-page').length > 0) {
// ============== 新建 =============== // ============== 新建 ===============
var $modal = $('.modal.admin-create-sub-discipline-modal'); var $modal = $('.modal.admin-create-sub-discipline-modal');
var $form = $modal.find('form.admin-create-sub-discipline-form'); var $form = $modal.find('form.admin-create-sub-discipline-form');
var $nameInput = $form.find('input[name="name"]'); var $nameInput = $form.find('input[name="name"]');
$form.validate({ $form.validate({
errorElement: 'span', errorElement: 'span',
errorClass: 'danger text-danger', errorClass: 'danger text-danger',
rules: { rules: {
name: { name: {
required: true required: true
} }
} }
}); });
// modal ready fire // modal ready fire
$modal.on('show.bs.modal', function () { $modal.on('show.bs.modal', function () {
$nameInput.val(''); $nameInput.val('');
}); });
$modal.on('click', '.submit-btn', function(){ $modal.on('click', '.submit-btn', submit_create_form);
$form.find('.error').html('');
$nameInput.keydown(function (e) {
var ev = e || event;
var keycode = ev.which || ev.keyCode;
if (keycode == 13) {
submit_create_form();
return false;
}
});
if ($form.valid()) { function submit_create_form() {
var url = $form.data('url'); $form.find('.error').html('');
$.ajax({ if ($form.valid()) {
method: 'POST', var url = $form.data('url');
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '创建成功' });
$modal.modal('hide');
setTimeout(function(){ $.ajax({
window.location.reload(); method: 'POST',
}, 500); dataType: 'json',
}, url: url,
error: function(res){ data: $form.serialize(),
var data = res.responseJSON; success: function () {
$form.find('.error').html(data.message); $.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
});
}); });
} // ------------ 上移/下移 -------------
}); $('.sub-discipline-list-container').on('click', ".move-action", function () {
var $doAction = $(this);
$(".sub-discipline-list-container").on("change", '.sub-discipline-source-form', function () { var objectId = $doAction.data('id');
var s_id = $(this).attr("data-id"); var opr = $doAction.data('opr');
var s_value = $(this).val(); $.ajax({
var s_name = $(this).attr("name"); url: '/admins/sub_disciplines/' + objectId + '/adjust_position',
var json = {}; method: 'POST',
json[s_name] = s_value; dataType: 'script',
$.ajax({ data: {opr: opr}
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,72 @@
$(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('#homepage_show').attr('checked', false);
$form.find('#excellent').attr('checked', false); $form.find('#excellent').attr('checked', false);
$form.find('input[type="submit"]').trigger('click'); $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) { var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.subject-list-container').on('click', doElement, function () { $('.subject-list-container').on('click', doElement, function () {

@ -1,65 +1,90 @@
$(document).on('turbolinks:load', function() { $(document).on('turbolinks:load', function () {
if ($('body.admins-tag-disciplines-index-page').length > 0) { if ($('body.admins-tag-disciplines-index-page').length > 0) {
// ============== 新建 =============== // ============== 新建 ===============
var $modal = $('.modal.admin-create-tag-discipline-modal'); var $modal = $('.modal.admin-create-tag-discipline-modal');
var $form = $modal.find('form.admin-create-tag-discipline-form'); var $form = $modal.find('form.admin-create-tag-discipline-form');
var $nameInput = $form.find('input[name="name"]'); var $nameInput = $form.find('input[name="name"]');
$form.validate({ $form.validate({
errorElement: 'span', errorElement: 'span',
errorClass: 'danger text-danger', errorClass: 'danger text-danger',
rules: { rules: {
name: { name: {
required: true required: true
} }
} }
}); });
// modal ready fire
$modal.on('show.bs.modal', function () {
$nameInput.val('');
});
$modal.on('click', '.submit-btn', submit_create_form);
// modal ready fire $nameInput.keydown(function (e) {
$modal.on('show.bs.modal', function () { var ev = e || event;
$nameInput.val(''); var keycode = ev.which || ev.keyCode;
}); if (keycode == 13) {
submit_create_form();
return false;
}
});
function submit_create_form() {
$form.find('.error').html('');
$modal.on('click', '.submit-btn', function(){ if ($form.valid()) {
$form.find('.error').html(''); var url = $form.data('url');
if ($form.valid()) { $.ajax({
var url = $form.data('url'); method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function () {
$.notify({message: '创建成功'});
$modal.modal('hide');
$.ajax({ setTimeout(function () {
method: 'POST', window.location.reload();
dataType: 'json', }, 500);
url: url, },
data: $form.serialize(), error: function (res) {
success: function(){ var data = res.responseJSON;
$.notify({ message: '创建成功' }); $form.find('.error').html(data.message);
$modal.modal('hide'); }
});
}
}
setTimeout(function(){ $(".tag-discipline-list-container").on("change", '.tag-discipline-source-form', function () {
window.location.reload(); var s_id = $(this).attr("data-id");
}, 500); var s_value = $(this).val();
}, var s_name = $(this).attr("name");
error: function(res){ var json = {};
var data = res.responseJSON; json[s_name] = s_value;
$form.find('.error').html(data.message); $.ajax({
} url: "/admins/tag_disciplines/" + s_id,
type: "PUT",
dataType: 'script',
data: json
});
}); });
}
});
$(".tag-discipline-list-container").on("change", '.tag-discipline-source-form', function () { // ------------ 上移/下移 -------------
var s_id = $(this).attr("data-id"); $('.tag-discipline-list-container').on('click', ".move-action", function () {
var s_value = $(this).val(); var $doAction = $(this);
var s_name = $(this).attr("name");
var json = {}; var objectId = $doAction.data('id');
json[s_name] = s_value; var opr = $doAction.data('opr');
$.ajax({ $.ajax({
url: "/admins/tag_disciplines/" + s_id, url: '/admins/tag_disciplines/' + objectId + '/adjust_position',
type: "PUT", method: 'POST',
dataType:'script', dataType: 'script',
data: json data: {opr: opr}
}); });
}); });
} }
}); });

@ -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
});
});
}
});

@ -51,12 +51,12 @@ class AccountsController < ApplicationController
# todo user_extension # todo user_extension
UserExtension.create!(user_id: @user.id) UserExtension.create!(user_id: @user.id)
# 注册完成手机号或邮箱想可以奖励500金币 # 注册完成手机号或邮箱想可以奖励500金币
RewardGradeService.call( # RewardGradeService.call(
@user, # @user,
container_id: @user.id, # container_id: @user.id,
container_type: pre == 'p' ? 'Phone' : 'Mail', # container_type: pre == 'p' ? 'Phone' : 'Mail',
score: 500 # score: 500
) # )
# 注册时,记录是否是引流用户 # 注册时,记录是否是引流用户
ip = request.remote_ip ip = request.remote_ip
ua = UserAgent.find_by_ip(ip) ua = UserAgent.find_by_ip(ip)
@ -167,7 +167,7 @@ class AccountsController < ApplicationController
end end
# 检验邮箱是否已被注册及邮箱或者手机号是否合法 # 检验邮箱是否已被注册及邮箱或者手机号是否合法
# 参数type为事件类型 1注册2忘记密码 # 参数type为事件类型 1注册2忘记密码3绑定
def valid_email_and_phone def valid_email_and_phone
check_mail_and_phone_valid(params[:login], params[:type]) check_mail_and_phone_valid(params[:login], params[:type])
end end

@ -7,7 +7,7 @@ class Admins::DisciplinesController < Admins::BaseController
def create def create
name = params[:name].to_s.strip name = params[:name].to_s.strip
return render_error('名称重复') if Discipline.where(name: name).exists? return render_error('名称重复') if Discipline.where(name: name).exists?
Discipline.create!(name: name) Discipline.create!(name: name, position: Discipline.all.pluck(:position).max + 1)
render_ok render_ok
end end
@ -16,26 +16,54 @@ class Admins::DisciplinesController < Admins::BaseController
end end
def update def update
if params[:discipline] && params[:discipline][:name].present? begin
name = params[:discipline][:name].to_s.strip if params[:discipline] && params[:discipline][:name]
current_discipline.update_attributes!(name: name) name = params[:discipline][:name].to_s.strip
else current_discipline.update_attributes!(name: name)
ActiveRecord::Base.transaction do else
current_discipline.update_attributes!(setting_params) ActiveRecord::Base.transaction do
current_discipline.sub_disciplines.each do |sub| current_discipline.update_attributes!(setting_params)
sub.tag_disciplines.each do |tag| current_discipline.sub_disciplines.each do |sub|
tag.update_attributes!(setting_params) sub.tag_disciplines.each do |tag|
tag.update_attributes!(setting_params)
end
sub.update_attributes!(setting_params)
end end
sub.update_attributes!(setting_params)
end end
end end
rescue Exception => e
@message = e.message
end end
@disciplines = Discipline.all @disciplines = Discipline.all
end end
def destroy def destroy
@discipline_id = params[:id] @discipline_id = params[:id]
current_discipline.destroy! ActiveRecord::Base.transaction do
Discipline.where("position > #{current_discipline.position}").update_all("position=position-1")
current_discipline.destroy!
end
end
def adjust_position
max_position = Discipline.all.pluck(:position).max
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_discipline.position == 1) || (params[:opr] == "down" && current_discipline.position == max_position)
@message = "超出范围"
else
ActiveRecord::Base.transaction do
if opr == "up"
Discipline.find_by("position = #{current_discipline.position - 1}")&.update!(position: current_discipline.position)
current_discipline.update!(position: current_discipline.position - 1)
else
Discipline.find_by("position = #{current_discipline.position + 1}")&.update!(position: current_discipline.position)
current_discipline.update!(position: current_discipline.position + 1)
end
end
end
@disciplines = Discipline.all
rescue Exception => e
@message = e.message
end end
private private

@ -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,35 @@
class Admins::SalesmanChannelsController < Admins::BaseController
before_action :set_salesman
def index
@channels = @salesman.salesman_channels
if params[:keyword].present?
@channels = @channels.joins(:school).where("schools.name like ?", "%#{params[:keyword]}%")
end
@start_time = params[:start_date]
@end_time = params[:end_date].blank? ? Time.now : params[:end_date]
end
def batch_add
channel_ids = @salesman.salesman_channels.pluck(:school_id)
school_ids = params[:school_ids] - channel_ids
school_ids.each do |school_id|
school = School.find_by(id: school_id)
next if school.blank? || @salesman.salesman_channels.where(school_id: school.id).exists?
@salesman.salesman_channels.create!(school_id: school.id)
end
render_ok
rescue Exception => ex
render_error(ex.message)
end
def destroy
@salesman.salesman_channels.find_by!(id: params[:id]).destroy
end
private
def set_salesman
@salesman = Salesman.find params[:salesman_id]
end
end

@ -0,0 +1,28 @@
class Admins::SalesmanCustomersController < Admins::BaseController
before_action :set_salesman
def index
@customers = @salesman.salesman_customers.includes(:user, :school)
end
def batch_add
customer_ids = @salesman.salesman_customers.pluck(:user_id)
user_ids = params[:user_ids] - customer_ids
user_ids.each do |user_id|
user = UserExtension.find_by(user_id: user_id)
next if user.blank? || @salesman.salesman_customers.where(user_id: user.user_id).exists?
@salesman.salesman_customers.create!(user_id: user.user_id, school_id: user.school_id)
end
render_ok
end
def destroy
@salesman.salesman_customers.find_by!(id: params[:id]).destroy
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

@ -4,7 +4,7 @@ class Admins::SchoolsController < Admins::BaseController
params[:sort_direction] ||= 'desc' params[:sort_direction] ||= 'desc'
schools = Admins::SchoolQuery.call(params) schools = Admins::SchoolQuery.call(params)
@total_count = schools.map(&:id).count
@schools = paginate schools @schools = paginate schools
school_ids = @schools.map(&:id) school_ids = @schools.map(&:id)

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

@ -7,8 +7,9 @@ class Admins::SubDisciplinesController < Admins::BaseController
def create def create
name = params[:name].to_s.strip name = params[:name].to_s.strip
return render_error('名称不能为空') if name.blank?
return render_error('名称重复') if current_discipline.sub_disciplines.where(name: name).exists? return render_error('名称重复') if current_discipline.sub_disciplines.where(name: name).exists?
SubDiscipline.create!(name: name, discipline_id: current_discipline.id) SubDiscipline.create!(name: name, discipline_id: current_discipline.id, position: current_discipline.sub_disciplines.pluck(:position).max + 1)
render_ok render_ok
end end
@ -17,25 +18,56 @@ class Admins::SubDisciplinesController < Admins::BaseController
end end
def update def update
if params[:sub_discipline] && params[:sub_discipline][:name].present? begin
name = params[:sub_discipline][:name].to_s.strip if params[:sub_discipline] && params[:sub_discipline][:name]
current_sub_discipline.update_attributes!(name: name) name = params[:sub_discipline][:name].to_s.strip
else current_sub_discipline.update_attributes!(name: name)
ActiveRecord::Base.transaction do else
current_sub_discipline.update_attributes!(setting_params) ActiveRecord::Base.transaction do
current_sub_discipline.tag_disciplines.each do |tag| current_sub_discipline.update_attributes!(setting_params)
tag.update_attributes!(setting_params) current_sub_discipline.tag_disciplines.each do |tag|
tag.update_attributes!(setting_params)
end
end end
end end
rescue Exception => e
@message = e.message
end end
@sub_disciplines = current_sub_discipline.discipline&.sub_disciplines @sub_disciplines = current_sub_discipline.discipline&.sub_disciplines
end end
def destroy def destroy
@sub_discipline_id = params[:id] @sub_discipline_id = params[:id]
current_sub_discipline.destroy! ActiveRecord::Base.transaction do
discipline = current_sub_discipline.discipline
discipline.sub_disciplines.where("position > #{current_sub_discipline.position}").update_all("position=position-1")
current_sub_discipline.destroy!
end
end end
def adjust_position
discipline = current_sub_discipline.discipline
max_position = discipline.sub_disciplines.pluck(:position).max
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_sub_discipline.position == 1) || (params[:opr] == "down" && current_sub_discipline.position == max_position)
@message = "超出范围"
else
ActiveRecord::Base.transaction do
if opr == "up"
discipline.sub_disciplines.find_by("position = #{current_sub_discipline.position - 1}")&.update!(position: current_sub_discipline.position)
current_sub_discipline.update!(position: current_sub_discipline.position - 1)
else
discipline.sub_disciplines.find_by("position = #{current_sub_discipline.position + 1}")&.update!(position: current_sub_discipline.position)
current_sub_discipline.update!(position: current_sub_discipline.position + 1)
end
end
end
@sub_disciplines = discipline&.sub_disciplines
rescue Exception => e
@message = e.message
end
private private
def current_sub_discipline def current_sub_discipline

@ -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,34 @@
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
def update_mobile_show
subject = Subject.find(params[:subject_id])
subject.update_attributes(:show_mobile => params[:show_mobile])
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') default_sort('created_at', 'desc')
subjects = Admins::SubjectQuery.call(params) 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 end
def edit def edit
@ -14,7 +14,7 @@ class Admins::SubjectsController < Admins::BaseController
current_subject.update!(update_params) current_subject.update!(update_params)
flash[:success] = '保存成功' flash[:success] = '保存成功'
redirect_to admins_subjects_path redirect_to admins_subject_settings_path
end end
def destroy def destroy
@ -49,7 +49,7 @@ class Admins::SubjectsController < Admins::BaseController
# 设为金课 # 设为金课
def excellent def excellent
current_subject.update!(excellent: true) current_subject.update!(excellent: true, public: 2)
render_ok render_ok
end end

@ -8,7 +8,8 @@ class Admins::TagDisciplinesController < Admins::BaseController
def create def create
name = params[:name].to_s.strip name = params[:name].to_s.strip
return render_error('名称重复') if current_sub_discipline.tag_disciplines.where(name: name).exists? return render_error('名称重复') if current_sub_discipline.tag_disciplines.where(name: name).exists?
TagDiscipline.create!(name: name, sub_discipline_id: current_sub_discipline.id, user_id: current_user.id) TagDiscipline.create!(name: name, sub_discipline_id: current_sub_discipline.id, user_id: current_user.id,
position: current_sub_discipline.tag_disciplines.pluck(:position).max + 1)
render_ok render_ok
end end
@ -17,20 +18,51 @@ class Admins::TagDisciplinesController < Admins::BaseController
end end
def update def update
if params[:tag_discipline] && params[:tag_discipline][:name].present? begin
name = params[:tag_discipline][:name].to_s.strip if params[:tag_discipline] && params[:tag_discipline][:name]
current_tag_discipline.update_attributes!(name: name) name = params[:tag_discipline][:name].to_s.strip
else current_tag_discipline.update_attributes!(name: name)
current_tag_discipline.update_attributes!(setting_params) else
current_tag_discipline.update_attributes!(setting_params)
end
rescue Exception => e
@message = e.message
end end
@tag_disciplines = current_tag_discipline.sub_discipline&.tag_disciplines @tag_disciplines = current_tag_discipline.sub_discipline&.tag_disciplines
end end
def destroy def destroy
@tag_discipline_id = params[:id] @tag_discipline_id = params[:id]
current_tag_discipline.destroy! ActiveRecord::Base.transaction do
sub_discipline = current_tag_discipline.sub_discipline
sub_discipline.tag_disciplines.where("position > #{current_tag_discipline.position}").update_all("position=position-1")
current_tag_discipline.destroy!
end
end end
def adjust_position
sub_discipline = current_tag_discipline.sub_discipline
max_position = sub_discipline.tag_disciplines.pluck(:position).max
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_tag_discipline.position == 1) || (params[:opr] == "down" && current_tag_discipline.position == max_position)
@message = "超出范围"
else
ActiveRecord::Base.transaction do
if opr == "up"
sub_discipline.tag_disciplines.find_by("position = #{current_tag_discipline.position - 1}")&.update!(position: current_tag_discipline.position)
current_tag_discipline.update!(position: current_tag_discipline.position - 1)
else
sub_discipline.tag_disciplines.find_by("position = #{current_tag_discipline.position + 1}")&.update!(position: current_tag_discipline.position)
current_tag_discipline.update!(position: current_tag_discipline.position + 1)
end
end
end
@tag_disciplines = sub_discipline&.tag_disciplines
rescue Exception => e
@message = e.message
end
private private
def current_sub_discipline def current_sub_discipline

@ -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

@ -48,6 +48,19 @@ class ApplicationController < ActionController::Base
EduSetting.get(name) EduSetting.get(name)
end end
# 平台身份权限判断(学生用户无权限)
def identity_auth
ue = current_user.user_extension
tip_exception(403, "..") unless current_user.admin_or_business? || ue.teacher? || ue.professional?
end
# 平台已认证身份判断(已认证的老师和专业人士)
def certi_identity_auth
ue = current_user.user_extension
tip_exception(403, "..") unless current_user.admin_or_business? ||
(current_user.professional_certification && (ue.teacher? || ue.professional?))
end
def shixun_marker def shixun_marker
unless current_user.is_shixun_marker? || current_user.admin_or_business? unless current_user.is_shixun_marker? || current_user.admin_or_business?
tip_exception(403, "..") tip_exception(403, "..")
@ -73,7 +86,7 @@ class ApplicationController < ActionController::Base
check_account check_account
tip_exception(@course.excellent ? 410 : 409, "您没有权限进入") tip_exception(@course.excellent ? 410 : 409, "您没有权限进入")
end end
if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT && @course.tea_id != current_user.id
# 实名认证和职业认证的身份判断 # 实名认证和职业认证的身份判断
tip_exception(411, "你的实名认证和职业认证审核未通过") if @course.authentication && tip_exception(411, "你的实名认证和职业认证审核未通过") if @course.authentication &&
@course.professional_certification && (!current_user.authentication && !current_user.professional_certification) @course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
@ -92,7 +105,7 @@ class ApplicationController < ActionController::Base
# 判断用户的邮箱或者手机是否可用 # 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码 # params[:type] 1: 注册2忘记密码3绑定
def check_mail_and_phone_valid login, type 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}$/ || 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])$/ login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
@ -104,6 +117,8 @@ class ApplicationController < ActionController::Base
tip_exception(-2, "该手机号码或邮箱已被注册") tip_exception(-2, "该手机号码或邮箱已被注册")
elsif type.to_i == 2 && user.nil? elsif type.to_i == 2 && user.nil?
tip_exception(-2, "该手机号码或邮箱未注册") tip_exception(-2, "该手机号码或邮箱未注册")
elsif type.to_i == 3 && user.present?
tip_exception(-2, "该手机号码或邮箱已绑定")
end end
sucess_status sucess_status
end end
@ -218,7 +233,7 @@ class ApplicationController < ActionController::Base
# 未授权的捕捉407弹试用申请弹框 # 未授权的捕捉407弹试用申请弹框
def require_login def require_login
#6.13 -hs #6.13 -hs
tip_exception(401, "..") unless User.current.logged? tip_exception(401, "请登录后再操作") unless User.current.logged?
end end
# 异常提醒 # 异常提醒
@ -632,7 +647,8 @@ class ApplicationController < ActionController::Base
end end
def paginate(relation) 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 page = params[:page].to_i.zero? ? 1 : params[:page].to_i
offset = (page - 1) * limit offset = (page - 1) * limit
@ -643,6 +659,8 @@ class ApplicationController < ActionController::Base
end end
end end
def strf_time(time) def strf_time(time)
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S") time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
end end

@ -17,9 +17,11 @@ class AttachmentsController < ApplicationController
redirect_to @file.cloud_url and return redirect_to @file.cloud_url and return
end end
pdf_attachment = params[:disposition] || "attachment" type_attachment = params[:disposition] || "attachment"
if pdf_attachment == "inline" if type_attachment == "inline"
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf' 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 else
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream') send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
end end
@ -202,4 +204,31 @@ class AttachmentsController < ApplicationController
end end
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 end

@ -1,13 +1,35 @@
class BindUsersController < ApplicationController class BindUsersController < ApplicationController
before_action :require_login # before_action :require_login
def create def create
user = CreateBindUserService.call(current_user, create_params) # user = CreateBindUserService.call(create_params)
successful_authentication(user) if user.id != current_user.id #
if params[:type] == "qq"
begin
user = CreateBindUserService.call(current_user, create_params)
successful_authentication(user) if user.id != current_user.id
render_ok render_ok
rescue ApplicationService::Error => ex rescue ApplicationService::Error => ex
render_error(ex.message) render_error(ex.message)
end
else
begin
tip_exception '系统错误' if session[:unionid].blank?
bind_user = User.try_to_login(params[:username], params[:password])
tip_exception '用户名或者密码错误' if bind_user.blank?
tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s)
tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
OpenUsers::Wechat.create!(user: bind_user, uid: session[:unionid])
successful_authentication(bind_user)
render_ok
rescue Exception => e
render_error(e.message)
end
end
end end
def new_user def new_user

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

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

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

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

@ -16,5 +16,25 @@ module RenderExpand
send_data kit.to_pdf, filename: options[:filename], disposition: options[:disposition] || 'attachment', type: 'application/pdf' send_data kit.to_pdf, filename: options[:filename], disposition: options[:disposition] || 'attachment', type: 'application/pdf'
end end
ActionController.add_renderer :exam_pdf do |template, options|
file = File.open(Rails.root.join('app/templates', template << '.html.erb'))
html = ERB.new(file.read).result(binding)
kit = PDFKit.new(html)
# PDFKit初始化后再添加样式文件到stylesheets会出现在页面的<!DOCTYPE>定义不起作用文档模式为默认为BackCompat从而导致katex不起作用
# 而测试发现通过配置添加css样式文件不会有影响
PDFKit.configure do |config|
config.default_options = {
:"user-style-sheet" => Rails.root.join('app/templates', options[:stylesheets])
}
end
send_data kit.to_pdf, filename: options[:filename], disposition: options[:disposition] || 'attachment', type: 'application/pdf'
end
end end
end end

@ -2,7 +2,7 @@ class CourseGroupsController < ApplicationController
before_action :require_login, :check_auth before_action :require_login, :check_auth
before_action :set_group, except: [:create] before_action :set_group, except: [:create]
before_action :find_course, only: [:create] before_action :find_course, only: [:create]
before_action :teacher_allowed before_action :teacher_allowed, except: [:set_invite_code_halt]
def create def create
tip_exception("分班名称不能为空") if params[:name].blank? tip_exception("分班名称不能为空") if params[:name].blank?
@ -55,6 +55,15 @@ class CourseGroupsController < ApplicationController
end end
end end
# 邀请码停用/启用
def set_invite_code_halt
teacher = @course.teachers.find_by(user_id: current_user.id)
tip_exception(403, "无权限") unless current_user.admin_or_business? ||
(teacher.present? && (teacher.teacher_course_groups.pluck(:course_group_id).include?(@group.id) || teacher.teacher_course_groups.size == 0))
@group.update!(invite_code_halt: !@group.invite_code_halt)
normal_status(0, "成功")
end
private private
def set_group def set_group

@ -1,6 +1,7 @@
class CoursesController < ApplicationController class CoursesController < ApplicationController
include MessagesHelper include MessagesHelper
include ExportHelper include ExportHelper
include CustomSortable
# model validation error # model validation error
rescue_from ActiveRecord::RecordInvalid do |ex| rescue_from ActiveRecord::RecordInvalid do |ex|
@ -12,7 +13,7 @@ class CoursesController < ApplicationController
end end
before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups, before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
:left_banner, :top_banner, :informs, :online_learning, :course_groups] :left_banner, :top_banner, :informs, :online_learning, :course_groups, :search_slim]
before_action :check_account, only: [:new, :create, :apply_to_join_course, :join_excellent_course] before_action :check_account, only: [:new, :create, :apply_to_join_course, :join_excellent_course]
before_action :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups, before_action :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
:left_banner, :top_banner, :apply_to_join_course, :exit_course, :course_groups] :left_banner, :top_banner, :apply_to_join_course, :exit_course, :course_groups]
@ -23,8 +24,8 @@ class CoursesController < ApplicationController
:course_group_list, :set_course_group, :change_course_admin, :change_course_teacher, :course_group_list, :set_course_group, :change_course_admin, :change_course_teacher,
:delete_course_teacher, :teacher_application_review, :students, :all_course_groups, :delete_course_teacher, :teacher_application_review, :students, :all_course_groups,
:transfer_to_course_group, :delete_from_course, :search_users, :add_students_by_search, :transfer_to_course_group, :delete_from_course, :search_users, :add_students_by_search,
:base_info, :get_historical_courses, :create_group_by_importing_file, :base_info, :get_historical_courses, :create_group_by_importing_file, :course_videos,
:attahcment_category_list,:export_member_scores_excel, :duplicate_course, :attahcment_category_list,:export_member_scores_excel, :duplicate_course, :delete_course_video,
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course, :switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course,
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list, :informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs, :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) @courses = @courses.preload(:school, :none_hidden_course_modules, teacher: :user_extension)
end 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 def visits_plus_one
new_visits = @course.visits + 1 new_visits = @course.visits + 1
@course.update_visits(new_visits) @course.update_visits(new_visits)
@ -377,8 +395,7 @@ class CoursesController < ApplicationController
def destroy def destroy
if @course.is_delete == 0 if @course.is_delete == 0
@course.delete! @course.delete!
Tiding.create!(user_id: current_user.id, trigger_user_id: current_user.id, container_id: @course.id, DeleteCourseNotifyJob.perform_later(@course.id, current_user.id)
container_type: 'DeleteCourse', tiding_type: 'System', belong_container: @course, extra: @course.name)
normal_status(0, "成功") normal_status(0, "成功")
else else
normal_status(-1, "课堂已删除,无需重复操作") normal_status(-1, "课堂已删除,无需重复操作")
@ -723,12 +740,15 @@ class CoursesController < ApplicationController
# 切换为教师 # 切换为教师
def switch_to_teacher def switch_to_teacher
begin begin
course_member = @course.course_members.find_by!(user_id: current_user.id, is_active: 1) course_student = @course.students.find_by!(user_id: current_user.id, is_active: 1)
tip_exception("切换失败") unless course_member.STUDENT? tip_exception("切换失败") unless course_student.present?
course_teacher = CourseMember.find_by!(user_id: current_user.id, role: %i[CREATOR PROFESSOR], course_id: @course.id) course_teacher = CourseMember.find_by!(user_id: current_user.id, role: %i[CREATOR PROFESSOR], course_id: @course.id)
course_member.update!(is_active: 0) ActiveRecord::Base.transaction do
course_teacher.update!(is_active: 1) course_student.destroy!
course_teacher.update!(is_active: 1)
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功") normal_status(0, "切换成功")
rescue => e rescue => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -739,12 +759,15 @@ class CoursesController < ApplicationController
# 切换为助教 # 切换为助教
def switch_to_assistant def switch_to_assistant
begin begin
course_member = @course.course_members.find_by!(user_id: current_user.id, is_active: 1) course_student = @course.course_members.find_by!(user_id: current_user.id, is_active: 1)
tip_exception("切换失败") unless course_member.STUDENT? tip_exception("切换失败") unless course_student.present?
course_teacher = CourseMember.find_by!(user_id: current_user.id, role: %i[ASSISTANT_PROFESSOR], course_id: @course.id) course_teacher = CourseMember.find_by!(user_id: current_user.id, role: %i[ASSISTANT_PROFESSOR], course_id: @course.id)
course_member.update!(is_active: 0) ActiveRecord::Base.transaction do
course_teacher.update!(is_active: 1) course_student.destroy!
course_teacher.update!(is_active: 1)
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功") normal_status(0, "切换成功")
rescue => e rescue => e
uid_logger_error(e.message) uid_logger_error(e.message)
@ -1109,11 +1132,11 @@ class CoursesController < ApplicationController
return normal_status(-1, "邀请码不能为空") if params[:invite_code].blank? return normal_status(-1, "邀请码不能为空") if params[:invite_code].blank?
invite_code = params[:invite_code] invite_code = params[:invite_code]
course = Course.find_by(invite_code: invite_code, is_delete: 0, invite_code_halt: 0, laboratory_id: current_laboratory.id) course = Course.find_by(invite_code: invite_code, is_delete: 0, invite_code_halt: 0, laboratory_id: current_laboratory.id)
course_group = CourseGroup.find_by(invite_code: invite_code) course_group = CourseGroup.find_by(invite_code: invite_code, invite_code_halt: 0)
if course.blank? if course.blank?
return normal_status(-1, "邀请码无效") if course_group.blank? return normal_status(-1, "邀请码无效") if course_group.blank?
course = Course.find_by(id: course_group.course_id, is_delete: 0, invite_code_halt: 0, laboratory_id: current_laboratory.id) course = Course.find_by(id: course_group.course_id, is_delete: 0, laboratory_id: current_laboratory.id)
return normal_status(-1, "邀请码无效") if course.blank? return normal_status(-1, "邀请码无效") if course.blank?
end end
@ -1146,6 +1169,7 @@ class CoursesController < ApplicationController
if existing_student.present? if existing_student.present?
# 如果在该课堂已经存在学生身份,且邀请码为分班邀请码,则将其直接加入分班 # 如果在该课堂已经存在学生身份,且邀请码为分班邀请码,则将其直接加入分班
existing_student.update!(course_group_id: course_group.id) if course_group.present? existing_student.update!(course_group_id: course_group.id) if course_group.present?
message = "您已是课堂成员"
else else
correspond_teacher_exist = current_user.none_admin_teacher_of_course? course 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) new_student = CourseMember.new(user_id: current_user.id, course_id: course.id, role: 4)
@ -1156,8 +1180,8 @@ class CoursesController < ApplicationController
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id]) CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id) StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
student_role = 1
end end
student_role = 1
end end
# 创建教师身份 # 创建教师身份
@ -1194,9 +1218,9 @@ class CoursesController < ApplicationController
teacher_role = 1 teacher_role = 1
end end
if teacher_role && student_role if (teacher_role && student_role) || message.to_s == "您已是课堂成员"
render json: { status: 0, message: message, course_id: course.id} 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} render json: { status: 0, message: "加入成功", course_id: course.id}
else else
normal_status(message) normal_status(message)

@ -1,8 +1,10 @@
class ExaminationBanksController < ApplicationController class ExaminationBanksController < ApplicationController
include PaginateHelper include PaginateHelper
before_action :require_login before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item]
before_action :find_exam, except: [:index, :create] before_action :find_exam, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item] before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item]
before_action :identity_auth, only: [:index]
def index def index
exams = ExaminationBankQuery.call(params) exams = ExaminationBankQuery.call(params)
@ -59,7 +61,7 @@ class ExaminationBanksController < ApplicationController
def set_public def set_public
tip_exception(-1, "该试卷已公开") if @exam.public? tip_exception(-1, "该试卷已公开") if @exam.public?
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank").exists? tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank", status: 0).exists?
ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id) ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id)
# @exam.update_attributes!(public: 1) # @exam.update_attributes!(public: 1)
render_ok render_ok

@ -1,5 +1,6 @@
class ExaminationIntelligentSettingsController < ApplicationController class ExaminationIntelligentSettingsController < ApplicationController
before_action :require_login before_action :require_login
before_action :certi_identity_auth, only: [:create, :optinal_items, :save_exam, :exchange_one_item, :exchange_items]
before_action :find_exam, only: [:exchange_one_item, :exchange_items, :save_exam] before_action :find_exam, only: [:exchange_one_item, :exchange_items, :save_exam]
def optinal_items def optinal_items
@ -36,16 +37,19 @@ class ExaminationIntelligentSettingsController < ApplicationController
end end
def exchange_one_item def exchange_one_item
item = @exam.item_baskets.find_by!(id: params[:item_id]) item = @exam.item_baskets.find_by!(item_bank_id: params[:item_id])
exam_type_setting = @exam.examination_type_settings.find_by!(item_type: item.item_type) exam_type_setting = @exam.examination_type_settings.find_by!(item_type: item.item_type)
# 获取可选的题 # 获取可选的题
items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public) items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public)
# 可选题中去掉已组卷的试题
type_items = items.select{ |t_item| t_item.item_type == item.item_type } type_items = items.select{ |t_item| t_item.item_type == item.item_type }
# 如果可选的题数小于等于设置的题数则提示无可换的题 optional_item_ids = (type_items.pluck(:id) - @exam.item_baskets.where(item_type: item.item_type).pluck(:item_bank_id)).uniq
tip_exception("无可换的题") if type_items.size <= exam_type_setting.count
# 可选题中去掉已组卷的同题型试题 # 如果可选的题数等于0则提示无可换的题
optional_item_ids = type_items.pluck(:id) - @exam.item_baskets.where(item_type: item.item_type).pluck(:item_bank_id) tip_exception("无可换的题") if optional_item_ids.size == 0
new_item = ItemBank.find optional_item_ids.sample(1).first new_item = ItemBank.find optional_item_ids.sample(1).first
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: item.position, score: item.score, item_type: new_item.item_type) @exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: item.position, score: item.score, item_type: new_item.item_type)
@ -61,13 +65,15 @@ class ExaminationIntelligentSettingsController < ApplicationController
# 获取可选的题 # 获取可选的题
items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public) items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public)
type_items = items.select{ |t_item| t_item.item_type == params[:item_type] } type_items = items.select{ |t_item| t_item.item_type == params[:item_type] }
# 如果可选的题数小于等于设置的题数则提示无可换的题
tip_exception("无可换的题") if type_items.size <= exam_type_setting.count # 可选题中去掉已组卷的试题
# 可选题中去掉已组卷的同题型试题
choosed_item_ids = choosed_items.pluck(:item_bank_id) choosed_item_ids = choosed_items.pluck(:item_bank_id)
optional_item_ids = type_items.pluck(:id) - choosed_item_ids optional_item_ids = (type_items.pluck(:id) - choosed_item_ids).uniq
# 如果可选的题数等于0则提示无可换的题
tip_exception("无可换的题") if optional_item_ids.size == 0
# 如果可选题数小于设置的题数n则在原来的选题中随机选n个确保换题时能选到新的题 # 如果可选题数小于设置的题数n则在原来的选题中随机选n个确保换题时能选到新的题
if optional_item_ids.size < exam_type_setting.count if optional_item_ids.size < exam_type_setting.count
absence_count = exam_type_setting.count - optional_item_ids.size absence_count = exam_type_setting.count - optional_item_ids.size
optional_item_ids = optional_item_ids + choosed_item_ids.sample(absence_count) optional_item_ids = optional_item_ids + choosed_item_ids.sample(absence_count)

@ -1,5 +1,6 @@
class ExaminationItemsController < ApplicationController class ExaminationItemsController < ApplicationController
before_action :require_login before_action :require_login
before_action :certi_identity_auth, only: [:create, :destroy, :delete_item_type, :set_score, :batch_set_score, :adjust_position]
before_action :validate_score, only: [:set_score, :batch_set_score] before_action :validate_score, only: [:set_score, :batch_set_score]
before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type] before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type]
before_action :find_item, except: [:create, :batch_set_score, :delete_item_type] before_action :find_item, except: [:create, :batch_set_score, :delete_item_type]

File diff suppressed because it is too large Load Diff

@ -1235,7 +1235,7 @@ class ExercisesController < ApplicationController
normal_status(0, "正在下载中") normal_status(0, "正在下载中")
else else
set_export_cookies set_export_cookies
render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false render exam_pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false
end end
end end

@ -524,11 +524,11 @@ class GamesController < ApplicationController
else else
{updated_at: Time.now} {updated_at: Time.now}
end end
logger.info("#############myshixuns_update: ##{myshixuns_update}") #logger.info("#############myshixuns_update: ##{myshixuns_update}")
@myshixun.update_attributes!(myshixuns_update) @myshixun.update_attributes!(myshixuns_update)
gitUrl = repo_ip_url @myshixun.repo_path gitUrl = repo_ip_url @myshixun.repo_path
logger.info("#############giturl: ##{gitUrl}") #logger.info("#############giturl: ##{gitUrl}")
gitUrl = Base64.urlsafe_encode64(gitUrl) gitUrl = Base64.urlsafe_encode64(gitUrl)
shixun_tomcat = edu_setting('cloud_bridge') shixun_tomcat = edu_setting('cloud_bridge')
@ -554,7 +554,7 @@ class GamesController < ApplicationController
testSet << test_cases testSet << test_cases
end end
logger.info("##############testSet: #{testSet}") #logger.info("##############testSet: #{testSet}")
testCases = Base64.urlsafe_encode64(testSet.to_json) unless testSet.blank? testCases = Base64.urlsafe_encode64(testSet.to_json) unless testSet.blank?
# 评测类型: 012 用于webssh的评测 3用于vnc # 评测类型: 012 用于webssh的评测 3用于vnc
@ -581,7 +581,7 @@ class GamesController < ApplicationController
if secret_rep&.repo_name if secret_rep&.repo_name
secretGitUrl = repo_ip_url secret_rep.repo_path secretGitUrl = repo_ip_url secret_rep.repo_path
br_params.merge!({secretGitUrl: Base64.urlsafe_encode64(secretGitUrl), secretDir: secret_rep.secret_dir_path}) br_params.merge!({secretGitUrl: Base64.urlsafe_encode64(secretGitUrl), secretDir: secret_rep.secret_dir_path})
logger.info("#######br_params:#{br_params}") #logger.info("#######br_params:#{br_params}")
end end
# 中间层交互 # 中间层交互
@ -700,10 +700,10 @@ class GamesController < ApplicationController
resubmit_identifier = @game.resubmit_identifier resubmit_identifier = @game.resubmit_identifier
# 如果没有超时并且正在评测中 # 如果没有超时并且正在评测中
# 判断评测中的状态有两种1、如果之前没有通关的只需判断status为1即可如果通过关则判断game的resubmit_identifier是否更新 # 判断评测中的状态有两种1、如果之前没有通关的只需判断status为1即可如果通过关则判断game的resubmit_identifier是否更新
uid_logger("################game_status: #{@game.status}") #uid_logger("################game_status: #{@game.status}")
uid_logger("################params[:resubmit]: #{params[:resubmit]}") #uid_logger("################params[:resubmit]: #{params[:resubmit]}")
uid_logger("################resubmit_identifier: #{resubmit_identifier}") #uid_logger("################resubmit_identifier: #{resubmit_identifier}")
uid_logger("################time_out: #{params[:time_out]}") #uid_logger("################time_out: #{params[:time_out]}")
sec_key = params[:sec_key] sec_key = params[:sec_key]
if (params[:time_out] == "false") && ((params[:resubmit].blank? && @game.status == 1) || (params[:resubmit].present? && if (params[:time_out] == "false") && ((params[:resubmit].blank? && @game.status == 1) || (params[:resubmit].present? &&
(params[:resubmit] != resubmit_identifier))) (params[:resubmit] != resubmit_identifier)))
@ -764,7 +764,7 @@ class GamesController < ApplicationController
end end
end end
uid_logger("game is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") #uid_logger("game is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
# 记录前端总耗时 # 记录前端总耗时
record_consume_time = e_record.try(:pod_execute) record_consume_time = e_record.try(:pod_execute)
max_mem = e_record.try(:max_mem) max_mem = e_record.try(:max_mem)
@ -850,7 +850,7 @@ class GamesController < ApplicationController
@allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER || @game.test_sets_view #解锁的用户 @allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER || @game.test_sets_view #解锁的用户
if max_query_index > 0 if max_query_index > 0
uid_logger("max_query_index is #{max_query_index} game id is #{@game.id}, challenge_id is #{challenge.id}") #uid_logger("max_query_index is #{max_query_index} game id is #{@game.id}, challenge_id is #{challenge.id}")
@qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position, o.ts_time, o.ts_mem, @qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position, o.ts_time, o.ts_mem,
o.query_index, t.is_public, t.input, t.output, o.compile_success FROM outputs o, games g, challenges c, o.query_index, t.is_public, t.input, t.output, o.compile_success FROM outputs o, games g, challenges c,
test_sets t where g.id=#{@game.id} and c.id=#{challenge.id} and o.query_index=#{max_query_index} test_sets t where g.id=#{@game.id} and c.id=#{challenge.id} and o.query_index=#{max_query_index}

@ -368,6 +368,7 @@ class HomeworkCommonsController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@homework = HomeworkCommon.new(homework_params) @homework = HomeworkCommon.new(homework_params)
@homework.reference_answer = params[:reference_answer].to_s.strip
@homework.homework_type = @homework_type @homework.homework_type = @homework_type
@homework.user_id = current_user.id @homework.user_id = current_user.id
@homework.course_id = @course.id @homework.course_id = @course.id
@ -417,6 +418,7 @@ class HomeworkCommonsController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@homework.update_attributes!(homework_params) @homework.update_attributes!(homework_params)
@homework.reference_answer = params[:reference_answer].to_s.strip
if @homework.homework_type == "group" if @homework.homework_type == "group"
homework_detail_group = @homework.homework_detail_group homework_detail_group = @homework.homework_detail_group
@ -497,7 +499,7 @@ class HomeworkCommonsController < ApplicationController
# tip_exception("challenge_id参数的长度与challenge_score参数的长度不匹配") if # tip_exception("challenge_id参数的长度与challenge_score参数的长度不匹配") if
# params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length # 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 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) tip_exception("分值之和必须等于总分值:#{params[:total_score]}") if params[:total_score].to_f.round(2) != total_score.to_f.round(2)
@ -874,10 +876,12 @@ class HomeworkCommonsController < ApplicationController
subjects = Subject.where(id: params[:subject_ids], status: 2).includes(stages: :shixuns).reorder("id desc") subjects = Subject.where(id: params[:subject_ids], status: 2).includes(stages: :shixuns).reorder("id desc")
@homework_ids = [] @homework_ids = []
none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id) # none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id)
course_module = @course.course_modules.find_by(module_type: "shixun_homework") course_module = @course.course_modules.find_by(module_type: "shixun_homework")
subjects.each do |subject| subjects.each do |subject|
shixun_ids = subject.shixuns.where(use_scope: 0).pluck(:id) +
subject.shixuns.joins(:shixun_schools).where("school_id = #{current_user.try(:school_id).to_i} and use_scope = 1").pluck(:id)
subject.stages.each do |stage| subject.stages.each do |stage|
@ -887,7 +891,7 @@ class HomeworkCommonsController < ApplicationController
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1) course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
# 去掉不对当前用户的单位公开的实训,已发布的实训 # 去掉不对当前用户的单位公开的实训,已发布的实训
stage.shixuns.no_jupyter.where.not(shixuns: {id: none_shixun_ids}).unhidden.each do |shixun| stage.shixuns.no_jupyter.where(id: shixun_ids).unhidden.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user homework = HomeworksService.new.create_homework shixun, @course, category, current_user
@homework_ids << homework.id @homework_ids << homework.id
CreateStudentWorkJob.perform_later(homework.id) CreateStudentWorkJob.perform_later(homework.id)
@ -910,7 +914,7 @@ class HomeworkCommonsController < ApplicationController
def publish_homework def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 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? if params[:detail].blank?
tip_exception("缺少截止时间参数") if params[:end_time].blank? tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
@ -918,7 +922,7 @@ class HomeworkCommonsController < ApplicationController
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
else else
tip_exception("缺少分班截止时间参数") if params[:group_end_times].blank? 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 tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
group_end_times.each do |time| group_end_times.each do |time|
tip_exception("分班截止时间不能早于当前时间") if time <= Time.now tip_exception("分班截止时间不能早于当前时间") if time <= Time.now
@ -979,8 +983,8 @@ class HomeworkCommonsController < ApplicationController
end end
homework.homework_detail_manual.update_attributes!(comment_status: 1) homework.homework_detail_manual.update_attributes!(comment_status: 1)
if homework.course_acts.size == 0 if homework.course_act.blank?
homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id) homework.course_act << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id)
end end
# 发消息 # 发消息
HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids) HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids)
@ -1041,7 +1045,7 @@ class HomeworkCommonsController < ApplicationController
def end_homework def end_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
time = Time.now.strftime("%Y-%m-%d %H:%M:%S") time = Time.now
# 已发布且未截止的作业才能立即截止 # 已发布且未截止的作业才能立即截止
@ -1049,7 +1053,7 @@ class HomeworkCommonsController < ApplicationController
homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings) homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings)
course_students = @course.students course_students = @course.students
charge_group_ids = @course.charge_group_ids(current_user) 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 end_groups = charge_group_ids & group_ids if group_ids
begin begin
@ -1082,7 +1086,7 @@ class HomeworkCommonsController < ApplicationController
homework.end_time = time homework.end_time = time
end end
homework_detail_manual.update_attributes!(comment_status: 2) if homework.end_time <= time # homework_detail_manual.update_attributes!(comment_status: 2) if homework.end_time <= time
# 实训作业的作品需要计算是否迟交 # 实训作业的作品需要计算是否迟交
if homework.homework_type == "practice" if homework.homework_type == "practice"
@ -1404,8 +1408,8 @@ class HomeworkCommonsController < ApplicationController
end end
def homework_params def homework_params
tip_exception("name参数不能为空") if params[:name].blank? tip_exception("标题不能为空") if params[:name].blank?
tip_exception("description参数不能为空") if params[:description].blank? tip_exception("内容不能为空") if params[:description].blank?
params.require(:homework_common).permit(:name, :description, :reference_answer) params.require(:homework_common).permit(:name, :description, :reference_answer)
end end

@ -1,8 +1,10 @@
class ItemBanksController < ApplicationController class ItemBanksController < ApplicationController
include PaginateHelper include PaginateHelper
before_action :require_login before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public]
before_action :find_item, except: [:index, :create] before_action :find_item, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public] before_action :edit_auth, only: [:update, :destroy, :set_public]
before_action :identity_auth, only: [:index]
def index def index
items = ItemBankQuery.call(params) items = ItemBankQuery.call(params)
@ -52,7 +54,7 @@ class ItemBanksController < ApplicationController
def set_public def set_public
tip_exception(-1, "该试题已公开") if @item.public? tip_exception(-1, "该试题已公开") if @item.public?
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @item.id, container_type: 'ItemBank').exists? tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @item.id, container_type: 'ItemBank', status: 0).exists?
ApplyAction.create!(container_id: @item.id, container_type: 'ItemBank', user_id: current_user.id) ApplyAction.create!(container_id: @item.id, container_type: 'ItemBank', user_id: current_user.id)
# @item.update_attributes!(public: 1) # @item.update_attributes!(public: 1)
render_ok render_ok

@ -1,5 +1,6 @@
class ItemBasketsController < ApplicationController class ItemBasketsController < ApplicationController
before_action :require_login before_action :require_login
before_action :certi_identity_auth, only: [:create, :delete_item_type, :destroy, :set_score, :batch_set_score, :adjust_position]
before_action :validate_score, only: [:set_score, :batch_set_score] before_action :validate_score, only: [:set_score, :batch_set_score]
helper_method :current_basket helper_method :current_basket

@ -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,24 @@ class MainController < ApplicationController
end end
def index 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
# TODO: 这块之后需要整合者架构重新变化统一跳转到index后再路由分发
if 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
end end

@ -91,7 +91,7 @@ class MyshixunsController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
t1 = Time.now t1 = Time.now
uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}") #uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}")
jsonTestDetails = JSON.parse(params[:jsonTestDetails]) jsonTestDetails = JSON.parse(params[:jsonTestDetails])
timeCost = JSON.parse(params[:timeCost]) timeCost = JSON.parse(params[:timeCost])
brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present? brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present?
@ -101,7 +101,7 @@ class MyshixunsController < ApplicationController
sec_key = jsonTestDetails['sec_key'] sec_key = jsonTestDetails['sec_key']
server_url = jsonTestDetails['showServer'] server_url = jsonTestDetails['showServer']
uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") #uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit'] resubmit = jsonTestDetails['resubmit']
outPut = tran_base64_decode64(jsonTestDetails['outPut']) outPut = tran_base64_decode64(jsonTestDetails['outPut'])
@ -267,10 +267,12 @@ class MyshixunsController < ApplicationController
@sec_key = generate_identifier(EvaluateRecord, 12) @sec_key = generate_identifier(EvaluateRecord, 12)
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id, record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
:identifier => @sec_key, :exec_time => exec_time) :identifier => @sec_key, :exec_time => exec_time)
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")}") #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 end
# 隐藏代码文件 和 VNC的都不需要走版本库 # 隐藏代码文件 和 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"] last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
@ -280,8 +282,6 @@ class MyshixunsController < ApplicationController
else else
params[:content] params[:content]
end end
uid_logger_dubug("###11222333####{content}")
uid_logger_dubug("###222333####{last_content}")
if content != last_content if content != last_content
@content_modified = 1 @content_modified = 1
@ -289,8 +289,6 @@ class MyshixunsController < ApplicationController
author_name = current_user.real_name author_name = current_user.real_name
author_email = current_user.git_mail author_email = current_user.git_mail
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted" message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
uid_logger_dubug("112233#{author_name}")
uid_logger_dubug("112233#{author_email}")
@content = GitService.update_file(repo_path: @repo_path, @content = GitService.update_file(repo_path: @repo_path,
file_path: path, file_path: path,
message: message, message: message,

@ -30,4 +30,22 @@ class Oauth::BaseController < ActionController::Base
@_default_yun_session = "#{request.subdomain.split('.').first}_user_id" @_default_yun_session = "#{request.subdomain.split('.').first}_user_id"
# @_default_yun_session = "#{current_laboratory.try(:identifier).split('.').first}_user_id" # @_default_yun_session = "#{current_laboratory.try(:identifier).split('.').first}_user_id"
end end
def session_openid
session[:openid]
end
def set_session_openid(openid)
Rails.logger.info("[wechat] set session openid: #{openid}")
session[:openid] = openid
end
def session_unionid
session[:unionid]
end
def set_session_unionid(unionid)
Rails.logger.info("[wechat] set session unionid: #{unionid}")
session[:unionid] = unionid
end
end end

@ -0,0 +1,13 @@
class Oauth::CasController < Oauth::BaseController
def create
user, is_new_user = Oauth::CreateORFindCasUserService.call(current_user, auth_hash)
successful_authentication(user)
redirect_to root_url
end
def auth_hash
JSON.parse(CGI.unescape(request.env['omniauth.auth'].extra.to_json))
end
end

@ -1,11 +1,32 @@
class Oauth::WechatController < Oauth::BaseController class Oauth::WechatController < Oauth::BaseController
def create def create
user, new_user = Oauth::CreateOrFindWechatAccountService.call(current_user ,params) # user, new_user = Oauth::CreateOrFindWechatAccountService.call(current_user ,params)
successful_authentication(user) begin
code = params['code'].to_s.strip
tip_exception("code不能为空") if code.blank?
new_user = false
render_ok(new_user: new_user) result = WechatOauth::Service.access_token(code)
rescue Oauth::CreateOrFindWechatAccountService::Error => ex result = WechatOauth::Service.user_info(result['access_token'], result['openid'])
render_error(ex.message)
# 存在该用户
open_user = OpenUsers::Wechat.find_by(uid: result['unionid'])
if open_user.present? && open_user.user.present?
successful_authentication(open_user.user)
else
if current_user.blank? || !current_user.logged?
new_user = true
set_session_openid(result['openid'])
set_session_unionid(result['unionid'])
else
OpenUsers::Wechat.create!(user: current_user, uid: result['unionid'])
end
end
render_ok(new_user: new_user)
rescue WechatOauth::Error => ex
render_error(ex.message)
end
end end
end end

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

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

@ -3,9 +3,10 @@ class SubjectsController < ApplicationController
# before_action :check_auth, except: [:index] # before_action :check_auth, except: [:index]
before_action :check_account, except: [:index, :show, :right_banner] before_action :check_account, except: [:index, :show, :right_banner]
before_action :find_subject, except: [:index, :create, :new, :append_to_stage, :add_shixun_to_stage] before_action :find_subject, except: [:index, :create, :new, :append_to_stage, :add_shixun_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish, before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish, :apply_public,
:search_members, :add_subject_members, :statistics, :shixun_report, :school_report, :search_members, :add_subject_members, :statistics, :shixun_report, :school_report,
:up_member_position, :down_member_position, :update_team_title, :statistics_info] :cancel_has_public, :up_member_position, :down_member_position, :update_team_title,
:statistics_info, :cancel_public]
before_action :require_admin, only: [:copy_subject] before_action :require_admin, only: [:copy_subject]
before_action :shixun_marker, only: [:add_shixun_to_stage] before_action :shixun_marker, only: [:add_shixun_to_stage]
@ -33,16 +34,16 @@ class SubjectsController < ApplicationController
laboratory_join = " AND subjects.id in #{subject_ids} " laboratory_join = " AND subjects.id in #{subject_ids} "
if select if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' #{laboratory_join} subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC") AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' #{laboratory_join} subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
GROUP BY subjects.id ORDER BY myshixun_member_count DESC") GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end end
else else
@ -59,7 +60,7 @@ class SubjectsController < ApplicationController
elsif reorder == "publish_time" elsif reorder == "publish_time"
@subjects = @subjects.unhidden @subjects = @subjects.unhidden
else else
@subjects = @subjects.visible.unhidden @subjects = @subjects.publiced.unhidden
end end
# 类型 # 类型
@ -72,7 +73,7 @@ class SubjectsController < ApplicationController
end 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, public = 2 desc, publish_time asc" : "homepage_show desc, excellent desc, updated_at desc")
@subjects = @subjects.reorder(order_str) @subjects = @subjects.reorder(order_str)
end end
@ -242,13 +243,14 @@ class SubjectsController < ApplicationController
## 云上实验室过滤 ## 云上实验室过滤
@courses = @courses.where(id: current_laboratory.all_courses) @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) @all_shixun_ids = @subject.shixuns.where(use_scope: 0).pluck(:id) +
@subject.shixuns.joins(:shixun_schools).where("school_id = #{current_user.user_extension.try(:school_id).to_i} and use_scope = 1").pluck(:id)
end end
def send_to_course def send_to_course
@course = Course.find_by!(id: params[:course_id]) @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 course_module = @course.course_modules.where(module_type: "shixun_homework").first
homework_ids = [] homework_ids = []
@ -259,7 +261,8 @@ class SubjectsController < ApplicationController
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework", 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) 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 = HomeworksService.new.create_homework shixun, @course, category, current_user
homework_ids << homework.id homework_ids << homework.id
end end
@ -271,14 +274,44 @@ class SubjectsController < ApplicationController
end end
def publish def publish
@subject.update_attributes(status: 2)
end
def cancel_publish
begin
apply = ApplyAction.where(container_type: "ApplySubject", container_id: @subject.id).order("created_at desc").first
if apply && apply.status == 0
apply.update_attributes(status: 3)
apply.tidings.destroy_all
end
@subject.update_attributes(status: 0)
rescue => e
uid_logger_error(e.message)
tip_exception("撤销申请失败")
end
end
def cancel_has_publish
begin
@subject.update_attributes(:status => 0)
rescue => e
uid_logger_error(e.message)
tip_exception("撤销发布失败")
raise ActiveRecord::Rollback
end
end
# 申请公开
def apply_public
tip_exception(-1, "请先发布课程再申请公开") if @subject.status != 2
apply = ApplyAction.where(container_type: "ApplySubject", container_id: @subject.id).order("created_at desc").first apply = ApplyAction.where(container_type: "ApplySubject", container_id: @subject.id).order("created_at desc").first
if apply && apply.status == 0 if apply && apply.status == 0
@status = 0 @status = 0
else else
@subject.update_attributes(status: 1) @subject.update_attributes(public: 1)
ApplyAction.create(container_type: "ApplySubject", container_id: @subject.id, user_id: current_user.id, status: 0) ApplyAction.create(container_type: "ApplySubject", container_id: @subject.id, user_id: current_user.id, status: 0)
begin begin
status = Educoder::Sms.send(mobile: '18711011226', send_type:'publish_subject' , name: '管理员') Educoder::Sms.send(mobile: '18711011226', send_type:'publish_subject' , name: '管理员')
rescue => e rescue => e
uid_logger_error("发送验证码出错: #{e}") uid_logger_error("发送验证码出错: #{e}")
end end
@ -286,28 +319,28 @@ class SubjectsController < ApplicationController
end end
end end
def cancel_publish def cancel_public
begin begin
apply = ApplyAction.where(container_type: "ApplySubject", container_id: @subject.id).order("created_at desc").first apply = ApplyAction.where(container_type: "ApplySubject", container_id: @subject.id).order("created_at desc").first
if apply && apply.status == 0 if apply && apply.status == 0
apply.update_attributes(status: 3) apply.update_attributes(status: 3)
apply.tidings.destroy_all apply.tidings.destroy_all
end end
@subject.update_attributes(status: 0) @subject.update_attributes(public: 0)
render_ok
rescue => e rescue => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("撤销申请失败") tip_exception("撤销申请失败")
raise ActiveRecord::Rollback
end end
end end
def cancel_has_publish def cancel_has_public
begin begin
@subject.update_attributes(:status => 0) @subject.update_attributes(:public => 0)
render_ok
rescue => e rescue => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("撤销发布失败") tip_exception("撤销公开失败")
raise ActiveRecord::Rollback
end end
end end

@ -2,11 +2,10 @@ class TagDisciplinesController < ApplicationController
before_action :require_login before_action :require_login
def create 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]) sub_discipline = SubDiscipline.find_by!(id: params[:sub_discipline_id])
tip_exception("重复的知识点") if sub_discipline.tag_disciplines.exists?(name: params[:name].to_s.strip) 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) tag_discipline = TagDiscipline.create!(name: params[:name].to_s.strip, sub_discipline: sub_discipline, user_id: current_user.id,
position: sub_discipline.tag_disciplines.pluck(:position).max + 1)
render_ok({tag_discipline_id: tag_discipline.id}) render_ok({tag_discipline_id: tag_discipline.id})
end end
end end

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

@ -13,7 +13,7 @@ class Users::VideosController < Users::BaseController
end end
def update 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]) current_video.update!(title: params[:title])
@ -39,6 +39,13 @@ class Users::VideosController < Users::BaseController
@videos = paginate videos @videos = paginate videos
end 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 def batch_publish
Videos::BatchPublishService.call(observed_user, batch_publish_params) Videos::BatchPublishService.call(observed_user, batch_publish_params)
render_ok render_ok
@ -50,6 +57,14 @@ class Users::VideosController < Users::BaseController
def current_video def current_video
@_current_video ||= observed_user.videos.find_by(id: params[:id]) @_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 end
def search_params def search_params
@ -57,6 +72,6 @@ class Users::VideosController < Users::BaseController
end end
def batch_publish_params def batch_publish_params
params.permit(videos: %i[video_id title]) params.permit(videos: %i[video_id title course_id])
end end
end end

@ -52,7 +52,7 @@ class UsersController < ApplicationController
def attachment_show def attachment_show
file_name = params[:file_name] file_name = params[:file_name]
path = params[:path] path = params[:path] || edu_setting('attachment_folder')
send_file "#{path}/#{file_name}", :filename => "#{file_name}", send_file "#{path}/#{file_name}", :filename => "#{file_name}",
:type => 'game', :type => 'game',
:disposition => 'attachment' #inline can open in browser :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 = @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,27 +1,50 @@
class Weapps::CoursesController < Weapps::BaseController class Weapps::CoursesController < Weapps::BaseController
before_action :require_login before_action :require_login
before_action :set_course, :user_course_identity, except: [:create] before_action :set_course, except: [:create, :check_invite_code]
before_action :check_account, only: [:create] 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_allowed, only: [:edit, :update]
before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers] before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers]
def course_activities
@course = current_course
homework_commons = @course.homework_commons.where(homework_type: ["practice", "normal"]).homework_published
member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
if (@user_course_identity == Course::STUDENT && member.try(:course_group_id).to_i == 0) || @user_course_identity > Course::STUDENT
homework_commons = homework_commons.unified_setting
elsif @user_course_identity == Course::STUDENT
not_homework_ids = @course.homework_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}").pluck(:homework_common_id)
homework_commons = homework_commons.where.not(id: not_homework_ids)
end
homework_ids = homework_commons.blank? ? "(-1)" : "(" + homework_commons.pluck(:id).join(",") + ")"
activities = @course.course_activities.where("course_act_type in ('Course', 'CourseMessage') or
(course_act_type = 'HomeworkCommon' and course_act_id in #{homework_ids})").order("id desc")
@activities_count = activities.size
@activities = paginate activities.includes(:course_act, user: :user_extension)
end
def create def create
# return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher? # return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher?
course = Course.new(tea_id: current_user.id) course = Course.new(tea_id: current_user.id)
Weapps::CreateCourseService.call(course, course_params) Weapps::CreateCourseService.call(course, course_params)
render_ok render_ok(id: course.id)
rescue ApplicationService::Error => ex rescue ApplicationService::Error => ex
render_error(ex.message) render_error(ex.message)
end end
def basic_info
@course = current_course
end
def edit def edit
@course = current_course @course = current_course
end end
def update def update
Weapps::UpdateCourseService.call(current_course, update_course_params) course = Weapps::UpdateCourseService.call(current_course, update_course_params)
render_ok render_ok(id: course.id)
end end
def show def show
@ -33,6 +56,23 @@ class Weapps::CoursesController < Weapps::BaseController
@categories = current_course.shixun_course_modules.first&.course_second_categories @categories = current_course.shixun_course_modules.first&.course_second_categories
end 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, invite_code_halt: 0)
if course.blank?
tip_exception(-1, "邀请码无效") if course_group.blank?
course = Course.find_by(id: course_group.course_id, is_delete: 0)
tip_exception(-1, "邀请码无效") if course.blank?
end
tip_exception(-1, "课堂已结束,无法加入") if course.is_end
render_ok
end
# 教师列表 # 教师列表
def teachers def teachers
@course = current_course @course = current_course
@ -179,11 +219,11 @@ class Weapps::CoursesController < Weapps::BaseController
private private
def course_params 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 end
def update_course_params def update_course_params
params.permit(:name, :course_list_name, :credit) params.permit(:name, :course_list_name, :credit, :end_date)
end end
def current_course def current_course

@ -17,7 +17,13 @@ class Weapps::SessionsController < Weapps::BaseController
# session[:wechat_user_extra].delete(:nickName) # 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) successful_authentication(user)
end end

@ -0,0 +1,14 @@
class Weapps::ShixunListsController < ApplicationController
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, except: [:index, :show]
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 I18n.t(locale_format(parent_container_type)) % container&.exercise_name
end end
def live_link_content
I18n.t(locale_format) % container&.course_name
end
def student_graduation_topic_content def student_graduation_topic_content
I18n.t(locale_format) % container&.graduation_topic.try(:name) I18n.t(locale_format) % container&.graduation_topic.try(:name)
end end

@ -7,8 +7,6 @@ class ItemBanks::SaveItemForm
validates :sub_discipline_id, presence: true validates :sub_discipline_id, presence: true
validates :item_type, presence: true, inclusion: {in: %W(SINGLE MULTIPLE JUDGMENT COMPLETION SUBJECTIVE PRACTICAL PROGRAM)} validates :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 :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! def validate!
super super
@ -27,7 +25,6 @@ class ItemBanks::SaveItemForm
attr_accessor :choice_text, :is_answer 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 } validates :is_answer, presence: true, inclusion: {in: 0..1}, numericality: { only_integer: true }
end end
end end

@ -2,7 +2,7 @@ class Weapps::CreateCourseForm
include ActiveModel::Model include ActiveModel::Model
attr_accessor :course 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 :name, presence: true
validates :course_list_name, presence: true validates :course_list_name, presence: true

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

@ -1,11 +1,22 @@
module Admins::SubjectsHelper module Admins::SubjectsHelper
def display_subject_status(subject) def display_subject_status(subject)
style = style =
case subject.status case subject.public
when 0 then 'text-secondary' when 0 then 'text-secondary'
when 1 then 'text-warning' when 1 then 'text-warning'
when 2 then 'text-success' when 2 then 'text-success'
end end
raw content_tag(:span, t("subject.status.#{subject.status}"), class: style)
status =
if subject.public == 2
"publiced"
elsif subject.public == 1
"pending"
elsif subject.status == 2
"processed"
else
"editing"
end
raw content_tag(:span, t("subject.public.#{status}"), class: style)
end end
end end

@ -137,7 +137,7 @@ module ApplicationHelper
# 用户图像url如果不存在的话source为匿名用户即默认使用匿名用户图像 # 用户图像url如果不存在的话source为匿名用户即默认使用匿名用户图像
def url_to_avatar(source) def url_to_avatar(source)
if File.exist?(disk_filename(source.class, source.id)) if File.exist?(disk_filename(source&.class, source&.id))
ctime = File.ctime(disk_filename(source.class, source.id)).to_i ctime = File.ctime(disk_filename(source.class, source.id)).to_i
if source.class.to_s == 'User' if source.class.to_s == 'User'
File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
@ -397,6 +397,8 @@ module ApplicationHelper
raw arr.join('') raw arr.join('')
end end
# 导出pdf时转化markdown为html # 导出pdf时转化markdown为html
def to_markdown(text,origin_url) def to_markdown(text,origin_url)
return nil if text.blank? return nil if text.blank?
@ -406,10 +408,10 @@ module ApplicationHelper
:fenced_code_blocks => true, :fenced_code_blocks => true,
:lax_html_blocks => true, :lax_html_blocks => true,
:strikethrough => true, :strikethrough => true,
:superscript => true, :superscript => false,
:tables => true :tables => true
} }
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,options) markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
m_t = markdown.render(text) m_t = markdown.render(text)
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
end end

@ -12,6 +12,12 @@ module CoursesHelper
# end # end
end end
def edit_auth group, teachers
User.current.admin_or_business? ||
teachers.select{|teacher| teacher.user_id == User.current.id &&
(teacher.teacher_course_groups.pluck(:course_group_id).include?(group.id) || teacher.teacher_course_groups.size == 0)}.size > 0
end
# 是否有切换为学生的入口 # 是否有切换为学生的入口
def switch_student_role is_teacher, course, user def switch_student_role is_teacher, course, user
is_teacher && course.course_members.where(user_id: user.id, role: %i(STUDENT)).exists? is_teacher && course.course_members.where(user_id: user.id, role: %i(STUDENT)).exists?
@ -65,6 +71,8 @@ module CoursesHelper
"/courses/#{course.id}/course_groups" "/courses/#{course.id}/course_groups"
when "statistics" when "statistics"
"/courses/#{course.id}/statistics" "/courses/#{course.id}/statistics"
when "video"
"/courses/#{course.id}/course_videos"
end end
end end
@ -126,6 +134,8 @@ module CoursesHelper
course.informs.count course.informs.count
when "online_learning" when "online_learning"
course.shixuns.count course.shixuns.count
when "video"
course.course_videos.count + course.live_links.count
end end
end end

@ -171,10 +171,21 @@ module HomeworkCommonsHelper
{status: status, time: time} {status: status, time: time}
end end
# 作品数统计type 1 已提交 0 未提交 # 作品数统计type 1 已提交 0 未提交 2 所有
def studentwork_count homework_common, type, member def studentwork_count homework_common, type, member
student_works = homework_common.teacher_works(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
# 作品数统计
def calculate_work_count homework_common, member
count = {}
student_works = homework_common.teacher_works(member)
count[:commit_count] = student_works.select{|work| work.work_status != 0 }.size
count[:uncommit_count] = student_works.select{|work| work.work_status == 0 }.size
count[:compelete_count] = Myshixun.where(id: student_works.pluck(:myshixun_id).reject(&:blank?), status: 1).size
count[:all_count] = student_works.size
count
end end
# 上次查重的时间 # 上次查重的时间

@ -152,7 +152,7 @@ module ShixunsHelper
challenge_program_name = [] challenge_program_name = []
shixun.challenges.map(&:exec_path).each do |exec_path| shixun.challenges.map(&:exec_path).each do |exec_path|
challenge_program_name << "\"#{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" || shixun.main_mirror_name == "JavaWeb"
if exec_path.nil? || exec_path.split("src/")[1].nil? if exec_path.nil? || exec_path.split("src/")[1].nil?
source = "\"\"" source = "\"\""
else else
@ -169,6 +169,7 @@ module ShixunsHelper
source_class_name << source if source.present? source_class_name << source if source.present?
end end
end end
logger.info("####source_class_name: #{source_class_name}")
script = if script.include?("sourceClassName") && script.include?("challengeProgramName") script = if script.include?("sourceClassName") && script.include?("challengeProgramName")
script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)") script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)")
else else

@ -1,12 +1,23 @@
module SubjectsHelper module SubjectsHelper
# 实训路径的发布状态 # 实训路径的发布状态
def publish_status subject, is_manager, user def publish_status subject, is_manager
status = -1 status = -1
if is_manager if is_manager
status = 0 if subject.status == 0 status = 0 if subject.status == 0
status = 1 if subject.status == 1 status = 1 if subject.status == 1
status = 2 if subject.status == 2 && user.admin? status = 2 if subject.status == 2
end
status
end
# 实训路径的公开状态
def public_status subject, is_manager, user
status = -1
if is_manager
status = 0 if subject.public == 0
status = 1 if subject.public == 1
status = 2 if subject.public == 2 && user.admin?
end end
status status
end end

@ -1,15 +1,16 @@
module Weapps::CoursesHelper module Weapps::CoursesHelper
require 'chinese_pinyin' require 'chinese_pinyin'
def teacher_list teachers def teacher_list teachers, user_course_identity
data = [] data = []
teachers.each do |teacher| teachers.each do |teacher|
if teacher.user.present? if teacher.user.present?
teacher_user = teacher.user teacher_user = teacher.user
name = teacher_user.real_name name = teacher_user.real_name
role = teacher.role == "CREATOR" ? "管理员" : teacher.role == "PROFESSOR" ? "教师" : "助教" 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, 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: '') pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0] first_char = pinyin[0]
letter = first_letter first_char letter = first_letter first_char
@ -28,15 +29,16 @@ module Weapps::CoursesHelper
end end
def student_list students, excellent def student_list students, excellent, user_course_identity
data = [] data = []
students.each do |student| students.each do |student|
if student.user.present? if student.user.present?
student_user = student.user student_user = student.user
name = student_user.real_name name = student_user.real_name
phone = excellent ? "" : student_user.hidden_phone 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, 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: '') pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0] first_char = pinyin[0]
letter = first_letter first_char letter = first_letter first_char

@ -0,0 +1,13 @@
# 删除课堂时将相应的课堂消息置为删除状态,并给老师发送删除消息
class DeleteCourseNotifyJob < ApplicationJob
queue_as :default
def perform(course_id, user_id)
course = Course.find_by(id: course_id)
return if course.blank?
Tiding.where(belong_container: course).update_all(is_delete: 1)
Tiding.create!(user_id: user_id, trigger_user_id: user_id, container_id: course.id,
container_type: 'DeleteCourse', tiding_type: 'System', belong_container: course, extra: course.name)
end
end

@ -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 result
end 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 end

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

@ -28,7 +28,7 @@ class Challenge < ApplicationRecord
scope :fields_for_list, -> { select([:id, :subject, :st, :score, :position, :shixun_id]) } 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 after_commit :create_diff_record

@ -3,7 +3,7 @@ class ChallengeAnswer < ApplicationRecord
belongs_to :challenge belongs_to :challenge
has_many :game_answers, :dependent => :destroy 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) def view_answer_time(user_id)
game_answers.where(user_id: user_id).last&.view_time 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_tags, :dependent => :destroy
has_many :challenge_questions, 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 end

@ -70,7 +70,9 @@ class Course < ApplicationRecord
# 课堂动态 # 课堂动态
has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy has_one :course_act, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
has_many :course_activities
has_many :tidings, as: :container, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy
# 开放课堂 # 开放课堂
@ -81,6 +83,13 @@ class Course < ApplicationRecord
# 老版的members弃用 现用course_members # 老版的members弃用 现用course_members
has_many :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 validate :validate_sensitive_string
scope :hidden, ->(is_hidden = true) { where(is_hidden: is_hidden) } scope :hidden, ->(is_hidden = true) { where(is_hidden: is_hidden) }
@ -206,7 +215,7 @@ class Course < ApplicationRecord
end end
def all_course_module_types 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 end
def get_course_module_by_type(type) def get_course_module_by_type(type)
@ -293,7 +302,7 @@ class Course < ApplicationRecord
#课程动态公共表记录 #课程动态公共表记录
def act_as_course_activity def act_as_course_activity
self.course_acts << CourseActivity.new(user_id: tea_id, course_id: id) self.course_act << CourseActivity.new(user_id: tea_id, course_id: id)
end end
# 当前老师分班下的所有学生 # 当前老师分班下的所有学生
@ -406,6 +415,7 @@ class Course < ApplicationRecord
when 'exercise' then '试卷' when 'exercise' then '试卷'
when 'poll' then '问卷' when 'poll' then '问卷'
when 'attachment' then '资源' when 'attachment' then '资源'
when 'video' then '视频直播'
when 'board' then '讨论' when 'board' then '讨论'
when 'course_group' then '分班' when 'course_group' then '分班'
when 'statistics' then '统计' when 'statistics' then '统计'
@ -425,9 +435,10 @@ class Course < ApplicationRecord
when 'exercise' then 8 when 'exercise' then 8
when 'poll' then 9 when 'poll' then 9
when 'attachment' then 10 when 'attachment' then 10
when 'board' then 11 when 'video' then 11
when 'course_group' then 12 when 'board' then 12
when 'statistics' then 13 when 'course_group' then 13
when 'statistics' then 14
else 100 else 100
end end
end end

@ -4,9 +4,26 @@ class CourseActivity < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :exercise belongs_to :exercise
belongs_to :poll belongs_to :poll
belongs_to :course_message
belongs_to :homework_common
# after_create :add_course_lead # after_create :add_course_lead
def container_name
case course_act_type
when "HomeworkCommon"
course_act&.name
when "Exercise"
course_act&.exercise_name
when "Poll"
course_act&.poll_name
when "Message"
course_act&.subject
else
""
end
end
# 发布新课导语 # 发布新课导语
# 导语要放置在课程创建信息之后 # 导语要放置在课程创建信息之后
def add_course_lead def add_course_lead

@ -2,6 +2,7 @@ class CourseMessage < ApplicationRecord
enum status: { UNHANDLED: 0, PASSED: 1, REJECTED: 2 } enum status: { UNHANDLED: 0, PASSED: 1, REJECTED: 2 }
belongs_to :course belongs_to :course
belongs_to :user belongs_to :user
has_one :course_act, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
scope :find_by_course, ->(course) { where(course_id: course.id) } scope :find_by_course, ->(course) { where(course_id: course.id) }
scope :join_course_requests, -> { where(course_message_type: "JoinCourseRequest") } scope :join_course_requests, -> { where(course_message_type: "JoinCourseRequest") }
@ -9,6 +10,8 @@ class CourseMessage < ApplicationRecord
scope :unhandled_join_course_requests_by_course, ->(course) { find_by_course(course).join_course_requests.unhandled } scope :unhandled_join_course_requests_by_course, ->(course) { find_by_course(course).join_course_requests.unhandled }
after_create :act_as_course_activity
def pass! def pass!
update!(status: :PASSED) update!(status: :PASSED)
send_deal_tiding(1) send_deal_tiding(1)
@ -25,6 +28,11 @@ class CourseMessage < ApplicationRecord
private private
#课程动态公共表记录
def act_as_course_activity
self.course_act << CourseActivity.new(user_id: course_message_id, course_id: course_id)
end
def send_deal_tiding deal_status def send_deal_tiding deal_status
# 发送申请处理结果消息 # 发送申请处理结果消息
Tiding.create!( Tiding.create!(

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

@ -1,7 +1,12 @@
class Discipline < ApplicationRecord class Discipline < ApplicationRecord
has_many :sub_disciplines, dependent: :destroy default_scope { order(position: :asc) }
has_many :sub_disciplines, -> { order("sub_disciplines.position ASC") }, dependent: :destroy
has_many :shixun_sub_disciplines, -> { where("shixun = 1") }, class_name: "SubDiscipline" has_many :shixun_sub_disciplines, -> { where("shixun = 1") }, class_name: "SubDiscipline"
has_many :subject_sub_disciplines, -> { where("subject = 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" has_many :question_sub_disciplines, -> { where("question = 1") }, class_name: "SubDiscipline"
validates_presence_of :name
end end

@ -3,5 +3,5 @@ class ExaminationIntelligentSetting < ApplicationRecord
belongs_to :user belongs_to :user
has_many :examination_type_settings, dependent: :destroy has_many :examination_type_settings, dependent: :destroy
has_many :tag_discipline_containers, as: :container, dependent: :destroy has_many :tag_discipline_containers, as: :container, dependent: :destroy
has_many :item_baskets, dependent: :destroy has_many :item_baskets, -> { order("item_baskets.position ASC") }, dependent: :destroy
end end

@ -1,3 +1,4 @@
class HackCode < ApplicationRecord class HackCode < ApplicationRecord
# 编程题代码相关 # 编程题代码相关
belongs_to :hack
end end

@ -28,14 +28,14 @@ class HomeworkCommon < ApplicationRecord
belongs_to :course_second_category, optional: true belongs_to :course_second_category, optional: true
# 课堂动态 # 课堂动态
has_many :course_acts, class_name: 'CourseActivity', as: :course_act, dependent: :destroy has_one :course_act, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
has_many :tidings, as: :container, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy
# 实训作业的分班查重记录 # 实训作业的分班查重记录
has_many :homework_group_reviews, :dependent => :destroy has_many :homework_group_reviews, :dependent => :destroy
# 学生的查重情况 # 学生的查重情况
has_many :homework_review_results, :dependent => :destroy 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 :description, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :explanation, length: { maximum: 5000, too_long: "不能超过5000个字符" } validates :explanation, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :reference_answer, length: { maximum: 15000, too_long: "不能超过15000个字符" } validates :reference_answer, length: { maximum: 15000, too_long: "不能超过15000个字符" }

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

Loading…
Cancel
Save