class SubjectsController < ApplicationController
before_action :require_login , :check_auth , except : [ :index , :show , :right_banner ]
# before_action :check_auth, except: [:index]
before_action :check_account , except : [ :index , :show , :right_banner ]
before_action :find_subject , except : [ :index , :create , :new , :append_to_stage ]
before_action :allowed , only : [ :update , :edit , :destroy , :publish , :cancel_publish , :cancel_has_publish ,
:search_members , :add_subject_members , :statistics , :shixun_report , :school_report ,
:up_member_position , :down_member_position , :update_team_title ]
include ApplicationHelper
include SubjectsHelper
def index
@tech_system = Repertoire . where ( nil ) . order ( " updated_at desc " )
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 "
laboratory_join = current_laboratory . main_site? ? '' : " JOIN laboratory_subjects ls ON ls.subject_id = subjects.id AND ls.laboratory_id = #{ current_laboratory . id } "
if select
@subjects = Subject . find_by_sql ( " SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects . shixuns_count , subjects . excellent , sum ( shixuns . myshixuns_count ) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns . subject_id = subjects . id join shixuns on shixuns . id = stage_shixuns . shixun_id #{laboratory_join} where
subjects . hidden = 0 AND subjects . status = 2 AND subjects . name like '%#{search}%'
AND subjects . repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject . find_by_sql ( " SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects . shixuns_count , subjects . excellent , sum ( shixuns . myshixuns_count ) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns . subject_id = subjects . id join shixuns on shixuns . id = stage_shixuns . shixun_id #{laboratory_join} where
subjects . hidden = 0 AND subjects . status = 2 AND subjects . name like '%#{search}%'
GROUP BY subjects . id ORDER BY myshixun_member_count DESC " )
end
else
# 我的路径
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 = Subject . where ( id : total_subject_id )
elsif reorder == " publish_time "
@subjects = Subject . unhidden
else
@subjects = Subject . visible . unhidden
end
# 云上实验室过滤
unless current_laboratory . main_site?
@subjects = @subjects . joins ( :laboratory_subjects ) . where ( laboratory_subjects : { laboratory_id : current_laboratory . id } )
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 " ? " status = 2 desc, publish_time asc " : " 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
end
def show
@user = current_user
@is_creator = current_user . creator_of_subject? ( @subject )
@is_manager = @user . manager_of_subject? ( @subject )
# 合作团队
@shixuns = @subject . shixuns . published . pluck ( :id )
@courses = @subject . courses if @subject . excellent
@members = @subject . subject_members . includes ( :user )
# 访问数变更
@subject . increment! ( :visits )
end
def right_banner
@user = current_user
# 合作团队
@members = @subject . subject_members . includes ( :user )
shixuns = @subject . shixuns . published . pluck ( :id )
challenge_ids = Challenge . where ( shixun_id : shixuns ) . pluck ( :id )
# 实训路径中的所有实训标签
@tags = ChallengeTag . where ( challenge_id : challenge_ids ) . pluck ( :name ) . uniq
# 用户获取的实训标签
# @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq
# 用户进展
user_subject_progress ( challenge_ids )
end
def new
normal_status ( " " )
end
def create
ActiveRecord :: Base . transaction do
begin
@subject = Subject . new ( subject_params )
@subject . user_id = current_user . id
@subject . save!
@subject . subject_members . create! ( role : 1 , user_id : current_user . id )
# 将实践课程标记为该云上实验室建立
Laboratory . current . laboratory_subjects . create! ( subject : @subject , ownership : true )
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( " 实训路径创建失败 " )
raise ActiveRecord :: Rollback
end
end
end
def edit
end
def update
begin
@subject . update_attributes ( subject_params )
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( " 实训路径更新失败 " )
raise ActiveRecord :: Rollback
end
end
def destroy
ActiveRecord :: Base . transaction do
begin
ApplyAction . where ( container_type : " ApplySubject " , container_id : @subject . id ) . destroy_all
@subject . destroy
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( " 实训路径删除失败 " )
raise ActiveRecord :: Rollback
end
end
end
def choose_subject_shixun
@search = params [ :search ] . strip if params [ :search ]
@type = params [ :type ]
# 超级管理员用户显示所有未隐藏的实训、非管理员显示合作团队用户的实训(对本单位公开且未隐藏)
if current_user . admin?
@shixuns = Shixun . select ( [ :id , :name , :status , :myshixuns_count , :identifier , :averge_star ] ) . where ( hidden : 0 )
else
none_shixun_ids = ShixunSchool . where ( " school_id != #{ current_user . user_extension . try ( :school_id ) . to_i } " ) . pluck ( :shixun_id )
@shixuns = Shixun . select ( [ :id , :name , :status , :myshixuns_count , :identifier , :averge_star ] ) . where . not ( id : none_shixun_ids ) . where ( hidden : 0 )
end
# 实训课程的所有标签
tag_ids = @shixuns . joins ( :shixun_tag_repertoires ) . pluck ( :tag_repertoire_id ) . uniq
@tags = TagRepertoire . select ( [ :id , :name ] ) . where ( id : tag_ids )
unless params [ :search ] . blank?
@shixuns = @shixuns . joins ( :user ) . where ( " shixuns.name like ? or concat(users.lastname, users.firstname) like ? " ,
" % #{ @search } % " , " % #{ @search } % " ) . distinct
end
unless @type . nil? || @type == " " || @type == " all "
shixun_ids = ShixunTagRepertoire . where ( tag_repertoire_id : @type ) . pluck ( :shixun_id ) . uniq
@shixuns = @shixuns . where ( id : shixun_ids )
end
@shixuns = @shixuns . reorder ( " created_at desc " )
@shixuns_count = @shixuns . size
## 分页参数
page = params [ :page ] || 1
@shixuns = @shixuns . page ( page ) . per ( 10 )
@shixuns = @shixuns . includes ( :myshixuns )
end
def append_to_stage
@shixuns = Shixun . where ( id : params [ :shixun_id ] ) . order ( " id desc " )
end
def choose_course
course_ids = Course . find_by_sql ( " SELECT c.id FROM courses c, course_members m
WHERE m . course_id = c . id AND m . role in ( 1 , 2 , 3 )
AND m . user_id = #{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
@courses = Course . where ( id : course_ids )
@none_shixun_ids = ShixunSchool . where ( " school_id != #{ current_user . user_extension . try ( :school_id ) . to_i } " ) . pluck ( :shixun_id )
end
def send_to_course
@course = Course . find_by! ( id : params [ :course_id ] )
stages = @subject . stages . where ( id : @subject . stage_shixuns . where ( shixun_id : params [ :shixun_ids ] ) . pluck ( :stage_id ) )
course_module = @course . course_modules . where ( module_type : " shixun_homework " ) . first
homework_ids = [ ]
ActiveRecord :: Base . transaction do
# 将实训课程下的所有已发布实训按顺序发送到课堂,同时创建与章节同名的实训作业目录
stages . each do | stage |
category = CourseSecondCategory . where ( name : stage . name , course_id : @course . id , category_type : " shixun_homework " ) . first ||
CourseSecondCategory . create! ( name : stage . name , course_id : @course . id , category_type : " shixun_homework " ,
course_module_id : course_module . id , position : course_module . course_second_categories . count + 1 )
stage . shixuns . where ( id : params [ :shixun_ids ] , status : 2 ) . each do | shixun |
homework = HomeworksService . new . create_homework shixun , @course , category , current_user
homework_ids << homework . id
end
end
end
homework_ids . each do | homework_id |
CreateStudentWorkJob . perform_later ( homework_id )
end
end
def publish
apply = ApplyAction . where ( container_type : " ApplySubject " , container_id : @subject . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
@status = 0
else
@subject . update_attributes ( status : 1 )
ApplyAction . create ( container_type : " ApplySubject " , container_id : @subject . id , user_id : current_user . id , status : 0 )
begin
status = Educoder :: Sms . send ( mobile : '18711011226' , send_type : 'publish_subject' , name : '管理员' )
rescue = > e
uid_logger_error ( " 发送验证码出错: #{ e } " )
end
@status = 1
end
end
def cancel_publish
begin
apply = ApplyAction . where ( container_type : " ApplySubject " , container_id : @subject . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
apply . update_attributes ( status : 3 )
apply . tidings . destroy_all
end
@subject . update_attributes ( status : 0 )
rescue = > e
uid_logger_error ( e . message )
tip_exception ( " 撤销申请失败 " )
raise ActiveRecord :: Rollback
end
end
def cancel_has_publish
begin
@subject . update_attributes ( :status = > 0 )
rescue = > e
uid_logger_error ( e . message )
tip_exception ( " 撤销发布失败 " )
raise ActiveRecord :: Rollback
end
end
def update_team_title
tip_exception ( " team_title参数不能为空 " ) if params [ :team_title ] . blank?
@subject . update_attributes! ( team_title : params [ :team_title ] )
normal_status ( " 更新成功 " )
end
def search_members
tip_exception ( " 搜索内容不能为空 " ) unless params [ :search ]
page = params [ :page ] || 1
member_ids = @subject . subject_members . map ( & :user_id ) . join ( ',' )
condition = " % #{ params [ :search ] . strip } % " . gsub ( " " , " " )
@users = User . where ( " id not in (?) and status = 1 and LOWER(concat(lastname, ifnull(firstname, ''), login)) LIKE ? " , member_ids , " #{ condition } " )
@users = @users . page ( page ) . per ( 10 )
@users = @users . includes ( :user_extension )
end
def add_subject_members
# tip_exception(403, "没权限操作") if !current_user.admin?
tip_exception ( " user_ids 不能为空! " ) if params [ :user_ids ] . blank?
memberships = params [ :user_ids ]
memberships . each do | member |
if SubjectMember . where ( user_id : member , subject_id : @subject . id ) . count == 0
user = User . find_by! ( id : member )
SubjectMember . create! ( user_id : member , subject_id : @subject . id , role : 2 , position : @subject . subject_members . size + 1 ) if user . present?
end
end
end
# 删除实训
# DELETE: /api/subejcts/:id/delete_member
def delete_member
tip_exception ( 403 , " 没权限操作 " ) unless current_user . manager_of_subject? ( @subject )
tip_exception ( '用户id不能为空' ) if params [ :user_id ] . blank?
user = @subject . subject_members . where ( :user_id = > params [ :user_id ] , :role = > 2 ) . first
tip_exception ( " 管理员用户不允许删除,或用户不存在 " ) if user . blank?
ActiveRecord :: Base . transaction do
begin
@subject . subject_members . where ( " position > #{ user . position } " ) . update_all ( " position = position - 1 " )
user . destroy
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( e . message )
raise ActiveRecord :: Rollback
end
end
end
# 合作者上移
def up_member_position
tip_exception ( '用户id不能为空' ) if params [ :user_id ] . blank?
ActiveRecord :: Base . transaction do
begin
member = @subject . subject_members . where ( user_id : params [ :user_id ] ) . first
# position为1时不能再往上移
tip_exception ( '不能再上移了' ) if member . position == 1
up_member = @subject . subject_members . where ( position : member . position - 1 ) . first
up_member . update_attribute ( :position , member . position )
member . update_attribute ( :position , member . position - 1 )
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( e . message )
raise ActiveRecord :: Rollback
end
end
end
# 合作者下移
def down_member_position
tip_exception ( '用户id不能为空' ) if params [ :user_id ] . blank?
ActiveRecord :: Base . transaction do
begin
member = @subject . subject_members . where ( user_id : params [ :user_id ] ) . first
# position已经是最大值时不能再往下移
tip_exception ( '不能再下移了' ) if member . position == @subject . subject_members . size
down_member = @subject . subject_members . where ( :position = > member . position + 1 ) . first
down_member . update_attribute ( :position , member . position )
member . update_attribute ( :position , member . position + 1 )
rescue Exception = > e
uid_logger_error ( e . message )
tip_exception ( e . message )
raise ActiveRecord :: Rollback
end
end
end
def statistics
@learn_count = @subject . member_count
shixun_ids = @subject . stage_shixuns . pluck ( :shixun_id )
# 受用课堂(已经发布的实训(在此路径中的实训)作业的个数)
homework_common_id = HomeworkCommonsShixun . where ( shixun_id : shixun_ids ) . pluck ( :homework_common_id ) . uniq
homework_common_id = homework_common_id . blank? ? - 1 : homework_common_id . join ( " , " )
courses = Course . find_by_sql ( " select c.id, c.school_id from courses c right join homework_commons hc on c.id = hc.course_id where c.is_delete = 0
and c . school_id is not null and hc . publish_time < '#{Time.now}' and hc . id in ( #{(homework_common_id)})")
course_ids = courses . pluck ( :id ) . uniq
@course_count = course_ids . length
# 受用院校
school_ids = courses . pluck ( :school_id ) . uniq
@schools_count = school_ids . length
# 采用课堂情况
@schools = School . select ( [ :id , :name ] ) . where ( id : school_ids )
@schools =
@schools . map do | s |
school_courses = Course . where ( id : course_ids , school_id : s . id )
course_count = school_courses . count
student_count = CourseMember . where ( course_id : school_courses . pluck ( :id ) , role : 4 ) . count
homework_count = HomeworkCommon . find_by_sql ( " select count(*) cnt from homework_commons hc join courses c on hc.course_id = c.id
where c . school_id = #{s.id} and hc.id in(#{homework_common_id})").first.try(:cnt)
s . attributes . dup . merge ( { name : s . name , course_count : course_count , student_count : student_count , homework_count : homework_count } )
end
@schools = @schools . sort { | x , y | y [ 'homework_count' ] < = > x [ 'homework_count' ] }
@school_total_count = @schools . size
page = params [ :page ] || 1
@schools = @schools [ ( page . to_i - 1 ) * 10 , 10 ]
# TODO: 这个可以异步加载,让页面刷新完成后再加载图形数据
# 章节使用情况
@stage_user_info = [ ]
@sum = 0 #总数
@subject . stages . includes ( :stage_shixuns ) . each do | stage |
shixun_ids = stage . stage_shixuns . pluck ( :shixun_id )
if shixun_ids . present?
homework_common_id = HomeworkCommonsShixun . where ( shixun_id : shixun_ids ) . pluck ( :homework_common_id ) . uniq
if homework_common_id . present?
publish_homework = HomeworkDetailManual . where ( " homework_common_id in(?) and comment_status > 0 " , homework_common_id . join ( " , " ) ) . pluck ( :homework_common_id )
use_count = publish_homework . present? ? HomeworkCommon . find_by_sql ( " select count(*) cnt from homework_commons hc join courses c on hc.course_id = c.id
where hc . id in ( #{publish_homework.join(",")}) and c.school_id is not null").first.try(:cnt) : 0
@sum += use_count
else
@sum += 0
use_count = 0
end
@stage_user_info << use_count
else
@sum += 0
@stage_user_info << 0
end
end
end
def shixun_report
end
def school_report
@schools = School . find_by_sql ( " select count(ms.id) ue_count, s.id, s.name school_name from user_extensions ue,
myshixuns ms , schools s where ue . user_id = ms . user_id and ms . shixun_id in ( select shixun_id from
stage_shixuns where subject_id = '#{@subject.id}' ) and s . id = ue . school_id group by ue . school_id
order by ue_count desc limit 10 " )
end
# 预约报名
def appointment
tip_exception ( " 还存在未结束的课堂 " ) unless @subject . max_course_end_date . nil? || @subject . max_course_end_date < Date . today
tip_exception ( " 无需重复报名 " ) if @subject . subject_appointments . exists? ( user_id : current_user . id )
ActiveRecord :: Base . transaction do
@subject . subject_appointments << SubjectAppointment . new ( user_id : current_user . id )
@subject . increment! ( :participant_count )
if @subject . participant_count == @subject . student_count
@subject . start_course_notify
end
normal_status ( " 预约成功 " )
end
end
private
def subject_params
tip_exception ( " 实训路径名称不能为空 " ) if params [ :name ] . blank?
tip_exception ( " 实训路径简介不能为空 " ) if params [ :description ] . blank?
tip_exception ( " 实训路径学习须知不能为空 " ) if params [ :learning_notes ] . blank?
params . require ( :subject ) . permit ( :name , :description , :learning_notes )
end
def find_subject
@subject = Subject . find_by! ( id : params [ :id ] )
unless @subject . status == 2 || current_user . manager_of_subject? ( @subject )
tip_exception ( " 403 " , " " )
end
end
def allowed
unless current_user . manager_of_subject? ( @subject )
tip_exception ( " 403 " , " " )
end
end
# 用户进展和获取的标签
def user_subject_progress challenge_ids
pass_games = Game . select ( :id , :cost_time , :challenge_id ) . where ( status : 2 , user_id : current_user . id , challenge_id : challenge_ids ) if current_user . logged?
@all_score = Challenge . where ( id : challenge_ids ) . size
# 如果没有通关的,没必要再继续统计了
if pass_games . blank?
@my_score = 0
@learned = 0
@time = 0
@user_tags = [ ]
else
pass_challenge_ids = pass_games . map ( & :challenge_id ) . uniq # 按道理是不用去重的,但是历史数据与重复
# subject_challenge_count = @subject.shixuns.sum(:challenges_count)
# 用户通关获得的标签
@user_tags = ChallengeTag . where ( challenge_id : pass_challenge_ids ) . pluck ( :name )
# 用户学习进度
@learned =
@all_score == 0 ? 0 :
( ( pass_challenge_ids . size . to_f / @all_score ) . round ( 2 ) * 100 ) . to_i
# 用户通关分数
@my_score = Challenge . where ( id : pass_challenge_ids ) . size
@time = pass_games . map ( & :cost_time ) . sum
end
end
end