| @@ -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 | |||
| @@ -102,7 +102,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 | |||
| # 邮箱类型的发送 | |||
| @@ -183,7 +183,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 | |||
| @@ -192,7 +192,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 | |||
| @@ -373,7 +373,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 | |||
| @@ -392,7 +392,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 | |||
| @@ -416,7 +416,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 | |||
| @@ -588,8 +588,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 | |||
| @@ -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, | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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}") | |||
| @@ -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 | |||
| @@ -1,2 +0,0 @@ | |||
| module EcCourseTargetDecorator | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -1,5 +0,0 @@ | |||
| module LibraryDecorator | |||
| extend ApplicationDecorator | |||
| display_time_method :published_at, :created_at, :updated_at | |||
| end | |||
| @@ -1,5 +0,0 @@ | |||
| module ShixunDecorator | |||
| def human_status | |||
| I18n.t("shixun.status.#{status}") | |||
| end | |||
| end | |||
| @@ -1,5 +0,0 @@ | |||
| module SubjectDecorator | |||
| def can_visited? | |||
| published? || User.current.admin? || member?(User.current) | |||
| end | |||
| end | |||
| @@ -1,5 +0,0 @@ | |||
| module VideoDecorator | |||
| extend ApplicationDecorator | |||
| display_time_method :published_at, :created_at, :updated_at | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -1,6 +1,6 @@ | |||
| # 所有的方法请按首字母的顺序依次列出 | |||
| module ApplicationHelper | |||
| include Educoder::I18n | |||
| include Gitlink::I18n | |||
| include GitHelper | |||
| ONE_MINUTE = 60 * 1000 | |||
| @@ -1,2 +0,0 @@ | |||
| module BoardsHelper | |||
| end | |||
| @@ -1,10 +0,0 @@ | |||
| module ChallengesHelper | |||
| def match_begin_symbol str | |||
| str.gsub(/\A\r/, "\r\r") | |||
| end | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module CourseGroupsHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module CourseModulesHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module CourseSecondCategoriesHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module CourseStagesHelper | |||
| end | |||
| @@ -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 | |||
| @@ -1,2 +0,0 @@ | |||
| module DiscussesHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module EduDatasHelper | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -1,2 +0,0 @@ | |||
| module HackUserLastestCodesHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module HacksHelper | |||
| end | |||
| @@ -1,2 +0,0 @@ | |||
| module TrustieHacksHelper | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -1,19 +1,19 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: tokens | |||
| # | |||
| # id :integer not null, primary key | |||
| # user_id :integer default("0"), not null | |||
| # action :string(30) default(""), not null | |||
| # value :string(40) default(""), not null | |||
| # created_on :datetime not null | |||
| # | |||
| # Indexes | |||
| # | |||
| # index_tokens_on_user_id (user_id) | |||
| # tokens_value (value) UNIQUE | |||
| # | |||
| # == Schema Information | |||
| # | |||
| # Table name: tokens | |||
| # | |||
| # id :integer not null, primary key | |||
| # user_id :integer default("0"), not null | |||
| # action :string(30) default(""), not null | |||
| # value :string(40) default(""), not null | |||
| # created_on :datetime not null | |||
| # | |||
| # Indexes | |||
| # | |||
| # index_tokens_on_user_id (user_id) | |||
| # tokens_value (value) UNIQUE | |||
| # | |||
| # | |||
| # This program is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU General Public License | |||
| @@ -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) | |||
| @@ -690,7 +690,7 @@ class User < Owner | |||
| end | |||
| def self.generate_salt | |||
| Educoder::Utils.random_hex(16) | |||
| Gitlink::Utils.random_hex(16) | |||
| end | |||
| # 全部已认证 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -1,2 +0,0 @@ | |||
| class CoursesService | |||
| end | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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}") | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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' %> | |||
| @@ -1 +0,0 @@ | |||
| $(".course-list-list-container").html("<%= j render partial: 'admins/course_lists/shared/list', locals: { courses: @course_lists }%>"); | |||
| @@ -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 } %> | |||
| @@ -1,29 +0,0 @@ | |||
| <div class="modal fade admin-merge-course-list-modal" tabindex="-1" role="dialog" aria-hidden="true"> | |||
| <div class="modal-dialog modal-dialog-centered" role="document"> | |||
| <div class="modal-content"> | |||
| <div class="modal-header"> | |||
| <h5 class="modal-title">修改课程</h5> | |||
| <button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |||
| <span aria-hidden="true">×</span> | |||
| </button> | |||
| </div> | |||
| <div class="modal-body"> | |||
| <form class="admin-merge-course-list-form" data-url="<%= merge_admins_course_lists_path %>"> | |||
| <%= hidden_field_tag(:origin_course_list_id, nil) %> | |||
| <div class="form-group d-flex"> | |||
| <label for="course_list_id" class="col-form-label">更改为:</label> | |||
| <div class="d-flex flex-column-reverse w-75"> | |||
| <input id="course_list_name" name="course_list_name" placeholder="请输入课程名称" class="form-control"> | |||
| </div> | |||
| </div> | |||
| <div class="error text-danger"></div> | |||
| </form> | |||
| </div> | |||
| <div class="modal-footer"> | |||
| <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> | |||
| <button type="button" class="btn btn-primary submit-btn">确认</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -1,2 +0,0 @@ | |||
| alert("删除成功"); | |||
| $(".course-item-<%= @course.id %>").find(".delete-course-action").remove(); | |||
| @@ -1,34 +0,0 @@ | |||
| <% define_admin_breadcrumbs do %> | |||
| <% add_admin_breadcrumb('课堂列表') %> | |||
| <% end %> | |||
| <div class="box search-form-container course-list-form"> | |||
| <%= form_tag(admins_courses_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> | |||
| <div class="form-group mr-1"> | |||
| <label for="status">状态:</label> | |||
| <% status_options = [['全部', ''], ["正在进行(#{@processed_courses})", 'processing'], ["已结束#{@ended_courses}", 'ended']] %> | |||
| <%= select_tag(:status, options_for_select(status_options), class: 'form-control') %> | |||
| </div> | |||
| <div class="form-group col-12 col-md-3"> | |||
| <label for="school_name">单位:</label> | |||
| <%= select_tag :school_id, options_for_select([''], params[:school_id]), class: 'form-control school-select flex-1' %> | |||
| </div> | |||
| <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-12 col-md-2 mr-3', placeholder: '创建者/课堂名称/课程名称检索') %> | |||
| <div class="form-check mr-2"> | |||
| <%= hidden_field_tag(:homepage_show, false, id:'') %> | |||
| <%= check_box_tag(:homepage_show, true, params[:homepage_show].to_s == 'true', class: 'form-check-input course-homepage-show') %> | |||
| <label class="form-check-label" for="homepage_show">只看首页展示</label> | |||
| </div> | |||
| <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | |||
| <input type="reset" class="btn btn-secondary clear-btn" value="清空"/> | |||
| <% end %> | |||
| <a href="javascript:void(0)" class="btn btn-primary" id="course-export" data-disable-with = '导出中...'>导出</a> | |||
| </div> | |||
| <div class="box admin-list-container course-list-container"> | |||
| <%= render partial: 'admins/courses/shared/list', locals: { courses: @courses } %> | |||
| </div> | |||
| @@ -1 +0,0 @@ | |||
| $('.course-list-container').html("<%= j( render partial: 'admins/courses/shared/list', locals: { courses: @courses } ) %>"); | |||
| @@ -1,29 +0,0 @@ | |||
| wb = xlsx_package.workbook | |||
| wb.styles do |s| | |||
| blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center} | |||
| wb.add_worksheet(name: "课堂列表") do |sheet| | |||
| sheet.add_row %w(ID 课堂名称 成员 资源 普通作业 分组作业 实训作业 试卷 评测次数 私有 状态 单位 创建者 创建时间 动态时间), :height => 25,:style => blue_cell | |||
| @courses.each do |course| | |||
| data = [ | |||
| course.id, | |||
| course.name, | |||
| course.course_members_count, | |||
| get_attachment_count(course, 0), | |||
| course.course_homework_count(1), | |||
| course.course_homework_count(3), | |||
| course.course_homework_count(4), | |||
| course.exercises_count, | |||
| course.evaluate_count, | |||
| course.is_public == 1 ? "--" : "√", | |||
| course.is_end ? "已结束" : "正在进行", | |||
| course.school&.name, | |||
| course.teacher&.real_name, | |||
| course.created_at&.strftime('%Y-%m-%d %H:%M'), | |||
| course.max_activity_time ? course.max_activity_time&.strftime('%Y-%m-%d %H:%M') : "--" | |||
| ] | |||
| sheet.add_row(data) | |||
| end | |||
| end | |||
| end | |||