diff --git a/.gitignore b/.gitignore
index 6a4516d20..3c9f5950e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
# Ignore bundler config.
/.bundle
+/bundle
# Ignore lock config file
*.lock
@@ -71,3 +72,13 @@ vendor/bundle/
/workspace
/log
/public/admin
+/mysql_data
+
+
+.generators
+.rakeTasks
+db/bak/
+docker/
+educoder.sql
+redis_data/
+Dockerfile
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
index b4a30658d..6757a157f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -108,3 +108,6 @@ gem 'diffy'
# oauth2
gem 'omniauth', '~> 1.9.0'
gem 'omniauth-oauth2', '~> 1.6.0'
+
+# global var
+gem 'request_store'
diff --git a/app/assets/javascripts/admins/courses/index.js b/app/assets/javascripts/admins/courses/index.js
index 336d8c7c9..0e3473dff 100644
--- a/app/assets/javascripts/admins/courses/index.js
+++ b/app/assets/javascripts/admins/courses/index.js
@@ -26,6 +26,15 @@ $(document).on('turbolinks:load', function() {
});
});
+ // 清空
+ searchForm.on('click', '.clear-btn', function () {
+ searchForm.find('select[name="status"]').val('');
+ searchForm.find('.school-select').val('').trigger('change');
+ searchForm.find('input[name="keyword"]').val('');
+ searchForm.find('#homepage_show').attr('checked', false);
+ searchForm.find('input[type="submit"]').trigger('click');
+ });
+
// ************** 学校选择 *************
searchForm.find('.school-select').select2({
theme: 'bootstrap4',
diff --git a/app/assets/javascripts/admins/projects/index.js b/app/assets/javascripts/admins/projects/index.js
new file mode 100644
index 000000000..534a065ca
--- /dev/null
+++ b/app/assets/javascripts/admins/projects/index.js
@@ -0,0 +1,11 @@
+$(document).on('turbolinks:load', function () {
+ if ($('body.admins-projects-index-page').length > 0) {
+ var $form = $('.search-form');
+
+ // 清空
+ $form.on('click', '.clear-btn', function () {
+ $form.find('input[name="search"]').val('');
+ $form.find('input[type="submit"]').trigger('click');
+ });
+ }
+});
diff --git a/app/assets/javascripts/admins/shixun_feedback_messages/index.js b/app/assets/javascripts/admins/shixun_feedback_messages/index.js
index c0b32ba32..c25a6b744 100644
--- a/app/assets/javascripts/admins/shixun_feedback_messages/index.js
+++ b/app/assets/javascripts/admins/shixun_feedback_messages/index.js
@@ -1,12 +1,14 @@
$(document).on('turbolinks:load', function(){
if ($('body.admins-shixun-feedback-messages-index-page').length > 0) {
+ $(".content-img img").addClass("w-20").addClass("preview-image");
+
var baseOptions = {
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd 00:00:00',
startDate: '2017-04-01'
- }
+ };
var defineDateRangeSelect = function(element){
var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, baseOptions);
@@ -14,9 +16,9 @@ $(document).on('turbolinks:load', function(){
$(element).find('.start-date').datepicker().on('changeDate', function(e){
$(element).find('.end-date').datepicker('setStartDate', e.date);
- })
+ });
};
defineDateRangeSelect('.grow-date-input-daterange');
}
-})
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/admins/shixun_modify_records/index.js b/app/assets/javascripts/admins/shixun_modify_records/index.js
new file mode 100644
index 000000000..13b348b04
--- /dev/null
+++ b/app/assets/javascripts/admins/shixun_modify_records/index.js
@@ -0,0 +1,12 @@
+$(document).on('turbolinks:load', function () {
+ if ($('body.admins-shixun-modify-records-index-page').length > 0) {
+ var $form = $('.search-form');
+
+ // 清空
+ $form.on('click', '.clear-btn', function () {
+ $form.find('select[name="date"]').val('weekly');
+ $form.find('input[name="user_name"]').val('');
+ $form.find('input[type="submit"]').trigger('click');
+ });
+ }
+});
diff --git a/app/assets/stylesheets/admins/diff.scss b/app/assets/stylesheets/admins/diff.scss
new file mode 100644
index 000000000..34944ae4c
--- /dev/null
+++ b/app/assets/stylesheets/admins/diff.scss
@@ -0,0 +1,14 @@
+.diff{overflow:auto;}
+.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0 1rem;display:table;width:100%;}
+.diff del, .diff ins{display:block;text-decoration:none;}
+.diff li{padding:0; display:table-row;margin: 0;height:1em;}
+.diff li.ins{background:#dfd; color:#080}
+.diff li.del{background:#fee; color:#b00}
+.diff li:hover{background:#ffc}
+
+/* try 'whitespace:pre;' if you don't want lines to wrap */
+.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
+.diff del strong{font-weight:normal;background:#fcc;}
+.diff ins strong{font-weight:normal;background:#9f9;}
+.diff li.diff-comment { display: none; }
+.diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
\ No newline at end of file
diff --git a/app/assets/stylesheets/admins/shixun_feedback_messages.scss b/app/assets/stylesheets/admins/shixun_feedback_messages.scss
new file mode 100644
index 000000000..92b92c01c
--- /dev/null
+++ b/app/assets/stylesheets/admins/shixun_feedback_messages.scss
@@ -0,0 +1,7 @@
+.admins-shixun-feedback-messages-index-page {
+ .content-img {
+ img {
+ height: 60px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/constraint/admin_constraint.rb b/app/constraint/admin_constraint.rb
index 3ddf9a11e..2cf5649a7 100644
--- a/app/constraint/admin_constraint.rb
+++ b/app/constraint/admin_constraint.rb
@@ -1,7 +1,8 @@
class AdminConstraint
def matches?(request)
- return false unless request.session[:user_id]
- user = User.find request.session[:user_id]
+ laboratory = Laboratory.first
+ return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
+ user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user && user.admin?
end
end
\ No newline at end of file
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index eab3c34a3..4525b0deb 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -69,6 +69,8 @@ class AccountsController < ApplicationController
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
end
+ return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
+
code = generate_identifier User, 8, pre
login = pre + code
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User")
@@ -145,6 +147,7 @@ class AccountsController < ApplicationController
end
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
+ return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
ActiveRecord::Base.transaction do
@@ -154,7 +157,7 @@ class AccountsController < ApplicationController
sucess_status
rescue Exception => e
uid_logger_error(e.message)
- tip_exception("密码重置失败")
+ tip_exception(e.message)
end
end
diff --git a/app/controllers/admins/daily_school_statistics_controller.rb b/app/controllers/admins/daily_school_statistics_controller.rb
index eb9c75fbc..f0911f239 100644
--- a/app/controllers/admins/daily_school_statistics_controller.rb
+++ b/app/controllers/admins/daily_school_statistics_controller.rb
@@ -6,6 +6,7 @@ class Admins::DailySchoolStatisticsController < Admins::BaseController
total_count, statistics = Admins::SchoolDailyStatisticService.call(params)
@statistics = paginate statistics, total_count: total_count
+ @params_page = params[:page] || 1
respond_to do |format|
format.html { load_statistic_total }
diff --git a/app/controllers/admins/myshixuns_controller.rb b/app/controllers/admins/myshixuns_controller.rb
index f70a64554..adc34e95e 100644
--- a/app/controllers/admins/myshixuns_controller.rb
+++ b/app/controllers/admins/myshixuns_controller.rb
@@ -6,6 +6,7 @@ class Admins::MyshixunsController < Admins::BaseController
myshixuns = Admins::MyshixunQuery.call(params)
@myshixuns = paginate myshixuns.includes(:last_executable_task, :last_task, shixun: :user, user: { user_extension: :school })
+ @params_page = params[:page] || 1
myshixun_ids = @myshixuns.map(&:id)
@finish_game_count = Game.where(myshixun_id: myshixun_ids, status: 2).group(:myshixun_id).count
diff --git a/app/controllers/admins/school_statistics_controller.rb b/app/controllers/admins/school_statistics_controller.rb
index fdd10c70f..5133cc997 100644
--- a/app/controllers/admins/school_statistics_controller.rb
+++ b/app/controllers/admins/school_statistics_controller.rb
@@ -10,6 +10,7 @@ class Admins::SchoolStatisticsController < Admins::BaseController
@grow_summary = service.grow_summary
total_count, statistics = service.call
+ @params_page = params[:page] || 1
@statistics = paginate statistics, total_count: total_count
end
diff --git a/app/controllers/admins/schools_controller.rb b/app/controllers/admins/schools_controller.rb
index 7e1626d98..8c4f1d59e 100644
--- a/app/controllers/admins/schools_controller.rb
+++ b/app/controllers/admins/schools_controller.rb
@@ -5,7 +5,7 @@ class Admins::SchoolsController < Admins::BaseController
schools = Admins::SchoolQuery.call(params)
- @schools = paginate schools.includes(:user_extensions)
+ @schools = paginate schools
school_ids = @schools.map(&:id)
@department_count = Department.where(school_id: school_ids).group(:school_id).count
diff --git a/app/controllers/admins/shixun_modify_records_controller.rb b/app/controllers/admins/shixun_modify_records_controller.rb
new file mode 100644
index 000000000..43d9a4a16
--- /dev/null
+++ b/app/controllers/admins/shixun_modify_records_controller.rb
@@ -0,0 +1,9 @@
+class Admins::ShixunModifyRecordsController < Admins::BaseController
+
+ def index
+ records = Admins::ShixunModifyRecordQuery.call(params)
+
+ @records = paginate records.includes(:diff_record_content)
+ end
+
+end
diff --git a/app/controllers/admins/shixun_settings_controller.rb b/app/controllers/admins/shixun_settings_controller.rb
index bd54018cd..6dbbc077a 100644
--- a/app/controllers/admins/shixun_settings_controller.rb
+++ b/app/controllers/admins/shixun_settings_controller.rb
@@ -15,7 +15,8 @@ class Admins::ShixunSettingsController < Admins::BaseController
hidden: params[:hidden].present? ? params[:hidden] : false,
homepage_show: params[:homepage_show].present? ? params[:homepage_show] : false,
task_pass: params[:task_pass].present? ? params[:task_pass] : false,
- code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false
+ code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false,
+ vip: params[:vip].present? ? params[:vip] : false
}
@shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
@@ -126,6 +127,6 @@ class Admins::ShixunSettingsController < Admins::BaseController
end
def setting_params
- params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:page_no, :id,tag_repertoires:[])
+ params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:vip,:page_no,:id,tag_repertoires:[])
end
end
diff --git a/app/controllers/admins/shixuns_controller.rb b/app/controllers/admins/shixuns_controller.rb
index e2d2830ad..6593f27c2 100644
--- a/app/controllers/admins/shixuns_controller.rb
+++ b/app/controllers/admins/shixuns_controller.rb
@@ -8,6 +8,9 @@ class Admins::ShixunsController < Admins::BaseController
@pending_shixuns = shixuns.where(status:1).size
@processed_shixuns = shixuns.where(status:2).size
@closed_shixuns = shixuns.where(status:3).size
+ @none_public_shixuns = shixuns.where(public:0).size
+ @pending_public_shixuns = shixuns.where(public:1).size
+ @processed_pubic_shixuns = shixuns.where(public:2).size
@shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
@params_page = params[:page] || 1
@shixuns = paginate shixuns.preload(:user,:challenges)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b00778958..5eb272a62 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -283,7 +283,7 @@ class ApplicationController < ActionController::Base
# 测试版前端需求
logger.info("subdomain:#{request.subdomain}")
- if request.subdomain == "test-newweb"
+ if request.subdomain != "www"
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 81403
elsif params[:debug] == 'student'
@@ -303,7 +303,7 @@ class ApplicationController < ActionController::Base
current_domain_session = session[:"#{default_yun_session}"]
if current_domain_session
# existing session
- (User.active.find(current_domain_session) rescue nil)
+ User.current = (User.active.find(current_domain_session) rescue nil)
elsif autologin_user = try_to_autologin
autologin_user
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
@@ -465,9 +465,9 @@ class ApplicationController < ActionController::Base
# 实训主类别列表,自带描述
def shixun_main_type
list = []
- mirrors = MirrorRepository.select([:id, :type_name, :description]).published_main_mirror
+ mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_main_mirror
mirrors.try(:each) do |mirror|
- list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description)}
+ list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description), mirror_name: mirror.name}
end
list
end
@@ -475,9 +475,9 @@ class ApplicationController < ActionController::Base
# 小类别列表
def shixun_small_type
list = []
- mirrors = MirrorRepository.select([:id, :type_name, :description]).published_small_mirror
+ mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_small_mirror
mirrors.try(:each) do |mirror|
- list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description}
+ list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description, mirror_name: mirror.name}
end
list
end
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 0c9c49621..5fc81c5d5 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -18,9 +18,9 @@ class AttachmentsController < ApplicationController
pdf_attachment = params[:disposition] || "attachment"
if pdf_attachment == "inline"
- send_file absolute_path(local_path(@file)),filename: @file.filename, disposition: 'inline',type: 'application/pdf'
+ send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
else
- send_file(absolute_path(local_path(@file)), filename: @file.filename,stream:false, type: @file.content_type.presence || 'application/octet-stream')
+ send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
end
update_downloads(@file)
end
@@ -28,52 +28,56 @@ class AttachmentsController < ApplicationController
def create
# 1. 本地存储
# 2. 上传到云
- upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
- uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
- raise "未上传文件" unless upload_file
-
- folder = edu_setting('attachment_folder')
- raise "存储目录未定义" unless folder.present?
-
- month_folder = current_month_folder
- save_path = File.join(folder, month_folder)
-
- ext = file_ext(upload_file.original_filename)
-
- local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
-
- content_type = upload_file.content_type.presence || 'application/octet-stream'
-
- # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
- remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
-
- logger.info "local_path: #{local_path}"
- logger.info "remote_path: #{remote_path}"
-
-
- disk_filename = local_path[save_path.size + 1, local_path.size]
- #存数据库
- #
- @attachment = Attachment.where(disk_filename: disk_filename,
- author_id: current_user.id,
- cloud_url: remote_path).first
+ begin
+ upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
+ uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
+ raise "未上传文件" unless upload_file
+
+ folder = edu_setting('attachment_folder')
+ raise "存储目录未定义" unless folder.present?
+
+ month_folder = current_month_folder
+ save_path = File.join(folder, month_folder)
+
+ ext = file_ext(upload_file.original_filename)
+
+ local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
+
+ content_type = upload_file.content_type.presence || 'application/octet-stream'
+
+ # remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
+ remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
+
+ logger.info "local_path: #{local_path}"
+ logger.info "remote_path: #{remote_path}"
+
+
+ disk_filename = local_path[save_path.size + 1, local_path.size]
+ #存数据库
+ #
+ @attachment = Attachment.where(disk_filename: disk_filename,
+ author_id: current_user.id,
+ cloud_url: remote_path).first
+ if @attachment.blank?
+ @attachment = Attachment.new
+ @attachment.filename = upload_file.original_filename
+ @attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
+ @attachment.filesize = upload_file.tempfile.size
+ @attachment.content_type = content_type
+ @attachment.digest = digest
+ @attachment.author_id = current_user.id
+ @attachment.disk_directory = month_folder
+ @attachment.cloud_url = remote_path
+ @attachment.save!
+ else
+ logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
+ end
- if @attachment.blank?
- @attachment = Attachment.new
- @attachment.filename = upload_file.original_filename
- @attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
- @attachment.filesize = upload_file.tempfile.size
- @attachment.content_type = content_type
- @attachment.digest = digest
- @attachment.author_id = current_user.id
- @attachment.disk_directory = month_folder
- @attachment.cloud_url = remote_path
- @attachment.save!
- else
- logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
+ render_json
+ rescue => e
+ uid_logger_error(e.message)
+ tip_exception(e.message)
end
-
- render_json
end
def destroy
@@ -196,4 +200,5 @@ class AttachmentsController < ApplicationController
end
end
end
+
end
diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb
index 0b5140743..354d63f6d 100644
--- a/app/controllers/challenges_controller.rb
+++ b/app/controllers/challenges_controller.rb
@@ -13,6 +13,9 @@ class ChallengesController < ApplicationController
include ShixunsHelper
include ChallengesHelper
+
+
+
# 新建实践题
def new
@position = @shixun.challenges.count + 1
@@ -160,6 +163,8 @@ class ChallengesController < ApplicationController
@shixun.increment!(:visits)
end
+
+
def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = @shixun.challenges_count
@@ -173,64 +178,70 @@ class ChallengesController < ApplicationController
# tab 0:过关任务的更新; 1:评测设置的更新; 2:表示参考答案的更新;
def update
- ActiveRecord::Base.transaction do
- tab = params[:tab].to_i
- @challenge.update_attributes(challenge_params)
- if tab == 0 && @challenge.st == 0
- @challenge.challenge_tags.delete_all
- if params[:challenge_tag].present?
- params[:challenge_tag].each do |input|
- ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
+ begin
+ ActiveRecord::Base.transaction do
+ tab = params[:tab].to_i
+ @challenge.update_attributes(challenge_params)
+ if tab == 0 && @challenge.st == 0
+ @challenge.challenge_tags.delete_all
+ if params[:challenge_tag].present?
+ params[:challenge_tag].each do |input|
+ ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
+ end
end
- end
- elsif tab == 1
- path = @challenge.path
- exec_path = @challenge.exec_path
- test_set = @challenge.test_sets
- sets_output = test_set.map(&:output)
- sets_input = test_set.map(&:input)
- sets_open = test_set.map(&:is_public)
- set_score = test_set.map(&:score)
- set_match_rule = test_set.map(&:match_rule)
- params_hidden = params[:test_set].map{|set| set[:hidden].to_i == 0}
- params_output = params[:test_set].map{|set| set[:output] }
- params_input = params[:test_set].map{|set| set[:input] }
- params_score = params[:test_set].map{|set| set[:score]}
- params_test_set = params[:test_set].map{|set| set[:match_rule]}
- # 测试集变化则需要更新(输入、 输出、 是否隐藏)
- if sets_output != params_output || sets_open != params_hidden || sets_input != params_input ||
- set_score != params_score || params_test_set != set_match_rule
- test_set.delete_all unless test_set.blank?
- params[:test_set].each_with_index do |set, index|
- # last: 末尾匹配, full: 全完匹配
- logger.info("set: #{set}; match_rule : #{set[:match_rule]}")
- match_rule = set[:match_rule] == 'last' ? 'last' : 'full'
- TestSet.create(:challenge_id => @challenge.id,
- :input => "#{set[:input]}",
- :output => "#{set[:output]}",
- :is_public => params_hidden[index],
- :score => set[:score],
- :match_rule => "#{match_rule}",
- :position => (index + 1))
+ elsif tab == 1
+ path = @challenge.path
+ exec_path = @challenge.exec_path
+ test_set = @challenge.test_sets
+ sets_output = test_set.map(&:output)
+ sets_input = test_set.map(&:input)
+ sets_open = test_set.map(&:is_public)
+ set_score = test_set.map(&:score)
+ set_match_rule = test_set.map(&:match_rule)
+ params_hidden = params[:test_set].map{|set| set[:hidden].to_i == 0}
+ params_output = params[:test_set].map{|set| set[:output] }
+ params_input = params[:test_set].map{|set| set[:input] }
+ params_score = params[:test_set].map{|set| set[:score]}
+ params_test_set = params[:test_set].map{|set| set[:match_rule]}
+ # 测试集变化则需要更新(输入、 输出、 是否隐藏)
+ if sets_output != params_output || sets_open != params_hidden || sets_input != params_input ||
+ set_score != params_score || params_test_set != set_match_rule
+ test_set.delete_all unless test_set.blank?
+ params[:test_set].each_with_index do |set, index|
+ # last: 末尾匹配, full: 全完匹配
+ logger.info("set: #{set}; match_rule : #{set[:match_rule]}")
+ match_rule = set[:match_rule] == 'last' ? 'last' : 'full'
+ TestSet.create(:challenge_id => @challenge.id,
+ :input => "#{set[:input]}",
+ :output => "#{set[:output]}",
+ :is_public => params_hidden[index],
+ :score => set[:score],
+ :match_rule => "#{match_rule}",
+ :position => (index + 1))
+ end
+ @challenge.update_column(:modify_time, Time.now)
+ # 测试集的
+ @shixun.myshixuns.update_all(:system_tip => 0)
end
- @challenge.update_column(:modify_time, Time.now)
- # 测试集的
- @shixun.myshixuns.update_all(:system_tip => 0)
- end
- if params[:challenge][:show_type].to_i == -1
- @challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil)
+ if params[:challenge][:show_type].to_i == -1
+ @challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil)
+ end
+ # 关卡评测执行文件如果被修改,需要修改脚本内容
+ script = modify_shixun_script @shixun, @shixun.evaluate_script
+ @shixun.shixun_info.update_column(:evaluate_script, script)
+ # TODO:
+ # if path != params[:challenge][:path]
+ # shixun_modify_status_without_publish(@shixun, 1)
+ # end
+ #Attachment.attach_files(@challenge, params[:attachments])
end
- # 关卡评测执行文件如果被修改,需要修改脚本内容
- script = modify_shixun_script @shixun, @shixun.evaluate_script
- @shixun.shixun_info.update_column(:evaluate_script, script)
- # TODO:
- # if path != params[:challenge][:path]
- # shixun_modify_status_without_publish(@shixun, 1)
- # end
- #Attachment.attach_files(@challenge, params[:attachments])
- end
+ end
+ rescue => e
+ logger_error("##update_challenges: ##{e.message}")
+ tip_exception("更新失败!")
end
+
end
# 参考答案的'增,删,改'
diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb
new file mode 100644
index 000000000..707255866
--- /dev/null
+++ b/app/controllers/colleges_controller.rb
@@ -0,0 +1,175 @@
+class CollegesController < ApplicationController
+ include PaginateHelper
+
+ # layout 'college'
+
+ before_action :require_login
+ before_action :check_college_present!
+ before_action :check_manage_permission!
+
+ helper_method :current_school, :current_college
+
+ def statistics
+ # 教师、学生总数
+ count_statistic = UserExtension.where(school_id: current_school.id)
+ .select('SUM(IF(identity=0, 1, 0)) AS teachers_count, SUM(IF(identity=1, 1, 0)) AS students_count').first
+ @teachers_count = count_statistic['teachers_count']
+ @students_count = count_statistic['students_count']
+
+ # 课堂总数
+ @courses_count = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309).count
+ # 实训总数
+ @shixuns_count = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
+ .where(user_extensions: { school_id: current_school.id }).count
+ render json: { teachers_count: @teachers_count, students_count: @students_count, courses_count: @courses_count, shixuns_count: @shixuns_count, school: current_school.name }
+ end
+
+ def shixun_time
+ time_sum = Game.joins('left join user_extensions on user_extensions.user_id = games.user_id')
+ .where(user_extensions: { school_id: current_school.id }).sum(:cost_time)
+ shixun_time_sum = (time_sum / (24 * 60 * 60.0)).ceil
+
+ render json: { shixun_time: shixun_time_sum }
+ end
+
+ def shixun_report_count
+ shixun_report_count = 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: current_school.id }).count
+ render json: { shixun_report_count: shixun_report_count }
+ end
+
+ def teachers
+ @teachers = User.find_by_sql("SELECT users.id, users.login, users.lastname, users.firstname, users.nickname, IFNULL((SELECT count(shixuns.id) FROM shixuns where shixuns.user_id =users.id group by shixuns.user_id), 0) AS publish_shixun_count,
+ (SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.user_id=users.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND c.is_delete = 0) as course_count
+ FROM `users`, user_extensions ue where ue.school_id=#{current_school.id} and users.id=ue.user_id and ue.identity=0 ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10")
+ # ).order("publish_shixun_count desc, experience desc").limit(10)
+ # @teacher_count = UserExtension.where(school_id: current_school.id)
+ # .select('SUM(IF(identity=0, 1, 0)) AS teachers_count').first.teachers_count
+ @teachers =
+ @teachers.map do |teacher|
+ course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{teacher.id} AND c.is_delete = 0 and c.school_id = #{current_school.id}")
+ course_count = course_ids.size
+ homeworks = HomeworkCommon.where(:homework_type => 4, :course_id => course_ids.map(&:id))
+ un_shixun_work_count = homeworks.where("publish_time > '#{Time.now}' or publish_time is null").count
+ shixun_work_count = homeworks.size - un_shixun_work_count
+ student_count = StudentsForCourse.where(:course_id => course_ids.map(&:id)).count
+ myshixun_ids = StudentWork.select("myshixun_id").where("homework_common_id in (#{homeworks.map(&:id).join(',').strip == "" ? -1 : homeworks.map(&:id).join(',')}) and myshixun_id is not null")
+ complete_myshixun = Myshixun.select("id").where(:status => 1, :id => myshixun_ids.map(&:myshixun_id)).size
+ all_myshixun = Myshixun.select("id").where(:id => myshixun_ids.map(&:myshixun_id)).size
+ complete_rate = all_myshixun == 0 ? 0 : ((complete_myshixun * 100) / all_myshixun).try(:round, 2).to_f
+ real_name = teacher.show_real_name
+ teacher = teacher.attributes.dup.merge({
+ real_name: real_name,
+ course_count: course_count,
+ shixun_work_count: shixun_work_count,
+ un_shixun_work_count: un_shixun_work_count,
+ student_count: student_count,
+ complete_rate: complete_rate
+ }).to_json
+ JSON.parse(teacher)
+ end
+ end
+
+ def shixun_chart_data
+ shixun_ids = HomeworkCommonsShixun.joins(homework_common: :course).where(courses: {school_id: current_school.id, is_delete: 0}).where('courses.id != 1309').pluck('distinct shixun_id')
+ shixun_count_map = ShixunTagRepertoire.joins(:tag_repertoire).where(shixun_id: shixun_ids).group('tag_repertoires.name').order('count_shixun_id desc').count(:shixun_id)
+
+ names = []
+ data = []
+ shixun_count_map.each do |name, count|
+ break if names.size == 9
+
+ names << name
+ data << { value: count, name: name }
+ end
+
+ if shixun_count_map.keys.size > 9
+ other_count = shixun_count_map.values[9..-1].reduce(:+)
+ names << 'Others'
+ data << { name: 'Others', value: other_count }
+ end
+
+ render json: { names: names, data: data }
+ end
+
+ # 在线课堂
+ def course_statistics
+ courses = Course.where(school_id: current_school.id, is_delete: 0).where.not(id: 1309)
+
+ @course_count = courses.size
+ courses = courses.left_joins(practice_homeworks: { student_works: { myshixun: :games } })
+ .select('courses.id, courses.name, courses.is_end, IFNULL(sum(games.evaluate_count), 0) evaluating_count')
+ .group('courses.id').order('is_end asc, evaluating_count desc')
+
+ @courses = paginate courses
+
+ course_ids = @courses.map(&:id)
+ @student_count = StudentsForCourse.where(course_id: course_ids).group(:course_id).count
+ @shixun_work_count = HomeworkCommon.where(homework_type: 4, course_id: course_ids).group(:course_id).count
+ @attachment_count = Attachment.where(container_id: course_ids, container_type: 'Course').group(:container_id).count
+ @message_count = Message.joins(:board).where(boards: { parent_id: 0, course_id: course_ids }).group('boards.course_id').count
+ @active_time = CourseActivity.where(course_id: course_ids).group(:course_id).maximum(:created_at)
+ @exercise_count = Exercise.where(course_id: course_ids).group(:course_id).count
+ @poll_count = Poll.where(course_id: course_ids).group(:course_id).count
+ @other_work_count = HomeworkCommon.where(homework_type: [1,3], course_id: course_ids).group(:course_id).count
+ end
+
+ # 学生实训
+ def student_shixun
+ # @student_count = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).count
+ @students = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).includes(:user_extension).order('experience desc').limit(10)
+
+ student_ids = @students.map(&:id)
+ @shixun_count = Myshixun.where(user_id: student_ids).group(:user_id).count
+ @study_shixun_count = Myshixun.where(user_id: student_ids, status: 0).group(:user_id).count
+ end
+
+ def student_hot_evaluations
+ games = Game.joins(:myshixun).joins('join shixun_tag_repertoires str on str.shixun_id = myshixuns.shixun_id')
+ games = games.joins('join tag_repertoires tr on tr.id = str.tag_repertoire_id')
+ games = games.joins("join user_extensions ue on ue.user_id = myshixuns.user_id and ue.school_id = #{current_school.id}")
+ evaluate_count_map = games.group('tr.name').reorder('sum_games_evaluate_count desc').limit(10).sum('games.evaluate_count')
+
+ render json: { names: evaluate_count_map.keys, values: evaluate_count_map.values }
+ end
+
+ private
+
+ def require_login
+ return if User.current.logged?
+
+ redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
+ end
+
+ def check_college_present!
+ return if current_college.present?
+
+ redirect_to '/404'
+ end
+
+ def check_manage_permission!
+ return if can_manage_college?
+
+ redirect_to '/403'
+ end
+
+ def can_manage_college?
+ 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.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id)
+
+ false
+ end
+
+ def current_school
+ current_college.is_a?(School) ? current_college : current_college.school
+ end
+
+ def current_college
+ @_current_college ||= begin
+ Department.find_by(identifier: params[:id]) || School.find_by(id: params[:id])
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index de24f7a8e..52911e905 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -29,7 +29,7 @@ class CoursesController < ApplicationController
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs,
:delete_informs, :change_member_role, :course_groups, :join_course_group, :statistics,
- :work_score, :act_score]
+ :work_score, :act_score, :calculate_all_shixun_scores]
before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course,
:search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list]
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
@@ -48,7 +48,7 @@ class CoursesController < ApplicationController
before_action :validate_page_size, only: :mine
before_action :course_tasks, only: [:tasks_list, :update_task_position]
before_action :validate_inform_params, only: [:update_informs, :new_informs]
- before_action :course_member_allowed, only: [:statistics, :work_score, :act_score]
+ before_action :course_member_allowed, only: [:statistics, :work_score, :act_score, :calculate_all_shixun_scores]
if RUBY_PLATFORM =~ /linux/
require 'simple_xlsx_reader'
@@ -1299,8 +1299,10 @@ class CoursesController < ApplicationController
begin
@all_members = @course.students
search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
- group_id = params[:group_id] #分班的班级id
- @all_members = @all_members.where(course_group_id: group_id.map(&:to_i)) unless group_id.blank?
+ if params[:group_id].present?
+ group_ids = params[:group_id].is_a?(String) ? [params[:group_id].to_i] : params[:group_id].map(&:to_i)
+ @all_members = @all_members.where(course_group_id: group_ids)
+ end
unless search.blank?
@all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{search}%","%#{search}%")
end
@@ -1316,7 +1318,7 @@ class CoursesController < ApplicationController
@c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.created_at asc")
set_export_cookies
- member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks)
+ member_to_xlsx(@course, @all_members.includes(user: :user_extension), @c_homeworks, @c_exercises, @c_tasks)
filename_ = "#{current_user.real_name}_#{@course.name}_总成绩_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_scores_excel.xlsx.axlsx",
locals: {course_scores:@course_user_scores,shixun_works:@shixun_work_arrays,
@@ -1332,6 +1334,16 @@ class CoursesController < ApplicationController
end
end
+ # 计算课堂所有已发布的实训作业成绩
+ def calculate_all_shixun_scores
+ tip_exception(-1, "课堂已结束") if @course.is_end
+ shixun_homeworks = @course.homework_commons.homework_published.where(homework_type: 4)
+ shixun_homeworks.includes(:homework_challenge_settings, :published_settings, :homework_commons_shixun).each do |homework|
+ homework.update_homework_work_score
+ end
+ normal_status(0, "更新成功")
+ end
+
def search_slim
courses = current_user.manage_courses.not_deleted.processing
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 0299fdf7d..25e0de44a 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -47,26 +47,26 @@ class FilesController < ApplicationController
def bulk_publish
return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5
- tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
+ # tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
attachments = @course.attachments.by_ids(@attachment_ids)
ActiveRecord::Base.transaction do
# 有分班设置时
- if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids]
- group_ids = params[:group_ids]&.reject(&:blank?)
- charge_group_ids = @course.charge_group_ids(current_user)
- publish_groups = charge_group_ids & group_ids if group_ids
-
- attachments.each do |atta|
- if atta.published? && !atta.unified_setting || !atta.published?
- create_atta_group_settings atta
- atta.update_all(unified_setting: 0) if atta.unified_setting
- none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published
- none_publish_settings.update_all(publish_time: Time.now)
- end
- end
- end
+ # if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids]
+ # group_ids = params[:group_ids]&.reject(&:blank?)
+ # charge_group_ids = @course.charge_group_ids(current_user)
+ # publish_groups = charge_group_ids & group_ids if group_ids
+ #
+ # attachments.each do |atta|
+ # if atta.published? && !atta.unified_setting || !atta.published?
+ # create_atta_group_settings atta
+ # atta.update_attributes!(unified_setting: 0) if atta.unified_setting
+ # none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published
+ # none_publish_settings.update_all(publish_time: Time.now)
+ # end
+ # end
+ # end
# 未发布的资源更新状态
attachments.where(is_publish: 0).update_all(is_publish: 1, publish_time: Time.now)
@@ -140,7 +140,7 @@ class FilesController < ApplicationController
def public_with_course_and_project
@attachments = Attachment.publiced.simple_columns
.contains_course_and_project
- .includes(:author => :user_extension)
+ .includes(:container, author: :user_extension)
.by_filename_or_user_name(params[:search])
.ordered(sort: 0, sort_type: 'created_on')
@@ -361,15 +361,16 @@ class FilesController < ApplicationController
def publish_params
tip_exception("缺少发布参数") if params[:delay_publish].blank?
@unified_setting = 1
- if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0
- tip_exception("分班发布设置不能为空") if params[:group_settings].blank?
- min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min
- max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max
- tip_exception("分班发布设置不能为空") if min_publish_time.blank?
-
- # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置
- @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort
- elsif params[:delay_publish].to_i == 1
+ # if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0
+ # tip_exception("分班发布设置不能为空") if params[:group_settings].blank?
+ # min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min
+ # max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max
+ # tip_exception("分班发布设置不能为空") if min_publish_time.blank?
+ #
+ # # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置
+ # @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort
+ # els
+ if params[:delay_publish].to_i == 1
tip_exception("缺少延期发布的时间参数") if params[:publish_time].blank?
min_publish_time = params[:publish_time]
end
diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb
index 3f7a451fd..d55eb9211 100644
--- a/app/controllers/games_controller.rb
+++ b/app/controllers/games_controller.rb
@@ -1,15 +1,18 @@
class GamesController < ApplicationController
before_action :require_login, :check_auth
- before_action :find_game
+ before_action :find_game, except: [:jupyter]
before_action :find_shixun, only: [:show, :answer, :rep_content, :choose_build, :game_build, :game_status]
- before_action :allowed
+ before_action :allowed, except: [:jupyter]
#require 'iconv'
include GamesHelper
include ApplicationHelper
+
+
+
def show
uid_logger("--games show start")
# 防止评测中途ajaxE被取消;3改成0是为了处理首次进入下一关的问题
@@ -88,6 +91,22 @@ class GamesController < ApplicationController
end
end
+
+ def jupyter
+ # Jupyter没有challenge
+ @myshixun = Myshixun.find_by_identifier params[:identifier]
+ unless current_user.id == @myshixun.user_id || current_user.admin_or_business?
+ raise Educoder::TipException.new(403, "..")
+ end
+ @shixun = @myshixun.shixun
+ # 判断tpm是否修改了
+ begin
+ @tpm_modified = @myshixun.repository_is_modified(@shixun.repo_path) # 判断TPM和TPI的版本库是否被改了
+ rescue
+ uid_logger("实训平台繁忙,繁忙等级(81)")
+ end
+ end
+
def reset_vnc_link
begin
# 删除vnc的pod
diff --git a/app/controllers/hack_user_lastest_codes_controller.rb b/app/controllers/hack_user_lastest_codes_controller.rb
index 4cd13d6d9..814d16d51 100644
--- a/app/controllers/hack_user_lastest_codes_controller.rb
+++ b/app/controllers/hack_user_lastest_codes_controller.rb
@@ -1,13 +1,14 @@
class HackUserLastestCodesController < ApplicationController
before_action :require_login, except: [:listen_result]
- before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code,
+ before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, :sync_code,
:listen_result, :result, :submit_records, :restore_initial_code]
before_action :update_user_hack_status, only: [:code_debug, :code_submit]
- before_action :require_auth_identity, only: [:update_code, :restore_initial_code]
+ before_action :require_auth_identity, only: [:update_code, :restore_initial_code, :sync_code]
before_action :require_manager_identity, only: [:update_code]
def show
@my_hack.update_attribute(:submit_status, 0) if @my_hack.submit_status == 1
+ @modify = @my_hack.modify_time.to_i < @hack.hack_codes.first.modify_time.to_i
end
def update_code
@@ -20,6 +21,11 @@ class HackUserLastestCodesController < ApplicationController
@my_hack.update_attribute(:code, @hack.code)
end
+ # 同步代码
+ def sync_code
+ @my_hack.update_attributes(code: @hack.code, modify_time: Time.now)
+ end
+
# 调试代码
def code_debug
exec_mode = "debug"
@@ -62,6 +68,7 @@ class HackUserLastestCodesController < ApplicationController
# 提交记录详情
def record_detail
@hack_user = HackUserCode.find params[:id]
+ @my_hack = @hack_user.hack_user_lastest_code
end
# 接收中间件返回结果接口
diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb
index ca0ebcb3b..b7f6a30a2 100644
--- a/app/controllers/hacks_controller.rb
+++ b/app/controllers/hacks_controller.rb
@@ -1,21 +1,23 @@
class HacksController < ApplicationController
before_action :require_login, except: [:index]
- before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set]
- before_action :require_teacher_identity, only: [:create, :update_set]
- before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set]
+ before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set, :destroy, :cancel_publish]
+ before_action :require_teacher_identity, only: [:create]
+ before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set, :destroy, :cancel_publish]
# 开启编程,如果第一次开启,创建一条记录,如果已经开启过的话,直接返回标识即可
def start
# 未发布的编程题,只能作者、或管理员访问
start_hack_auth
- user_hack = @hack.hack_user_lastest_codes.mine(current_user.id)
+ user_hack = @hack.hack_user_lastest_codes.where(user_id: current_user.id).first
+ logger.info("#user_hack: #{user_hack}")
identifier =
if user_hack.present?
+ logger.info("#####user_hack_id:#{user_hack.id}")
user_hack.identifier
else
user_identifier = generate_identifier HackUserLastestCode, 12
- user_code = {user_id: current_user.id, code: @hack.code,
+ user_code = {user_id: current_user.id, code: @hack.code, modify_time: Time.now,
identifier: user_identifier, language: @hack.language}
@hack.hack_user_lastest_codes.create!(user_code)
user_identifier
@@ -47,10 +49,10 @@ class HacksController < ApplicationController
hack.identifier = generate_identifier Hack, 8
hack.save!
# 创建测试集与代码
- logger.info("hack_sets_params:#{hack_sets_params}")
- logger.info("hack_code_params:#{hack_code_params}")
hack.hack_sets.create!(hack_sets_params)
- hack.hack_codes.create!(hack_code_params)
+ hack_codes = hack.hack_codes.new(hack_code_params)
+ hack_codes.modify_time = Time.now
+ hack_codes.save!
end
render_ok({identifier: hack.identifier})
rescue Exception => e
@@ -69,7 +71,8 @@ class HacksController < ApplicationController
# 新建
@hack.hack_sets.create!(hack_sets_params)
# 更新代码
- @hack.hack_codes.create!(hack_code_params)
+ code_params = params[:hack_codes][:code] != @hack.code ? hack_code_params.merge(modify_time: Time.now) : hack_code_params
+ @hack.hack_codes.first.update_attributes!(code_params)
end
render_ok
rescue Exception => e
@@ -98,6 +101,12 @@ class HacksController < ApplicationController
render_ok
end
+ # 取消发布
+ def cancel_publish
+ @hack.update_attribute(:status, 0)
+ render_ok
+ end
+
# 发布列表
def unpulished_list
limit = params[:limit] || 16
@@ -109,6 +118,13 @@ class HacksController < ApplicationController
def edit;end
+ def new;end
+
+ def destroy
+ @hack.destroy
+ render_ok
+ end
+
private
# 实名认证老师,管理员与运营人员权限
def require_teacher_identity
diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb
index 4a31fc474..3a60dcde5 100644
--- a/app/controllers/homework_commons_controller.rb
+++ b/app/controllers/homework_commons_controller.rb
@@ -78,7 +78,7 @@ class HomeworkCommonsController < ApplicationController
when '4'
sql_str = %Q((homework_detail_manuals.comment_status = #{order} and homework_detail_manuals.appeal_time > '#{Time.now}'))
when '5'
- sql_str = %Q((homework_detail_manuals.comment_status = #{order} or (anonymous_comment = 0 and homework_commons.end_time <= '#{Time.now}')))
+ sql_str = %Q((anonymous_comment = 0 or (anonymous_comment = 1 and homework_detail_manuals.comment_status = #{order})) and ((allow_late= 0 and homework_commons.end_time <= '#{Time.now}') or (allow_late= 1 and late_time <= '#{Time.now}')))
else
sql_str = %Q(homework_detail_manuals.comment_status = #{order})
end
@@ -167,11 +167,11 @@ class HomeworkCommonsController < ApplicationController
if params[:work_status].present?
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)
-
- @student_works = @student_works.or(all_student_works.where(work_status: 0)).or(all_student_works.where(myshixuns: {status: 0})) if work_status.include?(3)
- @student_works = @student_works.or(all_student_works.where(myshixuns: {status: 1})) if work_status.include?(4)
+ if @homework.homework_type == "practice"
+ @student_works = @student_works.where(compelete_status: work_status)
+ else
+ @student_works = @student_works.where(work_status: work_status)
+ end
end
# 分班情况
@@ -198,7 +198,6 @@ class HomeworkCommonsController < ApplicationController
end
@work_count = @student_works.size
- @work_excel = @student_works.where("work_status > 0")
# 排序
rorder = params[:order].blank? ? "update_time" : params[:order]
@@ -208,6 +207,7 @@ class HomeworkCommonsController < ApplicationController
elsif rorder == "student_id"
@student_works = @student_works.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end
+ @work_excel = @student_works
# 分页参数
page = params[:page] || 1
@@ -453,7 +453,7 @@ class HomeworkCommonsController < ApplicationController
# 课堂结束后不能再更新
unless @course.is_end
- UpdateHomeworkSettingService.call(@homework, publish_params)
+ UpdateHomeworkPublishSettingService.call(@homework, publish_params)
# 作业未发布时,unified_setting参数不能为空
=begin
if @homework.publish_time.nil? || @homework.publish_time > Time.now
@@ -585,8 +585,8 @@ class HomeworkCommonsController < ApplicationController
tip_exception("缺少answer_open_evaluation参数") if params[:answer_open_evaluation].nil?
tip_exception("缺少work_efficiency参数") if params[:work_efficiency].nil?
tip_exception("缺少eff_score参数") if params[:work_efficiency] && params[:eff_score].blank?
- tip_exception("效率分不能小于等于0") if params[:eff_score] && params[:eff_score].to_f <= 0
- tip_exception("效率分不能大于总分值") if params[:eff_score] && params[:eff_score].to_f.round(2) > params[:total_score].to_f.round(2)
+ tip_exception("效率分不能小于等于0") if params[:work_efficiency] && params[:eff_score] && params[:eff_score].to_f <= 0
+ tip_exception("效率分不能大于总分值") if params[:work_efficiency] && params[:eff_score] && params[:eff_score].to_f.round(2) > params[:total_score].to_f.round(2)
tip_exception("缺少shixun_evaluation参数") if params[:shixun_evaluation].blank?
tip_exception("缺少challenge_settings参数") if params[:challenge_settings].blank?
# tip_exception("缺少challenge_id参数") if params[:challenge_settings][:challenge_id].blank?
@@ -1501,8 +1501,12 @@ class HomeworkCommonsController < ApplicationController
@user = @student_work.user
tip_exception("当前用户无作品可以显示") if @student_work.nil?
# 查询最新一次的查重标识query_id
- group_id = @course.course_members.where(user_id: params[:user_id]).pluck(:course_group_id).first
- query_id = @homework.homework_group_reviews.where(:course_group_id => group_id).last.try(:query_id)
+ group_id = @course.students.where(user_id: params[:user_id]).pluck(:course_group_id).first
+ homework_group_review = @homework.homework_group_reviews.where(:course_group_id => group_id).last || @homework.homework_group_reviews.last
+ query_id = homework_group_review.try(:query_id)
+ Rails.logger.info("##################------query_id: #{query_id}")
+ tip_exception(-1, "query_id有误") unless query_id.present?
+
results = ReviewService.query_result({user_id: params[:user_id], query_id: query_id})
@shixun = @homework.shixuns.take
if results.status == 0
@@ -1652,7 +1656,7 @@ class HomeworkCommonsController < ApplicationController
end
def publish_params
- params.permit(:unified_setting, :publish_time, :end_time, group_settings: [])
+ params.permit(:unified_setting, :publish_time, :end_time, group_settings: [:publish_time, :end_time, group_id: []])
end
end
diff --git a/app/controllers/item_banks_controller.rb b/app/controllers/item_banks_controller.rb
new file mode 100644
index 000000000..104851676
--- /dev/null
+++ b/app/controllers/item_banks_controller.rb
@@ -0,0 +1,14 @@
+class LibrariesController < ApplicationController
+ include PaginateHelper
+
+ def index
+ default_sort('updated_at', 'desc')
+
+ @items = ItemBankQuery.call(params)
+ @items = paginate courses.includes(:school, :students, :attachments, :homework_commons, teacher: :user_extension)
+ end
+
+ def create
+
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/jupyters_controller.rb b/app/controllers/jupyters_controller.rb
new file mode 100644
index 000000000..96ebf3452
--- /dev/null
+++ b/app/controllers/jupyters_controller.rb
@@ -0,0 +1,46 @@
+
+class JupytersController < ApplicationController
+ include JupyterService
+
+ before_action :shixun, only: [:open, :open1, :test, :save]
+
+ def save_with_tpi
+ myshixun = Myshixun.find_by(identifier: params[:identifier])
+ jupyter_save_with_game(myshixun, params[:jupyter_port])
+ render json: {status: 0}
+ end
+
+ def save_with_tpm
+ shixun = Shixun.find_by(identifier: params[:identifier])
+ jupyter_save_with_shixun(shixun, params[:jupyter_port])
+ render json: {status: 0}
+ end
+
+ def get_info_with_tpi
+ myshixun = Myshixun.find_by(identifier: params[:identifier])
+ url = jupyter_url_with_game(myshixun)
+ port = jupyter_port_with_game(myshixun)
+ render json: {status: 0, url: url, port: port}
+ end
+
+ def get_info_with_tpm
+ shixun = Shixun.find_by(identifier: params[:identifier])
+ url = jupyter_url_with_shixun(shixun)
+ port = jupyter_port_with_shixun(shixun)
+ render json: {status: 0, url: url, port: port}
+ end
+
+ def reset_with_tpi
+ myshixun = Myshixun.find_by(identifier: params[:identifier])
+ info = jupyter_tpi_reset(myshixun)
+ render json: {status: 0, url: info[:url], port: info[:port]}
+ end
+
+ def reset_with_tpm
+ shixun = Shixun.find_by(identifier: params[:identifier])
+ info = jupyter_tpm_reset(shixun)
+ render json: {status: 0, url: info[:url], port: info[:port]}
+ end
+
+
+end
\ No newline at end of file
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index 4b2e3f54f..0e9ba477a 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -1,384 +1,411 @@
-class MyshixunsController < ApplicationController
- before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message]
- before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message]
- before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message]
- skip_before_action :verify_authenticity_token, :only => [:html_content]
-
- ## TPI关卡列表
- def challenges
- # @challenges = Challenge.where(shixun_id: params[:shixun_id])
- @shixun = @myshixun.shixun
- @games = @myshixun.games.includes(:challenge).reorder("challenges.position")
- @identity = current_user.game_identity(@games.first)
- end
-
-
- # For Admin
- # 强制重置实训
- # 前段需要按照操作过程提示
- def reset_my_game
- unless (current_user.admin? || current_user.id == @myshixun.user_id)
- tip_exception("403", "")
- end
- begin
- ActiveRecord::Base.transaction do
- begin
- @shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
- @myshixun.destroy!
- StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil,
- final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
- rescue Exception => e
- logger.error("######reset_my_game_failed:#{e.message}")
- raise("ActiveRecord::RecordInvalid")
- end
- end
- # 删除版本库
- GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?
- rescue Exception => e
- if e.message != "ActiveRecord::RecordInvalid"
- logger.error("######delete_repository_error-:#{e.message}")
- end
- raise "delete_repository_error:#{e.message}"
- end
- end
-
- # 代码运行中的信息接口
- # 这个方法是中间层主动调用的,点击评测后,中间层会发送参数过来,告诉目前Pod的启动情况,一次评测会调用两次请求
- def code_runinng_message
- begin
- jsonTestDetails = JSON.parse(params[:jsonTestDetails])
- game_id = jsonTestDetails['buildID']
- message = jsonTestDetails['textMsg']
- if game_id.present? && message.present?
- game = Game.find game_id
- msg = game.run_code_message
- # 只有评测中的game才会创建和更新代码评测中的信息
- if game.status == 1 || game.status == 2
- if msg.blank?
- RunCodeMessage.create!(:game_id => game_id, :status => 1, :message => message)
- else
- msg.update_attributes(:status => (msg.status + 1), :message => message)
- end
- end
- render :json => {:data => "success"}
- end
- rescue Exception => e
- render :json => {:data => "failed, exception_message: #{e}"}
- end
- end
-
- # 中间层评测接口
- # taskId 即返回的game id
- # 返回结果:params [:stauts] 0 表示成功,其它则失败
- # msg 错误信息
- # output 为测试用户编译输出结果
- # myshixun:status 1为完成实训
- # @jenkins: caseId对应test_set的position,passed: 1表示成功,0表示失败
- # resubmit 1:表示已通关后重新评测;0:表示非重新评测
- # retry_status 0:初始值;1:重新评测失败;2:重新评测成功
- # tpiRepoPath 中间层图片的workspace路径
- # params[:jsonTestDetails] = '{"buildID":"19284","compileSuccess":"1",
- # "msg":[{"caseId":"1","expectedOutput":"MSAyIDMNCg","input":"MiAzIDE","output":"MSAyIDMNCg","passed":"1"},
- # {"caseId":"2","expectedOutput":"LTMgMSA2DQo","input":"LTMgNiAx","output":"LTMgMSA2DQo","passed":"1"},
- # {"caseId":"3","expectedOutput":"LTcgLTUgLTMNCg","input":"LTcgLTMgLTU","output":"LTcgLTUgLTMNCg","passed":"1"}],
- # "outPut":"Y29tcGlsZSBzdWNjZXNzZnVsbHk","resubmit":"","status":"0"}'
- # params[:timeCost] = '{"evaluateEnd":"2017-11-24 11:04:37","pull":"0.086",
- # "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}'
- # params[:pics] = "a.png,b.png,c.png"
- def training_task_status
-
- ActiveRecord::Base.transaction do
- begin
- t1 = Time.now
- uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}")
- jsonTestDetails = JSON.parse(params[:jsonTestDetails])
- timeCost = JSON.parse(params[:timeCost])
- brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present?
- return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f
- status = jsonTestDetails['status']
- game_id = jsonTestDetails['buildID']
- sec_key = jsonTestDetails['sec_key']
-
- uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
- resubmit = jsonTestDetails['resubmit']
- outPut = tran_base64_decode64(jsonTestDetails['outPut'])
-
- jenkins_testsets = jsonTestDetails['msg']
- compile_success = jsonTestDetails['compileSuccess']
- # message = Base64.decode64(params[:msg]) unless params[:msg].blank?
-
- game = Game.find(game_id)
- myshixun = game.myshixun
- challenge = game.challenge
- # test_sets = challenge.test_sets
- if challenge.picture_path.present?
- #pics = params[:files]
- pics = params[:tpiRepoPath]
- game.update_column(:picture_path, pics)
- end
- max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
- test_set_score = 0
- unless jenkins_testsets.blank?
- jenkins_testsets.each_with_index do |j_test_set, i|
- actual_output = tran_base64_decode64(j_test_set['output'])
- #ts_time += j_test_set['testSetTime'].to_i
-
- # is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
- ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f if j_test_set['testSetTime']
- ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f if j_test_set['testSetMem']
-
- Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'],
- :actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index,
- :compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem)
- # 如果设置了按测试集给分,则需要统计测试集的分值
- if challenge.test_set_score && j_test_set['passed'].to_i == 1
- test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first
- end
- end
- end
- record = EvaluateRecord.where(:identifier => sec_key).first
- answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
- # answer_deduction是查看答案的扣分比例
- # status:0表示评测成功
- if status == "0"
- if resubmit.present?
- game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
- challenge.path.split(";").each do |path|
- game_passed_code(path.try(:strip), myshixun, game_id)
- end
- else
- game.update_attributes!(:status => 2,
- :end_time => Time.now,
- :accuracy => format("%.4f", 1.0 / game.query_index))
- myshixun.update_attributes!(:status => 1) if game.had_done == 1
- challenge.path.split(";").each do |path|
- game_passed_code(path.try(:strip), myshixun, game_id)
- end
- # 如果是已经发布的实训,则需要给出相应的奖励
- if challenge.shixun.try(:status) > 1
- score = (challenge.score * answer_deduction_percentage).to_i
- if score > 0
- reward_attrs = { container_id: game.id, container_type: 'Game', score: score }
- RewardGradeService.call(game.user, reward_attrs)
- RewardExperienceService.call(game.user, reward_attrs)
- end
- # 需要扣除查看答案的分数
- game.update_attributes!(:final_score => score)
- end
-
- # 更新实训关联的作品分数 TODO: 更新作品分数
- # HomeworksService.new.update_myshixun_work_score myshixun
- end
- # 如果过关了,下一关的状态是3(为开启),则需要把状态改成1(已开启)
- # next_game = game.next_game
- next_game = game.next_game(myshixun.shixun_id, game.myshixun_id, challenge.position)
- next_game.update_column(:status, 0) if next_game.present? && next_game.status == 3
- # status == "-1" 表示返回结果错误
- else
- if resubmit.present?
- game.update_attributes!(:retry_status => 1, :resubmit_identifier => resubmit)
- else
- # 评测没通关则,测试集对的个数给分,并且还要扣除用户是否查看答案的值
- test_set_percentage = test_set_score / 100.to_f # 测试集得分比
- score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i
- # 如果分数比上次多,则更新成绩
- game_update =
- if game.final_score < score
- {final_score: score, status: 0}
- else
- {status: 0}
- end
- game.update_attributes!(game_update)
- end
- end
- test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f
- if record.present?
- consume_time = format("%.3f", (Time.now - record.created_at)).to_f
-
- record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'],
- :pod_execute => timeCost['execute'], :test_cases => test_cases_time,
- :brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
- end
- sucess_status
- # rescue Exception => e
- # tip_exception(e.message)
- # uid_logger_error("training_task_status error: #{e}")
- # raise ActiveRecord::Rollback
- end
- end
- end
-
- # 连接webssh
- def open_webssh
- username = edu_setting('webssh_username')
- password = edu_setting('webssh_password')
- old_time = Time.now.to_i
- begin
- shixun_tomcat = edu_setting('tomcat_webssh')
- uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
- params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh),
- containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))}
- res = uri_post uri, params
- if res && res['code'].to_i != 0
- tip_exception("实训云平台繁忙(繁忙等级:92)")
- end
- render :json => {:host => res['address'],
- :port => res['port'],
- :ws_url => res['ws_address'],
- :username => username,
- :password => password,
- :game_id => @myshixun.id,
- :webssh_url => "#{shixun_tomcat}/bridge"}
- rescue Exception => e
- logger.error(e)
- render :json => {:error => e.try(:message)}
- ensure
- use_time = Time.now.to_i - old_time
- logger.info "open_webssh tpiID #{@myshixun.id} use time #{use_time}"
- end
- end
-
- include GitCommon
-
- # -----Repository
- # TODO: 之类需要一个resubmit参数,但是是关于games.
- def update_file
- begin
- @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
- tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
- path = params[:path].strip unless params[:path].blank?
- game_id = params[:game_id]
- game = Game.find(game_id)
- @content_modified = 0
-
- # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
- # 自动保存的时候evaluate为0;点评测的时候为1
- if params[:evaluate] == 1
- exec_time = game.challenge.try(:exec_time)
- @sec_key = generate_identifier(EvaluateRecord, 12)
- record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
- :identifier => @sec_key, :exec_time => exec_time)
- uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
- end
- # 隐藏代码文件 和 VNC的都不需要走版本库
- unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?)
- # 远程版本库文件内容
- last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
-
- content =
- if python_file?(path)
- params[:content].gsub(/\t/, ' ').gsub(/ /, ' ')
- else
- params[:content]
- end
- uid_logger_dubug("###11222333####{content}")
- uid_logger_dubug("###222333####{last_content}")
-
- if content != last_content
- @content_modified = 1
-
- author_name = current_user.real_name
- author_email = current_user.git_mail
- message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
- uid_logger_dubug("112233#{author_name}")
- uid_logger_dubug("112233#{author_email}")
- @content = GitService.update_file(repo_path: @repo_path,
- file_path: path,
- message: message,
- content: content,
- author_name: author_name,
- author_email: author_email)
- end
- end
-
- if game.status == 2
- @resubmit = Time.now.to_i
- end
-
- # 评测时间记录
- if record.present?
- consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
- record.update_attributes!(:file_update => consume_time)
- end
- rescue Exception => e
- uid_logger_error(e.message)
- tip_exception("文件内容更新异常,请稍后重试")
- end
- end
-
- # 渲染实训代码
- # educodercss: 字符串以 ‘,’分隔,存储的是版本库css的路径
- # educoderscript: 字符串以 ‘,’分隔,存储的是版本库js的路径
- # contents: html实训的整体内容
- def html_content
- @contents = params[:contents] || ""
- edu_css = params[:educodercss]
- edu_js = params[:educoderscript]
- if @contents.present?
- @contents = @contents.gsub("w3equalsign", "=").gsub("w3scrw3ipttag", "script").gsub("edulink", "link").html_safe
- end
- # css
- if edu_css.present?
- css_path = edu_css.split(",")
- css_path.each do |path|
- file_content = git_fle_content(@repo_path, path)["content"]
- file_content = tran_base64_decode64(file_content) unless file_content.blank?
- @contents = @contents.sub(/EDUCODERCSS/, "")
- end
- end
- # js
- if edu_js.present?
- js_path = edu_js.split(",")
- js_path.each do |path|
- file_content = git_fle_content(@repo_path, path)["content"]
- file_content = tran_base64_decode64(file_content) unless file_content.blank?
- @contents = @contents.sub(/EDUCODERJS/, "")
- end
- end
- respond_to do |format|
- format.json
- format.html{render :layout => false}
- end
- end
-
- # 最新可以用的并发测试接口
- def sigle_mul_test
- codes = %W(1 2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z)
- begin
- identifiers = Myshixun.where(:shixun_id => params[:shixun_id].split(",")).pluck(:identifier)
- ide = identifiers[rand(identifiers.length)]
- myshixun = Myshixun.where(:identifier => ide).first
-
- game = myshixun.games.last
- logger.warn("###2mul test game_build start ")
- identifier = game.try(:identifier)
- if game.status == 2
- code = codes.sample(8).join
- resubmit = "#{code}_#{myshixun.id}"
- end
- logger.warn("###3mul test game_build start ...")
- EvaluateRecord.create!(:user_id => myshixun.user_id, :shixun_id => myshixun.shixun.id, :game_id => game.id)
- redirect_to "/api/games/#{identifier}/game_build?resubmit=#{resubmit}&content_modified=0&first=1"
- rescue Exception => e
- logger.error("mul test failed ===> #{e.message}")
- end
- end
-
-
- # -----End
-
- private
- def find_myshixun
- @myshixun = Myshixun.find_by!(identifier: params[:identifier])
- end
-
- def find_repo_name
- @repo_path = @myshixun.try(:repo_path)
- @path = params[:path]
- end
-
- def python_file?(path)
- false if path.blank?
- path.to_s.split(".").last.downcase == "py"
- end
-end
+class MyshixunsController < ApplicationController
+ before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message]
+ before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message]
+ before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message]
+ skip_before_action :verify_authenticity_token, :only => [:html_content]
+
+ ## TPI关卡列表
+ def challenges
+ # @challenges = Challenge.where(shixun_id: params[:shixun_id])
+ @shixun = @myshixun.shixun
+ @games = @myshixun.games.includes(:challenge).reorder("challenges.position")
+ @identity = current_user.game_identity(@games.first)
+ end
+
+
+ # For Admin
+ # 强制重置实训
+ # 前段需要按照操作过程提示
+ def reset_my_game
+ unless (current_user.admin? || current_user.id == @myshixun.user_id)
+ tip_exception("403", "")
+ end
+ begin
+ ActiveRecord::Base.transaction do
+ begin
+ @shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
+ @myshixun.destroy!
+ StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil,
+ final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
+ rescue Exception => e
+ logger.error("######reset_my_game_failed:#{e.message}")
+ raise("ActiveRecord::RecordInvalid")
+ end
+ end
+ # 删除版本库
+ GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?
+ rescue Exception => e
+ if e.message != "ActiveRecord::RecordInvalid"
+ logger.error("######delete_repository_error-:#{e.message}")
+ end
+ raise "delete_repository_error:#{e.message}"
+ end
+ end
+
+ # 代码运行中的信息接口
+ # 这个方法是中间层主动调用的,点击评测后,中间层会发送参数过来,告诉目前Pod的启动情况,一次评测会调用两次请求
+ def code_runinng_message
+ begin
+ jsonTestDetails = JSON.parse(params[:jsonTestDetails])
+ game_id = jsonTestDetails['buildID']
+ message = jsonTestDetails['textMsg']
+ if game_id.present? && message.present?
+ game = Game.find game_id
+ msg = game.run_code_message
+ # 只有评测中的game才会创建和更新代码评测中的信息
+ if game.status == 1 || game.status == 2
+ if msg.blank?
+ RunCodeMessage.create!(:game_id => game_id, :status => 1, :message => message)
+ else
+ msg.update_attributes(:status => (msg.status + 1), :message => message)
+ end
+ end
+ render :json => {:data => "success"}
+ end
+ rescue Exception => e
+ render :json => {:data => "failed, exception_message: #{e}"}
+ end
+ end
+
+ # 中间层评测接口
+ # taskId 即返回的game id
+ # 返回结果:params [:stauts] 0 表示成功,其它则失败
+ # msg 错误信息
+ # output 为测试用户编译输出结果
+ # myshixun:status 1为完成实训
+ # @jenkins: caseId对应test_set的position,passed: 1表示成功,0表示失败
+ # resubmit 1:表示已通关后重新评测;0:表示非重新评测
+ # retry_status 0:初始值;1:重新评测失败;2:重新评测成功
+ # tpiRepoPath 中间层图片的workspace路径
+ # params[:jsonTestDetails] = '{"buildID":"19284","compileSuccess":"1",
+ # "msg":[{"caseId":"1","expectedOutput":"MSAyIDMNCg","input":"MiAzIDE","output":"MSAyIDMNCg","passed":"1"},
+ # {"caseId":"2","expectedOutput":"LTMgMSA2DQo","input":"LTMgNiAx","output":"LTMgMSA2DQo","passed":"1"},
+ # {"caseId":"3","expectedOutput":"LTcgLTUgLTMNCg","input":"LTcgLTMgLTU","output":"LTcgLTUgLTMNCg","passed":"1"}],
+ # "outPut":"Y29tcGlsZSBzdWNjZXNzZnVsbHk","resubmit":"","status":"0"}'
+ # params[:timeCost] = '{"evaluateEnd":"2017-11-24 11:04:37","pull":"0.086",
+ # "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}'
+ # params[:pics] = "a.png,b.png,c.png"
+ def training_task_status
+
+ ActiveRecord::Base.transaction do
+ begin
+ t1 = Time.now
+ uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}")
+ jsonTestDetails = JSON.parse(params[:jsonTestDetails])
+ timeCost = JSON.parse(params[:timeCost])
+ brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present?
+ return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f
+ status = jsonTestDetails['status']
+ game_id = jsonTestDetails['buildID']
+ sec_key = jsonTestDetails['sec_key']
+
+ uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
+ resubmit = jsonTestDetails['resubmit']
+ outPut = tran_base64_decode64(jsonTestDetails['outPut'])
+
+ jenkins_testsets = jsonTestDetails['msg']
+ compile_success = jsonTestDetails['compileSuccess']
+ # message = Base64.decode64(params[:msg]) unless params[:msg].blank?
+
+ game = Game.find(game_id)
+ myshixun = game.myshixun
+ challenge = game.challenge
+ # test_sets = challenge.test_sets
+ if challenge.picture_path.present?
+ #pics = params[:files]
+ pics = params[:tpiRepoPath]
+ game.update_column(:picture_path, pics)
+ end
+ max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
+ test_set_score = 0
+ unless jenkins_testsets.blank?
+ jenkins_testsets.each_with_index do |j_test_set, i|
+ actual_output = tran_base64_decode64(j_test_set['output'])
+ #ts_time += j_test_set['testSetTime'].to_i
+
+ # is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
+ ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f if j_test_set['testSetTime']
+ ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f if j_test_set['testSetMem']
+
+ Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'],
+ :actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index,
+ :compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem)
+ # 如果设置了按测试集给分,则需要统计测试集的分值
+ if challenge.test_set_score && j_test_set['passed'].to_i == 1
+ test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first
+ end
+ end
+ end
+ record = EvaluateRecord.where(:identifier => sec_key).first
+ answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
+ # answer_deduction是查看答案的扣分比例
+ # status:0表示评测成功
+ if status == "0"
+ if resubmit.present?
+ game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
+ challenge.path.split(";").each do |path|
+ game_passed_code(path.try(:strip), myshixun, game_id)
+ end
+ else
+ game.update_attributes!(:status => 2,
+ :end_time => Time.now,
+ :accuracy => format("%.4f", 1.0 / game.query_index))
+ myshixun.update_attributes!(:status => 1) if game.had_done == 1
+ challenge.path.split(";").each do |path|
+ game_passed_code(path.try(:strip), myshixun, game_id)
+ end
+ # 如果是已经发布的实训,则需要给出相应的奖励
+ if challenge.shixun.try(:status) > 1
+ score = (challenge.score * answer_deduction_percentage).to_i
+ if score > 0
+ reward_attrs = { container_id: game.id, container_type: 'Game', score: score }
+ RewardGradeService.call(game.user, reward_attrs)
+ RewardExperienceService.call(game.user, reward_attrs)
+ end
+ # 需要扣除查看答案的分数
+ game.update_attributes!(:final_score => score)
+ end
+
+ # 更新实训关联的作品分数 TODO: 更新作品分数
+ # HomeworksService.new.update_myshixun_work_score myshixun
+ end
+ # 如果过关了,下一关的状态是3(为开启),则需要把状态改成1(已开启)
+ # next_game = game.next_game
+ next_game = game.next_game(myshixun.shixun_id, game.myshixun_id, challenge.position)
+ next_game.update_column(:status, 0) if next_game.present? && next_game.status == 3
+ # status == "-1" 表示返回结果错误
+ else
+ if resubmit.present?
+ game.update_attributes!(:retry_status => 1, :resubmit_identifier => resubmit)
+ else
+ # 评测没通关则,测试集对的个数给分,并且还要扣除用户是否查看答案的值
+ test_set_percentage = test_set_score / 100.to_f # 测试集得分比
+ score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i
+ # 如果分数比上次多,则更新成绩
+ game_update =
+ if game.final_score < score
+ {final_score: score, status: 0}
+ else
+ {status: 0}
+ end
+ game.update_attributes!(game_update)
+ end
+ end
+ test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f
+ if record.present?
+ consume_time = format("%.3f", (Time.now - record.created_at)).to_f
+
+ record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'],
+ :pod_execute => timeCost['execute'], :test_cases => test_cases_time,
+ :brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
+ end
+ sucess_status
+ # rescue Exception => e
+ # tip_exception(e.message)
+ # uid_logger_error("training_task_status error: #{e}")
+ # raise ActiveRecord::Rollback
+ end
+ end
+ end
+
+ # 连接webssh
+ def open_webssh
+ username = edu_setting('webssh_username')
+ password = edu_setting('webssh_password')
+ old_time = Time.now.to_i
+ begin
+ shixun_tomcat = edu_setting('tomcat_webssh')
+ uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
+ # 由于中间层采用混合云的方式,因为local参数表示在有文件生成的实训是在本地生成,还是在其他云端生成评测文件
+ local = @myshixun.shixun.challenges.where.not(show_type: -1).count == 0
+ params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), local: local,
+ containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))}
+ res = uri_post uri, params
+ if res && res['code'].to_i != 0
+ tip_exception("实训云平台繁忙(繁忙等级:92)")
+ end
+ render :json => {:host => res['address'],
+ :port => res['port'],
+ :ws_url => res['ws_address'],
+ :username => username,
+ :password => password,
+ :game_id => @myshixun.id,
+ :webssh_url => "#{shixun_tomcat}/bridge"}
+ rescue Exception => e
+ logger.error(e)
+ render :json => {:error => e.try(:message)}
+ ensure
+ use_time = Time.now.to_i - old_time
+ logger.info "open_webssh tpiID #{@myshixun.id} use time #{use_time}"
+ end
+ end
+
+ include GitCommon
+
+ # -----Repository
+ # TODO: 之类需要一个resubmit参数,但是是关于games.
+ def update_file
+ begin
+ @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
+ tip_exception("实验环境不能为空,请查看实训模板的环境配置项是否正确!") if (@myshixun.mirror_name.blank? || @myshixun.mirror_name.first.to_s == "-1")
+ path = params[:path].strip unless params[:path].blank?
+ game_id = params[:game_id]
+ game = Game.find(game_id)
+ @content_modified = 0
+
+ # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
+ # 自动保存的时候evaluate为0;点评测的时候为1
+ if params[:evaluate] == 1
+ exec_time = game.challenge.try(:exec_time)
+ @sec_key = generate_identifier(EvaluateRecord, 12)
+ record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
+ :identifier => @sec_key, :exec_time => exec_time)
+ uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
+ end
+ # 隐藏代码文件 和 VNC的都不需要走版本库
+ unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?)
+ # 远程版本库文件内容
+ last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
+
+ content =
+ if python_file?(path)
+ params[:content].gsub(/\t/, ' ').gsub(/ /, ' ')
+ else
+ params[:content]
+ end
+ uid_logger_dubug("###11222333####{content}")
+ uid_logger_dubug("###222333####{last_content}")
+
+ if content != last_content
+ @content_modified = 1
+
+ author_name = current_user.real_name
+ author_email = current_user.git_mail
+ message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
+ uid_logger_dubug("112233#{author_name}")
+ uid_logger_dubug("112233#{author_email}")
+ @content = GitService.update_file(repo_path: @repo_path,
+ file_path: path,
+ message: message,
+ content: content,
+ author_name: author_name,
+ author_email: author_email)
+ end
+ end
+
+ if game.status == 2
+ @resubmit = Time.now.to_i
+ end
+
+ # 评测时间记录
+ if record.present?
+ consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
+ record.update_attributes!(:file_update => consume_time)
+ end
+ rescue Exception => e
+ uid_logger_error(e.message)
+ tip_exception("文件内容更新异常,请稍后重试")
+ end
+ end
+
+ # 渲染实训代码
+ # educodercss: 字符串以 ‘,’分隔,存储的是版本库css的路径
+ # educoderscript: 字符串以 ‘,’分隔,存储的是版本库js的路径
+ # contents: html实训的整体内容
+ def html_content
+ @contents = params[:contents] || ""
+ edu_css = params[:educodercss]
+ edu_js = params[:educoderscript]
+ if @contents.present?
+ @contents = @contents.gsub("w3equalsign", "=").gsub("w3scrw3ipttag", "script").gsub("edulink", "link").html_safe
+ end
+ # css
+ if edu_css.present?
+ css_path = edu_css.split(",")
+ css_path.each do |path|
+ file_content = git_fle_content(@repo_path, path)["content"]
+ file_content = tran_base64_decode64(file_content) unless file_content.blank?
+ @contents = @contents.sub(/EDUCODERCSS/, "")
+ end
+ end
+ # js
+ if edu_js.present?
+ js_path = edu_js.split(",")
+ js_path.each do |path|
+ file_content = git_fle_content(@repo_path, path)["content"]
+ file_content = tran_base64_decode64(file_content) unless file_content.blank?
+ @contents = @contents.sub(/EDUCODERJS/, "")
+ end
+ end
+ respond_to do |format|
+ format.json
+ format.html{render :layout => false}
+ end
+ end
+
+ # 最新可以用的并发测试接口
+ def sigle_mul_test
+ codes = %W(1 2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z)
+ begin
+ identifiers = Myshixun.where(:shixun_id => params[:shixun_id].split(",")).pluck(:identifier)
+ ide = identifiers[rand(identifiers.length)]
+ myshixun = Myshixun.where(:identifier => ide).first
+
+ game = myshixun.games.last
+ logger.warn("###2mul test game_build start ")
+ identifier = game.try(:identifier)
+ if game.status == 2
+ code = codes.sample(8).join
+ resubmit = "#{code}_#{myshixun.id}"
+ end
+ logger.warn("###3mul test game_build start ...")
+ EvaluateRecord.create!(:user_id => myshixun.user_id, :shixun_id => myshixun.shixun.id, :game_id => game.id)
+ redirect_to "/api/games/#{identifier}/game_build?resubmit=#{resubmit}&content_modified=0&first=1"
+ rescue Exception => e
+ logger.error("mul test failed ===> #{e.message}")
+ end
+ end
+
+ def sync_code
+ shixun_tomcat = edu_setting('cloud_bridge')
+ begin
+ git_myshixun_url = repo_ip_url @myshixun.repo_path
+ git_shixun_url = repo_ip_url @myshixun.shixun.try(:repo_path)
+ git_myshixun_url = Base64.urlsafe_encode64(git_myshixun_url)
+ git_shixun_url = Base64.urlsafe_encode64(git_shixun_url)
+ # todo: identifier 是以前的密码,用来验证的,新版如果不需要,和中间层协调更改.
+ params = {tpiID: "#{@myshixun.try(:id)}", tpiGitURL: "#{git_myshixun_url}", tpmGitURL: "#{git_shixun_url}",
+ identifier: "xinhu1ji2qu3"}
+ uri = "#{shixun_tomcat}/bridge/game/resetTpmRepository"
+ res = uri_post uri, params
+ if (res && res['code'] != 0)
+ tip_exception("实训云平台繁忙(繁忙等级:95)")
+ end
+ shixun_new_commit = GitService.commits(repo_path: @myshixun.shixun.repo_path).first["id"]
+ @myshixun.update_attributes!(commit_id: shixun_new_commit, reset_time: @myshixun.shixun.try(:reset_time))
+ # 更新完成后,弹框则隐藏不再提示
+ @myshixun.update_column(:system_tip, false)
+ render_ok
+ rescue Exception => e
+ tip_exception("立即更新代码失败!#{e.message}")
+ end
+ end
+
+
+ # -----End
+
+ private
+ def find_myshixun
+ @myshixun = Myshixun.find_by!(identifier: params[:identifier])
+ end
+
+ def find_repo_name
+ @repo_path = @myshixun.try(:repo_path)
+ @path = params[:path]
+ end
+
+ def python_file?(path)
+ false if path.blank?
+ path.to_s.split(".").last.downcase == "py"
+ end
+end
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 068a0dafd..0c442a613 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -1409,23 +1409,29 @@ class PollsController < ApplicationController
poll_questions.each do |q|
user_poll_votes = u_user.poll_votes.find_current_vote("poll_question_id",q.id)
if user_poll_votes.present?
- user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?)
- user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?)
- if user_poll_answer_ids.count > 0
- answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids)
- if user_poll_answer_ids.count >1
- u_answer = answer_content.pluck(:answer_text).join(";")
+ if q.question_type < 3
+ user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?)
+ if user_poll_answer_ids.count > 0
+ answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids)
+ if user_poll_answer_ids.count >1
+ u_answer = answer_content.pluck(:answer_text).join(";")
+ else
+ u_answer = answer_content.first&.answer_text
+ end
else
- u_answer = answer_content.first.answer_text
+ u_answer = "--"
end
- elsif user_poll_vote_texts.count > 0
- if user_poll_vote_texts.count > 1
- u_answer = user_poll_vote_texts.join(";")
+ else
+ user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?)
+ if user_poll_vote_texts.count > 0
+ if user_poll_vote_texts.count > 1
+ u_answer = user_poll_vote_texts.join(";")
+ else
+ u_answer = user_poll_vote_texts.first
+ end
else
- u_answer = user_poll_vote_texts.first
+ u_answer = "--"
end
- else
- u_answer = "--"
end
else
u_answer = "--"
diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb
index 03fdbf97f..aa25d0875 100644
--- a/app/controllers/shixuns_controller.rb
+++ b/app/controllers/shixuns_controller.rb
@@ -6,27 +6,28 @@ class ShixunsController < ApplicationController
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
:discusses, :collaborators, :fork_list, :propaedeutics]
- before_action :check_account, only: [:new, :create, :shixun_exec]
+ before_action :check_account, only: [:new, :create, :shixun_exec, :jupyter_exec]
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file, :shixun_list, :batch_send_to_course]
before_action :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
- :propaedeutics, :departments, :apply_shixun_mirror,
+ :propaedeutics, :departments, :apply_shixun_mirror, :jupyter_exec,
:get_mirror_script, :download_file, :shixun_list, :batch_send_to_course]
- before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy, :add_file]
+ before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy,
+ :add_file, :jupyter_exec]
- before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish,
+ before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, :apply_public,
:shixun_members_added, :change_manager, :collaborators_delete,
- :cancel_publish, :add_collaborators, :add_file]
+ :cancel_apply_public, :cancel_publish, :add_collaborators, :add_file]
before_action :portion_allowed, only: [:copy]
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
## 获取课程列表
def index
- @shixuns = current_laboratory.shixuns.unhidden
+ @shixuns = current_laboratory.shixuns.unhidden.publiced
## 方向
if params[:tag_level].present? && params[:tag_id].present?
@@ -66,15 +67,11 @@ class ShixunsController < ApplicationController
## 排序参数
bsort = params[:sort] || 'desc'
- case params[:order_by] || 'publish_time'
- when 'new'
- @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.created_at #{bsort}")
+ case params[:order_by] || 'new'
when 'hot'
- @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.myshixuns_count #{bsort}")
- when 'mine'
- @shixuns = @shixuns.order("shixuns.created_at #{bsort}")
+ @shixuns = @shixuns.order("shixuns.public = 2 desc, shixuns.myshixuns_count #{bsort}")
else
- @shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.publish_time #{bsort}")
+ @shixuns = @shixuns.order("shixuns.public = 2 desc, shixuns.publish_time #{bsort}")
end
# 用id计数会快10+MS左右,对于搜索的内容随着数据的增加,性能会提升一些。
@@ -168,9 +165,10 @@ class ShixunsController < ApplicationController
def show_right
owner = @shixun.owner
- #@fans_count = owner.fan_count
- #@followed_count = owner.follow_count
@user_own_shixuns = owner.shixuns.published.count
+ @user_tags = @shixun.user_tags_name(current_user)
+ @shixun_tags = @shixun.challenge_tags_name
+ @myshixun = @shixun.myshixuns.find_by(user_id: current_user.id)
end
# 排行榜
@@ -206,7 +204,7 @@ class ShixunsController < ApplicationController
@new_shixun = Shixun.new
@new_shixun.attributes = @shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier", "averge_star",
"homepage_show","repo_name", "myshixuns_count", "challenges_count",
- "can_copy", "created_at", "updated_at")
+ "can_copy", "created_at", "updated_at", "public")
@new_shixun.user_id = User.current.id
@new_shixun.averge_star = 5
@new_shixun.identifier = generate_identifier Shixun, 8
@@ -264,7 +262,12 @@ class ShixunsController < ApplicationController
project_fork(@new_shixun, @repo_path, current_user.login)
ShixunMember.create!(:user_id => User.current.id, :shixun_id => @new_shixun.try(:id), :role => 1)
-
+ # 如果是jupyter,先创建一个目录,为了挂载(因为后续数据集,开启Pod后环境在没销毁前,你上传数据集是挂载不上目录的,因此要先创建目录,方便中间层挂载)
+ if @new_shixun.is_jupyter?
+ folder = EduSetting.get('shixun_folder')
+ path = "#{folder}/#{@new_shixun.identifier}"
+ FileUtils.mkdir_p(path, :mode => 0777) unless File.directory?(path)
+ end
# 同步复制关卡
if @shixun.challenges.present?
@shixun.challenges.each do |challenge|
@@ -343,7 +346,11 @@ class ShixunsController < ApplicationController
#合作者
def collaborators
@user = current_user
- @members = @shixun.shixun_members.includes(:user)
+ ## 分页参数
+ page = params[:page] || 1
+ limit = params[:limit] || 10
+ @member_count = @shixun.shixun_members.count
+ @members = @shixun.shixun_members.includes(:user).page(page).per(limit)
end
def fork_list
@@ -364,73 +371,162 @@ class ShixunsController < ApplicationController
end
def create
- # 评测脚本的一些操作
- main_type, sub_type = params[:main_type], params[:small_type]
- mirror = MirrorScript.where(:mirror_repository_id => main_type)
-
- identifier = generate_identifier Shixun, 8
- @shixun = Shixun.new(shixun_params)
- @shixun.identifier = identifier
- @shixun.user_id = current_user.id
- @shixun.reset_time, @shixun.modify_time = Time.now, Time.now
-
- if sub_type.blank?
- shixun_script = mirror.first.try(:script)
- else
- main_mirror = MirrorRepository.find(main_type).type_name
- sub_mirror = MirrorRepository.where(id: sub_type).pluck(:type_name)
- if main_mirror == "Java" && sub_mirror.include?("Mysql")
- shixun_script = mirror.last.try(:script)
- else
- shixun_script = mirror.first.try(:script)
- shixun_script = modify_shixun_script @shixun, shixun_script
- end
- end
+ @shixun = CreateShixunService.call(current_user, shixun_params, params)
+ end
- ActiveRecord::Base.transaction do
- begin
- @shixun.save!
- # shixun_info关联ß
- ShixunInfo.create!(shixun_id: @shixun.id, evaluate_script: shixun_script, description: params[:description])
- # 实训的公开范围
- if params[:scope_partment].present?
- arr = []
- ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq
- ids.each do |id|
- arr << { :school_id => id, :shixun_id => @shixun.id }
- end
- ShixunSchool.create!(arr)
- end
+ # 保存jupyter到版本库
+ def update_jupyter
+ jupyter_save_with_shixun(@shixun, params[:jupyter_port])
+ end
- # 实训合作者
- @shixun.shixun_members.create!(user_id: current_user.id, role: 1)
-
- # 镜像-实训关联表
- ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present?
- # 实训主镜像服务配置
- ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i)
- if sub_type.present?
- sub_type.each do |mirror|
- ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
- # 实训子镜像服务配置
- name = MirrorRepository.find_by(id: mirror).try(:name) #查看镜像是否有名称,如果没有名称就不用服务配置
- ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) if name.present?
+ def update
+ # 镜像方面
+ mirror_ids = MirrorRepository.where(id: params[:main_type])
+ .or( MirrorRepository.where(id: params[:sub_type])).pluck(:id).uniq
+ old_mirror_ids = @shixun.shixun_mirror_repositories
+ .where(mirror_repository_id: params[:main_type])
+ .or(@shixun.shixun_mirror_repositories.where(mirror_repository_id: params[:sub_type]))
+ .pluck(:mirror_repository_id).uniq
+ new_mirror_id = (mirror_ids - old_mirror_ids).map{|id| {mirror_repository_id: id}} # 转换成数组hash方便操作
+ logger.info("##########new_mirror_id: #{new_mirror_id}")
+ logger.info("##########old_mirror_ids: #{old_mirror_ids}")
+ logger.info("##########mirror_ids: #{mirror_ids}")
+ # 服务配置方面
+ service_create_params = service_config_params[:shixun_service_configs]
+ .select{|config| !old_mirror_ids.include?(config[:mirror_repository_id]) &&
+ MirrorRepository.find(config[:mirror_repository_id]).name.present?}
+ service_update_params = service_config_params[:shixun_service_configs]
+ .select{|config| old_mirror_ids.include?(config[:mirror_repository_id])}
+ logger.info("#########service_create_params: #{service_create_params}")
+ logger.info("#########service_update_params: #{service_update_params}")
+ begin
+ ActiveRecord::Base.transaction do
+ @shixun.update_attributes(shixun_params)
+ @shixun.shixun_info.update_attributes(shixun_info_params)
+ # 镜像变动
+ @shixun.shixun_mirror_repositories.where.not(mirror_repository_id: old_mirror_ids).destroy_all
+ @shixun.shixun_mirror_repositories.create!(new_mirror_id) if new_mirror_id.present?
+ # 镜像变动要更换服务配置
+ @shixun.shixun_service_configs.where.not(mirror_repository_id: old_mirror_ids).destroy_all
+ @shixun.shixun_service_configs.create!(service_create_params) if service_create_params.present?
+ service_update_params&.map do |service|
+ smr = @shixun.shixun_service_configs.find_by(mirror_repository_id: service[:mirror_repository_id])
+ logger.info("########smr: #{smr}")
+ smr.update_attributes(service) if smr.present?
+ end
+ # 添加第二仓库(管理员权限)
+ if params[:is_secret_repository]
+ add_secret_repository if @shixun.shixun_secret_repository.blank?
+ else
+ # 如果有仓库,就要删
+ if @shixun.shixun_secret_repository&.repo_name
+ @shixun.shixun_secret_repository.lock!
+ GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path)
+ @shixun.shixun_secret_repository.destroy
end
end
+ end
+ rescue => e
+ uid_logger_error(e.message)
+ tip_exception("基本信息更新失败:#{e.message}")
+ end
+ end
+
+ # 实训权限设置
+ def update_permission_setting
+ # 查找需要增删的高校id
+ school_id = School.where(:name => params[:scope_partment]).pluck(:id)
+ old_school_ids = @shixun.shixun_schools.pluck(:school_id)
+ school_params = (school_id - old_school_ids).map{|id| {school_id: id}}
+ begin
+ ActiveRecord::Base.transaction do
+ @shixun.update_attributes!(shixun_params)
+ @shixun.shixun_schools.where.not(school_id: school_id).destroy_all if school_id.present?
+ @shixun.shixun_schools.create!(school_params)
+ end
+ rescue => e
+ uid_logger_error("实训权限设置失败--------#{e.message}")
+ tip_exception("实训权限设置失败")
+ end
+ end
- # 创建版本库
- repo_path = repo_namespace(User.current.login, @shixun.identifier)
- GitService.add_repository(repo_path: repo_path)
- # todo: 为什么保存的时候要去除后面的.git呢??
- @shixun.update_column(:repo_name, repo_path.split(".")[0])
+ # 实训学习页面设置
+ def update_learn_setting
+ begin
+ ActiveRecord::Base.transaction do
+ @shixun.update_attributes!(shixun_params)
+ end
+ rescue => e
+ uid_logger_error("实训学习页面设置失败--------#{e.message}")
+ tip_exception("实训学习页面设置失败")
+ end
+ end
- # 将实训标志为该云上实验室建立
- Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true)
- rescue Exception => e
- uid_logger_error(e.message)
- tip_exception("实训创建失败")
- raise ActiveRecord::Rollback
+ # Jupyter数据集
+ def get_data_sets
+ page = params[:page] || 1
+ limit = params[:limit] || 10
+ data_sets = @shixun.data_sets
+ @data_count = data_sets.count
+ @data_sets= data_sets.order("created_on desc").page(page).per(limit)
+ @absolute_folder = edu_setting('shixun_folder')
+ end
+
+ # 实训测试集附件
+ def upload_data_sets
+ begin
+
+ upload_file = params["file"]
+ raise "未上传文件" unless upload_file
+ folder = edu_setting('shixun_folder')
+ raise "存储目录未定义" unless folder.present?
+ rep_name = @shixun.data_sets.pluck(:filename).include?(upload_file.original_filename)
+ raise "文件名已经存在\"#{upload_file.original_filename}\", 请删除后再上传" if rep_name
+ tpm_folder = params[:identifier] # 这个是实训的identifier
+ save_path = File.join(folder, tpm_folder)
+ ext = file_ext(upload_file.original_filename)
+ local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
+ content_type = upload_file.content_type.presence || 'application/octet-stream'
+ disk_filename = local_path[save_path.size + 1, local_path.size]
+ @attachment = Attachment.where(disk_filename: disk_filename,
+ author_id: current_user.id).first
+ if @attachment.blank?
+ @attachment = Attachment.new
+ @attachment.filename = upload_file.original_filename
+ @attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
+ @attachment.filesize = upload_file.tempfile.size
+ @attachment.content_type = content_type
+ @attachment.digest = digest
+ @attachment.author_id = current_user.id
+ @attachment.disk_directory = tpm_folder
+ @attachment.container_id = @shixun.id
+ @attachment.container_type = @shixun.class.name
+ @attachment.attachtype = 2
+ @attachment.save!
+ else
+ logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
end
+ render_ok
+ rescue => e
+ uid_logger_error(e.message)
+ tip_exception(e.message)
+ end
+ end
+
+ # 多文件删除
+ def destroy_data_sets
+ files = Attachment.where(id: params[:id])
+ shixun_folder= edu_setting("shixun_folder")
+ begin
+ files.each do |file|
+ file_path = "#{shixun_folder}/#{file.relative_path_filename}"
+ delete_file(file_path)
+ end
+ files.destroy_all
+ render_ok
+ rescue => e
+ uid_logger_error(e.message)
+ tip_exception(e.message)
end
end
@@ -462,61 +558,6 @@ class ShixunsController < ApplicationController
tip_exception("申请失败")
end
- def update
- ActiveRecord::Base.transaction do
- begin
- @shixun.shixun_mirror_repositories.destroy_all
- if params[:main_type].present?
- ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => params[:main_type].to_i)
- end
- if params[:small_type].present?
- params[:small_type].each do |mirror|
- ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
- end
- end
- @shixun.update_attributes(shixun_params)
- @shixun.shixun_info.update_attributes(shixun_info_params)
- @shixun.shixun_schools.delete_all
- # scope_partment: 高校的名称
- if params[:scope_partment].present?
- arr = []
- ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq
- ids.each do |id|
- arr << { :school_id => id, :shixun_id => @shixun.id }
- end
- ShixunSchool.create!(arr)
- end
- # 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
- # 如果镜像改动了,则也需要更改
- mirror = @shixun.shixun_service_configs.map(&:mirror_repository_id).sort
- new_mirror = params[:shixun_service_configs].map{|c| c[:mirror_repository_id]}.sort
- if current_user.admin? || current_user.business? || (mirror != new_mirror)
- @shixun.shixun_service_configs.destroy_all
- service_config_params[:shixun_service_configs].each do |config|
- name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name
- # 不保存没有镜像的配置
- @shixun.shixun_service_configs.create!(config) if name.present?
- end
- end
- # 添加第二仓库
- if params[:is_secret_repository]
- add_secret_repository if @shixun.shixun_secret_repository.blank?
- else
- # 如果有仓库,就要删
- if @shixun.shixun_secret_repository&.repo_name
- @shixun.shixun_secret_repository.lock!
- GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path)
- @shixun.shixun_secret_repository.destroy
- end
- end
-
- rescue Exception => e
- uid_logger_error("实训保存失败--------#{e.message}")
- tip_exception("实训保存失败")
- raise ActiveRecord::Rollback
- end
- end
- end
# 永久关闭实训
def close
@@ -552,6 +593,8 @@ class ShixunsController < ApplicationController
# @evaluate_scirpt = @shixun.evaluate_script || "无"
end
+
+
# 获取脚本内容
def get_script_contents
mirrir_script = MirrorScript.find(params[:script_id])
@@ -708,154 +751,86 @@ class ShixunsController < ApplicationController
end
end
- # def shixun_exec
- # if is_shixun_opening?
- # tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
- # end
- # current_myshixun = @shixun.current_myshixun(current_user.id)
- #
- # min_challenges = @shixun.challenges.pluck(:id , :st)
- # # 因为读写分离有延迟,所以如果是重置来的请求可以先跳过,重置过来的params[:reset]为1
- # if current_myshixun && params[:reset] != "1"
- # games = current_myshixun.games
- # # 如果TPM和TPI的管卡数不相等或者关卡顺序错了,说明实训被极大的改动,需要重置,实训发布前打过的实训都需要重置
- # if is_shixun_reset?(games, min_challenges, current_myshixun)
- # # 这里页面弹框要收到 当前用户myshixun的identifier.
- # tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game")
- # end
- #
- #
- # if current_myshixun.repo_name.nil?
- # g = Gitlab.client
- # repo_name = g.project(current_myshixun.gpid).try(:path_with_namespace)
- # current_myshixun.update_column(:repo_name, repo_name)
- # end
- #
- # # 如果存在实训,则直接进入实训
- # # 如果实训允许跳关,传参params[:challenge_id]跳入具体的关卡
- # @current_task =
- # if params[:challenge_id]
- # game = games.where(challenge_id: params[:challenge_id]).take
- # if @shixun.task_pass || game.status != 3
- # game
- # else
- # current_myshixun.current_task(games)
- # end
- # else
- # current_myshixun.current_task(games)
- # end
- # else
- # # 如果未创建关卡一定不能开启实训,否则TPI没法找到当前的关卡
- # if @shixun.challenges_count == 0
- # tip_exception("开启实战前请先创建实训关卡")
- # end
- #
- # # 判断实训是否全为选择题
- # is_choice_type = (min_challenges.size == min_challenges.select{|challenge| challenge.last == 1}.count)
- # if !is_choice_type
- # commit = GitService.commits(repo_path: @repo_path).try(:first)
- # uid_logger("First comit########{commit}")
- # tip_exception("开启实战前请先在版本库中提交代码") if commit.blank?
- # commit_id = commit["id"]
- # end
- #
- # begin
- # ActiveRecord::Base.transaction do
- # begin
- # myshixun_identifier = generate_identifier Myshixun, 10
- # myshixun_params = {user_id: current_user.id, identifier: myshixun_identifier,
- # modify_time: @shixun.modify_time, reset_time: @shixun.reset_time,
- # onclick_time: Time.now, commit_id: commit_id}
- # @myshixun = @shixun.myshixuns.create!(myshixun_params)
- # # 其它创建关卡等操作
- # challenges = @shixun.challenges
- # # 之所以增加user_id是为了方便统计查询性能
- # game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at]
- # Game.bulk_insert(*game_attrs) do |worker|
- # base_attr = {myshixun_id: @myshixun.id, user_id: @myshixun.user_id}
- # challenges.each_with_index do |challenge, index|
- # status = (index == 0 ? 0 : 3)
- # game_identifier = generate_identifier(Game, 12)
- # worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now,
- # identifier: game_identifier, modify_time: challenge.modify_time))
- # end
- # end
- # @current_task = @myshixun.current_task(@myshixun.games)
- # rescue Exception => e
- # logger.error("------ActiveRecord::RecordInvalid: #{e.message}")
- # raise("ActiveRecord::RecordInvalid")
- # end
- # end
- # # 如果实训是纯选择题,则不需要去fork仓库以及中间层的相关操作了
- # ActiveRecord::Base.transaction do
- # unless is_choice_type
- # # fork仓库
- # cloud_bridge = edu_setting('cloud_bridge')
- # project_fork(@myshixun, @repo_path, current_user.login)
- # rep_url = Base64.urlsafe_encode64(repo_ip_url @repo_path)
- # uid_logger("start openGameInstance")
- # uri = "#{cloud_bridge}/bridge/game/openGameInstance"
- # logger.info("end openGameInstance")
- # params = {tpiID: "#{@myshixun.id}", tpmGitURL: rep_url, tpiRepoName: @myshixun.repo_name.split("/").last}
- # uid_logger("openGameInstance params is #{params}")
- # interface_post uri, params, 83, "实训云平台繁忙(繁忙等级:83)"
- # end
- # end
- # rescue Exception => e
- # logger.info("shixun_exec error: #{e.message}")
- # if e.message != "ActiveRecord::RecordInvalid"
- # logger.error("##########project_fork error #{e.message}")
- # @myshixun.destroy!
- # end
- # raise "实训云平台繁忙(繁忙等级:81)"
- # end
- # end
- # end
-
- # gameID 及实训ID
- # status: 0 , 1 申请过, 2,实训关卡路径未填, 3 实训标签未填, 4 实训未创建关卡
+ # jupyter开启挑战
+ def jupyter_exec
+ begin
+ if is_shixun_opening?
+ tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
+ end
+ current_myshixun = @shixun.current_myshixun(current_user.id)
+ if current_myshixun
+ @myshixun = current_myshixun
+ else
+ commit = GitService.commits(repo_path: @repo_path).try(:first)
+ uid_logger("First comit########{commit}")
+ tip_exception("开启挑战前,请先在Jupyter中填写内容") if commit.blank?
+ commit_id = commit["id"]
+ cloud_bridge = edu_setting('cloud_bridge')
+ myshixun_identifier = generate_identifier Myshixun, 10
+ ActiveRecord::Base.transaction do
+ @myshixun = @shixun.myshixuns.create!(user_id: current_user.id, identifier: myshixun_identifier,
+ modify_time: @shixun.modify_time, reset_time: @shixun.reset_time,
+ onclick_time: Time.now, commit_id: commit_id)
+ # fork仓库
+ project_fork(@myshixun, @repo_path, current_user.login)
+ rep_url = Base64.urlsafe_encode64(repo_ip_url @repo_path)
+ uri = "#{cloud_bridge}/bridge/game/openGameInstance"
+ params = {tpiID: "#{@myshixun.id}", tpmGitURL: rep_url, tpiRepoName: @myshixun.repo_name.split("/").last}
+ interface_post uri, params, 83, "实训云平台繁忙(繁忙等级:83)"
+ end
+ end
+ rescue => e
+ uid_logger_error(e.message)
+ tip_exception("#{e.message}")
+ end
+ end
+
def publish
@status = 0
@position = []
begin
- if @shixun.challenges.count == 0
- @status = 4
- else
- @shixun.challenges.each do |challenge|
- if challenge.challenge_tags.count == 0
- @status = 3
- @position << challenge.position
+ unless @shixun.is_jupyter?
+ if @shixun.challenges.count == 0
+ @status = 4
+ else
+ @shixun.challenges.each do |challenge|
+ if challenge.challenge_tags.count == 0
+ @status = 3
+ @position << challenge.position
+ end
end
- end
- unfinish_challenge = @shixun.challenges.where(:st => 0, :path => nil)
- if unfinish_challenge.count > 0 && !@shixun.is_choice_type?
- @status = 2
- @pos = []
- unfinish_challenge.each do |challenge|
- @pos << challenge.position
+ unfinish_challenge = @shixun.challenges.where(:st => 0, :path => nil)
+ if unfinish_challenge.count > 0 && !@shixun.is_choice_type?
+ @status = 2
+ @pos = []
+ unfinish_challenge.each do |challenge|
+ @pos << challenge.position
+ end
end
end
end
if @status == 0
- @shixun.update_attributes!(:status => 1)
- apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
- if apply && apply.status == 0
- @status = 0
- else
- ApplyAction.create(:container_type => "ApplyShixun", :container_id => @shixun.id, :user_id => current_user.id, :status => 0)
- #begin
- # status = Trustie::Sms.send(mobile: '18711011226', send_type:'publish_shixun' , name: '管理员')
- #rescue => e
- # Rails.logger.error "发送验证码出错: #{e}"
- #end
- @status = 1
- end
+ @shixun.update_attributes!(:status => 2)
end
rescue Exception => e
logger.error("pushlish game #{e}")
end
end
+ def apply_public
+ tip_exception(-1, "请先发布实训再申请公开") if @shixun.status != 2
+ ActiveRecord::Base.transaction do
+ @shixun.update_attributes!(public: 1)
+ apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
+ if apply && apply.status == 0
+ @status = 0
+ else
+ ApplyAction.create(:container_type => "ApplyShixun", :container_id => @shixun.id, :user_id => current_user.id, :status => 0)
+ end
+ end
+ normal_status(0, "申请成功")
+ end
+
# 设置私密版本库的在tpm中的目录
def set_secret_dir
raise("设置路径不能为空") if params[:secret_dir_path].blank?
@@ -993,14 +968,24 @@ class ShixunsController < ApplicationController
:disposition => 'attachment' #inline can open in browser
end
+ # 撤销申请公开
+ def cancel_apply_public
+ tip_exception("实训已经公开,无法撤销") if @shixun.public == 2
+ ActiveRecord::Base.transaction do
+ apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
+ if apply && apply.status == 0
+ apply.update_attributes!(status: 3)
+ apply.tidings&.destroy_all
+ end
+ @shixun.update_column(:public, 0)
+ end
+ normal_status(0, "成功撤销申请")
+ end
+
# 撤销发布
def cancel_publish
- tip_exception("实训已经发布,无法撤销") if @shixun.status == 2
- apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
- if apply && apply.status == 0
- apply.update_attribute(:status, 3)
- apply.tidings.destroy_all
- end
+ tip_exception("请先撤销申请公开,再撤销发布") if @shixun.public == 1
+ tip_exception("实训已经公开,无法撤销") if @shixun.public == 2
@shixun.update_column(:status, 0)
end
@@ -1021,10 +1006,9 @@ class ShixunsController < ApplicationController
private
def shixun_params
- raise("实训名称不能为空") if params[:shixun][:name].blank?
params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission,
:task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden,
- :hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission)
+ :hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission, :is_jupyter)
end
def validate_review_shixun_params
@@ -1033,8 +1017,6 @@ private
end
def shixun_info_params
- raise("实训描述不能为空") if params[:shixun_info][:description].blank?
- raise("评测脚本不能为空") if params[:shixun_info][:evaluate_script].blank?
params.require(:shixun_info).permit(:description, :evaluate_script)
end
@@ -1102,4 +1084,47 @@ private
ShixunSecretRepository.create!(repo_name: repo_path.split(".")[0], shixun_id: @shixun.id)
end
+ def file_save_to_local(save_path, temp_file, ext)
+ unless Dir.exists?(save_path)
+ FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
+ end
+
+ digest = md5_file(temp_file)
+ digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
+ local_file_path = File.join(save_path, digest) + ext
+ save_temp_file(temp_file, local_file_path)
+
+ [local_file_path, digest]
+ end
+
+ def save_temp_file(temp_file, save_file_path)
+ File.open(save_file_path, 'wb') do |f|
+ temp_file.rewind
+ while (buffer = temp_file.read(8192))
+ f.write(buffer)
+ end
+ end
+ end
+
+ def file_ext(file_name)
+ ext = ''
+ exts = file_name.split(".")
+ if exts.size > 1
+ ext = ".#{exts.last}"
+ end
+ ext
+ end
+
+ def delete_file(file_path)
+ File.delete(file_path) if File.exist?(file_path)
+ end
+
+ def md5_file(temp_file)
+ md5 = Digest::MD5.new
+ temp_file.rewind
+ while (buffer = temp_file.read(8192))
+ md5.update(buffer)
+ end
+ md5.hexdigest
+ end
end
diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb
index 637155a1a..d71ca8037 100644
--- a/app/controllers/student_works_controller.rb
+++ b/app/controllers/student_works_controller.rb
@@ -529,8 +529,8 @@ 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)
+ filename_ = "#{@user&.student_id}_#{@user&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf"
+ filename = filename_.strip.tr("+/", "-_")
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
@@ -559,6 +559,7 @@ class StudentWorksController < ApplicationController
if @work.work_status == 0
@work.work_status = 1
@work.commit_time = Time.now
+ @work.compelete_status = 1 if @homework.homework_type == "practice"
# 分组作业更新分组id
@work.group_id = @homework.max_group_id if @homework.homework_type == "group"
end
@@ -739,7 +740,8 @@ class StudentWorksController < ApplicationController
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
+ games = @work.myshixun.games.where(challenge_id: @homework.homework_challenge_settings.pluck(:challenge_id))
+ HomeworksService.new.update_myshixun_work_score @work, @work.myshixun, games, @homework, @homework.homework_challenge_settings
else
update_none_commit_work @work, @homework
end
@@ -877,6 +879,7 @@ class StudentWorksController < ApplicationController
def update_none_commit_work work, homework
if work.work_status == 0
work.work_status = 1
+ work.compelete_status = 1
work.commit_time = homework.end_time
work.update_time = Time.now
end
diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb
index 0cd57ecc8..6a9438a79 100644
--- a/app/controllers/subjects_controller.rb
+++ b/app/controllers/subjects_controller.rb
@@ -204,7 +204,7 @@ class SubjectsController < ApplicationController
def add_shixun_to_stage
identifier = generate_identifier Shixun, 8
ActiveRecord::Base.transaction do
- @shixun = Shixun.create!(name: params[:name], user_id: current_user.id, identifier: identifier)
+ @shixun = Shixun.create!(name: params[:name], user_id: current_user.id, identifier: identifier, is_jupyter: params[:is_jupyter])
# 添加合作者
@shixun.shixun_members.create!(user_id: current_user.id, role: 1)
# 创建长字段
diff --git a/app/controllers/users/authentication_applies_controller.rb b/app/controllers/users/authentication_applies_controller.rb
index 3c43be553..bf5aa0d40 100644
--- a/app/controllers/users/authentication_applies_controller.rb
+++ b/app/controllers/users/authentication_applies_controller.rb
@@ -1,5 +1,6 @@
class Users::AuthenticationAppliesController < Users::BaseAccountController
before_action :private_user_resources!
+ before_action :check_account, only: [:create]
def create
Users::ApplyAuthenticationService.call(observed_user, create_params)
diff --git a/app/controllers/users/professional_auth_applies_controller.rb b/app/controllers/users/professional_auth_applies_controller.rb
index d1ee70953..9fc8e73db 100644
--- a/app/controllers/users/professional_auth_applies_controller.rb
+++ b/app/controllers/users/professional_auth_applies_controller.rb
@@ -1,5 +1,6 @@
class Users::ProfessionalAuthAppliesController < Users::BaseAccountController
before_action :private_user_resources!
+ before_action :check_account, only: [:create]
def create
Users::ApplyProfessionalAuthService.call(observed_user, create_params)
diff --git a/app/controllers/weapps/courses_controller.rb b/app/controllers/weapps/courses_controller.rb
index 1ccefcbe2..cb3c195d6 100644
--- a/app/controllers/weapps/courses_controller.rb
+++ b/app/controllers/weapps/courses_controller.rb
@@ -6,7 +6,7 @@ class Weapps::CoursesController < Weapps::BaseController
before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers]
def create
- return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher?
+ # return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher?
course = Course.new(tea_id: current_user.id)
Weapps::CreateCourseService.call(course, course_params)
render_ok
@@ -93,8 +93,8 @@ class Weapps::CoursesController < Weapps::BaseController
end
if course_group_id.present?
- course_group = CourseGroup.find(course_group_id) if course_group_id != 0
- @students = @students.where(course_group_id: course_group&.id.to_i)
+ @course_group = CourseGroup.find(course_group_id) if course_group_id != 0
+ @students = @students.where(course_group_id: @course_group&.id.to_i)
end
@students_count = @students.size
@@ -107,7 +107,7 @@ class Weapps::CoursesController < Weapps::BaseController
# 批量修改角色
def change_member_roles
@course = current_course
- tip_exception("请至少选择一个角色") if params[:roles].blank?
+ tip_exception("请至少选择一个角色") if params[:roles].reject(&:blank?).blank?
tip_exception("不能具有老师、助教两种角色") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR")
params[:user_ids].each do |user_id|
@@ -150,13 +150,13 @@ class Weapps::CoursesController < Weapps::BaseController
new_student.is_active = 0 if correspond_teacher_exist
new_student.save!
- CourseAddStudentCreateWorksJob.perform_later(@course.id, user_id)
+ CourseAddStudentCreateWorksJob.perform_later(@course.id, [user_id])
# StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
elsif !params[:roles].include?("STUDENT") && student_member.present?
# 删除学生身份时激活老师身份
teacher_member.update_attributes!(is_active: 1) if student_member.is_active && teacher_member.present?
student_member.destroy!
- CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, user_id)
+ CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [user_id])
# CourseDeleteStudentNotifyJob.perform_later(@course.id, [params[:user_id]], current_user.id)
elsif params[:roles].include?("STUDENT") && student_member.present? && !params[:roles].include?("PROFESSOR") && !params[:roles].include?("ASSISTANT_PROFESSOR")
# 学生身份存在且学生没有教师身份时更新is_active
@@ -167,6 +167,15 @@ class Weapps::CoursesController < Weapps::BaseController
normal_status(0, "修改成功")
end
+ # 分班列表
+ def course_groups
+ @course_groups = @course.course_groups
+ @course_groups = @course_groups.where("name like ?", "%#{params[:search]}%") unless params[:search].blank?
+ @all_group_count = @course_groups.size
+ @teachers = @course.teachers.includes(:user, :teacher_course_groups) if @user_course_identity < Course::NORMAL
+ @current_group_id = @course.students.where(user_id: current_user.id).take&.course_group_id if @user_course_identity == Course::STUDENT
+ end
+
private
def course_params
diff --git a/app/controllers/weapps/homework_commons_controller.rb b/app/controllers/weapps/homework_commons_controller.rb
index 00d2ce926..ebadd00b0 100644
--- a/app/controllers/weapps/homework_commons_controller.rb
+++ b/app/controllers/weapps/homework_commons_controller.rb
@@ -6,8 +6,9 @@ class Weapps::HomeworkCommonsController < Weapps::BaseController
def update_settings
begin
# 课堂结束后不能再更新
- if @course.is_end
- UpdateHomeworkSettingService.call(@homework, publish_params)
+ unless @course.is_end
+ UpdateHomeworkPublishSettingService.call(@homework, publish_params)
+ render_ok
else
tip_exception("课堂已结束不能再更新")
end
@@ -31,7 +32,7 @@ class Weapps::HomeworkCommonsController < Weapps::BaseController
end
def publish_params
- params.permit(:unified_setting, :publish_time, :end_time, group_settings: [])
+ params.permit(:unified_setting, :publish_time, :end_time, group_settings: [:publish_time, :end_time, group_id: []])
end
end
\ No newline at end of file
diff --git a/app/forms/users/update_password_form.rb b/app/forms/users/update_password_form.rb
index 4da341839..db674384c 100644
--- a/app/forms/users/update_password_form.rb
+++ b/app/forms/users/update_password_form.rb
@@ -3,5 +3,5 @@ class Users::UpdatePasswordForm
attr_accessor :password, :old_password
- validates :password, presence: true
+ validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位密码,支持字母数字和符号" }
end
\ No newline at end of file
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index be633b2cc..cabf8d244 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -210,7 +210,7 @@ module ApplicationHelper
# 普通/分组 作业作品状态数组
def student_work_status homework, user_id, course, work
status = []
- homework_setting = homework.homework_group_setting user_id
+ homework_setting = homework.homework_group_setting user_id, true
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
late_time = homework.late_time || course.end_date
diff --git a/app/helpers/challenges_helper.rb b/app/helpers/challenges_helper.rb
index c6d05817d..fc0101dff 100644
--- a/app/helpers/challenges_helper.rb
+++ b/app/helpers/challenges_helper.rb
@@ -4,4 +4,7 @@ module ChallengesHelper
str.gsub(/\A\r/, "\r\r")
end
+
+
+
end
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index 31e1ecf45..ca76ee953 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -22,21 +22,21 @@ module ExportHelper
end
end
- shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user)
+ shixun_homeworks = shixun_homeworks&.includes(:student_works)
common_homeworks = homeworks.search_homework_type(1) #全部普通作业
common_titles = common_homeworks.pluck(:name)+ ["总得分"]
- common_homeworks = common_homeworks&.includes(score_student_works: :user)
+ common_homeworks = common_homeworks&.includes(:student_works)
group_homeworks = homeworks.search_homework_type(3) #全部分组作业
group_titles = group_homeworks.pluck(:name)+ ["总得分"]
- group_homeworks = group_homeworks&.includes(score_student_works: :user)
+ group_homeworks = group_homeworks&.includes(:student_works)
task_titles = tasks.pluck(:name) + ["总得分"]
- tasks = tasks&.includes(user: :user_extension, score_graduation_works: :user)
+ tasks = tasks&.includes(:graduation_works)
exercise_titles = exercises.pluck(:exercise_name) + ["总得分"]
- exercises = exercises&.includes(user: :user_extension, score_exercise_users: :user)
+ exercises = exercises&.includes(:exercise_users)
total_user_score_array = [] #学生总成绩集合
@@ -67,7 +67,7 @@ module ExportHelper
#实训作业
if shixun_homeworks.size > 0
shixun_homeworks.each do |s|
- user_student_work = s.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
+ user_student_work = s.student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work.nil?
h_score = 0.0 #该作业的得分为0
else
@@ -82,7 +82,7 @@ module ExportHelper
#普通作业
if common_homeworks.size > 0
common_homeworks.each do |c|
- user_student_work_1 = c.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
+ user_student_work_1 = c.student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_1.nil?
h_score_1 = 0.0 #该作业的得分为0
else
@@ -97,7 +97,7 @@ module ExportHelper
#分组作业
if group_homeworks.size > 0
group_homeworks.each do |g|
- user_student_work_3 = g.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
+ user_student_work_3 = g.student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_3.nil?
h_score_3 = 0.0 #该作业的得分为0
else
@@ -112,7 +112,7 @@ module ExportHelper
#毕设作业
if tasks.size > 0
tasks.each do |task|
- graduation_work = task.score_graduation_works.select{|work| work.user_id == user.id}.first
+ graduation_work = task.graduation_works.select{|work| work.user_id == user.id}.first
if graduation_work.nil?
t_score = 0.0
else
@@ -127,7 +127,7 @@ module ExportHelper
#试卷
if exercises.size > 0
exercises.each do |ex|
- exercise_work = ex.score_exercise_users.select{|work| work.user_id == user.id}.first
+ exercise_work = ex.exercise_users.select{|work| work.user_id == user.id}.first
if exercise_work.nil?
e_score = 0.0
else
@@ -163,9 +163,12 @@ module ExportHelper
count_2 = common_homeworks.size
count_3 = group_homeworks.size
count_4 = tasks.size
+
+ all_user_ids = all_members.pluck(:user_id)
+
#实训作业
shixun_homeworks.each_with_index do |s,index|
- all_student_works = s.score_student_works #该实训题的全部用户回答
+ all_student_works = s.student_works.where(user_id: all_user_ids) #该实训题的全部用户回答
title_no = index.to_i + 1
student_work_to_xlsx(all_student_works,s)
shixun_work_display_name = format_sheet_name (title_no.to_s + "." + s.name).strip.first(30)
@@ -175,7 +178,7 @@ module ExportHelper
#普通作业
common_homeworks.each_with_index do |c,index|
- all_student_works = c.score_student_works #当前用户的对该作业的回答
+ all_student_works = c.student_works.where(user_id: all_user_ids) #当前用户的对该作业的回答
title_no = count_1 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
@@ -187,7 +190,7 @@ module ExportHelper
#分组作业
group_homeworks.each_with_index do |c,index|
- all_student_works = c.score_student_works #当前用户的对该作业的回答
+ all_student_works = c.student_works.where(user_id: all_user_ids) #当前用户的对该作业的回答
title_no = count_1 + count_2 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
@@ -197,7 +200,7 @@ module ExportHelper
#毕设任务
tasks.each_with_index do |c,index|
- all_student_works = c.score_graduation_works #当前用户的对该作业的回答
+ all_student_works = c.graduation_works.where(user_id: all_user_ids) #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + index.to_i + 1
graduation_work_to_xlsx(all_student_works,c,current_user)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
@@ -207,7 +210,7 @@ module ExportHelper
#试卷的导出
exercises.each_with_index do |c,index|
- all_student_works = c.score_exercise_users #当前用户的对该作业的回答
+ all_student_works = c.exercise_users.where(user_id: all_user_ids) #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1
get_export_users(c,course,all_student_works)
work_name = format_sheet_name (title_no.to_s + "." + c.exercise_name).strip.first(30)
@@ -426,7 +429,7 @@ module ExportHelper
end
else #实训题
shixun = homework.shixuns.take
- shixun_head_cells = %w(完成情况 通关时间 学员在EduCoder做实训花费的时间 总评测次数 获得经验值 关卡得分)
+ shixun_head_cells = %w(截止前完成关卡 通关时间 学员在EduCoder做实训花费的时间 总评测次数 获得经验值 关卡得分)
eff_boolean = homework.work_efficiency
if eff_boolean
eff_score_cell = ["效率分"]
@@ -452,16 +455,18 @@ module ExportHelper
course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name)
w_5 = course_name.present? ? course_name : "--"
#0: 未提交, 1 按时提交, 2 延迟提交
- if w.work_status == 0
- w_6 = "未提交"
- elsif w.work_status == 1
- w_6 = "按时提交"
- elsif w.work_status == 2
- w_6 = "延迟提交"
+ if w.compelete_status == 0
+ w_6 = "未开启"
+ elsif w.compelete_status == 1
+ w_6 = "未通关"
+ elsif w.compelete_status == 2
+ w_6 = "按时通关"
+ elsif w.compelete_status == 3
+ w_6 = "迟交通关"
else
w_6 = "--"
end
- w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges_count.to_s
+ w_7 = myshixun&.time_passed_count(homework.homework_group_setting(w.user_id)&.end_time).to_i.to_s+"/"+shixun.challenges_count.to_s
w_8 = myshixun ? myshixun.try(:passed_time).to_s == "--" ? "--" : format_time(myshixun.try(:passed_time)) : "--" # 通关时间
w_9 = myshixun ? (myshixun.try(:passed_count).to_i > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时
w_10 = myshixun ? myshixun.output_times : 0 #评测次数
@@ -478,7 +483,7 @@ module ExportHelper
w_14 = nil
end
w_15 = w.work_score.nil? ? "--" : w.work_score.round(1)
- w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间"
+ w_16 = w.update_time ? format_time(w.update_time) : "--"
myshixun_complete = myshixun && myshixun.status == 1
w_17 = myshixun_complete && w.cost_time ? (game_spend_time w.cost_time) : "未完成"
teacher_comment = w.shixun_work_comments.select{|comment| comment.challenge_id == 0}.first
diff --git a/app/helpers/homework_commons_helper.rb b/app/helpers/homework_commons_helper.rb
index efc14dc5e..f962288eb 100644
--- a/app/helpers/homework_commons_helper.rb
+++ b/app/helpers/homework_commons_helper.rb
@@ -24,40 +24,37 @@ module HomeworkCommonsHelper
time = course.end_date.strftime("%Y-%m-%d")
time_status = 6
else
- if homework_common.end_time && homework_common.end_time < Time.now && homework_common.allow_late &&
- (homework_common.late_time.nil? || homework_common.late_time > Time.now)
- status << "补交中"
- end
-
ho_detail_manual = homework_common.homework_detail_manual
if ho_detail_manual
# 作业状态大于“提交”状态时,不用考虑分班权限
if ho_detail_manual.comment_status > 1
- case ho_detail_manual.comment_status
- when 3
- if ho_detail_manual.evaluation_end && ho_detail_manual.evaluation_end > Time.now
- status << "匿评中"
- time = "提交剩余时间:" + how_much_time(ho_detail_manual.evaluation_end)
- time_status = 3
- end
- when 4
- if ho_detail_manual.appeal_time && ho_detail_manual.appeal_time > Time.now
- status << "申诉中"
- time = "申诉剩余时间:" + how_much_time(ho_detail_manual.appeal_time)
- time_status = 4
- end
- when 2, 5, 6
- status << "评阅中"
- time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
- time_status = 5
- end
-
- # 如果还在补交阶段则显示补交结束时间
if homework_common.end_time && homework_common.end_time < Time.now && homework_common.allow_late &&
- homework_common.late_time && homework_common.late_time > Time.now
+ (homework_common.late_time.nil? || homework_common.late_time > Time.now)
+ status << "补交中"
time = "补交剩余时间:" + how_much_time(homework_common.late_time)
time_status = 2
end
+
+ case ho_detail_manual.comment_status
+ when 3
+ if ho_detail_manual.evaluation_end && ho_detail_manual.evaluation_end > Time.now
+ status << "匿评中"
+ time = "匿评剩余时间:" + how_much_time(ho_detail_manual.evaluation_end)
+ time_status = 3
+ end
+ when 4
+ if ho_detail_manual.appeal_time && ho_detail_manual.appeal_time > Time.now
+ status << "申诉中"
+ time = "申诉剩余时间:" + how_much_time(ho_detail_manual.appeal_time)
+ time_status = 4
+ end
+ else
+ if status.blank?
+ status << "已截止"
+ time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
+ time_status = 5
+ end
+ end
else
# member = course.course_members.find_by(user_id: user.id, is_active: 1)
# teacher_course_groups = member.try(:teacher_course_groups)
@@ -65,25 +62,28 @@ module HomeworkCommonsHelper
# 作业统一设置、游客身份、超级管理员、分班权限不限的老师身份
if homework_common.unified_setting || identity > Course::STUDENT || identity == Course::ADMIN ||
- (identity < Course::STUDENT && teacher_course_groups.blank?)
+ (identity < Course::STUDENT && teacher_course_groups.blank?)
case ho_detail_manual.comment_status
- when 0
- status << "未发布"
- time = homework_common.publish_time.present? ? "将于 #{format_time(homework_common.publish_time)} 发布" : "创建于#{time_from_now(homework_common.created_at)}"
- time_status = 0
- when 1
- if homework_common.end_time && homework_common.end_time >= Time.now
- status << "提交中"
- time = "提交剩余时间:" + how_much_time(homework_common.end_time)
- time_status = 1
- elsif homework_common.end_time && homework_common.end_time < Time.now
+ when 0
+ status << "未发布"
+ time = homework_common.publish_time.present? ? "将于 #{format_time(homework_common.publish_time)} 发布" : "创建于#{time_from_now(homework_common.created_at)}"
+ time_status = 0
+ when 1
+ if homework_common.end_time && homework_common.end_time >= Time.now
+ status << "提交中"
+ time = "提交剩余时间:" + how_much_time(homework_common.end_time)
+ time_status = 1
+ elsif homework_common.end_time && homework_common.end_time < Time.now
+ if homework_common.allow_late && (homework_common.late_time.nil? || homework_common.late_time >= Time.now)
+ status << "补交中"
+ time = "补交剩余时间:" + how_much_time(homework_common.late_time)
+ time_status = 2
+ else
+ status << "已截止"
+ time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
time_status = 5
- if homework_common.allow_late && (homework_common.late_time.nil? || homework_common.late_time >= Time.now)
- time = "补交剩余时间:" + how_much_time(homework_common.late_time)
- time_status = 2
- end
- status << "评阅中"
end
+ end
end
else
# 未分班的学生始终显示“未发布”(按理不会来到这个判断)
@@ -99,9 +99,9 @@ module HomeworkCommonsHelper
else
# 多个分班权限的取最小publish_time,最大end_time
min_publish_time = homework_common.homework_group_settings.where.not(publish_time: nil).
- where(course_group_id: teacher_course_groups.pluck(:course_group_id)).pluck(:publish_time).min
+ where(course_group_id: teacher_course_groups.pluck(:course_group_id)).pluck(:publish_time).min
max_end_time = homework_common.homework_group_settings.where.not(end_time: nil).
- where(course_group_id: teacher_course_groups.pluck(:course_group_id)).pluck(:end_time).max
+ where(course_group_id: teacher_course_groups.pluck(:course_group_id)).pluck(:end_time).max
end
if min_publish_time.nil?
@@ -116,24 +116,22 @@ module HomeworkCommonsHelper
status << "提交中"
time = "提交剩余时间:" + how_much_time(max_end_time)
time_status = 1
- elsif homework_common.allow_late && (homework_common.late_time.nil? || homework_common.late_time >= Time.now)
- status << "评阅中"
- time = "补交剩余时间:" + how_much_time(homework_common.late_time)
- time_status = 2
else
- status << "评阅中"
- time = ""
+ status << "已截止"
+ time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
time_status = 5
end
end
end
- status << "未开启补交" if !homework_common.allow_late && time_status != 0
+ status << "未开启补交" if !homework_common.allow_late && time_status == 1
end
end
end
- # 如果作业状态都没有的话,在课堂结束前,都显示评阅中
+ # 如果作业状态都没有的话,在课堂结束前,都显示已截止
if status.blank?
- status << "评阅中"
+ status << "已截止"
+ time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
+ time_status = 5
end
result[:status] = status
result[:time] = time
@@ -144,7 +142,7 @@ module HomeworkCommonsHelper
# 阶段剩余时间
def left_time homework, user_id
- setting = homework.homework_group_setting(user_id)
+ setting = homework.homework_group_setting(user_id, true)
if setting.publish_time && setting.publish_time < Time.now
if setting.end_time > Time.now
status = "剩余提交时间"
@@ -224,10 +222,10 @@ module HomeworkCommonsHelper
# 作品状态
def practice_homework_status homework, member
- [{id: 3, name: "未通关", count: homework.un_complete_count(member)},
- {id: 4, name: "已通关", count: homework.complete_count(member)},
- {id: 1, name: "按时完成", count: homework.finished_count(member)},
- {id: 2, name: "延时完成", count: homework.delay_finished_count(member)}]
+ [{id: 0, name: "未开启", count: homework.compelete_status_count(member, 0)},
+ {id: 1, name: "未通关", count: homework.compelete_status_count(member, 1)},
+ {id: 2, name: "按时通关", count: homework.compelete_status_count(member, 2)},
+ {id: 3, name: "迟交通关", count: homework.compelete_status_count(member, 3)}]
end
# 作品状态
diff --git a/app/helpers/shixuns_helper.rb b/app/helpers/shixuns_helper.rb
index b41750bed..655a7ed04 100644
--- a/app/helpers/shixuns_helper.rb
+++ b/app/helpers/shixuns_helper.rb
@@ -27,6 +27,17 @@ module ShixunsHelper
end
end
+ def shixun_public_status shixun
+ case shixun.try(:public)
+ when 0,nil
+ "未公开"
+ when 1
+ "待审核"
+ when 2
+ "已公开"
+ end
+ end
+
# 已完成实训所获得的经验值
def myshixun_exp myshixun
score = 0
diff --git a/app/jobs/sync_trustie_job.rb b/app/jobs/sync_trustie_job.rb
index 33df5b529..dec09debc 100644
--- a/app/jobs/sync_trustie_job.rb
+++ b/app/jobs/sync_trustie_job.rb
@@ -17,10 +17,17 @@ class SyncTrustieJob < ApplicationJob
"number": count
}
uri = URI.parse(url)
+ # http = Net::HTTP.new(uri.hostname, uri.port)
+
if api_host
http = Net::HTTP.new(uri.hostname, uri.port)
- http.send_request('PUT', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'})
- Rails.logger.info("#######_________response__sync__end_____#########")
+
+ if api_host.include?("https://")
+ http.use_ssl = true
+ end
+
+ response = http.send_request('PUT', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'})
+ Rails.logger.info("#######_________response__sync__end_____#########{response.body}")
end
end
end
diff --git a/app/libs/custom_regexp.rb b/app/libs/custom_regexp.rb
index 2a2a99384..2980f2ed2 100644
--- a/app/libs/custom_regexp.rb
+++ b/app/libs/custom_regexp.rb
@@ -3,4 +3,5 @@ module CustomRegexp
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
+ PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
end
\ No newline at end of file
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 37884e40b..ac051428f 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -21,18 +21,31 @@ class Attachment < ApplicationRecord
scope :contains_only_project, -> { where(container_type: 'Project') }
scope :contains_course_and_project, -> { contains_only_course.or(contains_only_project) }
scope :mine, -> (author_id) { where(author_id: author_id) }
- scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type) }
+ scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type, :container_type, :container_id) }
scope :search_by_container, -> (ids) {where(container_id: ids)}
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
validates_length_of :description, maximum: 100
+ DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
+
def diskfile
File.join(File.join(Rails.root, "files"), disk_directory.to_s, disk_filename.to_s)
end
+ def relative_path_filename
+ File.join(disk_directory.to_s, disk_filename.to_s)
+ end
+
def title
- filename
+ title = filename
+ if container && container.is_a?(StudentWork) && author_id != User.current.id
+ course = container&.homework_common&.course
+ unless User.current.teacher_of_course?(course)
+ title = "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{DCODES.sample(8).join}" + File.extname(filename)
+ end
+ end
+ title
end
def downloads_count
diff --git a/app/models/competition.rb b/app/models/competition.rb
index 23fa268ec..96fd14c1c 100644
--- a/app/models/competition.rb
+++ b/app/models/competition.rb
@@ -165,7 +165,7 @@ class Competition < ApplicationRecord
def get_module_name type
case type
- when 'home' then '首页'
+ when 'home' then '赛制介绍'
when 'enroll' then '报名'
when 'inform' then '通知公告'
when 'chart' then '排行榜'
diff --git a/app/models/game.rb b/app/models/game.rb
index d82392a59..062ad15cc 100644
--- a/app/models/game.rb
+++ b/app/models/game.rb
@@ -119,6 +119,12 @@ class Game < ApplicationRecord
# self.outputs.pluck(:query_index).first
#end
+ # 是否查看了答案(通关的是否在通关前看的答案)
+ def view_answer
+ answer_exists = Grade.where("container_type = 'Answer' and container_id = #{self.id} and created_at < '#{self.end_time}'").exists?
+ answer_open != 0 ? (status == 2 ? answer_exists : true) : false
+ end
+
# 用户关卡得分
def get_user_final_score
diff --git a/app/models/hack.rb b/app/models/hack.rb
index 80724d3d4..506cd4942 100644
--- a/app/models/hack.rb
+++ b/app/models/hack.rb
@@ -3,6 +3,8 @@ class Hack < ApplicationRecord
# diffcult: 难度 1:简单;2:中等; 3:困难
# 编程题
validates_length_of :name, maximum: 60
+ validates :description, presence: { message: "描述不能为空" }
+ validates :name, presence: { message: "名称不能为空" }
# 测试集
has_many :hack_sets, ->{order("position asc")}, :dependent => :destroy
# 代码
@@ -39,4 +41,9 @@ class Hack < ApplicationRecord
hack_sets.first&.input
end
+ # 管理员
+ def manager?(user)
+ user_id == user.id || user.admin_or_business?
+ end
+
end
diff --git a/app/models/hack_set.rb b/app/models/hack_set.rb
index 5dab862b5..6afe05663 100644
--- a/app/models/hack_set.rb
+++ b/app/models/hack_set.rb
@@ -1,6 +1,7 @@
class HackSet < ApplicationRecord
- validates :input, presence: { message: "测试集输入不能为空" }
+ #validates :input, presence: { message: "测试集输入不能为空" }
validates :output, presence: { message: "测试集输出不能为空" }
+ validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同"
# 编程题测试集
belongs_to :hack
end
diff --git a/app/models/hack_user_code.rb b/app/models/hack_user_code.rb
index 072fd4e31..eee394e39 100644
--- a/app/models/hack_user_code.rb
+++ b/app/models/hack_user_code.rb
@@ -1,6 +1,7 @@
class HackUserCode < ApplicationRecord
# 用户编程题的信息
belongs_to :hack
+ belongs_to :hack_user_lastest_code
scope :created_order, ->{ order("created_at desc")}
end
diff --git a/app/models/hack_user_lastest_code.rb b/app/models/hack_user_lastest_code.rb
index b4a707603..830f16dde 100644
--- a/app/models/hack_user_lastest_code.rb
+++ b/app/models/hack_user_lastest_code.rb
@@ -8,7 +8,7 @@ class HackUserLastestCode < ApplicationRecord
belongs_to :user
has_many :hack_user_codes, dependent: :destroy
has_one :hack_user_debug
- scope :mine, ->(author_id){ find_by(user_id: author_id) }
+ scope :mine, ->(author_id){ where(user_id: author_id).first }
scope :mine_hack, ->(author_id){ where(user_id: author_id) }
scope :passed, -> {where(status: 1)}
diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb
index d37650c37..58b52bdd2 100644
--- a/app/models/homework_common.rb
+++ b/app/models/homework_common.rb
@@ -108,7 +108,7 @@ class HomeworkCommon < ApplicationRecord
# 是否在补交阶段内
def late_duration
- homework_setting = self.homework_group_setting(User.current.id)
+ homework_setting = self.homework_group_setting(User.current.id, true)
!course.is_end && self.publish_time && self.publish_time < Time.now && homework_setting.end_time &&
homework_setting.end_time < Time.now && self.allow_late && (self.late_time.nil? || self.late_time > Time.now)
end
@@ -119,7 +119,7 @@ class HomeworkCommon < ApplicationRecord
if self.course.is_end || (self.allow_late && self.late_time && self.late_time < Time.now)
status = true
elsif !self.allow_late
- homework_setting = self.homework_group_setting(User.current.id)
+ homework_setting = self.homework_group_setting(User.current.id, true)
status = homework_setting.end_time && homework_setting.end_time < Time.now
end
status
@@ -241,14 +241,8 @@ class HomeworkCommon < ApplicationRecord
self.teacher_works(member).delay_finished.count
end
- # 未通关数
- def un_complete_count member
- teacher_works(member).count - complete_count(member)
- end
-
- # 通关数
- def complete_count member
- Myshixun.where(id: self.teacher_works(member).pluck(:myshixun_id), status: 1).count
+ def compelete_status_count member, status
+ teacher_works(member).where(compelete_status: status).count
end
# 分组作业的最大分组id
@@ -257,12 +251,13 @@ class HomeworkCommon < ApplicationRecord
end
# 作业的分班设置时间
- def homework_group_setting user_id
+ def homework_group_setting user_id, current_user=false
if unified_setting
homework_setting = self
else
- member = course.course_member(user_id)
- group_setting = self.homework_group_settings.find_by_course_group_id(member.try(:course_group_id))
+ # 当前用户是从course_member中取,否则是从学生中取(双重身份的原因)
+ member = current_user ? course.course_member(user_id) : course.students.find_by(user_id: user_id)
+ group_setting = self.homework_group_settings.select{ |setting| setting.course_group_id == member.try(:course_group_id)}.first
homework_setting = group_setting.present? ? group_setting : self
end
homework_setting
diff --git a/app/models/item_analysis.rb b/app/models/item_analysis.rb
new file mode 100644
index 000000000..8f6e71302
--- /dev/null
+++ b/app/models/item_analysis.rb
@@ -0,0 +1,3 @@
+class ItemAnalysis < ApplicationRecord
+ belongs_to :item_bank
+end
diff --git a/app/models/item_bank.rb b/app/models/item_bank.rb
new file mode 100644
index 000000000..8078a55e0
--- /dev/null
+++ b/app/models/item_bank.rb
@@ -0,0 +1,11 @@
+class ItemBank < ApplicationRecord
+ # difficulty: 1 简单 2 适中 3 困难
+ # item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程
+ enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 }
+
+ belongs_to :user
+
+ has_one :item_analysis, dependent: :destroy
+ has_many :item_choices, dependent: :destroy
+ has_many :item_baskets, dependent: :destroy
+end
diff --git a/app/models/item_basket.rb b/app/models/item_basket.rb
new file mode 100644
index 000000000..d736d9bc0
--- /dev/null
+++ b/app/models/item_basket.rb
@@ -0,0 +1,4 @@
+class ItemBasket < ApplicationRecord
+ belongs_to :item_bank
+ belongs_to :user
+end
diff --git a/app/models/item_choice.rb b/app/models/item_choice.rb
new file mode 100644
index 000000000..ccc35698e
--- /dev/null
+++ b/app/models/item_choice.rb
@@ -0,0 +1,3 @@
+class ItemChoice < ApplicationRecord
+ belongs_to :item_bank
+end
diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb
index 2ba86ed90..dab2f6f39 100644
--- a/app/models/laboratory.rb
+++ b/app/models/laboratory.rb
@@ -38,12 +38,20 @@ class Laboratory < ApplicationRecord
find_by_identifier(subdomain)
end
- def self.current=(laboratory)
- Thread.current[:current_laboratory] = laboratory
+ # def self.current=(laboratory)
+ # Thread.current[:current_laboratory] = laboratory
+ # end
+ #
+ # def self.current
+ # Thread.current[:current_laboratory] ||= Laboratory.find(1)
+ # end
+
+ def self.current=(user)
+ RequestStore.store[:current_laboratory] = user
end
def self.current
- Thread.current[:current_laboratory] ||= Laboratory.find(1)
+ RequestStore.store[:current_laboratory] ||= User.anonymous
end
def shixuns
diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb
index 4eacaf460..e53b54cd3 100644
--- a/app/models/laboratory_setting.rb
+++ b/app/models/laboratory_setting.rb
@@ -67,6 +67,7 @@ class LaboratorySetting < ApplicationRecord
{ 'name' => '在线竞赛', 'link' => '/competitions', 'hidden' => false },
{ 'name' => '教学案例', 'link' => '/moop_cases', 'hidden' => false },
{ 'name' => '交流问答', 'link' => '/forums', 'hidden' => false },
+ { 'name' => '开发者社区', 'link' => '/problems', 'hidden' => false },
],
footer: nil
}
diff --git a/app/models/myshixun.rb b/app/models/myshixun.rb
index 54dcf9011..1a89c755e 100644
--- a/app/models/myshixun.rb
+++ b/app/models/myshixun.rb
@@ -28,6 +28,11 @@ class Myshixun < ApplicationRecord
"#{self.repo_name}.git"
end
+
+ def repo_save_path
+ self.repo_name.split('/').last
+ end
+
def is_complete?
self.status == 1
end
@@ -83,9 +88,15 @@ class Myshixun < ApplicationRecord
self.games.select{|game| game.status == 2}.size
end
- # 查看答案的关卡数
+ # 指定时间前完成的关卡数
+ def time_passed_count time
+ time.present? ? self.games.select{|game| game.status == 2 && game.end_time < time}.size : 0
+ end
+
+ # 查看答案的关卡数,只统计通关前看的关卡
def view_answer_count
- self.games.select{|game| game.status == 2 && game.answer_open != 0}.size
+ answer_ids = user.grades.joins("join games on grades.container_id = games.id").where("container_type = 'Answer' and games.status=2 and games.end_time > grades.created_at").pluck(:container_id)
+ self.games.select{|game| game.status == 2 && game.answer_open != 0 && answer_ids.include?(game.id)}.size
end
# 通关时间
diff --git a/app/models/searchable/shixun.rb b/app/models/searchable/shixun.rb
index c574ecb1d..359b8b4dc 100644
--- a/app/models/searchable/shixun.rb
+++ b/app/models/searchable/shixun.rb
@@ -52,7 +52,8 @@ module Searchable::Shixun
challenges_count: challenges_count,
study_count: myshixuns_count,
star: averge_star,
- level: shixun_level
+ level: shixun_level,
+ is_jupyter: is_jupyter
}
end
diff --git a/app/models/shixun.rb b/app/models/shixun.rb
index 0f9842739..de014f87b 100644
--- a/app/models/shixun.rb
+++ b/app/models/shixun.rb
@@ -3,12 +3,14 @@ class Shixun < ApplicationRecord
attr_accessor :page_no #管理员页面 实训配置更新状态时,需要接受page_no参数
# status: 0:编辑 1:申请发布 2:正式发布 3:关闭 -1:软删除
+ # public: 0:未公开 1:申请公开 2:公开
# hide_code: 隐藏代码窗口
# code_hidden: 隐藏代码目录
# task_pass: 跳关
# webssh 0:不开启webssh;1:开启练习模式; 2:开启评测模式
# trainee 实训的难度
# vnc: VCN实训是否用于评测
+ validates_presence_of :name, message: "实训名称不能为空"
has_many :challenges, -> {order("challenges.position asc")}, dependent: :destroy
has_many :challenge_tags, through: :challenges
has_many :myshixuns, :dependent => :destroy
@@ -54,6 +56,8 @@ class Shixun < ApplicationRecord
has_many :laboratory_shixuns, dependent: :destroy
belongs_to :laboratory, optional: true
+ # Jupyter数据集,附件
+ has_many :data_sets, ->{where(attachtype: 2)}, class_name: 'Attachment', as: :container, dependent: :destroy
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
"%#{keyword}%", "%#{keyword}%") }
@@ -76,6 +80,7 @@ class Shixun < ApplicationRecord
scope :published_closed, lambda{ where(status: [2, 3]) }
scope :none_closed, lambda{ where(status: [0, 1, 2]) }
scope :unhidden, lambda{ where(hidden: 0, status: 2) }
+ scope :publiced, lambda{ where(public: 2) }
scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) }
scope :find_by_ids,lambda{|k| where(id:k)}
@@ -280,7 +285,7 @@ class Shixun < ApplicationRecord
end
def has_manager?(user)
- return true if user.admin?
+ return true if user.admin? || user.business?
shixun_members.where(role: [1, 2]).exists?(user_id: user.id)
end
diff --git a/app/models/shixun_info.rb b/app/models/shixun_info.rb
index 74a49412e..321b4c44a 100644
--- a/app/models/shixun_info.rb
+++ b/app/models/shixun_info.rb
@@ -1,8 +1,6 @@
class ShixunInfo < ApplicationRecord
belongs_to :shixun
validates_uniqueness_of :shixun_id
- validates_presence_of :shixun_id
-
after_commit :create_diff_record
private
diff --git a/app/models/shixun_mirror_repository.rb b/app/models/shixun_mirror_repository.rb
index 9376aac0b..841be6bb2 100644
--- a/app/models/shixun_mirror_repository.rb
+++ b/app/models/shixun_mirror_repository.rb
@@ -2,4 +2,5 @@ class ShixunMirrorRepository < ApplicationRecord
belongs_to :shixun
belongs_to :mirror_repository
validates_uniqueness_of :shixun_id, :scope => :mirror_repository_id
+ validates_presence_of :shixun_id, :mirror_repository_id
end
diff --git a/app/models/shixun_service_config.rb b/app/models/shixun_service_config.rb
index 6d106fc07..4dda75a25 100644
--- a/app/models/shixun_service_config.rb
+++ b/app/models/shixun_service_config.rb
@@ -1,4 +1,6 @@
class ShixunServiceConfig < ApplicationRecord
belongs_to :shixun
belongs_to :mirror_repository
+
+ validates_presence_of :shixun_id, :mirror_repository_id
end
diff --git a/app/models/student_work.rb b/app/models/student_work.rb
index d4f372823..4da23a30f 100644
--- a/app/models/student_work.rb
+++ b/app/models/student_work.rb
@@ -123,6 +123,26 @@ class StudentWork < ApplicationRecord
end
end
+ # 实训作业的作品状态 0:未提交,1:未通关,2:按时通关(提交截止前通关),3:迟交通关(提交截止-补交截止间通关)
+ def real_work_status
+ status = work_status
+ if status > 0 && myshixun
+ if myshixun.status != 1
+ status = 1
+ else
+ homework_end_time = homework_common.homework_group_setting(user_id)&.end_time
+ if homework_end_time.present? && homework_end_time > myshixun.passed_time
+ status = 2
+ elsif homework_end_time.present? && homework_common.allow_late && homework_common.late_time > myshixun.passed_time
+ status = 3
+ else
+ status = 1
+ end
+ end
+ end
+ status
+ end
+
# 更新作品成绩
def set_work_score
if work_status > 0 && homework_common && !self.ultimate_score
diff --git a/app/models/user.rb b/app/models/user.rb
index 0a16b7aa3..f25ecc4b8 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -546,12 +546,20 @@ class User < ApplicationRecord
mail.present?
end
+ # def self.current=(user)
+ # Thread.current[:current_user] = user
+ # end
+ #
+ # def self.current
+ # Thread.current[:current_user] ||= User.anonymous
+ # end
+
def self.current=(user)
- Thread.current[:current_user] = user
+ RequestStore.store[:current_user] = user
end
def self.current
- Thread.current[:current_user] ||= User.anonymous
+ RequestStore.store[:current_user] ||= User.anonymous
end
def self.anonymous
diff --git a/app/queries/admins/school_query.rb b/app/queries/admins/school_query.rb
index 888cded97..3206f0858 100644
--- a/app/queries/admins/school_query.rb
+++ b/app/queries/admins/school_query.rb
@@ -17,6 +17,7 @@ class Admins::SchoolQuery < ApplicationQuery
if keyword
schools = schools.where('schools.name LIKE ?', "%#{keyword}%")
end
+ schools = schools.left_joins(:user_extensions).select('schools.*, IFNULL(count(user_extensions.user_id),0) users_count').group('schools.id')
custom_sort schools, params[:sort_by], params[:sort_direction]
end
end
\ No newline at end of file
diff --git a/app/queries/admins/shixun_modify_record_query.rb b/app/queries/admins/shixun_modify_record_query.rb
new file mode 100644
index 000000000..227e2f4c2
--- /dev/null
+++ b/app/queries/admins/shixun_modify_record_query.rb
@@ -0,0 +1,33 @@
+class Admins::ShixunModifyRecordQuery < ApplicationQuery
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ if params[:user_name].blank? || params[:date].blank?
+ records = DiffRecord.none
+ else
+ records = DiffRecord.joins(:user).where("concat(users.lastname, users.firstname) like ?", "%#{params[:user_name].strip}%")
+ if time_range.present?
+ records = records.where(created_at: time_range)
+ end
+ end
+ records.order("diff_records.created_at desc")
+ end
+
+ private
+
+ def time_range
+ @_time_range ||= begin
+ case params[:date]
+ when 'weekly' then 1.weeks.ago..Time.now
+ when 'monthly' then 1.months.ago..Time.now
+ when 'quarterly' then 3.months.ago..Time.now
+ when 'yearly' then 1.years.ago..Time.now
+ else ''
+ end
+ end
+ end
+end
diff --git a/app/queries/admins/shixun_query.rb b/app/queries/admins/shixun_query.rb
index 0d726f267..0f8523599 100644
--- a/app/queries/admins/shixun_query.rb
+++ b/app/queries/admins/shixun_query.rb
@@ -21,7 +21,17 @@ class Admins::ShixunQuery < ApplicationQuery
[0,1,2,3]
end
+ public =
+ case params[:public]
+ when "editing" then [0]
+ when "pending" then [1]
+ when "processed" then [2]
+ else
+ [0,1,2]
+ end
+
all_shixuns = all_shixuns.where(status: status) if status.present?
+ all_shixuns = all_shixuns.where(public: public) if public.present?
if params[:tag].present?
all_shixuns = all_shixuns.joins(:mirror_repositories).where("mirror_repositories.id = ?",params[:tag].to_i)
diff --git a/app/queries/admins/shixun_settings_query.rb b/app/queries/admins/shixun_settings_query.rb
index ab871b58e..377e7bf60 100644
--- a/app/queries/admins/shixun_settings_query.rb
+++ b/app/queries/admins/shixun_settings_query.rb
@@ -51,6 +51,7 @@ class Admins::ShixunSettingsQuery < ApplicationQuery
all_shixuns = all_shixuns.where(homepage_show: params[:homepage_show]) if params[:homepage_show]
all_shixuns = all_shixuns.where(task_pass: params[:task_pass]) if params[:task_pass]
all_shixuns = all_shixuns.where(code_hidden: params[:code_hidden]) if params[:code_hidden]
+ all_shixuns = all_shixuns.where(vip: params[:vip]) if params[:vip]
custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
end
diff --git a/app/services/admins/check_shixun_mirrors_service.rb b/app/services/admins/check_shixun_mirrors_service.rb
index 8334df485..4aa0af4cf 100644
--- a/app/services/admins/check_shixun_mirrors_service.rb
+++ b/app/services/admins/check_shixun_mirrors_service.rb
@@ -75,13 +75,12 @@ class Admins::CheckShixunMirrorsService < ApplicationService
def bridge_images
@_bridge_images ||= begin
- url = EduSetting.get('cloud_bridge')
+ url = "#{EduSetting.get('cloud_bridge')}/bridge/docker/images"
res = Faraday.get(url)
- res_body = JSON.parse(res.body)
+ res = JSON.parse(res.body)
+ raise Error, '拉取镜像信息异常' if res && res['code'] != 0
- raise Error, '拉取镜像信息异常' if res_body && res_body['code'].to_i != 0
-
- res_body
+ res
rescue => e
Rails.logger.error("get response failed ! #{e.message}")
raise Error, '实训云平台繁忙(繁忙等级:84)'
diff --git a/app/services/admins/shixun_auths/agree_apply_service.rb b/app/services/admins/shixun_auths/agree_apply_service.rb
index 4734e03bb..b8875cf09 100644
--- a/app/services/admins/shixun_auths/agree_apply_service.rb
+++ b/app/services/admins/shixun_auths/agree_apply_service.rb
@@ -10,7 +10,7 @@ class Admins::ShixunAuths::AgreeApplyService < ApplicationService
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
- shixun.update!(status: 2, publish_time: Time.now)
+ shixun.update!(public: 2, publish_time: Time.now)
# 奖励金币、经验
reward_grade_and_experience!
diff --git a/app/services/admins/shixun_auths/refuse_apply_service.rb b/app/services/admins/shixun_auths/refuse_apply_service.rb
index 49416a2b0..76d420e53 100644
--- a/app/services/admins/shixun_auths/refuse_apply_service.rb
+++ b/app/services/admins/shixun_auths/refuse_apply_service.rb
@@ -10,7 +10,7 @@ class Admins::ShixunAuths::RefuseApplyService < ApplicationService
def call
ActiveRecord::Base.transaction do
- shixun.update!(status: 0)
+ shixun.update!(public: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
diff --git a/app/services/create_diff_record_service.rb b/app/services/create_diff_record_service.rb
index 8365404e2..3943af1ae 100644
--- a/app/services/create_diff_record_service.rb
+++ b/app/services/create_diff_record_service.rb
@@ -25,21 +25,23 @@ class CreateDiffRecordService < ApplicationService
index = 0
fragment_size = 1
Diffy::Diff.new(before, after).each do |line|
- unless line =~ /^[\+-]/
- if arr.empty? && index < fragment_size
- content += line
- index += 1
- else
- index = 0
- arr << line
- arr.shift if arr.size > fragment_size
+ unless line.include?("\\ 文件尾没有 newline 字符")
+ unless line =~ /^[\+-]/
+ if arr.empty? && index < fragment_size
+ content += line
+ index += 1
+ else
+ index = 0
+ arr << line
+ arr.shift if arr.size > fragment_size
+ end
+ next
end
- next
- end
- content += arr.join('') if arr.present?
- content += line
- arr.clear
+ content += arr.join('') if arr.present?
+ content += line
+ arr.clear
+ end
end
content
end
diff --git a/app/services/git_service.rb b/app/services/git_service.rb
index 076f62920..544e830a4 100644
--- a/app/services/git_service.rb
+++ b/app/services/git_service.rb
@@ -45,4 +45,4 @@ class GitService
end
end
-end
\ No newline at end of file
+end
diff --git a/app/services/homeworks_service.rb b/app/services/homeworks_service.rb
index 0dc814c89..487a79bfe 100644
--- a/app/services/homeworks_service.rb
+++ b/app/services/homeworks_service.rb
@@ -322,11 +322,16 @@ class HomeworksService
work.efficiency = format("%.2f", efficiency)
if myshixun_endtime <= homework_end_or_late_time
- work.compelete_status = myshixun_endtime < setting_time.publish_time ? 2 : 1
+ # 2是按时通关, 3是迟交通关
+ work.compelete_status = myshixun_endtime < setting_time.end_time ? 2 : 3
# 如果作业的最大效率值有变更则更新所有作品的效率分
homework.update_column("max_efficiency", work.efficiency) if homework.work_efficiency && homework.max_efficiency < work.efficiency
+ else
+ work.compelete_status = 1 # 未通关
end
+ else
+ work.compelete_status = 1 # 未通关
end
work.late_penalty = work.work_status == 2 ? homework.late_penalty : 0
@@ -346,7 +351,7 @@ class HomeworksService
work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score
#logger.info("#############work_score: #{score}")
work.calculation_time = Time.now
- work.save!
+ work.save(validate: false)
end
end
end
\ No newline at end of file
diff --git a/app/services/jupyter_service.rb b/app/services/jupyter_service.rb
new file mode 100644
index 000000000..0f5af6cb8
--- /dev/null
+++ b/app/services/jupyter_service.rb
@@ -0,0 +1,195 @@
+#coding=utf-8
+
+module JupyterService
+
+ def _open_shixun_jupyter(shixun)
+ if shixun.is_jupyter?
+ shixun_tomcat = edu_setting('cloud_bridge')
+ uri = "#{shixun_tomcat}/bridge/jupyter/get"
+ tpiID = "tpm#{shixun.id}"
+ mount = shixun.data_sets.present?
+ params = {tpiID: tpiID, identifier: shixun.identifier, needMount: mount,
+ :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"}
+
+ logger.info "test_juypter: uri->#{uri}, params->#{params}"
+ res = uri_post uri, params
+ if res && res['code'].to_i != 0
+ raise("实训云平台繁忙(繁忙等级:99)")
+ end
+
+ logger.info "test_juypter: #{res}"
+
+ @shixun_jupyter_port = res['port']
+
+ "#{jupyter_service(res['port'])}/notebooks/data/workspace/myshixun_#{tpiID}/01.ipynb"
+ end
+ end
+
+ def jupyter_url_with_shixun(shixun)
+ #打开tpm - juypter接口
+ _open_shixun_jupyter(shixun)
+ end
+
+ def jupyter_port_with_shixun(shixun)
+ if @shixun_jupyter_port.to_i <=0
+ _open_shixun_jupyter(shixun)
+ end
+ @shixun_jupyter_port
+ end
+
+
+ def _open_game_jupyter(myshixun)
+ ## 打开tpi
+ shixun = myshixun.shixun
+
+ if shixun.is_jupyter?
+ shixun_tomcat = edu_setting('cloud_bridge')
+ uri = "#{shixun_tomcat}/bridge/jupyter/get"
+
+ tpiID = myshixun.id
+ mount = myshixun.shixun.data_sets.present?
+ params = {tpiID: tpiID, identifier: shixun.identifier, myshixunIdentifier: myshixun.identifier, needMount: mount,
+ :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"}
+ res = uri_post uri, params
+
+ logger.info "test_juypter: #{res}"
+
+ if res && res['code'].to_i != 0
+ raise("实训云平台繁忙(繁忙等级:99)")
+ end
+
+ @game_jupyter_port = res['port']
+
+ repo_save_path = myshixun.repo_save_path
+
+ "#{jupyter_service(res['port'])}/notebooks/data/workspace/myshixun_#{tpiID}/#{repo_save_path}/01.ipynb"
+ end
+ end
+
+
+ def jupyter_url_with_game(myshixun)
+ _open_game_jupyter(myshixun)
+ end
+
+ def jupyter_port_with_game(myshixun)
+ if @game_jupyter_port.to_i <=0
+ _open_game_jupyter(myshixun)
+ end
+ @game_jupyter_port
+ end
+
+ def jupyter_save_with_shixun(shixun,jupyter_port)
+ author_name = current_user.real_name
+ author_email = current_user.git_mail
+ message = "User submitted"
+
+ tpiID = "tpm#{shixun.id}"
+
+ src_url = "#{jupyter_service(jupyter_port)}/nbconvert/notebook/data/workspace/myshixun_#{tpiID}/01.ipynb?download=true"
+
+ response = Faraday.get(src_url)
+
+ if response.status.to_i != 200
+ raise("获取文件内容失败:#{response.status}")
+ end
+
+ content = response.body.force_encoding('utf-8')
+
+ c = GitService.update_file(repo_path: shixun.repo_path,
+ file_path: "01.ipynb",
+ message: message,
+ content: content,
+ author_name: author_name,
+ author_email: author_email)
+
+ return c.size
+ end
+
+ def jupyter_save_with_game(myshixun,jupyter_port)
+ author_name = current_user.real_name
+ author_email = current_user.git_mail
+ message = "User submitted"
+
+ tpiID = myshixun.id
+
+ repo_save_path = myshixun.repo_save_path
+ src_url = "#{jupyter_service(jupyter_port)}/nbconvert/notebook/data/workspace/myshixun_#{tpiID}/#{repo_save_path}/01.ipynb?download=true"
+ response = Faraday.get(src_url)
+
+ if response.status.to_i != 200
+ raise("获取文件内容失败:#{response.status}")
+ end
+
+ content = response.body.force_encoding('utf-8')
+
+ c = GitService.update_file(repo_path: myshixun.repo_path,
+ file_path: "01.ipynb",
+ message: message,
+ content: content,
+ author_name: author_name,
+ author_email: author_email)
+
+ return c.size
+ end
+
+
+ ##重置jupyter环境
+ def jupyter_tpi_reset(myshixun)
+ jupyter_delete_tpi(myshixun)
+ url = jupyter_url_with_game(myshixun)
+ port = jupyter_port_with_game(myshixun)
+ {url: url, port: port}
+ end
+
+ ## 重置tpm环境
+ def jupyter_tpm_reset(shixun)
+ jupyter_delete_tpm(shixun)
+
+ url = jupyter_url_with_shixun(shixun)
+ port = jupyter_port_with_shixun(shixun)
+
+ {url: url, port: port}
+ end
+
+
+
+ # 删除pod
+ def jupyter_delete_tpi(myshixun)
+ myshixun_id = myshixun.id
+ digest = myshixun.identifier + edu_setting('bridge_secret_key')
+ digest_key = Digest::SHA1.hexdigest("#{digest}")
+ begin
+ shixun_tomcat = edu_setting('cloud_bridge')
+ uri = "#{shixun_tomcat}/bridge/jupyter/delete"
+ Rails.logger.info("#{current_user} => cloese_jupyter digest is #{digest}")
+ params = {:tpiID => myshixun_id, :digestKey => digest_key, :identifier => myshixun.identifier}
+ res = uri_post uri, params
+ if res && res['code'].to_i != 0
+ raise("实训云平台繁忙(繁忙等级:110)")
+ end
+ end
+ end
+
+
+ def jupyter_delete_tpm(shixun)
+ tpiID = "tpm#{shixun.id}"
+ digest = shixun.identifier + edu_setting('bridge_secret_key')
+ digest_key = Digest::SHA1.hexdigest("#{digest}")
+ begin
+ shixun_tomcat = edu_setting('cloud_bridge')
+ uri = "#{shixun_tomcat}/bridge/jupyter/delete"
+ Rails.logger.info("#{current_user} => cloese_jupyter digest is #{digest}")
+ params = {:tpiID => tpiID, :digestKey => digest_key, :identifier => shixun.identifier}
+ res = uri_post uri, params
+ if res && res['code'].to_i != 0
+ raise("实训云平台繁忙(繁忙等级:110)")
+ end
+ end
+ end
+
+ def jupyter_service jupyter_port
+ edu_setting('jupyter_service').gsub("PORT", jupyter_port)
+ end
+
+
+end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 5eb11f398..a45875e07 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -30,7 +30,6 @@ class SearchService < ApplicationService
model_options = {
includes: modal_name.searchable_includes
}
- model_options.deep_merge!(where: { status: 2 }) if modal_name == Shixun
model_options.deep_merge!(extra_options)
model_options.deep_merge!(default_options)
@@ -40,7 +39,7 @@ class SearchService < ApplicationService
def extra_options
case params[:type].to_s.strip
when 'shixun' then
- { where: { id: Laboratory.current.shixuns.pluck(:id) } }
+ { where: { id: Laboratory.current.shixuns.where(public: 2, status: 2, fork_from: nil).or(Laboratory.current.shixuns.where(status: 2, id: User.current.shixuns)).pluck(:id) } }
when 'subject' then
{ where: { id: Laboratory.current.subjects.pluck(:id) } }
when 'course' then
diff --git a/app/services/shixun_search_service.rb b/app/services/shixun_search_service.rb
index 580208dfe..f5af69179 100644
--- a/app/services/shixun_search_service.rb
+++ b/app/services/shixun_search_service.rb
@@ -25,7 +25,7 @@ class ShixunSearchService < ApplicationService
else
none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id)
- @shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0)
+ @shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0, status: 2, public: 2).or(@shixuns.where(id: User.current.shixuns))
end
end
@@ -38,6 +38,7 @@ class ShixunSearchService < ApplicationService
@shixuns = @shixuns.where(trainee: params[:diff])
end
+ Rails.logger.info("search_shixun_ids: #{@shixuns.pluck(:id)}")
Shixun.search(keyword, search_options)
end
diff --git a/app/services/shixuns/create_shixun_service.rb b/app/services/shixuns/create_shixun_service.rb
new file mode 100644
index 000000000..c85455901
--- /dev/null
+++ b/app/services/shixuns/create_shixun_service.rb
@@ -0,0 +1,115 @@
+class CreateShixunService < ApplicationService
+ attr_reader :user, :params, :permit_params
+
+ def initialize(user, permit_params, params)
+ @user = user
+ @params = params
+ @permit_params = permit_params
+ end
+
+ def call
+ shixun = Shixun.new(permit_params)
+ identifier = Util::UUID.generate_identifier(Shixun, 8)
+ shixun.identifier= identifier
+ shixun.user_id = user.id
+ main_mirror = MirrorRepository.find params[:main_type]
+ sub_mirrors = MirrorRepository.where(id: params[:sub_type])
+ begin
+ ActiveRecord::Base.transaction do
+ shixun.save!
+ # 获取脚本内容
+ shixun_script = get_shixun_script(shixun, main_mirror, sub_mirrors)
+ # 创建额外信息
+ ShixunInfo.create!(shixun_id: shixun.id, evaluate_script: shixun_script, description: params[:description])
+ # 创建合作者
+ shixun.shixun_members.create!(user_id: user.id, role: 1)
+ # 创建镜像
+ ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id)
+ # 创建主服务配置
+ ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id)
+ # 创建子镜像相关数据(实训镜像关联表,子镜像服务配置)
+ sub_mirrors.each do |sub|
+ ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id)
+ # 实训子镜像服务配置
+ name = sub.name #查看镜像是否有名称,如果没有名称就不用服务配置
+ ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) if name.present?
+ end
+ # 创建版本库
+ repo_path = repo_namespace(user.login, shixun.identifier)
+ GitService.add_repository(repo_path: repo_path)
+ shixun.update_column(:repo_name, repo_path.split(".")[0])
+ # 如果是云上实验室,创建相关记录
+ if !Laboratory.current.main_site?
+ Laboratory.current.laboratory_shixuns.create!(shixun: shixun, ownership: true)
+ end
+ # 如果是jupyter,先创建一个目录,为了挂载(因为后续数据集,开启Pod后环境在没销毁前,你上传数据集是挂载不上目录的,因此要先创建目录,方便中间层挂载)
+ if shixun.is_jupyter?
+ folder = EduSetting.get('shixun_folder')
+ path = "#{folder}/#{identifier}"
+ FileUtils.mkdir_p(path, :mode => 0777) unless File.directory?(path)
+ end
+ return shixun
+ end
+ rescue => e
+ Rails.logger.error("shixun_create_error: #{e.message}")
+ raise("创建实训失败!")
+ end
+ end
+
+ private
+
+ def get_shixun_script shixun, main_mirror, sub_mirrors
+ if !shixun.is_jupyter?
+ mirror = main_mirror.mirror_scripts
+ if main_mirror.blank?
+ modify_shixun_script shixun, mirror.first&.(:script)
+ else
+ sub_name = sub_mirrors.pluck(:type_name)
+ if main_mirror.type_name == "Java" && sub_name.include?("Mysql")
+ mirror.last.try(:script)
+ else
+ shixun_script = mirror.first&.script
+ modify_shixun_script shixun, shixun_script
+ end
+ end
+ end
+ end
+
+ def modify_shixun_script shixun, script
+ if script.present?
+ source_class_name = []
+ challenge_program_name = []
+ shixun.challenges.map(&:exec_path).each do |exec_path|
+ challenge_program_name << "\"#{exec_path}\""
+ if shixun.main_mirror_name == "Java"
+ if exec_path.nil? || exec_path.split("src/")[1].nil?
+ source = "\"\""
+ else
+ source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\""
+ end
+ logger.info("----source: #{source}")
+ source_class_name << source.gsub("/", ".") if source.present?
+ elsif shixun.main_mirror_name.try(:first) == "C#"
+ if exec_path.nil? || exec_path.split(".")[1].nil?
+ source = "\"\""
+ else
+ source = "\"#{exec_path.split(".")[0]}.exe\""
+ end
+ source_class_name << source if source.present?
+ end
+ end
+ script = if script.include?("sourceClassName") && script.include?("challengeProgramName")
+ script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)")
+ else
+ script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)")
+ end
+ end
+ return script
+ end
+
+ # 版本库目录空间
+ def repo_namespace(user, shixun_identifier)
+ "#{user}/#{shixun_identifier}.git"
+ end
+
+end
diff --git a/app/services/subjects/copy_subject_service.rb b/app/services/subjects/copy_subject_service.rb
index 94157dc7b..f44191fda 100644
--- a/app/services/subjects/copy_subject_service.rb
+++ b/app/services/subjects/copy_subject_service.rb
@@ -60,7 +60,7 @@ class Subjects::CopySubjectService < ApplicationService
shixun = stage_shixun.shixun
to_shixun = Shixun.new
to_shixun.attributes = shixun.attributes.dup.except('id', 'user_id', 'identifier', 'homepage_show',
- 'use_scope', 'averge_star', 'myshixuns_count', 'challenges_count')
+ 'use_scope', 'averge_star', 'myshixuns_count', 'challenges_count', "public")
to_shixun.identifier = Util::UUID.generate_identifier(Shixun, 8)
to_shixun.user_id = user.id
if laboratory
diff --git a/app/services/update_homework_publish_setting_service.rb b/app/services/update_homework_publish_setting_service.rb
index 00d618522..69a68b613 100644
--- a/app/services/update_homework_publish_setting_service.rb
+++ b/app/services/update_homework_publish_setting_service.rb
@@ -1,4 +1,4 @@
-class UpdateHomeworkSettingService < ApplicationService
+class UpdateHomeworkPublishSettingService < ApplicationService
attr_reader :homework, :params
def initialize(homework, params)
@@ -7,6 +7,7 @@ class UpdateHomeworkSettingService < ApplicationService
end
def call
+ puts params
course = homework.course
# 作业未发布时,unified_setting参数不能为空
if homework.publish_time.nil? || homework.publish_time > Time.now
@@ -37,9 +38,9 @@ class UpdateHomeworkSettingService < ApplicationService
tip_exception("分班id不能为空") if setting[:group_id].length == 0
tip_exception("发布时间不能为空") if setting[:publish_time].blank?
tip_exception("截止时间不能为空") if setting[:end_time].blank?
- tip_exception("发布时间不能早于当前时间") if setting[:publish_time] <= strf_time(Time.now)
- tip_exception("截止时间不能早于当前时间") if setting[:end_time] <= strf_time(Time.now)
- tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time]
+ tip_exception("发布时间不能早于当前时间") if setting[:publish_time].to_time <= Time.now
+ tip_exception("截止时间不能早于当前时间") if setting[:end_time].to_time <= Time.now
+ tip_exception("截止时间不能早于发布时间") if setting[:publish_time].to_time > setting[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
course.end_date.present? && setting[:end_time] > course.end_date.end_of_day
@@ -74,15 +75,15 @@ class UpdateHomeworkSettingService < ApplicationService
else
if homework.end_time > Time.now && homework.unified_setting
tip_exception("截止时间不能为空") if params[:end_time].blank?
- tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
+ tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if
- course.end_date.present? && params[:end_time] > strf_time(course.end_date.end_of_day)
+ course.end_date.present? && params[:end_time].to_time > course.end_date.end_of_day
homework.end_time = params[:end_time]
elsif !homework.unified_setting
homework.create_homework_group_settings
- tip_exception("分班发布设置不能为空") if params[:group_settings].blank?
+ tip_exception("分班发布设置不能为空") if params[:group_settings].reject(&:blank?).blank?
params[:group_settings].each do |setting|
group_settings = HomeworkGroupSetting.where(homework_common_id: homework.id, course_group_id: setting[:group_id])
@@ -90,12 +91,12 @@ class UpdateHomeworkSettingService < ApplicationService
tip_exception("发布时间不能为空") if setting[:publish_time].blank?
tip_exception("截止时间不能为空") if setting[:end_time].blank?
# 如果该发布规则 没有已发布的分班则需判断发布时间
- tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0
+ tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time].to_time <= Time.now && group_settings.group_published.count == 0
- 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("截止时间不能早于等于当前时间") if setting[:end_time].to_time <= Time.now && group_settings.none_end.count > 0
+ tip_exception("截止时间不能早于发布时间") if setting[:publish_time].to_time > setting[:end_time].to_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)
+ course.end_date.present? && setting[:end_time].to_time > course.end_date.end_of_day
group_settings.none_published.update_all(publish_time: setting[:publish_time])
group_settings.none_end.update_all(end_time: setting[:end_time])
@@ -107,4 +108,9 @@ class UpdateHomeworkSettingService < ApplicationService
homework.save!
HomeworkCommonPushNotifyJob.perform_later(homework.id, publish_group_ids) if send_tiding
end
+
+ private
+ def tip_exception(status = -1, message)
+ raise Educoder::TipException.new(status, message)
+ end
end
\ No newline at end of file
diff --git a/app/services/users/shixun_service.rb b/app/services/users/shixun_service.rb
index ef399ce8c..279d147f4 100644
--- a/app/services/users/shixun_service.rb
+++ b/app/services/users/shixun_service.rb
@@ -44,7 +44,7 @@ class Users::ShixunService
def user_policy_filter(relations)
# 只有自己或者管理员才有过滤筛选及查看全部状态下实训功能
if self_or_admin?
- relations = relations.where.not(status: -1)
+ relations = relations.where.not(status: -1).where(hidden: false)
status_filter(relations)
else
relations.where(status: [2, 3], hidden: false)
diff --git a/app/services/users/subject_service.rb b/app/services/users/subject_service.rb
index 8a4fdce3b..53ff3f4b9 100644
--- a/app/services/users/subject_service.rb
+++ b/app/services/users/subject_service.rb
@@ -35,7 +35,7 @@ class Users::SubjectService
def user_policy_filter(relations)
# 只有自己或者管理员才有过滤筛选及查看全部状态下实训功能
if self_or_admin?
- status_filter(relations)
+ status_filter(relations.unhidden)
else
relations.where(status: 2, hidden: false)
end
diff --git a/app/templates/shared/main.css b/app/templates/shared/main.css
index 09d295421..704246b74 100644
--- a/app/templates/shared/main.css
+++ b/app/templates/shared/main.css
@@ -557,7 +557,6 @@ a.user_orangebg_btn{background-color:#FF6800;color: #fff;}
a.user_greybg_btn{background-color:#747A7F;color: #fff;}
/*.user_white_btn{border: 1px solid #ffffff;color: #ffffff!important;}*/
-
.pointer{cursor: pointer}
.cdefault{cursor: default}
diff --git a/app/views/admins/courses/shared/_list.html.erb b/app/views/admins/courses/shared/_list.html.erb
index 633616462..4105c8153 100644
--- a/app/views/admins/courses/shared/_list.html.erb
+++ b/app/views/admins/courses/shared/_list.html.erb
@@ -1,30 +1,31 @@
+ 序号 |
ID |
课堂名称 |
- 成员 |
+ 成员 |
资源 |
普通作业 |
分组作业 |
实训作业 |
试卷 |
- 评测次数 |
+ 评测次数 |
私有 |
状态 |
单位 |
创建者 |
<%= sort_tag('创建时间', name: 'created_at', path: admins_courses_path) %> |
首页 |
- 邮件通知 |
- 操作 |
+ 邮件通知 |
+ 操作 |
<% if courses.present? %>
- <% courses.each do |course| %>
+ <% courses.each_with_index do |course, index| %>
- <%= render 'admins/courses/shared/td', course: course %>
+ <%= render partial: 'admins/courses/shared/td', locals: {course: course, no: index} %>
<% end %>
<% else %>
diff --git a/app/views/admins/courses/shared/_td.html.erb b/app/views/admins/courses/shared/_td.html.erb
index 1d2da2a33..51cc4b199 100644
--- a/app/views/admins/courses/shared/_td.html.erb
+++ b/app/views/admins/courses/shared/_td.html.erb
@@ -1,3 +1,4 @@
+<%= list_index_no((params[:page] || 1).to_i, no) %> |
<%= course.id %> |
<%= link_to(course.name, "/courses/#{course.id}", target: '_blank') %>
diff --git a/app/views/admins/courses/update.js.erb b/app/views/admins/courses/update.js.erb
index 1278a2e1f..983ac22f0 100644
--- a/app/views/admins/courses/update.js.erb
+++ b/app/views/admins/courses/update.js.erb
@@ -1 +1,3 @@
-$("#course-item-<%= @course.id %>").html("<%= j render partial: "admins/courses/shared/td",locals: {course: @course} %>")
\ No newline at end of file
+var index = $("#course-item-<%= @course.id %>").children(":first").html();
+$("#course-item-<%= @course.id %>").html("<%= j render partial: "admins/courses/shared/td",locals: {course: @course, no: 1} %>");
+$("#course-item-<%= @course.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/customers/shared/_list.html.erb b/app/views/admins/customers/shared/_list.html.erb
index 0ba5638cb..6f84db4e5 100644
--- a/app/views/admins/customers/shared/_list.html.erb
+++ b/app/views/admins/customers/shared/_list.html.erb
@@ -1,15 +1,17 @@
- 客户名称 |
+ 序号 |
+ 客户名称 |
<%= sort_tag('添加时间', name: 'created_at', path: admins_partner_customers_path(current_partner)) %> |
操作 |
<% if customers.present? %>
- <% customers.each do |customer| %>
+ <% customers.each_with_index do |customer, index| %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= customer.school&.name %> |
<%= customer.created_at&.strftime('%Y-%m-%d %H:%M') %> |
diff --git a/app/views/admins/daily_school_statistics/shared/_list.html.erb b/app/views/admins/daily_school_statistics/shared/_list.html.erb
index 611acdd2a..6982891ee 100644
--- a/app/views/admins/daily_school_statistics/shared/_list.html.erb
+++ b/app/views/admins/daily_school_statistics/shared/_list.html.erb
@@ -1,8 +1,8 @@
+ 序号 |
单位名称 |
-
<%= sort_tag('教师总数', name: 'teacher_count', path: admins_daily_school_statistics_path) %> |
<%= sort_tag('学生总数', name: 'student_count', path: admins_daily_school_statistics_path) %> |
<%= sort_tag('课堂总数', name: 'course_count', path: admins_daily_school_statistics_path) %> |
@@ -16,13 +16,14 @@
<%= sort_tag('实训作业总数', name: 'homework_count', path: admins_daily_school_statistics_path) %> |
<%= sort_tag('其它作业总数', name: 'other_homework_count', path: admins_daily_school_statistics_path) %> |
- <%= sort_tag('动态时间', name: 'nearly_course_time', path: admins_daily_school_statistics_path) %> |
+ <%= sort_tag('动态时间', name: 'nearly_course_time', path: admins_daily_school_statistics_path) %> |
<% if statistics.present? %>
- <% statistics.each do |statistic| %>
+ <% statistics.each_with_index do |statistic, index| %>
+ <%= list_index_no(@params_page.to_i, index) %> |
<%= link_to statistic[:name], "/colleges/#{statistic[:id]}/statistics",
target: '_blank', data: { toggle: 'tooltip', title: '点击查看学校统计概况' } %>
diff --git a/app/views/admins/department_applies/shared/_list.html.erb b/app/views/admins/department_applies/shared/_list.html.erb
index 0a1d803be..87d5ab66f 100644
--- a/app/views/admins/department_applies/shared/_list.html.erb
+++ b/app/views/admins/department_applies/shared/_list.html.erb
@@ -1,18 +1,20 @@
+ 序号 |
ID |
部门名称 |
单位名称 |
- 创建者 |
+ 创建者 |
<%= sort_tag('创建于', name: 'created_at', path: admins_department_applies_path) %> |
操作 |
<% if applies.present? %>
- <% applies.each do |apply| %>
+ <% applies.each_with_index do |apply, index| %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= apply.id %> |
<%= apply.name %> |
<%= apply.school.try(:name) %> |
diff --git a/app/views/admins/department_members/create.js.erb b/app/views/admins/department_members/create.js.erb
index 4355c7432..6bf0a6ac3 100644
--- a/app/views/admins/department_members/create.js.erb
+++ b/app/views/admins/department_members/create.js.erb
@@ -1,4 +1,6 @@
$('.modal.admin-add-department-member-modal').modal('hide');
$.notify({ message: '操作成功' });
-$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>")
\ No newline at end of file
+var index = $(".department-item-<%= current_department.id %>").children(":first").html();
+$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department, index: 1 }) %>");
+$(".department-item-<%= current_department.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/departments/shared/_department_item.html.erb b/app/views/admins/departments/shared/_department_item.html.erb
index 64b4ee70b..62f3a81ac 100644
--- a/app/views/admins/departments/shared/_department_item.html.erb
+++ b/app/views/admins/departments/shared/_department_item.html.erb
@@ -1,3 +1,4 @@
+<%= list_index_no((params[:page] || 1).to_i, index) %> |
<% not_list = defined?(:users_count) %>
<%= overflow_hidden_span department.name, width: 150 %> |
diff --git a/app/views/admins/departments/shared/_list.html.erb b/app/views/admins/departments/shared/_list.html.erb
index 6af63d6f4..09ba2a65f 100644
--- a/app/views/admins/departments/shared/_list.html.erb
+++ b/app/views/admins/departments/shared/_list.html.erb
@@ -1,10 +1,11 @@
+ 序号 |
部门名称 |
单位名称 |
用户数 |
- 已职业认证 |
+ 已职业认证 |
部门管理员 |
统计链接 |
云主机数 |
@@ -14,9 +15,9 @@
<% if departments.present? %>
- <% departments.each do |department| %>
+ <% departments.each_with_index do |department, index| %>
- <%= render 'admins/departments/shared/department_item', department: department %>
+ <%= render partial: 'admins/departments/shared/department_item', locals: {department: department, index: index} %>
<% end %>
<% else %>
diff --git a/app/views/admins/departments/update.js.erb b/app/views/admins/departments/update.js.erb
index 359bac59c..d20ca9524 100644
--- a/app/views/admins/departments/update.js.erb
+++ b/app/views/admins/departments/update.js.erb
@@ -1,4 +1,6 @@
$('.modal.admin-edit-department-modal').modal('hide');
$.notify({ message: '操作成功' });
-$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>")
\ No newline at end of file
+var index = $(".department-item-<%= current_department.id %>").children(":first").html();
+$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: {department: current_department, index: 1}) %>");
+$(".department-item-<%= current_department.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/identity_authentications/shared/_list.html.erb b/app/views/admins/identity_authentications/shared/_list.html.erb
index 607feb93a..6e12d1c54 100644
--- a/app/views/admins/identity_authentications/shared/_list.html.erb
+++ b/app/views/admins/identity_authentications/shared/_list.html.erb
@@ -3,6 +3,7 @@
+ 序号 |
<% unless is_processed %>
<%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box',
@@ -13,7 +14,7 @@
| 姓名 |
身份证号 |
学校/单位 |
- 职称 |
+ 职称 |
<% unless is_processed %>
照片
@@ -33,9 +34,10 @@
|
<% if applies.present? %>
- <% applies.each do |apply| %>
+ <% applies.each_with_index do |apply, index| %>
<% user = apply.user %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<% unless is_processed %>
<%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %> |
<% end %>
diff --git a/app/views/admins/laboratories/shared/_laboratory_item.html.erb b/app/views/admins/laboratories/shared/_laboratory_item.html.erb
index 81a45ca71..765616926 100644
--- a/app/views/admins/laboratories/shared/_laboratory_item.html.erb
+++ b/app/views/admins/laboratories/shared/_laboratory_item.html.erb
@@ -1,4 +1,5 @@
<% school = laboratory.school %>
+<%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= school&.name || 'EduCoder主站' %> |
<% if laboratory.identifier %>
diff --git a/app/views/admins/laboratories/shared/_list.html.erb b/app/views/admins/laboratories/shared/_list.html.erb
index 2520b3276..a731be44a 100644
--- a/app/views/admins/laboratories/shared/_list.html.erb
+++ b/app/views/admins/laboratories/shared/_list.html.erb
@@ -1,6 +1,7 @@
+ 序号 |
单位名称 |
域名 |
统计链接 |
@@ -9,14 +10,14 @@
同步课堂 |
同步实践课程 |
同步实训 |
- 操作 |
+ 操作 |
<% if laboratories.present? %>
- <% laboratories.each do |laboratory| %>
+ <% laboratories.each_with_index do |laboratory, index| %>
- <%= render 'admins/laboratories/shared/laboratory_item', laboratory: laboratory %>
+ <%= render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: laboratory, index: index} %>
<% end %>
<% else %>
diff --git a/app/views/admins/laboratories/update.js.erb b/app/views/admins/laboratories/update.js.erb
index 1b9f307a6..149539ad6 100644
--- a/app/views/admins/laboratories/update.js.erb
+++ b/app/views/admins/laboratories/update.js.erb
@@ -1 +1,3 @@
-$(".laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: "admins/laboratories/shared/laboratory_item",locals: {laboratory: @laboratory} %>")
\ No newline at end of file
+var index = $(".laboratory-item-<%= @laboratory.id %>").children(":first").html();
+$(".laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: "admins/laboratories/shared/laboratory_item",locals: {laboratory: @laboratory, index: 1} %>");
+$(".laboratory-item-<%= @laboratory.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/laboratories/update_sync_course.js.erb b/app/views/admins/laboratories/update_sync_course.js.erb
index 5ae68f673..663f56ee1 100644
--- a/app/views/admins/laboratories/update_sync_course.js.erb
+++ b/app/views/admins/laboratories/update_sync_course.js.erb
@@ -1 +1,3 @@
-$("#laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: @laboratory} %>")
\ No newline at end of file
+var index = $(".laboratory-item-<%= @laboratory.id %>").children(":first").html();
+$("#laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: @laboratory, index: 1} %>");
+$(".laboratory-item-<%= @laboratory.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/laboratory_shixuns/shared/_list.html.erb b/app/views/admins/laboratory_shixuns/shared/_list.html.erb
index e1244c472..462486f4b 100644
--- a/app/views/admins/laboratory_shixuns/shared/_list.html.erb
+++ b/app/views/admins/laboratory_shixuns/shared/_list.html.erb
@@ -1,21 +1,22 @@
- 实训名称 |
+ 序号 |
+ 实训名称 |
技术平台 |
技术体系 |
封面 |
创建者 |
- 状态 |
+ 状态 |
执行时间 |
操作 |
<% if laboratory_shixuns.present? %>
- <% laboratory_shixuns.each do |laboratory_shixun| %>
+ <% laboratory_shixuns.each_with_index do |laboratory_shixun, index| %>
- <%= render partial: 'admins/laboratory_shixuns/shared/td', locals: { laboratory_shixun: laboratory_shixun } %>
+ <%= render partial: 'admins/laboratory_shixuns/shared/td', locals: { laboratory_shixun: laboratory_shixun, index: index } %>
<% end %>
<% else %>
diff --git a/app/views/admins/laboratory_shixuns/shared/_td.html.erb b/app/views/admins/laboratory_shixuns/shared/_td.html.erb
index dbdf0df75..d987b53b4 100644
--- a/app/views/admins/laboratory_shixuns/shared/_td.html.erb
+++ b/app/views/admins/laboratory_shixuns/shared/_td.html.erb
@@ -1,5 +1,6 @@
<%- shixun = laboratory_shixun.shixun -%>
+<%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %>
<%= shixun.name %>
diff --git a/app/views/admins/laboratory_subjects/shared/_list.html.erb b/app/views/admins/laboratory_subjects/shared/_list.html.erb
index 55f67dea8..c40d02260 100644
--- a/app/views/admins/laboratory_subjects/shared/_list.html.erb
+++ b/app/views/admins/laboratory_subjects/shared/_list.html.erb
@@ -1,7 +1,8 @@
- 课程名称 |
+ 序号 |
+ 课程名称 |
技术体系 |
等级体系 |
封面 |
@@ -13,10 +14,11 @@
<% if laboratory_subjects.present? %>
- <% laboratory_subjects.each do |laboratory_subject| %>
+ <% laboratory_subjects.each_with_index do |laboratory_subject, index| %>
<%- subject = laboratory_subject.subject -%>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= link_to(subject.name, "/paths/#{subject.id}", target: '_blank') %>
首页
diff --git a/app/views/admins/laboratory_users/create.js.erb b/app/views/admins/laboratory_users/create.js.erb
index f43fd7887..604e62943 100644
--- a/app/views/admins/laboratory_users/create.js.erb
+++ b/app/views/admins/laboratory_users/create.js.erb
@@ -1,4 +1,6 @@
$('.modal.admin-add-laboratory-user-modal').modal('hide');
$.notify({ message: '操作成功' });
-$('.laboratory-list-table .laboratory-item-<%= current_laboratory.id %>').html("<%= j(render partial: 'admins/laboratories/shared/laboratory_item', locals: { laboratory: current_laboratory }) %>")
\ No newline at end of file
+var index = $(".laboratory-item-<%= current_laboratory.id %>").children(":first").html();
+$('.laboratory-list-table .laboratory-item-<%= current_laboratory.id %>').html("<%= j(render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: current_laboratory, index: 1}) %>");
+$(".laboratory-item-<%= current_laboratory.id %>").children(":first").html(index);
\ No newline at end of file
diff --git a/app/views/admins/library_applies/shared/_list.html.erb b/app/views/admins/library_applies/shared/_list.html.erb
index 783d0db30..fde3d1d1a 100644
--- a/app/views/admins/library_applies/shared/_list.html.erb
+++ b/app/views/admins/library_applies/shared/_list.html.erb
@@ -3,11 +3,12 @@
+ 序号 |
头像 |
姓名 |
教学案例 |
案例描述 |
- 时间 |
+ 时间 |
<% if is_processed %>
拒绝原因 |
状态 |
@@ -18,10 +19,11 @@
<% if applies.present? %>
- <% applies.each do |apply| %>
+ <% applies.each_with_index do |apply, index| %>
<% user = apply.library.user %>
<% library = apply.library %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
diff --git a/app/views/admins/myshixuns/shared/_list.html.erb b/app/views/admins/myshixuns/shared/_list.html.erb
index 440437320..af43c3c22 100644
--- a/app/views/admins/myshixuns/shared/_list.html.erb
+++ b/app/views/admins/myshixuns/shared/_list.html.erb
@@ -1,9 +1,10 @@
+ 序号 |
ID |
标识 |
- 实训名称 |
+ 实训名称 |
实训老师 |
完成 |
经验值 |
@@ -14,14 +15,23 @@
<% if myshixuns.present? %>
- <% myshixuns.each do |myshixun| %>
+ <% myshixuns.each_with_index do |myshixun, index| %>
+ <%= list_index_no(@params_page.to_i, index) %> |
<%= myshixun.id %> |
<%= myshixun.identifier %> |
- <% current_task = myshixun.last_executable_task || myshixun.last_task %>
- <%= link_to "/tasks/#{current_task.identifier}", target: '_blank' do %>
- <%= overflow_hidden_span myshixun.shixun.name, width: 280 %>
+ <% if myshixun.shixun.is_jupyter? %>
+ <%= link_to "/tasks/#{myshixun.identifier}/jupyter", target: '_blank' do %>
+ <%= overflow_hidden_span myshixun.shixun.name, width: 280 %>
+ <% end %>
+ <% else %>
+ <% current_task = myshixun.last_executable_task || myshixun.last_task %>
+ <% if current_task %>
+ <%= link_to "/tasks/#{current_task.identifier}", target: '_blank' do %>
+ <%= overflow_hidden_span myshixun.shixun.name, width: 280 %>
+ <% end %>
+ <% end %>
<% end %>
|
<%= myshixun.shixun.user.real_name %> |
diff --git a/app/views/admins/partners/shared/_list.html.erb b/app/views/admins/partners/shared/_list.html.erb
index 0bebc2a4b..71153c175 100644
--- a/app/views/admins/partners/shared/_list.html.erb
+++ b/app/views/admins/partners/shared/_list.html.erb
@@ -1,15 +1,17 @@
- 名称 |
+ 序号 |
+ 名称 |
<%= sort_tag('添加时间', name: 'created_at', path: admins_partners_path) %> |
操作 |
<% if partners.present? %>
- <% partners.each do |partner| %>
+ <% partners.each_with_index do |partner, index| %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= link_to partner.school&.name || partner.name, customers_partner_path(partner), target: '_blank' %>
|
diff --git a/app/views/admins/professional_authentications/shared/_list.html.erb b/app/views/admins/professional_authentications/shared/_list.html.erb
index 6ec6355ba..7ffa5837e 100644
--- a/app/views/admins/professional_authentications/shared/_list.html.erb
+++ b/app/views/admins/professional_authentications/shared/_list.html.erb
@@ -3,6 +3,7 @@
+ 序号 |
<% unless is_processed %>
<%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box',
@@ -12,7 +13,7 @@
| 头像 |
姓名 |
学校/单位 |
- 职称 |
+ 职称 |
<% unless is_processed %>
照片
@@ -31,9 +32,10 @@
|
<% if applies.present? %>
- <% applies.each do |apply| %>
+ <% applies.each_with_index do |apply, index| %>
<% user = apply.user %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<% unless is_processed %>
<%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %> |
<% end %>
diff --git a/app/views/admins/project_package_applies/shared/_list.html.erb b/app/views/admins/project_package_applies/shared/_list.html.erb
index d94c96184..bec0912ca 100644
--- a/app/views/admins/project_package_applies/shared/_list.html.erb
+++ b/app/views/admins/project_package_applies/shared/_list.html.erb
@@ -3,11 +3,12 @@
+ 序号 |
头像 |
姓名 |
众包需求 |
需求描述 |
- 时间 |
+ 时间 |
<% if is_processed %>
拒绝原因 |
状态 |
@@ -18,10 +19,11 @@
<% if applies.present? %>
- <% applies.each do |apply| %>
+ <% applies.each_with_index do |apply, index| %>
<% package = apply.project_package %>
<% user = package.creator %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %>
diff --git a/app/views/admins/projects/shared/_list.html.erb b/app/views/admins/projects/shared/_list.html.erb
index 8a84a72d0..e2a6307ad 100644
--- a/app/views/admins/projects/shared/_list.html.erb
+++ b/app/views/admins/projects/shared/_list.html.erb
@@ -1,6 +1,7 @@
+ 序号 |
ID |
项目名称 |
公开 |
@@ -11,14 +12,15 @@
里程碑 |
成员 |
管理员 |
- <%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %> |
+ <%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %> |
操作 |
<% if projects.present? %>
- <% projects.each do |project| %>
+ <% projects.each_with_index do |project, index| %>
+ <%= list_index_no((params[:page] || 1).to_i, index) %> |
<%= project.id %> |
<%= link_to(project.name, "/projects/#{project.id}", target: '_blank') %>
diff --git a/app/views/admins/school_statistics/shared/_list.html.erb b/app/views/admins/school_statistics/shared/_list.html.erb
index aa043f097..9d2a1c209 100644
--- a/app/views/admins/school_statistics/shared/_list.html.erb
+++ b/app/views/admins/school_statistics/shared/_list.html.erb
@@ -20,7 +20,8 @@
- 单位名称 |
+ 序号 |
+ 单位名称 |
<%= sort_tag('新增教师', name: 'teacher_increase_count', path: admins_school_statistics_path) %> |
<%= sort_tag('新增学生', name: 'student_increase_count', path: admins_school_statistics_path) %> |
<%= sort_tag('新增课堂', name: 'course_increase_count', path: admins_school_statistics_path) %> |
@@ -32,8 +33,9 @@
<% if statistics.present? %>
- <% statistics.each do |statistic| %>
+ <% statistics.each_with_index do |statistic, index| %>
+ <%= list_index_no(@params_page.to_i, index) %> |
<%= link_to statistic.school_name, "/colleges/#{statistic.school_id}/statistics",
target: '_blank', data: { toggle: 'tooltip', title: '点击查看学校统计概况' } %>
diff --git a/app/views/admins/schools/index.html.erb b/app/views/admins/schools/index.html.erb
index 9c41067ee..56cbadd9d 100644
--- a/app/views/admins/schools/index.html.erb
+++ b/app/views/admins/schools/index.html.erb
@@ -4,7 +4,7 @@
| | | | | | | | | |