fix confict

dev_daiao
daiao 5 years ago
commit 2392106f78

140
.gitignore vendored

@ -1,68 +1,72 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# mac
*.DS_Store
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
/node_modules
/yarn-error.log
# /public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/database.yml
/.idea/*
# Ignore react node_modules
/public/react/.cache
/public/react/build
/public/react/build/
/public/react/node_modules/
/public/react/config/stats.json
/public/react/stats.json
/public/react/.idea/*
/public/npm-debug.log
# avatars
/public/images/avatars
/config/secrets.yml
/config/redis.yml
/config/elasticsearch.yml
/config/aliyun_vod.yml
public/upload.html
/config/configuration.yml
/config/environments/production.rb
/config/initializers/gitlab_config.rb
/db/schema.rb
.vscode/
vendor/bundle/
.ruby-version
.ruby-gemset
/Users
/files
/public/images/avatars
/public/files
/workspace
/log
/public/admin
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore lock config file
*.lock
*.log
# mac
*.DS_Store
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
/node_modules
/yarn-error.log
# /public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/database.yml
/.idea/*
# Ignore react node_modules
/public/react/.cache
/public/react/build
/public/react/build/
/public/react/node_modules/
/public/react/config/stats.json
/public/react/stats.json
/public/react/.idea/*
/public/npm-debug.log
# avatars
/public/images/avatars
/config/secrets.yml
/config/redis.yml
/config/elasticsearch.yml
/config/aliyun_vod.yml
public/upload.html
/config/configuration.yml
/config/environments/production.rb
/config/initializers/gitlab_config.rb
/db/schema.rb
.vscode/
vendor/bundle/
.ruby-version
.ruby-gemset
/Users
/files
/public/images/avatars
/public/files
/workspace
/log
/public/admin

@ -0,0 +1,6 @@
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 2
}

@ -0,0 +1,6 @@
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 2
}

@ -1,426 +0,0 @@
PATH
remote: lib/gitlab-cli
specs:
gitlab (3.2.0)
httparty
terminal-table
GEM
remote: https://gems.ruby-china.com/
specs:
aasm (5.0.5)
concurrent-ruby (~> 1.0)
actioncable (5.2.1)
actionpack (= 5.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.1)
actionpack (= 5.2.1)
actionview (= 5.2.1)
activejob (= 5.2.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.1)
actionview (= 5.2.1)
activesupport (= 5.2.1)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.1)
activesupport (= 5.2.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_decorator (1.2.0)
activejob (5.2.1)
activesupport (= 5.2.1)
globalid (>= 0.3.6)
activemodel (5.2.1)
activesupport (= 5.2.1)
activerecord (5.2.1)
activemodel (= 5.2.1)
activesupport (= 5.2.1)
arel (>= 9.0)
activestorage (5.2.1)
actionpack (= 5.2.1)
activerecord (= 5.2.1)
marcel (~> 0.3.1)
activesupport (5.2.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
acts-as-taggable-on (6.0.0)
activerecord (~> 5.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
archive-zip (0.11.0)
io-like (~> 0.3.0)
arel (9.0.0)
autoprefixer-rails (9.6.1)
execjs
awesome_print (1.8.0)
axlsx (3.0.0.pre)
htmlentities (~> 4.3, >= 4.3.4)
mimemagic (~> 0.3)
nokogiri (~> 1.8, >= 1.8.2)
rubyzip (~> 1.2, >= 1.2.1)
axlsx_rails (0.5.2)
actionpack (>= 3.1)
axlsx (>= 2.0.1)
bindex (0.5.0)
bootsnap (1.3.1)
msgpack (~> 1.0)
bootstrap (4.3.1)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.14.3, < 2)
sassc-rails (>= 2.0.0)
builder (3.2.3)
bulk_insert (1.7.0)
activerecord (>= 3.2.0)
byebug (10.0.2)
capybara (3.5.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
xpath (~> 3.1)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
chromedriver-helper (1.2.0)
archive-zip (~> 0.10)
nokogiri (~> 1.8)
chunky_png (1.3.10)
concurrent-ruby (1.0.5)
connection_pool (2.2.2)
crass (1.0.4)
diff-lcs (1.3)
diffy (3.3.0)
elasticsearch (7.2.0)
elasticsearch-api (= 7.2.0)
elasticsearch-transport (= 7.2.0)
elasticsearch-api (7.2.0)
multi_json
elasticsearch-transport (7.2.0)
faraday
multi_json
enumerize (2.3.1)
activesupport (>= 3.2)
erubi (1.7.1)
execjs (2.7.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.9.25)
font-awesome-sass (4.7.0)
sass (>= 3.2)
globalid (0.4.1)
activesupport (>= 4.2.0)
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
hashie (3.5.7)
htmlentities (4.3.4)
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (1.1.0)
concurrent-ruby (~> 1.0)
io-like (0.3.0)
jbuilder (2.7.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
jquery-rails (4.3.5)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jwt (2.1.0)
kaminari (1.1.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.1.1)
kaminari-activerecord (= 1.1.1)
kaminari-core (= 1.1.1)
kaminari-actionview (1.1.1)
actionview
kaminari-core (= 1.1.1)
kaminari-activerecord (1.1.1)
activerecord
kaminari-core (= 1.1.1)
kaminari-core (1.1.1)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.2.2)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
mini_mime (>= 0.1.1)
marcel (0.3.2)
mimemagic (~> 0.3.2)
method_source (0.9.0)
mimemagic (0.3.2)
mini_mime (1.0.0)
mini_portile2 (2.3.0)
minitest (5.11.3)
msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
mustermann (1.0.3)
mysql2 (0.5.2)
nio4r (2.3.1)
nokogiri (1.8.4)
mini_portile2 (~> 2.3.0)
oauth2 (1.4.1)
faraday (>= 0.8, < 0.16.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
omniauth (~> 1.9)
pdfkit (0.8.4.1)
popper_js (1.14.5)
public_suffix (4.0.1)
puma (3.12.0)
rack (2.0.5)
rack-cors (1.0.2)
rack-protection (2.0.5)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.1)
actioncable (= 5.2.1)
actionmailer (= 5.2.1)
actionpack (= 5.2.1)
actionview (= 5.2.1)
activejob (= 5.2.1)
activemodel (= 5.2.1)
activerecord (= 5.2.1)
activestorage (= 5.2.1)
activesupport (= 5.2.1)
bundler (>= 1.3.0)
railties (= 5.2.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
rails-i18n (5.1.3)
i18n (>= 0.7, < 2)
railties (>= 5.0, < 6)
railties (5.2.1)
actionpack (= 5.2.1)
activesupport (= 5.2.1)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rake (12.3.1)
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rchardet (1.8.0)
redcarpet (3.4.0)
redis (4.1.0)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6)
redis-rack (>= 1, < 3)
redis-store (>= 1.1.0, < 2)
redis-activesupport (5.0.7)
activesupport (>= 3, < 6)
redis-store (>= 1.3, < 2)
redis-rack (2.0.5)
rack (>= 1.5, < 3)
redis-store (>= 1.2, < 2)
redis-rails (5.0.2)
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
roo (2.8.2)
nokogiri (~> 1)
rubyzip (>= 1.2.1, < 2.0.0)
roo-xls (1.2.0)
nokogiri
roo (>= 2.0.0, < 3)
spreadsheet (> 0.9.0)
rqrcode (0.10.1)
chunky_png (~> 1.0)
rqrcode_png (0.1.5)
chunky_png
rqrcode
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
ruby-ole (1.2.12.2)
ruby_dep (1.5.0)
rubyzip (1.2.1)
sass (3.5.7)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.7)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sassc (2.0.1)
ffi (~> 1.9)
rake
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
searchkick (3.1.3)
activemodel (>= 4.2)
elasticsearch (>= 5)
hashie
selenium-webdriver (3.14.0)
childprocess (~> 0.5)
rubyzip (~> 1.2)
sidekiq (5.2.7)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
simple_form (4.1.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
simple_xlsx_reader (1.0.4)
nokogiri
rubyzip
sinatra (2.0.5)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.5)
tilt (~> 2.0)
spreadsheet (1.2.3)
ruby-ole (>= 1.0)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thor (0.20.0)
thread_safe (0.3.6)
tilt (2.0.8)
turbolinks (5.2.0)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (4.1.17)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.4.0)
web-console (3.6.2)
actionview (>= 5.0)
activemodel (>= 5.0)
bindex (>= 0.4.0)
railties (>= 5.0)
websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
wkhtmltopdf-binary (0.12.4)
xpath (3.1.0)
nokogiri (~> 1.8)
PLATFORMS
ruby
DEPENDENCIES
aasm
active_decorator
acts-as-taggable-on (~> 6.0)
awesome_print
axlsx (~> 3.0.0.pre)
axlsx_rails (~> 0.5.2)
bootsnap (>= 1.1.0)
bootstrap (~> 4.3.1)
bulk_insert
byebug
capybara (>= 2.15, < 4.0)
chromedriver-helper
diffy
enumerize
faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0)
gitlab!
grape-entity (~> 0.7.1)
jbuilder (~> 2.5)
jquery-rails
kaminari (~> 1.1, >= 1.1.1)
listen (>= 3.0.5, < 3.2)
mysql2 (>= 0.4.4, < 0.6.0)
oauth2
omniauth (~> 1.9.0)
omniauth-oauth2 (~> 1.6.0)
pdfkit
puma (~> 3.11)
rack-cors
rails (~> 5.2.0)
rails-i18n (~> 5.1)
rchardet (~> 1.8)
redcarpet (~> 3.4)
redis-rails
roo-xls
rqrcode (~> 0.10.1)
rqrcode_png
rspec-rails (~> 3.8)
ruby-ole
rubyzip
sass-rails (~> 5.0)
searchkick
selenium-webdriver
sidekiq
simple_form
simple_xlsx_reader
sinatra
spreadsheet
spring
spring-watcher-listen (~> 2.0.0)
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
wkhtmltopdf-binary
RUBY VERSION
ruby 2.3.7p456
BUNDLED WITH
1.17.3

@ -115,7 +115,7 @@ $(document).on('turbolinks:load', function(){
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function(params){
return { keyword: params.term };

@ -69,5 +69,80 @@ $(document).on('turbolinks:load', function() {
});
}
});
// 导入学生
var $importScoreModal = $('.modal.admin-import-competition-score-modal');
var $importScoreForm = $importScoreModal.find('form.admin-import-competition-score-form');
var $competitionIdInput = $importScoreForm.find('input[name="competition_id"]');
$importScoreModal.on('show.bs.modal', function(event){
resetFileInputFunc($importScoreModal.find('.upload-file-input'));
$importScoreModal.find('.file-names').html('选择文件');
$importScoreModal.find('.upload-file-input').trigger('click');
var $link = $(event.relatedTarget);
var competitionId = $link.data('competition-id');
$competitionIdInput.val(competitionId);
});
$importScoreModal.on('change', '.upload-file-input', function(e){
var file = $(this)[0].files[0];
$importScoreModal.find('.file-names').html(file ? file.name : '请选择文件');
});
var importUserFormValid = function(){
if($importScoreForm.find('input[name="file"]').val() == undefined || $importScoreForm.find('input[name="file"]').val().length == 0){
$importScoreForm.find('.error').html('请选择文件');
return false;
}
return true;
};
var buildResultMessage = function(data){
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
if(data.fail.length > 0){
messageHtml += '<table class="table"><thead class="thead-light"><tr><th>数据</th><th>失败原因</th></tr></thead><tbody>';
data.fail.forEach(function(item){
messageHtml += '<tr><td>' + item.data + '</td><td>' + item.message + '</td></tr>';
});
messageHtml += '</tbody></table>'
}
return messageHtml;
};
$importScoreModal.on('click', '.submit-btn', function(){
$importScoreForm.find('.error').html('');
if (importUserFormValid()) {
$('body').mLoading({ text: '正在导入...' });
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/import_competition_scores',
data: new FormData($importScoreForm[0]),
processData: false,
contentType: false,
success: function(data){
$('body').mLoading('destroy');
$importScoreModal.modal('hide');
showMessageModal(buildResultMessage(data), function(){
window.location.reload();
});
},
error: function(res){
$('body').mLoading('destroy');
var data = res.responseJSON;
$importScoreForm.find('.error').html(data.message);
}
});
}
});
});

@ -3,7 +3,7 @@ $(document).on('turbolinks:load', function() {
var $container = $('.edit-laboratory-setting-container');
var $form = $container.find('.edit_laboratory');
$('.logo-item-left').on("change", 'input[type="file"]', function () {
$('.logo-item-left, .banner-item-bottom').on("change", 'input[type="file"]', function () {
var $fileInput = $(this);
var file = this.files[0];
var imageType = /image.*/;

@ -0,0 +1,126 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-laboratory-shixuns-index-page').length > 0) {
var $searchForm = $('.laboratory-shixun-list-form .search-form');
var laboratoryId = $('.laboratory-shixun-list-container').data('id');
$searchForm.find('select#tag_id').select2({
placeholder: "请选择",
allowClear: true
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-shixun-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratoryShixunId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/admins/laboratories/' + laboratoryId + '/laboratory_shixuns/' + laboratoryShixunId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratoryShixunId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-shixun-list-container').find('.laboratory-shixun-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
// 添加实训功能
var $addModal = $('.modal.admin-add-laboratory-shixun-modal');
var $addForm = $addModal.find('form.admin-add-laboratory-user-form');
var $shixunSelect = $addForm.find('select.shixun-select');
$addModal.on('show.bs.modal', function(){
$addModal.find('.error').html('');
$shixunSelect.select2('val', ' ');
});
$shixunSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入实训名称/创建者检索',
multiple: true,
closeOnSelect: false,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/shixuns_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term, page: params.page || 1, per_page: 20 };
},
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.shixuns,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
var ele = '<span>'
ele += '<span>' + item.name + '</span>';
ele += '<span class="font-12"> -- ' + item.creator_name + '</span>';
ele += '<span class="font-12"> -- ' + item.status_text+ '</span>';
ele += '</span>';
return $(ele);
},
templateSelection: function(item){
if (item.id) {
}
var ele = '<span>' + (item.name || item.text) + '<span class="font-12"> -- ' + item.creator_name + '</span></span>'
return $(ele);
}
});
$addModal.on('click', '.submit-btn', function(){
$addModal.find('.error').html('');
var shixunIds = $shixunSelect.val();
if (shixunIds && shixunIds.length > 0) {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/laboratories/' + laboratoryId + '/laboratory_shixuns',
data: { shixun_ids: shixunIds },
success: function(){
show_success_flash();
window.location.reload();
},
error: function(res){
$addModal.find('.error').html(res.responseJSON.message);
}
});
} else {
$addModal.find('.error').html('请选择实训');
}
});
}
})

@ -0,0 +1,149 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-laboratory-subjects-index-page').length > 0) {
var $searchForm = $('.laboratory-subject-list-form .search-form');
var laboratoryId = $('.laboratory-subject-list-container').data('id');
// ************** 学校选择 *************
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
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;
}
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-subject-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratorySubjectId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/admins/laboratories/' + laboratoryId + '/laboratory_subjects/' + laboratorySubjectId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratorySubjectId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-subject-list-container').find('.laboratory-subject-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
// 添加实践课程功能
var $addModal = $('.modal.admin-add-laboratory-subject-modal');
var $addForm = $addModal.find('form.admin-add-laboratory-user-form');
var $subjectSelect = $addForm.find('select.subject-select');
$addModal.on('show.bs.modal', function(){
$addModal.find('.error').html('');
$subjectSelect.select2('val', ' ');
});
$subjectSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入课程名称/创建者检索',
multiple: false,
closeOnSelect: true,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/subjects_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term, page: params.page || 1, per_page: 20 }
},
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.subjects,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
var ele = '<span>'
ele += '<span>' + item.name + '</span>';
ele += '<span class="font-12"> -- ' + item.creator_name + '</span>';
ele += '<span class="font-12"> -- ' + item.status_text+ '</span>';
ele += '</span>';
return $(ele);
},
templateSelection: function(item){
if (item.id) {
}
var ele = '<span>' + (item.name || item.text) + '<span class="font-12"> -- ' + item.creator_name + '</span></span>'
return $(ele);
}
});
$addModal.on('click', '.submit-btn', function(){
$addModal.find('.error').html('');
var subjectIds = $subjectSelect.val();
if (subjectIds && subjectIds.length > 0) {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/laboratories/' + laboratoryId + '/laboratory_subjects',
data: { subject_id: subjectIds },
success: function(){
show_success_flash();
window.location.reload();
},
error: function(res){
$addModal.find('.error').html(res.responseJSON.message);
}
});
} else {
$addModal.find('.error').html('请选择课程');
}
});
}
})

@ -0,0 +1,90 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-select-school-modal');
if ($modal.length > 0) {
var $link = null;
var $form = $modal.find('form.admin-select-school-form');
var multiple = $form.data('multiple');
$form.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择',
multiple: multiple,
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;
var html = "<span>" + item.name + "<span class='ml-4 font-12'>";
if(item.province){ html += item.province }
html += "</span></span>";
return $(html);
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
school_ids: {
required: true
}
},
messages: {
school_ids: {
required: '请选择'
}
}
});
$modal.on('show.bs.modal', function(event){
$link = $(event.relatedTarget);
});
$modal.on('hide.bs.modal', function(){
$form.find('.error').html('');
$form.find('.school-select').select2('val', ' ');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if($form.valid()){
var url = $form.data('url');
var schoolIds = $form.find('#school_ids').val();
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: { school_ids: schoolIds },
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);
}
});
}
});
}
});

@ -9,7 +9,7 @@ $(document).on('turbolinks:load', function () {
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};

@ -3,13 +3,24 @@
//= require jquery3
//= require popper
//= require bootstrap-sprockets
//= require jquery.validate.min
//= require additional-methods.min
//= require bootstrap-notify
//= require select2
//= require common
//= require echarts
//= require ./i18n/jquery-validate-message-zh
//= require ./i18n/select2-i18n.zh-CN
//= require_tree ./colleges
Turbolinks.setProgressBarDelay(200);
// ******** select2 global config ********
$.fn.select2.defaults.set('theme', 'bootstrap4');
$.fn.select2.defaults.set('language', 'zh-CN');
$(document).on('turbolinks:load', function() {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="popover"]').popover();

@ -0,0 +1,28 @@
$(document).on('turbolinks:load', function() {
if ($('body.partners-customers-page').length > 0) {
var $customerContainer = $('.customer-list-container');
var partnerId = $customerContainer.find('.customer-list-body').data('id');
$customerContainer.on('change', '.manager-group-select', function(){
console.log('manager-group-select change', $(this).val());
var $select = $(this);
var customerId = $select.data('id');
var managerGroupId = $select.val();
$.ajax({
url: '/partners/' + partnerId + '/customer_manager_group.json',
method: 'POST',
dataType: 'json',
data: { customer_id: customerId, manager_group_id: managerGroupId },
success: function(){
showSuccessFlash();
$select.data('last', managerGroupId);
},
error: function(res){
showErrorNotify(res.responseJSON.message);
$select.val($select.data('last'));
}
})
})
}
});

@ -0,0 +1,125 @@
$(document).on('turbolinks:load', function() {
if ($('body.partners-partner-manager-groups-page').length > 0) {
var $container = $('.manager-group-list-container');
var partnerId = $container.find('.manager-group-list-body').data('id');
// ------- 新建编辑权限组弹窗 --------
var $managerGroupModal = $('.modal.partner-save-manager-group-modal');
var $managerGroupForm = $managerGroupModal.find('form.partner-save-manager-group-form');
var $managerGroupIdInput = $managerGroupForm.find('input[name="manager_group_id"]');
var $managerGroupNameInput = $managerGroupForm.find('input[name="manager_group_name"]');
$managerGroupForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
manager_group_name: {
required: true,
maxlength: 20
},
}
});
$managerGroupModal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var managerGroupId = $link.data('id');
var managerGroupName = $link.data('name');
if(managerGroupId && managerGroupId !== ''){
$managerGroupModal.find('.modal-title').html('重命名');
$managerGroupIdInput.val(managerGroupId);
$managerGroupNameInput.val(managerGroupName)
} else {
$managerGroupModal.find('.modal-title').html('新建');
$managerGroupIdInput.val('');
$managerGroupNameInput.val('');
}
});
$managerGroupModal.on('hide.bs.modal', function(){
$managerGroupIdInput.val('');
$managerGroupNameInput.val('');
});
$managerGroupModal.on('click', '.submit-btn', function(){
$managerGroupForm.find('.error').html('');
var url = $managerGroupForm.data('url');
if ($managerGroupForm.valid()) {
$.ajax({
method: 'POST',
dataType: 'script',
url: url,
data: $managerGroupForm.serialize()
});
}
});
// ---------- 添加管理员弹窗 ------------
var $partnerManagerModal = $('.modal.partner-add-partner-manager-modal');
var $partnerManagerForm = $partnerManagerModal.find('form.partner-add-partner-manager-form');
var $managerGroupIdInput = $partnerManagerForm.find('input[name="manager_group_id"]');
var $userSelect = $partnerManagerForm.find('.partner-manager-select');
$userSelect.select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的管理员姓名',
multiple: true,
closeOnSelect: false,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/users_for_partners',
dataType: 'json',
data: function(params){
return { name: params.term, partner_id: partnerId, page: params.page || 1, per_page: 20 };
},
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.users,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<span>" + item.real_name + " <span class='font-12'>" + item.school_name + ' ' + item.identity + "</span></span>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
$partnerManagerModal.on('show.bs.modal', function(event){
var $link = $(event.relatedTarget);
var managerGroupId = $link.data('id');
$managerGroupIdInput.val(managerGroupId);
$userSelect.select2('val', ' ');
$partnerManagerModal.find('.error').html('');
});
$partnerManagerModal.on('click', '.submit-btn', function(){
$partnerManagerModal.find('.error').html('');
var managerGroupId = $managerGroupIdInput.val();
var userIds = $userSelect.val();
if (userIds && userIds.length > 0) {
$.ajax({
method: 'POST',
dataType: 'script',
url: '/partners/' + partnerId + '/partner_managers',
data: { user_ids: userIds, manager_group_id: managerGroupId }
});
} else {
$partnerManagerModal.modal('hide');
}
});
}
});

@ -88,6 +88,14 @@ function show_success_flash(message){
});
}
function showSuccessFlash(message){
$.notify({
message: message || '操作成功'
},{
type: 'success'
});
}
function showErrorNotify(message){
$.notify({
message: message || '操作失败'

@ -0,0 +1,803 @@
$(document).on('turbolinks:load', function(){
if ($('body.cooperative-competition-settings-index-page').length > 0) {
var dateOptions = {
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd',
startDate: '2017-04-01'
};
var timeOptions = {
autoclose: 1,
language: 'zh-CN',
format: 'yyyy-mm-dd hh:ii',
minuteStep: 30
};
var defineDateRangeSelect = function (element) {
var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, dateOptions);
$(element).datepicker(options);
$(element).find('.start-date').datepicker().on('changeDate', function (e) {
$(element).find('.end-date').datepicker('setStartDate', e.date);
});
};
$(".competition-start-end-date .start-date").datetimepicker(timeOptions);
$(".competition-start-end-date .end-date").datetimepicker(timeOptions);
$(".nav-setting-form .enroll_end_time").datetimepicker(timeOptions);
$(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-time").datetimepicker(timeOptions);
defineDateRangeSelect('.teaching-mode-date');
// defineTimeRangeSelect('.competition-start-end-date');
var $basicForm = $('form.basic-setting-form');
$basicForm.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
name: "required",
subTitle: "required",
startTime: "required",
endTime: "required",
mode: "required",
identifier: "required"
}
});
// 保存按钮
$basicForm.on('click', ".submit-btn", function () {
$basicForm.find('.submit-btn').attr('disabled', 'disabled');
$basicForm.find('.error').html('');
var valid = $basicForm.valid();
if ($("input[name='mode']:checked").val() == 2) {
var $courseId = $("input[name='course_id']");
if ($courseId.val() === undefined || $courseId.val().length === 0) {
$courseId.addClass('danger text-danger');
valid = false;
} else {
$courseId.removeClass('danger text-danger');
}
} else if ($("input[name='mode']:checked").val() == 3) {
var $techStartTime = $("input[name='teach_start_time']");
var $techEndTime = $("input[name='teach_end_time']");
if ($techStartTime.val() === undefined || $techStartTime.val().length === 0) {
$techStartTime.addClass('danger text-danger');
valid = false;
} else {
$techStartTime.removeClass('danger text-danger');
}
if ($techEndTime.val() === undefined || $techEndTime.val().length === 0) {
$techEndTime.addClass('danger text-danger');
valid = false;
} else {
$techEndTime.removeClass('danger text-danger');
}
} else {
$("input[name='course_id']").removeClass('danger text-danger');
$("input[name='teach_start_time']").removeClass('danger text-danger');
$("input[name='teach_end_time']").removeClass('danger text-danger');
}
if (!valid) return;
$.ajax({
method: 'POST',
dataType: 'json',
url: $basicForm.attr('action'),
data: new FormData($basicForm[0]),
processData: false,
contentType: false,
success: function (data) {
$.notify({message: '保存成功'});
// window.location.reload();
},
error: function (res) {
var data = res.responseJSON;
$basicForm.find('.error').html(data.message);
},
complete: function () {
$basicForm.find('.submit-btn').attr('disabled', false);
}
});
});
var selectOptions = {
theme: 'bootstrap4',
placeholder: '请输入要添加的单位名称',
multiple: true,
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 || item.text;
},
templateSelection: function(item){
return item.name || item.text;
}
};
$('.sponsor-select').select2(selectOptions);
$('.allow-school-select').select2(selectOptions);
$('.manager-select').select2({
theme: 'bootstrap4',
placeholder: '请输入要添加的管理员姓名',
multiple: true,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/cooperative/users',
dataType: 'json',
data: function(params){
return { keyword: params.term };
},
processResults: function(data){
return { results: data.users }
}
},
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return $("<div class='row px-0'><span class='col-3'>" + item.real_name + "</span><span class='col-5 font-12'>" + item.school_name + "</span><span class='col-4 font-12'>" + item.hidden_phone + "</span></div>");
},
templateSelection: function(item){
if (item.id) {
}
return item.real_name || item.text;
}
});
// 排行榜
//链接
$(".nav-setting-form").on("click",".add_linkBtn",function () {
var length=$(".nav-setting-form").find(".linkFormItem").length + 1;
var html='<div class="row mt-2 align-items-center linkFormItem">\n' +
' <div class="col-1 text-right">\n' +
' <label class="checkbox checkbox-primary mt-1">\n' +
' <input type="checkbox" name="navbar[][hidden]" value="0" hidden class="font-16" checked="checked">\n' +
' <input type="checkbox" value="0" class="font-16 module_hidden" checked="checked">\n' +
' </label>\n' +
' </div>\n' +
' <div class="col-md-label mt-1"><input type="hidden" value="md" name="navbar[][module_type]">\n' +
' <input type="text" name="navbar[][name]" value="" class="form-control" placeholder="模块名称"></div>\n' +
' <div class="col-md-1 mt-1"><input type="text" name="navbar[][position]" value="" class="form-control" placeholder="位置"></div>\n' +
' <div class="col-md-3 mt-1"><input type="text" name="navbar[][url]" value="" class="form-control" placeholder="请输入资料下载地址"></div>\n' +
' <a class="mt-1 btn btn-primary waves-effect waves-light btn-xs setBtn_s add_linkBtn" href="javascript:void(0)">+</a>\n' +
' <a class="mt-1 btn btn-icon waves-effect btn-default waves-light setBtn_s ml10 del_linkBtn" href="javascript:void(0)">×</a>\n' +
' </div>';
$(this).parents(".linkFormItem").after(html);
});
$(".nav-setting-form").on("click", ".del_linkBtn", function () {
$(this).parents(".linkFormItem").remove();
});
//有关报名要求
$(".addRequireBtn").on("click",function () {
var length=$("#requireForm").find(".requireForm_item").length + 1;
var html='<div class="row mt-2 mb-4 requireForm_item">\n' +
' <div class="col-1 text-right">&nbsp;&nbsp;</div>\n' +
' <div class="col-1 text-left mt-1">\n' +
' <input type="text" class="form-control" name="competition_staffs[][minimum]" value="0">\n' +
' </div>\n' +
' <span class="mt-2">~</span>\n' +
' <div class="col-1 mt-1">\n' +
' <input type="text" class="form-control" name="competition_staffs[][maximum]" value="1">\n' +
' </div>\n' +
' <span class="mt-2">人</span>\n' +
' <div class="col-2 mt-1">\n' +
' <select class="form-control" name="competition_staffs[][category]">\n' +
' <option value="student">学生</option>\n' +
' <option value="teacher">教师</option>\n' +
' </select>\n' +
' </div>\n' +
' <div class="col-2 mt-1">\n' +
' <label class="radio checkbox-primary mt-1" value="require_'+length+'_1">\n' +
' <input id="require_'+length+'_1" class="mutiple-limited-radio" value="false" checked name="competition_staffs[][mutiple_limited]" type="checkbox">\n' +
' <label for="require_'+length+'_1">可多次报名</label>\n' +
' </label>\n' +
' </div>\n' +
' <div class="col-2 mt-1">\n' +
' <label class="radio checkbox-primary mt-1" value="require_'+length+'_2">\n' +
' <input id="require_'+length+'_2" class="mutiple-limited-radio" value="true" name="competition_staffs[][mutiple_limited]" type="checkbox">\n' +
' <label for="require_'+length+'_2">不可多次报名</label>\n' +
' </label>\n' +
' <a href="javascript:void(0)" class="ml20 delRequrieBtn">\n' +
' <i class="fa fa-times-circle font-20 color-grey-c"></i>\n' +
' </a>\n' +
' </div>\n' +
' </div>';
$("#requireForm").append(html);
});
$("#requireForm").on("click",".delRequrieBtn",function () {
$(this).parents(".requireForm_item").remove();
});
$('.nav-setting-form').on('click', '.module_hidden', function(){
var checkEle = $(this);
if (checkEle.is(':checked')) {
checkEle.prev().val(0);
} else {
checkEle.prev().val(1);
}
});
$('.competition-staff-settings').on('click', '.mutiple-limited-radio', function(){
var radio = $(this);
if (radio.is(':checked')) {
radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', false)
} else {
radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', true)
}
});
var $navForm = $('form.nav-setting-form');
$navForm.on('click', ".submit-btn", function () {
$navForm.find('.submit-btn').attr('disabled', 'disabled');
$navForm.find('.error').html('');
var valid = $navForm.valid();
if (!valid) return;
$.ajax({
method: 'POST',
dataType: 'json',
url: $navForm.attr('action'),
data: new FormData($navForm[0]),
processData: false,
contentType: false,
success: function (data) {
$.notify({message: '保存成功'});
// window.location.reload();
},
error: function (res) {
var data = res.responseJSON;
$navForm.find('.error').html(data.message);
},
complete: function () {
$navForm.find('.submit-btn').attr('disabled', false);
}
});
});
// 排行榜设置
//删除小阶段
$("#large_panel").on("click",".small_panel_item_del",function () {
var list = $(this).parents(".small_panel");
$(this).parents(".small_panel_item").remove();
for(var i=0;i < $(list).find(".subName").length;i++){
console.log(i);
$(list).find(".subName").eq(i).html("第"+parseInt(i+1)+"阶段");
}
});
// $('form.stage-update-form').validate({
// errorElement: 'span',
// errorClass: 'danger text-danger',
// rules: {
// stage_name: "required",
// "stage[][start_time]": "required",
// "stage[][end_time]": "required",
// "stage[][mission_count]": {
// required: true,
// min: 1
// },
// "stage[][entry]": {
// required: true,
// min: 1
// },
// score_rate: {
// required: true,
// range: [0, 100]
// }
// },
// messages: {
// "stage[][mission_count]": {
// min: ">=1"
// },
// "stage[][entry]": {
// min: ">=1"
// },
// }
// });
$('.competition-chart-setting').on('click', ".update-stage", function () {
var updateForm = $(this).parents("form");
$(this).attr('disabled', 'disabled');
updateForm.find('.error').html('');
// var valid = updateForm.valid();
var valid = true;
var $stageName = updateForm.find('input[name="stage_name"]');
if($stageName.val() === undefined || $stageName.val().length === 0){
$stageName.addClass('danger text-danger');
valid = false;
} else {
$stageName.removeClass('danger text-danger');
}
var $scoreRate = updateForm.find('input[name="score_rate"]');
if($scoreRate.val() === undefined || $scoreRate.val().length === 0){
$scoreRate.addClass('danger text-danger');
valid = false;
} else if (parseInt($scoreRate.val()) > 100 || parseInt($scoreRate.val()) < 0) {
$scoreRate.addClass('danger text-danger');
$scoreRate.after('<span class="danger text-danger">0-100之间的数值</span>');
valid = false;
} else {
$scoreRate.removeClass('danger text-danger');
$scoreRate.siblings().remove();
}
updateForm.find('input[name="stage[][start_time]"]').each(function(_, e){
var $ele = $(e);
if($ele.val() === undefined || $ele.val().length === 0){
$ele.addClass('danger text-danger');
valid = false;
} else {
$ele.removeClass('danger text-danger');
}
});
updateForm.find('input[name="stage[][end_time]"]').each(function(_, e){
var $ele = $(e);
if($ele.val() === undefined || $ele.val().length === 0){
$ele.addClass('danger text-danger');
valid = false;
} else {
$ele.removeClass('danger text-danger');
}
});
updateForm.find('input[name="stage[][mission_count]"]').each(function(i, e){
var $ele = $(e);
var $entry = updateForm.find('input[name="stage[][entry]"]').eq(i);
if($ele.val() === undefined || $ele.val().length === 0){
$ele.addClass('danger text-danger');
valid = false;
} else if (parseInt($ele.val()) < 1) {
$ele.addClass('danger text-danger');
$ele.after('<span class="danger text-danger">大于等于1</span>');
valid = false;
} else if (parseInt($ele.val()) > parseInt($entry.val())) {
$ele.addClass('danger text-danger');
$ele.after('<span class="danger text-danger">不能大于总任务数</span>');
valid = false;
} else {
$ele.removeClass('danger text-danger');
$ele.siblings().remove();
}
});
updateForm.find('input[name="stage[][entry]"]').each(function(_, e){
var $ele = $(e);
if($ele.val() === undefined || $ele.val().length === 0){
$ele.addClass('danger text-danger');
valid = false;
} else if (parseInt($ele.val()) < 1) {
$ele.addClass('danger text-danger');
$ele.after('<span class="danger text-danger">大于等于1</span>');
valid = false;
} else {
$ele.removeClass('danger text-danger');
$ele.siblings().remove();
}
});
updateForm.find('input[name="stage[][identifiers][]"]').each(function(_, e){
var $ele = $(e);
if($ele.val() === undefined || $ele.val().length === 0){
$ele.addClass('danger text-danger');
valid = false;
} else {
$ele.removeClass('danger text-danger');
}
});
if (!valid) return;
updateForm.find('input[name="stage[][mission_count]"]').each(function(_, e){
var $missionCount = $(e);
var $entryCount = $(e).parents("div.row").find('input[name="stage[][mission_count]"]');
if(parseInt($missionCount.val()) > parseInt($entryCount.val()) ){
$missionCount.addClass('danger text-danger');
$missionCount.after('<span class="danger text-danger">不能大于总任务数</span>');
valid = false;
} else {
$missionCount.removeClass('danger text-danger');
$missionCount.siblings().remove();
}
});
$.ajax({
method: 'POST',
dataType: 'json',
url: updateForm.attr('action'),
data: new FormData(updateForm[0]),
processData: false,
contentType: false,
success: function (data) {
$.notify({message: '保存成功'});
window.location.reload();
},
error: function (res) {
var data = res.responseJSON;
$navForm.find('.error').html(data.message);
},
complete: function () {
$navForm.find('.submit-btn').attr('disabled', false);
}
});
});
$(".competition-chart-stages").on("click", ".add-new-tab", function () {
if($(".new-stage-form").length > 0){
alert("请先保存上一个tab");
} else {
var count = parseInt($("#large_panel").find(".large_panel_part").length)+1;
var html = '<form class="stage-update-form new-stage-form flex-1" action="/cooperative/competitions/'+$(this).attr("data-competition-id")+'/competition_stages" accept-charset="UTF-8" data-remote="true" method="post">' +
'<div class="large_panel_part" attr_line="'+count+'"><div class="row d-flex mt-3">\n' +
' <span class="col-1 mt-2">tab标题</span>\n' +
' <div class="col-2 no_padding">\n' +
' <input type="text" class="form-control" name="stage_name"/>\n' +
' </div>\n' +
' <span class="col-1 text-right mt-2 no_padding">总排行榜占比:</span>\n' +
' <div class="col-1 no_padding">\n' +
' <input type="number" class="form-control" name="score_rate" value="100"/>\n' +
' </div><span class=" mt-2">%</span>\n' +
' <div class="flex-1">\n' +
' <a href="javascript:void(0)"class="btn btn-outline-primary export-action ml20 add-task-sub">新增子阶段</a>\n' +
' </div>\n' +
' <a href="javascript:void(0)" class="btn btn-default ml20" onclick="Del_tab(this)">删除</a>\n' +
' <a href="javascript:void(0)" class="btn btn-outline-primary update-stage export-action ml20">保存</a>\n' +
' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' +
' <div class="row">\n' +
' <div class="row col-6"><span class="mt-2 ml20">有效时间:</span>\n' +
' <div class="col-4 no_padding">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' +
' <span class="mt-2">~</span>\n' +
' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding">总任务数:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' +
' </select>\n' +
' </div></div>\n' +
' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' <span>\n' +
' <a href="javascript:void(0)" class="btn btn-default ml20 small_panel_item_del">删除</a>\n' +
' </span>\n' +
' </div>\n' +
'</div></div></form>';
$("#large_panel").append(html);
$(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-time").datetimepicker(timeOptions);
}
});
//新增子阶段
$(".competition-chart-stages").on("click", ".add-task-sub", function () {
var index = $(this).parents(".large_panel_part").attr("attr_line");
var count= 0;
console.log("sdfsf");
console.log($("#small_panel_"+index).find(".small_panel_item").length > 0);
if($("#small_panel_"+index).find(".small_panel_item").length > 0){
count = parseInt($("#small_panel_"+index).find(".small_panel_item").last().attr("count")) + 1;
console.log($("#small_panel_"+index).find(".small_panel_item").last().attr("count"));
}else{
count = 1;
}
var showCount=parseInt($("#small_panel_"+index).find(".small_panel_item").length) + 1;
var html='<div class="row d-flex small_panel_item" attr_line="sub_'+index+'_'+count+'" count="'+count+'">\n' +
' <span class="mr10 mt-2 subName">第'+showCount+'阶段</span>\n' +
' <div class="flex-1">\n' +
' <div class="row">\n' +
' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' +
' <span class="mt-2">~</span>\n' +
' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 mr10 text-right mt-2 no_padding">成绩来源:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' +
' </select>\n' +
' </div></div>\n' +
' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_'+index+'_'+count+'">\n'+
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-4 text-right mt-3 no_padding mr10">任务3</span>\n' +
' <div class="col-6 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' <span>\n' +
' <a href="javascript:void(0)" class="btn btn-default ml20 small_panel_item_del">删除</a>\n' +
' </span>\n' +
' </div>';
$("#small_panel_"+index).append(html);
$(".stage-update-form .section-start-time").datetimepicker(timeOptions);
$(".stage-update-form .section-end-time").datetimepicker(timeOptions);
});
// 奖项设置
var $prizeContainer = $('#competition-prize-card');
var competitionId = $prizeContainer.data('id');
$(document).on('prize.save.success', function(){
$.ajax({
method: 'GET',
url: '/cooperative/competitions/' + competitionId + '/competition_prizes',
dataType: 'script'
})
});
$('.modal.cooperative-upload-file-modal').on('upload:success', function(e, data){
var $imageElement;
if(data.suffix === '_member'){
$imageElement = $('.prize-member-image-' + data.source_id);
} else if(data.suffix === '_team'){
$imageElement = $('.prize-team-image-' + data.source_id);
} else {
$imageElement = $('.prize-teacher-image-' + data.source_id);
}
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
// 生成获奖记录
$prizeContainer.on('click', '.generate-prize-user-action', function(){
var $link = $(this);
var generateRequest = function(){
return $.ajax({
method: 'POST',
url: '/cooperative/competitions/' + competitionId + '/competition_prize_users',
dataType: 'json',
success: function(data){
if(data && data.status === 0){
show_success_flash();
$link.remove();
} else {
showErrorNotify(data.message);
}
},
error: function(res){
var data = res.responseJSON;
showErrorNotify(data.message);
}
})
}
customConfirm({
content: '确认生成吗?',
ok: function () {
customLoading({
ajax: generateRequest
})
}
})
});
} else {
$(document).unbind('prize.save.success');
}
});
//添加主办方或者开放范围
function addSponsor(item){
var html='<div class="sponsor_label">\n' +
' <input type="hidden" value="school_id" />\n' +
' <span>caicai</span>\n' +
' <a href="javascript:void(0)" onclick="del_sponsor(this)">×</a>\n' +
' </div>';
$(item).parents(".sponsorPanel").append(html);
}
//删除
function del_sponsor(item){
$(item).parents(".sponsor_label").remove();
}
// 小阶段修改总任务数
function change_total(item) {
var count=parseInt($(item).val());
var index = $(item).parents(".small_panel_item").attr("attr_line");
var indexLarge = $(item).parents(".large_panel_part").attr("attr_line");
console.log(indexLarge);
console.log(index);
var divCount=parseInt($("#task_Input_"+index).find(".task_Input_div").length);
var html = "";
if(count > divCount){
for(var i=0;i < count-divCount ;i++){
html+='<div class="col-4 row task_Input_div"><span class="col-4 text-right mt-3 no_padding mr10">任务'+(divCount+i+1)+'</span>\n' +
'<div class="col-6 no_padding">\n' +
'<input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
'</div>\n' +
'</div>';
}
$("#task_Input_"+index).append(html);
}else{
var delCount = divCount - count ;
console.log(divCount);
console.log(count);
var _max=parseInt($("#task_Input_"+index).find(".task_Input_div:last").index());
console.log(_max);
var _get= _max - delCount;
console.log(_get);
if(count == 0){
$("#task_Input_"+index).empty();
}else{
$("#task_Input_"+index).find(".task_Input_div:gt("+_get+")").remove();
}
}
}
//删除tab
function Del_tab(item) {
$(item).parents(".large_panel_part").remove();
}
//新增tab
function addNewTab(competition_id) {
if($(".new-stage-form").length > 0){
alert("请先保存上一个tab");
} else {
var count = parseInt($("#large_panel").find(".large_panel_part").length)+1;
var html = '<form class="stage-update-form new-stage-form flex-1" action="/cooperative/competitions/'+competition_id+'/competition_stages" accept-charset="UTF-8" data-remote="true" method="post">' +
'<div class="large_panel_part" attr_line="'+count+'"><div class="row d-flex mt-3">\n' +
' <span class="col-1 mt-2">tab标题</span>\n' +
' <div class="col-2 no_padding">\n' +
' <input type="text" class="form-control" name="stage_name"/>\n' +
' </div>\n' +
' <span class="col-1 text-right mt-2 no_padding">总排行榜占比:</span>\n' +
' <div class="col-1 no_padding">\n' +
' <input type="number" class="form-control" name="score_rate" value="100"/>\n' +
' </div><span class=" mt-2">%</span>\n' +
' <div class="flex-1">\n' +
' <a href="javascript:void(0)"class="btn btn-outline-primary export-action ml20 add-task-sub">新增子阶段</a>\n' +
' </div>\n' +
' <a href="javascript:void(0)" class="btn btn-default ml20" onclick="Del_tab(this)">删除</a>\n' +
' <a href="javascript:void(0)" class="btn btn-outline-primary update-stage export-action ml20">保存</a>\n' +
' </div>\n' +
' <div id="small_panel_'+count+'" class="small_panel">\n' +
' <div class="row d-flex small_panel_item" attr_line="sub_new_new" count="1">\n' +
' <span class="mt-2 subName mr10">第1阶段</span>\n' +
' <div class="flex-1">\n' +
' <div class="row">\n' +
' <div class="row col-6"><span class="mt-2 ml20 mr10">有效时间:</span>\n' +
' <div class="col-4 no_padding ">\n' +
' <input type="text" name="stage[][start_time]" id="stage__start_time" value="" autocomplete="off" class="section-start-time form-control" placeholder="有效开始时间">\n' +
' </div>\n' +
' <span class="mt-2">~</span>\n' +
' <div class="col-4 no_padding input_middle">\n' +
' <input type="text" name="stage[][end_time]" id="stage__end_time" value="" autocomplete="off" class="section-end-time form-control" placeholder="有效结束时间">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">总任务数:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <input type="number" class="form-control" onchange="change_total(this)" value="3" name="stage[][entry]">\n' +
' </div></div>\n' +
' <div class="row col-3"><span class="col-4 text-right mt-2 no_padding mr10">成绩来源:</span>\n' +
' <div class="col-6 no_padding ">\n' +
' <select class="form-control" name="stage[][score_source]">\n' +
' <option value="0">经验值</option>\n' +
' <option value="1">预测准确率</option>\n' +
' </select>\n' +
' </div></div>\n' +
' </div>\n' +
' <div class="row mt-2" id="task_Input_sub_new_new">\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-right mt-3 no_padding mr10">任务1</span>\n' +
' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-right mt-3 no_padding mr10">任务2</span>\n' +
' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' <div class="col-4 row task_Input_div">\n' +
' <span class="col-3 text-right no_padding mr10 mt-3">任务3</span>\n' +
' <div class="col-8 no_padding">\n' +
' <input type="text" class="form-control mt-2" name="stage[][identifiers][]" placeholder="请填写实训ID">\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' </div>\n' +
' <span>\n' +
' <a href="javascript:void(0)" class="btn btn-default ml20 small_panel_item_del">删除</a>\n' +
' </span>\n' +
' </div>\n' +
'</div></div></form>';
$("#large_panel").append(html);
}
}

@ -0,0 +1,148 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-competitions-index-page').length > 0) {
$('.modal.cooperative-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.competition-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
}
$(".cooperative-competition-list-form").on("change", '.competitions-hot-select', function () {
var s_value = $(this).get(0).checked ? 1 : 0;
var json = {};
json["hot"] = s_value;
$.ajax({
url: "/cooperative/competitions/hot_setting",
type: "POST",
dataType:'json',
data: json,
success: function(){
$.notify({ message: '操作成功' });
}
});
});
// ============== 新增竞赛 ===============
var $modal = $('.modal.cooperative-create-competition-modal');
var $form = $modal.find('form.cooperative-create-competition-form');
var $competitionNameInput = $form.find('input[name="competition_name"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
competition_name: {
required: true
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function () {
$competitionNameInput.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);
}
});
}
});
// 导入学生
var $importScoreModal = $('.modal.cooperative-import-competition-score-modal');
var $importScoreForm = $importScoreModal.find('form.cooperative-import-competition-score-form');
var $competitionIdInput = $importScoreForm.find('input[name="competition_id"]');
$importScoreModal.on('show.bs.modal', function(event){
resetFileInputFunc($importScoreModal.find('.upload-file-input'));
$importScoreModal.find('.file-names').html('选择文件');
$importScoreModal.find('.upload-file-input').trigger('click');
var $link = $(event.relatedTarget);
var competitionId = $link.data('competition-id');
$competitionIdInput.val(competitionId);
});
$importScoreModal.on('change', '.upload-file-input', function(e){
var file = $(this)[0].files[0];
$importScoreModal.find('.file-names').html(file ? file.name : '请选择文件');
});
var importUserFormValid = function(){
if($importScoreForm.find('input[name="file"]').val() == undefined || $importScoreForm.find('input[name="file"]').val().length == 0){
$importScoreForm.find('.error').html('请选择文件');
return false;
}
return true;
};
var buildResultMessage = function(data){
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
if(data.fail.length > 0){
messageHtml += '<table class="table"><thead class="thead-light"><tr><th>数据</th><th>失败原因</th></tr></thead><tbody>';
data.fail.forEach(function(item){
messageHtml += '<tr><td>' + item.data + '</td><td>' + item.message + '</td></tr>';
});
messageHtml += '</tbody></table>'
}
return messageHtml;
};
$importScoreModal.on('click', '.submit-btn', function(){
$importScoreForm.find('.error').html('');
if (importUserFormValid()) {
$('body').mLoading({ text: '正在导入...' });
$.ajax({
method: 'POST',
dataType: 'json',
url: '/cooperative/import_competition_scores',
data: new FormData($importScoreForm[0]),
processData: false,
contentType: false,
success: function(data){
$('body').mLoading('destroy');
$importScoreModal.modal('hide');
showMessageModal(buildResultMessage(data), function(){
window.location.reload();
});
},
error: function(res){
$('body').mLoading('destroy');
var data = res.responseJSON;
$importScoreForm.find('.error').html(data.message);
}
});
}
});
});

@ -0,0 +1,9 @@
$(document).on('turbolinks:load', function() {
if($('body.cooperative-enroll-lists-index-page').length > 0){
var search_form = $(".search-form");
//导出
$(".competition-enroll-list-form").on("click","#enroll-lists-export",function () {
window.location.href = "/cooperative/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists/export.xlsx?" + search_form.serialize();
});
}
});

@ -3,7 +3,7 @@ $(document).on('turbolinks:load', function() {
var $container = $('.edit-laboratory-setting-container');
var $form = $container.find('.edit_laboratory');
$('.logo-item-left').on("change", 'input[type="file"]', function () {
$('.logo-item-left, .banner-item-bottom').on("change", 'input[type="file"]', function () {
var $fileInput = $(this);
var file = this.files[0];
var imageType = /image.*/;

@ -0,0 +1,60 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-shixuns-index-page').length > 0) {
var $searchForm = $('.laboratory-shixun-list-form .search-form');
$searchForm.find('select#tag_id').select2({
placeholder: "请选择",
allowClear: true
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.shixun-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-shixun-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratoryShixunId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_shixuns/' + laboratoryShixunId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratoryShixunId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-shixun-list-container').find('.laboratory-shixun-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})

@ -0,0 +1,83 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-subjects-index-page').length > 0) {
var $searchForm = $('.laboratory-subject-list-form .search-form');
// ************** 学校选择 *************
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
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;
}
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.subject-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-subject-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratorySubjectId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_subjects/' + laboratorySubjectId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratorySubjectId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-subject-list-container').find('.laboratory-subject-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})

@ -16,7 +16,7 @@ $(document).on('turbolinks:load', function() {
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/cooperative/users',
url: '/cooperative/users/for_select',
dataType: 'json',
data: function(params){
return { name: params.term };

@ -0,0 +1,18 @@
$(document).on('turbolinks:load', function () {
$('.cooperative-modal-container').on('show.bs.modal', '.modal.cooperative-edit-subject-modal', function () {
var $modal = $('.modal.cooperative-edit-subject-modal');
var $form = $modal.find('form.cooperative-edit-subject-form');
$modal.on('click', '.submit-btn', function () {
$form.find('.error').html('');
var url = $form.attr('action');
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
});
})
});

@ -42,7 +42,7 @@ $(document).on('turbolinks:load', function() {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/cooperatives/files?' + formDataString,
url: '/cooperative/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,

@ -24,7 +24,7 @@
background: unset;
}
/* 内容表格 */
/* 内容表格 */
table {
table-layout: fixed;
@ -47,6 +47,12 @@
}
}
.image-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}
.action-container {
& > .action {
padding: 0 3px;
@ -94,6 +100,14 @@
}
}
.admin-list-container {
overflow-x: scroll;
& > table {
min-width: 900px;
}
}
.global-error {
color: grey;
min-height: 300px;
@ -118,7 +132,6 @@
}
.batch-action-container {
margin-bottom: -15px;
padding: 10px 20px 0;
background: #fff;
}

@ -96,5 +96,76 @@
font-size: 14px;
}
}
.banner-item {
margin-bottom: 15px;
display: flex;
flex-direction: column;
&-img {
display: block;
width: 300px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 300px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 149px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 137px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-top {
margin-bottom: 10px;
}
&-bottom {
position: relative;
width: 300px;
height: 80px;
&.has-img {
.banner-item-upload {
display: none;
}
&:hover {
.banner-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
}
}
}
}
&-title {
color: #23272B;
font-size: 14px;
}
}
}
}

@ -86,8 +86,11 @@
align-items: center;
& > img {
width: 40px;
height: auto;
//width: 40px;
//height: auto;
max-width: 130px !important;
max-height: 40px !important;
overflow: hidden;
}
& > .logo-label {

@ -1,6 +1,8 @@
@import "bootstrap";
@import "font-awesome-sprockets";
@import "font-awesome";
@import "select2.min";
@import "select2-bootstrap4.min";
@import "common";
@ -10,4 +12,34 @@
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, 1);
font-size: 16px;
}
.box {
padding: 20px;
border-radius: 5px;
background: #fff;
}
.custom-nav {
padding: 0 1rem;
display: flex;
border-bottom: 1px solid #EBEBEB;
&-item {
padding: 0 0.5rem;
}
&-link {
display: block;
margin-bottom: 2px;
padding: 0.8rem 0.5rem;
color: #495057;
font-size: 16px;
&.active {
margin-bottom: 0px;
color: #007bff;
border-bottom: 2px solid #007bff;
}
}
}

@ -0,0 +1,131 @@
.college-body-container {
padding: 20px;
flex: 1;
min-height: 100vh;
display: flex;
flex-direction: column;
overflow-y: scroll;
& > .content {
flex: 1;
font-size: 14px;
.box {
padding: 20px;
border-radius: 5px;
background: #fff;
}
}
/* 面包屑 */
.breadcrumb {
padding-left: 5px;
font-size: 20px;
background: unset;
}
/* 内容表格 */
table {
table-layout: fixed;
td {
vertical-align: middle;
}
tr {
&.no-data {
&:hover {
color: darkgrey;
background: unset;
}
& > td {
text-align: center;
height: 300px;
}
}
}
}
.image-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}
.action-container {
& > .action {
padding: 0 3px;
}
.more-action-dropdown {
.dropdown-item {
font-size: 14px;
}
}
}
/* 分页 */
.paginate-container {
margin-top: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.paginate-total {
margin-bottom: 10px;
color: darkgrey;
}
.pagination {
margin-bottom: 0px;
}
}
/* 搜索表单 */
.search-form-container {
display: flex;
margin-bottom: 20px;
.search-form {
flex: 1;
* { font-size: 14px; }
select, input {
margin-right: 10px;
font-size: 14px;
}
}
}
.global-error {
color: grey;
min-height: 300px;
&-code {
font-size: 80px;
}
&-text {
font-size: 24px;
}
}
.nav-tabs {
.nav-link {
padding: 0.5rem 2rem;
}
}
.CodeMirror {
border: 1px solid #ced4da;
}
.batch-action-container {
padding: 10px 20px 0;
background: #fff;
}
}

@ -0,0 +1,5 @@
.partners-customers-page {
.customer-list-body {
min-height: 300px;
}
}

@ -0,0 +1,104 @@
.partners-partner-manager-groups-page {
.customer-list-form {
padding: 10px 20px;
align-items: center;
}
.manager-group-item {
margin-bottom: 20px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
&-left {
flex: 1;
}
&-right {
.action {
}
}
}
}
.partner-manager {
&-body {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
&-item {
padding: 5px 10px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.remove-partner-manager-action {
display: none;
position: absolute;
z-index: 100;
right: 10px;
top: 0;
font-size: 24px;
& > i {
color: #dc3545;
}
}
&:hover {
.remove-partner-manager-action {
display: block;
}
}
&-avatar {
cursor: pointer;
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 50%;
position: relative;
& > img {
width: 80px;
height: 80px;
}
}
&.add-partner-manager-item {
.partner-manager-item-avatar {
background: #E4E4E4;
&:hover {
background: #D0D0D0;
}
&::before {
content: '';
position: absolute;
top: 39px;
left: 20px;
width: 40px;
height: 2px;
background: #fff;
}
&::after {
content: '';
position: absolute;
top: 20px;
left: 39px;
width: 2px;
height: 40px;
background: #fff;
}
}
}
}
}
}

@ -1,5 +1,7 @@
.colleges-statistics-page {
.college-body-container {
padding: 0;
.statistic-header {
width: 100%;
height: 240px;

@ -7,6 +7,7 @@
@import "bootstrap-datepicker.standalone";
@import "jquery.mloading";
@import "jquery-confirm.min";
@import "bootstrap-datetimepicker.min";
@import "codemirror/lib/codemirror";
@import "editormd/css/editormd.min";

@ -47,6 +47,12 @@
}
}
.image-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}
.action-container {
& > .action {
padding: 0 3px;
@ -118,7 +124,6 @@
}
.batch-action-container {
margin-bottom: -15px;
padding: 10px 20px 0;
background: #fff;
}

@ -0,0 +1,116 @@
.cooperative-competition-settings-index-page {
.competition-mode-container {
.row {
height: 35px;
}
.des-row {
height: auto;
}
.form-control {
font-size: 14px;
}
//.mode-input {
// input {
// width: 40%;
// }
//}
}
.col-md-label{
-webkit-box-flex: 0;
flex: 0 0 10%;
max-width: 10%;
min-width: 30px;
padding-right: 15px;
padding-left: 15px;
position: relative;
}
.col-md-label-s{
-webkit-box-flex: 0;
flex: 0 0 30px;
padding-right: 15px;
padding-left: 15px;
position: relative;
}
.setBtn_s{
height: 35px;
line-height: 20px;
}
.sponsor_label{
border:1px solid #4CACFF;
border-radius: 5px;
background-color: rgba(76,172,255,0.3);
color: #333;
padding:0px 4px;
height: 30px;
line-height: 30px;
float: left;
margin: 4px 5px;
span{
display: block;
float: left;
height: 28px;
line-height: 28px;
margin-right: 5px;
}
a{
font-size: 18px;
float: left;
height: 28px;
line-height: 28px;
}
}
.large_panel{
padding:0px 15px;
.large_panel_part{
border-top: 1px solid #eaeaea;
}
.large_panel_part:first-child{
border:none;
}
.large_panel_part >.row ,.small_panel >.row{
border-bottom: 1px solid #eaeaea;
padding:20px 0px;
}
.small_panel{
margin-left: 20px;
}
.row:last-child{
border:none;
}
.task_Input_div:nth-child(3n-2) > span.col-4{
flex: 0 0 81px;
max-width: 81px;
}
.task_Input_div:nth-child(3n-2){
flex: 0 0 50%;
max-width: 50%;
}
.task_Input_div:nth-child(3n-1){
flex: 0 0 25%;
max-width: 25%;
}
.task_Input_div:nth-child(3n){
flex: 0 0 25%;
max-width: 25%;
}
.task_Input_div:nth-child(3n) > span.col-4{
flex: 0 0 33.3%;
max-width: 33.3%;
}
.task_Input_div:nth-child(3n) > div.col-6{
flex: 0 0 50%;
max-width: 50%;
}
}
}

@ -72,5 +72,76 @@
font-size: 14px;
}
}
.banner-item {
margin-bottom: 15px;
display: flex;
flex-direction: column;
&-img {
display: block;
width: 300px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 300px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 149px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 137px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-top {
margin-bottom: 10px;
}
&-bottom {
position: relative;
width: 300px;
height: 80px;
&.has-img {
.banner-item-upload {
display: none;
}
&:hover {
.banner-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
}
}
}
}
&-title {
color: #23272B;
font-size: 14px;
}
}
}
}

@ -86,8 +86,11 @@
align-items: center;
& > img {
width: 40px;
height: auto;
//width: 40px;
//height: auto;
max-width: 130px !important;
max-height: 40px !important;
overflow: hidden;
}
& > .logo-label {

@ -78,12 +78,17 @@ class AccountsController < ApplicationController
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
login_control = LimitForbidControl::UserLogin.new(@user)
return normal_status(-2, "登录密码出错已达上限,将锁定密码1小时") if login_control.forbid?
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
password_ok = @user.check_password?(params[:password].to_s)
unless password_ok
if login_control.remain_times-1 == 0
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
else
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
end
login_control.increment!
return normal_status(-2, "错误的账号或密码")
return
end
successful_authentication(@user)
@ -111,9 +116,11 @@ class AccountsController < ApplicationController
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if user.save!
sucess_status
ActiveRecord::Base.transaction do
user.save!
LimitForbidControl::UserLogin.new(user).clear
end
sucess_status
rescue Exception => e
uid_logger_error(e.message)
tip_exception("密码重置失败")

@ -37,4 +37,9 @@ class Admins::BaseController < ApplicationController
append_js = ERB.new(File.open(path).read).result
response.body += append_js
end
# 重写此方法,防止影响超级管理员端云上实验室功能,因为那里重写了:current_laboratory方法
def setup_laboratory
Laboratory.current = Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)
end
end

@ -6,6 +6,16 @@ class Admins::CompetitionPrizeUsersController < Admins::BaseController
include_class = [:competition_team, :competition_prize, :approver,
user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]]
@prize_users = paginate(prize_users.preload(include_class))
respond_to do |format|
format.js
format.html
format.xlsx do
@all_prize_users = prize_users
filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end
end
end
def create

@ -0,0 +1,38 @@
class Admins::CustomersController < Admins::BaseController
helper_method :current_partner
def index
default_sort('created_at', 'desc')
customers = Admins::CustomerQuery.call(params.merge(partner_id: current_partner.id))
@customers = paginate(customers.preload(:school))
end
def create
params[:school_ids] = Array.wrap(params[:school_ids])
school_ids = School.where(id: params[:school_ids]).pluck(:id)
ActiveRecord::Base.transaction do
school_ids.each do |school_id|
next if current_partner.customers.exists?(school_id)
customer = Customer.create!(school_id: school_id)
current_partner.partner_customers.create!(customer: customer)
end
end
render_ok
end
def destroy
current_partner.customers.find(params[:id]).destroy!
render_delete_success
end
private
def current_partner
@_current_partner ||= Partner.find(params[:partner_id])
end
end

@ -12,10 +12,6 @@ class Admins::EnrollListsController < Admins::BaseController
respond_to do |format|
format.js
format.html
format.xls{
filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
}
end
end

@ -0,0 +1,14 @@
class Admins::ImportCompetitionScoresController < Admins::BaseController
def create
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
result = Admins::ImportCompetitionScoreService.call(params[:file].to_io, current_competition)
render_ok(result)
rescue Admins::ImportCompetitionScoreService::Error => ex
render_error(ex)
end
def current_competition
competition = Competition.find_by!(id: params[:competition_id])
end
end

@ -1,7 +1,6 @@
class Admins::LaboratoriesController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'id'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('id', 'desc')
laboratories = Admins::LaboratoryQuery.call(params)
@laboratories = paginate laboratories.preload(:school, :laboratory_users)
@ -20,6 +19,37 @@ class Admins::LaboratoriesController < Admins::BaseController
render_delete_success
end
def shixuns_for_select
except_shixun_ids = current_laboratory.laboratory_shixuns.pluck(:shixun_id)
shixuns = Shixun.where.not(id: except_shixun_ids)
keyword = params[:keyword].to_s.strip
if keyword.present?
like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword '\
'OR mirror_repositories.name LIKE :keyword'
shixuns = shixuns.joins(:user, :mirror_repositories).where(like_sql, keyword: "%#{keyword}%")
end
@count = shixuns.count
@shixuns = paginate(shixuns.includes(:user))
end
def subjects_for_select
except_subject_ids = current_laboratory.laboratory_subjects.pluck(:subject_id)
subjects = Subject.where.not(id: except_subject_ids)
keyword = params[:keyword].to_s.strip
if keyword.present?
like_sql = 'subjects.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword'
subjects = subjects.joins(:user).where(like_sql, keyword: "%#{keyword}%")
end
@count = subjects.count
@subjects = paginate(subjects.includes(:user))
end
private
def current_laboratory

@ -15,6 +15,9 @@ class Admins::LaboratorySettingsController < Admins::BaseController
end
def form_params
params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden])
params.permit(:identifier, :name,
:nav_logo, :login_logo, :tab_logo,
:subject_banner, :course_banner, :competition_banner, :moop_cases_banner,
:footer, navbar: %i[name link hidden])
end
end

@ -0,0 +1,48 @@
class Admins::LaboratoryShixunsController < Admins::BaseController
helper_method :current_laboratory, :current_laboratory_shixun
def index
laboratory_shixuns = Admins::LaboratoryShixunQuery.call(current_laboratory, params)
@laboratory_shixuns = paginate laboratory_shixuns.includes(shixun: %i[tag_repertoires user])
end
def create
shixun_ids = Array.wrap(params[:shixun_ids])
shixun_ids = Shixun.where(id: shixun_ids).pluck(:id)
exist_shixun_id = current_laboratory.laboratory_shixuns.where(shixun_id: shixun_ids).pluck(:shixun_id)
LaboratoryShixun.bulk_insert(*%i[shixun_id laboratory_id created_at updated_at]) do |worker|
(shixun_ids - exist_shixun_id).each do |shixun_id|
worker.add(shixun_id: shixun_id, laboratory_id: current_laboratory.id)
end
end
render_ok
end
def destroy
return render_js_error('不能删除自建实训', type: :notify) if current_laboratory_shixun.ownership?
current_laboratory_shixun.destroy!
render_delete_success
end
def homepage
current_laboratory_shixun.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_shixun.update!(homepage: false)
render_ok
end
private
def current_laboratory
@_current_laboratory ||= Laboratory.find(params[:laboratory_id])
end
def current_laboratory_shixun
@_current_laboratory_shixun ||= current_laboratory.laboratory_shixuns.find(params[:id])
end
end

@ -0,0 +1,45 @@
class Admins::LaboratorySubjectsController < Admins::BaseController
helper_method :current_laboratory, :current_laboratory_subject
def index
laboratory_subjects = Admins::LaboratorySubjectQuery.call(current_laboratory, params)
includes_tables = { subject: [:repertoire, :subject_level_system, user: {user_extension: :school}] }
@laboratory_subjects = paginate(laboratory_subjects.includes(includes_tables))
end
def create
subject = Subject.find(params[:subject_id])
Subjects::CopySubjectService.call(subject, current_user, current_laboratory)
render_ok
end
def destroy
return render_js_error('不能删除自建课程', type: :notify) if current_laboratory_subject.ownership?
current_laboratory_subject.destroy!
render_delete_success
end
def homepage
current_laboratory_subject.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_subject.update!(homepage: false)
render_ok
end
private
def current_laboratory
@_current_laboratory ||= Laboratory.find(params[:laboratory_id])
end
def current_laboratory_subject
@_current_laboratory_subject ||= current_laboratory.laboratory_subjects.find(params[:id])
end
end

@ -87,7 +87,6 @@ class Admins::MirrorRepositoriesController < Admins::BaseController
end
def check_shixun_mirrors!
return
return unless request.format.html?
Admins::CheckShixunMirrorsService.call

@ -0,0 +1,29 @@
class Admins::PartnersController < Admins::BaseController
def index
default_sort('created_at', 'desc')
partners = Admins::PartnerQuery.call(params)
@partners = paginate(partners.preload(:school))
end
def create
params[:school_ids] = Array.wrap(params[:school_ids])
school_ids = School.where(id: params[:school_ids]).pluck(:id)
exist_school_ids = Partner.where(school_id: school_ids).pluck(:school_id)
Partner.bulk_insert(*%i[school_id created_at updated_at]) do |worker|
(school_ids - exist_school_ids).each do |school_id|
worker.add(school_id: school_id)
end
end
render_ok
end
def destroy
Partner.find(params[:id]).destroy!
render_delete_success
end
end

@ -1,8 +1,7 @@
class Admins::ShixunSettingsController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('created_at', 'desc')
shixun_settings = Admins::ShixunSettingsQuery.call(params)
@editing_shixuns = shixun_settings.where(status:0).size

@ -191,6 +191,7 @@ class AttachmentsController < ApplicationController
candown = current_user.member_of_course?(course)
end
tip_exception(403, "您没有权限进入") if course.present? && !candown
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
end
end
end

@ -1,5 +1,5 @@
class CollegesController < ApplicationController
include Admins::PaginateHelper
include PaginateHelper
layout 'college'
@ -154,7 +154,7 @@ class CollegesController < ApplicationController
return true if current_user.admin_or_business? # 超级管理员|运营
return true if current_college.is_a?(Department) && current_college.member?(current_user) # 部门管理员
return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师
return true if current_school.customer_id && 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
end

@ -1,6 +1,11 @@
class Competitions::CertificatesController < Competitions::BaseController
def personal
prize_user = CompetitionPrizeUser.find_by!(user: current_user, id: params[:id])
prize_user =
if current_user.admin_or_business?
CompetitionPrizeUser.find(params[:id])
else
CompetitionPrizeUser.find_by!(user: current_user, id: params[:id])
end
return render_not_found unless prize_user.certificate_exist?
team = prize_user.competition_team
@ -12,7 +17,7 @@ class Competitions::CertificatesController < Competitions::BaseController
def team
team = CompetitionTeam.find(params[:id])
return render_forbidden unless team.team_members.exists?(user_id: current_user.id)
return render_forbidden unless current_user.admin_or_business? || team.team_members.exists?(user_id: current_user.id)
return render_not_found unless team.certificate_exists?
prize = team.competition_prize_users.first.competition_prize

@ -1,4 +1,6 @@
class Competitions::CompetitionStaffsController < Competitions::BaseController
skip_before_action :require_login
def show
end
end

@ -46,7 +46,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController
.where("exists(select 1 from homework_commons hcs where hcs.course_id = courses.id and hcs.publish_time is not null and hcs.publish_time < NOW() and hcs.homework_type = 4 and exists(#{subquery}))")
.joins('join course_members on course_members.course_id = courses.id and course_members.role in (1,2,3)')
.where(course_members: { user_id: @team_user_ids }).pluck(:id)
courses = Course.where(id: course_ids).joins(:practice_homeworks).where('homework_commons.publish_time < now()')
courses = Course.where(id: course_ids).joins(:practice_homeworks).where('homework_commons.publish_time < ?', end_time)
@courses = courses.select('courses.id, courses.name, courses.members_count, count(*) shixun_homework_count')
.group('courses.id').order('shixun_homework_count desc').having('shixun_homework_count > 0')

@ -9,7 +9,8 @@ class Competitions::CompetitionsController < Competitions::BaseController
def index
# 已上架 或者 即将上架
competitions = Competition.where(status: true).or(Competition.where.not(published_at: nil))
competitions = current_laboratory.competitions
competitions = competitions.where(status: true).or(competitions.where.not(published_at: nil))
competitions =
case params[:category]
@ -46,7 +47,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
@competition_modules = @competition.unhidden_competition_modules
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.finished? || !current_competition.competition_prize_users.exists?(user: current_user)
if !current_user.logged? || !current_competition.finished? || (!current_competition.competition_prize_users.exists?(user: current_user) && !current_user.admin_or_business?)
@competition_modules = @competition_modules.select { |mod| mod.name != '获奖证书' }
end
@ -123,26 +124,41 @@ class Competitions::CompetitionsController < Competitions::BaseController
@stage = @competition.competition_stages.take
end
@records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})
@all_records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})
.select("competition_teams.*, score, cost_time").order("score desc, cost_time desc")
current_team_ids = @competition.team_members.where(user_id: current_user.id).pluck(:competition_team_id).uniq
@user_ranks = @records.select{|com_team| current_team_ids.include?(com_team.id)}
@records = @records.where("score > 0")
@user_ranks = @all_records.select{|com_team| current_team_ids.include?(com_team.id)}
@records = @all_records.where("score > 0")
@record_ids = @records.pluck(:id)
if params[:format] == "xlsx"
@records = @records.includes(user: [user_extension: :school], team_members: :user)
respond_to do |format|
format.xlsx{
set_export_cookies
chart_to_xlsx(@records, @competition)
chart_to_xlsx(@all_records, @competition)
exercise_export_name = "#{@competition.name}比赛成绩"
render xlsx: "#{exercise_export_name.strip}",template: "competitions/competitions/chart_list.xlsx.axlsx",locals:
{table_columns: @competition_head_cells, chart_lists: @competition_cells_column}
}
end
else
@records = @records.includes(:team_members, user: :user_extension).limit(@competition.awards_count)
@records = @records.includes(:team_members, competition_prize_users: :competition_prize, user: :user_extension).limit(@competition.awards_count)
end
end
def export_extra_course_statistics
@competition = current_competition
@all_records = @competition.competition_teams.joins(:competition_scores, user: [user_extension: :school])
.select("competition_teams.*, competition_scores.score, cost_time").order("score desc, cost_time desc")
respond_to do |format|
format.xlsx{
extra_chart_to_xlsx(@all_records)
exercise_export_name = "#{@competition.name}比赛成绩"
render xlsx: "#{exercise_export_name.strip}",template: "competitions/competitions/chart_list.xlsx.axlsx",locals:
{table_columns: @competition_head_cells, chart_lists: @competition_cells_column}
}
end
end
@ -154,7 +170,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
def allow_visit
return if current_competition.published? || admin_or_business?
return if current_competition.nearly_published? && current_competition.manager?(current_user)
return if current_competition.manager?(current_user)
render_forbidden
end
@ -166,7 +182,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
def check_manager_permission!
return if current_user.admin_or_business?
return if current_competition.nearly_published? && current_competition.manager?(current_user)
return if current_competition.manager?(current_user)
render_forbidden
end
@ -219,4 +235,67 @@ class Competitions::CompetitionsController < Competitions::BaseController
@competition_cells_column.push(row_cells_column)
end
end
def extra_chart_to_xlsx records
@competition_head_cells = []
@competition_cells_column = []
@competition_head_cells = %w(序号 姓名 id 学校 实训数 学习人数 被fork发布的学习人数 实训有效作品数 实训应用值 课堂数 学生数量 发布的实训作业数 有效作品数 课堂应用值 总分)
records.each_with_index do |record, index|
row_cells_column = []
row_cells_column << index + 1
record_user = record.user
row_cells_column << record_user.real_name
row_cells_column << record_user.login
row_cells_column << record_user.school_name
total_score = 0
shixun_count = 0
shixun_member_count = 0
shixun_fork_member_count = 0
shixun_valid_count = 0
shixun_score = 0
shixun_records = record.competition_course_records.where(type: 'CompetitionCourseShixunRecord')
shixun_records.each do |shixun|
shixun_count += 1
shixun_member_count += shixun.snapshot['myshixuns_count'].to_i
shixun_fork_member_count += shixun.snapshot['forked_myshixun_count'].to_i
shixun_valid_count += shixun.snapshot['valid_myshixun_count'].to_i
shixun_score += shixun.score.to_i
end
row_cells_column << shixun_count
row_cells_column << shixun_member_count
row_cells_column << shixun_fork_member_count
row_cells_column << shixun_valid_count
row_cells_column << shixun_score
total_score += shixun_score
course_count = 0
course_member_count = 0
course_homework_count = 0
course_valid_count = 0
course_score = 0
course_records = record.competition_course_records.where(type: 'CompetitionCourseCourseRecord')
course_records.each do |course|
course_count += 1
course_member_count += course.snapshot['members_count'].to_i
course_homework_count += course.snapshot['shixun_homework_count'].to_i
course_valid_count += course.snapshot['valid_myshixun_count'].to_i
course_score += course.score.to_i
end
row_cells_column << course_count
row_cells_column << course_member_count
row_cells_column << course_homework_count
row_cells_column << course_valid_count
row_cells_column << course_score
total_score += course_score
row_cells_column << total_score
@competition_cells_column.push(row_cells_column)
end
end
end

@ -2,7 +2,7 @@ class Competitions::PrizeLeaderAccountsController < Competitions::BaseController
before_action :require_prize_team_leader!
def update
Competitions::SavePrizeTeamAccountService.call(current_competition, current_user, update_params)
Competitions::SavePrizeTeamAccountService.call(current_competition, current_prize_user, update_params)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
@ -13,8 +13,8 @@ class Competitions::PrizeLeaderAccountsController < Competitions::BaseController
def require_prize_team_leader!
prize_user = current_competition.competition_prize_users.joins(:competition_prize)
.where(competition_prizes: { category: :bonus })
.find_by(leader: true, user_id: current_user.id)
return if prize_user.present?
.find_by(leader: true, user_id: current_prize_user.id)
return if prize_user.present? && (current_user.admin_or_business? || current_user.id == current_prize_user.id)
render_forbidden
end
@ -22,4 +22,8 @@ class Competitions::PrizeLeaderAccountsController < Competitions::BaseController
def update_params
params.permit(:bank, :second_bank, :card_no)
end
def current_prize_user
@_current_prize_user ||= User.find(params[:user_id])
end
end

@ -1,12 +1,14 @@
class Competitions::PrizesController < Competitions::BaseController
before_action :require_prize_user!
helper_method :current_prize_user
def show
self_prizes = current_competition.competition_prize_users.where(user_id: current_user.id).includes(:competition_team).order(:competition_prize_id)
self_prizes = current_competition.competition_prize_users.where(user_id: current_prize_user.id).includes(:competition_team).order(:competition_prize_id)
@leader = self_prizes.any?{ |prize_user| prize_user.leader? && prize_user.competition_prize.category == 'bonus' } # 是否为队长并且有奖金奖励
if @leader
@bank_account = self_prizes.find(&:leader?).extra
if @leader || current_user.admin_or_business?
@bank_account = self_prizes.find(&:leader?)&.extra
@bank_account_editable = self_prizes.select(&:leader?).all?(&:pending?)
end
@ -22,8 +24,13 @@ class Competitions::PrizesController < Competitions::BaseController
private
def require_prize_user!
return if current_competition.competition_prize_users.exists?(user: current_user)
return if current_competition.competition_prize_users.exists?(user: current_prize_user)
return if current_user.admin_or_business? || current_user.id == current_prize_user.id
render_forbidden
end
def current_prize_user
@_current_prize_user ||= User.find(params[:user_id])
end
end

@ -18,6 +18,7 @@ module Base::ErrorRescueHandler
render_unprocessable_entity(ex.model.errors.full_messages.join(','))
end
rescue_from ActiveRecord::RecordInvalid do |ex|
ex.backtrace.each { |msg| Rails.logger.error(msg) }
render_unprocessable_entity(ex.record.errors.full_messages.join(','))
end
end

@ -8,6 +8,7 @@ module Base::RenderHelper
def render_forbidden
render_by_format(html: -> { current_user&.business? ? render('shared/403') : redirect_to('/403') },
js: -> { render_js_error(I18n.t('error.forbidden'), type: :notify) },
json: -> { render status: 403, json: { messages: I18n.t('error.forbidden') } } )
end

@ -50,7 +50,7 @@ module GitHelper
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
# 将要生成的仓库名字
new_repo_name = "#{username.try(:strip)}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
uid_logger("start fork container: repo_name is #{new_repo_name}")
# uid_logger("start fork container: repo_name is #{new_repo_name}")
GitService.fork_repository(repo_path: original_rep_path, fork_repository_path: (new_repo_name + ".git"))
container.update_attributes!(:repo_name => new_repo_name)
end

@ -2,6 +2,8 @@ module LaboratoryHelper
extend ActiveSupport::Concern
included do
before_action :setup_laboratory
helper_method :current_laboratory
helper_method :default_setting
end
@ -17,4 +19,8 @@ module LaboratoryHelper
def default_setting
@_default_setting ||= LaboratorySetting.find_by(laboratory_id: 1)
end
def setup_laboratory
Laboratory.current = current_laboratory
end
end

@ -17,6 +17,7 @@ class Cooperative::BaseController < ApplicationController
def current_laboratory
@_current_laboratory ||= Laboratory.find_by_subdomain(request.subdomain)
# @_current_laboratory ||= Laboratory.find 1
end
def current_setting_or_default(name)

@ -0,0 +1,51 @@
class Cooperative::CompetitionPrizeUsersController < Cooperative::BaseController
def index
@competition = current_competition
prize_users = Admins::CompetitionPrizeUserQuery.call(params.merge(competition_id: current_competition.id))
include_class = [:competition_team, :competition_prize, :approver,
user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]]
@prize_users = paginate(prize_users.preload(include_class))
respond_to do |format|
format.js
format.html
format.xlsx do
@all_prize_users = prize_users
filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end
end
end
def create
Admins::CreateCompetitionPrizeUsersService.call(current_competition)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def approve
Admins::ApproveCompetitionPrizeUserService.call(current_prize_user, current_user)
@prize_user = current_prize_user
rescue ApplicationService::Error => ex
render_js_error(ex.message, type: :notify)
end
def unapprove
Admins::UnapproveCompetitionPrizeUserService.call(current_prize_user, current_user)
@prize_user = current_prize_user
rescue ApplicationService::Error => ex
render_js_error(ex.message, type: :notify)
end
private
def current_prize_user
@_current_prize_user ||= current_competition.competition_prize_users.find(params[:id])
end
def current_competition
@_current_competition ||= current_laboratory.competitions.find(params[:competition_id])
end
end

@ -0,0 +1,43 @@
class Cooperative::CompetitionPrizesController < Cooperative::BaseController
def index
@competition = current_competition
end
def new
@prize = current_competition.competition_prizes.new
end
def create
@prize = current_competition.competition_prizes.create!(save_params)
render_ok
end
def edit
@prize = current_competition_prize
end
def update
current_competition_prize.update!(save_params)
render_ok
end
def destroy
current_competition_prize.destroy!
render_delete_success
end
private
def current_competition_prize
@_current_competition_prize ||= current_competition.competition_prizes.find(params[:id])
end
def current_competition
@_current_competition ||= current_laboratory.competitions.find(params[:competition_id])
end
def save_params
params.require(:competition_prize).permit(:name, :category, :num)
end
end

@ -0,0 +1,33 @@
class Cooperative::CompetitionSettingsController < Cooperative::BaseController
def index
@competition = current_competition
end
def basic_setting
Admins::CompetitionBasicSettingService.call(current_competition, basic_form_params)
render_ok
end
def nav_setting
Admins::CompetitionNavSettingService.call(current_competition, nav_form_params)
render_ok
end
private
def current_competition
@_current_competition ||= current_laboratory.competitions.find(params[:competition_id])
end
def basic_form_params
params.permit(:identifier, :name, :sub_title, :start_time, :end_time, :mode,
:identifier, :bonus, :awards_count, :description, :course_id, :teach_start_time,
:teach_end_time, sponsor_schools: [], region_schools: [], manager_ids: [])
end
def nav_form_params
params.permit(:enroll_end_time,
competition_staffs: %i[category minimum maximum mutiple_limited],
navbar: %i[module_type module_id name hidden position url])
end
end

@ -0,0 +1,194 @@
class Cooperative::CompetitionStagesController < Cooperative::BaseController
def create
Admins::CompetitionStageCreateService.call(current_competition, update_form_params)
render_ok
end
def update
Admins::CompetitionStageUpdateService.call(current_competition, update_form_params, current_stage)
render_ok
end
def destroy
current_stage.destroy!
end
def calculate_stage_score
if current_stage.max_end_time && current_stage.max_end_time < Time.now
ActiveRecord::Base.transaction do
begin
current_stage.competition_scores.destroy_all
if current_stage.competition_stage_sections.size > 0
# 是否只有老师参赛
only_teacher = current_competition.member_staff.blank?
stage_sections = current_stage.competition_stage_sections.includes(:competition_entries)
shixuns = Shixun.where(identifier: current_stage.competition_entries.pluck(:shixun_identifier).reject(&:blank?))
challenges = Challenge.where(shixun_id: shixuns.pluck(:id))
# 计算每个战队的成绩
current_competition.competition_teams.each do |team|
totoal_score = 0
total_time = 0
# 只有老师参赛则计算所有参赛队员的成绩,否则只计算学生的成绩
user_ids = only_teacher ? team.team_members.pluck(:user_id) : team.team_members.where(is_teacher: 0).pluck(:user_id)
stage_sections.each do |section|
shixun_identifiers = section.competition_entries.pluck(:shixun_identifier).reject(&:blank?)
shixun_ids = shixuns.select{ |shixun| shixun_identifiers.include?(shixun.identifier) }.map(&:id)
section_challenges = challenges.select{ |challenge| shixun_ids.include?(challenge.shixun_id) }
if section.score_source == 0
result1 = chart_stage_score user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length
else
result1 = chart_stage_rate user_ids, section.start_time, section.end_time, section_challenges, section_challenges.length/shixun_ids.length
end
score = result1[0]
time = result1[1]
totoal_score += score
total_time += time
end
# 比赛已截止且未有分数纪录 则创建
unless team.competition_scores.exists?(competition_id: current_competition.id, competition_stage_id: current_stage.id)
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: current_competition.id,
competition_stage_id: current_stage.id, score: totoal_score, cost_time: total_time)
end
end
# 如果计算的是最后一个阶段,则同时计算总成绩(只有一个阶段则不需计算)
if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size > 1
calculate_total_score current_competition
end
end
rescue Exception => e
uid_logger_error(e.message)
@message = "#{e.message}"
end
end
@message = "计算成功"
else
@message = "#{current_stage.name}还未结束"
end
end
def send_message
if current_stage.max_end_time && current_stage.max_end_time > Time.now
User.where(id: TeamMember.where(competition_team_id: current_competition.competition_teams.pluck(:id)).pluck(:user_id).uniq).each do |user|
name = current_competition.name + "#{current_competition.sub_title}#{stage.name}"
begin
if user.phone.present?
Educoder::Sms.send(mobile: user.phone.to_s, code: '1', send_type:'competition_start', user_name:user.show_name,
name:name, result:section.start_time.strftime('%Y-%m-%d %H:%M:%S'))
end
rescue => e
logger_error(e)
render_error("发送验证码出错")
end
end
else
render_error("#{current_stage.name}已结束")
end
end
private
def current_competition
@_current_competition ||= current_laboratory.competitions.find(params[:competition_id])
end
def current_stage
@_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:id])
end
def update_form_params
params.permit(:stage_name, :score_rate, stage: [:start_time, :end_time, :entry, :score_source, identifiers: []])
end
# challenges 每阶段的所有关卡
# s_time 阶段开始时间 e_time 阶段结束时间
# rate 关卡经验值与分数的比值
# challenge_count 每个实训的关卡数
# 对三个实训的所有关卡循环: 找到在比赛时间内通关的最低耗时
def chart_stage_score user_ids, s_time, e_time, challenges, challenge_count
total_score = 0
total_time = 0
length = challenge_count #每个实训的关卡数
for i in 1..length
score = 0
time = 0
challenges.select{|challenge| challenge.position == i}.each do |challenge|
Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game|
game_score = challenge.score
cost_time = (game.end_time.to_i - s_time.to_i) > 0 ? (game.end_time.to_i - s_time.to_i) : 0
if score < game_score
score = game_score
time = cost_time
elsif score == game_score
time = cost_time > time ? time : cost_time
end
end
end
total_score += score
total_time += time
end
return [total_score, total_time]
end
def chart_stage_rate user_ids, s_time, e_time, challenges, challenge_count
# 第三阶段的得分和耗时
total_score = 0
total_time = 0
length = challenge_count #每个实训的关卡数
for i in 1..length
score3 = 0
time3 = 0
challenges.select{|challenge| challenge.position == i}.each do |challenge|
Game.where(:challenge_id => challenge.id, :user_id => user_ids, :status => 2).select{|game| game.open_time >= s_time && game.end_time <= e_time }.each do |game|
outputs = game.outputs.select{|output| !output.text_scor.nil? && output.created_at <= e_time }
if outputs.present?
outputs = outputs.sort { |a, b| b[:text_scor].to_f <=> a[:text_scor].to_f }
myshixun_score = outputs.first.text_scor.to_f
myshixun_time = outputs.first.created_at.to_i - s_time.to_i
if score3 < myshixun_score
score3 = myshixun_score
time3 = myshixun_time
elsif score3 == myshixun_score
time3 = myshixun_time > time3 ? time3 : myshixun_time
end
end
end
end
total_score += score3
total_time += time3
end
return [total_score, total_time]
end
def calculate_total_score competition
competition.competition_scores.where(competition_stage_id: 0).destroy_all
competition.competition_teams.each do |team|
total_score = 0
total_time = 0
competition.competition_stages.where("score_rate > 0").each do |stage|
stage_score = team.competition_scores.where(competition_stage_id: stage.id).take
total_score += stage_score.try(:score).to_f * stage.score_rate
total_time += stage_score.try(:cost_time).to_i
end
unless team.competition_scores.exists?(competition_id: competition.id, competition_stage_id: 0)
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
competition_stage_id: 0, score: total_score, cost_time: total_time)
end
end
end
end

@ -0,0 +1,57 @@
class Cooperative::CompetitionsController < Cooperative::BaseController
before_action :find_competition, except: [:index]
def index
# params[:sort_by] = params[:sort_by].presence || 'created_at'
# params[:sort_direction] = params[:sort_direction].presence || 'desc'
@competitions = current_laboratory.competitions.order("created_at desc")
@params_page = params[:page] || 1
@competitions = paginate @competitions
ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count
@competition_hot = ModuleSetting.exists?(module_type: "Competition", property: "hot")
respond_to do |format|
format.js
format.html
end
end
def create
name = params[:competition_name].to_s.strip
Competition.create!(name: name)
render_ok
end
def hot_setting
if params[:hot].to_i == 1 && !ModuleSetting.exists?(module_type: "Competition", property: "hot")
ModuleSetting.create!(module_type: "Competition", property: "hot")
elsif params[:hot].to_i == 0 && ModuleSetting.exists?(module_type: "Competition", property: "hot")
ModuleSetting.where(module_type: "Competition", property: "hot").destroy_all
end
render_ok
end
def publish
@competition.update_attributes!(published_at: Time.now)
end
def unpublish
@competition.update_attributes!(published_at: nil)
end
def online_switch
if @competition.status
@competition.update_attributes!(status: false)
else
@competition.update_attributes!(status: true, online_time: Time.now)
end
end
private
def find_competition
@competition = current_laboratory.competitions.find_by(id: params[:id])
end
end

@ -0,0 +1,33 @@
class Cooperative::EnrollListsController < Cooperative::BaseController
def index
@competition = current_competition
default_sort('created_at', 'desc')
enroll_lists = Admins::CompetitionEnrollListQuery.call(@competition, params)
@params_page = params[:page] || 1
@enroll_lists = paginate enroll_lists.preload(competition_team: [:user, :teachers], user: { user_extension: :school })
@personal = @competition.personal?
respond_to do |format|
format.js
format.html
end
end
def export
default_sort('created_at', 'desc')
@enroll_lists = Admins::CompetitionEnrollListQuery.call(current_competition, params)
@enroll_lists = @enroll_lists.preload(competition_team: [:user, :teachers], user: { user_extension: :school })
@competition_scores = current_competition.competition_scores.where(competition_stage_id: 0).order("score desc, cost_time desc").pluck(:competition_team_id)
@personal = current_competition.personal?
filename = ["#{current_competition.name}竞赛报名列表", Time.zone.now.strftime('%Y-%m-%d%H:%M:%S')].join('-') << '.xlsx'
render xlsx: 'export', filename: filename
end
private
def current_competition
@_current_competition ||= current_laboratory.competitions.find(params[:competition_id])
end
end

@ -1,5 +1,5 @@
class Cooperative::FilesController < Cooperative::BaseController
before_action :convert_file!, only: [:create]
before_action :convert_file!, :check_permission!, only: [:create]
def create
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
@ -29,6 +29,22 @@ class Cooperative::FilesController < Cooperative::BaseController
render_error(ex.message)
end
def check_permission!
permission =
case params[:source_type].to_s
when '' then false
when 'Shixun' then
current_laboratory.laboratory_shixuns.exists?(ownership: true, shixun_id: params[:source_id])
when 'Subject' then
current_laboratory.laboratory_subjects.exists?(ownership: true, subject_id: params[:source_id])
else true
end
return if permission
render_forbidden
end
def file_path
@_file_path ||= begin
case params[:source_type].to_s

@ -9,6 +9,9 @@ class Cooperative::LaboratorySettingsController < Cooperative::BaseController
end
def form_params
params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden])
params.permit(:identifier, :name,
:nav_logo, :login_logo, :tab_logo,
:subject_banner, :course_banner, :competition_banner, :moop_cases_banner,
:footer, navbar: %i[name link hidden])
end
end

@ -0,0 +1,46 @@
class Cooperative::LaboratoryShixunsController < Cooperative::BaseController
before_action :check_shixun_ownership!, only: [:edit, :update]
helper_method :current_laboratory_shixun
def index
laboratory_shixuns = Admins::LaboratoryShixunQuery.call(current_laboratory, params)
@laboratory_shixuns = paginate laboratory_shixuns.includes(shixun: %i[tag_repertoires user])
end
def edit
end
def update
end
def destroy
return render_js_error('不能删除自建实训', type: :notify) if current_laboratory_shixun.ownership?
current_laboratory_shixun.destroy!
render_delete_success
end
def homepage
current_laboratory_shixun.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_shixun.update!(homepage: false)
render_ok
end
private
def current_laboratory_shixun
@_current_laboratory_shixun ||= current_laboratory.laboratory_shixuns.find(params[:id])
end
def check_shixun_ownership!
return if current_laboratory_shixun.ownership?
render_forbidden
end
end

@ -0,0 +1,53 @@
class Cooperative::LaboratorySubjectsController < Cooperative::BaseController
before_action :check_subject_ownership!, only: [:edit, :update]
helper_method :current_laboratory_subject
def index
laboratory_subjects = Admins::LaboratorySubjectQuery.call(current_laboratory, params)
includes_tables = { subject: [:repertoire, :subject_level_system, user: {user_extension: :school}] }
@laboratory_subjects = paginate(laboratory_subjects.includes(includes_tables))
end
def edit
@laboratory_subject = current_laboratory_subject
end
def update
current_laboratory_subject.subject.update!(update_params)
end
def destroy
return render_js_error('不能删除自建实践课程', type: :notify) if current_laboratory_subject.ownership?
current_laboratory_subject.destroy!
render_delete_success
end
def homepage
current_laboratory_subject.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_subject.update!(homepage: false)
render_ok
end
private
def current_laboratory_subject
@_current_laboratory_subject ||= current_laboratory.laboratory_subjects.find(params[:id])
end
def check_subject_ownership!
return if current_laboratory_subject.ownership?
render_forbidden
end
def update_params
params.require(:laboratory_subject).permit(:repertoire_id, :subject_level_system_id)
end
end

@ -1,7 +1,13 @@
class Cooperative::UsersController < Cooperative::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('created_on', 'desc')
users = Admins::UserQuery.call(search_params.merge(laboratory_id: current_laboratory.id))
@users = paginate users.includes(user_extension: :school)
end
def for_select
default_sort('created_on', 'desc')
users = Admins::UserQuery.call(search_params)
@users = paginate users.includes(user_extension: :school)
@ -10,6 +16,6 @@ class Cooperative::UsersController < Cooperative::BaseController
private
def search_params
params.permit(:name, :sort_by, :sort_direction)
params.permit(:identity, :name, :keyword, :school_name, :sort_by, :sort_direction)
end
end

@ -18,7 +18,7 @@ class CoursesController < ApplicationController
:left_banner, :top_banner, :apply_to_join_course, :exit_course, :course_groups]
before_action :set_course, only: [:show, :update, :destroy, :settings, :set_invite_code_halt,
:set_public_or_private, :search_teacher_candidate, :teachers, :apply_teachers,
:top_banner, :left_banner, :add_teacher_popup, :add_teacher,
:top_banner, :left_banner, :add_teacher_popup, :add_teacher, :inform_up, :inform_down,
:graduation_group_list, :create_graduation_group, :join_graduation_group,
:course_group_list, :set_course_group, :change_course_admin, :change_course_teacher,
:delete_course_teacher, :teacher_application_review, :students, :all_course_groups,
@ -41,7 +41,7 @@ class CoursesController < ApplicationController
:set_course_group, :create_group_by_importing_file,
:update_task_position, :tasks_list]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group,
:change_course_teacher, :course_group_list, :change_member_role,
:change_course_teacher, :course_group_list, :change_member_role,:inform_up, :inform_down,
:teacher_application_review, :apply_teachers, :delete_course_teacher]
before_action :validate_course_name, only: [:create, :update]
before_action :find_board, only: :board_list
@ -61,12 +61,13 @@ class CoursesController < ApplicationController
@user = current_user
# 根据分类查询课堂(全部,我的,最新,最热)
@order = params[:order].present? ? params[:order] : "all"
@courses = current_laboratory.courses.not_deleted
if @order == "visits"
order_str = "courses.id = 1309 DESC, courses.visits DESC"
@courses = Course.where(is_delete: 0, is_hidden: 0)
@courses = @courses.where(is_hidden: 0)
else
order_str = "courses.id = 1309 DESC, courses.homepage_show DESC, courses.created_at desc"
@courses = Course.where(is_delete: 0, is_hidden: 0, is_end: 0)
@courses = @courses.where(is_hidden: 0, is_end: 0)
end
# 金课未开课的不显示在首页
@ -281,13 +282,43 @@ class CoursesController < ApplicationController
end
def informs
@informs = @course.informs
@informs = @course.informs.order("position desc")
end
def inform_up
inform = @course.informs.find_by(id: params[:inform_id])
next_inform = inform.next_inform
ActiveRecord::Base.transaction do
if next_inform.blank?
render_error('已经到达最顶部')
else
inform.update_attribute(:position, (inform.position + 1))
next_inform.update_attribute(:position, inform.position - 1)
render_ok
end
end
end
def inform_down
inform = @course.informs.find_by(id: params[:inform_id])
last_inform = inform.last_inform
ActiveRecord::Base.transaction do
if last_inform.blank?
render_error('已经到达最底部')
else
inform.update_attribute(:position, (inform.position - 1))
last_inform.update_attribute(:position, inform.position + 1)
render_ok
end
end
end
def new_informs
inform = Inform.new(container: @course)
inform.name = params[:name]
inform.description = params[:description]
inform.position = @course.informs.maximum(:position).to_i + 1
inform.save!
normal_status("创建成功")
end
@ -300,6 +331,7 @@ class CoursesController < ApplicationController
def delete_informs
inform = @course.informs.find_by(id: params[:inform_id])
@course.informs.where("position > ?", inform.position).update_all("position = position - 1")
inform.destroy!
normal_status("删除成功")
end
@ -436,6 +468,7 @@ class CoursesController < ApplicationController
# @users = User.where.not(id: user_ids_of_course_members)
@users = User.where(status: User::STATUS_ACTIVE)
@users = @users.where(laboratory_id: current_laboratory.id) unless current_laboratory.main_site?
@users = @users.where("concat(users.lastname, users.firstname) like '%#{name}%'") if name.present?
# REDO:Extension
@users = @users.joins(user_extension: :school).where("schools.name like '%#{school_name}%'") if school_name.present?
@ -1052,6 +1085,7 @@ class CoursesController < ApplicationController
# REDO:Extension
@users = User.where(status: User::STATUS_ACTIVE)
@users = @users.where(laboratory_id: current_laboratory.id) unless current_laboratory.main_site?
@users = @users.where("concat(users.lastname, users.firstname) like '%#{name}%'") if name.present?
# REDO:Extension
@users = @users.joins(user_extension: :school).where("schools.name like '%#{school_name}%'") if school_name.present?
@ -1071,12 +1105,12 @@ class CoursesController < ApplicationController
# 邀请码验证
return normal_status(-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 = 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)
if course.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)
course = Course.find_by(id: course_group.course_id, is_delete: 0, invite_code_halt: 0, laboratory_id: current_laboratory.id)
return normal_status(-1, "邀请码无效") if course.blank?
end
@ -1110,7 +1144,7 @@ class CoursesController < ApplicationController
# 如果在该课堂已经存在学生身份,且邀请码为分班邀请码,则将其直接加入分班
existing_student.update_attributes(course_group_id: course_group.id) if course_group.present?
else
correspond_teacher_exist = current_user.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.is_active = 0 if correspond_teacher_exist
@ -1508,7 +1542,7 @@ class CoursesController < ApplicationController
end
def course_statistics course, max_exp, limit
max_rate = 20.0 / max_exp
max_rate = max_exp.nil? ? 0 : 20.0 / max_exp
sql_select = %Q{ SELECT a.*, (message_num*0.2 + message_reply_num*0.1 + resource_num*0.5 + homework_journal_num*0.1 + graduation_num +
homework_num + exercise_num + poll_num*0.7 + exercise_score * 0.7 + graduation_score * 0.7 + homework_score * 0.7 + exp*#{max_rate})

@ -107,7 +107,7 @@ class ExerciseAnswersController < ApplicationController
normal_status(-1,"已提交/已结束的试卷不允许修改!")
else
if (@exercise_user_status == Exercise::DEADLINE && @exercise_user.commit_status == 0) || (@exercise.time > 0 && @exercise_user.start_at.present? && ((@exercise_user.start_at + @exercise.time.to_i.minutes) < Time.now))
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
objective_score = calculate_student_score(@exercise,current_user,Time.now)[:total_score]
subjective_score = @exercise_user.subjective_score < 0.0 ? 0.0 : @exercise_user.subjective_score
total_score = objective_score + subjective_score
commit_option = {

@ -458,15 +458,14 @@ class ExercisesController < ApplicationController
# 统一设置或者分班为0则更新试卷并删除试卷分组
if unified_setting || (course_group_ids.size == 0)
params_publish_time = params[:publish_time].blank? ? nil : params[:publish_time].to_time
params_end_time = nil
if params[:end_time].blank?
if params_publish_time.present?
params_end_time = params_publish_time + 30.days
end
else
params_end_time = params[:end_time].to_time
end
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day
params_publish_time = params[:publish_time].to_time
params_end_time = params[:end_time].to_time
if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time)
normal_status(-1,"已发布/已截止,不允许修改发布时间")
@ -500,20 +499,23 @@ class ExercisesController < ApplicationController
old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除
params_times.each do |t|
tip_exception("发布时间不能为空") if t[:publish_time].blank?
tip_exception("截止时间不能为空") if t[:end_time].blank?
tip_exception("截止时间不能早于发布时间") if t[:publish_time].to_time > t[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && t[:end_time].to_time > @course.end_date.end_of_day
course_id = t[:course_group_id]
exercise_publish_time = t[:publish_time].present? ? t[:publish_time].to_time : nil
exercise_end_time = nil
if t[:end_time].blank?
if exercise_publish_time.present?
exercise_end_time = exercise_publish_time + 30.days
end
else
exercise_end_time = t[:end_time].to_time
end
exercise_publish_time = t[:publish_time].to_time
exercise_end_time = t[:end_time].to_time
exercise_group = exercise_groups.find_in_exercise_group("course_group_id",course_id) #判断该分班是否存在
if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time)
error_count += 1
end
if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now)
error_count += 1
end
if error_count == 0
common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id
@ -529,12 +531,12 @@ class ExercisesController < ApplicationController
if the_group_setting_status == 2
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => exercise_end_time
:end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time
}
elsif the_group_setting_status == 3
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
:end_time => exercise_end_time
}
end
the_group_setting.update_attributes!(ex_group_params)
@ -550,7 +552,7 @@ class ExercisesController < ApplicationController
:end_time => exercise_end_time
}
new_exercise_group = ExerciseGroupSetting.new(exercise_group_params)
new_exercise_group.save
new_exercise_group.save!
end
end
end
@ -558,7 +560,7 @@ class ExercisesController < ApplicationController
if error_count > 0
error_count == 0
normal_status(-1,"已发布/已截止的试卷不允许修改时间")
normal_status(-1,"试卷发布/截止时间不能小于当前时间")
else
# 未发布的分班设置才能删除
if old_exercise_groups.size > 0
@ -599,7 +601,7 @@ class ExercisesController < ApplicationController
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("提交出现错误!")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -609,13 +611,27 @@ class ExercisesController < ApplicationController
def adjust_score
exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id])
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-#{@exercise.question_scores}") if params[:score].to_f < 0 || params[:score].to_f.round(1) > @exercise.question_scores.round(1)
if @exercise.subjective_score > 0
tip_exception("主观题成绩不能为空") if params[:subjective_score].blank?
tip_exception("主观题成绩不能小于零") if params[:subjective_score].to_f < 0
tip_exception("主观题成绩不能大于总分值:#{@exercise.subjective_score}") if params[:subjective_score].to_f.round(1) > @exercise.subjective_score.round(1)
end
if @exercise.objective_score > 0
tip_exception("客观题成绩不能为空") if params[:objective_score].blank?
tip_exception("客观题成绩不能小于零") if params[:objective_score].to_f < 0
tip_exception("客观题成绩不能大于总分值:#{@exercise.objective_score}") if params[:objective_score].to_f.round(1) > @exercise.objective_score.round(1)
end
ActiveRecord::Base.transaction do
start_at_time = exercise_user.start_at || Time.now
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: params[:score].to_f.round(2), commit_method: 5)
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, score: params[:score], comment: params[:comment])
subjective_score = @exercise.subjective_score > 0 ? params[:subjective_score].to_f.round(2) : 0
objective_score = @exercise.objective_score > 0 ? params[:objective_score].to_f.round(2) : 0
score = subjective_score + objective_score
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score,
subjective_score: subjective_score, objective_score: objective_score, commit_method: 5)
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id,
subjective_score: subjective_score, objective_score: objective_score)
normal_status("操作成功")
end
end
@ -834,10 +850,11 @@ class ExercisesController < ApplicationController
g_course = params[:group_ids]
if g_course.present?
teacher_course_group_ids = @course.charge_group_ids(current_user)
if g_course.map(&:to_i).sort == teacher_course_group_ids.sort #开始为统一设置
all_course_group_ids = @course.course_groups.pluck(:id)
if exercise.unified_setting && g_course.map(&:to_i).sort == all_course_group_ids.sort #开始为统一设置
exercise.exercise_group_settings.destroy_all
new_ex_status = set_exercise_status(exercise.publish_time,Time.now)
exercise.update_attributes(:end_time => Time.now,:unified_setting => true,:exercise_status => new_ex_status)
exercise.update_attributes(:end_time => Time.now,:exercise_status => new_ex_status)
exercise_users = exercise.exercise_users
else
course_members_ids = course_students.course_find_by_ids("course_group_id",g_course).pluck(:user_id).uniq #该班级的全部学生
@ -886,7 +903,7 @@ class ExercisesController < ApplicationController
ex_user_ids = exercise_users.pluck(:id)
EndExerciseCalculateJob.perform_later(ex_user_ids,exercise)
EndExerciseCalculateJob.perform_later(ex_user_ids,exercise,Time.now.to_s)
# exercise_users.each do |user|
# if user.commit_status == 0 && user.start_at.present?
# objective_score = calculate_student_score(exercise,user.user)[:total_score]
@ -1019,59 +1036,57 @@ class ExercisesController < ApplicationController
#学生开始答题页面
def start_answer
ActiveRecord::Base.transaction do
begin
ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users因为exercise_users删除时只是状态改变未删除
@exercise_user_current = ex_users_current&.first
if ex_users_current.exists?
if @exercise_user_current.start_at.blank?
@exercise_user_current.update_attribute("start_at",Time.now)
end
else
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建exercise_user表理论上老师是不能进入答题的
exercise_user_params = {
:user_id => @exercise_current_user_id,
:exercise_id => @exercise.id,
:start_at => Time.now
}
exercise_user_current = ExerciseUser.new(exercise_user_params)
exercise_user_current.save
end
begin
ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users因为exercise_users删除时只是状态改变未删除
@exercise_user_current = ex_users_current&.first
if ex_users_current.exists?
if @exercise_user_current.start_at.blank?
@exercise_user_current.update_attribute("start_at",Time.now)
end
@t_user_exercise_status = @exercise.get_exercise_status(current_user)
@user_left_time = nil
if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) ||
(ex_users_current.exists? && @exercise_user_current.commit_status == 1)
@user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑
else
@user_left_time = get_exercise_left_time(@exercise,current_user)
@user_exercise_status = 0 #可编辑
else
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建exercise_user表理论上老师是不能进入答题的
exercise_user_params = {
:user_id => @exercise_current_user_id,
:exercise_id => @exercise.id,
:start_at => Time.now
}
exercise_user_current = ExerciseUser.new(exercise_user_params)
exercise_user_current.save
end
end
@t_user_exercise_status = @exercise.get_exercise_status(current_user)
@exercise_questions = @exercise.exercise_questions
if @exercise.question_random
@exercise_questions = @exercise_questions.order("RAND()")
else
@exercise_questions = @exercise_questions.order("question_number ASC")
end
# 判断问题是否已回答还是未回答
@exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges,
:exercise_shixun_answers,
:exercise_answers,
:exercise_standard_answers)
@user_left_time = nil
if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) ||
(ex_users_current.exists? && @exercise_user_current.commit_status == 1)
@user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑
else
@user_left_time = get_exercise_left_time(@exercise,current_user)
@user_exercise_status = 0 #可编辑
end
if @t_user_exercise_status == Exercise::DEADLINE
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status)
@exercise_questions = @exercise.exercise_questions
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
if @exercise.question_random
@exercise_questions = @exercise_questions.order("RAND()")
else
@exercise_questions = @exercise_questions.order("question_number ASC")
end
# 判断问题是否已回答还是未回答
@exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges,
:exercise_shixun_answers,
:exercise_answers,
:exercise_standard_answers)
if @t_user_exercise_status == Exercise::DEADLINE
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -1084,14 +1099,23 @@ class ExercisesController < ApplicationController
@shixun_undo = 0
@ques_undo = 0
ex_answer_time = @exercise.time.to_i
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
if ex_answer_time > 0
exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
if exercise_end_time.present?
ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
@ex_end_time = ex_end_times + ex_answer_time.minutes
end
if ex_answer_time > 0 #有剩余时间的时候
user_left_time = get_exercise_left_time(@exercise,current_user)
@ex_end_time = Time.now + user_left_time.to_i.seconds
else
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
end
# @ex_end_time = @exercise.get_exercise_end_time(current_user.id)
# if ex_answer_time > 0
# left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到
# if left_answer_time < @ex_end_time
# exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
# if exercise_end_time.present?
# ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
# @ex_end_time = ex_end_times + ex_answer_time.minutes
# end
# end
# end
@exercise_questions.each do |q|
if q.question_type == Exercise::PRACTICAL #当为实训题时
user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id)
@ -1116,6 +1140,7 @@ class ExercisesController < ApplicationController
# 学生提交试卷
def commit_exercise
tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1
ActiveRecord::Base.transaction do
begin
can_commit_exercise = false
@ -1131,7 +1156,7 @@ class ExercisesController < ApplicationController
can_commit_exercise = true
end
if can_commit_exercise
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
objective_score = calculate_student_score(@exercise,current_user,Time.now)[:total_score]
subjective_score = @answer_committed_user.subjective_score
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = objective_score + total_score_subjective_score
@ -1195,7 +1220,6 @@ class ExercisesController < ApplicationController
#答题列表
def exercise_lists
ActiveRecord::Base.transaction do
begin
@current_user_id = current_user.id
exercise_ids = [@exercise.id]
@ -1269,81 +1293,80 @@ class ExercisesController < ApplicationController
if params[:review].present?
review_type = params[:review].first.to_i #已评则数据为1未评则数据为0,前端传过来的为数组
if review_type == 1
@exercise_users_list = teacher_reviews
else
@exercise_users_list = teacher_unreviews
end
@exercise_users_list = teacher_reviews
else
@exercise_users_list = teacher_unreviews
end
end
#答题状态的选择
if params[:commit_status].present?
choose_type = params[:commit_status]
@exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type)
end
#答题状态的选择
if params[:commit_status].present?
choose_type = params[:commit_status]
@exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type)
end
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end
#搜索
if params[:search].present?
@exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
#搜索
if params[:search].present?
@exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} #{order_type}")
else
@exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}")
end
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} #{order_type}")
else
@exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}")
end
@export_ex_users = @exercise_users_list
@export_ex_users = @exercise_users_list
@exercise_users_size = @exercise_users_list.size
@exercise_users_size = @exercise_users_list.size
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@exercise_users_list = @exercise_users_list.page(@page).per(@limit)
else
@exercise_users_list = []
@export_ex_users = @exercise_users_list
@exercise_users_size = 0
end
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@exercise_users_list = @exercise_users_list.page(@page).per(@limit)
else
@exercise_users_list = []
@export_ex_users = @exercise_users_list
@exercise_users_size = 0
end
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @exercise_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
set_export_cookies
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name_.strip}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns}
}
end
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @exercise_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
set_export_cookies
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name_.strip}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns}
}
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -1382,101 +1405,99 @@ class ExercisesController < ApplicationController
#学生的统计结果
def exercise_result
ActiveRecord::Base.transaction do
begin
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班
@course_all_members = @course.students #课堂的全部学生
@exercise_all_users = @exercise.exercise_users
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids)
@course_all_members_count = @exercise_all_users.size
else
@exercise_users_list = @exercise.all_exercise_users(current_user.id)
@course_all_members_count = @exercise_users_list.size
end
@exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户
@exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id
@exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数
@exercise_status = @exercise.get_exercise_status(current_user)
#提交率
if @course_all_members_count == 0
commit_percent = 0.00
min_score = 0.0
max_score = 0.0
average_score = 0.0
fail_counts = 0
pass_counts = 0
good_counts = 0
best_counts = 0
else
commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3)
exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?)
min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0
max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0
total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0
average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0
question_scores = @exercise.question_scores
fail_score = question_scores * 0.6.round(2)
pass_score = question_scores * 0.7.round(2)
good_score = question_scores * 0.9.round(2)
fail_counts = exercise_scores.count{|a| a < fail_score}
pass_counts = exercise_scores.count{|a| a < pass_score && a >= fail_score}
good_counts = exercise_scores.count{|a| a < good_score && a >= pass_score}
best_counts = exercise_scores.count{|a| a >= good_score && a <= question_scores}
end
@counts_array = {
:commit_percent => commit_percent,
:min_score => min_score.to_s,
:max_score => max_score.to_s,
:average_score => average_score.to_s,
:fail_counts => fail_counts,
:pass_counts => pass_counts,
:good_counts => good_counts,
:best_counts => best_counts,
}
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
begin
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班
@course_all_members = @course.students #课堂的全部学生
@exercise_all_users = @exercise.exercise_users
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids)
@course_all_members_count = @exercise_all_users.size
else
@exercise_users_list = @exercise.all_exercise_users(current_user.id)
@course_all_members_count = @exercise_users_list.size
end
@exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户
@exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id
@exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数
@exercise_status = @exercise.get_exercise_status(current_user)
#提交率
if @course_all_members_count == 0
commit_percent = 0.00
min_score = 0.0
max_score = 0.0
average_score = 0.0
fail_counts = 0
pass_counts = 0
good_counts = 0
best_counts = 0
else
commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3)
exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?)
min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0
max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0
total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0
average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0
question_scores = @exercise.question_scores
fail_score = question_scores * 0.6.round(2)
pass_score = question_scores * 0.7.round(2)
good_score = question_scores * 0.9.round(2)
fail_counts = exercise_scores.count{|a| a < fail_score}
pass_counts = exercise_scores.count{|a| a < pass_score && a >= fail_score}
good_counts = exercise_scores.count{|a| a < good_score && a >= pass_score}
best_counts = exercise_scores.count{|a| a >= good_score && a <= question_scores}
end
@counts_array = {
:commit_percent => commit_percent,
:min_score => min_score.to_s,
:max_score => max_score.to_s,
:average_score => average_score.to_s,
:fail_counts => fail_counts,
:pass_counts => pass_counts,
:good_counts => good_counts,
:best_counts => best_counts,
}
percent_sort = "desc"
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
if params[:sort].present?
percent_sort = params[:sort]
end
# @paging_type = "percent"
# # 按题型排序
# if params[:sort].present?
# @paging_type = params[:sort].to_s
# end
percent_sort = "desc"
ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids)
if params[:sort].present?
percent_sort = params[:sort]
end
# @paging_type = "percent"
# # 按题型排序
# if params[:sort].present?
# @paging_type = params[:sort].to_s
# end
#默认降序排列
if percent_sort == "desc"
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}.reverse
else
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}
end
ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids)
@exercise_questions_count = @exercise_questions.size
@page = params[:page] || 1
@limit = params[:limit] || 10
@question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
#默认降序排列
if percent_sort == "desc"
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}.reverse
else
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}
end
@exercise_questions_count = @exercise_questions.size
@page = params[:page] || 1
@limit = params[:limit] || 10
@question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
@ -1513,7 +1534,7 @@ class ExercisesController < ApplicationController
ex_group_settings = @exercise.exercise_group_settings
if ex_group_settings.present?
p_time_present = ex_group_settings.publish_time_no_null.map(&:publish_time).min
if p_time_present < Time.now
if p_time_present && p_time_present < Time.now
normal_status(-1,"设置失败,存在已发布的分班")
end
elsif params[:publish_time].blank?
@ -1607,12 +1628,14 @@ class ExercisesController < ApplicationController
ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班
unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级
else
ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq
ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班
unpublish_group = unpublish_group + ex_and_user
unpublish_group = unpublish_group + ex_and_user - ex_ended_groups
end
end
end
end
Rails.logger.info("#####____________unpublish_group_______#######{unpublish_group}")
unpublish_group = unpublish_group.uniq
if unpublish_group.count > 0
course_groups = CourseGroup.by_group_ids(unpublish_group)

@ -49,11 +49,12 @@ class GitsController < ApplicationController
shixunname = git_url.split("/")[1].split(".")[0]
repo_name = username + "/" + shixunname
uid_logger("git start: repo_name is #{repo_name}")
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name).first
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name, laboratory_id: nil).first
uid_logger("git start auth: shixun identifier is #{shixun.try(:identifier)}")
uid_logger("git start auth: systemuser is #{system_user.try(:login)}")
if shixun.present?
logger.info("#######{system_user.manager_of_shixun?(shixun)}")
if system_user.present? && system_user.manager_of_shixun?(shixun)
result = true
else
@ -72,7 +73,6 @@ class GitsController < ApplicationController
authenticate_or_request_with_http_basic do |username, password|
result
logger.info("1111111 git auth end: code is #{rand_code}, time is #{Time.now}")
end
end

@ -149,6 +149,7 @@ class GraduationTasksController < ApplicationController
else
respond_to do |format|
format.xlsx{
set_export_cookies
graduation_work_to_xlsx(@work_excel,@task,current_user)
task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{task_export_name_.strip}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column}

@ -379,8 +379,9 @@ class GraduationWorksController < ApplicationController
end
def adjust_score
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-100") if params[:score].to_f < 0 || params[:score].to_f > 100
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效

@ -11,27 +11,29 @@ class HomeController < ApplicationController
end
# 目录分级
repertoires = Repertoire.includes(sub_repertoires: :tag_repertoires).order("updated_at asc")
@rep_list = []
repertoires.each do |rep|
sub_rep_list = []
rep.sub_repertoires.each do |sub_rep|
tag_rep_list = []
sub_rep.tag_repertoires.each do |tag_rep|
tag_rep_list << {tag_id: tag_rep.id, tag_name: tag_rep.name}
end
sub_rep_list << {sub_rep_id: sub_rep.id, sub_rep_name: sub_rep.name, tag_rep_list: tag_rep_list}
end
@rep_list << {rep_id: rep.id, rep_name: rep.name, sub_rep_list: sub_rep_list}
@rep_list = current_laboratory.shixun_repertoires
shixuns = current_laboratory.shixuns
subjects = current_laboratory.subjects
if current_laboratory.main_site?
shixuns = shixuns.where(homepage_show: true)
subjects = subjects.where(homepage_show: true)
else
shixuns = shixuns.where(laboratory_shixuns: { homepage: true })
subjects = subjects.where(laboratory_subjects: { homepage: true })
end
@shixuns = Shixun.where(homepage_show: 1).includes(:tag_repertoires, :challenges).limit(8)
@shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8)
@subjects = subjects.includes(:repertoire, :shixuns).limit(8)
@subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8)
@main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8)
@main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8)
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
if current_laboratory.main_site?
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
end
end
def search

@ -160,7 +160,7 @@ class HomeworkCommonsController < ApplicationController
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
if params[:work_status].present?
params_work_status = request.get? ? params[:work_status].split(",") : params[:work_status]
params_work_status = params[:work_status]
work_status = params_work_status.map{|status| status.to_i}
all_student_works = @student_works.left_joins(:myshixun)
@student_works = all_student_works.where(work_status: work_status)
@ -171,7 +171,7 @@ class HomeworkCommonsController < ApplicationController
# 分班情况
unless params[:course_group].blank?
group_ids = request.get? ? params[:course_group].split(",") : params[:course_group]
group_ids = params[:course_group]
group_user_ids = @course.students.where(course_group_id: group_ids).pluck(:user_id)
# 有分组只可能是老师身份查看列表
@student_works = @student_works.where(user_id: group_user_ids)
@ -179,9 +179,9 @@ class HomeworkCommonsController < ApplicationController
if @homework.homework_type == "group" && !params[:member_work].blank?
if params[:member_work].to_i == 1
@student_works = @student_works.where("user_id = commit_user_id")
@student_works = @student_works.where("student_works.user_id = commit_user_id")
elsif params[:member_work].to_i == 0
@student_works = @student_works.where("user_id != commit_user_id")
@student_works = @student_works.where("student_works.user_id != commit_user_id")
end
end
@ -532,7 +532,7 @@ class HomeworkCommonsController < ApplicationController
# 如果该发布规则 没有已发布的分班则需判断发布时间
tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0
tip_exception("截止时间不能早于等于当前时间") if setting[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于等于当前时间") if setting[:end_time] <= strf_time(Time.now) && group_settings.none_end.count > 0
tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time]
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && setting[:end_time] > strf_time(@course.end_date.end_of_day)
@ -1512,7 +1512,7 @@ class HomeworkCommonsController < ApplicationController
end_time = game.end_time
# 用户关卡的得分
all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score).to_f
final_score = @student_work.work_challenge_score game, all_score
final_score = @student_work.work_challenge_score game, all_score, challenge.id
# 抄袭用户
copy_user = User.find_by_id(game_codes[0].try(:target_user_id))
copy_end_time = copy_user.games.find_by(challenge_id: challenge.id).try(:end_time) if copy_user.present?

@ -7,7 +7,7 @@ class LibrariesController < ApplicationController
helper_method :current_library, :library_manageable?
def index
libraries = Library.all
libraries = current_laboratory.libraries
libraries =
if User.current&.logged? && params[:type] == 'mine'

@ -20,7 +20,12 @@ class MessagesController < ApplicationController
sort = params[:sort].to_i == 1 ? 'asc' : 'desc'
sort_type = params[:sort_type] || 'time'
messages = @board.messages.root_nodes.by_keywords(params[:search])
if @board.parent_id == 0
messages = Message.where(board_id: @board.course.boards.pluck(:id))
else
messages = @board.messages
end
messages = messages.root_nodes.by_keywords(params[:search])
messages = messages.reorder('(sticky = 1) DESC') # 置顶
@ -31,7 +36,7 @@ class MessagesController < ApplicationController
else messages.order("created_on #{sort}")
end
messages = messages.includes(:author)
messages = messages.includes(:author, :board)
@messages = Kaminari.paginate_array(messages).page(@page).per(@page_size)
ids = @messages.map(&:id)
@ -103,14 +108,19 @@ class MessagesController < ApplicationController
return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin
h = {is_md: true}
board = @message.board&.course&.boards.find_by!(id: params[:select_board_id])
email_notify = @message.email_notify ? 1 : @message.board&.course.email_notify && params[:email_notify]
send_email = !@message.email_notify && email_notify
h = {is_md: true, email_notify: email_notify, board_id: board&.id}
m_params = message_params.merge(h)
@message.update_attributes(m_params)
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content])
notify_course_students(@message, @message.board&.course) if send_email
rescue Exception => e
uid_logger_error(e.message)
tip_exception("修改失败")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -123,8 +133,12 @@ class MessagesController < ApplicationController
@message.author = current_user
@message.board_id = params[:select_board_id]
@message.message_detail_attributes = {content: params[:content]}
@message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0
@message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
if @board.course.email_notify && params[:email_notify]
notify_course_students @message, @board.course
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -186,7 +200,7 @@ class MessagesController < ApplicationController
private
def validate_sort_type
normal_status(2, "参数sort_tyope暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def find_message
@ -201,4 +215,10 @@ class MessagesController < ApplicationController
def message_params
params.require(:message).permit(:subject, :sticky)
end
def notify_course_students message, course
course.students.includes(:user).each do |student|
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail
end
end
end

@ -1,9 +1,14 @@
class Oauth::BaseController < ActionController::Base
include RenderHelper
include LoginHelper
include ControllerRescueHandler
skip_before_action :verify_authenticity_token
def auth_failure
render_error(params[:message])
end
private
def session_user_id
@ -15,6 +20,7 @@ class Oauth::BaseController < ActionController::Base
end
def auth_hash
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
request.env['omniauth.auth']
end
end

@ -0,0 +1,137 @@
class PartnersController < ApplicationController
include Base::PaginateHelper
include Admins::RenderHelper
layout 'college'
before_action :require_login, :check_partner_present!, :check_permission!
before_action :check_admin_manager_group_permission!, except: [:customers]
helper_method :current_partner, :manager_permission?
def customers
customers = CustomerQuery.call(current_partner, current_user, params)
@customers = paginate(customers.includes(:school))
load_customer_extra_statistic_data
end
def partner_manager_groups
@manager_groups = current_partner.partner_manager_groups.includes(users: :user_extension).to_a
end
def manager_group
name = params[:manager_group_name].to_s.strip
if params[:manager_group_id].present?
# 重命名
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
return render_error('不能修改管理者权限组名称') if @manager_group.admin?
@manager_group.update!(name: name)
else
# 新建
@manager_group = current_partner.partner_manager_groups.create!(name: name)
end
end
def remove_manager_group
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
return render_error('不能删除管理者权限组') if manager_group.admin?
manager_group.destroy!
render_delete_success
end
def partner_managers
user_ids = Array.wrap(params[:user_ids])
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
ActiveRecord::Base.transaction do
User.where(id: user_ids).pluck(:id).each do |user_id|
next if current_partner.partner_managers.exists?(partner_manager_group: @manager_group, user_id: user_id)
current_partner.partner_managers.create!(partner_manager_group: @manager_group, user_id: user_id)
end
end
@manager_group.reload
end
def remove_partner_manager
partner_manager = current_partner.partner_managers.find(params[:manager_id])
return render_error('不能删除自己') if partner_manager.user_id == current_user.id && partner_manager.partner_manager_group.admin?
partner_manager.destroy!
render_delete_success
end
def customer_manager_group
customer = current_partner.customers.find(params[:customer_id])
if params[:manager_group_id].present?
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
customer.update!(partner_manager_group: manager_group)
else
customer.update!(partner_manager_group_id: nil)
end
render_ok
end
private
def current_partner
@_current_partner ||= Partner.find(params[:id].presence || params[:partner_id])
end
def check_partner_present!
return if current_partner.present?
redirect_to '/404'
end
def manager_permission?
admin_or_business? || current_user.partner_managers.exists?(partner_id: current_partner.id)
end
def check_permission!
return if manager_permission?
redirect_to '/403'
end
def check_admin_manager_group_permission!
return if admin_or_business?
return if current_partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
render_forbidden
end
def load_customer_extra_statistic_data
school_ids = @customers.map(&:school_id)
teacher_map = UserExtension.where(school_id: school_ids, identity: 0).group(:school_id).count
student_map = UserExtension.where(school_id: school_ids, identity: 1).group(:school_id).count
course_map = Course.where(school_id: school_ids, is_delete: 0).where.not(id: 1309).group(:school_id).count
shixun_map = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
.where(user_extensions: { school_id: school_ids }).group('user_extensions.school_id').count
shixun_report_map = StudentWork.where(work_status: [1, 2]).where('myshixun_id != 0')
.joins('left join user_extensions on user_extensions.user_id = student_works.user_id')
.where(user_extensions: { school_id: school_ids })
.group('user_extensions.school_id').count
course_time_map = Course.where(school_id: school_ids, is_delete: 0)
.where.not(id: 1309).group(:school_id).maximum(:updated_at)
@customers.each do |customer|
customer._extra_data = {
teacher_count: teacher_map[customer.school_id],
student_count: student_map[customer.school_id],
course_count: course_map[customer.school_id],
shixun_count: shixun_map[customer.school_id],
shixun_report_count: shixun_report_map[customer.school_id],
course_time: course_time_map[customer.school_id]
}
end
end
end

@ -17,4 +17,13 @@ class SchoolsController < ApplicationController
render_ok(schools: schools.select(:id, :name).as_json)
end
def search
schools = School.all
keyword = params[:keyword].to_s.strip
schools = schools.where('name LIKE ?', "%#{keyword}%") if keyword
schools = paginate(schools)
render_ok(schools: schools.as_json(only: %i[id name province]))
end
end

@ -1,6 +1,6 @@
class ShixunListsController < ApplicationController
def index
@results = ShixunSearchService.call(search_params)
@results = ShixunSearchService.call(search_params, current_laboratory)
end
private

@ -33,7 +33,15 @@ class ShixunsController < ApplicationController
current_user.my_shixuns
else
Shixun.unhidden
end
end
## 云上实验室过滤
unless current_laboratory.main_site?
@shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id })
else
not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{current_laboratory.id}")
@shixuns = @shixuns.where.not(id: not_shixun_ids)
end
## 方向
if params[:tag_level].present? && params[:tag_id].present?
@ -149,10 +157,7 @@ class ShixunsController < ApplicationController
## 获取顶部菜单
def menus
@repertoires = Repertoire.includes(sub_repertoires: [:tag_repertoires]).order("updated_at asc")
# respond_with @repertoires
render_json
@repertoires = current_laboratory.shixun_repertoires
end
## 实训详情
@ -335,6 +340,9 @@ class ShixunsController < ApplicationController
end
end
end
# 将实训标志为该云上实验室建立
Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true)
rescue Exception => e
uid_logger_error("copy shixun failed ##{e.message}")
# 删除版本库
@ -430,6 +438,9 @@ class ShixunsController < ApplicationController
GitService.add_repository(repo_path: repo_path)
# todo: 为什么保存的时候要去除后面的.git呢??
@shixun.update_column(:repo_name, repo_path.split(".")[0])
# 将实训标志为该云上实验室建立
Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("实训创建失败")
@ -905,6 +916,7 @@ class ShixunsController < ApplicationController
else
@users = User.none
end
@users = @users.where(laboratory_id: current_laboratory.id) unless current_laboratory.main_site?
page = params[:page] || 1
limit = params[:limit] || 20
@user_count = @users.count
@ -963,8 +975,14 @@ class ShixunsController < ApplicationController
end
@course_count = course_ids.length
@courses = Course.where(:id => course_ids).page(page).per(limit)
@courses = Course.where(:id => course_ids)
## 云上实验室过滤
unless current_laboratory.main_site?
@courses = @courses.where(laboratory_id: current_laboratory.id )
end
@course_count = @courses.count
@courses = @courses.page(page).per(limit)
end
# 将实训发送到课程

@ -464,6 +464,7 @@ class StudentWorksController < ApplicationController
@shixun = @homework.shixuns.take
# 提示: 这里如果includes outputs表的话 sum(:evaluate_count)会出现错误
@games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun
@challenges = @shixun.challenges if @shixun
@comment = @work.shixun_work_comments.find_by(challenge_id: 0)
# 用户最大评测次数
@ -475,7 +476,7 @@ class StudentWorksController < ApplicationController
end
# 图形效率图的数据
@echart_data = student_efficiency(@homework, @work)
@echart_data = student_efficiency(@homework, @work) if @work.myshixun
end
# 实训作品的评阅
@ -493,6 +494,9 @@ class StudentWorksController < ApplicationController
@comment.comment = params[:comment]
@comment.hidden_comment = params[:hidden_comment]
@comment.save!
if @work.work_status == 0
@work.update_attributes!(work_status: 1, commit_time: @homework.end_time, update_time: Time.now, work_score: 0, final_score: 0)
end
end
end
@ -517,6 +521,7 @@ class StudentWorksController < ApplicationController
@user = @work.user
@shixun = @homework.shixuns.take
@games = @work.myshixun.games.includes(:challenge, :game_codes, :outputs) if @work.myshixun
@challenges = @shixun.challenges if @shixun
# 用户最大评测次数
@user_evaluate_count = @games.pluck(:evaluate_count).sum if @games
@ -524,19 +529,23 @@ class StudentWorksController < ApplicationController
@echart_data = student_efficiency(@homework, @work)
@myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id }
@myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id }
filename_ = "#{@use&.student_id}_#{@use&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
filename = Base64.urlsafe_encode64(filename_.strip)
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# 作品调分
def adjust_score
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-100") if @homework.homework_type != "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > 100.round(1))
tip_exception("已提交的作品请去评阅页进行调分") if @homework.homework_type == "practice" && @work.work_status > 0
tip_exception("分数不能超过总分值#{@homework.total_score}") if @homework.homework_type == "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > @homework.total_score.round(1))
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效
@ -713,27 +722,35 @@ class StudentWorksController < ApplicationController
tip_exception("参数错误score和challenge_id不能为空")
end
challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id])
challenge = challenge_setting&.challenge
tip_exception("不能小于零") if params[:score].to_i < 0
tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting.score < params[:score].to_i
if challenge_setting
challenge = challenge_setting&.challenge
tip_exception("不能小于零") if params[:score].to_i < 0
tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting && challenge_setting.score < params[:score].to_i
ActiveRecord::Base.transaction do
begin
if params[:type] == "review"
copy_user = User.find params[:copy_user_id]
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%"
else
comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数"
ActiveRecord::Base.transaction do
begin
if params[:type] == "review"
copy_user = User.find params[:copy_user_id]
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%"
else
comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数"
end
challenge_score = @work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score],
comment: comment)
challenge_score.create_tiding current_user.id
if @work.work_status != 0 && @work.myshixun
HomeworksService.new.update_myshixun_work_score @work, @work.myshixun, @work.myshixun&.games, @homework, @homework.homework_challenge_settings
else
update_none_commit_work @work, @homework
end
rescue Exception => e
uid_logger(e.message)
tip_exception("调分失败")
raise ActiveRecord::Rollback
end
challenge_score = @work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score],
comment: comment)
challenge_score.create_tiding current_user.id
HomeworksService.new.update_myshixun_work_score @work, @work&.myshixun, @work&.myshixun&.games, @homework, @homework.homework_challenge_settings
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
else
tip_exception("该关卡不记分")
end
end
@ -856,4 +873,20 @@ class StudentWorksController < ApplicationController
end
end
end
def update_none_commit_work work, homework
if work.work_status == 0
work.work_status = 1
work.commit_time = homework.end_time
work.update_time = Time.now
end
final_score = 0
homework.homework_challenge_settings.each do |cha_setting|
adjust_score = work.challenge_work_scores.select{|work_score| work_score.challenge_id == cha_setting.challenge_id}.last
final_score += adjust_score.score if adjust_score.present?
end
work.final_score = final_score
work.work_score = final_score
work.save!
end
end

@ -1,6 +1,6 @@
class SubjectListsController < ApplicationController
def index
@results = SubjectSearchService.call(search_params)
@results = SubjectSearchService.call(search_params, current_laboratory)
end
private

@ -5,13 +5,14 @@ class SubjectsController < ApplicationController
before_action :find_subject, except: [:index, :create, :new, :append_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish,
:search_members, :add_subject_members, :statistics, :shixun_report, :school_report,
:up_member_position, :down_member_position]
:up_member_position, :down_member_position, :update_team_title]
before_action :require_admin, only: [:copy_subject]
include ApplicationHelper
include SubjectsHelper
def index
@tech_system = Repertoire.where(nil).order("updated_at desc")
@tech_system = current_laboratory.subject_repertoires
select = params[:select] # 路径导航类型
reorder = params[:order] || "publish_time"
search = params[:search]
@ -23,17 +24,27 @@ class SubjectsController < ApplicationController
# 最热排序
if reorder == "myshixun_count"
if current_laboratory.main_site?
not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}").pluck(:id)
not_subject_ids = not_subject_ids.length > 0 ? "(" + not_subject_ids.join(",") + ")" : "(-1)"
laboratory_join = " AND subjects.id not in #{not_subject_ids} "
else
subject_ids = Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id }).pluck(:id)
subject_ids = subject_ids.length > 0 ? "(" + subject_ids.join(",") + ")" : "(-1)"
laboratory_join = " AND subjects.id in #{subject_ids} "
end
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
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
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
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
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
else
@ -52,6 +63,14 @@ class SubjectsController < ApplicationController
@subjects = Subject.visible.unhidden
end
# 云上实验室过滤
unless current_laboratory.main_site?
@subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id })
else
not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}")
@subjects = @subjects.where.not(id: not_subject_ids)
end
# 类型
if select
@subjects = @subjects.where(repertoire_id: select)
@ -117,6 +136,9 @@ class SubjectsController < ApplicationController
@subject.user_id = current_user.id
@subject.save!
@subject.subject_members.create!(role: 1, user_id: current_user.id)
# 将实践课程标记为该云上实验室建立
Laboratory.current.laboratory_subjects.create!(subject: @subject, ownership: true)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("实训路径创建失败")
@ -195,6 +217,10 @@ class SubjectsController < ApplicationController
WHERE m.course_id = c.id AND m.role in (1,2,3)
AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
@courses = Course.where(id: course_ids)
## 云上实验室过滤
unless current_laboratory.main_site?
@courses = @courses.where(laboratory_id: current_laboratory.id )
end
@none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id)
end
@ -264,12 +290,19 @@ class SubjectsController < ApplicationController
end
end
def update_team_title
tip_exception("team_title参数不能为空") if params[:team_title].blank?
@subject.update_attributes!(team_title: params[:team_title])
normal_status("更新成功")
end
def search_members
tip_exception("搜索内容不能为空") unless params[:search]
page = params[:page] || 1
member_ids = @subject.subject_members.map(&:user_id).join(',')
condition = "%#{params[:search].strip}%".gsub(" ","")
@users = User.where("id not in (?) and status = 1 and LOWER(concat(lastname, ifnull(firstname, ''), login)) LIKE ?", member_ids, "#{condition}")
@users = @users.where(laboratory_id: current_laboratory.id) unless current_laboratory.main_site?
@users = @users.page(page).per(10)
@users = @users.includes(:user_extension)
@ -429,6 +462,13 @@ class SubjectsController < ApplicationController
end
end
# 复制实践课程
def copy
end
private
def subject_params
tip_exception("实训路径名称不能为空") if params[:name].blank?
@ -479,4 +519,6 @@ class SubjectsController < ApplicationController
end
end

@ -1,22 +1,28 @@
class TrustieHacksController < ApplicationController
before_action :require_admin, :except => [:index]
before_action :require_admin, :except => [:index, :entry]
before_action :require_login, :except => [:index]
before_action :find_hackathon
before_action :find_hack, :except => [:create, :index]
before_action :find_hack, :except => [:create, :index, :edit_hackathon, :update_hackathon]
def index
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 16
search = params[:search]
hacks = @hackathon.trustie_hacks
@hackathon_users_count = hacks.sum(:hack_users_count)
if search
hacks = hacks.where("name like ?", "%#{search}%")
end
@hackathon_users_count = hacks.blank? ? 0 : hacks.sum(:hack_users_count)
@hacks_count = hacks.count
@hacks = hacks.page(page).per(limit)
end
def edit ;end
def edit;end
def create
@hackathon.trustie_hacks.create!(name: params[:name], description: params[:description])
@ -25,12 +31,30 @@ class TrustieHacksController < ApplicationController
def update
@hack.update_attributes(name: params[:name], description: params[:description])
render_ok
end
def edit_hackathon ;end
def destroy
@hack.destroy
render_ok
end
def edit_hackathon
end
def update_hackathon
@hackathon.update_attributes(name: params[:name], description: params[:description])
render_ok
end
# 报名入口
def entry
if @hack.hack_users.exists?(user_id: current_user.id)
render_error('已经报名,请勿重复操作')
else
@hack.hack_users.create(user_id: current_user.id)
render_ok
end
end
@ -38,7 +62,7 @@ class TrustieHacksController < ApplicationController
def find_hackathon
@hackathon = TrustieHackathon.first ||
TrustieHackathon.create(name: params[:name], description: params[:description])
TrustieHackathon.create!(name: params[:name], description: params[:description])
end
def find_hack

@ -17,6 +17,6 @@ class Users::AuthenticationAppliesController < Users::BaseAccountController
private
def create_params
params.permit(:name, :gender, :id_number, :upload_image)
params.permit(:name, :show_realname, :gender, :id_number, :upload_image, attachment_ids: [])
end
end

@ -2,6 +2,8 @@ class Users::CoursesController < Users::BaseController
def index
courses = Users::CourseService.new(observed_user, query_params).call
courses = courses.where(laboratory_id: current_laboratory.id)
@count = courses.count
@courses = paginate(courses.includes(teacher: { user_extension: :school }), special: observed_user.is_teacher?)
end

@ -17,6 +17,6 @@ class Users::ProfessionalAuthAppliesController < Users::BaseAccountController
private
def create_params
params.permit(:school_id, :department_id, :identity, :extra, :upload_image)
params.permit(:school_id, :department_id, :identity, :extra, :upload_image, attachment_ids: [])
end
end

@ -3,6 +3,7 @@ class Users::RecentContactsController < Users::BaseController
def index
contacts = observed_user.recent_contacts.distinct
contacts = contacts.where(laboratory_id: current_laboratory.id) unless current_laboratory.main_site?
@contacts = contacts.order('private_messages.created_at DESC').limit(10).includes(:user_extension)
end
end

@ -2,6 +2,14 @@ class Users::ShixunsController < Users::BaseController
def index
shixuns = Users::ShixunService.new(observed_user, query_params).call
## 云上实验室过滤
if current_laboratory.main_site?
not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{current_laboratory.id}")
shixuns = shixuns.where.not(id: not_shixun_ids)
else
shixuns = shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id })
end
@count = shixuns.count
@shixuns = paginate(shixuns.includes(:first_tag_repertoire), special: observed_user.is_teacher?)

@ -2,6 +2,14 @@ class Users::SubjectsController < Users::BaseController
def index
subjects = Users::SubjectService.new(observed_user, query_params).call
## 云上实验室过滤
if current_laboratory.main_site?
not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}")
subjects = subjects.where.not(id: not_subject_ids)
else
subjects = subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id })
end
@count = subjects.count
@subjects = paginate(subjects.includes(:user, :repertoire), special: observed_user.is_teacher?)
end

@ -0,0 +1,27 @@
class UsersForPartnersController < ApplicationController
include Base::PaginateHelper
before_action :check_partner_manager_permission!
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
users = Admins::UserQuery.call(search_params)
@users = paginate users.includes(user_extension: :school)
end
private
def search_params
params.permit(:name, :sort_by, :sort_direction)
end
def check_partner_manager_permission!
partner = Partner.find(params[:partner_id])
return if admin_or_business?
return if partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
render_forbidden
end
end

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

Loading…
Cancel
Save