Merge branch 'dev_aliyun' into dev_daiao

dev_daiao
daiao 5 years ago
commit 0a6f58eced

@ -20,6 +20,8 @@ gem 'bootsnap', '>= 1.1.0', require: false
gem 'gitlab', path: 'lib/gitlab-cli'
gem 'chinese_pinyin'
gem 'rack-cors'
gem 'redis-rails'
gem 'roo-xls'
@ -48,7 +50,6 @@ gem 'rqrcode_png'
gem 'acts-as-taggable-on', '~> 6.0'
group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails', '~> 3.8'
end

@ -0,0 +1,57 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-courses-index-page').length > 0) {
let searchContainer = $(".course-list-form");
let searchForm = $("form.search-form",searchContainer);
searchContainer.on('change', '.course-homepage-show', function(){
searchForm.find('input[type="submit"]').trigger('click');
});
//导出
searchContainer.on('click', "#course-export", function () {
window.location.href = "/admins/courses.xlsx?" + searchForm.serialize();
});
$(".course-list-container").on("change", '.course-setting-form', function () {
var s_id = $(this).attr("data-id");
var s_value = $(this).val();
var s_name = $(this).attr("name");
var json = {};
json[s_name] = s_value;
$.ajax({
url: "/admins/courses/" + s_id,
type: "PUT",
dataType:'script',
data: json
});
});
// ************** 学校选择 *************
searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择单位',
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};
},
processResults: function (data) {
return {results: data.schools}
}
},
templateResult: function (item) {
if (!item.id || item.id === '') return item.text;
return item.name;
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
}
});

@ -160,5 +160,16 @@ $(document).on('turbolinks:load', function() {
$addMemberModal.modal('hide');
}
});
$(".laboratory-list-container").on("change", '.laboratory-sync-course', function () {
var s_id = $(this).attr("data-id");
var json = {};
$.ajax({
url: "/admins/laboratories/" + s_id + "/update_sync_course",
type: "POST",
dataType:'script',
data: json
})
});
}
});

@ -0,0 +1,60 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-merge-course-list-modal');
if ($modal.length > 0) {
var $form = $modal.find('form.admin-merge-course-list-form');
var $originCourseListIdInput = $form.find('input[name="origin_course_list_id"]');
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
course_list_name: {
required: true
}
},
messages: {
course_list_name: {
required: '请输入课程名称'
}
}
});
// modal ready fire
$modal.on('show.bs.modal', function (event) {
var $link = $(event.relatedTarget);
var couresListId = $link.data('courseListId');
var url = $link.data('url');
$originCourseListIdInput.val(couresListId);
$form.data('url', url);
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if ($form.valid()) {
var url = $form.data('url');
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: $form.serialize(),
success: function(){
$.notify({ message: '操作成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});

@ -0,0 +1,22 @@
$(document).on('turbolinks:load', function(){
if ($('body.admins-shixun-feedback-messages-index-page').length > 0) {
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);
$(element).datepicker(options);
$(element).find('.start-date').datepicker().on('changeDate', function(e){
$(element).find('.end-date').datepicker('setStartDate', e.date);
})
};
defineDateRangeSelect('.grow-date-input-daterange');
}
})

@ -12,6 +12,11 @@ $(document).on('turbolinks:load', function() {
window.location.href = "/admins/shixun_settings.xls?" + searchForm.serialize();
});
// 基础数据导出
searchContainer.on('click', "#shixun-settings-base-export", function () {
window.location.href = "/admins/shixun_settings.xls?base_data=1" + searchForm.serialize();
});
$(".shixun-settings-list-container").on("change", '.shixun-setting-form', function () {
var s_id = $(this).attr("data-id");
var s_value = $(this).val();

@ -53,3 +53,8 @@ input.form-control {
position: absolute;
}
.export-base-absolute{
right:100px;
position: absolute;
}

@ -60,7 +60,7 @@ class AccountsController < ApplicationController
ua = UserAgent.find_by_ip(ip)
ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua
successful_authentication(@user)
session[:user_id] = @user.id
# session[:user_id] = @user.id
normal_status("注册成功")
end
rescue Exception => e
@ -94,7 +94,7 @@ class AccountsController < ApplicationController
successful_authentication(@user)
login_control.clear # 重置每日密码错误次数
session[:user_id] = @user.id
# session[:user_id] = @user.id
end
# 忘记密码
@ -136,6 +136,7 @@ class AccountsController < ApplicationController
set_autologin_cookie(user)
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
user.update_column(:last_login_on, Time.now)
session[:"#{default_yun_session}"] = user.id
# 注册完成后有一天的试用申请(先去掉)
# UserDayCertification.create(user_id: user.id, status: 1)
end
@ -158,7 +159,6 @@ class AccountsController < ApplicationController
def logout
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
session[:user_id] = nil
logout_user
render :json => {status: 1, message: "退出成功!"}
end

@ -0,0 +1,35 @@
class Admins::CourseListsController < Admins::BaseController
def index
course_lists = Admins::CourseListQuery.call(params)
@course_lists = paginate course_lists.preload(:courses, :user)
@params_page = params[:page] || 1
respond_to do |format|
format.js
format.html
end
end
def destroy
CourseList.find(params[:id]).destroy!
render_delete_success
end
def merge
origin_course_list = CourseList.find_by!(id: params[:origin_course_list_id])
o_courselist = CourseList.find_by(name: params[:course_list_name])
if o_courselist
origin_course_list.courses.each do |course|
course.update!(name: course.name.sub(origin_course_list.name, params[:course_list_name]), course_list_id: o_courselist.id)
end
origin_course_list.destroy
else
origin_course_list.courses.each do |course|
course.update!(name: course.name.sub(origin_course_list.name, params[:course_list_name]))
end
origin_course_list.update!(name: params[:course_list_name])
end
render_ok
end
end

@ -0,0 +1,49 @@
class Admins::CoursesController < Admins::BaseController
before_action :find_course, except: [:index]
def index
default_sort('created_at', 'desc')
courses = Admins::CourseQuery.call(params)
@ended_courses = courses.where(is_end: 1).size
@processed_courses = courses.where(is_end: 0).size
@courses = paginate courses.includes(:school, :students, :attachments, :homework_commons, teacher: :user_extension)
respond_to do |format|
format.js
format.html
format.xlsx do
@courses = courses.includes(:school, :students, :attachments, :homework_commons, :course_acts, teacher: :user_extension)
filename = "课堂列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end
end
end
def destroy
if @course.is_delete == 0
@course.delete!
Tiding.create!(user_id: current_user.id, trigger_user_id: current_user.id, container_id: @course.id,
container_type: 'DeleteCourse', tiding_type: 'System', belong_container: @course, extra: @course.name)
end
end
def update
if @course.update_attributes(setting_params)
render_ok
else
redirect_to admins_courses_path
flash[:danger] = "更新失败"
end
end
private
def find_course
@course = Course.find_by!(id: params[:id])
end
def setting_params
params.permit(:homepage_show, :email_notify)
end
end

@ -50,6 +50,17 @@ class Admins::LaboratoriesController < Admins::BaseController
@subjects = paginate(subjects.includes(:user))
end
def synchronize_user
school = current_laboratory.school
users = User.joins(:user_extension).where(user_extensions: {school_id: school.id})
users.update_all(laboratory_id: current_laboratory.id)
end
def update_sync_course
current_laboratory.update!(sync_course: !current_laboratory.sync_course)
@laboratory = current_laboratory
end
private
def current_laboratory

@ -17,10 +17,16 @@ class Admins::LaboratorySubjectsController < Admins::BaseController
def destroy
return render_js_error('不能删除自建课程', type: :notify) if current_laboratory_subject.ownership?
current_laboratory_subject.destroy!
ActiveRecord::Base.transaction do
current_subject = current_laboratory_subject.subject
# 实训软删除,并解除与子站的关联
current_laboratory.laboratory_shixuns.where(shixun_id: current_subject.shixuns).destroy_all
current_subject.shixuns.update_all(status: -1)
current_subject.destroy!
render_delete_success
end
end
def homepage

@ -0,0 +1,25 @@
class Admins::ProjectsController < Admins::BaseController
def index
default_sort('created_at', 'desc')
search = params[:search].to_s.strip
projects = Project.where("name like ?", "%#{search}%")
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
end
def destroy
project = Project.find_by!(id: params[:id])
ActiveRecord::Base.transaction do
g = Gitlab.client
g.delete_project(project.gpid)
# 删除Trustie版本库记录
repoisitory = Repository.where(project_id: project.id, type: "Repository::Gitlab").first
repoisitory.destroy!
Tiding.where(container_id: project.id, container_type: ["JoinProject", "DealProject", "ReporterJoinProject", "ManagerJoinProject"]).destroy_all
project.destroy!
render_delete_success
end
end
end

@ -5,7 +5,7 @@ class Admins::SchoolsController < Admins::BaseController
schools = Admins::SchoolQuery.call(params)
@schools = paginate schools
@schools = paginate schools.includes(:user_extensions)
school_ids = @schools.map(&:id)
@department_count = Department.where(school_id: school_ids).group(:school_id).count

@ -0,0 +1,22 @@
class Admins::ShixunFeedbackMessagesController < Admins::BaseController
def index
@params_page = params[:page] || 1
if params[:keyword].present?
discusses = Discuss.joins("LEFT JOIN shixuns ON discusses.dis_id = shixuns.id AND dis_type = 'Shixun'")
.where("shixuns.name like ?", "%#{params[:keyword]}%")
else
discusses = Discuss.where(:dis_type => 'Shixun').includes(:user, :dis)
end
if params[:begin_date].present?
discusses = discusses.where("discusses.created_at > ?", params[:begin_date])
end
if params[:end_date].present?
discusses = discusses.where("discusses.created_at < ?", params[:end_date])
end
@discusses = paginate discusses.order("created_at desc")
end
end

@ -0,0 +1,22 @@
class Admins::ShixunRecyclesController < Admins::BaseController
def index
sort_by = params[:sort_by].presence || 'created_at'
sort_direction = params[:sort_direction].presence || 'desc'
search = params[:search].to_s.strip
shixuns = Shixun.where(status: -1).where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
@shixuns = paginate shixuns.preload(:user, :laboratory)
end
def destroy
Shixun.find(params[:id]).destroy!
render_delete_success
end
def resume
Shixun.find(params[:id]).update!(status: 0)
render_delete_success
end
end

@ -28,7 +28,13 @@ class Admins::ShixunSettingsController < Admins::BaseController
format.html
format.xls{
filename = "实训详情_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
send_data(shixun_list_xls(shixun_settings), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
export_url =
if params[:base_data].present?
shixun_base_list_xls(shixun_settings)
else
shixun_list_xls(shixun_settings)
end
send_data(export_url, :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
}
end
@ -65,19 +71,20 @@ class Admins::ShixunSettingsController < Admins::BaseController
sheet1.row(0).default_format = blue
sheet1.row(0).concat(["实训ID","实训名称","技术平台", "Fork源", "实践任务","选择题任务","挑战人数", "通关人数", "状态","创建者", "单位", "职业", "关卡序号","关卡名称","技能标签"])
count_row = 1
shixuns.find_each do |shixun|
shixuns.includes(:fork_shixuns, :myshixuns, :mirror_repositories, challenges: [:challenge_tags], user: [user_extension: :school]).find_each do |shixun|
sheet1[count_row, 0] = shixun.identifier
sheet1[count_row, 1] = shixun.name
sheet1[count_row, 2] = shixun.shixun_main_name
sheet1[count_row, 2] = shixun.mirror_repositories.select{|mr| mr.main_type == "1"}.first&.type_name
sheet1[count_row, 3] = shixun.fork_identifier
sheet1[count_row, 4] = shixun.challenges.practice_type.count
sheet1[count_row, 5] = shixun.challenges.choose_type.count
sheet1[count_row, 6] = shixun.myshixuns.count
sheet1[count_row, 7] = shixun.myshixuns.finished.count
sheet1[count_row, 4] = shixun.challenges.select{|c| c.st == 0}.size
sheet1[count_row, 5] = shixun.challenges.select{|c| c.st == 1}.size
sheet1[count_row, 6] = shixun.myshixuns_count
sheet1[count_row, 7] = shixun.myshixuns.select{|m| m.status == 1}.size
sheet1[count_row, 8] = shixun.shixun_status
sheet1[count_row, 9] = shixun.owner.show_real_name
sheet1[count_row, 10] = shixun.owner.school_name
sheet1[count_row, 11] = shixun.owner.identity
sheet1[count_row, 9] = shixun.user.show_real_name
sheet1[count_row, 10] = shixun.user.school_name
sheet1[count_row, 11] = shixun.user.identity
shixun.challenges.each do |challenge|
sheet1[count_row, 12] = "#{challenge.position}"
sheet1[count_row, 13] = challenge.subject
@ -90,6 +97,34 @@ class Admins::ShixunSettingsController < Admins::BaseController
xls_report.string
end
def shixun_base_list_xls shixuns
xls_report = StringIO.new
book = Spreadsheet::Workbook.new
sheet1 = book.create_worksheet :name => "sheet"
blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10
sheet1.row(0).default_format = blue
sheet1.row(0).concat(["实训ID","实训名称","技术平台", "Fork源", "状态","创建者", "单位", "职业", "关卡序号","关卡名称"])
count_row = 1
shixuns.includes(:mirror_repositories, :challenges, user: [user_extension: :school]).find_each do |shixun|
sheet1[count_row, 0] = shixun.identifier
sheet1[count_row, 1] = shixun.name
sheet1[count_row, 2] = shixun.mirror_repositories.select{|mr| mr.main_type == "1"}.first&.type_name
sheet1[count_row, 3] = shixun.fork_from
sheet1[count_row, 4] = shixun.shixun_status
sheet1[count_row, 5] = shixun.user.show_real_name
sheet1[count_row, 6] = shixun.user.school_name
sheet1[count_row, 7] = shixun.user.identity
shixun.challenges.each do |challenge|
sheet1[count_row, 8] = "#{challenge.position}"
sheet1[count_row, 9] = challenge.subject
count_row += 1
end
count_row += 1
end
book.write xls_report
xls_report.string
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:[])
end

@ -1,7 +1,7 @@
class Admins::ShixunsController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_by] = params[:sort_by].presence || 'created_at'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
shixuns = Admins::ShixunQuery.call(params)
@editing_shixuns = shixuns.where(status:0).size
@ -23,7 +23,7 @@ class Admins::ShixunsController < Admins::BaseController
end
def destroy
Shixun.find(params[:id]).destroy!
Shixun.find(params[:id]).update!(status: -1)
render_delete_success
end

@ -45,6 +45,13 @@ class ApplicationController < ActionController::Base
check_account
tip_exception(@course.excellent ? 410 : 409, "您没有权限进入")
end
if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT
# 实名认证和职业认证的身份判断
tip_exception(411, "你的实名认证和职业认证审核未通过") if @course.authentication &&
@course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
tip_exception(411, "你的实名认证审核未通过") if @course.authentication && !current_user.authentication
tip_exception(411, "你的职业认证审核未通过") if @course.professional_certification && !current_user.professional_certification
end
uid_logger("###############user_course_identity:#{@user_course_identity}")
end
@ -292,9 +299,11 @@ class ApplicationController < ActionController::Base
# and starts a session if needed
def find_current_user
uid_logger("user setup start: session[:user_id] is #{session[:user_id]}")
if session[:user_id]
uid_logger("0000000000000user setup start: default_yun_session is #{default_yun_session}, session[:current_user_id] is #{session[:"#{default_yun_session}"]}")
current_domain_session = session[:"#{default_yun_session}"]
if current_domain_session
# existing session
(User.active.find(session[:user_id]) rescue nil)
(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?
@ -306,10 +315,10 @@ class ApplicationController < ActionController::Base
def try_to_autologin
if cookies[autologin_cookie_name]
# auto-login feature starts a new session
user = User.try_to_autologin(cookies[autologin_cookie_name])
if user
start_user_session(user)
end
user = nil
Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
user = User.try_to_autologin(cookies[autologin_cookie_name]) if session[:"#{default_yun_session}"]
start_user_session(user) if user
user
end
end
@ -395,25 +404,6 @@ class ApplicationController < ActionController::Base
end
end
# 处理返回非0就报错的请求
def interface_post(uri, params, status, message)
begin
uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.post_form(uri, params).body
uid_logger_dubug("--uri_exec: .....res is #{res}")
res = JSON.parse(res)
if (res && res['code'] != 0)
tip_exception(status, message)
else
res
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Educoder::TipException.new("实训平台繁忙繁忙等级84")
end
end
# json格式请求
def interface_json_post(uri, params, status, message)
begin

@ -125,7 +125,7 @@ class AttachmentsController < ApplicationController
end
digest = md5_file(temp_file)
digest = "#{digest}_#{Time.now.to_i}"
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)

@ -308,6 +308,7 @@ class ChallengesController < ApplicationController
end
def challenge_params
tip_exception("评测时间不能超过300秒") if params[:challenge][:exec_time].to_i > 300
params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average,
:path, :exec_path, :show_type, :original_picture_path, :test_set_score,
:expect_picture_path, :picture_path, :web_route, :answer, :exec_time)

@ -125,7 +125,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
end
@all_records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})
.select("competition_teams.*, score, cost_time").order("score desc, cost_time desc")
.select("competition_teams.*, score, cost_time").order("score desc, cost_time asc")
current_team_ids = @competition.team_members.where(user_id: current_user.id).pluck(:competition_team_id).uniq
@user_ranks = @all_records.select{|com_team| current_team_ids.include?(com_team.id)}
@ -213,7 +213,7 @@ class Competitions::CompetitionsController < Competitions::BaseController
if personal
row_cells_column << record_user.real_name
row_cells_column << record_user.school_name
row_cells_column << record_user.student_id.present? ? (record_user.student_id.to_s + "\t") : "--"
row_cells_column << (record_user.student_id.present? ? (record_user.student_id.to_s + "\t") : "--")
else
row_cells_column << record.name
row_cells_column << record.teachers_name

@ -6,6 +6,7 @@ module LaboratoryHelper
helper_method :current_laboratory
helper_method :default_setting
helper_method :default_yun_session
end
def current_laboratory
@ -23,4 +24,9 @@ module LaboratoryHelper
def setup_laboratory
Laboratory.current = current_laboratory
end
def default_yun_session
laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1))
@_default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
end
end

@ -29,7 +29,7 @@ module LoginHelper
Rails.logger.info("id: #{user&.id} Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
# Valid user
self.logged_user = user
session[:"#{default_yun_session}"] = user.id
# generate a key and set cookie if autologin
set_autologin_cookie(user)
@ -47,12 +47,16 @@ module LoginHelper
User.current.delete_session_token(session[:tk])
self.logged_user = nil
end
session[:user_id] = nil
# 云上实验室退出清理当前session
laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1))
default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
# end
session[:"#{default_yun_session}"] = nil
end
# Sets the logged in user
def logged_user=(user)
reset_session
# reset_session
if user && user.is_a?(User)
User.current = user
start_user_session(user)
@ -62,7 +66,19 @@ module LoginHelper
end
def start_user_session(user)
session[:user_id] = user.id
# re_subdomain = "#{request.subdomain.split('.').first}_user_id"
# session[:"#{request.subdomain}_user_id"] = user.id
# Rails.logger.info("domain_user_id session is: 3333332222111#{session[:"#{request.subdomain}_user_id"]}")
# Rails.logger.info("user_id session is: 3333332222111#{session[:"#{request.subdomain}_user_id"]}")
#
# # if current_laboratory.main_site?
# # session[:user_id] = user.id
# # else
# # session[:"#{request.subdomain}_user_id"] = user.id
# # end
# session[:user_id] = user.id
session[:"#{default_yun_session}"] = user.id
session[:ctime] = Time.now.utc.to_i
session[:atime] = Time.now.utc.to_i
end

@ -61,7 +61,7 @@ class CoursesController < ApplicationController
@user = current_user
# 根据分类查询课堂(全部,我的,最新,最热)
@order = params[:order].present? ? params[:order] : "all"
@courses = current_laboratory.courses.not_deleted
@courses = current_laboratory.all_courses.not_deleted
if @order == "visits"
order_str = "courses.id = 1309 DESC, courses.visits DESC"
@courses = @courses.where(is_hidden: 0)
@ -635,7 +635,7 @@ class CoursesController < ApplicationController
teacher_member = CourseMember.create!(course_id: @course.id, user_id: params[:user_id], role: params[:roles].include?("PROFESSOR") ? 2 : 3)
# 如果有未审批的申请教师/助教的记录,则修改状态为已审批
apply_teacher = CourseMessage.where(course_id: @course.id, course_message_id: params[:user_id], status: 0).last
apply_teacher.update!(status: 1, apply_user_id: current_user.id)
apply_teacher.update!(status: 1, apply_user_id: current_user.id) if apply_teacher.present?
elsif course_members.exists?(role: %i[PROFESSOR ASSISTANT_PROFESSOR])
teacher_member = course_members.where(role: %i[PROFESSOR ASSISTANT_PROFESSOR]).take
if params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR")

@ -610,7 +610,7 @@ class ExercisesController < ApplicationController
# 对未提交的用户进行调分
def adjust_score
exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id])
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1 && exercise_user.commit_method != 5
if @exercise.subjective_score > 0
tip_exception("主观题成绩不能为空") if params[:subjective_score].blank?
tip_exception("主观题成绩不能小于零") if params[:subjective_score].to_f < 0
@ -628,8 +628,13 @@ class ExercisesController < ApplicationController
subjective_score = @exercise.subjective_score > 0 ? params[:subjective_score].to_f.round(2) : 0
objective_score = @exercise.objective_score > 0 ? params[:objective_score].to_f.round(2) : 0
score = subjective_score + objective_score
if exercise_user.commit_status == 1
exercise_user.update_attributes!(score: score, subjective_score: subjective_score, objective_score: objective_score)
else
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score,
subjective_score: subjective_score, objective_score: objective_score, commit_method: 5)
end
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id,
subjective_score: subjective_score, objective_score: objective_score)
normal_status("操作成功")
@ -1760,19 +1765,12 @@ class ExercisesController < ApplicationController
else
ques_number = q.question_number
end
ques_status = 0
if q.question_type != Exercise::PRACTICAL
ques_vote = q.exercise_answers.select{|answer| answer.user_id == user_id}
else
ques_vote = q.exercise_shixun_answers.select{|answer| answer.user_id == user_id}
end
ques_status = 0
if ques_vote.present?
if q.question_type == Exercise::PRACTICAL
if ques_vote.pluck(:exercise_shixun_challenge_id).sort == q.exercise_shixun_challenges.pluck(:id).sort #用户的总得分等于问题的分数
ques_status = 1 #全部回答了,才算已答
question_answered += 1
end
else #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答
#其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答
vote_answer_id = ques_vote.pluck(:exercise_choice_id).reject(&:blank?)
vote_text_count = ques_vote.pluck(:answer_text).reject(&:blank?).size
if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答
@ -1780,11 +1778,6 @@ class ExercisesController < ApplicationController
ques_status = 1
question_answered += 1
end
elsif q.question_type == Exercise::COMPLETION #填空题的时候,需要有选项和内容,才算回答
if vote_answer_id.uniq.sort == q.exercise_standard_answers.pluck(:exercise_choice_id).uniq.sort
ques_status = 1
question_answered += 1
end
else
if vote_text_count > 0 #主观题,必选有内容,才算回答
ques_status = 1
@ -1792,6 +1785,11 @@ class ExercisesController < ApplicationController
end
end
end
else
if Myshixun.exists?(user_id: user_id, shixun_id: q.shixun_id)
ques_status = 1
question_answered += 1
end
end
question_status = {
:ques_id => q.id,

@ -24,26 +24,53 @@ class FilesController < ApplicationController
get_category(@course, @course_second_category_id)
@total_count = @attachments.size
@publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count
@attachments = @attachments.by_keywords(params[:search])
@attachments =
case @user.course_identity(@course)
when 5
@attachments.published
when 6, 7
@attachments.publiced.published
if @user.course_identity(@course) == 5
member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
if member.try(:course_group_id).to_i == 0
@attachments = @attachments.published.unified_setting
else
@attachments
not_atta_ids = @course.attachment_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}").pluck(:attachment_id)
@attachments = @attachments.where.not(id: not_atta_ids).published
end
elsif @user.course_identity(@course) > 5
@attachments = @attachments.publiced.published
end
@publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count
@attachments = @attachments.by_keywords(params[:search])
@attachments = @attachments.page(@page).per(@page_size)
end
def bulk_publish
return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5
@course.attachments.by_ids(@attachment_ids).unpublish.update_all(is_publish: 1, publish_time: Time.now)
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
# 未发布的资源更新状态
attachments.where(is_publish: 0).update_all(is_publish: 1, publish_time: Time.now)
end
render_ok
end
@ -153,6 +180,10 @@ class FilesController < ApplicationController
attachment.is_publish = @atta_is_publish
attachment.delay_publish = @atta_delay_publish
attachment.publish_time = @atta_publish_time
attachment.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting attachment, params[:group_settings]
end
# attachment.set_publish_time(publish_time) if is_unified_setting
# attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank?
attachment.save!
@ -195,6 +226,10 @@ class FilesController < ApplicationController
attach_copied_obj.is_publish = @atta_is_publish
attach_copied_obj.delay_publish = @atta_delay_publish
attach_copied_obj.publish_time = @atta_publish_time
attach_copied_obj.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting attach_copied_obj, params[:group_settings]
end
attach_copied_obj.course_second_category_id = course_second_category_id
attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil
@ -234,6 +269,12 @@ class FilesController < ApplicationController
@old_attachment.is_publish = @atta_is_publish
@old_attachment.delay_publish = @atta_delay_publish
@old_attachment.publish_time = @atta_publish_time
@old_attachment.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting @old_attachment, params[:group_settings]
else
@old_attachment.attachment_group_settings.destroy_all
end
if params[:description] && !params[:description].strip.blank? && params[:description] != @old_attachment.description
@old_attachment.description = params[:description]
@ -319,9 +360,40 @@ class FilesController < ApplicationController
def publish_params
tip_exception("缺少发布参数") if params[:delay_publish].blank?
tip_exception("缺少延期发布的时间参数") if params[:delay_publish].to_i == 1 && params[:publish_time].blank?
@atta_is_publish = params[:delay_publish].to_i == 1 && params[:publish_time].to_time > Time.now ? 0 : 1
@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
tip_exception("缺少延期发布的时间参数") if params[:publish_time].blank?
min_publish_time = params[:publish_time]
end
@atta_is_publish = params[:delay_publish].to_i == 1 && min_publish_time.to_time > Time.now ? 0 : 1
@atta_delay_publish = params[:delay_publish].to_i
@atta_publish_time = params[:delay_publish].to_i == 1 && params[:publish_time] ? params[:publish_time] : Time.now
@atta_publish_time = params[:delay_publish].to_i == 1 ? min_publish_time : Time.now
end
def create_atta_group_settings atta
if atta.attachment_group_settings.size != @course.course_groups.size
@course.course_groups.where.not(id: atta.attachment_group_settings.pluck(:course_group_id)).each do |group|
atta.attachment_group_settings << AttachmentGroupSetting.new(course_group_id: group.id, course_id: @course.id,
publish_time: atta.publish_time)
end
end
end
def attachment_group_setting attachment, group_setting
create_atta_group_settings attachment
group_setting.each do |setting|
tip_exception("分班id不能为空") if setting[:group_id].length == 0
tip_exception("发布时间不能为空") if setting[:publish_time].blank?
AttachmentGroupSetting.where(attachment_id: attachment.id, course_group_id: setting[:group_id]).
update_all(publish_time: setting[:publish_time])
end
end
end

@ -767,7 +767,8 @@ class GamesController < ApplicationController
# 记录实训花费的时间
# REDO:需要添加详细的说明
def cost_time
cost_time = params[:time].to_i
#return if @game.status >= 2
cost_time = params[:time].to_i < @game.cost_time.to_i ? (@game.cost_time.to_i + params[:time].to_i) : params[:time].to_i
@game.update_attribute(:cost_time, cost_time)
end

@ -38,7 +38,6 @@ class GitsController < ApplicationController
else
# 用户是否对对象拥有权限
system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username)
# 如果用户名密码错误
if system_user && !system_user.check_password?(input_password)
uid_logger_error("git start: password is wrong")
@ -49,7 +48,13 @@ class GitsController < ApplicationController
shixunname = git_url.split("/")[1].split(".")[0]
repo_name = username + "/" + shixunname
uid_logger("git start: repo_name is #{repo_name}")
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name, laboratory_id: nil).first
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name).first
if shixun.blank?
shixun_id = ShixunSecretRepository.where(repo_name: repo_name).pluck(:shixun_id).first
logger.info("####repo_name:#{repo_name}")
logger.info("####shixun_id:#{shixun_id}")
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).find_by(id: shixun_id)
end
uid_logger("git start auth: shixun identifier is #{shixun.try(:identifier)}")
uid_logger("git start auth: systemuser is #{system_user.try(:login)}")

@ -1,9 +1,9 @@
class HackUserLastestCodesController < ApplicationController
before_action :require_login, except: [:listen_result]
before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code,
:listen_result, :result, :submit_records]
: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]
before_action :require_auth_identity, only: [:update_code, :restore_initial_code]
before_action :require_manager_identity, only: [:update_code]
def show
@ -12,6 +12,13 @@ class HackUserLastestCodesController < ApplicationController
def update_code
@my_hack.update_attribute(:code, params[:code])
render_ok
end
# 回复初始代码
def restore_initial_code
@my_hack.update_attribute(:code, @hack.code)
render_ok
end
# 调试代码
@ -35,7 +42,7 @@ class HackUserLastestCodesController < ApplicationController
# 提交结果显示
def result
if @my_hack.submit_status == 1
render json: {status:0, message: "正在评测中"}
render json: {status: 1, message: "正在评测中"}
else
@mode = params[:mode]
@result =
@ -103,9 +110,9 @@ class HackUserLastestCodesController < ApplicationController
if exec_mode == "submit"
@hack.hack_sets.map{|set| {input: set.input, output: set.output, caseId: set.id}}
else
{input: params[:input]}
[{input: params[:input]}]
end
testCases = Base64.urlsafe_encode64(test_sets.to_json)
testCases = Base64.encode64(test_sets.to_json)
#codeFileContent = Base64.urlsafe_encode64(@my_hack.code)
debug_params = {execMode: exec_mode,
tpiID: @my_hack.identifier,
@ -121,6 +128,7 @@ class HackUserLastestCodesController < ApplicationController
# 正则错误行数
def regular_match_error_line content, language
content = Base64.decode64(content).force_encoding("utf-8")
case language
when 'Java'
content.scan(/.java.\d+/).map{|s| s.match(/\d+/)[0].to_i}.min
@ -136,7 +144,9 @@ class HackUserLastestCodesController < ApplicationController
if @my_hack.hack_user_debug.present?
@my_hack.hack_user_debug.update_attributes!(debug_params)
else
@my_hack.hack_user_debug.create!(debug_params)
debug = HackUserDebug.new(debug_params)
debug.hack_user_lastest_code_id = @my_hack.id
debug.save!
end
end

@ -1,8 +1,9 @@
class HacksController < ApplicationController
before_action :require_login, except: [:index]
before_action :require_teacher_identity, only: [:create, :edit, :update]
before_action :require_auth_identity, only: [:update, :edit, :publish]
before_action :find_hack, only: [:edit, :update, :publish, :start]
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]
# 开启编程,如果第一次开启,创建一条记录,如果已经开启过的话,直接返回标识即可
def start
@ -19,7 +20,7 @@ class HacksController < ApplicationController
@hack.hack_user_lastest_codes.create!(user_code)
user_identifier
end
render_ok(data: {identifier: identifier})
render_ok(identifier: identifier)
end
# 首页
@ -27,7 +28,7 @@ class HacksController < ApplicationController
# 筛选过滤与排序
params_filter_or_order
# 我解决的编程题数
user_codes = HackUserLastestCode.mine(current_user).passed.joins(:hack)
user_codes = HackUserLastestCode.joins(:hack).mine_hack(current_user).passed
@simple_count = user_codes.where(hacks: {difficult: 1}).count
@medium_count = user_codes.where(hacks: {difficult: 2}).count
@diff_count = user_codes.where(hacks: {difficult: 3}).count
@ -46,6 +47,8 @@ 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)
end
@ -75,6 +78,20 @@ class HacksController < ApplicationController
end
end
# 更新测试集接口
def update_set
set = @hack.hack_sets.find_by(id: params[:id])
set.update_attributes!(hack_set_params)
render_ok
end
# 单独删除测试集
def delete_set
set = @hack.hack_sets.find_by(id: params[:id])
set.destroy!
render_ok
end
# 发布功能
def publish
@hack.update_attribute(:status, 1)
@ -119,6 +136,10 @@ class HacksController < ApplicationController
params.permit(hack_sets: [:input, :output, :position])[:hack_sets]
end
def hack_set_params
params.require(:hack_set).permit(:id, :input, :output, :position)
end
def hack_code_params
params.require(:hack_codes).permit(:code, :language)
end
@ -144,7 +165,8 @@ class HacksController < ApplicationController
if params[:come_from]
hacks = Hack.select(select_sql).mine(current_user.id)
else
hacks = Hack.select(select_sql).published.opening
# 全部包括已经发布的,和我的未发布的
hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id))
end
# 搜索
if params[:search]
@ -162,9 +184,14 @@ class HacksController < ApplicationController
hacks = hacks.where.not(id: user_hacks.pluck(:hack_id))
end
else
hacks = hacks.joins(:hack_user_lastest_code).where(hack_user_lastest_code: {status: params[:status]})
hacks = hacks.joins(:hack_user_lastest_codes).where(hack_user_lastest_codes: {status: params[:status]})
end
end
# 分类
if params[:category]
hacks = hacks.where(category: params[:category])
end
# 排序
sort_by = params[:sort_by] || "hack_user_lastest_codes_count"
sort_direction = params[:sort_direction] || "desc"

@ -25,7 +25,16 @@ class HelpsController < ApplicationController
end
def feedback
if params[:url].blank?
content = "<p>[#{params[:question_kind]}]</p></p>#{params[:description]}"
if params[:attachment_ids]
params[:attachment_ids].each do |attachment_id|
content += "![](/api/attachments/#{attachment_id})↵"
end
end
else
content = "<p>[#{params[:question_kind]}]</p><p>问题页面网址:#{params[:url]}</p>#{params[:description]}"
end
ActiveRecord::Base.transaction do
attr = { sender_id: User.current.id, receiver_id: 1, content: content, send_time: Time.now }

@ -30,10 +30,10 @@ class HomeController < ApplicationController
@main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8)
@main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8)
if current_laboratory.main_site?
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
end
# if current_laboratory.main_site?
# @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
# @stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
# end
end
def search

@ -13,7 +13,8 @@ class HomeworkCommonsController < ApplicationController
:reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation,
:update_score, :update_student_score]
before_action :user_course_identity
before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer, :update_student_score]
before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer,
:update_student_score]
before_action :teacher_allowed, only: [:new, :edit, :create, :update, :shixuns, :subjects, :create_shixun_homework,
:publish_homework, :end_homework, :set_public, :choose_category, :move_to_category,
:choose_category, :create_subject_homework, :multi_destroy, :group_list, :homework_code_repeat,
@ -64,6 +65,9 @@ class HomeworkCommonsController < ApplicationController
end
unless order.blank?
if @course.is_end
@homework_commons = @homework_commons.none
else
case order
when '1'
sql_str = %Q(homework_detail_manuals.comment_status = #{order} and homework_commons.end_time > '#{Time.now}')
@ -80,6 +84,7 @@ class HomeworkCommonsController < ApplicationController
end
@homework_commons = @homework_commons.joins(:homework_detail_manual).where(sql_str)
end
end
@task_count = @homework_commons.size
order_str = @homework_type == 4 ? "position DESC" : "IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC,
@ -577,8 +582,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_i <= 0
tip_exception("效率分不能大于总分值") if params[:eff_score] && params[:eff_score].to_i > params[:total_score].to_i
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("缺少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?
@ -586,12 +591,12 @@ class HomeworkCommonsController < ApplicationController
# tip_exception("challenge_id参数的长度与challenge_score参数的长度不匹配") if
# params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length
current_eff_score = @homework.eff_score
current_eff_score = @homework.eff_score.to_f.round(2)
@homework.total_score = params[:total_score]
@homework.work_efficiency = params[:work_efficiency]
@homework.eff_score = params[:work_efficiency] ? params[:eff_score].to_i : 0
@homework.eff_score = params[:work_efficiency] ? params[:eff_score].to_f.round(2) : 0
update_eff_score = current_eff_score != @homework.eff_score
update_eff_score = current_eff_score.round(2) != @homework.eff_score.round(2)
if @homework_detail_manual.answer_open_evaluation != params[:answer_open_evaluation]
@homework_detail_manual.answer_open_evaluation = params[:answer_open_evaluation]
@ -625,14 +630,10 @@ class HomeworkCommonsController < ApplicationController
@homework.score_open = params[:score_open]
@homework.save!
# if score_change
# @homework.student_works.has_committed.each do |student_work|
# HomeworksService.new.set_shixun_final_score student_work
# end
# end
# 更新所有学生的效率分(作业允许补交且补交已截止 或者 作业不允许补交且提交已截止)
if update_eff_score && @homework.end_or_late_none_group
if score_change && @homework.end_or_late_none_group
UpdateShixunWorkScoreJob.perform_now(@homework.id)
elsif update_eff_score && (@homework.end_or_late_none_group || @homework.max_efficiency > 0)
# 更新所有学生的效率分(作业允许补交且补交已截止 或者 作业不允许补交且提交已截止 或者作业已计算过效率分)
HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: @homework.id)
end

@ -2,6 +2,7 @@ class Oauth::BaseController < ActionController::Base
include RenderHelper
include LoginHelper
include ControllerRescueHandler
include LaboratoryHelper
skip_before_action :verify_authenticity_token
@ -12,7 +13,8 @@ class Oauth::BaseController < ActionController::Base
private
def session_user_id
session[:user_id]
# session[:user_id]
session[:"#{default_yun_session}"]
end
def current_user
@ -23,4 +25,9 @@ class Oauth::BaseController < ActionController::Base
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
request.env['omniauth.auth']
end
def default_yun_session
@_default_yun_session = "#{request.subdomain.split('.').first}_user_id"
# @_default_yun_session = "#{current_laboratory.try(:identifier).split('.').first}_user_id"
end
end

@ -235,9 +235,9 @@ class PollQuestionsController < ApplicationController
end
def validates_params
normal_status(-1, "问题标题不能为空!") if params[:question_title].blank?
normal_status(-1, "题目不能为空!") if params[:question_title].blank?
normal_status(-1, "是否要求必答的值不能为空!") if params[:is_necessary].blank?
normal_status(-1, "题类型不能为空!") if params[:question_type].blank?
normal_status(-1, "类型不能为空!") if params[:question_type].blank?
if params[:min_choices].present? && params[:max_choices].present? && (params[:min_choices].to_i > params[:max_choices].to_i)
normal_status(-1, "最小可选不能大于最大可选!")
elsif params[:question_answers].present? && (params[:max_choices].to_i > params[:question_answers].count)
@ -247,9 +247,9 @@ class PollQuestionsController < ApplicationController
elsif params[:question_type] == 3 && (params[:question_answers] || params[:question_other_answer])
normal_status(-1, "主观问题不需要可选答案!")
elsif params[:question_type] != 3
if params[:question_answers].present? && params[:question_answers].include?("")
normal_status(-1, "择题不能有空值!")
elsif params[:question_other_answer].present? && params[:question_other_answer].length > 0
if params[:question_answers].present? && params[:question_answers].select{|answer| answer.blank?}.count > 0
normal_status(-1, "不能有空值!")
elsif params[:question_other_answer].present? && !params[:question_other_answer].blank?
normal_status(-1, "其他选项不能有值!")
elsif params[:question_type] == 1 && params[:question_answers].count < 2
normal_status(-1, "单选题选项不能小于2")

@ -198,14 +198,14 @@ class PollsController < ApplicationController
def common_header
ActiveRecord::Base.transaction do
begin
@poll_status = @poll.get_poll_status(current_user)
if @user_course_identity > Course::ASSISTANT_PROFESSOR
@is_teacher_or = 0
@user_poll_answer = @poll.check_user_votes_status(current_user)
@user_poll_answer = @poll.check_user_votes_status(current_user, @poll_status)
else
@is_teacher_or = 1
@user_poll_answer = 3 #教师页面
end
@poll_status = @poll.get_poll_status(current_user)
poll_id_array = [@poll.id]
@poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的
@poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的

@ -10,11 +10,11 @@ class ShixunsController < ApplicationController
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file, :shixun_list]
: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,
:get_mirror_script, :download_file, :shixun_list, :review_shixuns]
: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 :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish,
@ -515,7 +515,7 @@ class ShixunsController < ApplicationController
end
# 添加第二仓库
if params[:is_secret_repository]
add_secret_repository
add_secret_repository if @shixun.shixun_secret_repository.blank?
else
# 如果有仓库,就要删
if @shixun.shixun_secret_repository&.repo_name
@ -977,9 +977,7 @@ class ShixunsController < ApplicationController
@courses = Course.where(:id => course_ids)
## 云上实验室过滤
unless current_laboratory.main_site?
@courses = @courses.where(laboratory_id: current_laboratory.id )
end
@courses = @courses.where(id: current_laboratory.all_courses)
@course_count = @courses.count
@courses = @courses.page(page).per(limit)
@ -992,6 +990,16 @@ class ShixunsController < ApplicationController
CreateStudentWorkJob.perform_later(homework.id)
end
# 批量发送
def batch_send_to_course
@course = Course.find_by!(id: params[:course_id])
shixuns = Shixun.where(id: params[:shixun_ids]).unhidden
shixuns.each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, nil, current_user
CreateStudentWorkJob.perform_later(homework.id)
end
end
# 二维码扫描下载
def download_file
file_path = params[:file_name]

@ -2,7 +2,7 @@ class SubjectsController < ApplicationController
before_action :require_login, :check_auth, except: [:index, :show, :right_banner]
# before_action :check_auth, except: [:index]
before_action :check_account, except: [:index, :show, :right_banner]
before_action :find_subject, except: [:index, :create, :new, :append_to_stage]
before_action :find_subject, except: [:index, :create, :new, :append_to_stage, :add_shixun_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish,
:search_members, :add_subject_members, :statistics, :shixun_report, :school_report,
:up_member_position, :down_member_position, :update_team_title]
@ -10,6 +10,7 @@ class SubjectsController < ApplicationController
include ApplicationHelper
include SubjectsHelper
include GitCommon
def index
@tech_system = current_laboratory.subject_repertoires
@ -212,15 +213,36 @@ class SubjectsController < ApplicationController
@shixuns = Shixun.where(id: params[:shixun_id]).order("id desc")
end
# 添加实训项目
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_members.create!(user_id: current_user.id, role: 1)
# 创建长字段
ShixunInfo.create!(shixun_id: @shixun.id, description: "请在此处添加实训描述")
# 创建版本库
repo_path = repo_namespace(current_user.login, identifier)
GitService.add_repository(repo_path: repo_path)
# todo: 为什么保存的时候要去除后面的.git呢??
@shixun.update_column(:repo_name, repo_path.split(".")[0])
mirror_id = MirrorRepository.find_by(type_name: 'Python3.6')&.id
if mirror_id
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror_id)
@shixun.shixun_service_configs.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror_id)
end
end
end
def choose_course
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m
WHERE m.course_id = c.id AND m.role in (1,2,3)
AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
@courses = Course.where(id: course_ids)
## 云上实验室过滤
unless current_laboratory.main_site?
@courses = @courses.where(laboratory_id: current_laboratory.id )
end
@courses = @courses.where(id: current_laboratory.all_courses)
@none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id)
end

@ -6,6 +6,7 @@ class TidingsController < ApplicationController
def index
tidings = current_user.tidings
@onclick_time = current_user.click_time
tiding_types =
case params[:type]
@ -18,11 +19,13 @@ class TidingsController < ApplicationController
end
tidings = tidings.where(tiding_type: tiding_types) if tiding_types.present?
tidings = tidings.where(container_type: 'JoinCourse') if params[:type] == 'course_apply'
@course_apply_count = tidings.where("created_at > '#{@onclick_time}'").where(container_type: 'JoinCourse').count
tidings = tidings.where(container_type: 'ProjectPackage') if params[:type] == 'project_package'
@count = tidings.count
@tidings = paginate(tidings.order(created_at: :desc), per_page: 10)
@onclick_time = current_user.click_time
end
private

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

@ -15,6 +15,8 @@ class Weapps::CodeSessionsController < Weapps::BaseController
logged = true
else
# 根据 code没拿到 unionid
Rails.logger.info("[Weapp] session_key: #{result['session_key']}")
Rails.logger.info("[Weapp] code: #{params[:code]}")
user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
# 老用户,已绑定

@ -1,6 +1,8 @@
class Weapps::CoursesController < Weapps::BaseController
before_action :require_login
before_action :teacher_allowed, except: [:create, :show, :shixun_homework_category]
before_action :set_course, :user_course_identity, except: [:create]
before_action :teacher_allowed, only: [:edit, :update]
before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers]
def create
return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher?
@ -30,6 +32,140 @@ class Weapps::CoursesController < Weapps::BaseController
@categories = current_course.shixun_course_modules.first&.course_second_categories
end
# 教师列表
def teachers
@course = current_course
@page = (params[:page] || 1).to_i
@limit = (params[:limit] || 20).to_i
search = params[:search].present? ? params[:search].strip : ""
if @course.try(:id) != 1309 || current_user.admin? || current_user.try(:id) == 15582
@teacher_list = @course.course_members.joins(:user).where("course_members.role in (1, 2, 3)")
else
@teacher_list = @course.course_members.joins(:user).where("(course_members.role in (1, 3) or (course_members.user_id = #{current_user.id}
and course_members.role = 2))")
end
if search.present?
@teacher_list = @teacher_list.joins(:user).where("LOWER(CONCAT(users.lastname, users.firstname)) like ?", "%#{search}%")
end
@teacher_list_size = @teacher_list.size
@applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size
@teacher_list = @teacher_list.includes(user: [user_extension: :school])
# 中英文混合排序(忽略大小写)
@teacher_list = @teacher_list.sort {|x, y| Pinyin.t(x.user&.real_name, splitter: '').upcase <=> Pinyin.t(y.user&.real_name, splitter: '').upcase}
@teacher_list = @teacher_list[(@page-1)*@limit ... @page*@limit]
end
# 批量删除教师或助教
def delete_course_teachers
begin
@course = current_course
@page = (params[:page] || 1).to_i
@limit = (params[:limit] || 20).to_i
course_members = @course.course_members.where(id: params[:course_member_ids], role: %i[PROFESSOR ASSISTANT_PROFESSOR])
user_ids = course_members.pluck(:user_id)
course_members.destroy_all
CourseDeleteStudentNotifyJob.perform_later(@course.id, user_ids, current_user.id)
@course.students.where(user_id: user_ids).update_all(is_active: 1)
normal_status(0, "删除成功")
rescue => e
uid_logger_error(e.message)
tip_exception("删除失败")
end
end
def students
@course = current_course
@page = (params[:page] || 1).to_i
@limit = (params[:limit] || 20).to_i
search = params[:search].present? ? params[:search].strip : nil
course_group_id = params[:course_group_id].present? ? params[:course_group_id].to_i : nil
@students = CourseMember.students(@course)
if search.present?
@students = @students.joins(user: :user_extension).where("LOWER(CONCAT(users.lastname, users.firstname)) like ? or
user_extensions.student_id like ?", "%#{search}%", "%#{search}%")
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)
end
@students_count = @students.size
@students = @students.includes(user: :user_extension)
# 中英文混合排序(忽略大小写)
@students = @students.sort {|x, y| Pinyin.t(x.user&.real_name, splitter: '').upcase <=> Pinyin.t(y.user&.real_name, splitter: '').upcase}
@students = @students[(@page-1)*@limit ... @page*@limit]
end
# 批量修改角色
def change_member_roles
@course = current_course
tip_exception("请至少选择一个角色") if params[:roles].blank?
tip_exception("不能具有老师、助教两种角色") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR")
params[:user_ids].each do |user_id|
course_members = @course.course_members.where(user_id: user_id)
tip_exception("非课堂成员不能修改角色") if course_members.blank?
ActiveRecord::Base.transaction do
# 第一次修改为教师或助教身份时直接创建数据
if params[:roles].include?("CREATOR")
teacher_member = course_members.where(role: %i[CREATOR]).take
elsif (params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR")) && !course_members.exists?(role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR])
teacher_member = CourseMember.create!(course_id: @course.id, user_id: user_id, role: params[:roles].include?("PROFESSOR") ? 2 : 3)
# 如果有未审批的申请教师/助教的记录,则修改状态为已审批
apply_teacher = CourseMessage.where(course_id: @course.id, course_message_id: user_id, status: 0).last
apply_teacher.update!(status: 1, apply_user_id: current_user.id) if apply_teacher
elsif course_members.exists?(role: %i[PROFESSOR ASSISTANT_PROFESSOR])
teacher_member = course_members.where(role: %i[PROFESSOR ASSISTANT_PROFESSOR]).take
if params[:roles].include?("PROFESSOR") || params[:roles].include?("ASSISTANT_PROFESSOR")
# 如果之前有老师身份且老师身份要调整时只需要修改role字段
if !params[:roles].include?(teacher_member.role) && params[:roles].include?("PROFESSOR")
teacher_member.PROFESSOR!
elsif !params[:roles].include?(teacher_member.role) && params[:roles].include?("ASSISTANT_PROFESSOR")
teacher_member.ASSISTANT_PROFESSOR!
end
teacher_member.save!
else
# 不含教师的参数时删除记录
teacher_member.destroy!
# CourseDeleteStudentNotifyJob.perform_later(@course.id, [teacher_member.user_id], current_user.id)
end
end
# 学生身份的处理
student_member = course_members.where(role: %i[STUDENT]).take
# 不存在则创建学生身份
if params[:roles].include?("STUDENT") && student_member.blank?
correspond_teacher_exist = CourseMember.exists?(user_id: user_id, is_active: 1, course_id: @course.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR])
new_student = CourseMember.new(user_id: user_id, course_id: @course.id, role: 4)
new_student.is_active = 0 if correspond_teacher_exist
new_student.save!
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)
# 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
student_member.update_attributes!(is_active: 1)
end
end
end
normal_status(0, "修改成功")
end
private
def course_params
@ -45,6 +181,18 @@ class Weapps::CoursesController < Weapps::BaseController
end
def teacher_allowed
return render_forbidden unless current_user.course_identity(current_course) < Course::STUDENT
return render_forbidden unless @user_course_identity < Course::STUDENT
end
# 课堂教师,课堂管理员以及超级管理员的权限判断
def teacher_or_admin_allowed
unless @user_course_identity < Course::ASSISTANT_PROFESSOR
tip_exception(403, "..")
end
end
def set_course
@course = Course.find_by!(id: params[:id])
tip_exception(404, "") if @course.is_delete == 1 && !current_user.admin?
end
end

@ -48,9 +48,10 @@ class Weapps::RegistersController < Weapps::BaseController
)
end
successful_authentication(@user)
session[:user_id] = @user.id
# session[:user_id] = @user.id
session[:"#{default_yun_session}"] = @user.id
render_ok
# render_ok(user_id: @user.id)
end
private

@ -77,7 +77,7 @@ module PollsHelper
ex_pb_time = poll.get_poll_times(user.id,false)
poll_publish_time = ex_pb_time[:publish_time]
poll_end_time = ex_pb_time[:end_time]
current_status = poll.check_user_votes_status(user)
current_status = poll.check_user_votes_status(user, poll_status)
lock_icon = 0 #不显示锁图标
else
poll_users_list = poll.get_poll_exercise_users

@ -0,0 +1,67 @@
module Weapps::CoursesHelper
require 'chinese_pinyin'
def teacher_list teachers
data = []
teachers.each do |teacher|
if teacher.user.present?
teacher_user = teacher.user
name = teacher_user.real_name
role = teacher.role == "CREATOR" ? "管理员" : teacher.role == "PROFESSOR" ? "教师" : "助教"
item = {name: name, course_member_id: teacher.id, login: teacher_user.login, user_id: teacher.user_id, role: role,
school: teacher_user.school_name, image_url: url_to_avatar(teacher_user)}
pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0]
letter = first_letter first_char
if data.pluck(:letter).include?(letter)
data.select{|a|a[:letter]==letter}.first[:items] << item
else
data << {letter: letter, items: [item]}
end
end
end
# data = data.sort do |a, b|
# [a[:letter]] <=> [b[:letter]]
# end
# data.push(data.shift) if data.select{|a|a[:letter]=='#'}.first.present? # '#'排在最后
return data
end
def student_list students, excellent
data = []
students.each do |student|
if student.user.present?
student_user = student.user
name = student_user.real_name
phone = excellent ? "" : student_user.hidden_phone
item = {name: name, course_member_id: student.id, login: student_user.login, user_id: student.user_id,
student_id: student_user.student_id, image_url: url_to_avatar(student_user), phone: phone}
pinyin = Pinyin.t(name.strip, splitter: '')
first_char = pinyin[0]
letter = first_letter first_char
if data.pluck(:letter).include?(letter)
data.select{|a|a[:letter]==letter}.first[:items] << item
else
data << {letter: letter, items: [item]}
end
end
end
# data = data.sort do |a, b|
# [a[:letter]] <=> [b[:letter]]
# end
# data.push(data.shift) if data.select{|a|a[:letter]=='#'}.first.present? # '#'排在最后
return data
end
def first_letter char
if char.ord >= 97 && char.ord <= 122
letter = (char.ord - 32).chr.to_s
elsif char.ord >= 65 && char.ord <= 90
letter = char
else
letter = '#'
end
letter
end
end

@ -0,0 +1,10 @@
class UpdateShixunWorkScoreJob < ApplicationJob
queue_as :default
def perform(homework_id)
homework = HomeworkCommon.find_by(id: homework_id)
return if homework.blank?
homework.update_homework_work_score
end
end

@ -31,7 +31,9 @@ class Wechat::Weapp
cipher.padding = 0
cipher.key = session_key
cipher.iv = iv
Rails.logger.info("[Weapp] encrypted_data: #{encrypted_data}")
data = cipher.update(encrypted_data) << cipher.final
Rails.logger.info("[Weapp] data: #{data}")
result = JSON.parse(data[0...-data.last.ord])
raise Wechat::Error.new(-1, '解密错误') if result.dig('watermark', 'appid') != appid

@ -23,6 +23,7 @@ class Attachment < ApplicationRecord
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 :search_by_container, -> (ids) {where(container_id: ids)}
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
validates_length_of :description, maximum: 100

@ -3,4 +3,6 @@ class AttachmentGroupSetting < ActiveRecord::Base
belongs_to :course_group
belongs_to :course
scope :none_published, -> {where("attachment_group_settings.publish_time IS NULL OR attachment_group_settings.publish_time > ?", Time.now)}
end

@ -31,6 +31,7 @@ class Course < ApplicationRecord
has_many :graduation_groups, dependent: :destroy
has_many :course_members, dependent: :destroy
has_many :students, -> { course_students }, class_name: 'CourseMember'
has_many :teacher_course_members, -> { teachers_and_admin }, class_name: 'CourseMember'
has_many :teacher_users, through: :teacher_course_members, source: :user
has_many :course_messages, dependent: :destroy
@ -114,6 +115,10 @@ class Course < ApplicationRecord
course_members.where(user_id: user_id, role: role).exists?
end
def course_group_module?
course_modules.exists?(module_type: "course_group", hidden: 0)
end
# 作业对应的子目录/父目录名称
def category_info type
course_module = course_modules.find_by(module_type: type)
@ -234,11 +239,6 @@ class Course < ApplicationRecord
course_members.where(role: %i[CREATOR PROFESSOR])
end
# 课堂学生
def students
course_members.where(role: %i[STUDENT])
end
# 更新课程的访问人数
def update_visits(new_visits)
update_attributes(visits: new_visits)
@ -367,6 +367,23 @@ class Course < ApplicationRecord
count = course_challeng_count == 0 ? 0 : ((my_challenge_count.to_f / course_challeng_count).round(2) * 100).to_i
end
# 课堂实训作业的评测次数
def evaluate_count
course_user_ids = students.pluck(:user_id)
shixun_ids = homework_commons.joins(:homework_commons_shixun).where(homework_type: 4).pluck(:shixun_id)
return 0 if shixun_ids.blank?
Game.joins(:challenge).where(challenges: {shixun_id: shixun_ids}, games: {user_id: course_user_ids}).sum(:evaluate_count)
end
def max_activity_time
course_acts.pluck(:updated_at).max
end
# 课堂作业数
def course_homework_count type
homework_commons.select{|homework| homework.homework_type == type}.size
end
private
#创建课程后,给该用户发送消息

@ -5,4 +5,5 @@ class CourseList < ApplicationRecord
has_many :exercise_banks
has_many :gtask_banks
has_many :gtopic_banks
belongs_to :user
end

@ -3,7 +3,7 @@
# modify_time 与challenges表的modify_time联合使用2个字段一致则标识测试集未修改反之被修改
# answer_open: 查看查看答案的深度, 0: 未查看过答案, 其他数值与challenge_answer的level值相关
# answer_deduction: 查看答案扣分的百分比;如 查看答案 扣除70%
#
#play_sign 与play_time: sign记录浏览器是否正常关闭 0表示正常1表示非正常 play_time表示游玩时间
class Game < ApplicationRecord
default_scope { order("games.created_at desc") }

@ -12,6 +12,7 @@ class Hack < ApplicationRecord
belongs_to :user
scope :published, -> { where(status: 1) }
scope :unpublish, -> { where(status: 0) }
scope :opening, -> {where(open_or_not: 1)}
scope :mine, -> (author_id){ where(user_id: author_id) }
@ -25,9 +26,11 @@ class Hack < ApplicationRecord
def code
if hack_codes.count == 1
tran_base64_decode64(hack_codes.first.code)
#tran_base64_decode64(hack_codes.first.code)
hack_codes.first.code
else
tran_base64_decode64(hack_codes.pluck(:code))
#tran_base64_decode64(hack_codes.pluck(:code))
hack_codes.pluck(:code)
end
end

@ -1,4 +1,6 @@
class HackSet < ApplicationRecord
validates :input, presence: { message: "测试集输入不能为空" }
validates :output, presence: { message: "测试集输出不能为空" }
# 编程题测试集
belongs_to :hack
end

@ -9,6 +9,7 @@ class HackUserLastestCode < ApplicationRecord
has_many :hack_user_codes, dependent: :destroy
has_one :hack_user_debug
scope :mine, ->(author_id){ find_by(user_id: author_id) }
scope :mine_hack, ->(author_id){ where(user_id: author_id) }
scope :passed, -> {where(status: 1)}
end

@ -54,6 +54,10 @@ class Laboratory < ApplicationRecord
main_site? ? Subject.all : Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id })
end
def all_courses
main_site? || !sync_course ? courses : courses.or(Course.where(school_id: school_id))
end
def shixun_repertoires
where_sql = ShixunTagRepertoire.where("shixun_tag_repertoires.tag_repertoire_id = tag_repertoires.id")

@ -128,7 +128,7 @@ class Poll < ApplicationRecord
en_time = end_time
else
poll_group_setting = poll_group_settings
user_group = course.course_members.where(user_id: user_id).select(:course_group_id)
user_group = course.students.where(user_id: user_id).select(:course_group_id)
if user_group.exists?
user_group_id = user_group.first&.course_group_id
user_p_group_setting = poll_group_setting.where(course_group_id: user_group_id).select(:publish_time,:end_time)
@ -146,12 +146,22 @@ class Poll < ApplicationRecord
end
#判断当前用户的答题状态
def check_user_votes_status(user)
def check_user_votes_status(user, poll_status)
poll_answer_user = poll_users.where(user_id: user.id).select(:start_at,:end_at,:commit_status)
user_status = 2
if poll_answer_user.exists? && (poll_answer_user.first&.start_at.present? || poll_answer_user.first&.end_at.present?) #学生有过答题的,或者立即截止,但学生未做试卷的
user_status = poll_answer_user.first.commit_status
end
# 问卷已截止时学生的答题状态需要考虑问卷的状态
if poll_status > 2
# 问卷如果还是继续答题状态则自动提交
if user_status == 0
poll_end_time = get_poll_times(user.id,false)[:end_time]
poll_answer_user.first.update_attributes!(:commit_status => 1, :end_at => poll_end_time)
user_status = 1
end
user_status = user_status == 1 ? 1 : 4
end
user_status
end

@ -7,6 +7,9 @@ class Project < ApplicationRecord
has_many :issues
has_many :user_grades, dependent: :destroy
has_many :attachments, as: :container, dependent: :destroy
has_one :project_score, dependent: :destroy
has_many :versions, -> { order("versions.effective_date DESC, versions.name DESC") }, dependent: :destroy
after_create do
SyncTrustieJob.perform_later("project", 1) if allow_sync_to_trustie?

@ -39,7 +39,7 @@ module Searchable::Shixun
end
def should_index?
[0, 1, 2].include?(status) # published
!hidden? && [0, 1, 2].include?(status) # published
end
def to_searchable_json

@ -28,6 +28,7 @@ class Shixun < ApplicationRecord
has_one :first_tag_repertoire, through: :first_shixun_tag_repertoire, source: :tag_repertoire
has_many :homework_commons_shixuns, class_name: 'HomeworkCommonsShixun'
has_many :fork_shixuns, foreign_key: "fork_from", class_name: 'Shixun'
#实训的关卡
has_many :exercise_shixun_challenges, :dependent => :destroy
@ -52,6 +53,7 @@ class Shixun < ApplicationRecord
has_many :shixun_reviews, -> {order("shixun_reviews.created_at desc")}, :dependent => :destroy
has_many :laboratory_shixuns, dependent: :destroy
belongs_to :laboratory, optional: true
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
"%#{keyword}%", "%#{keyword}%") }
@ -97,7 +99,7 @@ class Shixun < ApplicationRecord
end
def fork_identifier
self.fork_from.nil? ? "--" : Shixun.where(id: self.fork_from).first.try(:identifier)
self.fork_from.nil? ? "--" : fork_shixuns.first&.identifier
end
def shixun_status
@ -171,7 +173,7 @@ class Shixun < ApplicationRecord
end
def owner
User.find(self.user_id)
User.find_by_id(self.user_id)
end
def shixun_main_name

@ -3,5 +3,5 @@ class ShixunTagRepertoire < ApplicationRecord
belongs_to :tag_repertoire
has_many :memos, :through => :memo_tag_repertoires
has_many :memo_tag_repertoires, :dependent => :destroy
# has_many :memo_tag_repertoires, :dependent => :destroy
end

@ -111,14 +111,14 @@ class StudentWork < ApplicationRecord
# 作品总体评价
def overall_appraisal
case self.work_score.to_i
when (90..100)
case (self.work_score.to_f / homework_common.total_score).round(2)
when (0.90..1.00)
'优秀'
when (70...90)
when (0.70...0.90)
'良好'
when (60...70)
when (0.60...0.70)
'及格'
when (0...60)
when (0.00...0.60)
'不及格'
end
end

@ -329,7 +329,7 @@ class User < ApplicationRecord
# 实训路径合作者、admin
def manager_of_subject?(subject)
subject.subject_members.exists?(user_id: id, role: [1,2]) || admin?
subject.subject_members.exists?(user_id: id, role: [1,2]) || admin? || business?
end
# 实训管理员实训合作者、admin
@ -699,6 +699,10 @@ class User < ApplicationRecord
LimitForbidControl::UserLogin.new(self).clear
end
def from_sub_site?
laboratory_id.present? && laboratory_id != 1
end
protected
def validate_password_length
# 管理员的初始密码是5位

@ -0,0 +1,3 @@
class Version < ApplicationRecord
belongs_to :project
end

@ -0,0 +1,30 @@
class Admins::CourseListQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
course_lists = CourseList.all
# 关键字模糊查询
keyword = params[:keyword].to_s.strip
if keyword.present?
search_type = params[:search_type] || "0"
case search_type
when "0"
course_lists = course_lists.joins(:user)
.where('CONCAT(lastname, firstname) like :keyword', keyword: "%#{keyword}%")
when "1"
course_lists = course_lists.where('name like :keyword', keyword: "%#{keyword}%")
end
end
custom_sort(course_lists, params[:sort_by], params[:sort_direction])
end
end

@ -0,0 +1,44 @@
class Admins::CourseQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc, default_table: 'courses'
def initialize(params)
@params = params
end
def call
courses = Course.all
courses = courses.where(id: params[:id]) if params[:id].present?
# 状态过滤
status =
case params[:status].to_s.strip
when 'processing' then 0
when 'ended' then 1
end
courses = courses.where(is_end: status) if status
# 单位
if params[:school_id].present?
courses = courses.where(school_id: params[:school_id])
end
# 首页展示
if params[:homepage_show].present? && params[:homepage_show].to_s == 'true'
courses = courses.where(homepage_show: true)
end
# 关键字
keyword = params[:keyword].to_s.strip
if keyword
sql = 'CONCAT(lastname, firstname) LIKE :keyword OR courses.name LIKE :keyword OR course_lists.name LIKE :keyword'
courses = courses.joins(:teacher, :course_list).where(sql, keyword: "%#{keyword}%")
end
custom_sort(courses, params[:sort_by], params[:sort_direction])
end
end

@ -13,11 +13,10 @@ class Admins::SchoolQuery < ApplicationQuery
schools = School.all
keyword = strip_param(:keyword)
schools = schools.where('schools.name LIKE ?', "%#{keyword}%") if keyword
schools = schools.joins(:user_extensions).group(:id)
schools = schools.select('schools.*, COUNT(*) AS users_count')
Rails.logger.info("###########{keyword}")
if keyword
schools = schools.where('schools.name LIKE ?', "%#{keyword}%")
end
custom_sort schools, params[:sort_by], params[:sort_direction]
end
end

@ -10,6 +10,7 @@ class Admins::IdentityAuths::RefuseApplyService < ApplicationService
def call
ActiveRecord::Base.transaction do
apply.update!(status: 2, remarks: reason)
user.update!(authentication: false)
deal_tiding!
apply.attachment&.destroy

@ -10,6 +10,7 @@ class Admins::ProfessionalAuths::RefuseApplyService < ApplicationService
def call
ActiveRecord::Base.transaction do
apply.update!(status: 2, remarks: reason)
user.update!(professional_certification: false)
deal_tiding!
apply.attachment&.destroy

@ -3,6 +3,12 @@ class ApplicationService
Error = Class.new(StandardError)
def regix_emoji content
" " if content.blank?
regex = /[^a-zA-Z0-9\u4E00-\u9FFF]/
content.gsub(regex, '')
end
private
def strip(str)

@ -17,7 +17,8 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
new_user = true
# 新用户
login = User.generate_login('Q')
@user = User.new(login: login, nickname: params.dig('info', 'nickname'), type: 'User', status: User::STATUS_ACTIVE)
#nickname = regix_emoji params.dig('info', 'nickname')
@user = User.new(login: login, type: 'User', status: User::STATUS_ACTIVE)
end
ActiveRecord::Base.transaction do
@ -31,7 +32,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
Util.download_file(params.dig('info', 'image'), avatar_path)
end
new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], extra: params.dig('extra', 'raw_info'))
new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'])
Rails.cache.write(new_open_user.can_bind_cache_key, 1, expires_in: 1.hours) if new_user # 方便后面进行账号绑定
end

@ -24,7 +24,10 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService
new_user = true
# 新用户
login = User.generate_login('w')
@user = User.new(login: login, nickname: result['nickname'], type: 'User', status: User::STATUS_ACTIVE)
# result['nickname'] = regix_emoji(result['nickname'])
@user = User.new(login: login, type: 'User', status: User::STATUS_ACTIVE)
#@user = User.new(login: login, nickname: result['nickname'], type: 'User', status: User::STATUS_ACTIVE)
end
ActiveRecord::Base.transaction do
@ -39,7 +42,7 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService
Util.download_file(result['headimgurl'], avatar_path)
end
new_open_user= OpenUsers::Wechat.create!(user: user, uid: result['unionid'], extra: result)
new_open_user= OpenUsers::Wechat.create!(user: user, uid: result['unionid'])
Rails.cache.write(new_open_user.can_bind_cache_key, 1, expires_in: 1.hours) if new_user # 方便后面进行账号绑定
end

@ -5,7 +5,8 @@ class Subjects::CopySubjectService < ApplicationService
@subject = subject
@user = user
@laboratory = laboratory
subject_params = subject.attributes.dup.except('id', 'copy_subject_id', 'user_id', 'homepage_show')
subject_params = subject.attributes.dup.except('id', 'copy_subject_id', 'user_id', 'homepage_show',
'stages_count', 'shixuns_count', 'stage_shixuns_count')
@to_subject = Subject.new(subject_params)
end
@ -59,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')
'use_scope', 'averge_star', 'myshixuns_count', 'challenges_count')
to_shixun.identifier = Util::UUID.generate_identifier(Shixun, 8)
to_shixun.user_id = user.id
if laboratory

@ -10,7 +10,7 @@ class Users::ApplyAuthenticationService < ApplicationService
raise Error, '请先完善基本信息' unless user.profile_completed?
Users::ApplyAuthenticationForm.new(params).validate!
raise Error, '您已经申请过实名认证了' if ApplyUserAuthentication.real_name_auth.processing.exists?(user_id: user.id)
# raise Error, '您已经申请过实名认证了' if ApplyUserAuthentication.real_name_auth.processing.exists?(user_id: user.id)
user.lastname = params[:name].to_s.strip
user.firstname = ''
@ -18,7 +18,9 @@ class Users::ApplyAuthenticationService < ApplicationService
user.show_realname = params[:show_realname].to_s == 'true' if params[:show_realname].to_s.present?
ActiveRecord::Base.transaction do
user.authentication = false
ApplyUserAuthentication.real_name_auth.processing.where(user_id: user.id).destroy_all
user.authentication = true
user.save!
user.user_extension.update!(gender: params[:gender].to_i) if params[:gender].present?

@ -12,15 +12,15 @@ class Users::ApplyProfessionalAuthService < ApplicationService
raise Error, '请先完善基本信息' unless user.profile_completed?
Users::ApplyProfessionalAuthForm.new(params).validate!
raise Error, '您已经申请过职业认证了' if ApplyUserAuthentication.professional_auth.processing.exists?(user_id: user.id)
user.professional_certification = false
# raise Error, '您已经申请过职业认证了' if ApplyUserAuthentication.professional_auth.processing.exists?(user_id: user.id)
extension = user.user_extension
extension.school_id = params[:school_id]
extension.department_id = params[:department_id]
extension.identity = params[:identity]
user.professional_certification = params[:identity] != "teacher"
extra = params[:extra].to_s.strip.presence
if extension.identity.to_s == 'student'
extension.technical_title = nil
@ -31,6 +31,7 @@ class Users::ApplyProfessionalAuthService < ApplicationService
end
ActiveRecord::Base.transaction do
ApplyUserAuthentication.professional_auth.processing.where(user_id: user.id).destroy_all
user.save!
extension.save!

@ -3,7 +3,7 @@ wb = xlsx_package.workbook
wb.styles do |s|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(name: "#{@competition.name}证书审批列表") do |sheet|
sheet.add_row %w(序号 排名 奖项 战队ID 战队名称 姓名 职业 学号 学校名称 学院名称 地区 实名认证 职业认证 手机号码 队长 签领/开户行及银行卡号 审批时间 审批人), :height => 25,:style => blue_cell
sheet.add_row %w(序号 排名 奖项 战队ID 战队名称 姓名 性别 职业 学号 学校名称 学院名称 地区 实名认证 职业认证 手机号码 队长 身份证号 签领/开户行及银行卡号 审批时间 审批人), :height => 25,:style => blue_cell
@all_prize_users.each_with_index do |prize_user, index|
user = prize_user.user
@ -14,15 +14,17 @@ wb.styles do |s|
prize_user.competition_team_id,
prize_user.competition_team.name,
user.real_name,
user.gender == 1 ? "女" : "男",
user.identity,
user.student_id,
user.student_id.present? ? (user.student_id.to_s + "\t") : "--",
user.school_name,
user.department_name,
user.location,
user.auth_status,
user.pro_status,
user.phone,
user.phone.present? ? (user.phone.to_s + "\t") : "--",
prize_user.leader? ? "是" : "-",
user.ID_number.present? ? (user.ID_number.to_s + "\t") : "--",
[prize_user.extra&.[]('bank'), prize_user.extra&.[]('second_bank'), prize_user.extra&.[]('card_no')].compact.join('/'),
prize_user.approved_at&.strftime('%Y-%m-%d %H:%M'),
prize_user.approver&.real_name

@ -0,0 +1,22 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('课程列表') %>
<% end %>
<div class="box search-form-container course-list-list-form">
<%= form_tag(admins_course_lists_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group">
<label>搜索类型:</label>
<% auto_trial_options = [['创建者姓名', 0], ['课程名称', 1]] %>
<%= select_tag(:search_type, options_for_select(auto_trial_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '输入关键字搜索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3','data-disable-with': '搜索中...') %>
<%= link_to "清除",admins_course_lists_path,class: "btn btn-default",id:"course-lists-clear-search",'data-disable-with': '清除中...' %>
<% end %>
</div>
<div class="box admin-list-container course-list-list-container">
<%= render partial: 'admins/course_lists/shared/list', locals: { courses: @course_lists } %>
</div>
<%= render 'admins/course_lists/shared/merge_course_list_modal' %>

@ -0,0 +1 @@
$(".course-list-list-container").html("<%= j render partial: 'admins/course_lists/shared/list', locals: { courses: @course_lists }%>");

@ -0,0 +1,37 @@
<table class="table table-hover text-center shixuns-list-table">
<thead class="thead-light">
<th width="4%">序号</th>
<th width="8%">ID</th>
<th width="38%" class="text-left">课程名称</th>
<th width="10%">课堂数</th>
<th width="10%">创建者</th>
<th width="12%"><%= sort_tag('创建时间', name: 'created_at', path: admins_course_lists_path) %></th>
<th width="18%">操作</th>
</thead>
<tbody>
<% if courses.present? %>
<% courses.each_with_index do |course_list,index| %>
<tr id="course-list-item-<%= course_list.id %>">
<td><%= list_index_no(@params_page.to_i, index) %></td>
<td><%= course_list.id %></td>
<td class="text-left"><%= course_list.name %></td>
<% course_count = course_list.courses.size %>
<td><%= course_count %></td>
<td><%= link_to course_list.user.try(:real_name),"/users/#{course_list.user.try(:login)}",target:'_blank' %></td>
<td><%= format_time course_list.created_at %></td>
<td class="operate">
<% if course_count == 0 %>
<%= delete_link '删除', admins_course_list_path(course_list, element: ".course-list-item-#{course_list.id}"), class: 'delete-department-action' %>
<% end %>
<%= javascript_void_link '修改', class: 'action', data: { course_list_id: course_list.id,
toggle: 'modal', target: '.admin-merge-course-list-modal', url: merge_admins_course_lists_path } %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: courses } %>

@ -0,0 +1,29 @@
<div class="modal fade admin-merge-course-list-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">修改课程</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-merge-course-list-form" data-url="<%= merge_admins_course_lists_path %>">
<%= hidden_field_tag(:origin_course_list_id, nil) %>
<div class="form-group d-flex">
<label for="course_list_id" class="col-form-label">更改为:</label>
<div class="d-flex flex-column-reverse w-75">
<input id="course_list_name" name="course_list_name" placeholder="请输入课程名称" class="form-control">
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,2 @@
alert("删除成功");
$(".course-item-<%= @course.id %>").find(".delete-course-action").remove();

@ -0,0 +1,34 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('课堂列表') %>
<% end %>
<div class="box search-form-container course-list-form">
<%= form_tag(admins_courses_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-1">
<label for="status">状态:</label>
<% status_options = [['全部', ''], ["正在进行(#{@processed_courses})", 'processing'], ["已结束#{@ended_courses}", 'ended']] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<div class="form-group col-12 col-md-3">
<label for="school_name">单位:</label>
<%= select_tag :school_id, options_for_select([''], params[:school_id]), class: 'form-control school-select flex-1' %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-12 col-md-2 mr-3', placeholder: '创建者/课堂名称/课程名称检索') %>
<div class="form-check mr-2">
<%= hidden_field_tag(:homepage_show, false, id:'') %>
<%= check_box_tag(:homepage_show, true, params[:homepage_show].to_s == 'true', class: 'form-check-input course-homepage-show') %>
<label class="form-check-label" for="homepage_show">只看首页展示</label>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
<% end %>
<a href="javascript:void(0)" class="btn btn-primary" id="course-export" data-disable-with = '导出中...'>导出</a>
</div>
<div class="box admin-list-container course-list-container">
<%= render partial: 'admins/courses/shared/list', locals: { courses: @courses } %>
</div>

@ -0,0 +1 @@
$('.course-list-container').html("<%= j( render partial: 'admins/courses/shared/list', locals: { courses: @courses } ) %>");

@ -0,0 +1,29 @@
wb = xlsx_package.workbook
wb.styles do |s|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(name: "课堂列表") do |sheet|
sheet.add_row %w(ID 课堂名称 成员 资源 普通作业 分组作业 实训作业 试卷 评测次数 私有 状态 单位 创建者 创建时间 动态时间), :height => 25,:style => blue_cell
@courses.each do |course|
data = [
course.id,
course.name,
course.course_members_count,
get_attachment_count(course, 0),
course.course_homework_count(1),
course.course_homework_count(3),
course.course_homework_count(4),
course.exercises_count,
course.evaluate_count,
course.is_public == 1 ? "--" : "√",
course.is_end ? "已结束" : "正在进行",
course.school&.name,
course.teacher&.real_name,
course.created_at&.strftime('%Y-%m-%d %H:%M'),
course.max_activity_time ? course.max_activity_time&.strftime('%Y-%m-%d %H:%M') : "--"
]
sheet.add_row(data)
end
end
end

@ -0,0 +1,62 @@
<table class="table table-hover text-center subject-list-table">
<thead class="thead-light">
<tr>
<th width="4%">ID</th>
<th width="10%" class="text-left">课堂名称</th>
<th width="6%">成员</th>
<th width="4%">资源</th>
<th width="4%">普通作业</th>
<th width="4%">分组作业</th>
<th width="4%">实训作业</th>
<th width="4%">试卷</th>
<th width="7%">评测次数</th>
<th width="4%">私有</th>
<th width="6%">状态</th>
<th width="10%">单位</th>
<th width="7%">创建者</th>
<th width="10%"><%= sort_tag('创建时间', name: 'created_at', path: admins_courses_path) %></th>
<th width="4%">首页</th>
<th width="6%">邮件通知</th>
<th width="6%">操作</th>
</tr>
</thead>
<tbody>
<% if courses.present? %>
<% courses.each do |course| %>
<tr class="course-item-<%= course.id %>">
<td><%= course.id %></td>
<td class="text-left">
<%= link_to(course.name, "/courses/#{course.id}", target: '_blank') %>
</td>
<td><%= course.course_members_count %></td>
<td><%= get_attachment_count(course, 0) %></td>
<td><%= course.course_homework_count(1) %></td>
<td><%= course.course_homework_count(3) %></td>
<td><%= course.course_homework_count(4) %></td>
<td><%= course.exercises_count %></td>
<td><%= course.evaluate_count %></td>
<td><%= course.is_public == 1 ? "--" : "√" %></td>
<td><%= course.is_end ? "已结束" : "正在进行" %></td>
<td><%= course.school&.name %></td>
<td><%= course.teacher&.real_name %></td>
<td><%= course.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td>
<%= check_box_tag :homepage_show,!course.homepage_show,course.homepage_show,remote:true,data:{id:course.id},class:"course-setting-form" %>
</td>
<td>
<%= check_box_tag :email_notify,!course.email_notify,course.email_notify,remote:true,data:{id:course.id},class:"course-setting-form" %>
</td>
<td class="action-container">
<% if course.is_delete == 0 %>
<%= delete_link '删除', admins_course_path(course, element: ".course-item-#{course.id}"), class: 'delete-course-action' %>
<% end %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: courses } %>

@ -29,12 +29,18 @@
</div>
</td>
<td><%= laboratory.created_at.strftime('%Y-%m-%d %H:%M') %></td>
<td>
<% if school.present? && laboratory.id != 1 %>
<%= check_box_tag :sync_course,!laboratory.sync_course,laboratory.sync_course,remote:true,data:{id:laboratory.id},class:"laboratory-sync-course" %>
<% end %>
</td>
<td class="action-container">
<%= link_to '定制', admins_laboratory_laboratory_setting_path(laboratory), class: 'action' %>
<% if school.present? && laboratory.id != 1 %>
<%= javascript_void_link '添加管理员', class: 'action', data: { laboratory_id: laboratory.id, toggle: 'modal', target: '.admin-add-laboratory-user-modal' } %>
<% end %>
<%= link_to '同步用户', synchronize_user_admins_laboratory_path(laboratory), remote: true, data: { confirm: '确认同步该单位下的所有用户到云上实验室吗?' }, class: 'action' %>
<% end %>
<div class="d-inline">
<%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %>

@ -1,11 +1,12 @@
<table class="table table-hover text-center laboratory-list-table">
<thead class="thead-light">
<tr>
<th width="20%" class="text-left">单位名称</th>
<th width="14%" class="text-left">单位名称</th>
<th width="16%" class="text-left">域名</th>
<th width="10%">统计链接</th>
<th width="22%">管理员</th>
<th width="14%"><%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %></th>
<th width="6%" title="同步显示显示主站下该单位的课堂">同步课堂</th>
<th width="20%">操作</th>
</tr>
</thead>

@ -0,0 +1 @@
$("#laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: @laboratory} %>")

@ -21,7 +21,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
<a href="javascript:void(0)" class="btn btn-primary submit-btn" data-disable-with = '导入中...'>确认</a>
</div>
</div>
</div>

@ -0,0 +1,2 @@
alert("删除成功");
$(".course-item-<%= @course.id %>").find(".delete-course-action").remove();

@ -0,0 +1,15 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('项目列表') %>
<% end %>
<div class="box search-form-container project-list-form">
<%= form_tag(admins_projects_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '项目名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
<% end %>
</div>
<div class="box admin-list-container project-list-container">
<%= render partial: 'admins/projects/shared/list', locals: { projects: @projects } %>
</div>

@ -0,0 +1 @@
$('.project-list-container').html("<%= j( render partial: 'admins/projects/shared/list', locals: { projects: @projects } ) %>");

@ -0,0 +1,48 @@
<table class="table table-hover text-center subject-list-table">
<thead class="thead-light">
<tr>
<th width="4%">ID</th>
<th width="15%" class="text-left">项目名称</th>
<th width="6%">公开</th>
<th width="5%">issue</th>
<th width="5%">资源</th>
<th width="6%">版本库</th>
<th width="8%">PullRequest</th>
<th width="6%">里程碑</th>
<th width="10%">成员</th>
<th width="10%">管理员</th>
<th width="15%"><%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %></th>
<th width="10%">操作</th>
</tr>
</thead>
<tbody>
<% if projects.present? %>
<% projects.each do |project| %>
<tr class="project-item-<%= project.id %>">
<td><%= project.id %></td>
<td class="text-left">
<%= link_to(project.name, "/projects/#{project.id}", target: '_blank') %>
</td>
<td><%= project.is_public ? '√' : '' %></td>
<td><%= project.issues.size %></td>
<td><%= project.attachments.size %></td>
<td><%= project.project_score.try(:changeset_num).to_i %></td>
<td><%= project.project_score.try(:pull_request_num).to_i %></td>
<td><%= project.versions.size %></td>
<td><%= project.members.size %></td>
<td>
<%= project.owner ? link_to(project.owner&.real_name, "/users/#{project.owner&.login}", target: '_blank') : "" %>
</td>
<td><%= project.created_on&.strftime('%Y-%m-%d %H:%M') %></td>
<td class="action-container">
<%= delete_link '删除', admins_project_path(project, element: ".project-item-#{project.id}"), class: 'delete-project-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: projects } %>

@ -31,7 +31,7 @@
<td><%= school.province %></td>
<td><%= school.city %></td>
<td class="text-left"><%= school.address %></td>
<td><%= school.users_count %></td>
<td><%= school.user_extensions.count %></td>
<td><%= @department_count.fetch(school.id, 0) %></td>
<td><%= school.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td>

@ -27,6 +27,7 @@
<li><%= sidebar_item(admins_shixun_settings_path, '实训配置', icon: 'cog', controller: 'admins-shixun_settings') %></li>
<li><%= sidebar_item(admins_mirror_repositories_path, '镜像管理', icon: 'cubes', controller: 'admins-mirror_repositories') %></li>
<li><%= sidebar_item(admins_myshixuns_path, '学员实训列表', icon: 'server', controller: 'admins-myshixuns') %></li>
<li><%= sidebar_item(admins_shixun_recycles_path, '实训回收站', icon: 'recycle', controller: 'admins-myshixuns') %></li>
<% end %>
</li>
@ -36,6 +37,15 @@
<% end %>
</li>
<li>
<%= sidebar_item_group('#course-submenu', '课堂管理', icon: 'book') do %>
<li><%= sidebar_item(admins_course_lists_path, '课程列表', icon: 'list', controller: 'admins-course_lists') %></li>
<li><%= sidebar_item(admins_courses_path, '课堂列表', icon: 'clone', controller: 'admins-courses') %></li>
<!-- <li><%#= sidebar_item(admins_mirror_repositories_path, '镜像管理', icon: 'cubes', controller: 'admins-mirror_repositories') %></li>-->
<li><%= sidebar_item(admins_projects_path, '项目列表', icon: 'database', controller: 'admins-projects') %></li>
<% end %>
</li>
<li>
<%= sidebar_item_group('#schools-submenu', '单位管理', icon: 'building') do %>
<li><%= sidebar_item(admins_schools_path, '单位列表', icon: 'university', controller: 'admins-schools') %></li>
@ -65,6 +75,12 @@
<% end %>
</li>
<li>
<%= sidebar_item_group('#comments-submenu', '消息', icon: 'comments') do %>
<li><%= sidebar_item(admins_shixun_feedback_messages_path, '实训反馈', icon: 'comment', controller: 'admins-shixun_feedback_messages') %></li>
<% end %>
</li>
<li>
<%= sidebar_item_group('#major-identification-submenu', '工程认证', icon: 'anchor') do %>
<li><%= sidebar_item(admins_major_informations_path, '本科专业目录', icon: 'outdent', controller: 'admins-major_informations') %></li>

@ -0,0 +1,23 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('实训反馈', admins_shixun_feedback_messages_path) %>
<% end %>
<div class="box search-form-container">
<%= form_tag(admins_shixun_feedback_messages_path, method: :get, class: 'form-inline search-form', remote: true) do %>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-md-4 ml-3', placeholder: '输入实训名称关键字进行搜索') %>
<div class="time-select">
<div class="form-group grow-date-container">
<div class="input-group input-daterange grow-date-input-daterange">
<%= text_field_tag :begin_date, params[:begin_date], class: 'form-control start-date mx-0', placeholder: '开始时间' %>
<div class="input-group-prepend"><span class="input-group-text">到</span></div>
<%= text_field_tag :end_date, params[:end_date], class: 'form-control end-date mx-0', placeholder: '结束时间' %>
</div>
</div>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
</div>
<div class="box admin-list-container shixun_feedback_messages-list-container">
<%= render(partial: 'admins/shixun_feedback_messages/shared/list', locals: {discusses: @discusses}) %>
</div>

@ -0,0 +1,2 @@
$(".shixun_feedback_messages-list-container")
.html("<%= j render partial: "admins/shixun_feedback_messages/shared/list", locals: {discusses: @discusses} %>")

@ -0,0 +1,29 @@
<table class="table table-hover text-center">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="25%" class="text-left">实训名称</th>
<th width="50%" class="text-left">评论内容</th>
<th width="10%">评论者</th>
<th width="10%">评论时间</th>
</tr>
</thead>
<tbody>
<% if discusses.present? %>
<% discusses.each_with_index do |discuss, index| %>
<tr>
<td><%= (@params_page.to_i - 1) * 20 + index + 1 %></td>
<% identifier = Game.find_by(challenge_id: discuss.challenge_id, user_id: discuss.user_id)&.identifier %>
<td class="text-left"><%= link_to discuss.dis.name, "/tasks/#{identifier}", target: '_blank'%></td>
<td class="text-left"><%= content_safe discuss.content %></td>
<td><%= discuss.user.show_real_name %></td>
<td><%= format_time discuss.created_at %></td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: discusses } %>

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

Loading…
Cancel
Save