FIX code review and conflict

This commit is contained in:
jasder 2021-11-14 20:50:22 +08:00
commit 651bf34cfc
277 changed files with 194 additions and 6102 deletions

View File

@ -33,12 +33,13 @@ class Admins::ProjectCategoriesController < Admins::BaseController
end
def update
if @project_category.update_attributes({name: @name, pinned_index: params[:project_category][:pinned_index].to_i}) && save_image_file(params[:logo], 'logo')
if @project_category.update_attributes({name: @name, pinned_index: params[:project_category][:pinned_index].to_i})
save_image_file(params[:logo], 'logo')
redirect_to admins_project_categories_path
flash[:success] = '更新成功'
else
redirect_to admins_project_categories_path
flash[:success] = '更新失败'
flash[:danger] = '更新失败'
end
end

View File

@ -103,7 +103,7 @@ class ApplicationController < ActionController::Base
when 1, 2, 4, 9
# 手机类型的发送
sigle_para = {phone: value}
status = Educoder::Sms.send(mobile: value, code: code)
status = Gitlink::Sms.send(mobile: value, code: code)
tip_exception(-2, code_msg(status)) if status != 0
when 8, 3, 5
# 邮箱类型的发送
@ -184,7 +184,7 @@ class ApplicationController < ActionController::Base
# 异常提醒
def tip_exception(status = -1, message)
raise Educoder::TipException.new(status, message)
raise Gitlink::TipException.new(status, message)
end
def missing_template
@ -193,7 +193,7 @@ class ApplicationController < ActionController::Base
# 弹框提醒
def tip_show_exception(status = -2, message)
raise Educoder::TipException.new(status, message)
raise Gitlink::TipException.new(status, message)
end
def normal_status(status = 0, message)
@ -272,18 +272,18 @@ class ApplicationController < ActionController::Base
# 测试版前端需求
logger.info("subdomain:#{request.subdomain}")
if request.subdomain != "www"
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 81403
elsif params[:debug] == 'student'
User.current = User.find 8686
elsif params[:debug] == 'admin'
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
user = User.find 36480
User.current = user
cookies.signed[:user_id] = user.id
end
end
# if request.subdomain != "www"
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
# User.current = User.find 81403
# elsif params[:debug] == 'student'
# User.current = User.find 8686
# elsif params[:debug] == 'admin'
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
# user = User.find 36480
# User.current = user
# cookies.signed[:user_id] = user.id
# end
# end
# User.current = User.find 81403
end
@ -368,7 +368,7 @@ class ApplicationController < ActionController::Base
JSON.parse(res)
rescue Exception => e
uid_logger_error("--uri_exec: exception #{e.message}")
raise Educoder::TipException.new("实训平台繁忙繁忙等级84")
raise Gitlink::TipException.new("实训平台繁忙繁忙等级84")
end
end
@ -387,7 +387,7 @@ class ApplicationController < ActionController::Base
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Educoder::TipException.new(message)
raise Gitlink::TipException.new(message)
end
end
@ -411,7 +411,7 @@ class ApplicationController < ActionController::Base
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Educoder::TipException.new("服务器繁忙")
raise Gitlink::TipException.new("服务器繁忙")
end
end
@ -583,8 +583,8 @@ class ApplicationController < ActionController::Base
# 获取Oauth Client
def get_client(site)
client_id = Rails.configuration.educoder['client_id']
client_secret = Rails.configuration.educoder['client_secret']
client_id = Rails.configuration.Gitlink['client_id']
client_secret = Rails.configuration.Gitlink['client_secret']
OAuth2::Client.new(client_id, client_secret, site: site)
end

View File

@ -196,7 +196,7 @@ class AttachmentsController < ApplicationController
end
def file_save_to_ucloud(path, file, content_type)
ufile = Educoder::Ufile.new(
ufile = Gitlink::Ufile.new(
ucloud_public_key: edu_setting('public_key'),
ucloud_private_key: edu_setting('private_key'),
ucloud_public_read: true,

View File

@ -20,7 +20,7 @@ module ControllerRescueHandler
end
# rescue_from ActionView::MissingTemplate, with: :object_not_found
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from Educoder::TipException, with: :tip_show
rescue_from Gitlink::TipException, with: :tip_show
rescue_from ::ActionView::MissingTemplate, with: :missing_template
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from ActionController::ParameterMissing, with: :render_parameter_missing

View File

@ -36,10 +36,10 @@ module GitCommon
begin
@commits = GitService.commits(repo_path: @repo_path)
logger.info("git first commit is #{@commits.try(:first)}")
raise Educoder::TipException.new("请先创建版本库") if @commits.nil?
raise Gitlink::TipException.new("请先创建版本库") if @commits.nil?
rescue Exception => e
uid_logger_error(e.message)
raise Educoder::TipException.new("提交记录异常")
raise Gitlink::TipException.new("提交记录异常")
end
end

View File

@ -34,7 +34,7 @@ module GitHelper
rescue Exception => e
Rails.logger.error(e.message)
raise Educoder::TipException.new("文档内容获取异常")
raise Gitlink::TipException.new("文档内容获取异常")
end
end
@ -64,7 +64,7 @@ module GitHelper
# 版本库Fork功能
def project_fork(container, original_rep_path, username)
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
raise Gitlink::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
# 将要生成的仓库名字
new_repo_name = "#{username.try(:strip)}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
# uid_logger("start fork container: repo_name is #{new_repo_name}")

View File

@ -1,5 +0,0 @@
module CourseDecorator
def can_visited?
is_public == 1 || User.current.admin_or_business? || User.current.member_of_course?(self)
end
end

View File

@ -1,2 +0,0 @@
module EcCourseTargetDecorator
end

View File

@ -1,16 +0,0 @@
module ExperienceDecorator
def container_type_text
I18n.t("experience.container_type.#{container_type.to_s.underscore}")
end
def content
case container_type.to_s.underscore
when 'game' then
game = Game.find_by(id: container_id)
game.present? ? "通过实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关获得的奖励" : ''
when 'shixun_publish' then
shixun = Shixun.find_by(id: container_id)
shixun.present? ? "发布实训“#{shixun.name}”获得的奖励" : ''
end
end
end

View File

@ -1,39 +0,0 @@
module GradeDecorator
def container_type_text
I18n.t("grade.container_type.#{container_type.to_s.underscore}")
end
def content
case container_type.to_s.underscore
when 'avatar' then '用户首次上传头像获得的奖励'
when 'phone' then '用户首次绑定手机号码获得的奖励'
when 'mail' then '用户首次绑定邮箱获得的奖励'
when 'attendance' then '用户每天签到获得的奖励'
when 'account' then '新用户首次填写基本资料获得的奖励'
when 'memo' then '发布的评论或者帖子获得平台奖励'
when 'discusses' then '发布的评论获得平台奖励'
when 'star' then '用户给实训评分获得的随机奖励'
when 'feedback' then '反馈的问题获得平台奖励'
when 'authentication' then '用户首次完成实名认证获得的奖励'
when 'professional' then '用户首次完成职业认证获得的奖励'
when 'answer' then
game = Game.find_by(id: container_id)
game.present? ? "查看实训“#{game.challenge.shixun.name}”第#{game.challenge.position}关的参考答案消耗的金币" : ''
when 'game' then
game = Game.find_by(id: container_id)
game.present? ? "通过实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关获得的奖励" : ''
when 'test_set' then
game = Game.find_by(id: container_id)
game.present? ? "查看实训“#{game.challenge.shixun.name}”的第#{game.challenge.position}关的隐藏测试集消耗的金币" : ''
when 'shixun_publish' then
shixun = Shixun.find_by(id: container_id)
shixun.present? ? "发布实训“#{shixun.name}”获得的奖励" : ''
when 'check_ta_answer' then
game = Game.find_by(id: container_id)
game.present? ? "查看实训“#{game.challenge.shixun.name}”第#{game.challenge.position}关的TA人解答消耗的金币" : ''
when 'hack' then
hack = Hack.find_by(id: container_id)
hack.present? ? "完成了题目解答“#{hack.name}”,获得金币奖励:#{hack.score}" : ''
end
end
end

View File

@ -1,5 +0,0 @@
module LibraryDecorator
extend ApplicationDecorator
display_time_method :published_at, :created_at, :updated_at
end

View File

@ -1,5 +0,0 @@
module ShixunDecorator
def human_status
I18n.t("shixun.status.#{status}")
end
end

View File

@ -1,5 +0,0 @@
module SubjectDecorator
def can_visited?
published? || User.current.admin? || member?(User.current)
end
end

View File

@ -1,5 +0,0 @@
module VideoDecorator
extend ApplicationDecorator
display_time_method :published_at, :created_at, :updated_at
end

View File

@ -1,10 +0,0 @@
class AddSchoolApplyForm
include ActiveModel::Model
attr_accessor :name, :province, :city, :address, :remarks
validates :name, presence: true
# validates :province, presence: true
# validates :city, presence: true
# validates :address, presence: true
end

View File

@ -1,27 +0,0 @@
class ApplyShixunMirrorForm
include ActiveModel::Model
attr_accessor :language, :runtime, :run_method, :attachment_id
validates :language, presence: true
validates :runtime, presence: true
validates :run_method, presence: true
validates :attachment_id, presence: true, numericality: { only_integer: true }
validate :ensure_attachment_presence
def ensure_attachment_presence
return unless attachment_id
if attachment.blank?
errors.add(:attachment_id, :attachment_not_exist)
end
end
def attachment
@attachment ||= Attachment.find_by_id(attachment_id)
end
def to_json
{ language: language, runtime: runtime, run_method: run_method, attachment_id: attachment_id }.to_json
end
end

View File

@ -1,15 +0,0 @@
class ExaminationBanks::SaveExamForm
include ActiveModel::Model
attr_accessor :discipline_id, :sub_discipline_id, :difficulty, :name, :duration, :tag_discipline_id
validates :discipline_id, presence: true
validates :sub_discipline_id, presence: true
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
validates :name, presence: true, length: { maximum: 60, too_long: "不能超过60个字符" }
validate :validate_duration
def validate_duration
raise '时长应为大于0的整数' if duration.present? && duration.to_i < 1
end
end

View File

@ -1,12 +0,0 @@
class ExaminationIntelligentSettings::SaveExamForm
include ActiveModel::Model
attr_accessor :name, :duration
validates :name, presence: true, length: { maximum: 60 }
validate :validate_duration
def validate_duration
raise '时长应为大于0的整数' if duration.present? && duration.to_i < 1
end
end

View File

@ -1,11 +0,0 @@
class ExaminationIntelligentSettings::SaveExamSettingForm
include ActiveModel::Model
attr_accessor :discipline_id, :sub_discipline_id, :source, :difficulty, :tag_discipline_id, :question_settings
validates :discipline_id, presence: true
validates :sub_discipline_id, presence: true
validates :source, presence: true
validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true }
validates :question_settings, presence: true
end

View File

@ -1,20 +0,0 @@
class Weapps::CreateCourseForm
include ActiveModel::Model
attr_accessor :course
attr_accessor :name, :course_list_name, :credit, :course_module_types, :end_date
validates :name, presence: true
validates :course_list_name, presence: true
validate :course_name_prefix
validate :check_course_modules
def course_name_prefix
raise '课堂名称应以课程名称开头' unless name.index(course_list_name) && name.index(course_list_name) == 0
end
def check_course_modules
raise '请至少添加一个课堂模块' if course_module_types.blank?
end
end

View File

@ -1,15 +0,0 @@
class Weapps::UpdateCourseForm
include ActiveModel::Model
attr_accessor :course
attr_accessor :name, :course_list_name, :credit, :end_date
validates :name, presence: true
validates :course_list_name, presence: true
validate :course_name_prefix
def course_name_prefix
raise '课堂名称应以课程名称开头' unless name.index(course_list_name) && name.index(course_list_name) == 0
end
end

View File

@ -4,7 +4,7 @@ module Admins::ProjectsHelper
owner = project.owner
if owner.is_a?(User)
link_to(project.owner&.real_name, "/users/#{project&.owner&.login}", target: '_blank')
link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank')
elsif owner.is_a?(Organization)
link_to(project.owner&.real_name, "/organize/#{project&.owner&.login}", target: '_blank')
else

View File

@ -1,6 +1,6 @@
# 所有的方法请按首字母的顺序依次列出
module ApplicationHelper
include Educoder::I18n
include Gitlink::I18n
include GitHelper
ONE_MINUTE = 60 * 1000

View File

@ -1,2 +0,0 @@
module BoardsHelper
end

View File

@ -1,10 +0,0 @@
module ChallengesHelper
def match_begin_symbol str
str.gsub(/\A\r/, "\r\r")
end
end

View File

@ -1,2 +0,0 @@
module CourseGroupsHelper
end

View File

@ -1,2 +0,0 @@
module CourseModulesHelper
end

View File

@ -1,2 +0,0 @@
module CourseSecondCategoriesHelper
end

View File

@ -1,2 +0,0 @@
module CourseStagesHelper
end

View File

@ -1,298 +0,0 @@
module CoursesHelper
def member_manager group, teachers
str = ""
members = teachers.select{|teacher| teacher.teacher_course_groups.pluck(:course_group_id).include?(group.id) || teacher.teacher_course_groups.size == 0}
str = members.uniq.size == teachers.size ? "全部教师" : members.map{|member| member.user.real_name}.join("")
str
# teachers.each do |member|
# if member.teacher_course_groups.exists?(course_group_id: group.id) || member.teacher_course_groups.size == 0
# str << member.user.real_name
# end
# end
end
def edit_auth group, teachers
User.current.admin_or_business? ||
teachers.select{|teacher| teacher.user_id == User.current.id &&
(teacher.teacher_course_groups.pluck(:course_group_id).include?(group.id) || teacher.teacher_course_groups.size == 0)}.size > 0
end
# 是否有切换为学生的入口
def switch_student_role is_teacher, course, user
is_teacher && course.course_members.where(user_id: user.id, role: %i(STUDENT)).exists?
end
# 是否有切换为教师的入口
def switch_teacher_role is_student, course, user
is_student && course.course_members.where(user_id: user.id, role: %i(CREATOR PROFESSOR)).exists?
end
# 是否有切换为助教的入口
def switch_assistant_role is_student, course, user
is_student && course.course_members.where(user_id: user.id, role: %i(ASSISTANT_PROFESSOR)).exists?
end
# 课堂结束天数
def course_end_date end_date
if end_date.present?
curr = Time.new
date = ((Date.parse(end_date.to_s) - Date.parse(curr.to_s)).to_i)
date > 0 ? "#{date}天后" : ""
end
end
# 课堂模块的url
def module_url mod, course
return nil if mod.blank? or course.blank?
case mod.module_type
when "announcement"
"/courses/#{course.id}/informs"
when "online_learning"
"/courses/#{course.id}/online_learning"
when "shixun_homework"
"/courses/#{course.id}/shixun_homeworks/#{mod.id}"
when "common_homework"
"/courses/#{course.id}/common_homeworks/#{mod.id}"
when "group_homework"
"/courses/#{course.id}/group_homeworks/#{mod.id}"
when "graduation"
"/courses/#{course.id}/graduation_topics/#{mod.id}"
when "exercise"
"/courses/#{course.id}/exercises/#{mod.id}"
when "poll"
"/courses/#{course.id}/polls/#{mod.id}"
when "attachment"
"/courses/#{course.id}/files/#{mod.id}"
when "board"
course_board = course.course_board
"/courses/#{course.id}/boards/#{course_board.id}"
when "course_group"
"/courses/#{course.id}/course_groups"
when "statistics"
"/courses/#{course.id}/statistics"
when "video"
"/courses/#{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}"
end
end
# 子目录下的任务数
def category_task_count course, category, user
case category.category_type
when "shixun_homework"
get_homework_commons_count(course, 4, category.id)
when "graduation"
if category.name == "毕设选题"
course.graduation_topics_count
else
course.graduation_tasks_count
end
when "attachment"
get_attachment_count(course, category.id)
end
end
# 课堂模块的任务数
def course_task_count(course, module_type)
case module_type
when "shixun_homework"
get_homework_commons_count(course, 4, 0)
when "common_homework"
get_homework_commons_count(course, 1, 0)
when "group_homework"
get_homework_commons_count(course, 3, 0)
when "graduation"
0
when "exercise"
course.exercises_count
when "poll"
course.polls_count
when "attachment"
get_attachment_count(course, 0)
when "board"
course_board = course.course_board
course_board.present? ? course_board.messages.size : 0
when "course_group"
course.course_groups_count
when "announcement"
course.informs.count
when "online_learning"
course.shixuns.count
when "video"
course.course_videos.count + course.live_links.count
end
end
# 当前用户可见的课堂作业type指定作业类型 category_id指定二级目录
def visible_homework course, user, type, category_id=0
if user.teacher_of_course?(course)
homeworks = course.homework_commons.where("homework_type = #{type} and course_second_category_id = #{category_id}")
elsif user.member_of_course?(course)
member = course.course_members.find_by(user_id: user.id, role: 4)
if member.try(:course_group_id).to_i == 0
homeworks = course.homework_commons.where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}'
and unified_setting = 1 and course_second_category_id = #{category_id}")
else
not_homework_ids = course.homework_group_settings.where("course_group_id = #{member.try(:course_group_id)} and
(publish_time > '#{Time.now}' or publish_time is null)").pluck(:homework_common_id)
# not_homework_ids = not_homework_ids.blank? ? "(-1)" : "(" + not_homework_ids.map(&:homework_common_id).join(",") + ")"
homeworks = course.homework_commons.where.not(id: not_homework_ids).where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}'
and course_second_category_id = #{category_id}")
end
else
homeworks = course.homework_commons.where("homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1
and course_second_category_id = #{category_id}")
end
homeworks
end
# 当前用户可见的课堂试卷
def visible_exercise course, user
if user.teacher_of_course?(course)
exercises = course.exercises
elsif user.member_of_course?(course)
member = course.course_members.find_by(user_id: user.id, role: 4)
if member.try(:course_group_id).to_i == 0
exercises = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1")
else
not_exercise_ids = course.exercise_group_settings.where("course_group_id = #{member.try(:course_group_id)} and
(publish_time > '#{Time.now}' or publish_time is null)").pluck(:exercise_id)
exercises = course.exercises.where.not(id: not_exercise_ids).where("publish_time <= '#{Time.now}'")
end
else
exercises = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1")
end
exercises
end
# 当前用户可见的课堂问卷
def visible_poll course, user
if user.teacher_of_course?(course)
polls = course.polls
elsif user.member_of_course?(course)
member = course.course_members.find_by(user_id: user.id, role: 4)
if member.try(:course_group_id).to_i == 0
polls = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1")
else
not_poll_ids = course.poll_group_settings.where("course_group_id = #{member.try(:course_group_id)} and
(publish_time > '#{Time.now}' or publish_time is null)").pluck(:poll_id)
polls = course.polls.where.not(id: not_poll_ids).where("publish_time <= '#{Time.now}'")
end
else
polls = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1")
end
polls
end
# 当前用户可见的课堂资源category_id指定资源的目录
def visible_attachment course, user, category_id=0
result = []
course.attachments.where(course_second_category_id: category_id).each do |attachment|
if attachment.unified_setting
if attachment.is_public == 1 && attachment.is_publish == 1 || user == attachment.author || user.teacher_of_course?(course) || (user.member_of_course?(course) && attachment.is_publish == 1)
result << attachment
end
else
if attachment.is_public == 1 && attachment.is_publish == 1 && !user.member_of_course?(course) || user == attachment.author || user.teacher_of_course?(course)
result << attachment
elsif user.member_of_course?(course) && attachment.is_publish == 1
member = course.course_members.find_by(user_id: user.id, role: 4)
if member.try(:course_group_id).to_i == 0 && attachment.unified_setting
result << attachment
elsif attachment.attachment_group_settings.where("course_group_id = #{member.try(:course_group_id)} and publish_time > '#{Time.now}'").count == 0
result << attachment
end
end
end
end
result
end
# 获取课堂的资源数
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
end
# 获取课堂的作业数
def get_homework_commons_count(course, type, category_id)
category_id == 0 ? HomeworkCommon.where(course_id: course.id, homework_type: type).size :
HomeworkCommon.where(course_id: course.id, homework_type: type, course_second_category_id: category_id).size
end
# 获取课堂的任务数(作业数+试卷数+问卷数)
def get_tasks_count(course)
course.homework_commons_count + course.exercises_count + course.polls_count
end
# 当前用户可见的毕设任务
def visible_graduation_task course, user
if user.teacher_of_course?(course)
tasks = course.graduation_tasks
else
tasks = course.graduation_tasks.where("publish_time <= '#{Time.now}'")
end
tasks
end
# 分班情况
def course_group_info course, user_id
course_group_ids = course.group_course_power(user_id)
course_groups =
if course_group_ids.present?
course.course_groups.where(id: course_group_ids).includes(:course_members)
else
course.course_groups.includes(:course_members)
end
group_info = []
if !course_groups.blank?
course_groups.each do |group|
group_info << {course_group_id: group.id, group_group_name: group.name, count: group.course_members_count}
end
none_group_count = course.students.where(course_group_id: 0).size
group_info << {course_group_id: 0, group_group_name: "未分班", count: none_group_count} if none_group_count > 0 && !course_group_ids.present?
end
return group_info
end
def left_group_info course
group_info = []
if course.course_groups_count > 0
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"}
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}"}
end
end
group_info
end
def last_subject_shixun course, myshixuns
myshixun = myshixuns.sort{|x,y| y[:updated_at] <=> x[:updated_at] }.first
return "" unless myshixun
stage_shixun = course.course_stage_shixuns.where(shixun_id: myshixun.shixun_id).take
progress = stage_shixun&.course_stage&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name
end
end

View File

@ -1,2 +0,0 @@
module DiscussesHelper
end

View File

@ -1,2 +0,0 @@
module EduDatasHelper
end

View File

@ -1,150 +0,0 @@
module GraduationTasksHelper
include CoursesHelper
# 教师评阅
def teacher_comment task, user_id
[{ id: 0 ,name: "未评", count: task.uncomment_count(user_id)}, {id: 1, name: "已评", count: task.comment_count(user_id)}]
end
# 作品状态
def task_status task, user_id
[{id: 0, name: "未提交", count: task.unfinished_count(user_id)},
{id: 1, name: "按时提交", count: task.finished_count(user_id)},
{id: 2, name: "延时提交", count: task.delay_finished_count(user_id)}]
end
# 交叉评阅
def cross_comment task, user_id
if task.cross_comment && task.status >= 3
[{id: 1, name: "只看我的交叉评阅", count: task.graduation_work_comment_assignations.myself(user_id).count}]
else
[]
end
end
def task_curr_status task, course
result = {}
status = []
time = ""
if course.try(:is_end)
status << "已结束"
time = course.end_date.present? ? course.end_date.strftime("%Y-%m-%d") : ""
else
if task.status > 1 && task.allow_late && (task.late_time.nil? || task.late_time > Time.now)
status << "补交中"
end
case task.status
when 0
status << "未发布"
time = task.publish_time.present? ? "将于 #{format_time(task.publish_time)} 发布" : "创建于#{time_from_now(task.created_at)}"
when 1
if task.end_time && task.end_time >= Time.now
status << "提交中"
time = how_much_time(task.end_time)
end
when 2
status << "评阅中"
time = task.comment_time.present? ? how_much_time(task.comment_time) : course.end_date.present? ? how_much_time(course.end_date.end_of_day) : ""
when 3
status << "交叉评阅中"
time = course.end_date.present? ? how_much_time(course.end_date.end_of_day) : ""
end
status << "未开启补交" if (!task.allow_late && task.status != 0) #6.11 -hs 新增status不等于0
# 如果还在补交阶段则显示补交结束时间
if task.status > 1 && task.allow_late && task.late_time && task.late_time > Time.now
time = how_much_time(task.late_time)
end
end
result[:status] = status
result[:time] = time
result
end
# 作品数统计type 1 已提交 0 未提交
def grduationwork_count task, type
works = task.graduation_works
type == 1 ? works.select{|work| work.work_status != 0}.size : works.select{|work| work.work_status == 0}.size
end
# 普通/分组 作业作品状态数组
def graduation_work_status task, user_id, course
status = []
work = task.graduation_works.find_by(user_id: user_id)
work = work || GraduationWork.create(graduation_task_id: task.id, user_id: user_id)
late_time = task.late_time || course.end_date
if course.is_end && work && work.work_status > 0
status << "查看作品"
elsif !course.is_end
if task.publish_time && task.publish_time < Time.now
# 作业未截止时
if task.end_time > Time.now
if task.task_type == 2 && task.base_on_project
if work.project_id.nil? || work.project_id == 0
status << "创建项目"
status << "关联项目"
elsif work.work_status == 0
status << "取消关联"
status << "提交作品"
else
status << "修改作品"
end
else
if work.work_status == 0
status << "提交作品"
else
status << "修改作品"
end
end
# 补交阶段
elsif task.allow_late && (late_time.nil? || late_time > Time.now)
if task.task_type == 2 && task.base_on_project
if work.project_id.nil? || work.project_id == 0
status << "创建项目"
status << "关联项目"
elsif work.work_status == 0
status << "取消关联"
status << "补交作品"
else
status << "补交附件"
status << "查看作品"
end
else
if work.work_status == 0
status << "补交作品"
else
status << "补交附件"
status << "查看作品"
end
end
# 匿评阶段
elsif work.work_status != 0
status << "查看作品"
end
end
end
end
# 阶段剩余时间
def task_left_time task
if task.publish_time && task.publish_time < Time.now
if task.end_time > Time.now
status = "剩余提交时间"
time = "#{how_much_time(task.end_time)}"
else
if task.allow_late && task.late_time && task.late_time >= Time.now
status = "剩余补交时间"
time = "#{how_much_time(task.late_time)}"
end
end
end
{status: status, time: time}
end
end

View File

@ -1,30 +0,0 @@
module GraduationTopicsHelper
# 课题类型
def topic_type
[{id: 1, name: "设计"}, {id: 2, name: "论文"}, {id: 3, name: "创作"}]
end
# 课程来源
def topic_source
[{id: 1, name: "生产/社会实际"}, {id: 2, name:"结合科研"}, {id: 3, name: "其它"}]
end
# 课题性质1
def topic_property_first
[{id: 1, name: "真题"}, {id: 2, name:"模拟题"}]
end
# 课题性质2
def topic_property_second
[{id: 1, name: "纵向课题"}, {id: 2, name:"横向课题"}, {id: 3, name: "自选"}]
end
# 课题重复
def topic_repeat
[{id: 1, name: "新题"}, {id: 2, name:"往届题,有新要求"}, {id: 3, name: "往届题,无新要求"}]
end
end

View File

@ -1,20 +0,0 @@
module GraduationWorksHelper
include GraduationTasksHelper
# 作品最终成绩
# 参数: work作品 current_user用户course_identity用户在课堂的身份
def work_final_score work, current_user, course_identity
work_score =
if work.work_score.nil?
"--"
else
if work.check_score_power? current_user, course_identity
format("%.1f", work.work_score < 0 ? 0 : work.work_score.round(1))
else
"**"
end
end
# work_score 最终成绩; late_penalty 迟交扣分; final_score 最终评分
{username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.final_score}
end
end

View File

@ -1,2 +0,0 @@
module HackUserLastestCodesHelper
end

View File

@ -1,2 +0,0 @@
module HacksHelper
end

View File

@ -1,2 +0,0 @@
module TrustieHacksHelper
end

View File

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

View File

@ -1,20 +0,0 @@
class Admins::ImportCourseMemberExcel < BaseImportXlsx
Data = Struct.new(:student_id, :name, :course_id, :role, :course_group_name, :school_id)
def read_each(&block)
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
data = row.map(&method(:cell_value))[0..5]
block.call Data.new(*data)
end
end
private
def check_sheet_valid!
raise_import_error('请按照模板格式导入') if sheet.row(1).size != 6
end
def cell_value(obj)
obj&.cell_value&.to_s&.strip
end
end

View File

@ -1,23 +0,0 @@
# 批量发布视频 消息任务
class BatchPublishVideoNotifyJob < ApplicationJob
queue_as :notify
def perform(user_id, video_ids)
user = User.find_by(id: user_id)
return if user.blank?
attrs = %i[user_id trigger_user_id container_id container_type tiding_type status created_at updated_at]
same_attrs = {
user_id: 1,
trigger_user_id: user.id,
container_type: 'Video',
tiding_type: 'Apply', status: 0
}
Tiding.bulk_insert(*attrs) do |worker|
user.videos.where(id: video_ids).each do |video|
worker.add same_attrs.merge(container_id: video.id)
end
end
end
end

View File

@ -1,67 +0,0 @@
# 学生加入课堂时创建相关任务作品
class CourseAddStudentCreateWorksJob < ApplicationJob
queue_as :default
def perform(course_id, student_ids)
course = Course.find_by(id: course_id)
return if course.blank?
# 如果之前存在相关作品则更新is_delete字段
student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id})
student_works.update_all(is_delete: 0)
exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id})
exercise_users.update_all(is_delete: 0)
poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id})
poll_users.update_all(is_delete: 0)
graduation_works = course.graduation_works.where(user_id: student_ids)
graduation_works.update_all(is_delete: 0)
attrs = %i[homework_common_id user_id created_at updated_at]
StudentWork.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.homework_commons.where(homework_type: %i[normal group practice]).each do |homework|
next if StudentWork.where(user_id: user_id, homework_common_id: homework.id).any?
worker.add same_attrs.merge(homework_common_id: homework.id)
end
end
end
attrs = %i[exercise_id user_id created_at updated_at]
ExerciseUser.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.exercises.each do |exercise|
next if ExerciseUser.where(user_id: user_id, exercise_id: exercise.id).any?
worker.add same_attrs.merge(exercise_id: exercise.id)
end
end
end
attrs = %i[poll_id user_id created_at updated_at]
PollUser.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.polls.each do |poll|
next if PollUser.where(user_id: user_id, poll_id: poll.id).any?
worker.add same_attrs.merge(poll_id: poll.id)
end
end
end
attrs = %i[graduation_task_id user_id course_id created_at updated_at]
GraduationWork.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id, course_id: course.id}
course.graduation_tasks.each do |task|
next if GraduationWork.where(user_id: user_id, graduation_task_id: task.id).any?
worker.add same_attrs.merge(graduation_task_id: task.id)
end
end
end
end
end

View File

@ -1,19 +0,0 @@
class CourseDeleteStudentDeleteWorksJob < ApplicationJob
queue_as :default
def perform(course_id, student_ids)
course = Course.find_by(id: course_id)
return if course.blank?
student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id})
student_works.update_all(is_delete: 1)
exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id})
exercise_users.update_all(is_delete: 1)
poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id})
poll_users.update_all(is_delete: 1)
course.graduation_works.where(user_id: student_ids).update_all(is_delete: 1)
end
end

View File

@ -1,22 +0,0 @@
# 删除课堂用户
class CourseDeleteStudentNotifyJob < ApplicationJob
queue_as :notify
def perform(course_id, student_ids, trigger_user_id)
course = Course.find_by(id: course_id)
return if course.blank?
attrs = %i[user_id trigger_user_id container_id container_type belong_container_id
belong_container_type tiding_type created_at updated_at]
same_attrs = {
trigger_user_id: trigger_user_id, container_id: course.id, container_type: 'DeleteCourseMember',
belong_container_id: course.id, belong_container_type: 'Course', tiding_type: 'System'
}
Tiding.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

View File

@ -1,12 +0,0 @@
class CreateDiffRecordJob < ApplicationJob
queue_as :default
def perform(user_id, obj_id, obj_klass, column_name, before, after)
user = User.find_by(id: user_id)
obj = obj_klass.constantize.find_by(id: obj_id)
return if user.blank? || obj.blank?
CreateDiffRecordService.call(user, obj, column_name, before, after)
end
end

View File

@ -1,21 +0,0 @@
# 删除部门 消息通知
class DeleteDepartmentNotifyJob < ApplicationJob
queue_as :notify
def perform(department_id, operator_id, user_ids)
department = Department.unscoped.find_by(id: department_id)
return if department.blank? || user_ids.blank?
attrs = %i[ user_id trigger_user_id container_id container_type tiding_type status created_at updated_at]
same_attrs = {
trigger_user_id: operator_id, container_id: department.id, container_type: 'Department',
status: 4, tiding_type: 'System'
}
Tiding.bulk_insert(*attrs) do |worker|
user_ids.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

View File

@ -1,44 +0,0 @@
# 试卷发布 消息通知
class ExercisePublishNotifyJob < ApplicationJob
queue_as :notify
def perform(exercise_id, group_ids)
exercise = Exercise.find_by(id: exercise_id)
return if exercise.blank?
user = exercise.user
course = exercise.course
if group_ids.present?
students = course.students.where(course_group_id: group_ids)
subquery = course.teacher_course_groups.where(course_group_id: group_ids).select(:course_member_id)
teachers = course.teachers.where(id: subquery)
else
students = course.students
teachers = course.teachers
end
attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type
belong_container_id belong_container_type viewed tiding_type created_at updated_at
]
same_attrs = {
trigger_user_id: user.id, container_id: exercise.id, container_type: 'Exercise',
parent_container_id: exercise.id, parent_container_type: 'ExercisePublish',
belong_container_id: exercise.course_id, belong_container_type: 'Course',
viewed: 0, tiding_type: 'Exercise'
}
Tiding.bulk_insert(*attrs) do |worker|
teacher_ids = teachers.pluck(:user_id)
unless exercise.tidings.exists?(parent_container_type: 'ExercisePublish', user_id: teacher_ids)
teacher_ids.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
students.pluck(:user_id).each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

View File

@ -1,17 +0,0 @@
# 获取阿里云视频信息
class GetAliyunVideoInfoJob < ApplicationJob
queue_as :default
def perform(vod_video_id)
video = Video.find_by(uuid: vod_video_id)
return if video.blank? || video.vod_uploading?
result = AliyunVod::Service.get_play_info(video.uuid)
cover_url = result.dig('VideoBase', 'CoverURL')
file_url = (result.dig('PlayInfoList', 'PlayInfo') || []).first&.[]('PlayURL')
video.cover_url = cover_url if cover_url.present? && video.cover_url.blank?
video.file_url = file_url if file_url.present?
video.save!
end
end

View File

@ -1,22 +0,0 @@
# 毕设任务的交叉评阅分配
class GraduationTaskCrossCommentJob < ApplicationJob
queue_as :default
def perform(graduation_task_id)
task = GraduationTask.find_by(id: graduation_task_id)
return if task.blank?
task.graduation_task_group_assignations.includes(:graduation_group, :graduation_work).each do |assignation|
graduation_group = assignation.graduation_group
work = assignation.graduation_work
if graduation_group.present? && work.present?
member_ids = graduation_group.course_members.pluck(:user_id).uniq
member_ids.each do |user_id|
unless work.graduation_work_comment_assignations.exists?(user_id: user_id)
work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(user_id: user_id, graduation_task_id: task.id)
end
end
end
end
end
end

View File

@ -1,28 +0,0 @@
# 任务发布 消息通知
class GraduationTaskPublishNotifyJob < ApplicationJob
queue_as :notify
def perform(graduation_task_id)
task = GraduationTask.find_by(id: graduation_task_id)
return if task.blank?
course = task.course
return if course.blank?
attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type
belong_container_id belong_container_type viewed tiding_type created_at updated_at
]
same_attrs = {
trigger_user_id: task.user_id, container_id: task.id, container_type: 'GraduationTask',
parent_container_id: task.id, parent_container_type: 'TaskPublish',
belong_container_id: task.course_id, belong_container_type: 'Course',
viewed: 0, tiding_type: 'GraduationTask'
}
Tiding.bulk_insert(*attrs) do |worker|
course.course_members.pluck(:user_id).uniq.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end
end

View File

@ -1,33 +0,0 @@
class ResubmitStudentWorkNotifyJob < ApplicationJob
queue_as :notify
def perform(homework_id, student_ids)
homework = HomeworkCommon.find_by(id: homework_id)
return if homework.blank? || student_ids.blank?
course = homework.course
attrs = %i[user_id trigger_user_id container_id container_type parent_container_id parent_container_type
belong_container_id belong_container_type tiding_type viewed created_at updated_at]
same_attrs = {
container_type: 'ResubmitStudentWork', parent_container_id: homework.id, parent_container_type: 'HomeworkCommon',
belong_container_id: course.id, belong_container_type: 'Course', tiding_type: 'HomeworkCommon', viewed: 0
}
Tiding.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
next unless User.exists?(id: user_id)
work = homework.student_works.find_by(user_id: user_id)
next if work.blank?
score_user_ids = work.student_works_scores.where.not(score: nil).where(reviewer_role: [1, 2]).pluck(user_id).uniq
next if score_user_ids.blank?
attrs = same_attrs.merge(trigger_user_id: user_id, container_id: work.id)
score_user_ids.each do |user_id|
worker.add attrs.merge(user_id: user_id)
end
end
end
end
end

View File

@ -36,9 +36,9 @@ class SendTemplateMessageJob < ApplicationJob
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = receivers.where.not(id: operator&.id)
# receivers = receivers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2, operator_id)
when 'IssueChanged'
operator_id, issue_id, change_params = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)
@ -234,9 +234,9 @@ class SendTemplateMessageJob < ApplicationJob
operator = User.find_by_id(operator_id)
pull_request = PullRequest.find_by_id(pull_request_id)
return unless operator.present? && pull_request.present?
receivers = receivers.where.not(id: operator&.id)
# receivers = receivers.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2, operator_id)
when 'PullRequestChanged'
operator_id, pull_request_id, change_params = args[0], args[1], args[2]
operator = User.find_by_id(operator_id)

View File

@ -44,7 +44,7 @@ class Laboratory < ApplicationRecord
def site
rails_env = EduSetting.get('rails_env')
suffix = rails_env && rails_env != 'production' ? ".#{rails_env}.trustie.net" : '.trustie.net'
suffix = rails_env && rails_env != 'production' ? ".#{rails_env}.gitlink.org.cn" : '.gitlink.org.cn'
identifier ? "#{identifier}#{suffix}" : ''
end
@ -74,74 +74,6 @@ class Laboratory < ApplicationRecord
RequestStore.store[:current_laboratory] ||= User.anonymous
end
def shixuns
if main_site?
not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{Laboratory.current.id}")
Shixun.where.not(id: not_shixun_ids.pluck(:shixun_id))
elsif sync_shixun
laboratory_shixun_ids = laboratory_shixuns.pluck(:shixun_id)
school_shixun_ids = Shixun.joins("join user_extensions on shixuns.user_id=user_extensions.user_id").where(user_extensions: { school_id: school_id }).pluck(:id)
shixun_ids = laboratory_shixun_ids + school_shixun_ids
Shixun.where(id: shixun_ids.uniq)
else
Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id })
end
end
def subjects
if main_site?
not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{Laboratory.current.id}")
Subject.where.not(id: not_subject_ids.pluck(:subject_id))
elsif sync_subject
laboratory_subject_ids = laboratory_subjects.pluck(:subject_id)
school_subject_ids = Subject.joins("join user_extensions on subjects.user_id=user_extensions.user_id").where(user_extensions: { school_id: school_id }).pluck(:id)
subject_ids = laboratory_subject_ids + school_subject_ids
Subject.where(id: subject_ids.uniq)
else
Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id })
end
end
def all_courses
main_site? || !sync_course ? courses : courses.or(Course.where(school_id: school_id))
end
def shixun_repertoires
where_sql = ShixunTagRepertoire.where("shixun_tag_repertoires.tag_repertoire_id = tag_repertoires.id")
# 云上实验室过滤
unless main_site?
where_sql = where_sql.joins("JOIN laboratory_shixuns ls ON ls.shixun_id = shixun_tag_repertoires.shixun_id "\
"AND ls.laboratory_id = #{id}")
end
where_sql = where_sql.select('1').to_sql
tags = TagRepertoire.where("EXISTS(#{where_sql})").distinct.includes(sub_repertoire: :repertoire)
tags_map = tags.group_by(&:sub_repertoire)
sub_reps_map = tags_map.keys.group_by(&:repertoire)
sub_reps_map.keys.sort_by(&:updated_at).reverse.map do |repertoire|
repertoire_hash = repertoire.as_json(only: %i[id name])
repertoire_hash[:sub_repertoires] =
sub_reps_map[repertoire].sort_by(&:updated_at).reverse.map do |sub_repertoire|
sub_repertoire_hash = sub_repertoire.as_json(only: %i[id name])
sub_repertoire_hash[:tags] = tags_map[sub_repertoire].sort_by(&:updated_at).reverse.map { |tag| tag.as_json(only: %i[id name]) }
sub_repertoire_hash
end
repertoire_hash
end
end
def subject_repertoires
exist_sql = Subject.where('subjects.repertoire_id = repertoires.id')
unless main_site?
exist_sql = exist_sql.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id })
end
Repertoire.where("EXISTS(#{exist_sql.select('1').to_sql})").order(updated_at: :desc).distinct
end
# 是否为主站
def main_site?
id == 1

View File

@ -17,55 +17,55 @@ class MessageTemplate < ApplicationRecord
def self.build_init_data
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个易修')
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个易修')
self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在易修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
email_html = File.read("#{email_template_html_dir}/issue_changed.html")
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: '易修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: 'GitLink: 易修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
email_html = File.read("#{email_template_html_dir}/issue_deleted.html")
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', email: email_html, email_title: '易修 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', email: email_html, email_title: 'GitLink: 易修 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论易修{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '')
email_html = File.read("#{email_template_html_dir}/organization_joined.html")
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: '你已加入 {organization} 组织')
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_left.html")
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: '你已被移出 {organization} 组织')
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_role.html")
self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '')
self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_issue.html")
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 新建了一个易修')
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 新建了一个易修')
email_html = File.read("#{email_template_html_dir}/project_joined.html")
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '你已加入 {repository} 项目')
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: 你已加入 {repository} 项目')
email_html = File.read("#{email_template_html_dir}/project_left.html")
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: '你已被移出 {repository} 项目')
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {repository} 项目')
email_html = File.read("#{email_template_html_dir}/project_member_joined.html")
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已加入项目 {nickname2}/{repository}')
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已加入项目 {nickname2}/{repository}')
email_html = File.read("#{email_template_html_dir}/project_member_left.html")
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已被移出项目 {nickname2}/{repository}')
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已被移出项目 {nickname2}/{repository}')
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 提交了一个合并请求')
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求')
email_html = File.read("#{email_template_html_dir}/project_role.html")
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
email_html = File.read("#{email_template_html_dir}/project_setting_changed.html")
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: '您管理的仓库 {nickname2}/{repository} 仓库设置已被更改')
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: 'GitLink: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改')
self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases')
email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html")
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求')
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求')
self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_changed.html")
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_closed.html")
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '')
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: '合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
end
def self.sys_notice

View File

@ -188,6 +188,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
end
def self.get_email_message_content(receiver, operator, issue, change_params)
return '', '', '' if change_params.blank?
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::IssueChanged"]
end

View File

@ -100,6 +100,7 @@ class MessageTemplate::PullRequestChanged < MessageTemplate
end
def self.get_email_message_content(receiver, operator, pull_request, change_params)
return '', '', '' if change_params.blank?
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["CreateOrAssign::PullRequestChanged"]
end

View File

@ -105,7 +105,7 @@ class Token < ActiveRecord::Base
end
def self.generate_token_value
Educoder::Utils.random_hex(20)
Gitlink::Utils.random_hex(20)
end
def self.delete_user_all_tokens(user)

View File

@ -703,7 +703,7 @@ class User < Owner
end
def self.generate_salt
Educoder::Utils.random_hex(16)
Gitlink::Utils.random_hex(16)
end
# 全部已认证

View File

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

View File

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

View File

@ -1,25 +0,0 @@
class Admins::DepartmentApplyQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
status = params[:status]
applies = ApplyAddDepartment.where(status: status) if status.present?
# 关键字模糊查询
keyword = params[:keyword].to_s.strip
if keyword.present?
applies = applies.where('name LIKE :keyword', keyword: "%#{keyword}%")
end
custom_sort(applies, params[:sort_by], params[:sort_direction])
end
end

View File

@ -1,32 +0,0 @@
class Admins::DepartmentQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
departments = Department.where(is_auth: true).without_deleted
keyword = params[:keyword].to_s.strip
if keyword.present?
departments = departments.joins(:school)
.where('schools.name LIKE :keyword OR departments.name LIKE :keyword', keyword: "%#{keyword}%")
end
if params[:with_member].to_s == 'true'
subquery = DepartmentMember.where('department_id = departments.id').select('1 AS one').to_sql
departments = departments.where("EXISTS(#{subquery})")
end
if params[:with_identifier].to_s == 'true'
departments = departments.where.not(identifier: nil).where.not(identifier: '')
end
custom_sort(departments, params[:sort_by], params[:sort_direction])
end
end

View File

@ -1,36 +0,0 @@
class Admins::LaboratoryShixunQuery < ApplicationQuery
attr_reader :laboratory, :params
def initialize(laboratory, params)
@laboratory = laboratory
@params = params
end
def call
laboratory_shixuns = laboratory.laboratory_shixuns.joins(:shixun)
keyword = params[:keyword].to_s.strip
if keyword.present?
like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword OR users.nickname LIKE :keyword'
laboratory_shixuns = laboratory_shixuns.joins(shixun: :user).where(like_sql, keyword: "%#{keyword}%")
end
# 实训状态
laboratory_shixuns = laboratory_shixuns.where(shixuns: { status: params[:status] }) if params[:status].present?
# 技术平台
if params[:tag_id].present?
laboratory_shixuns = laboratory_shixuns.joins(shixun: :shixun_mirror_repositories)
.where(shixun_mirror_repositories: { mirror_repository_id: params[:tag_id] })
end
# 首页展示、单位自建
%i[homepage ownership].each do |column|
if params[column].present? && params[column].to_s == 'true'
laboratory_shixuns = laboratory_shixuns.where(column => true)
end
end
laboratory_shixuns
end
end

View File

@ -1,23 +0,0 @@
class Admins::SchoolQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :users_count, :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
schools = School.all
keyword = strip_param(:keyword)
Rails.logger.info("###########{keyword}")
if keyword
schools = schools.where('schools.name LIKE ?', "%#{keyword}%")
end
schools = schools.left_joins(:user_extensions).select('schools.*, IFNULL(count(user_extensions.user_id),0) users_count').group('schools.id')
custom_sort schools, params[:sort_by], params[:sort_direction]
end
end

View File

@ -1,49 +0,0 @@
class Admins::SubjectQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc, default_table: 'subjects'
def initialize(params)
@params = params
end
def call
subjects = Subject.all
subjects = subjects.where(id: params[:id]) if params[:id].present?
# 状态过滤
status =
case params[:status].to_s.strip
when "editing" then {status: 0}
when "applying" then {status: 2, public: [0, 1]}
when "pending" then {public: 1}
when "published" then {public: 2}
end
subjects = subjects.where(status) if status
# 创建者单位
if params[:school_id].present?
subjects = subjects.joins(user: :user_extension).where(user_extensions: { school_id: params[:school_id] })
end
# 首页展示、金课
%i[homepage_show excellent].each do |column|
if params[column].present? && params[column].to_s == 'true'
subjects = subjects.where(column => true)
end
end
# 关键字
keyword = params[:keyword].to_s.strip
if keyword
sql = 'CONCAT(lastname, firstname) LIKE :keyword OR users.nickname LIKE :keyword OR subjects.name LIKE :keyword'
subjects = subjects.joins(:user).where(sql, keyword: "%#{keyword}%")
end
custom_sort(subjects, params[:sort_by], params[:sort_direction])
end
end

View File

@ -1,28 +0,0 @@
class Users::VideoQuery < ApplicationQuery
include CustomSortable
sort_columns :published_at, :title, default_by: :published_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
videos = user.videos
videos =
case params[:status]
when 'published' then videos.published
when 'processing' then videos.processing
else videos.published
end
keyword = params[:keyword].to_s.strip
videos = videos.where('title LIKE ?', "%#{keyword}%") if keyword.present?
custom_sort(videos, params[:sort_by], params[:sort_direction])
end
end

View File

@ -1,37 +0,0 @@
class Weapps::SearchQuery < ApplicationQuery
include ElasticsearchAble
attr_reader :params
def initialize(params)
@params = params
end
def call
modal_name.search(keyword, search_options)
end
private
def search_options
hash = {
fields: [:name],
page: page,
per_page: per_page
}
hash.merge(where: { status: 2 }) if modal_name == Shixun
hash
end
def modal_name
@_modal_name ||= begin
case params[:type].to_s
when 'subject' then Subject
when 'shixun' then Shixun
when 'course' then Course
else Subject
end
end
end
end

View File

@ -1,37 +0,0 @@
class Weapps::SubjectQuery < ApplicationQuery
include CustomSortable
attr_reader :params
def initialize(current_laboratory, params)
@current_laboratory = current_laboratory
@params = params
end
def call
subjects = @current_laboratory.subjects.unhidden.publiced.show_moblied
# 课程体系的过滤
if params[:sub_discipline_id].present?
subjects = subjects.joins(:sub_disciplines).where(sub_disciplines: {id: params[:sub_discipline_id]})
elsif params[:discipline_id].present?
subjects = subjects.joins(:sub_disciplines).where(sub_disciplines: {discipline_id: params[:discipline_id]})
else
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')
.group('subjects.id').order("subjects.homepage_show #{sort_type}, #{order_type} #{sort_type}")
subjects
end
private
def order_type
Subject.column_names.include?(params[:order]) ? params[:order] : 'updated_at'
end
def sort_type
%w(desc asc).include?(params[:sort]) ? params[:sort] : "desc"
end
end

View File

@ -1,20 +0,0 @@
class Admins::AddDepartmentMemberService < ApplicationService
attr_reader :department, :params
def initialize(department, params)
@department = department
@params = params
end
def call
columns = %i[]
DepartmentMember.bulk_insert(*columns) do |worker|
Array.wrap(params[:user_ids]).compact.each do |user_id|
next if department.department_members.exists?(user_id: user_id)
worker.add(department_id: department.id, user_id: user_id)
end
end
end
end

View File

@ -1,89 +0,0 @@
class Admins::CheckShixunMirrorsService < ApplicationService
Error = Class.new(StandardError)
def call
bridge_images
ActiveRecord::Base.transaction do
check_sync_mirrors!
check_mirrors!
end
end
private
def mirrors
bridge_images['images']
end
def sync_mirrors
bridge_images['imagesNotSync']
end
def check_mirrors!
return if mirrors.blank?
image_names = []
mirrors.each do |data|
mirror = JSON.parse(data)
name_repository = MirrorRepository.find_by(name: mirror['imageName'])
id_repository = MirrorRepository.find_by(mirrorID: mirror['imageID'])
image_names << mirror['imageName']
if name_repository.blank? && id_repository.present? # 镜像名称被修改
id_repository.update_column(:status, 2)
MirrorOperationRecord.create!(mirror_repository_id: id_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 2, user_id: -1)
elsif name_repository.blank? # 镜像不存在、创建镜像
new_repository = MirrorRepository.create!(mirrorID: mirror['imageID'], name: mirror['imageName'])
MirrorOperationRecord.create!(mirror_repository_id: new_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 0, user_id: -1)
elsif name_repository.mirrorID != mirror['imageID'] # 镜像ID被修改
name_repository.update_column(:status, 2)
MirrorOperationRecord.create!(mirror_repository_id: name_repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 1, user_id: -1)
end
end
# 判断中间层镜像是否被删除
MirrorRepository.find_each do |mirror|
next if mirror&.name.blank? || image_names.index(mirror.name)
mirror.update_column(:status, 4)
MirrorOperationRecord.create!(mirror_repository_id: mirror.id, mirror_id: mirror&.mirrorID,
mirror_name: mirror.name, status: 3, user_id: -1)
end
end
def check_sync_mirrors!
return if sync_mirrors.blank?
sync_mirrors.each do |data|
mirror = JSON.parse(data)
repository = MirrorRepository.find_by(name: mirror['imageName'])
next if repository.blank? || repository.status != 1
repository.update_column(:status, 5)
MirrorOperationRecord.create!(mirror_repository_id: repository.id, mirror_id: mirror['imageID'],
mirror_name: mirror['imageName'], status: 4, user_id: -1)
end
end
def bridge_images
@_bridge_images ||= begin
url = "#{EduSetting.get('cloud_bridge')}/bridge/docker/images"
res = Faraday.get(url)
res = JSON.parse(res.body)
raise Error, '拉取镜像信息异常' if res && res['code'] != 0
res
rescue => e
Rails.logger.error("get response failed ! #{e.message}")
raise Error, '实训云平台繁忙繁忙等级84'
end
end
end

View File

@ -1,35 +0,0 @@
class Admins::DragCooperativeService < ApplicationService
Error = Class.new(StandardError)
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
raise Error, '未知错误' if after && move.img_type != after.img_type
coo_imgs = CooImg.where(img_type: move.img_type)
ActiveRecord::Base.transaction do
if after.blank? # 移动至末尾
total = coo_imgs.count
coo_imgs.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
coo_imgs.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
coo_imgs.where('position > ? AND position <= ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position)
end
end
end
end

View File

@ -1,35 +0,0 @@
class Admins::DragPortalImageService < ApplicationService
Error = Class.new(StandardError)
attr_reader :laboratory, :move, :after
def initialize(laboratory, move, after)
@laboratory = laboratory
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
images = laboratory.portal_images
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = images.count
images.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
images.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
images.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@ -1,32 +0,0 @@
class Admins::DragWeappAdvertService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
adverts = WeappSettings::Advert.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = adverts.count
adverts.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
adverts.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
adverts.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@ -1,32 +0,0 @@
class Admins::DragWeappCarouselService < ApplicationService
attr_reader :move, :after
def initialize(move, after)
@move = move
@after = after # 移动后下一个位置的元素
end
def call
return if move.position + 1 == after&.position # 未移动
carousels = WeappSettings::Carousel.all
ActiveRecord::Base.transaction do
if after.blank? || move.id == after.id # 移动至末尾
total = carousels.count
carousels.where('position > ?', move.position).update_all('position = position - 1')
move.update!(position: total)
return
end
if move.position > after.position # 前移
carousels.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1')
move.update!(position: after.position)
else # 后移
carousels.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1')
move.update!(position: after.position - 1)
end
end
end
end

View File

@ -1,63 +0,0 @@
class Admins::ImportCourseMemberService < ApplicationService
Error = Class.new(StandardError)
attr_reader :file, :result
def initialize(file)
@file = file
@result = { success: 0, fail: [] }
end
def call
raise Error, '文件不存在' if file.blank?
excel = Admins::ImportCourseMemberExcel.new(file)
excel.read_each(&method(:create_course_member))
result
rescue ApplicationImport::Error => ex
raise Error, ex.message
end
private
def create_course_member(data)
raise '课堂角色必须为 2、3、4' unless [2, 3, 4].include?(data.role.to_i)
user = User.joins(:user_extension).where(user_extensions: { student_id: data.student_id, school_id: data.school_id }).first
raise '该学号的用户不存在' if user.blank?
course = Course.find_by(id: data.course_id)
raise '该课堂不存在' if course.blank?
course_group = nil
if data.course_group_name.present?
course_group = course.course_groups.find_or_create_by!(name: data.course_group_name)
end
member = course.course_members.find_by(user_id: user.id, role: data.role.to_i)
# 如果已是课堂成员且是学生身份and不在指定的分班则移动到该分班
if member.present? && member.role == 'STUDENT' && course_group && member.course_group_id != course_group&.id.to_i
member.update!(course_group_id: course_group&.id.to_i)
elsif member.blank?
course.course_members.create!(user_id: user.id, role: data.role.to_i, course_group_id: course_group&.id.to_i)
extra =
case data.role.to_i
when 2 then 9
when 3 then 7
else 10
end
Tiding.create!(user_id: user.id, trigger_user_id: course.tea_id, container_id: course.id,
container_type: 'TeacherJoinCourse', belong_container_id: course.id,
belong_container_type: 'Course', tiding_type: 'System', extra: extra)
end
result[:success] += 1
rescue Exception => ex
fail_data = data.as_json
fail_data[:data] = fail_data.values.join(',')
fail_data[:message] = ex.message
result[:fail] << fail_data
end
end

View File

@ -1,123 +0,0 @@
class Admins::SchoolDailyStatisticService < ApplicationService
include CustomSortable
attr_reader :params
sort_columns :student_count, :teacher_count, :homework_count, :other_homework_count,
:course_count, :active_course_count, :nearly_course_time, :shixun_count, :shixun_evaluate_count,
default_by: :teacher_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
schools = School.group('schools.id')
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
schools = schools.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
count = schools.count.count
# 根据排序字段进行查询
schools = query_by_sort_column(schools, params[:sort_by])
schools = custom_sort(schools, params[:sort_by], params[:sort_direction])
schools = schools.limit(page_size).offset(offset)
# 查询并组装其它数据
schools = package_other_data(schools)
[count, schools]
end
def package_other_data(schools)
ids = schools.map(&:id)
student_map = UserExtension.where(school_id: ids, identity: :student).group(:school_id).count
teacher_map = UserExtension.where(school_id: ids, identity: :teacher).group(:school_id).count
homeworks = HomeworkCommon.joins(:course)
shixun_homework_map = homeworks.where(homework_type: 4, courses: { school_id: ids }).group('school_id').count
other_homework_map = homeworks.where(homework_type: [1, 3], courses: { school_id: ids }).group('school_id').count
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')
active_course_map = courses.where(is_end: false).count
shixun_map = Shixun.joins(user: :user_extension).where(user_extensions: { identity: :teacher, school_id: ids })
.where(fork_from: nil).group('school_id').count
reports = SchoolReport.where(school_id: ids)
evaluate_count_map = reports.each_with_object({}) { |report, obj| obj[report.school_id] = report.shixun_evaluate_count }
schools.map do |school|
{
id: school.id,
name: school.name,
teacher_count: teacher_map[school.id],
student_count: student_map[school.id],
homework_count: shixun_homework_map[school.id],
other_homework_count: other_homework_map[school.id],
course_count: course_map[school.id],
nearly_course_time: nearly_course_time_map[school.id],
active_course_count: active_course_map[school.id],
shixun_count: shixun_map.fetch(school.id, 0),
shixun_evaluate_count: evaluate_count_map.fetch(school.id, 0)
}
end
end
private
def query_by_sort_column(schools, sort_by_column)
base_query_column = 'schools.id, schools.name'
case sort_by_column.to_s
when 'teacher_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.select("#{base_query_column}, COUNT(*) teacher_count")
when 'student_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 1')
.select("#{base_query_column}, COUNT(*) student_count")
when 'homework_count' then
schools.joins('LEFT JOIN courses ON courses.school_id = schools.id')
.joins('LEFT JOIN homework_commons hc ON hc.course_id = courses.id AND hc.homework_type = 4')
.select("#{base_query_column}, COUNT(*) homework_count")
when 'other_homework_count' then
schools.joins('LEFT JOIN courses ON courses.school_id = schools.id')
.joins('LEFT JOIN homework_commons hc ON hc.course_id = courses.id AND hc.homework_type IN (1, 3)')
.select("#{base_query_column}, COUNT(*) other_homework_count")
when 'course_count' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0')
.select("#{base_query_column}, COUNT(*) course_count")
when 'shixun_count' then
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.joins('LEFT JOIN users ON users.id = ue.user_id')
.joins('LEFT JOIN shixuns sx ON sx.user_id = users.id AND sx.fork_from IS NULL')
.select("#{base_query_column}, COUNT(*) shixun_count")
when 'shixun_evaluate_count' then
schools.joins('LEFT JOIN school_reports ON school_reports.school_id = schools.id')
.select("#{base_query_column}, shixun_evaluate_count")
when 'nearly_course_time' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0')
.joins('LEFT JOIN course_activities acs ON acs.course_id = cs.id')
.select("#{base_query_column}, MAX(acs.updated_at) nearly_course_time")
when 'active_course_count' then
schools.joins('LEFT JOIN courses cs ON cs.school_id = schools.id AND cs.is_delete = 0 AND cs.is_end = false')
.select("#{base_query_column}, COUNT(*) active_course_count")
else
schools.joins('LEFT JOIN user_extensions ue ON ue.school_id = schools.id AND ue.identity = 0')
.select("#{base_query_column}, COUNT(*) teacher_count")
end
end
def page_size
params[:per_page] || 20
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size
end
end

View File

@ -1,43 +0,0 @@
class Admins::ShixunAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :shixun
def initialize(apply, user)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
shixun.update!(public: 2, publish_time: Time.now)
# 奖励金币、经验
reward_grade_and_experience!
deal_tiding!
end
end
private
def reward_grade_and_experience!
score = shixun.all_score
shixun_creator = shixun.user
RewardGradeService.call(shixun_creator, container_id: shixun.id, container_type: 'shixunPublish', score: score)
Experience.create!(user_id: shixun_creator.id, container_id: shixun.id, container_type: 'shixunPublish', score: score)
shixun_creator.update_column(:experience, shixun_creator.experience.to_i + score)
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 1, tiding_type: 'System')
end
end

View File

@ -1,35 +0,0 @@
class Admins::ShixunAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :shixun, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@shixun = Shixun.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
shixun.update!(public: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Shixun',
status: 2, tiding_type: 'System')
end
end

View File

@ -1,80 +0,0 @@
class Admins::StatisticSchoolContrastDataService < ApplicationService
ParameterError = Class.new(StandardError)
PAGE_SIZE = 20
CONTRAST_COLUMN_LIST = %w(
teacher_increase_count student_increase_count course_increase_count
shixun_increase_count active_user_count shixun_homework_count shixun_evaluate_count
).freeze
attr_reader :params, :sort_direction, :contrast_column
def initialize(params)
@params = params
@sort_direction = params[:sort_direction].to_s
@contrast_column = params[:contrast_column].to_s
end
def call
validate_parameter!
reports = School.joins(:school_daily_reports).select(select_columns)
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
reports = reports.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
count = reports.count('distinct(schools.id)')
sql = query_report_sql(reports.group('schools.id').to_sql)
reports = SchoolDailyReport.find_by_sql(sql)
[count, reports]
end
private
def validate_parameter!
if %i[begin_date end_date other_begin_date other_end_date].any? { |key| params[key].blank? }
raise ParameterError
end
unless %w(desc asc).include?(sort_direction)
raise ParameterError
end
unless CONTRAST_COLUMN_LIST.include?(contrast_column)
raise ParameterError
end
end
def format_date(date)
Time.zone.parse(date).strftime("%Y-%m-%d")
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
end
def select_columns
if contrast_column != 'active_user_count'
"schools.id school_id, schools.name school_name,"\
"(SUM(IF(date BETWEEN '#{format_date(params[:begin_date])}' AND '#{format_date(params[:end_date])}', #{contrast_column}, 0))) total,"\
"(SUM(IF(date BETWEEN '#{format_date(params[:other_begin_date])}' AND '#{format_date(params[:other_end_date])}', #{contrast_column}, 0))) other_total"
else
# 活跃用户对比时处理方法不同
relations = SchoolDailyActiveUser.select('COUNT(distinct user_id)').joins(:school_daily_report)
.where('school_id = schools.id')
total_subquery = relations.where("date BETWEEN '#{format_date(params[:begin_date])}' AND '#{format_date(params[:end_date])}'").to_sql
other_total_subquery = relations.where("date BETWEEN '#{format_date(params[:other_begin_date])}' AND '#{format_date(params[:other_end_date])}'").to_sql
"schools.id school_id, schools.name school_name, (#{total_subquery}) AS total, (#{other_total_subquery}) AS other_total"
end
end
def query_report_sql(from_sql)
order_by = "(total = 0 AND other_total != 0) #{sort_direction}, (percentage != 0) #{sort_direction}, percentage #{sort_direction}"
"SELECT reports.*, (other_total - total) increase, (IF(other_total - total = 0, 0.0, round((other_total - total) / IF(total = 0, 1, total), 5))) percentage "\
"FROM (#{from_sql}) reports ORDER BY #{order_by} LIMIT #{PAGE_SIZE} OFFSET #{offset}"
end
end

View File

@ -1,107 +0,0 @@
class Admins::StatisticSchoolDataGrowService < ApplicationService
include CustomSortable
PAGE_SIZE = 20
attr_reader :params
sort_columns :teacher_increase_count, :student_increase_count,
:course_increase_count, :shixun_increase_count, :uniq_active_user_count,
:shixun_homework_count, :shixun_evaluate_count,
default_by: :teacher_increase_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
reports = School.where(nil)
reports = search_filter(reports)
count = reports.count
subquery = SchoolDailyActiveUser.select('COUNT(distinct(user_id))').joins(:school_daily_report)
.where(date_condition_sql).where("school_id is not null and school_id = schools.id").to_sql
reports = reports.joins("LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id AND #{date_condition_sql}")
reports = reports.select(
'schools.id school_id, schools.name school_name,'\
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(shixun_homework_count) shixun_homework_count,'\
'SUM(shixun_evaluate_count) shixun_evaluate_count,'\
"(#{subquery}) uniq_active_user_count,"\
'SUM(active_user_count) active_user_count').group('schools.id')
reports = custom_sort(reports, params[:sort_by], params[:sort_direction])
reports = reports.order('school_id asc').limit(PAGE_SIZE).offset(offset)
[count, reports]
end
def grow_summary
@_grow_summary ||= begin
reports = School.joins("LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id")
.where(date_condition_sql)
subquery = SchoolDailyActiveUser.select('COUNT(distinct user_id)')
.joins('LEFT JOIN school_daily_reports sdr ON sdr.id = school_daily_active_users.school_daily_report_id')
.where(date_condition_sql).to_sql
reports = search_filter(reports)
reports.select(
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(shixun_homework_count) shixun_homework_count,'\
'SUM(shixun_evaluate_count) shixun_evaluate_count,'\
"(#{subquery}) uniq_active_user_count,"\
'SUM(active_user_count) active_user_count'
).first
end
end
private
def search_filter(relations)
keyword = params[:keyword].try(:to_s).try(:strip)
if keyword.present?
relations = relations.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
end
relations
end
def date_condition_sql
date = query_date
if date.is_a?(Range)
"date BETWEEN '#{date.min.strftime('%Y-%m-%d')}' AND '#{date.max.strftime('%Y-%m-%d')}'"
else
"date = '#{date.strftime('%Y-%m-%d')}'"
end
end
def query_date
if params[:grow_begin_date].present?
begin_time = Time.zone.parse(params[:grow_begin_date])
end_date = if params[:grow_end_date].present?
Time.zone.parse(params[:grow_end_date])
end
end_date.blank? || end_date == begin_time ? begin_time : begin_time..end_date
else
yesterday
end
end
def yesterday
# 每日凌晨5点为节点, 25日凌晨4点、3点、2点等等未到更新数据时间点看到的数据是23日-24日的统计数据
(Time.zone.now - 5.hours).beginning_of_day - 1.days
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
end
end

View File

@ -1,30 +0,0 @@
class Admins::SubjectAuths::AgreeApplyService < ApplicationService
attr_reader :apply, :user, :subject
def initialize(apply, user)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
end
def call
ActiveRecord::Base.transaction do
apply.update!(status: 1, dealer_id: user.id)
subject.update!(public: 2, publish_time: Time.now)
deal_tiding!
end
end
private
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 1, tiding_type: 'System')
end
end

View File

@ -1,35 +0,0 @@
class Admins::SubjectAuths::RefuseApplyService < ApplicationService
attr_reader :apply, :user, :subject, :params
def initialize(apply, user, params)
@apply = apply
@user = user
@subject = Subject.find(apply.container_id)
@params = params
end
def call
ActiveRecord::Base.transaction do
subject.update!(public: 0)
apply.update!(status: 2, reason: reason, dealer_id: user.id)
deal_tiding!
end
end
private
def reason
params[:reason].to_s.strip
end
def deal_tiding!
apply.tidings.where(tiding_type: 'Apply', status: 0).update_all(status: 1)
Tiding.create!(user_id: apply.user_id, trigger_user_id: 0,
container_id: apply.id, container_type: 'ApplyAction',
parent_container_id: apply.container_id, parent_container_type: apply.container_type,
belong_container_id: apply.container_id, belong_container_type: 'Subject',
status: 2, tiding_type: 'System')
end
end

View File

@ -1,2 +0,0 @@
class CoursesService
end

View File

@ -1,44 +0,0 @@
class CreateAddDepartmentApplyService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
name = params[:name].to_s.strip
raise Error, '名称不能为空' if name.blank?
school = School.find_by(id: params[:school_id])
raise Error, '学校/单位不存在' if school.blank?
raise Error, '部门已存在' if school.departments.exists?(name: name)
department = Department.new
department.name = name
department.school = school
ActiveRecord::Base.transaction do
department.save!
attrs = {
user_id: user.id, department: department, school: school,
name: department.name, remarks: params[:remarks], status: 0,
}
apply = ApplyAddDepartment.create!(attrs)
unless user.professional_certification?
user.user_extension.update!(department_id: department.id)
end
# 向管理员发送通知
message = AppliedMessage.new(user_id: 1, status: 0, applied_user_id: user.id, viewed: 0,
applied_id: apply.id, applied_type: 'ApplyAddDepartment', name: department.name)
message.save(validate: false)
end
department
end
end

View File

@ -1,37 +0,0 @@
class CreateAddSchoolApplyService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
AddSchoolApplyForm.new(params).validate!
name = params[:name].to_s.strip
raise Error, '学校/单位已经存在' if name.present? && School.exists?(name: name)
school = School.new
school.name = name
school.province = params[:province].to_s.strip
school.city = params[:city].to_s.strip
school.address = params[:address].to_s.strip
ActiveRecord::Base.transaction do
school.save!
school_attrs = school.as_json(only: %i[name province city address])
ApplyAddSchool.create!(school_attrs.merge(school: school, user_id: user.id, remarks: params[:remarks]))
# 向管理员发送通知
message = AppliedMessage.new(user_id: 1, status: 0, applied_user_id: user.id, viewed: 0,
applied_id: school.id, applied_type: 'ApplyAddSchools', name: school.name)
message.save(validate: false)
end
school
end
end

View File

@ -1,164 +0,0 @@
class DuplicateCourseService < ApplicationService
attr_reader :origin_course, :user, :course
def initialize(origin_course, user)
@user = user
@origin_course = origin_course
end
def call
ActiveRecord::Base.transaction do
@course = copy_course!
copy_course_modules!
join_course!
copy_homework_commons!
copy_exercises!
copy_polls!
copy_attachments!
course
end
end
private
def copy_course!
create_attrs = origin_course.as_json(only: %i[name class_period credit course_list_id])
create_attrs.merge!(tea_id: user.id, school_id: user.school_id, is_public: 0, is_copy: 1)
Course.create!(create_attrs)
end
def copy_course_modules!
@second_category_list = {}
origin_course.course_modules.each do |course_module|
attrs = course_module.as_json(only: %i[module_type position hidden module_name])
new_course_module = CourseModule.create!(attrs.merge(course_id: course.id))
# 复制子目录
course_module.course_second_categories.each do |second_category|
category_attr = second_category.as_json(only: %i[category_type name position])
new_second_category =
CourseSecondCategory.create!(category_attr.merge(course_id: course.id, course_module_id: new_course_module.id))
@second_category_list[second_category.id] = new_second_category.id
end
end
end
def join_course!
CourseMember.create!(course_id: course.id, user_id: user.id, role: 1)
end
def copy_homework_commons!
origin_course.homework_commons.where(homework_type: %i[normal group practice]).find_each do |origin_homework|
homework_attrs = origin_homework.as_json(only: %i[name description homework_type homework_bank_id reference_answer])
course_second_category_id = @second_category_list[origin_homework.course_second_category_id]
homework = HomeworkCommon.create!(homework_attrs.merge(user_id: user.id, course_id: course.id,
course_second_category_id:course_second_category_id))
origin_homework.attachments.find_each do |origin_attachment|
attachment = origin_attachment.copy
attrs = { container: homework, author_id: origin_homework.user_id, copy_from: origin_attachment.id }
attachment.assign_attributes(attrs)
attachment.save!
origin_attachment.increment!(:quotes)
end
homework.create_homework_detail_manual!
if homework.group_homework_type?
attrs = origin_homework.homework_detail_group.as_json(only: %i[min_num max_num base_on_project])
homework.create_homework_detail_group!(attrs)
elsif homework.practice_homework_type?
HomeworkCommonsShixun.create!(homework_common_id: homework.id, shixun_id: origin_homework.homework_commons_shixun.shixun_id)
HomeworksService.new.create_shixun_homework_cha_setting(homework, origin_homework.shixuns.first)
end
origin_homework.increment!(:quotes)
origin_homework.homework_bank.increment!(:quotes) if origin_homework.homework_bank
end
end
def copy_exercises!
origin_course.exercises.find_each do |origin_exercise|
attrs = origin_exercise.as_json(only: %i[exercise_name exercise_description exercise_bank_id])
exercise = course.exercises.create!(attrs.merge(user_id: user.id))
origin_exercise.exercise_questions.find_each do |origin_question|
question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score shixun_name shixun_id is_ordered level])
# question_attrs[:question_type] ||= 1
question = exercise.exercise_questions.create!(question_attrs)
exercise_choice_map = {}
origin_question.exercise_choices.each_with_index do |origin_choice, index|
choice_attrs = { choice_position: index + 1, choice_text: origin_choice.choice_text }
choice = question.exercise_choices.create!(choice_attrs)
# exercise_choice_map[origin_choice.id] = choice.id 标准答案中存的是choice_position, 直接取原题的exercise_choice_id就行
end
origin_question.exercise_standard_answers.find_each do |origin_answer|
question.exercise_standard_answers.create!(
exercise_choice_id: origin_answer.exercise_choice_id,
answer_text: origin_answer.answer_text
)
end
origin_question.exercise_shixun_challenges.each_with_index do |sc, index|
question.exercise_shixun_challenges.create!({position: index+1, challenge_id: sc.challenge_id,
shixun_id: sc.shixun_id, question_score: sc.question_score})
end
end
origin_exercise.exercise_bank.increment!(:quotes) if exercise.exercise_bank
end
end
def copy_polls!
origin_course.polls.includes(poll_questions: :poll_answers).find_each do |origin_poll|
poll_attrs = origin_poll.as_json(only: %i[polls_name polls_description exercise_bank_id])
poll = course.polls.create!(poll_attrs.merge(user_id: user.id))
origin_poll.poll_questions.each do |origin_question|
attr_names = %i[question_title question_type is_necessary question_number max_choices min_choices]
question_attrs = origin_question.as_json(only: attr_names)
question_attrs[:question_type] ||= 1
question = poll.poll_questions.create!(question_attrs)
origin_question.poll_answers.each_with_index do |origin_answer, index|
question.poll_answers.create!(answer_position: index + 1, answer_text: origin_answer.answer_text)
end
end
origin_poll.exercise_bank.increment!(:quotes) if origin_poll.exercise_bank
end
end
def copy_attachments!
origin_course.attachments.each do |origin_attachment|
attachment = origin_attachment.copy
# attachment.tag_list.add(origin_attachment.tag_list) # tag关联
attachment.container = course
attachment.created_on = Time.now
attachment.publish_time = nil
attachment.author_id = User.current.id
attachment.copy_from = origin_attachment.copy_from || origin_attachment.id
attachment.is_publish = 0
attachment.attachtype ||= 4
attachment.course_second_category_id = @second_category_list[origin_attachment.course_second_category_id]
attachment.save!
origin_course.update_quotes(attachment)
end
end
end

View File

@ -21,7 +21,7 @@ class Notice::Write::EmailCreateService < Notice::Write::ClientService
end
def request_subject
"Trustie: #{subject}"
"#{subject}"
end
def request_params

View File

@ -65,7 +65,7 @@ class Projects::ApplyJoinService < ApplicationService
owner = project.user
return if owner.phone.blank?
Educoder::Sms.send(mobile: owner.phone, send_type:'applied_project_info',
Gitlink::Sms.send(mobile: owner.phone, send_type:'applied_project_info',
user_name: owner.show_name, name: project.name)
rescue Exception => ex
Rails.logger.error("发送短信失败 => #{ex.message}")

View File

@ -1,24 +0,0 @@
class RewardExperienceService
attr_reader :user, :attrs
def initialize(user, **attrs)
@user = user
@attrs = attrs.slice(*%i[container_id container_type score])
end
def call
return if user.experiences.exists?(attrs.except(:score))
ActiveRecord::Base.transaction do
experience = user.experiences.create!(attrs)
user.increment!(:experience, experience.score)
experience
end
end
def self.call(user, **attrs)
new(user, attrs).call
end
end

View File

@ -52,7 +52,7 @@ class Users::ApplyAuthenticationService < ApplicationService
end
def sms_notify_admin
Educoder::Sms.notify_admin(send_type: 'apply_auth')
Gitlink::Sms.notify_admin(send_type: 'apply_auth')
rescue => ex
Util.logger_error(ex)
end

View File

@ -62,7 +62,7 @@ class Users::ApplyProfessionalAuthService < ApplicationService
def sms_notify_admin
sms_cache = Rails.cache.read('apply_pro_certification')
if sms_cache.nil?
Educoder::Sms.notify_admin(send_type: 'apply_pro_certification')
Gitlink::Sms.notify_admin(send_type: 'apply_pro_certification')
Rails.cache.write('apply_pro_certification', 1, expires_in: 5.minutes)
end
rescue => ex

View File

@ -51,7 +51,7 @@ class Users::ApplyTrailService < ApplicationService
end
def send_trial_apply_notify!
Educoder::Sms.notify_admin(send_type:'user_apply_auth')
Gitlink::Sms.notify_admin(send_type:'user_apply_auth')
rescue => ex
Rails.logger.error('发送通知管理员短信失败')
Rails.logger.error(ex.message)

View File

@ -1,52 +0,0 @@
class Users::CourseService
include CustomSortable
sort_columns :created_at, :updated_at, default_by: :updated_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
courses = category_scope_courses.not_deleted.not_excellent
courses = status_filter(courses)
custom_sort(courses, params[:sort_by], params[:sort_direction])
end
private
def category_scope_courses
case params[:category]
when 'study' then
user.as_student_courses.started
when 'manage' then
user.manage_courses
else
ids = user.as_student_courses.started.pluck(:id) + user.manage_courses.pluck(:id)
Course.where(id: ids)
end
end
def status_filter(relations)
# 只有自己查看才有过滤
return relations unless observed_logged_user?
case params[:status]
when 'processing' then
relations.processing
when 'end' then
relations.ended
else
relations
end
end
def observed_logged_user?
User.current.id == user.id
end
end

View File

@ -1,99 +0,0 @@
class Users::QuestionBankService
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
relations = class_name.classify.constantize.all
relations = category_filter(relations)
relations = type_filter(relations) if params[:type].present?
relations = relations.where(course_list_id: params[:course_list_id]) if params[:course_list_id].present?
custom_sort(relations, params[:sort_by], params[:sort_direction])
end
def course_lists
relation_name = class_name.underscore.pluralize.to_sym
course_lists = CourseList.joins(relation_name).where.not(relation_name => { id: nil })
category_condition =
case params[:object_type]
when 'normal' then { homework_type: 1 }
when 'group' then { homework_type: 3 }
when 'exercise' then { container_type: 'Exercise' }
when 'poll' then { container_type: 'Poll' }
when 'gtask', 'gtopic' then {}
else raise ArgumentError
end
course_lists = course_lists.where(relation_name => category_condition) if category_condition.present?
type_condition =
case params[:type]
when 'personal' then { user_id: user.id }
when 'publicly' then { is_public: true }
else {}
end
course_lists = course_lists.where(relation_name => type_condition) if type_condition.present?
course_lists.distinct.select(:id, :name)
end
private
def class_name
@_class_name ||= begin
case params[:object_type]
when 'normal', 'group' then 'HomeworkBank'
when 'exercise', 'poll' then 'ExerciseBank'
when 'gtask' then 'GtaskBank'
when 'gtopic' then 'GtopicBank'
else raise ArgumentError
end
end
end
def category_filter(relations)
case params[:object_type]
when 'normal' then
relations.where(homework_type: 1)
when 'group' then
relations.where(homework_type: 3)
when 'exercise' then
relations.where(container_type: 'Exercise')
when 'poll' then
relations.where(container_type: 'Poll')
when 'gtask', 'gtopic' then
relations.all
else
raise ArgumentError
end
end
def type_filter(relations)
case params[:type]
when 'personal' then relations.where(user_id: user.id)
when 'publicly' then relations.where(is_public: true)
else relations
end
end
def custom_sort(relations, sort_by, sort_direction)
case sort_by
when 'updated_at' then
relations.order("updated_at #{sort_direction}, id #{sort_direction}")
when 'name' then
relations.order("CONVERT(name USING gbk) COLLATE gbk_chinese_ci #{sort_direction}")
when 'contributor' then
order_sql = "CONVERT (users.lastname USING gbk) COLLATE gbk_chinese_ci #{sort_direction},"\
" CONVERT (users.firstname USING gbk) COLLATE gbk_chinese_ci #{sort_direction}"
relations.joins(:user).where(users: { status: 1 }).order(order_sql)
else
relations
end
end
end

View File

@ -71,7 +71,7 @@ class Users::UpdateAccountService < ApplicationService
end
def sms_notify_admin name
Educoder::Sms.send(mobile:'17680641960', send_type:'teacher_register', name: name, user_name:'管理员')
Gitlink::Sms.send(mobile:'17680641960', send_type:'teacher_register', name: name, user_name:'管理员')
rescue => ex
Util.logger_error(ex)
end

View File

@ -1,40 +0,0 @@
class Weapps::CreateCourseService < ApplicationService
attr_reader :course, :params
def initialize(course, params)
@course = course
@params = params
end
def call
Weapps::CreateCourseForm.new(form_params).validate!
ActiveRecord::Base.transaction do
course.name = params[:name].to_s.strip
course.school_id = course.teacher&.school_id
course.is_public = 0
course.credit = params[:credit].blank? ? nil : params[:credit]
course.end_date = params[:end_date].blank? ? nil : params[:end_date]
course_list = CourseList.find_by(name: params[:course_list_name].to_s.strip)
if course_list
course.course_list_id = course_list.id
else
new_course_list = CourseList.create!(name: params[:course_list_name].to_s.strip, user_id: course.tea_id, is_admin: 0)
course.course_list_id = new_course_list.id
end
course.is_end = course.end_date.present? && course.end_date < Date.today
course.save!
course.generate_invite_code
CourseMember.create!(course_id: course.id, user_id: course.tea_id, role: 1)
course.create_course_modules(params[:course_module_types])
end
end
private
def form_params
params.merge(course: course)
end
end

View File

@ -1,34 +0,0 @@
class Weapps::UpdateCourseService < ApplicationService
attr_reader :course, :params
def initialize(course, params)
@course = course
@params = params
end
def call
Weapps::UpdateCourseForm.new(form_params).validate!
ActiveRecord::Base.transaction do
course.name = params[:name].to_s.strip
course.credit = params[:credit].blank? ? nil : params[:credit]
course.end_date = params[:end_date].blank? ? nil : params[:end_date]
course_list = CourseList.find_by(name: params[:course_list_name].to_s.strip)
if course_list
course.course_list_id = course_list.id
else
new_course_list = CourseList.create!(name: params[:course_list_name].to_s.strip, user_id: course.tea_id, is_admin: 0)
course.course_list_id = new_course_list.id
end
course.is_end = course.end_date.present? && course.end_date < Date.today
course.save!
end
course
end
private
def form_params
params.merge(course: course)
end
end

View File

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

View File

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

View File

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

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