Merge branch 'develop' into dev_jupyter

dev_jupyter
daiao 5 years ago
commit e719671132

@ -0,0 +1,2 @@
web: cd client && npm start
api: bundle exec rails s -p 3001

File diff suppressed because it is too large Load Diff

@ -19,7 +19,7 @@ $(document).on('turbolinks:load', function() {
var json = {};
json[s_name] = s_value;
$.ajax({
url: "/admins/courses/" + s_id,
url: "/admins/classrooms/" + s_id,
type: "PUT",
dataType:'script',
data: json

@ -0,0 +1,81 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-user-schools-statistics-index-page').length > 0) {
var $form = $('.user-schools-statistic-list-form');
// ************** 学校选择 *************
var matcherFunc = function(params, data){
if ($.trim(params.term) === '') {
return data;
}
if (typeof data.text === 'undefined') {
return null;
}
if (data.name && data.name.indexOf(params.term) > -1) {
var modifiedData = $.extend({}, data, true);
return modifiedData;
}
// Return `null` if the term should not be displayed
return null;
}
var defineSchoolSelect = function (schools) {
$form.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '选择学校/单位',
minimumInputLength: 1,
data: schools,
templateResult: function (item) {
if(!item.id || item.id === '') return item.text;
return item.name;
},
templateSelection: function(item){
if (item.id) {
$form.find('#school_id').val(item.id);
}
return item.name || item.text;
},
matcher: matcherFunc
});
};
// 初始化学校选择器
$.ajax({
url: '/api/schools/for_option.json',
dataType: 'json',
type: 'GET',
success: function(data) {
defineSchoolSelect(data.schools);
}
});
// 清空
$form.on('click', '.clear-btn', function(){
$form.find('select[name="date"]').val('');
$form.find('select[name="province"]').val('');
$form.find('.school-select').val('').trigger('change');
$form.find('input[type="submit"]').trigger('click');
})
// 导出
$('.export-action').on('click', function(){
var form = $(".user-schools-statistic-list-form")
var exportLink = $(this);
var date = form.find("select[name='date']").val();
var schoolId = form.find('input[name="school_id"]').val();
var province = form.find('input[name="province"]').val();
console.log(province)
if(province == "" || province == null){
alert("只能按省份导出");
return;
}
var url = exportLink.data("url").split('?')[0] + "?date=" + date + "&school_id=" + schoolId + "&province=" + province;
window.open(url);
});
}
});

@ -0,0 +1,25 @@
$(document).on('turbolinks:load', function() {
if ($('.weapp-banner-setting-container').length > 0) {
var $form = $('#course_form');
$('.course.banner-item-bottom').on("change", 'input[type="file"]', function() {
var $fileInput = $(this);
var file = this.files[0];
var imageType = /image.*/;
if (file && file.type.match(imageType)) {
$form.ajaxSubmit()
}
});
var $shixunform = $('#shixun_form');
$('.shixun.banner-item-bottom').on("change", 'input[type="file"]', function() {
var $fileInput = $(this);
var file = this.files[0];
var imageType = /image.*/;
if (file && file.type.match(imageType)) {
$shixunform.ajaxSubmit()
}
});
}
})

@ -1,171 +1,154 @@
.admins-laboratories-index-page {
.laboratory-list-table {
.member-container {
.laboratory-user {
display: flex;
justify-content: center;
flex-wrap: wrap;
.laboratory-user-item {
display: flex;
align-items: center;
height: 22px;
line-height: 22px;
padding: 2px 5px;
margin: 2px 2px;
border: 1px solid #91D5FF;
background-color: #E6F7FF;
color: #91D5FF;
border-radius: 4px;
.laboratory-list-table {
.member-container {
.laboratory-user {
display: flex;
justify-content: center;
flex-wrap: wrap;
.laboratory-user-item {
display: flex;
align-items: center;
height: 22px;
line-height: 22px;
padding: 2px 5px;
margin: 2px 2px;
border: 1px solid #91D5FF;
background-color: #E6F7FF;
color: #91D5FF;
border-radius: 4px;
}
}
}
}
}
}
}
.admins-laboratory-settings-show-page, .admins-laboratory-settings-update-page {
.edit-laboratory-setting-container {
.logo-item {
display: flex;
&-img {
display: block;
width: 80px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 80px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 39px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 27px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-left {
position: relative;
width: 80px;
height: 80px;
&.has-img {
.logo-item-upload {
display: none;
}
&:hover {
.logo-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
.admins-laboratory-settings-show-page,
.admins-laboratory-settings-update-page,
.weapp-banner-setting-container {
.edit-laboratory-setting-container {
.logo-item {
display: flex;
&-img {
display: block;
width: 80px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 80px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 39px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 27px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-left {
position: relative;
width: 80px;
height: 80px;
&.has-img {
.logo-item-upload {
display: none;
}
&:hover {
.logo-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
}
}
}
}
&-right {
display: flex;
flex-direction: column;
justify-content: space-between;
color: #777777;
font-size: 12px;
}
&-title {
color: #23272B;
font-size: 14px;
}
}
}
}
&-right {
display: flex;
flex-direction: column;
justify-content: space-between;
color: #777777;
font-size: 12px;
}
&-title {
color: #23272B;
font-size: 14px;
}
}
.banner-item {
margin-bottom: 15px;
display: flex;
flex-direction: column;
&-img {
display: block;
width: 300px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 300px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 149px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 137px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-top {
margin-bottom: 10px;
}
&-bottom {
position: relative;
width: 300px;
height: 80px;
&.has-img {
.banner-item-upload {
display: none;
}
&:hover {
.banner-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
.banner-item {
margin-bottom: 15px;
display: flex;
flex-direction: column;
&-img {
display: block;
width: 300px;
height: 80px;
background: #f0f0f0;
}
&-upload {
cursor: pointer;
position: absolute;
top: 0;
width: 300px;
height: 80px;
background: #F5F5F5;
border: 1px solid #E5E5E5;
&::before {
content: '';
position: absolute;
top: 27px;
left: 149px;
width: 2px;
height: 26px;
background: #E5E5E5;
}
&::after {
content: '';
position: absolute;
top: 39px;
left: 137px;
width: 26px;
height: 2px;
background: #E5E5E5;
}
}
&-top {
margin-bottom: 10px;
}
&-bottom {
position: relative;
width: 300px;
height: 80px;
&.has-img {
.banner-item-upload {
display: none;
}
&:hover {
.banner-item-upload {
display: block;
background: rgba(145, 145, 145, 0.8);
}
}
}
}
&-title {
color: #23272B;
font-size: 14px;
}
}
}
}
&-title {
color: #23272B;
font-size: 14px;
}
}
}
}

@ -5,6 +5,16 @@ class Admins::DashboardsController < Admins::BaseController
@month_active_user_count = User.where(last_login_on: current_month).count
@new_user_count = User.where(created_on: current_month).count
unless Rails.env.development?
shixun_tomcat = edu_setting('cloud_bridge')
uri = "#{shixun_tomcat}/bridge/monitor/getPodsInfo"
res = interface_get uri, 502, "数据接口延迟"
if res['code'] == 0
@pod_num = res['sum'] || 0
end
end
end
def month_active_user

@ -7,7 +7,7 @@ class Admins::DisciplinesController < Admins::BaseController
def create
name = params[:name].to_s.strip
return render_error('名称重复') if Discipline.where(name: name).exists?
Discipline.create!(name: name, position: Discipline.all.pluck(:position).max + 1)
Discipline.create!(name: name, position: Discipline.all.pluck(:position).max.to_i + 1)
render_ok
end
@ -46,7 +46,7 @@ class Admins::DisciplinesController < Admins::BaseController
end
def adjust_position
max_position = Discipline.all.pluck(:position).max
max_position = Discipline.all.pluck(:position).max.to_i
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_discipline.position == 1) || (params[:opr] == "down" && current_discipline.position == max_position)
@message = "超出范围"

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

@ -9,7 +9,7 @@ class Admins::SubDisciplinesController < Admins::BaseController
name = params[:name].to_s.strip
return render_error('名称不能为空') if name.blank?
return render_error('名称重复') if current_discipline.sub_disciplines.where(name: name).exists?
SubDiscipline.create!(name: name, discipline_id: current_discipline.id, position: current_discipline.sub_disciplines.pluck(:position).max + 1)
SubDiscipline.create!(name: name, discipline_id: current_discipline.id, position: current_discipline.sub_disciplines.pluck(:position).max.to_i + 1)
render_ok
end
@ -47,7 +47,7 @@ class Admins::SubDisciplinesController < Admins::BaseController
def adjust_position
discipline = current_sub_discipline.discipline
max_position = discipline.sub_disciplines.pluck(:position).max
max_position = discipline.sub_disciplines.pluck(:position).max.to_i
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_sub_discipline.position == 1) || (params[:opr] == "down" && current_sub_discipline.position == max_position)
@message = "超出范围"

@ -9,7 +9,7 @@ class Admins::TagDisciplinesController < Admins::BaseController
name = params[:name].to_s.strip
return render_error('名称重复') if current_sub_discipline.tag_disciplines.where(name: name).exists?
TagDiscipline.create!(name: name, sub_discipline_id: current_sub_discipline.id, user_id: current_user.id,
position: current_sub_discipline.tag_disciplines.pluck(:position).max + 1)
position: current_sub_discipline.tag_disciplines.pluck(:position).max.to_i + 1)
render_ok
end
@ -42,7 +42,7 @@ class Admins::TagDisciplinesController < Admins::BaseController
def adjust_position
sub_discipline = current_tag_discipline.sub_discipline
max_position = sub_discipline.tag_disciplines.pluck(:position).max
max_position = sub_discipline.tag_disciplines.pluck(:position).max.to_i
opr = params[:opr] || "down"
if (params[:opr] == "up" && current_tag_discipline.position == 1) || (params[:opr] == "down" && current_tag_discipline.position == max_position)
@message = "超出范围"

@ -0,0 +1,18 @@
class Admins::UserSchoolsStatisticsController < Admins::BaseController
def export
params[:per_page] = 500
_count, @schools = Admins::UserSchoolsStatisticQuery.call(params)
filename = ['用户运营统计', Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << '.xlsx'
render xlsx: 'export', filename: filename
end
def index
default_sort('cnt', 'desc')
total_count, schools = Admins::UserSchoolsStatisticQuery.call(params)
@schools = paginate schools, total_count: total_count
end
end

@ -0,0 +1,52 @@
class Admins::WeappBannersController < Admins::BaseController
def index
@shixun = WeappSettings::ShixunBanner.first
@course = WeappSettings::CourseBanner.first
end
def create
ActiveRecord::Base.transaction do
old_carouse = WeappSettings::CourseBanner.first
if old_carouse.present?
old_carouse.destroy!
file_path = Util::FileManage.source_disk_filename(old_carouse)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
end
@course = WeappSettings::CourseBanner.create!
save_image_file(params[:course_banner], @course)
end
end
def shixun_banner
ActiveRecord::Base.transaction do
old_shixun = WeappSettings::ShixunBanner.first
if old_shixun.present?
old_shixun.destroy!
file_path = Util::FileManage.source_disk_filename(old_shixun)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
end
@shixun = WeappSettings::ShixunBanner.create!
save_image_file(params[:shixun_banner], @shixun)
end
end
private
def save_image_file(file, model)
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
file_path = Util::FileManage.source_disk_filename(model)
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(file, file_path)
end
end

@ -72,6 +72,15 @@ class ApplicationController < ActionController::Base
if !current_user.shixun_permission(@shixun)
tip_exception(403, "..")
end
# if !current_user.shixun_permission(@shixun)
# if @shixun.user_scope == 1
# school_id = @shixun.shixun_schools.first&.school_id
# name = School.find_by(id: school_id)&.name
# tip_exception(-5, "当前实训只对#{name}等单位开放")
# else
# tip_exception(403, "..")
# end
# end
end
def admin_or_business?
@ -86,13 +95,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 && @course.tea_id != current_user.id
# 实名认证和职业认证的身份判断
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
# if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT && @course.tea_id != current_user.id
# # 实名认证和职业认证的身份判断
# 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
@ -448,6 +457,25 @@ class ApplicationController < ActionController::Base
end
end
# 无参类型处理
def interface_get(uri, status, message)
begin
uid_logger_dubug("--uri_exec: url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.get(uri)
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(message)
end
end
# json格式请求
def interface_json_post(uri, params, status, message)
begin

@ -155,9 +155,16 @@ class ChallengesController < ApplicationController
def index
uid_logger("identifier: #{params}")
base_columns = "challenges.id, challenges.subject, challenges.st, challenges.score, challenges.position,
challenges.shixun_id, games.identifier, games.status"
join_sql = "LEFT JOIN games ON games.challenge_id = challenges.id AND games.user_id = #{current_user.id}"
# 下面2个参数是为了解决列表获取通关人数与正在游玩人数的问题
#@pass_games_map = @shixun.challenges.joins(:games).where(games: {status:2}).group(:challenge_id).reorder(nil).count
#@play_games_map = @shixun.challenges.joins(:games).where(games: {status:[0,1]}).group(:challenge_id).reorder(nil).count
@challenges = @shixun.challenges.fields_for_list
@challenges = @shixun.challenges.joins(join_sql).select(base_columns).uniq
#@challenges = @shixun.challenges.fields_for_list
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user
@shixun.increment!(:visits)
@ -230,7 +237,7 @@ class ChallengesController < ApplicationController
logger.info("############shixun_publiced:#{@shixun.public == 0}")
if @shixun.public == 0
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script) if script.present?
end
# TODO:
# if path != params[:challenge][:path]

@ -25,7 +25,7 @@ module GitHelper
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
elsif cd['encoding'].blank?
elsif cd['encoding'].blank? && !content.blank?
raise("ERROR_UTF8")
else
content.force_encoding('UTF-8')
@ -36,7 +36,7 @@ module GitHelper
rescue Exception => e
Rails.logger.error(e.message)
error_msg = e.message == "ERROR_UTF8" ? "文件无法预览" : "文档内容获取异常"
error_msg = e.message == "ERROR_UTF8" ? "文件编码异常请将文件编码设置为UTF-8" : "文档内容获取异常"
error_status = e.message == "ERROR_UTF8" ? -2 : -1
raise Educoder::TipException.new(error_status, error_msg)
end

@ -35,6 +35,7 @@ module LoginHelper
UserAction.create(action_id: user&.id, action_type: 'Login', user_id: user&.id, ip: request.remote_ip)
user.update_column(:last_login_on, Time.now)
# 注册完成后有一天的试用申请(先去掉)
# UserDayCertification.create(user_id: user.id, status: 1)
end
@ -44,6 +45,8 @@ module LoginHelper
if autologin = cookies.delete(autologin_cookie_name)
User.current.delete_autologin_token(autologin)
end
UserOnline.logout(User.current.id)
User.current.delete_session_token(session[:tk])
self.logged_user = nil
end
@ -52,6 +55,7 @@ module LoginHelper
default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
# end
session[:"#{default_yun_session}"] = nil
session[:request_user_id] = nil
end
# Sets the logged in user
@ -78,6 +82,8 @@ module LoginHelper
# # end
# session[:user_id] = user.id
UserOnline.login(user.id)
session[:request_user_id] = user.id
session[:"#{default_yun_session}"] = user.id
session[:ctime] = Time.now.utc.to_i
session[:atime] = Time.now.utc.to_i

@ -2,9 +2,13 @@ class CourseModulesController < ApplicationController
before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules]
before_action :teacher_or_admin_allowed, except: [:add_second_category]
before_action :teacher_or_admin_allowed, except: [:show, :add_second_category]
before_action :teacher_allowed, only: [:add_second_category]
def show
end
# 模块置顶
def sticky_module
# position为1则不做处理否则该模块的position置为1position小于当前模块的position加1

@ -36,10 +36,13 @@ class CourseSecondCategoriesController < ApplicationController
# 更新相应对象的子目录id
if @course_module.module_type == "shixun_homework"
@category.homework_commons.update_all(course_second_category_id: 0)
@right_url = "/courses/#{@course.id}/shixun_homeworks/#{@course_module.id}"
@right_url = "/classrooms/#{@course.id}/shixun_homeworks/#{@course_module.id}"
elsif @course_module.module_type == "attachment"
Attachment.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0)
@right_url = "/courses/#{@course.id}/files/#{@course_module.id}"
@right_url = "/classrooms/#{@course.id}/files/#{@course_module.id}"
elsif @course_module.module_type == "video"
@course.course_videos.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0)
@right_url = "/classrooms/#{@course.id}/course_videos"
end
@category.destroy

@ -0,0 +1,35 @@
class CourseVideosController < ApplicationController
before_action :require_login
before_action :validate_params
before_action :find_course, only: [:create]
before_action :find_video, only: [:update]
before_action :teacher_allowed
def create
title = params[:name].strip
link = params[:link].strip
course_second_category_id = params[:category_id] || 0
@course.course_videos.create!(title: title, link: link, is_link: 1, user_id: current_user.id, course_second_category_id: course_second_category_id)
render_ok
end
def update
title = params[:name].strip
link = params[:link].strip
@video.update!(title: title, link: link)
render_ok
end
private
def validate_params
tip_exception("视频名称不能为空") if params[:name].blank?
tip_exception("链接地址不能为空") if params[:link].blank?
end
def find_video
@video = CourseVideo.find params[:id]
@course = @video.course
end
end

@ -30,14 +30,14 @@ class CoursesController < ApplicationController
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs,
:delete_informs, :change_member_role, :course_groups, :join_course_group, :statistics,
:work_score, :act_score, :calculate_all_shixun_scores]
:work_score, :act_score, :calculate_all_shixun_scores, :move_to_category]
before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course,
:search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list]
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course, :export_member_scores_excel,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup,
:add_teacher, :export_couser_info, :export_member_act_score,
:update_informs, :new_informs, :delete_informs, :switch_to_student]
:update_informs, :new_informs, :delete_informs, :switch_to_student, :move_to_category]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :create_group_by_importing_file,
:update_task_position, :tasks_list]
@ -102,22 +102,60 @@ class CoursesController < ApplicationController
end
def course_videos
logger.info("########[#{@course}")
videos = @course.videos
videos = @course.course_videos
@video_module = @course.course_modules.find_by(module_type: "video")
if params[:category_id].present? && params[:category_id].to_i != 0
@category = @video_module&.course_second_categories.find_by(id: params[:category_id])
tip_exception("子目录id有误") if !@category.present?
videos = videos.where(course_second_category_id: params[:category_id].to_i)
end
videos = custom_sort(videos, params[:sort_by], params[:sort_direction])
@count = videos.count
#sql = "left join videos on videos.id=course_videos.video_id AND (videos.transcoded=1 OR videos.user_id = #{current_user.id})"
#@videos = paginate videos.joins(sql).includes(video: [user: :user_extension], user: :user_extension)
videos = videos.includes(video: [user: :user_extension], user: :user_extension)
videos = videos.where(videos: {transcoded: true})
.or(videos.where(videos: {user_id: current_user.id}))
.or(videos.where(course_videos: {is_link: true}))
@count = videos.count
@videos = paginate videos
end
def delete_course_video
video = Video.find_by(id: params[:video_id])
tip_exception(404, "找不到资源") if video.blank?
tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?)
video.destroy!
AliyunVod::Service.delete_video([video.uuid]) rescue nil
if params[:is_link]
video = @course.course_videos.find_by!(id: params[:video_id])
tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?)
video.destroy!
else
video = Video.find_by(id: params[:video_id])
tip_exception(404, "找不到资源") if video.blank?
tip_exception(403, "...") unless (video.user_id == current_user.id || current_user.admin_or_business?)
video.destroy!
end
render_ok
end
# 视频移动到目录
def move_to_category
tip_exception("请选择要移动的目录") if params[:new_category_id].blank?
category = @course.course_second_categories.find_by(id: params[:new_category_id])
if params[:new_category_id].to_i == 0 || category.present?
video = @course.course_videos.where(video_id: params[:video_ids]).or(@course.course_videos.where(id: params[:video_ids])).first
user_id = video.user_id || video.video.user_id
tip_exception("您不是课堂管理员或者视频发布者,暂不能移动视频。") unless @user_course_identity < Course::PROFESSOR || user_id == current_user.id
video.update!(course_second_category_id: params[:new_category_id])
normal_status(0, "视频移动成功!")
else
normal_status(-1, "目录不存在")
end
end
def visits_plus_one
new_visits = @course.visits + 1
@course.update_visits(new_visits)
@ -153,8 +191,8 @@ class CoursesController < ApplicationController
begin
ActiveRecord::Base.transaction do
@course = Course.new(name: params[:name], class_period: params[:class_period], credit: params[:credit],
end_date: params[:end_date], is_public: params[:is_public], school_id: @school.id,
authentication: params[:authentication], professional_certification: params[:professional_certification])
end_date: params[:end_date], is_public: params[:is_public], school_id: @school.id)
# authentication: params[:authentication], professional_certification: params[:professional_certification])
@course.tea_id = current_user.id
if params[:subject_id].blank?
@ -219,8 +257,8 @@ class CoursesController < ApplicationController
extra_params[:is_end] = 1
end
extra_params[:authentication] = params[:authentication]
extra_params[:professional_certification] = params[:professional_certification]
# extra_params[:authentication] = params[:authentication]
# extra_params[:professional_certification] = params[:professional_certification]
if @course.subject
@course.start_date = params[:start_date]
@ -747,6 +785,12 @@ class CoursesController < ApplicationController
ActiveRecord::Base.transaction do
course_student.destroy!
course_teacher.update!(is_active: 1)
teacher_course_record = @course.teacher_group_records.find_by(user_id: current_user.id)
if teacher_course_record.present?
teacher_course_record.update!(group_id: course_student.course_group_id)
else
TeacherGroupRecord.create!(user_id: current_user.id, course_id: @course.id, group_id: course_student.course_group_id)
end
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功")
@ -766,6 +810,12 @@ class CoursesController < ApplicationController
ActiveRecord::Base.transaction do
course_student.destroy!
course_teacher.update!(is_active: 1)
teacher_course_record = @course.teacher_group_records.find_by(user_id: current_user.id)
if teacher_course_record.present?
teacher_course_record.update!(group_id: course_student.course_group_id)
else
TeacherGroupRecord.create!(user_id: current_user.id, course_id: @course.id, group_id: course_student.course_group_id)
end
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功")
@ -788,7 +838,9 @@ class CoursesController < ApplicationController
course_student.update_attributes!(is_active: 1)
else
# 学生身份不存在则创建
CourseMember.create!(user_id: current_user.id, role: 4, course_id: @course.id)
course_group_id = @course.teacher_group_records.find_by(user_id: current_user.id)&.group_id.to_i
course_group_id = @course.course_groups.find_by(id: course_group_id)&.id.to_i
CourseMember.create!(user_id: current_user.id, role: 4, course_id: @course.id, course_group_id: course_group_id)
CourseAddStudentCreateWorksJob.perform_later(@course.id, [current_user.id])
end
normal_status(0, "切换成功")
@ -1143,10 +1195,10 @@ class CoursesController < ApplicationController
return normal_status(-1, "课堂已结束,无法加入") if course.is_end
# 实名认证和职业认证的身份判断
return normal_status(-2, "该课堂要求成员完成实名和职业认证") if course.authentication &&
course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
return normal_status(-2, "该课堂要求成员完成实名认证") if course.authentication && !current_user.authentication
return normal_status(-2, "该课堂要求成员完成职业认证") if course.professional_certification && !current_user.professional_certification
# return normal_status(-2, "该课堂要求成员完成实名和职业认证") if course.authentication &&
# course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
# return normal_status(-2, "该课堂要求成员完成实名认证") if course.authentication && !current_user.authentication
# return normal_status(-2, "该课堂要求成员完成职业认证") if course.professional_certification && !current_user.professional_certification
# 身份验证
if params[:professor].blank? && params[:assistant_professor].blank? && params[:student].blank?
@ -1245,7 +1297,7 @@ class CoursesController < ApplicationController
@is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR
@course_modules = @course.course_modules.where(hidden: 0)
@hidden_modules = @course.course_modules.where(hidden: 1)
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"]
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group", "video", "common_homework", "group_homework"]
end
def board_list
@ -1438,6 +1490,7 @@ class CoursesController < ApplicationController
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:name, :class_period, :credit, :end_date, :is_public, :authentication, :professional_certification)
# params.require(:course).permit(:name, :class_period, :credit, :end_date, :is_public, :authentication, :professional_certification)
end
def validate_course_name

@ -46,7 +46,7 @@ class DiscussesController < ApplicationController
end
sql = "select d.id from discusses d join shixuns s on d.dis_id = s.id where s.status = 2 and s.hidden = false and d.root_id is null
and d.hidden = false #{sql1} #{sql2} order by d.created_at desc"
and d.hidden = false and d.dis_type = 'Shixun' #{sql1} #{sql2} order by d.created_at desc"
memo_ids = Discuss.find_by_sql(sql).pluck(:id)
@memo_count = memo_ids.size
@ -81,8 +81,7 @@ class DiscussesController < ApplicationController
begin
@discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type],
:content => params[:content].gsub("&nbsp\;", "").strip, :user_id => current_user.id,
:praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id],
:hidden => !current_user.admin?) # 管理员回复的能够显示
:praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id])
rescue Exception => e
uid_logger_error("create discuss failed : #{e.message}")
raise Educoder::TipException.new("评论异常,原因:#{e.message}")

@ -0,0 +1,378 @@
#encoding=utf-8
# 云启训练场EduCoder个人版 产品编码appId 9200108
# 产品名称 计费类型 套餐编码
# 云启训练场EduCoder个人版 固定包月 9200108001
# 固定包月 9200108002
# 固定包月 9200108003
# ---------------------------------------------------
# 产品名称 计费类型 套餐编码
# 云启训练场EduCoder院校版 包月+按license 9200109001
# 包月+按license 9200109002
# 云启训练场EduCoder院校版 产品编码appId 9200109
require 'net/http'
require 'digest'
class EcloudController < ApplicationController
before_action :save_para
before_action :check_sign_key, only: [:ps_new, :ps_update, :bs_new, :bs_update]
def index
render file: 'public/react-oschina/build/index.html', :layout => false
end
def trustie_login
end
# 测试环境
# CLIENT_ID = '1022'
# CLIENT_SECRET = '2112037a-6d7a-432b-9081-feb1153d8668'
# SERVER_URL = "https://221.176.54.92:9081/restful/services/"
#
# 正式环境
CLIENT_ID = '1056'
CLIENT_SECRET = '2e84256a-3de4-4713-9e02-10ee88a14592'
SERVER_URL = "https://221.176.53.130:44390/services/"
## 签名
def sign(timestamp)
Digest::MD5.hexdigest("client_id=#{CLIENT_ID}client_key=#{CLIENT_SECRET}timestamp=#{timestamp}").upcase
end
# 企业/个人业务开通
# applyno 申请单号,唯一
# ecordercode 唯一标志一个企业的订购关系
# params['opttype']操作类型。0开通1变更2试用转商用4再次开通
# 业务列表opttype: 0新增1注销2修改
# serviceparas: 但是由于企业版是按成员收费的所以serviceparas里面会传成员数个人版是包月计费的serviceparas不会传成员数
def bs_new
ActiveRecord::Base.transaction do
begin
if params['opttype'] == 0 # 开通企业/个人业务
ecloud = Ecloud.create!(eloud_params)
create_service(params['services'], ecloud.try(:id)) if params['services'].present?
create_product_params(params['productparas'], ecloud.try(:id)) if params['productparas'].present?
# 为管理员添加一条记录
# 开通的时候都是用户的opttype也是0
# 如果管理员已经存在,则不用重复开通
euser = EcloudUser.where(userid: params['userid'], custid: params['custid']).first
unless euser
EcloudUser.create!(custid: params['custid'], opttype: params['opttype'], userid: params['userid'],
username: params['username'], useralias: params['useralias'],
mobile: params['mobile'], email: params['email'], begintime: params['begintime'],
endtime: params['endtime'])
end
elsif params['opttype'] == 2 # 试用转商用 # 变更企业/个人业务
# 业务列表:注销业务(注销试用的套餐),另一个业务项的操作代码是:新增业务(开通商用的套餐)
# 需要通过产品服务编号和业务编码来区分哪个产品
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode'], trial: true).first
# 注销试用的套餐
## 需要注销的套餐; 试用转商用是不会有批量操作的所以可以使用first
des_service = params['services'].select{|s| s['opttype'] == 1}.first
esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: des_service['code']).first
ecloud.update_attribute(:trial, params['trial'])
esd.update_attributes!(opttype: des_service['opttype'], begintime: des_service['begintime'], endtime: des_service['endtime'])
# 试用转商用是不会有批量操作的
# 新增业务
add_service = params['services'].select{|s| s['opttype'] == 0}
create_service(add_service, ecloud.try(:id))
#
elsif params['opttype'] == 1 # 业务变更
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
# 套餐变更
# 操作代码 0新增业务1注销业务2修改业务
# # 新增服务
add_service = params['services'].select{|s| s['opttype'] == 0}
create_service(add_service, ecloud.try(:id)) if add_service.present?
# 如果有注销业务,注销业务
des_services = params['services'].select{|s| s['opttype'] == 1}
if des_services.present?
des_services.each do |ds|
logger.info("666666#{ecloud.try(:id)}, 55555555#{ds['code']}")
esd = EcloudService.where(ecloud_id: ecloud.try(:id), code: ds['code']).first
esd.update_attributes!(opttype: ds['opttype'], begintime: ds['begintime'], endtime: ds['endtime'])
end
end
# 变更业务
edt_services = params['services'].select{|s| s['opttype'] == 2}
if edt_services.present?
edt_services.each do |es|
ese = EcloudService.where(ecloud_id: ecloud.try(:id), code: es['code']).first
ese.update_attributes!(opttype: es['opttype'], begintime: es['begintime'], endtime: es['endtime']) if ese.present?
create_serviceparas(es['serviceparas'].first, ese.id) if ese.present?
end
end
# ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
# ecloud.update_attributes!(eloud_params)
# ecloud.ecloud_productparas.destroy
# ecloud.ecloud_services.destroy
#
# ecloud_id = ecloud.try(:id)
elsif params['opttype'] == 4 # 再次重复开通
# 再次申请开通,这种情况就是累加时间
ecloud = Ecloud.where(custid: params['custid'], custcode: params['custcode'], productcode: params['productcode']).first
create_service(params['services'], ecloud.try(:id))
create_product_params(params['productparas'], ecloud.try(:id)) if params['productparas'].present?
end
#
# # 非试用情况下,为管理员单独创建一条账号,企业账号
# unless params['trial']
# EcloudUser.create!(ecloud_id: ecloud.try(:id), opttype: params['opttype'], userid: params['userid'],
# username: params['username'], useralias: params['useralias'],
# mobile: params['mobile'], email: params['email'])
# end
render :json => {result: true, errmsg: ""}
# rescue Exception => e
# logger.error(e.message)
# render :json => {code: 500, msg: "#{e.message}"}
# raise ActiveRecord::Rollback
end
end
end
# 企业/个人业务变更、注销
# 处理业务平台退订、暂停(欠费暂停,信控暂停等)、暂停后恢复应用业务
# 这个接口是不会新增业务的
# 试用退订的时候bossorderid传空字符
def bs_update
ActiveRecord::Base.transaction do
begin
case params['opttype']
when 0 # 退订
opttype = 6
when 1 # 暂停
opttype = 7
when 2 # 恢复
opttype = 8
end
if params['bossorderid'].present?
ecloud = Ecloud.where(bossorderid: params['bossorderid']).first
ecloud.update_attribute(:opttype, opttype)
else
# 试用退订
params['services'].each do |service|
ecloud_id = EcloudService.where(code: service['packagecode']).first.try(:ecloud_id)
Ecloud.find(ecloud_id).update_attribute(:opttype, opttype)
end
end
render :json => {result: true, errmsg: ""}
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
raise ActiveRecord::Rollback
end
end
end
# 用户业务开通与变更接口
# 授权statu为1取消授权status为0
# user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
def ps_new
ActiveRecord::Base.transaction do
begin
user_params = params['users']
user_params.each do |user_param|
if user_param['opttype'] == 0 # 开通
EcloudUser.create!(custid: params['custid'], opttype: user_param['opttype'], userid: user_param['userid'],
username: user_param['username'], useralias: user_param['useralias'],
mobile: user_param['mobile'], email: user_param['email'], begintime: user_param['begintime'].to_s,
endtime: user_param['endtime'].to_s)
elsif user_param['opttype'] == 1 # 变更
ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
ecloud_user.update_attributes!(opttype: user_param['opttype'], username: user_param['username'],
useralias: user_param['useralias'], mobile: user_param['mobile'], email: user_param['email'],
begintime: user_param['begintime'].to_s, endtime: user_param['endtime'].to_s)
end
end
render :json => {success: true, errmsg: ""}
# end
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
raise ActiveRecord::Rollback
end
end
end
# 用户业务状态变更
# user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
def ps_update
begin
user_params = params['users']
user_params.each do |user_param|
case user_param['opttype']
when 0 # 取消授权
opttype = 3
when 1 # 暂停
opttype = 4
when 2 # 恢复
opttype = 5
end
ecloud_user = EcloudUser.where(custid: params['custid'], userid: user_param['userid']).first
ecloud_user.update_attributes!(opttype: opttype, operatime: params['operatime'], effecttime: params['effecttime'])
end
render :json => {success: true, errmsg: ""}
rescue Exception => e
logger.error(e.message)
render :json => {code: 500, msg: "#{e.message}"}
end
end
def ecloud_login_callback
if params[:test]
user_info = decode '{"userid":2147,"custid":2104,"custcode":"E0002018042810010054","custtype":2,"status":2,"username":"15111030087@QW_er","useralias":"15111030087","isadmin":true,"entprise":"04**004","departments":"","departmentnames":"","mobile":"15365386520","email":"15111030087@139.com"}'
else
res = request_ecloud_authorization
logger.info "oauth2 authorization resp: #{res}"
raise '登录失败' unless res["access_token"]
user_info = decode get_ecloud_user(res)
logger.info "oauth2 get user info: #{user_info}"
end
open_user = OpenUsers::Ecloud.find_or_initialize_by(uid: user_info['userid']) do |u|
u.extra = user_info
end
redirect_to "/users/#{open_user.user.login}/courses" and return if open_user.persisted?
ActiveRecord::Base.transaction do
user = User.find_or_initialize_by(phone: user_info["mobile"]) do |u|
u.login = "ecoder_#{user_info['mobile']}"
u.type ='User'
u.status = User::STATUS_ACTIVE
u.nickname = user_info['username']
u.lastname = user_info['username']
end
if !user.persisted?
user.mail = user_info["email"] unless user_info["email"].blank? || User.find_by_mail(user_info["email"])
user.save!
user.create_user_extension!
end
open_user.user = user
open_user.save!
successful_authentication(user)
redirect_to "/users/#{user.login}/courses"
end
rescue Exception => e
render :json => {code: 500, msg: "#{e.message}"}
end
private
def request_ecloud_authorization
url = "#{SERVER_URL}/oauth2/authorization?grant_type=authorization_code&client_id=#{CLIENT_ID}&scope=&redirect_uri=&code=#{params[:code]}"
decode post(url)
end
def get_ecloud_user(body)
res = get("#{SERVER_URL}/user/info?access_token=#{body['access_token']}&userid=#{body['uid']}")
end
def get(url)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = url.start_with?('https')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
response = http.request(request)
response.body
end
def post(url)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = url.start_with?('https')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.request_uri)
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
response = http.request(request)
response.body
end
def decode(s)
begin
obj = ActiveSupport::JSON.decode(s)
rescue ActiveSupport::JSON.parse_error
logger.error("Attempted to decode invalid JSON: #{s}")
end
end
private
def eloud_params
return {applyno: params['applyno'], ecordercode: params['ecordercode'], opttype: params['opttype'],
trial: params['trial'], bossorderid: params['bossorderid'], custid: params['custid'], custtype: params['custtype'],
custcode: params['custcode'], registersource: params['registersource'], custname: params['custname'],
userid: params['userid'], username: params['username'], useralias: params['useralias'], mobile: params['mobile'],
email: params['email'], productcode: params['productcode'], begintime: params['begintime'],
endtime: params['endtime']}
end
# 新增套餐
def create_service services, ecloud_id
services.each do |service|
ese = EcloudService.create!(opttype: service['opttype'], code: service['code'], begintime: service['begintime'],
endtime: service['endtime'], ecloud_id: ecloud_id)
if service['serviceparas'].present?
create_serviceparas(service['serviceparas'].first, ese.id)
end
end
end
def create_serviceparas params_serviceparas, ese_id
if params_serviceparas.present?
EcloudServieceServicepara.create(key: params_serviceparas['key'], value: params_serviceparas['value'], ecloud_service_id: ese_id)
end
end
def create_product_params params, ecloud_id
params.each do |p|
EcloudProductpara.create(key: p['key'], value: p['value'], ecloud_id: ecloud_id)
end
end
def check_sign_key
sign = sign(params['timestamp'])
if sign != params['sign']
render :json => {code: 501, msg: "sign的值错误"}
return
end
end
def save_para
EcloudLog.create(url: request.url, para_value: params, applyno: params['applyno'], custid: params['custid'],
custcode: params['custcode'], userid: params['userid'], username: params['username'])
end
end

@ -1,9 +1,9 @@
class ExaminationBanksController < ApplicationController
include PaginateHelper
before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item]
before_action :find_exam, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item]
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item, :cancel_items]
before_action :find_exam, except: [:index, :create, :cancel_items]
before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item, :cancel_items]
before_action :identity_auth, only: [:index]
def index
@ -36,8 +36,8 @@ class ExaminationBanksController < ApplicationController
end
current_user.item_baskets.destroy_all
render_ok({exam_id: exam.id})
end
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
@ -76,6 +76,11 @@ class ExaminationBanksController < ApplicationController
render_ok
end
def cancel_items
current_user.item_baskets.where(item_bank_id: params[:item_ids]).destroy_all
render_ok
end
private
def form_params

@ -379,6 +379,7 @@ class ExercisesController < ApplicationController
#试卷的提交设置
def commit_setting
tip_exception("助教无权限修改本试卷") if @user_course_identity == Course::ASSISTANT_PROFESSOR && !@exercise.assistant_auth
ActiveRecord::Base.transaction do
error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。
# course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组
@ -398,6 +399,7 @@ class ExercisesController < ApplicationController
choice_random = params[:choice_random] ? true : false
score_open = params[:score_open] ? true : false #分数是否公开
answer_open = params[:answer_open] ? true : false #答案是否公开
assistant_auth = params[:assistant_auth] # 助教权限
# 统一设置或者分班为0则更新试卷并删除试卷分组
if unified_setting || (course_group_ids.size == 0)
@ -426,7 +428,8 @@ class ExercisesController < ApplicationController
:answer_open => answer_open,
:exercise_status => exercise_status_n,
:publish_time => params_publish_time,
:end_time => params_end_time
:end_time => params_end_time,
:assistant_auth => assistant_auth
}
@exercise.update!(exercise_params)
@exercise.exercise_group_settings.destroy_all
@ -529,7 +532,8 @@ class ExercisesController < ApplicationController
:answer_open => answer_open,
:exercise_status => exercise_status,
:publish_time => p_time,
:end_time => e_time
:end_time => e_time,
:assistant_auth => assistant_auth
}
@exercise.update!(exercise_params)
if @exercise.exercise_status == Exercise::PUBLISHED
@ -770,10 +774,11 @@ class ExercisesController < ApplicationController
ex_group_setting = exercise.exercise_group_settings
old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", g_course) #试卷的分组设置
left_course_groups = teacher_course_group_ids - g_course
all_left_groups = all_course_group_ids - g_course
left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", left_course_groups)
if left_exercise_groups.blank? && exercise.unified_setting
if left_course_groups.size > 0 #开始为统一设置但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting
left_course_groups.each do |g|
if all_left_groups.size > 0 #开始为统一设置但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting
all_left_groups.each do |g|
ex_group_options = {
:exercise_id => exercise.id,
:course_group_id => g,

@ -2,13 +2,13 @@ class FilesController < ApplicationController
include MessagesHelper
before_action :require_login, :check_auth, except: %i[index]
before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project]
before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project update_visits]
before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish]
before_action :file_validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send
before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project]
before_action :validate_upload_params, only: %i[upload import]
before_action :find_file, only: %i[show setting update]
before_action :validate_upload_params, only: %i[import]
before_action :find_file, only: %i[show setting update update_visits]
before_action :publish_params, only: %i[upload import update]
SORT_TYPE = %w[created_on downloads quotes]
@ -163,6 +163,7 @@ class FilesController < ApplicationController
# 上传资源
def upload
find_course_second_category_id
attachment_ids = params[:attachment_ids]
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
# is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true
@ -170,25 +171,48 @@ class FilesController < ApplicationController
# course_group_publish_times = params[:course_group_publish_times] || []
begin
attachment_ids.each do |attchment_id|
attachment = Attachment.find_by_id attchment_id
unless attachment.nil?
attachment.container = @course
attachment.course_second_category_id = course_second_category_id
attachment.description = params[:description]
attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
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]
if attachment_ids.present?
attachment_ids.each do |attchment_id|
attachment = Attachment.find_by_id attchment_id
unless attachment.nil?
attachment.container = @course
attachment.course_second_category_id = course_second_category_id
attachment.description = params[:description]
attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
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!
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!
end
else
tip_exception("资源名称不能为空") if params[:name].blank?
tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60
tip_exception("链接地址不能为空") if params[:link].blank?
attachment = Attachment.new
attachment.container = @course
attachment.course_second_category_id = course_second_category_id
attachment.author_id = current_user.id
attachment.filename = params[:name].strip
attachment.link = params[:link].strip
attachment.description = params[:description]
attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
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.save!
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -265,6 +289,11 @@ class FilesController < ApplicationController
@old_attachment.save!
@new_attachment.delete
end
if params[:name].present? && params[:link].present?
tip_exception("资源名称不能超过60个字符") if params[:name].strip.length > 60
@old_attachment.filename = params[:name].strip
@old_attachment.link = params[:link].strip
end
@old_attachment.is_public = is_public == true && @course.is_public == 1 ? 1 : 0
@old_attachment.is_publish = @atta_is_publish
@old_attachment.delay_publish = @atta_delay_publish
@ -326,6 +355,11 @@ class FilesController < ApplicationController
end
end
def update_visits
@file.increment!(:downloads)
render_ok
end
private
def find_file
@file = Attachment.find params[:id]

@ -963,7 +963,7 @@ class GamesController < ApplicationController
begin
shixun = game.myshixun.shixun
shixun_tomcat = edu_setting('cloud_bridge')
#service_host = edu_setting('vnc_url')
service_host = edu_setting('vnc_url')
tpiGitURL = "#{edu_setting('git_address_domain')}/#{game.myshixun.repo_path}"
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
@ -973,14 +973,15 @@ class GamesController < ApplicationController
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
@vnc_url = res['showServer']
# if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# # 无域名版本
# "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
# else
# # 有域名版本
# "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
# end
# @vnc_url = res['showServer']
@vnc_url =
if request.subdomain == "pre-newweb" || request.subdomain == "test-newweb"
# 无域名版本
"http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
else
# 有域名版本
"https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
end
@vnc_evaluate = shixun.vnc_evaluate
rescue Exception => e
Rails.logger.error(e.message)

@ -13,7 +13,8 @@ class HackUserLastestCodesController < ApplicationController
end
def update_code
@my_hack.update_attribute(:code, params[:code])
# 防止tpm改动了语言所以更新语言字段
@my_hack.update_attributes(code: params[:code], language: @hack.language)
render_ok
end
@ -72,8 +73,8 @@ class HackUserLastestCodesController < ApplicationController
def record_detail
@hack_user = HackUserCode.find params[:id]
set = HackSet.find_by(id: @hack_user.error_test_set_id)
@pass_set_count = set ? set.position - 1 : 0
@set_count = @hack_user.hack.hack_sets.count
@pass_set_count = set ? set.position - 1 : (@hack_user.status == 0 ? @set_count : 0)
@my_hack = @hack_user.hack_user_lastest_code
end
@ -87,7 +88,7 @@ class HackUserLastestCodesController < ApplicationController
# 只有编译出错时,才正则匹配错误行数
error_line=
if ojEvaResult['status'] == "4" || ojEvaResult['status'] == "5"
regular_match_error_line ojEvaResult['outPut'], @my_hack.hack.language
regular_match_error_line ojEvaResult['outPut'], @hack.language
end
# debug 与submit 公用的参数
@ -100,7 +101,7 @@ class HackUserLastestCodesController < ApplicationController
if ojEvaResult['execMode'] == "debug"
save_debug_data ds_params
elsif ojEvaResult['execMode'] == "submit"
save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'],
save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'], language: @hack.language,
error_test_set_id: ojEvaResult['failCaseNum'])
end
# 评测完成后,还原评测中的状态
@ -134,10 +135,11 @@ class HackUserLastestCodesController < ApplicationController
end
testCases = Base64.encode64(test_sets.to_json)
#codeFileContent = Base64.urlsafe_encode64(@my_hack.code)
Rails.logger.info("##########code_#{@my_hack.identifier}: #{@my_hack.code}")
debug_params = {execMode: exec_mode,
tpiID: @my_hack.identifier,
testCases: testCases,
platform: @my_hack.language,
platform: @my_hack.hack.language,
codeFileContent: @my_hack.code,
timeLimit: @hack.time_limit,
sec_key: Time.now.to_i}
@ -148,7 +150,7 @@ class HackUserLastestCodesController < ApplicationController
# 正则错误行数
def regular_match_error_line content, language
content = Base64.decode64(content).force_encoding("utf-8")
content = Base64.decode64(content) #.force_encoding("utf-8")
logger.info("######content: #{content}")
case language
when 'Java'

@ -64,7 +64,7 @@ class HacksController < ApplicationController
render_ok({identifier: hack.identifier})
rescue => e
logger.error("########create_hack_error: #{e.message}")
render_error("创建失败: #{e.message}")
render_error("#{e.message}")
end
end
@ -96,7 +96,7 @@ class HacksController < ApplicationController
render_ok
rescue Exception => e
logger.error("####update_hack_error: #{e.message}")
render_error("更新失败: #{e.message}")
render_error("#{e.message}")
end
end

File diff suppressed because it is too large Load Diff

@ -34,8 +34,9 @@ class ItemBasketsController < ApplicationController
def delete_item_type
baskets = basket_items.where(item_type: params[:item_type])
item_ids = baskets.pluck(:item_bank_id)
baskets.destroy_all
render_ok
render_ok({item_ids: item_ids})
end
def set_score

@ -4,6 +4,7 @@ class MainController < ApplicationController
skip_before_action :setup_laboratory
def first_stamp
UserOnline.login(session[:request_user_id]) if session[:request_user_id]
render :json => { status: 0, message: Time.now.to_i }
end

@ -22,23 +22,17 @@ class MyshixunsController < ApplicationController
tip_exception("403", "")
end
begin
@shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
ActiveRecord::Base.transaction do
begin
@shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
@myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil,
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
rescue Exception => e
logger.error("######reset_my_game_failed:#{e.message}")
raise("ActiveRecord::RecordInvalid")
end
StudentWork.where(:myshixun_id => @myshixun.id)
.update_all(myshixun_id: 0, work_status: 0, work_score: nil,
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
end
# 删除版本库
GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?
rescue Exception => e
if e.message != "ActiveRecord::RecordInvalid"
logger.error("######delete_repository_error-:#{e.message}")
end
raise "delete_repository_error:#{e.message}"
end
end

@ -135,6 +135,7 @@ class PollsController < ApplicationController
:course_id => @course.id,
:polls_status => 1,
:polls_type => "Course",
:un_anonymous => true
}
@poll = Poll.create!(poll_options)
end

@ -212,6 +212,11 @@ class QuestionBanksController < ApplicationController
homework_type: homework.homework_type, course_id: course.id, homework_bank_id: homework.id,
reference_answer: homework.reference_answer)
if params[:category].present?
category = course.course_second_categories.find_by(id: params[:category])
new_homework.course_second_category_id = category&.id.to_i
end
# 作业的基本设置复制
new_homework.homework_detail_manual = HomeworkDetailManual.new
new_homework_detail_manual = new_homework.homework_detail_manual

@ -87,11 +87,11 @@ class ShixunsController < ApplicationController
@shixuns = @shixuns.includes(:tag_repertoires, :challenges).page(page).per(limit)
@tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires)
.where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) })
.group('shixun_tag_repertoires.shixun_id')
.select('shixun_id, tag_repertoires.name')
.each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name }
#@tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires)
# .where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) })
# .group('shixun_tag_repertoires.shixun_id')
# .select('shixun_id, tag_repertoires.name')
# .each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name }
end
def shixun_list
@ -154,7 +154,7 @@ class ShixunsController < ApplicationController
@can_fork = {can_fork: "已经职业认证的教师才能fork实训",
certi_url: "/account/certification"}
end
@current_myshixun = @shixun.current_myshixun(current_user)
@current_myshixun = @shixun.current_myshixun(current_user.id)
if @shixun.fork_from
fork_shixun = Shixun.select(:id, :user_id, :name, :identifier).where(id: @shixun.fork_from).first
@fork_from = {name: fork_shixun.name, username: fork_shixun.owner.try(:full_name),
@ -182,7 +182,7 @@ class ShixunsController < ApplicationController
select m.user_id, u.login, u.lastname, m.updated_at,
(select sum(cost_time) from games g where g.myshixun_id = m.id) as time,
(select sum(final_score) from games g where g.myshixun_id = m.id) as score
from (users u left join myshixuns m on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1
from (users u left join myshixuns m on m.user_id = u.id) where u.is_test =0 and m.shixun_id = #{@shixun.id} and m.status = 1
order by score desc, time asc limit 10
"
@myshixuns = Myshixun.find_by_sql(sql)
@ -418,8 +418,8 @@ class ShixunsController < ApplicationController
logger.info("#########service_update_params: #{service_update_params}")
begin
ActiveRecord::Base.transaction do
@shixun.update_attributes(shixun_params)
@shixun.shixun_info.update_attributes(shixun_info_params)
@shixun.update_attributes!(shixun_params)
@shixun.shixun_info.update_attributes!(shixun_info_params)
# 镜像变动
@shixun.shixun_mirror_repositories.where.not(mirror_repository_id: old_mirror_ids).destroy_all
@shixun.shixun_mirror_repositories.create!(new_mirror_id) if new_mirror_id.present?

@ -360,6 +360,7 @@ class StudentWorksController < ApplicationController
# 给作品评分
def add_score
tip_exception("该学生的分数已经过调整,不能再评阅") if @work.ultimate_score
tip_exception("学生匿评时分数为必填") if params[:score].blank? && @user_course_identity == Course::STUDENT
tip_exception("分数和评语不能都为空") if params[:score].blank? && params[:comment].blank?
tip_exception("分数不能超过0-100") if params[:score] && (params[:score].to_f < 0 || params[:score].to_f > 100)
@ -373,6 +374,7 @@ class StudentWorksController < ApplicationController
new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != ""
new_score.user_id = current_user.id
new_score.student_work_id = @work.id
new_score.homework_common_id = @work.homework_common_id
# 如果作品是未提交的状态则更新为已提交
if @user_course_identity < Course::STUDENT && !new_score.score.nil? && @work.work_status == 0
@ -552,8 +554,10 @@ class StudentWorksController < ApplicationController
# 分数不为空的历史评阅都置为失效
@work.student_works_scores.where.not(score: nil).update_all(is_invalid: 1)
reviewer_role = @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score = StudentWorksScore.new(student_work_id: @work.id, score: params[:score].to_f, comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}",
user_id: current_user.id, reviewer_role: reviewer_role, is_ultimate: 1)
new_score = StudentWorksScore.new(student_work_id: @work.id, score: params[:score].to_f,
comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}",
homework_common_id: @work.homework_common_id, user_id: current_user.id,
reviewer_role: reviewer_role, is_ultimate: 1)
new_score.save!
# 如果作品是未提交的状态则更新为已提交
@ -843,7 +847,7 @@ class StudentWorksController < ApplicationController
def add_score_to_member student_work, homework, new_score
student_works = homework.student_works.where("group_id = #{student_work.group_id} and id != #{student_work.id} and ultimate_score = 0")
student_works.each do |st_work|
st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score,
st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score, homework_common_id: homework.id,
reviewer_role: new_score.reviewer_role, comment: new_score.comment)
score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id, reviewer_role: new_score.reviewer_role).last

@ -17,76 +17,9 @@ class SubjectsController < ApplicationController
include CustomSortable
def index
@tech_system = current_laboratory.subject_repertoires
select = params[:select] # 路径导航类型
reorder = params[:order] || "publish_time"
search = params[:search]
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 16
offset = (page.to_i-1) * limit
# 最热排序
if reorder == "myshixun_count"
subject_ids = current_laboratory.subjects.pluck(:id)
subject_ids = subject_ids.length > 0 ? "(" + subject_ids.join(",") + ")" : "(-1)"
laboratory_join = " AND subjects.id in #{subject_ids} "
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, subjects.public,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.public = 2 AND subjects.name like '%#{search}%' #{laboratory_join}
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
else
@subjects = current_laboratory.subjects
# 我的路径
if reorder == "mine"
tip_exception(401, "..") unless current_user.logged?
mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in
(select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id)
manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id)
total_subject_id = (mine_subject_id + manage_subject_id).uniq
@subjects = @subjects.where(id: total_subject_id)
elsif reorder == "publish_time"
@subjects = @subjects.unhidden
else
@subjects = @subjects.publiced.unhidden
end
# 类型
if select
@subjects = @subjects.where(repertoire_id: select)
end
if search.present?
@subjects = @subjects.where("name like ?", "%#{search}%")
end
# 排序
order_str = (reorder == "publish_time" ? "homepage_show desc, excellent desc, public = 2 desc, publish_time asc" : "homepage_show desc, excellent desc, updated_at desc")
@subjects = @subjects.reorder(order_str)
end
@total_count = @subjects.size
if reorder != "myshixun_count"
@subjects = @subjects.page(page).per(limit).includes(:shixuns, :repertoire)
else
@subjects = @subjects[offset, limit]
subject_ids = @subjects.pluck(:id)
order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1
@subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, :repertoire)
end
subjects = Weapps::SubjectQuery.call(current_laboratory, params)
@subject_count = subjects.map(&:id).size
@subjects = paginate subjects.includes(:shixuns, :repertoire)
end
def show

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

@ -1,6 +1,6 @@
class Users::VideosController < Users::BaseController
before_action :private_user_resources!, :check_account
before_action :require_teacher!
before_action :require_teacher!, except: [:destroy]
before_action :require_auth_teacher!, except: [:index, :review]
helper_method :current_video
@ -26,7 +26,6 @@ class Users::VideosController < Users::BaseController
return render_error('该状态下不能删除视频') unless video.pending?
video.destroy!
AliyunVod::Service.delete_video([video.uuid]) rescue nil
render_ok
end
@ -53,6 +52,16 @@ class Users::VideosController < Users::BaseController
render_error(ex.message)
end
def destroy
video = Video.find_by(id: params[:id])
return render_forbidden unless video.user_id == current_user.id || current_user.admin?
return render_not_found if video.blank?
video.destroy!
render_ok
end
private
def current_video
@ -72,6 +81,6 @@ class Users::VideosController < Users::BaseController
end
def batch_publish_params
params.permit(videos: %i[video_id title course_id])
params.permit(videos: %i[video_id title course_id category_id])
end
end

@ -0,0 +1,169 @@
class Weapps::AttendancesController < ApplicationController
before_action :require_login
before_action :find_course, only: [:create, :index, :student_attendances, :history_attendances]
before_action :find_attendance, except: [:create, :index, :student_attendances, :history_attendances]
before_action :user_course_identity
before_action :teacher_allowed, only: [:create]
before_action :edit_auth, only: [:update, :destroy, :end]
def create
ActiveRecord::Base.transaction do
attendance = @course.course_attendances.create!(create_params.merge(user_id: current_user.id))
unless params[:group_ids].blank? || @course.course_groups.where(id: params[:group_ids]).count == @course.course_groups.count
group_ids = @course.charge_group_ids(current_user) & params[:group_ids].map(&:to_i)
group_ids.each do |group_id|
@course.course_attendance_groups.create!(course_group_id: group_id, course_attendance: attendance)
end
CreateStudentAttendanceRecordJob.perform_now(attendance.id, group_ids)
else
@course.course_attendance_groups.create!(course_group_id: 0, course_attendance: attendance)
CreateStudentAttendanceRecordJob.perform_now(attendance.id, [0])
end
render_ok({attendance_id: attendance.id})
end
end
def index
tip_exception(403) if @user_course_identity >= Course::STUDENT
current_date = Date.current
current_end_time = Time.current.strftime("%H:%M:%S")
@current_attendance = @course.course_attendances.where("attendance_date > '#{current_date}' or (attendance_date = '#{current_date}' and end_time > '#{current_end_time}')")
.order("attendance_date asc, start_time asc")
all_attendances = @course.course_attendances.where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and end_time < '#{current_end_time}')")
@all_member_attendances = CourseMemberAttendance.where(course_attendance_id: all_attendances)
if params[:group_id].present?
all_attendances = all_attendances.joins(:course_attendance_groups).where(course_attendance_groups: {course_group_id: [params[:group_id], 0]})
@all_member_attendances = @all_member_attendances.joins(:course_member).where(course_members: {course_group_id: params[:group_id]})
end
@history_attendances = all_attendances.order("id asc")
@all_history_count = @history_attendances.size
end
def student_attendances
tip_exception(403) if @user_course_identity > Course::STUDENT
# tip_exception("学生身份的签到列表") if @user_course_identity != Course::STUDENT
member = @course.students.find_by(user_id: current_user.id)
if member.present?
current_date = Date.current
current_end_time = Time.current.strftime("%H:%M:%S")
# 先算出该学生所在分班的签到id
# 分班id为0 表示签到不限制分班
group_ids = [member&.course_group_id.to_i, 0]
all_attendance_ids = @course.course_attendance_groups.where(course_group_id: group_ids).pluck(:course_attendance_id)
# 学生的历史签到只统计加入课堂后创建的签到
history_attendance_ids = member.course_member_attendances.where(course_id: @course.id).pluck(:course_attendance_id)
@history_attendances = @course.course_attendances.where(id: history_attendance_ids.uniq).
where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and end_time < '#{current_end_time}')").order("id desc")
@current_attendances = @course.course_attendances.where(id: all_attendance_ids.uniq).
where("attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}'")
@history_count = @history_attendances.size
# 当前签到如果存在快捷签到,则直接签到(不在这里处理)
# quick_attendances = @current_attendances.where(mode: "QUICK")
# if quick_attendances.present?
# student_direct_attendance quick_attendances, member
# end
student_attendance_ids = @history_attendances.pluck(:id)
student_attendance_ids += @current_attendances.present? ? @current_attendances.pluck(:id) : []
if student_attendance_ids.uniq.blank?
@normal_count = 0
@leave_count = 0
@absence_count = 0
else
@normal_count = @course.course_member_attendances.where(course_member_id: member&.id, course_attendance_id: student_attendance_ids, attendance_status: "NORMAL").size
@leave_count = @course.course_member_attendances.where(course_member_id: member&.id, course_attendance_id: student_attendance_ids, attendance_status: "LEAVE").size
# 旷课只统计历史签到的
@absence_count = @course.course_member_attendances.where(course_member_id: member&.id, course_attendance_id: @history_attendances.pluck(:id), attendance_status: "ABSENCE").size
end
@all_history_count = @history_attendances.size
@history_attendances = paginate @history_attendances.includes(:course_member_attendances)
end
end
def show
@normal_count = @attendance.normal_count
@leave_count = @attendance.leave_count
@absence_count = @attendance.absence_count
@all_count = @attendance.course_member_attendances.size
@_is_current_attendance = @attendance.current_attendance?
if @attendance.course_attendance_groups.first&.course_group_id.to_i == 0
@group_ids = @course.course_groups.pluck(:id) + [0]
else
@group_ids = @attendance.course_attendance_groups.pluck(:course_group_id)
end
@groups = @course.course_groups.where(id: @group_ids)
@course_members = @course.students if @_is_current_attendance
@all_attendances = @attendance.course_member_attendances
end
def update
@attendance.update!(name: params[:name])
render_ok
end
def destroy
@attendance.destroy!
render_ok
end
def history_attendances
current_date = Date.current
current_end_time = Time.current.strftime("%H:%M:%S")
@history_attendances = @course.course_attendances.where("attendance_date < '#{current_date}' or
(attendance_date = '#{current_date}' and end_time < '#{current_end_time}')").order("id desc")
@all_history_count = @history_attendances.size
@history_attendances = paginate @history_attendances.includes(:course_member_attendances)
end
def end
a_end_time = "#{@attendance.attendance_date} #{@attendance.end_time}".to_time
tip_exception("该签到已截止") if a_end_time < Time.now
a_start_time = "#{@attendance.attendance_date} #{@attendance.start_time}".to_time
if a_start_time > Time.now
@attendance.update!(end_time: Time.current, start_time: Time.current, attendance_date: Date.current)
else
@attendance.update!(end_time: Time.current)
end
render_ok
end
private
def create_params
params.permit(:name, :mode, :attendance_date, :start_time, :end_time)
end
def find_attendance
@attendance = CourseAttendance.find params[:id]
@course = @attendance.course
end
def edit_auth
tip_exception(403, "") unless @user_course_identity < Course::PROFESSOR || @attendance.user_id == current_user.id
end
def student_direct_attendance quick_attendances, member
quick_attendances.each do |attendance|
current_attendance = attendance.course_member_attendances.find_by(user_id: member.user_id)
if current_attendance.present?
current_attendance.update!(attendance_status: "NORMAL", attendance_mode: "QUICK")
else
attendance.course_member_attendances.create!(course_member_id: member.id, user_id: member.user_id, course_id: attendance.course_id,
course_group_id: member.course_group_id, attendance_status: "NORMAL", attendance_mode: "QUICK")
end
end
end
end

@ -0,0 +1,12 @@
class Weapps::BannersController < Weapps::BaseController
def index
shixun = WeappSettings::ShixunBanner.first
course = WeappSettings::CourseBanner.first
render json: {
shixun_img: shixun ? Util::FileManage.source_disk_file_url(shixun) : '',
course_img: course ? Util::FileManage.source_disk_file_url(course) : ''
}
end
end

@ -9,7 +9,7 @@ class Weapps::ChallengesController < Weapps::BaseController
play = @shixun.is_jupyter? || @shixun.vnc ||
@shixun.hide_code? || (@shixun.small_mirror_name & ["Css", "Html", "Web"]).present?
if play
if @challenge.st != 1 && play
normal_status(-5, "该关卡暂不支持小程序")
else
render_ok

@ -0,0 +1,81 @@
class Weapps::CourseMemberAttendancesController < ApplicationController
before_action :require_login
before_action :find_course, :user_course_identity, only: [:update_status]
def index
attendance = CourseAttendance.find params[:attendance_id]
if attendance.course_attendance_groups.first&.course_group_id.to_i == 0
@members = attendance.course.students
else
@members = attendance.course.students.where(course_group_id: attendance.course_attendance_groups.pluck(:course_group_id))
end
@member_attendances = attendance.course_member_attendances
if params[:group_ids].present?
@members = @members.where(course_group_id: params[:group_ids])
end
if params[:attendance_status].present?
@members = @members.joins(:course_member_attendances).where(course_member_attendances: {course_attendance_id: attendance.id, attendance_status: params[:attendance_status]})
end
@members = @members.joins(:course_member_attendances).order("attendance_status=1 desc, course_member_attendances.updated_at desc")
@members_count = @members.uniq.count
@members = paginate @members.preload(user: :user_extension).uniq
# @member_attendances = @member_attendances.where(attendance_status: params[:attendance_status]) if params[:attendance_status].present?
# @member_attendances = @member_attendances.joins(user: :user_extension).order("attendance_status=1 desc, course_member_attendances.updated_at desc, user_extensions.student_id asc")
# @member_attendances = paginate @member_attendances.preload(user: :user_extension)
end
def create
tip_exception("签到码不能为空") if params[:attendance_mode] != "QUICK" && params[:code].blank?
tip_exception("attendance_mode参数不对") unless ["NUMBER", "QRCODE", "QUICK"].include?(params[:attendance_mode])
if params[:attendance_mode] == "QUICK"
attendance = CourseAttendance.find_by(id: params[:attendance_id])
else
attendance = CourseAttendance.find_by(attendance_code: params[:code])
end
tip_exception("该签到不存在") if attendance.blank? || attendance.course.blank?
member = attendance.course.students.find_by(user_id: current_user.id)
tip_exception("该签到不存在") if member.blank?
tip_exception("不在签到时间内") unless attendance.current_attendance?
tip_exception("只支持数字签到") if attendance.mode != "ALL" && attendance.mode == "NUMBER" && params[:attendance_mode] != "NUMBER"
tip_exception("只支持二维码签到") if attendance.mode != "ALL" && attendance.mode == "QRCODE" && params[:attendance_mode] != "QRCODE"
tip_exception("只支持快捷签到") if attendance.mode == "QUICK" && params[:attendance_mode] != "QUICK"
current_attendance = attendance.course_member_attendances.find_by(user_id: current_user.id)
if current_attendance.present?
tip_exception("请勿重复签到") if current_attendance.attendance_status == "NORMAL"
tip_exception("您当前是请假状态,无法签到") if current_attendance.attendance_status == "LEAVE"
tip_exception("您当前是旷课状态,无法签到") if current_attendance.attendance_status == "ABSENCE" && current_attendance.attendance_mode == "TEACHER"
current_attendance.update!(attendance_status: "NORMAL", attendance_mode: params[:attendance_mode])
else
attendance.course_member_attendances.create!(course_member_id: member.id, user_id: current_user.id, course_id: attendance.course_id,
course_group_id: member.course_group_id, attendance_status: "NORMAL", attendance_mode: params[:attendance_mode])
end
render_ok
end
def update_status
tip_exception("user_id不能为空") if params[:user_id].blank?
tip_exception(403, "无权限调整签到状态") if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception("attendance_status参数不对") unless ["NORMAL", "LEAVE", "ABSENCE"].include?(params[:attendance_status])
attendance = @course.course_attendances.find_by!(id: params[:attendance_id])
current_attendance = attendance.course_member_attendances.find_by(user_id: params[:user_id])
if current_attendance.present?
current_attendance.update!(attendance_status: params[:attendance_status], attendance_mode: "TEACHER")
else
member = attendance.course.students.find_by(user_id: params[:user_id])
tip_exception( "该用户非课堂学生") if member.blank?
attendance.course_member_attendances.create!(course_member_id: member.id, user_id: params[:user_id], course_id: attendance.course_id,
course_group_id: member.course_group_id, attendance_status: params[:attendance_status], attendance_mode: "TEACHER")
end
render_ok
end
end

@ -1,4 +1,6 @@
class Weapps::CoursesController < Weapps::BaseController
include CustomSortable
before_action :require_login
before_action :set_course, except: [:create, :check_invite_code]
before_action :user_course_identity, except: [:basic_info, :create, :check_invite_code]
@ -8,18 +10,32 @@ class Weapps::CoursesController < Weapps::BaseController
def course_activities
@course = current_course
homework_commons = @course.homework_commons.where(homework_type: ["practice", "normal"]).homework_published
member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
# 签到数据
attendances = @course.course_attendances
current_date = Date.current
current_end_time = Time.current.strftime("%H:%M:%S")
if @user_course_identity == Course::STUDENT
attendances = attendances.joins(:course_attendance_groups).where(course_attendance_groups: {course_group_id: [member.try(:course_group_id).to_i, 0]})
.where("attendance_date < '#{current_date}' or (attendance_date = '#{current_date}' and start_time < '#{current_end_time}')")
end
attendance_ids = attendances.blank? ? "(-1)" : "(" + attendances.pluck(:id).join(",") + ")"
homework_commons = @course.homework_commons.where(homework_type: ["practice", "normal"]).homework_published
if (@user_course_identity == Course::STUDENT && member.try(:course_group_id).to_i == 0) || @user_course_identity > Course::STUDENT
homework_commons = homework_commons.unified_setting
elsif @user_course_identity == Course::STUDENT
not_homework_ids = @course.homework_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}").pluck(:homework_common_id)
not_homework_ids = @course.homework_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}")
.pluck(:homework_common_id)
homework_commons = homework_commons.where.not(id: not_homework_ids)
end
homework_ids = homework_commons.blank? ? "(-1)" : "(" + homework_commons.pluck(:id).join(",") + ")"
activities = @course.course_activities.where("course_act_type in ('Course', 'CourseMessage') or
(course_act_type = 'HomeworkCommon' and course_act_id in #{homework_ids})").order("id desc")
(course_act_type = 'HomeworkCommon' and course_act_id in #{homework_ids}) or
(course_act_type = 'CourseAttendance' and course_act_id in #{attendance_ids})").order("id desc")
@activities_count = activities.size
@activities = paginate activities.includes(:course_act, user: :user_extension)
end
@ -34,6 +50,16 @@ class Weapps::CoursesController < Weapps::BaseController
render_error(ex.message)
end
def course_videos
videos = @course.videos.where(transcoded: true)
videos = custom_sort(videos, params[:sort_by], params[:sort_direction])
#sql = "left join videos on videos.id=course_videos.video_id AND (videos.transcoded=1 OR videos.user_id = #{current_user.id})"
#@videos = paginate videos.joins(sql).includes(video: [user: :user_extension], user: :user_extension)
videos = videos.includes(user: :user_extension)
@count = videos.count
@videos = paginate videos
end
def basic_info
@course = current_course
end

@ -14,6 +14,7 @@ class Users::UpdateAccountForm
validates :technical_title, presence: true, unless: -> { identity.to_s == 'student' }
validates :student_id, presence: true, if: -> { identity.to_s == 'student' }
validates :school_id, presence: true
validates :department_id, presence: true
validate :check_school_exist
def check_school_exist

@ -70,6 +70,8 @@ module ApplicationHelper
# shixun开启挑战对应的行为名及url
def task_operation_url current_myshixun, shixun
return ["开启挑战", "/shixuns/#{shixun.identifier}/shixun_exec"] unless current_user.logged?
if current_myshixun.blank?
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
url = "/shixuns/#{shixun.identifier}/shixun_exec"

@ -55,48 +55,54 @@ module CoursesHelper
return nil if mod.blank? or course.blank?
case mod.module_type
when "announcement"
"/courses/#{course.id}/informs"
"/classrooms/#{course.id}/informs"
when "online_learning"
"/courses/#{course.id}/online_learning"
"/classrooms/#{course.id}/online_learning"
when "shixun_homework"
"/courses/#{course.id}/shixun_homeworks/#{mod.id}"
"/classrooms/#{course.id}/shixun_homeworks/#{mod.id}"
when "common_homework"
"/courses/#{course.id}/common_homeworks/#{mod.id}"
"/classrooms/#{course.id}/common_homeworks/#{mod.id}"
when "group_homework"
"/courses/#{course.id}/group_homeworks/#{mod.id}"
"/classrooms/#{course.id}/group_homeworks/#{mod.id}"
when "graduation"
"/courses/#{course.id}/graduation_topics/#{mod.id}"
"/classrooms/#{course.id}/graduation_topics/#{mod.id}"
when "exercise"
"/courses/#{course.id}/exercises/#{mod.id}"
"/classrooms/#{course.id}/exercises/#{mod.id}"
when "poll"
"/courses/#{course.id}/polls/#{mod.id}"
"/classrooms/#{course.id}/polls/#{mod.id}"
when "attachment"
"/courses/#{course.id}/files/#{mod.id}"
"/classrooms/#{course.id}/files/#{mod.id}"
when "board"
course_board = course.course_board
"/courses/#{course.id}/boards/#{course_board.id}"
"/classrooms/#{course.id}/boards/#{course_board.id}"
when "course_group"
"/courses/#{course.id}/course_groups"
"/classrooms/#{course.id}/course_groups"
when "statistics"
"/courses/#{course.id}/statistics"
"/classrooms/#{course.id}/statistics"
when "video"
"/courses/#{course.id}/course_videos"
"/classrooms/#{course.id}/course_videos"
end
end
# 子目录对应的url
def category_url category, course
case category.category_type
when "shixun_homework"
"/courses/#{course.id}/shixun_homework/#{category.id}"
when "graduation"
if category.name == "毕设选题"
"/courses/#{course.id}/graduation_topics/#{category.course_module_id}"
else
"/courses/#{course.id}/graduation_tasks/#{category.course_module_id}"
end
when "attachment"
"/courses/#{course.id}/file/#{category.id}"
when "shixun_homework"
"/classrooms/#{course.id}/shixun_homework/#{category.id}"
when "common_homework"
"/classrooms/#{course.id}/common_homework/#{category.id}"
when "group_homework"
"/classrooms/#{course.id}/group_homework/#{category.id}"
when "graduation"
if category.name == "毕设选题"
"/classrooms/#{course.id}/graduation_topics/#{category.course_module_id}"
else
"/classrooms/#{course.id}/graduation_tasks/#{category.course_module_id}"
end
when "attachment"
"/classrooms/#{course.id}/file/#{category.id}"
when "video"
"/classrooms/#{course.id}/course_video/#{category.id}"
end
end
@ -105,6 +111,10 @@ module CoursesHelper
case category.category_type
when "shixun_homework"
get_homework_commons_count(course, 4, category.id)
when "common_homework"
get_homework_commons_count(course, 1, category.id)
when "group_homework"
get_homework_commons_count(course, 3, category.id)
when "graduation"
if category.name == "毕设选题"
course.graduation_topics_count
@ -113,6 +123,8 @@ module CoursesHelper
end
when "attachment"
get_attachment_count(course, category.id)
when "video"
get_video_count(course, category.id)
end
end
@ -143,7 +155,7 @@ module CoursesHelper
when "online_learning"
course.shixuns.count
when "video"
course.course_videos.count + course.live_links.count
course.videos_count + course.live_links.count
end
end
@ -234,7 +246,14 @@ module CoursesHelper
# 获取课堂的资源数
def get_attachment_count(course, category_id)
category_id.to_i == 0 ? course.attachments.size : course.attachments.where(course_second_category_id: category_id).size
identity = current_user.course_identity(course)
attachments = category_id.to_i == 0 ? course.attachments : course.attachments.where(course_second_category_id: category_id)
identity > Course::ASSISTANT_PROFESSOR ? attachments.published.size : attachments.size
end
# 获取课堂的视频数
def get_video_count(course, category_id)
category_id.to_i == 0 ? course.course_videos.size : course.course_videos.where(course_second_category_id: category_id).size
end
# 获取课堂的作业数
@ -287,11 +306,11 @@ module CoursesHelper
none_group_count = course.students.where(course_group_id: 0).size
group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1,
category_count: none_group_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/0"}
second_category_url: "/classrooms/#{@course.id}/course_groups/0"}
course.course_groups.each do |course_group|
group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position,
category_count: course_group.course_members_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"}
second_category_url: "/classrooms/#{@course.id}/course_groups/#{course_group.id}"}
end
end
group_info

@ -348,7 +348,7 @@ module ExportHelper
normal_head_cells = %w(作品描述 教师评分 教辅评分)
anon_boolean = homework.anonymous_comment
if anon_boolean
head_cells_add = %w(匿名评分 缺评扣分 违规匿评申诉扣分)
head_cells_add = %w(匿名评分 已评数 缺评扣分 违规匿评申诉扣分)
else
head_cells_add = []
end
@ -395,36 +395,37 @@ module ExportHelper
w_10 = w.teaching_asistant_score.nil? ? "未评分" : w.teaching_asistant_score.round(1)
if anon_boolean
w_11 = w.student_score.nil? ? "未评分" : w.student_score.round(1)
w_12 = (homework.teacher_priority == 1 && !w.teacher_score.nil?) ? 0 : w.absence_penalty #缺评扣分
w_12 = w.user_comment_num
w_13 = (homework.teacher_priority == 1 && !w.teacher_score.nil?) ? 0 : w.absence_penalty #缺评扣分
home_work_de = homework.homework_detail_manual
w_13 = home_work_de.present? ? home_work_de.appeal_penalty : "--" #违规匿评申诉扣分
w_14 = home_work_de.present? ? home_work_de.appeal_penalty : "--" #违规匿评申诉扣分
else
w_11,w_12,w_13 = nil
w_11,w_12,w_13,w_14 = nil
end
if allow_late_boolean #允许迟交
w_14 = (homework.teacher_priority == 1 && !w.teacher_score.nil?) ? 0 : w.late_penalty #迟交扣分
w_15 = (homework.teacher_priority == 1 && !w.teacher_score.nil?) ? 0 : w.late_penalty #迟交扣分
else
w_14 = nil
w_15 = nil
end
w_15 = w.work_score.nil? ? "未评分" : w.work_score.round(1)
w_16 = w.commit_time ? format_time(w.commit_time) : "--"
w_17 = w.update_time ? format_time(w.update_time) : "--"
w_16 = w.work_score.nil? ? "未评分" : w.work_score.round(1)
w_17 = w.commit_time ? format_time(w.commit_time) : "--"
w_18 = w.update_time ? format_time(w.update_time) : "--"
teacher_comments = w.student_works_scores
if teacher_comments.present?
w_18 = ""
w_19 = ""
teacher_comments.each do |t|
user_name = t.user&.real_name
user_time = format_time(t.updated_at)
user_score = t&.score
user_comment = t.comment.present? ? t.comment : "--"
comment_title = "#{user_name} #{user_time.to_s} #{user_score.to_s}\n#{user_comment}\n\n"
w_18 = w_18 + comment_title
w_19 = w_19 + comment_title
end
else
w_18 = "--"
w_19 = "--"
end
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18]
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18,w_19]
row_cells_column = row_cells_column.reject(&:blank?)
@work_cells_column.push(row_cells_column)
end

@ -117,9 +117,16 @@ module HomeworkCommonsHelper
time = "提交剩余时间:" + how_much_time(max_end_time)
time_status = 1
else
status << "已截止"
time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
time_status = 5
if max_end_time.present? && max_end_time < Time.now && homework_common.allow_late &&
(homework_common.late_time.nil? || homework_common.late_time > Time.now)
status << "补交中"
time = "补交剩余时间:" + how_much_time(homework_common.late_time)
time_status = 2
else
status << "已截止"
time = course.end_date.present? ? ("评阅剩余时间:" + how_much_time(course.end_date.end_of_day)) : ""
time_status = 5
end
end
end
end
@ -183,7 +190,7 @@ module HomeworkCommonsHelper
student_works = homework_common.teacher_works(member)
count[:commit_count] = student_works.select{|work| work.work_status != 0 }.size
count[:uncommit_count] = student_works.select{|work| work.work_status == 0 }.size
count[:compelete_count] = Myshixun.where(id: student_works.pluck(:myshixun_id).reject(&:blank?), status: 1).size
count[:compelete_count] = Myshixun.where(id: student_works.pluck(:myshixun_id).reject{|ms| ms==0}, status: 1).size
count[:all_count] = student_works.size
count
end

@ -0,0 +1,20 @@
module Weapps::AttendancesHelper
def student_attendance_status attendance, user
st_attendance = attendance.course_member_attendances.find_by(user_id: user.id)
st_attendance.present? ? st_attendance.attendance_status : "ABSENCE"
end
def group_attendance_count attendances, member_ids
# course_member_ids = group.course_members.pluck(:id)
attendances.select{|attendance| member_ids.include?(attendance.course_member_id) && attendance.attendance_status == "NORMAL"}.size
end
def history_member_count member_attendances, status, attendance_id
member_attendances.select{|member_attendance| member_attendance.attendance_status == status && member_attendance.course_attendance_id == attendance_id}.size
end
def cal_rate base, sum
sum == 0 ? 0 : (base.to_f / sum)
end
end

@ -0,0 +1,26 @@
class CreateStudentAttendanceRecordJob < ApplicationJob
queue_as :default
def perform(attendance_id, group_ids)
attendance = CourseAttendance.find_by(id: attendance_id)
course = attendance.course
return if attendance.blank? || course.blank?
if group_ids.include?(0)
students = course.students
else
students = course.students.where(course_group_id: group_ids)
end
attrs = %i[course_attendance_id user_id course_member_id course_id course_group_id created_at updated_at]
same_attrs = {course_attendance_id: attendance.id, course_id: course.id}
CourseMemberAttendance.bulk_insert(*attrs) do |worker|
students.each do |student|
worker.add same_attrs.merge(user_id: student.user_id, course_member_id: student.id, course_group_id: student.course_group_id)
end
end
end
end

@ -14,7 +14,9 @@ class CreateStudentWorkJob < ApplicationJob
student_ids = course.students.pluck(:user_id)
student_ids.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
unless StudentWork.where(user_id: user_id, homework_common_id: homework.id).exists?
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

@ -22,7 +22,7 @@ class HomeworkEndUpdateScoreJob < ApplicationJob
challenge_settings = homework.homework_challenge_settings
myshixuns.find_each(batch_size: 100) do |myshixun|
work = student_works.select{|work| work.user_id == myshixun.user_id}.first
if work && myshixun && (work.update_time.nil? || work.update_time < myshixun.updated_at)
if work.present? && myshixun
games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id))
HomeworksService.new.update_myshixun_work_score work, myshixun, games, homework, challenge_settings
end

@ -0,0 +1,32 @@
class StudentJoinAttendanceRecordJob < ApplicationJob
queue_as :default
def perform(member_id)
member = CourseMember.find_by(id: member_id)
course = member&.course
return if member.blank? || course.blank?
current_date = Date.current
current_end_time = Time.current.strftime("%H:%M:%S")
group_ids = member.course_group_id == 0 ? [0] : [member.course_group_id, 0]
current_attendance_ids = course.course_attendances.joins(:course_attendance_groups).where(course_attendance_groups: {course_group_id: group_ids}).
where("(attendance_date = '#{current_date}' and start_time <= '#{current_end_time}' and end_time > '#{current_end_time}') or (attendance_date > '#{current_date}')").pluck(:id)
all_group_attendance_ids = course.course_attendances.joins(:course_attendance_groups).where(course_attendance_groups: {course_group_id: 0}).pluck(:id)
member.course_member_attendances.where.not(course_attendance_id: all_group_attendance_ids+current_attendance_ids).delete_all
attrs = %i[course_attendance_id user_id course_member_id course_id course_group_id created_at updated_at]
same_attrs = {course_member_id: member_id, course_id: course.id, user_id: member.user_id, course_group_id: member.course_group_id}
CourseMemberAttendance.bulk_insert(*attrs) do |worker|
current_attendance_ids.each do |attendance_id|
unless course.course_member_attendances.where(course_member_id: member_id, course_attendance_id: attendance_id).exists?
worker.add same_attrs.merge(course_attendance_id: attendance_id)
end
end
end
end
end

@ -23,7 +23,8 @@ module AliyunVod::Service::Base
result
rescue => ex
::Util.logger_error(ex)
raise AliyunVod::Error, ex.message
""
#raise AliyunVod::Error, ex.message
end
def base_params

@ -26,6 +26,26 @@ module AliyunVod::Service::VideoManage
result
end
# 读取视频编码格式与视频格式
def get_meta_code_info(video_id)
params = {
Action: 'GetMezzanineInfo',
VideoId: video_id,
AdditionType: 'video'
}.merge(base_params)
result = request(:post, params)
Rails.logger.info("#######:#{result['Mezzanine']['VideoStreamList'][0]['CodecName']}")
codecnamne = result['Mezzanine']['VideoStreamList'].first['CodecName']
file_url = result['Mezzanine']['FileURL']
format = file_url&.split(".")&.last
{codecnamne: codecnamne, format: format}
rescue => e
Rails.logger.info "读取视频编码信息失败: #{video_id}, #{e.message}"
{codecnamne: "", format: ""}
end
# 删除视频信息
def delete_video(video_ids)
params = {

@ -14,4 +14,20 @@ module AliyunVod::Service::VideoProcess
result
end
# 提交视频转码任务
def submit_transcode_job(video_id, group_id, **opts)
params = {
Action: 'SubmitTranscodeJobs',
VideoId: video_id,
TemplateGroupId: group_id
}.merge(base_params)
params = opts.merge(params)
result = request(:post, params)
raise AliyunVod::Error, '提交视频转码作业失败' if result['TranscodeJobs'].blank?
result
end
end

@ -8,6 +8,8 @@ module AliyunVod::Service::VideoUpload
FileName: filename
}.merge(base_params)
# TODO 获取视频的同时,可以指定转码组,在这里指定
# 参数TemplateGroupId 转码组的id.
# 分类
cate_id = AliyunVod.cate_id
params[:CateId] = cate_id if cate_id.present?

@ -0,0 +1,41 @@
module UserOnline
class << self
def login(user_id)
set_bit(user_id, 1)
end
def logout(user_id)
set_bit(user_id, 0)
end
def set_bit(user_id, flag)
if !Rails.cache.data.exists(cache_key)
Rails.cache.data.setbit(cache_key, user_id, flag)
Rails.cache.data.expire(cache_key, 20 * 60 + 10)
else
Rails.cache.data.setbit(cache_key, user_id, flag)
end
end
def count
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
Rails.cache.data.bitcount(cache_key)
else
0
end
end
def cache_key
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
# 10分钟为一段记录用户在线, 统计范围为20分钟内的线用户
# TODO 更精确时长
begin_hour = Time.now.beginning_of_hour
minutes_piece = (Time.now - begin_hour) / 600
time = begin_hour.since((minutes_piece.to_i - 1) * 600).strftime("%H-%M")
"online_user_#{time}"
else
raise '请配置config.cache_store = redis_store'
end
end
end
end

@ -24,6 +24,7 @@ class Attachment < ApplicationRecord
scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type, :container_type, :container_id) }
scope :search_by_container, -> (ids) {where(container_id: ids)}
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
scope :published, -> {where(is_publish: 1)}
validates_length_of :description, maximum: 100, message: "不能超过100个字符"

@ -69,39 +69,54 @@ class Challenge < ApplicationRecord
end
# 开启挑战
def open_game user_id, shixun
game = self.games.where(user_id: user_id).first
if game.present?
shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : ""
def open_game shixun
# 这里的identifier,status是关联了games取了games的identifier,status
identifier = self.identifier
if identifier.present?
shixun.task_pass || self.status != 3 ? "/tasks/#{identifier}" : ""
else
"/api/shixuns/#{shixun.identifier}/shixun_exec"
self.position == 1 ? "/api/shixuns/#{shixun.identifier}/shixun_exec" : ""
end
end
# # 开启挑战
# def open_game(user_id, shixun)
#
#
# game = self.games.select([:status, :identifier]).where(user_id: user_id).first
# game = self.games.select{|game| game.user_id == user_id}
# def open_game shixun, user_id
# game = self.games.map{|g| g.user_id == user_id}.first
# if game.present?
# shixun.task_pass || game.status != 3 ? "/tasks/#{game.identifier}" : ""
# else
# "/api/shixuns/#{shixun.identifier}/shixun_exec"
# self.position == 1 ? "/api/shixuns/#{shixun.identifier}/shixun_exec" : ""
# end
# end
## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成
def user_tpi_status user_id
# def user_tpi_status shixun, user_id
# # todo: 以前没加索引导致相同关卡,同一用户有多个games
# # 允许跳关则直接开启
# game = games.where(user_id: user_id).take
# if game.blank?
# position == 1 ? 1 : 0
# else
# if game.status == 3
# shixun.task_pass ? 1 : 0
# elsif game.status == 2
# 2
# else
# 1
# end
# end
# end
# ## 用户关卡状态 0: 不能开启实训; 1:直接开启; 2表示已完成
def user_tpi_status shixun
# todo: 以前没加索引导致相同关卡,同一用户有多个games
# 允许跳关则直接开启
game = games.where(user_id: user_id).take
if game.blank?
position == 1 ? 1 : 0
identifier = self.identifier
if identifier.blank?
self.position == 1 ? 1 : 0
else
if game.status == 3
if status == 3
shixun.task_pass ? 1 : 0
elsif game.status == 2
elsif status == 2
2
else
1
@ -127,12 +142,14 @@ class Challenge < ApplicationRecord
# 关卡用户通关数
def user_passed_count
games.where(status: 2).count
#games.map{|g| g.status == 2}.count
self.games.where(status: 2).count
end
# 关卡用户正在挑战的人数
def playing_count
games.where(status: [0, 1]).count
#games.map{|g| g.status == 0 || g.status == 1}.count
self.games.where(status: [0,1]).count
end
def last_challenge

@ -90,6 +90,13 @@ class Course < ApplicationRecord
# 直播
has_many :live_links, dependent: :destroy
# 签到
has_many :course_attendances, dependent: :destroy
has_many :course_attendance_groups
has_many :course_member_attendances
has_many :teacher_group_records, dependent: :destroy
validate :validate_sensitive_string
scope :hidden, ->(is_hidden = true) { where(is_hidden: is_hidden) }
@ -153,6 +160,10 @@ class Course < ApplicationRecord
students.find_by(user_id: user_id)&.course_group_name
end
def videos_count
course_videos.where(video_id: videos.where("transcoded = 1 or videos.user_id = #{User.current.id}").pluck(:id))
.or(course_videos.where(course_videos: {is_link: true})).size
end
def teacher_group(user_id)
data =
@ -257,10 +268,10 @@ class Course < ApplicationRecord
# 老师负责的分班id
def charge_group_ids user
member = course_member(user.id)
member = user.is_a?(CourseMember) ? user : course_member(user&.id)
group_ids = if member.present?
member.teacher_course_groups.size > 0 ? member.teacher_course_groups.pluck(:course_group_id) : course_groups.pluck(:id)
elsif user.admin_or_business?
elsif user&.admin_or_business?
course_groups.pluck(:id)
else
[]
@ -387,7 +398,7 @@ class Course < ApplicationRecord
end
def max_activity_time
course_acts.pluck(:updated_at).max
course_activities.pluck(:updated_at).max
end
# 课堂作业数

@ -2,10 +2,11 @@ class CourseActivity < ApplicationRecord
belongs_to :course_act, polymorphic: true
belongs_to :course
belongs_to :user
belongs_to :exercise
belongs_to :poll
belongs_to :course_message
belongs_to :homework_common
belongs_to :exercise, optional: true
belongs_to :poll, optional: true
belongs_to :course_message, optional: true
belongs_to :homework_common, optional: true
belongs_to :course_attendance, optional: true
# after_create :add_course_lead

@ -0,0 +1,69 @@
class CourseAttendance < ApplicationRecord
# status: 0: 未开启1已开启2已截止
# mode: 0 两种签到1 二维码签到2 数字签到3 快捷签到
enum mode: { ALL: 0, QRCODE: 1, NUMBER: 2, QUICK: 3 }
belongs_to :course
belongs_to :user
has_many :course_attendance_groups, dependent: :destroy
has_many :course_member_attendances, dependent: :destroy
has_one :course_act, class_name: 'CourseActivity', as: :course_act, dependent: :destroy
validates :name, presence: true, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :mode, presence: true
validates :attendance_date, presence: true
validates :start_time, presence: true
validates :end_time, presence: true
after_create :generate_attendance_code, :act_as_course_activity
# 正常签到人数
def normal_count
course_member_attendances.select{|member_attendance| member_attendance.attendance_status == "NORMAL"}.size
end
# 请假人数
def leave_count
course_member_attendances.select{|member_attendance| member_attendance.attendance_status == "LEAVE"}.size
end
# 旷课人数
def absence_count
course_member_attendances.select{|member_attendance| member_attendance.attendance_status == "ABSENCE"}.size
end
# 总人数
def all_count
course_member_attendances.size
end
def current_attendance?
a_start_time = "#{attendance_date} #{start_time}".to_time
a_end_time = "#{attendance_date} #{end_time}".to_time
a_start_time < Time.current && Time.current < a_end_time
end
#课程动态公共表记录
def act_as_course_activity
CourseActivity.create(user_id: user_id, course_id: course_id, course_act: self)
end
# 延迟生成邀请码
def attendance_code
return generate_attendance_code
end
# 生成邀请码
CODES = %W(2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z)
def generate_attendance_code
code = read_attribute(:attendance_code)
if !code || code.size < 4
code = CODES.sample(4).join
return generate_attendance_code if CourseAttendance.where(attendance_code: code).present?
update_attribute(:attendance_code, code)
end
code
end
end

@ -0,0 +1,5 @@
class CourseAttendanceGroup < ApplicationRecord
belongs_to :course
belongs_to :course_attendance
belongs_to :course_group, optional: true
end

@ -9,6 +9,8 @@ class CourseGroup < ApplicationRecord
has_many :homework_group_settings, :dependent => :destroy
scope :by_group_ids, lambda { |ids| where(id: ids)}
has_many :course_attendance_groups, dependent: :destroy
validates :name, length: { maximum: 60, too_long: "不能超过60个字符" }
validates_uniqueness_of :name, scope: :course_id, message: "不能创建相同名称的分班"

@ -8,6 +8,7 @@ class CourseMember < ApplicationRecord
belongs_to :course_group, counter_cache: true, optional: true
belongs_to :graduation_group, optional: true
has_many :teacher_course_groups, dependent: :destroy
has_many :course_member_attendances, dependent: :destroy
scope :teachers_and_admin, -> { where(role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR]) }
scope :students, ->(course) { where(course_id: course.id, role: %i[STUDENT])}
@ -22,6 +23,10 @@ class CourseMember < ApplicationRecord
# after_destroy :delete_works
# after_create :work_operation
after_create :create_attendance_record
after_commit :create_attendance_record
def delete_works
if self.role == "STUDENT"
course = self.course
@ -156,4 +161,11 @@ class CourseMember < ApplicationRecord
end
teachers
end
private
def create_attendance_record
StudentJoinAttendanceRecordJob.perform_later(id)
end
end

@ -0,0 +1,11 @@
class CourseMemberAttendance < ApplicationRecord
# attendance_mode 0 初始数据1 二维码签到2 数字签到3 老师签到
enum attendance_mode: { DEFAULT: 0, QRCODE: 1, NUMBER: 2, QUICK: 3, TEACHER: 4}
# attendance_status 1 正常签到2 请假0 旷课
enum attendance_status: { NORMAL: 1, LEAVE: 2, ABSENCE: 0 }
belongs_to :course_member
belongs_to :user
belongs_to :course
belongs_to :course_attendance
belongs_to :course_group
end

@ -1,4 +1,8 @@
class CourseVideo < ApplicationRecord
belongs_to :course
belongs_to :video
belongs_to :video, optional: true
belongs_to :user, optional: true
validates :title, length: { maximum: 60, too_long: "不能超过60个字符" }, allow_blank: true
validates :link, format: { with: CustomRegexp::URL, message: "必须为网址超链接" }, allow_blank: true
end

@ -0,0 +1,11 @@
#encoding=utf-8
class Ecloud < ActiveRecord::Base
# attr_accessible :applyno, :begintime, :bossorderid, :custcode, :custid, :custname, :custtype, :ecordercode, :endtime,
# :mobile, :opttype, :productcode, :registersource, :string, :trial, :useralias, :userid, :username, :email,
# :effecttime, :operatime
has_many :ecloud_services, :dependent => :destroy # 业务列表
has_many :ecloud_productparas, :dependent => :destroy # 开通参数列表
has_one :ecloud_user
end

@ -0,0 +1,3 @@
class EcloudLog < ActiveRecord::Base
end

@ -0,0 +1,4 @@
class EcloudProductpara < ActiveRecord::Base
# attr_accessible :key, :value, :ecloud_id
belongs_to :ecloud
end

@ -0,0 +1,6 @@
# 操作代码 0新增业务1注销业务2修改业务
class EcloudService < ActiveRecord::Base
# attr_accessible :begintime, :code, :endtime, :opttype, :ecloud_id, :packagecode, :bossorderid
belongs_to :ecloud
has_many :ecloud_serviece_serviceparas
end

@ -0,0 +1,5 @@
# ket值license表示人数对应企业版duration表示月数对应个人版
class EcloudServieceServicepara < ActiveRecord::Base
# attr_accessible :key, :value, :ecloud_service_id
belongs_to :ecloud_service
end

@ -0,0 +1,3 @@
class EcloudUser < ActiveRecord::Base
has_many :ecloud_user_paras
end

@ -0,0 +1,3 @@
class EcloudUserPara < ActiveRecord::Base
belongs_to :ecloud_user
end

@ -0,0 +1,4 @@
class EcloudUser < ActiveRecord::Base
# opttype: # user['opttype']: 操作类型0开通1变更3: 取消授权4暂停5恢复
# attr_accessible :begintime, :email, :endtime, :mobile, :opttype, :paras, :useralias, :userid, :username, :custid
end

@ -7,6 +7,7 @@
class Game < ApplicationRecord
default_scope { order("games.created_at desc") }
#TODO: games表要增加challenge_id与user_id的唯一索引
has_many :outputs, -> { order('query_index DESC') }
has_many :challenge_samples, :dependent => :destroy
has_many :game_codes, :dependent => :destroy

@ -4,8 +4,8 @@ class Hack < ApplicationRecord
# 编程题
validates_length_of :name, maximum: 60, message: "不能超过60个字符"
validates_length_of :description, maximum: 5000, message: "不能超过5000个字符"
validates :description, presence: { message: "描述不能为空" }
validates :name, presence: { message: "名称不能为空" }
validates_presence_of :description, message: "描述不能为空"
validates_presence_of :name, message: "名称不能为空"
# 测试集
has_many :hack_sets, ->{order("position asc")}, :dependent => :destroy
# 代码

@ -1,9 +1,9 @@
class HackSet < ApplicationRecord
validates_length_of :input, maximum: 1000, message: "不能超过1000个字符"
validates_length_of :output, maximum: 1000, message: "不能超过1000个字符"
validates :input, presence: { message: "测试集输入不能为空" }
validates :output, presence: { message: "测试集输出不能为空" }
validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同"
#validates :input, presence: { message: "测试集输入不能为空" }
validates_presence_of :output, message: "不能为空"
#validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个不能相同"
# 编程题测试集
belongs_to :hack
end

@ -12,5 +12,5 @@ class HomeworkBank < ApplicationRecord
validates :name, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :description, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :reference_answer, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :reference_answer, length: { maximum: 25000, too_long: "不能超过25000个字符" }
end

@ -6,6 +6,7 @@ class HomeworkCommon < ApplicationRecord
has_many :student_works, -> { where(is_delete: 0) }
has_many :score_student_works, -> { where("is_delete = 0 and work_status != 0").order("work_score desc") }, class_name: "StudentWork"
has_one :homework_detail_manual, dependent: :destroy
has_many :student_works_scores
# 分组作业的设置
has_one :homework_detail_group, dependent: :destroy
@ -38,7 +39,7 @@ class HomeworkCommon < ApplicationRecord
validates :name, presence: true, length: { maximum: 60, too_long: "不能超过60个字符" }
validates :description, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :explanation, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :reference_answer, length: { maximum: 15000, too_long: "不能超过15000个字符" }
validates :reference_answer, length: { maximum: 25000, too_long: "不能超过25000个字符" }
# after_update :update_activity
before_destroy :update_homework_bank_quotes
@ -47,6 +48,7 @@ class HomeworkCommon < ApplicationRecord
scope :homework_published, -> {where("homework_commons.publish_time IS NOT NULL AND homework_commons.publish_time <= ? ",Time.now)}
scope :published_no_end, -> {where("homework_commons.publish_time IS NOT NULL AND homework_commons.publish_time < ?
and homework_commons.end_time > ?", Time.now, Time.now)}
scope :homework_ended, -> {where("homework_commons.end_time IS NOT NULL AND homework_commons.end_time <= ? ",Time.now)}
scope :search_homework_type, lambda {|num| where(homework_type:num)}
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
@ -67,17 +69,18 @@ class HomeworkCommon < ApplicationRecord
# 作业对应的子目录/父目录名称
def category_info
case self.homework_type
when 'normal'
{category_id: course.common_course_modules.first.try(:id), category_name: course.common_course_modules.first.try(:module_name), main: 1}
when 'group'
{category_id: course.group_course_modules.first.try(:id), category_name: course.group_course_modules.first.try(:module_name), main: 1}
when 'practice'
if self.course_second_category.present?
{category_id: self.course_second_category.try(:id), category_name: self.course_second_category.try(:name), main: 0}
else
{category_id: course.shixun_course_modules.take.try(:id), category_name: course.shixun_course_modules.take.try(:module_name), main: 1}
end
if self.course_second_category.present?
{category_id: self.course_second_category.try(:id), category_name: self.course_second_category.try(:name), main: 0}
else
course_module = case homework_type
when 'normal'
course.common_course_modules.take
when 'group'
course.group_course_modules.take
when 'practice'
course.shixun_course_modules.take
end
{category_id: course_module.try(:id), category_name: course_module.try(:module_name), main: 1}
end
end
@ -103,7 +106,7 @@ class HomeworkCommon < ApplicationRecord
end
def user_work user_id
work = self.student_works.find_by_user_id(user_id) || StudentWork.create!(homework_common_id: id, user_id: user_id)
work = StudentWork.find_by(homework_common_id: id, user_id: user_id) || StudentWork.create!(homework_common_id: id, user_id: user_id)
end
# 是否在补交阶段内
@ -141,15 +144,17 @@ class HomeworkCommon < ApplicationRecord
end
# 作业能否立即发布
def publish_immediately user
homework_detail_manual.try(:comment_status) == 0 || homework_group_settings.where(course_group_id: course.charge_group_ids(user)).
none_published.count > 0
def publish_immediately charge_ids
homework_detail_manual.try(:comment_status) == 0 ||
homework_group_settings.select{|setting| charge_ids.include?(setting.course_group_id) &&
(setting.publish_time.nil? || setting.publish_time > Time.now)}.size > 0
end
# 作业能否立即截止
def end_immediately user
(unified_setting && homework_detail_manual.try(:comment_status) == 1 && end_time > Time.now) || homework_group_settings.
where(course_group_id: course.charge_group_ids(user)).published_no_end.count > 0
def end_immediately charge_ids
(unified_setting && homework_detail_manual.try(:comment_status) == 1 && end_time.present? && end_time > Time.now) ||
homework_group_settings.select{|setting| charge_ids.include?(setting.course_group_id) &&
!setting.publish_time.nil? && setting.publish_time < Time.now && setting.end_time > Time.now}.size > 0
end
# 学生是否提交了作品

@ -7,5 +7,6 @@ class HomeworkGroupSetting < ApplicationRecord
scope :published_no_end, -> {where("homework_group_settings.publish_time IS NOT NULL AND homework_group_settings.publish_time < ?
and homework_group_settings.end_time > ?", Time.now, Time.now)}
scope :none_end, -> {where("homework_group_settings.end_time IS NULL or homework_group_settings.end_time > ?", Time.now)}
scope :has_end, -> {where("homework_group_settings.end_time IS NOT NULL AND homework_group_settings.end_time <= ?", Time.now)}
end

@ -30,6 +30,10 @@ class LaboratorySetting < ApplicationRecord
image_url('_subject_banner')
end
def shixun_banner_url
image_url('_shixun_banner')
end
def course_banner_url
image_url('_course_banner')
end
@ -62,7 +66,7 @@ class LaboratorySetting < ApplicationRecord
name: nil,
navbar: [
{ 'name' => '实践课程', 'link' => '/paths', 'hidden' => false },
{ 'name' => '翻转课堂', 'link' => '/courses', 'hidden' => false },
{ 'name' => '教学课堂', 'link' => '/courses', 'hidden' => false },
{ 'name' => '实训项目', 'link' => '/shixuns', 'hidden' => false },
{ 'name' => '在线竞赛', 'link' => '/competitions', 'hidden' => false },
{ 'name' => '教学案例', 'link' => '/moop_cases', 'hidden' => false },

@ -264,7 +264,7 @@ class Shixun < ApplicationRecord
# 实训关卡的总分(由于大部分是实践题,因此没关联查choose表)
# 提前加载问题由于选择题比较少所以几乎不会触发选择题的查询所以没必要提前载入choose_score
def all_score
self.challenges.pluck(:score).sum
self.challenges.sum(:score)
end
### fork 数量

@ -2,9 +2,11 @@ class ShixunInfo < ApplicationRecord
belongs_to :shixun
validates_uniqueness_of :shixun_id
validates_length_of :fork_reason, maximum: 60, message: "不能超过60个字符"
# validates_presence_of :evaluate_script, message: "实训脚本不能为空"
after_commit :create_diff_record
validates :description, length: { maximum: 5000, too_long: "不能超过5000个字符" }
validates :description, length: { maximum: 10000, too_long: "不能超过10000个字符" }
private

@ -0,0 +1,20 @@
class StaAll < ApplicationRecord
# t.integer :school_id 学校ID
# t.integer :tea_count 老师数
# t.integer :stu_count 学生数
# t.integer :active_users_count 活跃用户数3个月内有登录
# t.integer :courses_count 总课堂数
# t.integer :curr_courses_count 正在进行的课堂数
# t.integer :homw_shixuns_count 实训作业数
# t.integer :homw_other_count 其它类型作业数
# t.integer :sources_count 资源数
# t.integer :videos_count 视频总个数
# t.integer :shixuns_count 制作实训总数
# t.integer :myshixuns_count 挑战实训总数
# t.integer :mys_passed_count 通关的实训总数
# t.integer :games_count 挑战的总关卡数
# t.integer :games_passed_count 通关的总关卡数
# t.integer :build_count 评测总数
belongs_to :school
end

@ -46,7 +46,17 @@ class StudentWork < ApplicationRecord
# 匿评次数
def student_comment_num
homework_common.homework_detail_manual.comment_status > 2 ? self.student_works_scores.select{|score| score.reviewer_role == 3}.group_by(&:user_id).count : 0
homework_common.homework_detail_manual.comment_status > 2 && work_status > 0 ? self.student_works_scores.select{|score| score.reviewer_role == 3}.group_by(&:user_id).size : 0
end
# 学生评阅作品数
def user_comment_num
if homework_common.homework_detail_manual.comment_status > 2 && work_status > 0
count = homework_common.student_works_scores.select{|score| score.reviewer_role == 3 && score.user_id == user_id}.group_by(&:student_work_id).size
else
count = 0
end
count
end
# 匿评申诉总条数

@ -2,6 +2,7 @@ class StudentWorksScore < ApplicationRecord
#appeal_status: 0正常1申诉中2撤销申诉3申诉成功4申诉被拒绝5申诉失效
belongs_to :student_work
belongs_to :user
belongs_to :homework_common, optional: true
has_many :journals_for_messages, -> { order('created_on desc') }, as: :jour, dependent: :destroy
has_one :student_works_scores_appeal, dependent: :destroy
has_many :tidings, as: :container, dependent: :destroy

@ -0,0 +1,4 @@
class TeacherGroupRecord < ApplicationRecord
belongs_to :user
belongs_to :course
end

@ -118,8 +118,8 @@ class User < ApplicationRecord
has_many :manage_courses, through: :manage_course_members, source: :course
# 关注
has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
# has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
# has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
# 认证
has_many :apply_user_authentication
@ -160,6 +160,8 @@ class User < ApplicationRecord
has_many :examination_banks, dependent: :destroy
has_many :examination_intelligent_settings, dependent: :destroy
has_many :teacher_group_records, dependent: :destroy
# Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) }
@ -337,7 +339,7 @@ class User < ApplicationRecord
# 实训管理员实训合作者、admin
def manager_of_shixun?(shixun)
logger.info("############id: #{id}")
shixun.shixun_members.exists?(role: [1,2], user_id: id) || admin? || business?
shixun.shixun_members.exists?(user_id: id, role: [1,2]) || admin? || business?
end
# 实训管理员
@ -655,6 +657,7 @@ class User < ApplicationRecord
# 邮箱w***l@qq.com
def hidden_mail
Rails.logger.info("######-----: #{mail}")
Util.conceal(mail, :email).to_s
end
@ -726,8 +729,8 @@ class User < ApplicationRecord
end
def validate_sensitive_string
raise("真实姓名包含敏感词汇,请重新输入") if lastname && !HarmoniousDictionary.clean?(lastname)
raise("昵称包含敏感词汇,请重新输入") if nickname && !HarmoniousDictionary.clean?(nickname)
raise("真实姓名包含敏感词汇,请重新输入#{lastname}") if lastname && !HarmoniousDictionary.clean?(lastname)
raise("昵称包含敏感词汇,请重新输入#{nickname}") if nickname && !HarmoniousDictionary.clean?(nickname)
end
def set_laboratory

@ -1,6 +1,16 @@
class Video < ApplicationRecord
include AASM
alias_method :hard_destroy, :destroy
default_scope -> { where(delete_state: nil) }
scope :deleted, -> { unscope(where: :delete_state).where.not(delete_state: nil) }
BEGIN_DELETE = 1 # 标记软删除
FINISH_DELETE = 2 # 视频资源完成删除
# 标准视频转码组
NORMAL_TRANSCODE_GROUP_ID = 'a0277c5c0c7458458e171b0cee6ebf5e'
belongs_to :user
has_many :video_applies, dependent: :destroy
@ -38,4 +48,17 @@ class Video < ApplicationRecord
def video_play_duration
(play_duration / (60*60.0)).ceil
end
def destroy
run_callbacks(:destroy) do
if persisted?
update_column(:delete_state, Video::BEGIN_DELETE)
AliyunVod::Service.delete_video([self.uuid])
end
@destroyed = true
end
freeze
end
end

@ -0,0 +1,3 @@
class WeappSettings::CourseBanner < WeappSetting
default_scope { order(position: :asc) }
end

@ -0,0 +1,3 @@
class WeappSettings::ShixunBanner < WeappSetting
default_scope { order(position: :asc) }
end

@ -0,0 +1,114 @@
class Admins::UserSchoolsStatisticQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :cnt,
default_by: :cnt, default_direction: :desc
def initialize(params)
@params = params
end
def call
schools = School
if params[:province].present?
schools = schools.where("province like ?", "%#{params[:province]}%")
end
if params[:school_id].present?
schools = schools.where(id: params[:school_id])
end
total = schools.count
# 根据排序字段进行查询
schools = query_by_sort_column(schools.group(:id), params[:sort_by])
#schools = custom_sort(schools, params[:sort_by], params[:sort_direction])
schools = schools.limit(page_size).offset(offset).to_a
# 查询并组装其它数据
schools = package_other_data(schools)
[total, schools]
end
private
def package_other_data(schools)
ids = schools.map(&:id)
user_e = UserExtension.where(school_id: schools.map(&:id))
#study_myshixun = Myshixun.joins("join user_extensions ue on ue.user_id = myshixuns.user_id").where(ue: {school_id: ids})
#finish_myshixun = Myshixun.joins("join user_extensions ue on ue.user_id = myshixuns.user_id")
# .where(ue: {school_id: ids}, myshixuns: {status: 1})
study_challenge = Game.joins("join user_extensions ue on ue.user_id = games.user_id")
.where(ue: {school_id: ids},).where( games:{status: [0, 1, 2]})
finish_challenge = Game.joins("join user_extensions ue on ue.user_id = games.user_id")
.where(ue: {school_id: ids}).where(games: {status: 2})
reg_teacher = user_e.where(identity: 'teacher')
reg_student = user_e.where.not(identity: 'teacher')
if time_range.present?
#study_myshixun = study_myshixun.where(updated_at: time_range)
#finish_myshixun = finish_myshixun.where(updated_at: time_range)
study_challenge = study_challenge.where(updated_at: time_range)
finish_challenge = finish_challenge.where(updated_at: time_range)
reg_teacher = reg_teacher.where(created_at: time_range)
reg_student = reg_student.where(created_at: time_range)
user_e = user_e.joins(:user).where(users: {last_login_on: time_range})
end
#study_myshixun_map = study_myshixun.reorder(nil).group(:school_id).count
#finish_myshixun_map = finish_myshixun.reorder(nil).group(:school_id).count
study_challenge_map = study_challenge.reorder(nil).group(:school_id).count
finish_challenge_map = finish_challenge.reorder(nil).group(:school_id).count
evaluate_count_map = study_challenge.reorder(nil).group(:school_id).sum(:evaluate_count)
reg_teacher_map = reg_teacher.reorder(nil).group(:school_id).count
reg_student_map = reg_student.reorder(nil).group(:school_id).count
user_e_map = user_e.reorder(nil).group(:school_id).count
schools.each do |school|
school._extra_data = {
#study_shixun_count: study_myshixun_map.fetch(schools.id, 0),
#finish_shixun_count: finish_myshixun_map.fetch(schools.id, 0),
study_challenge_count: study_challenge_map.fetch(school.id, 0),
finish_challenge_count: finish_challenge_map.fetch(school.id, 0),
evaluate_count: evaluate_count_map.fetch(school.id, 0),
reg_teacher_count: reg_teacher_map.fetch(school.id, 0),
reg_student_count: reg_student_map.fetch(school.id, 0),
user_active_count: user_e_map.fetch(school.id, 0)
}
end
schools
end
def query_by_sort_column(schools, sort_by_column)
#base_query_column = 'schools.*'
case sort_by_column.to_s
when 'cnt' then
schools.left_joins(:user_extensions).select("schools.*, count(*) cnt").order("cnt desc")
else
schools
end
end
def time_range
@_time_range ||= begin
case params[:date]
when 'dayly' then 1.days.ago..Time.now
when 'weekly' then 1.weeks.ago..Time.now
when 'monthly' then 1.months.ago..Time.now
when 'quarterly' then 3.months.ago..Time.now
when 'yearly' then 1.years.ago..Time.now
else ''
end
end
end
def page_size
params[:per_page].to_i.zero? ? 20 : params[:per_page].to_i
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size
end
end

@ -8,7 +8,7 @@ class Weapps::SubjectQuery < ApplicationQuery
end
def call
subjects = @current_laboratory.subjects.unhidden.publiced.show_moblied
subjects = @current_laboratory.subjects.unhidden.publiced
# 课程体系的过滤
if params[:sub_discipline_id].present?
@ -19,8 +19,13 @@ class Weapps::SubjectQuery < ApplicationQuery
subjects = subjects.joins(:sub_discipline_containers).where(sub_discipline_containers: {container_type: "Subject"})
end
subjects = subjects.left_joins(:shixuns).select('subjects.id, subjects.name, subjects.excellent, subjects.stages_count, subjects.status, subjects.homepage_show,
subjects.shixuns_count, subjects.updated_at, IFNULL(sum(shixuns.myshixuns_count), 0) myshixuns_count')
# 搜索
if params[:keyword].present?
subjects = subjects.where("subjects.name like '%#{params[:keyword]}%'")
end
subjects = subjects.left_joins(:shixuns, :repertoire).select('subjects.id, subjects.name, subjects.excellent, subjects.stages_count, subjects.status, subjects.homepage_show,
subjects.shixuns_count, subjects.repertoire_id, subjects.updated_at, IFNULL(sum(shixuns.myshixuns_count), 0) myshixuns_count')
.group('subjects.id').order("subjects.homepage_show #{sort_type}, #{order_type} #{sort_type}")
subjects
end

@ -29,14 +29,14 @@ class Admins::ImportDisciplineService < ApplicationService
return unless discipline_name.present?
discipline = Discipline.find_by(name: discipline_name)
if discipline.blank?
discipline = Discipline.create!(name: discipline_name, position: Discipline.all.pluck(:position).max + 1)
discipline = Discipline.create!(name: discipline_name, position: Discipline.all.pluck(:position).max.to_i + 1)
count += 1
end
if sub_discipline_name.present?
sub_discipline = SubDiscipline.find_by(name: discipline_name, discipline: discipline)
if sub_discipline.blank?
SubDiscipline.create!(name: sub_discipline_name, discipline: discipline, position: discipline.sub_disciplines.pluck(:position).max + 1)
SubDiscipline.create!(name: sub_discipline_name, discipline: discipline, position: discipline.sub_disciplines.pluck(:position).max.to_i + 1)
count += 1
end
end

@ -40,6 +40,7 @@ class Admins::SaveLaboratorySettingService < ApplicationService
save_image_file(params[:login_logo], 'login')
save_image_file(params[:tab_logo], 'tab')
save_image_file(params[:subject_banner], '_subject_banner')
save_image_file(params[:shixun_banner], '_shixun_banner')
save_image_file(params[:course_banner], '_course_banner')
save_image_file(params[:competition_banner], '_competition_banner')
save_image_file(params[:moop_cases_banner], '_moop_cases_banner')

@ -44,7 +44,7 @@ class Admins::SchoolDailyStatisticService < ApplicationService
courses = Course.where(is_delete: 0, school_id: ids).group('school_id')
course_map = courses.count
nearly_course_time_map = courses.joins(:course_acts).maximum('course_activities.updated_at')
nearly_course_time_map = courses.joins(:course_activities).maximum('course_activities.updated_at')
active_course_map = courses.where(is_end: false).count
shixun_map = Shixun.joins(user: :user_extension).where(user_extensions: { identity: :teacher, school_id: ids })

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

Loading…
Cancel
Save