diff --git a/Gemfile b/Gemfile index 11029470..7909cb17 100644 --- a/Gemfile +++ b/Gemfile @@ -63,8 +63,8 @@ gem 'elasticsearch-rails' gem 'oauth2' # xlsx -#gem 'axlsx', '3.0.0.pre' -#gem 'axlsx_rails', '0.3.0' +gem 'axlsx', '3.0.0.pre' +gem 'axlsx_rails', '0.3.0' #Ruby 2.2+ has removed test/unit from the core library. if RUBY_VERSION>='2.2' diff --git a/app/api/mobile/api.rb b/app/api/mobile/api.rb index eefedb5b..894ba099 100644 --- a/app/api/mobile/api.rb +++ b/app/api/mobile/api.rb @@ -34,9 +34,9 @@ module Mobile version 'v1', using: :path format :json content_type :json, "application/json;charset=UTF-8" - # use ActionDispatch::Session::CookieStore - + #use ActionDispatch::Session::CookieStore, :expire_after => 8.hours, :key => '_educoder_session', :domain => :all + require 'digest' use Mobile::Middleware::ErrorHandler helpers do @@ -53,6 +53,27 @@ module Mobile error!('401 Unauthorized', 401) if params[:private_token] != "hriEn3UwXfJs3PmyXnSG" end + def cnmooc_access_key! + ## 签名 + accessKeyId = 'LTAISM4HFWpQHh3g'.freeze + accessKeySecret = '9NMU8ushmFu8SN1EKHOhvo9jmv1qp0'.freeze + str = [] + params.each do |key, value| + if key != "sign" + str << "#{key}=#{value}" + end + end + sign_str = "#{str.join("&")}&sk=#{accessKeySecret}" + Rails.logger.info("#####sign_str: #{sign_str}") + sign = Digest::MD5.hexdigest("#{sign_str}").upcase + Rails.logger.info("#####sign: #{sign}") + Rails.logger.info("#####params[:sign]: #{params[:sign]}") + + if params[:sign] != sign + error!('401 Unauthorized', 401) + end + end + # 有一些接口没登录也能查看数据 def career_authenticate! pass = request.path.include?("introduction") || request.path.include?("get_published_careers")|| request.path.include?("get_current_user") @@ -62,6 +83,9 @@ module Mobile end def memo_authenticate! + Rails.logger.info("#######current_user: ###{current_user}") + Rails.logger.info("#######session: ###{session[:user_id]}") + pass = (request.path.match(/memos\/\d+/).present? && !request.path.include?("reply")) || request.path.include?("get_memos_list") || request.path.include?("memos?page=") || request.path.match(/memos$/).present? @@ -73,6 +97,8 @@ module Mobile end def discusses_authenticate! + Rails.logger.info("#######current_user: ###{current_user}") + Rails.logger.info("#######session: ###{session[:user_id]}") pass = request.path.match(/discusses$/).present? || request.path.include?("discusses?page=") unless pass error!('401 Unauthorized', 401) unless current_user @@ -99,6 +125,13 @@ module Mobile return uw.user if uw end + # third_party_user_id = session[:third_party_user_id] + # Rails.logger.info("#########third_party_user_id: #{third_party_user_id}") + # if third_party_user_id + # c_user = UserSource.find_by_id(session[:third_party_user_id]) + # return c_user.user if c_user + # end + token = ApiKey.where(access_token: params[:token]).first if token && !token.expired? return User.find(token.user_id) @@ -106,7 +139,9 @@ module Mobile # Rails.logger.info("########### host is #{request.host}") - if (Rails.env.development? && session[:user_id].blank?) || (session[:user_id].blank? && request.host.include?("testbdweb")) || params[:action] == "privateGit" + if (Rails.env.development? && session[:user_id].blank?) || + (session[:user_id].blank? && request.host.include?("testbdweb")) || + params[:action] == "privateGit" session[:user_id] = 12 #116 end @@ -160,6 +195,7 @@ module Mobile mount Apis::Careers mount Apis::Assets mount Apis::Ecloud + mount Apis::Cnmooc diff --git a/app/api/mobile/apis/cnmooc.rb b/app/api/mobile/apis/cnmooc.rb new file mode 100644 index 00000000..21585ea0 --- /dev/null +++ b/app/api/mobile/apis/cnmooc.rb @@ -0,0 +1,84 @@ +# encoding=utf-8 +# 好大学接口数据 +module Mobile + module Apis + class Cnmooc < Grape::API + # before {cnmooc_access_key!} + content_type :json, 'application/json;charset=UTF-8' + + resources :cnmoocs do + desc '获取实训数据' + get "get_resources_data" do + CnmoocsService.new.get_resources_data params + end + + desc "实训搜索功能" + params do + requires :name, type: String, desc: "搜索名称" + end + get 'search_resources' do + CnmoocsService.new.search_resources params + end + + desc " 查找用户" + params do + requires :userName, type: String, desc: "好大学用户名" + end + get 'find_user' do + CnmoocsService.new.find_user params + end + + desc "创建用户" + params do + requires :userName, type: String, desc: "好大学用户名" + end + post "create_user" do + CnmoocsService.new.create_user params + end + + desc "获取资源访问地址" + params do + requires :userId, type: Integer, desc: "用户ID" + requires :resourceId, type: String, desc: "资源唯一标示" + requires :accessType, type: Integer, desc: "资源类型" + end + get "source_url" do + user = User.find_by_id(params[:userId]) + return {error: -1, messages: "用户不存在,请先创建用户"} unless user + token = Token.get_or_create_permanent_login_token(user) + cookie_options = { + :value => token.value, + :expires => 1.month.from_now, + :path => (Redmine::Configuration['autologin_cookie_path'] || '/'), + :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false), + :httponly => true + } + if Redmine::Configuration['cookie_domain'].present? + cookie_options = cookie_options.merge(domain: Redmine::Configuration['cookie_domain']) + end + cookies[Redmine::Configuration['autologin_cookie_name'].presence || 'autologin'] = cookie_options + CnmoocsService.new.source_url(params, token) + end + + desc "远程登录" + params do + requires :mail, type: String, desc: "邮箱地址" + requires :password, type: String, desc: "密码" + end + get "login_educoder" do + CnmoocsService.new.login_educoder params + end + + desc "资源学习情况查询" + params do + requires :userId, type: Integer, desc: "用户ID" + requires :resourceId, type: String, desc: "资源唯一标示" + end + get 'get_students_data' do + CnmoocsService.new.get_students_data params + end + + end + end + end +end \ No newline at end of file diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index 60096a22..128475e6 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -456,7 +456,9 @@ class AccountController < ApplicationController @pref = @user.pref @se = @user.extensions - # 已授权的用户修改单位名称,需要重新授权 + old_identity = @se.identity + + # 已授权的用户修改单位名称,需要重新授权 if @se.school_id != params[:occupation].to_i && @user.certification == 1 @user.certification = 0 apply_user = ApplyAction.where(:user_id => @user.id, :container_type => "TrialAuthorization") @@ -510,10 +512,15 @@ class AccountController < ApplicationController @se.technical_title = params[:pro_technical_title] if params[:pro_technical_title] @se.student_id = nil end + # @se.brief_introduction = params[:brief_introduction] if @user.save && @se.save + if old_identity.nil? && @se.identity == 0 + Trustie::Sms.send(mobile: '17680641960', send_type:'teacher_register', name: @user.login, user_name: "管理员") + end + reward_grade(@user, @user.id, 'Account', 500) if @user.certification != 1 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 435c71fc..601ebb8a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -66,6 +66,8 @@ class ApplicationController < ActionController::Base include Redmine::MenuManager::MenuController helper Redmine::MenuManager::MenuHelper + helper_method :admin_or_business? + # 云启训练场(EduCoder)个人版 产品编码(appId) 9200108 # 产品名称 计费类型 套餐编码 # 云启训练场(EduCoder)个人版 固定包月 9200108001 @@ -133,7 +135,7 @@ class ApplicationController < ActionController::Base end def ec_public_auth major_school - unless User.current.admin? || major_school.template_major || major_school.school.users.where(:id => User.current.id).count > 0 || + unless admin_or_business? || major_school.template_major || major_school.school.users.where(:id => User.current.id).count > 0 || major_school.ec_major_school_users.where(:user_id => User.current.id).count > 0 || EcCourseUser.where(:user_id => User.current.id, :ec_course_id => EcCourse.where(:ec_year_id => major_school.ec_years.pluck(:id)).pluck(:id)).count > 0 render_403 @@ -193,6 +195,21 @@ class ApplicationController < ActionController::Base find_current_user end + def set_autologin_cookie(user) + token = Token.get_or_create_permanent_login_token(user) + cookie_options = { + :value => token.value, + :expires => 1.month.from_now, + :path => (Redmine::Configuration['autologin_cookie_path'] || '/'), + :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false), + :httponly => true + } + if Redmine::Configuration['cookie_domain'].present? + cookie_options = cookie_options.merge(domain: Redmine::Configuration['cookie_domain']) + end + cookies[autologin_cookie_name] = cookie_options + end + def find_current_user user = nil unless api_request? @@ -207,6 +224,11 @@ class ApplicationController < ActionController::Base elsif session[:wechat_openid] uw = UserWechat.find_by_openid(session[:wechat_openid]) user = uw.user if uw + elsif params[:authToken] + user = Token.find_by_value(params[:authToken]).user + #set_autologin_cookie(user) + #start_user_session(user) + session[:user_id] = user.id end end if user.nil? && Setting.rest_api_enabled? && accept_api_auth? @@ -332,6 +354,8 @@ class ApplicationController < ActionController::Base end def require_login + logger.info("#########login?: #{User.current.logged?}") + logger.info("#########get?: #{request.get?}") if !User.current.logged? # Extract only the basic url parameters on non-GET requests if request.get? @@ -368,6 +392,10 @@ class ApplicationController < ActionController::Base end end + def admin_or_business? + User.current.business? || User.current.admin? + end + def deny_access User.current.logged? ? render_403 : require_login end diff --git a/app/controllers/careers_controller.rb b/app/controllers/careers_controller.rb index 081bce0f..9c10a3fd 100644 --- a/app/controllers/careers_controller.rb +++ b/app/controllers/careers_controller.rb @@ -27,6 +27,6 @@ class CareersController < ApplicationController private def render_react - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 05b36ba3..cc290d8c 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -32,6 +32,6 @@ class CategoriesController < ApplicationController private def render_react - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end end diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index bf01ffb0..3322f1f2 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -16,6 +16,7 @@ class ChallengesController < ApplicationController #before_filter :find_shixun_language, :only => [:show, :new, :edit] before_filter :base_index, :only => [:index, :index_down, :index_up, :destroy] before_filter :view_allow, :only => [:show] + # before_filter :check_cnmooc, :only => [:index] include ApplicationHelper @@ -487,4 +488,12 @@ class ChallengesController < ApplicationController response.headers['content--type'] = 'text/javascript' request.format = 'js' end + + # def check_cnmooc + # if params[:authToken] + # user = User.find_by_id(session[:user_id]) + # set_autologin_cookie(user) + # end + # end + end diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb index fff508a8..418015fd 100644 --- a/app/controllers/colleges_controller.rb +++ b/app/controllers/colleges_controller.rb @@ -50,7 +50,7 @@ class CollegesController < ApplicationController # Redo:这样做内存会卡死的 # user_ids = User.find_by_sql("SELECT users.id FROM users LEFT JOIN user_extensions ON users.id=user_extensions.user_id WHERE user_extensions.`school_id` = #{@school.id}").map(&:id) # Redo:是否直接使用count会更好 - all_course_ids = Course.joins("join users u on courses.tea_id = u.id").joins("join user_extensions ue on u.id = ue.user_id").where("courses.id != 1309 and ue.school_id = #{@school.id}") + all_course_ids = Course.where("id != 1309 and is_delete = 0 and school_id = #{@school.id}") @courses_count = all_course_ids.size # Redo:对于量比较大的尽量不使用笛卡尔积 @@ -131,7 +131,7 @@ class CollegesController < ApplicationController (select count(m.id) from messages m inner join boards b on b.id=m.board_id and b.parent_id=0 where b.course_id=c.id group by c.id) as messages_count, c.tea_id, c.name, c.is_end, (SELECT MAX(created_at) FROM `course_activities` ca WHERE ca.course_id = c.id) AS update_time - FROM `courses` c WHERE (c.school_id = #{@school.id} and c.is_delete = 0)") + FROM `courses` c WHERE c.school_id = #{@school.id} and c.is_delete = 0") @courses.each do |course| course[:evaluating_count] = Output.find_by_sql("select sum(g.evaluate_count) as evaluating_count from games g inner join diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index e87c7297..669cc58f 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -577,7 +577,7 @@ class CoursesController < ApplicationController cha_member.member_roles.where("role_id = 10").first.destroy StudentsForCourse.where(:course_id => @course.id, :student_id => cha_member.user_id).destroy_all end - @course.update_attributes(:tea_id => cha_member.user_id) + @course.update_attributes(:tea_id => cha_member.user_id, :school_id => cha_member.user.try(:user_extensions).try(:school_id)) man_member.member_roles.first.update_attributes(:role_id => 9) course_act = CourseActivity.where(:course_id => @course.id, :course_act_id => @course.id, :course_act_type => 'Course').first course_act.update_column('user_id', cha_member.user_id) diff --git a/app/controllers/ec_course_achievement_methods_controller.rb b/app/controllers/ec_course_achievement_methods_controller.rb index ecc74a67..5dcdfea8 100644 --- a/app/controllers/ec_course_achievement_methods_controller.rb +++ b/app/controllers/ec_course_achievement_methods_controller.rb @@ -309,7 +309,7 @@ class EcCourseAchievementMethodsController < ApplicationController @ec_course = EcCourse.find(params[:ec_course_id]) @year = @ec_course.ec_year @ec_major_school = @year.ec_major_school - @template_major = User.current.admin? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || + @template_major = admin_or_business? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) @is_manager = @template_major || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id) end diff --git a/app/controllers/ec_course_evaluations_controller.rb b/app/controllers/ec_course_evaluations_controller.rb index bf47d16e..f2a54e6f 100644 --- a/app/controllers/ec_course_evaluations_controller.rb +++ b/app/controllers/ec_course_evaluations_controller.rb @@ -298,7 +298,7 @@ class EcCourseEvaluationsController < ApplicationController def find_course @ec_course = EcCourse.find params[:ec_course_id] ec_major_school = @ec_course.ec_year.ec_major_school - @is_manager = User.current.admin? || ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || + @is_manager = admin_or_business? || ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id) end @@ -306,7 +306,7 @@ class EcCourseEvaluationsController < ApplicationController @ce = EcCourseEvaluation.find params[:id] @ec_course = @ce.ec_course ec_major_school = @ec_course.ec_year.ec_major_school - @is_manager = User.current.admin? || ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || + @is_manager = admin_or_business? || ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id) end end diff --git a/app/controllers/ec_course_supports_controller.rb b/app/controllers/ec_course_supports_controller.rb index 6bb0288b..39b7d06b 100644 --- a/app/controllers/ec_course_supports_controller.rb +++ b/app/controllers/ec_course_supports_controller.rb @@ -50,7 +50,7 @@ class EcCourseSupportsController < ApplicationController max_support_count = 0 subitems_count = 0 major_school = @year.ec_major_school - is_manager = User.current.admin? || major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) + is_manager = admin_or_business? || major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) ec_graduation_requirements.each_with_index do |gr, i| logger.info("#############index:#{i}#####_ec_gradiation_reqiorements: #{gr.id}") subitems_count += gr.ec_graduation_subitems.count diff --git a/app/controllers/ec_courses_controller.rb b/app/controllers/ec_courses_controller.rb index a81d6796..8ad9f4e4 100644 --- a/app/controllers/ec_courses_controller.rb +++ b/app/controllers/ec_courses_controller.rb @@ -88,7 +88,7 @@ class EcCoursesController < ApplicationController def ec_course_support_setting respond_to do |format| format.html { - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false } format.json { course_targets = @ec_course.ec_course_targets.includes(:ec_graduation_subitems) @@ -152,19 +152,19 @@ class EcCoursesController < ApplicationController # 课程体系(课程考核与数据来源) # /ec_courses/1/ec_course_reach_setting def ec_course_reach_setting - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 课程体系(课程目标评价方法) # /ec_courses/1/evaluation_methods def evaluation_methods - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 课程达成详情(蓝胡12) # GET /ec_courses/1/competition_calculation_info def competition_calculation_info - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 评价详情的导出 @@ -346,7 +346,7 @@ class EcCoursesController < ApplicationController # 关联课堂弹框-搜索 def search_courses user = User.where(:id => params[:user_id]).first - if user.try(:admin?) + if user.try(:admin?) || user.try(:business?) courses = Course.where(:is_delete => 0) else course_ids = Member.where("user_id = #{user.try(:id)} and course_id != -1").pluck(:course_id) @@ -425,7 +425,7 @@ class EcCoursesController < ApplicationController format.html{ Rails.logger.info("1111111111111111111template_major: #{@template_major}") Rails.logger.info("1111111111111111111is_manager: #{@is_manager}") - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false } format.json{ levels = @ec_course.ec_score_levels @@ -588,7 +588,7 @@ class EcCoursesController < ApplicationController @ec_course = EcCourse.find(params[:id]) @year = @ec_course.ec_year @ec_major_school = @year.ec_major_school - @template_major = User.current.admin? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || + @template_major = admin_or_business? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) @is_manager = @template_major || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id) end @@ -596,7 +596,7 @@ class EcCoursesController < ApplicationController def find_year @year = EcYear.find(params[:ec_year_id]) @ec_major_school = @year.ec_major_school - @template_major = User.current.admin? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || + @template_major = admin_or_business? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) #@is_manager = @template_major || @ec_course.ec_course_users.pluck(:user_id).include?(User.current.id) end diff --git a/app/controllers/ec_graduation_requirements_controller.rb b/app/controllers/ec_graduation_requirements_controller.rb index ea0f5464..091588cd 100644 --- a/app/controllers/ec_graduation_requirements_controller.rb +++ b/app/controllers/ec_graduation_requirements_controller.rb @@ -34,7 +34,7 @@ class EcGraduationRequirementsController < ApplicationController ActiveRecord::Base.transaction do @year = EcYear.find params[:year_id] position = @year.ec_graduation_requirements ? @year.ec_graduation_requirements.count + 1 : 1 - @template_major = User.current.admin? || @year.ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) + @template_major = admin_or_business? || @year.ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) ec_requirement_id = EcGraduationRequirement.create(content: params[:requirement], :ec_year_id => @year.id, :position => position) params[:subitems].try(:each_with_index) do |sub, index| EcGraduationSubitem.create(content: sub, ec_graduation_requirement_id: ec_requirement_id.id, position: index+1) @@ -48,7 +48,7 @@ class EcGraduationRequirementsController < ApplicationController def update requirement = EcGraduationRequirement.find params[:id] @year = requirement.ec_year - @template_major = User.current.admin? || @year.ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) + @template_major = admin_or_business? || @year.ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) requirement.update_attribute(:content, params[:requirement]) requirement.ec_graduation_subitems.destroy_all params[:subitems].try(:each_with_index) do |sub, index| diff --git a/app/controllers/ec_major_schools_controller.rb b/app/controllers/ec_major_schools_controller.rb index c47899f6..dfeb9ce4 100644 --- a/app/controllers/ec_major_schools_controller.rb +++ b/app/controllers/ec_major_schools_controller.rb @@ -13,7 +13,7 @@ class EcMajorSchoolsController < ApplicationController # 这个status 用于创建界别时,局部刷新的状态 @status = params[:status] - @btn_text = @major_school.template_major && User.current.admin? ? "立即配置" : + @btn_text = @major_school.template_major && admin_or_business? ? "立即配置" : (!@major_school.template_major && @major_manager ? "立即配置" : "查看") if params[:search] @@ -84,7 +84,7 @@ class EcMajorSchoolsController < ApplicationController user_url = user_path(User.current) year = @year.year # 学校操作权限 - template_major = User.current.admin? || major.school.ec_school_users.pluck(:user_id).include?(User.current.id) + template_major = admin_or_business? || major.school.ec_school_users.pluck(:user_id).include?(User.current.id) # 示例专业 example_major = major.template_major ec_course_support_setting_url = ec_course_support_setting_ec_course_path(ec_course) if ec_course.present? @@ -122,7 +122,7 @@ class EcMajorSchoolsController < ApplicationController requirement_vs_objective_url: "#{requirement_vs_objective_ec_major_school_ec_year_path(@year, :ec_major_school_id => @year.ec_major_school_id)}", requirement_vs_standard: "#{requirement_vs_standard_ec_major_school_ec_year_path(@year, :ec_major_school_id => @year.ec_major_school_id)}", requirement_vs_courses: "#{requirement_vs_courses_ec_major_school_ec_year_path(@year, :ec_major_school_id => @year.ec_major_school_id)}", - students_url: student_lists_ec_major_schools_ec_years_path(@year, ec_major_school_id: @year.ec_major_school_id), + students_url: student_lists_ec_major_school_ec_year_path(@year, ec_major_school_id: @year.ec_major_school_id), go_back_url: ec_major_school_path(major), ec_course_support_setting_url: ec_course_support_setting_url, ec_course_reach_setting_url: ec_course_reach_setting_url, @@ -130,7 +130,7 @@ class EcMajorSchoolsController < ApplicationController competition_calculation_info_url: competition_calculation_info_url, score_level_setting_url: score_level_setting_url, example_major: example_major, - allow_visit: User.current.admin? || (User.current.ec_school.present? && User.current.ec_school == major.school.id) + allow_visit: admin_or_business? || (User.current.ec_school.present? && User.current.ec_school == major.school.id) } end @@ -159,7 +159,7 @@ class EcMajorSchoolsController < ApplicationController end def add_manager - @is_school_manager = User.current.admin? || @major_school.school.users.where(:id => User.current.id).count > 0 # 学校管理员 + @is_school_manager = admin_or_business? || @major_school.school.users.where(:id => User.current.id).count > 0 # 学校管理员 if @is_school_manager || @major_school.ec_major_school_users.where(:user_id => User.current.id).count > 0 params[:user_id].each do |user_id| if @major_school.ec_major_school_users.count < 5 && @major_school.ec_major_school_users.where(:user_id => user_id).count == 0 @@ -172,7 +172,7 @@ class EcMajorSchoolsController < ApplicationController end def delete_manager - @is_school_manager = User.current.admin? || @major_school.school.users.where(:id => User.current.id).count > 0 # 学校管理员 + @is_school_manager = admin_or_business? || @major_school.school.users.where(:id => User.current.id).count > 0 # 学校管理员 if @is_school_manager || @major_school.ec_major_school_users.where(:user_id => User.current.id).count > 0 @major_school.ec_major_school_users.where(:user_id => params[:user_id]).destroy_all else @@ -184,7 +184,7 @@ class EcMajorSchoolsController < ApplicationController def find_major_school @major_school = EcMajorSchool.find(params[:id]) # 管理员权限 - @major_manager = User.current.admin? || @major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) + @major_manager = admin_or_business? || @major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) end # 职业认证的权限判断 diff --git a/app/controllers/ec_years_controller.rb b/app/controllers/ec_years_controller.rb index c0c9483c..6baf5d58 100644 --- a/app/controllers/ec_years_controller.rb +++ b/app/controllers/ec_years_controller.rb @@ -25,7 +25,7 @@ class EcYearsController < ApplicationController @status = 1 end @major_manager = true - @btn_text = @major_school.template_major && User.current.admin? ? "立即配置" : + @btn_text = @major_school.template_major && admin_or_business? ? "立即配置" : (!@major_school.template_major && @major_manager ? "立即配置" : "查看") @years = EcYear.where(:ec_major_school_id => @major_school.id) @years = paginateHelper @years, 10 @@ -46,7 +46,7 @@ class EcYearsController < ApplicationController def student_lists respond_to do |format| format.html { - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false } end end @@ -217,7 +217,7 @@ class EcYearsController < ApplicationController # 本专业必要要求VS课程支撑体系 def requirement_vs_courses - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 导出课程支撑体系 @@ -251,7 +251,7 @@ class EcYearsController < ApplicationController # 课程达成点计算(蓝胡13) # GET /ec_courses/1/competition_calculation_info def reach_calculation_info - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 蓝胡13数据获取 @@ -338,7 +338,7 @@ class EcYearsController < ApplicationController @ec_major_school = EcMajorSchool.find(params[:ec_major_school_id]) @year = EcYear.find(params[:id]) # 专业管理员身份 - @template_major = User.current.admin? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) + @template_major = admin_or_business? || @ec_major_school.school.ec_school_users.pluck(:user_id).include?(User.current.id) || @ec_major_school.ec_major_school_users.pluck(:user_id).include?(User.current.id) end # 职业认证的权限判断 diff --git a/app/controllers/ecs_controller.rb b/app/controllers/ecs_controller.rb index 172d13fc..5d391a5d 100644 --- a/app/controllers/ecs_controller.rb +++ b/app/controllers/ecs_controller.rb @@ -7,7 +7,7 @@ class EcsController < ApplicationController def department @template_major = EcMajorSchool.where(:template_major => true).first @school_managers = @school.users - @is_school_manager = User.current.admin? || @school.users.where(:id => User.current.id).count > 0 # 学校管理员 + @is_school_manager = User.current.admin? || User.current.business? || @school.users.where(:id => User.current.id).count > 0 # 学校管理员 @major_schools = @school.ec_major_schools.where(:template_major => false) unless @is_school_manager @@ -70,7 +70,7 @@ class EcsController < ApplicationController end def school_manager - unless User.current.admin? || @school.users.where(:id => User.current.id).count > 0 + unless User.current.admin? || User.current.business? || @school.users.where(:id => User.current.id).count > 0 render_403 end end diff --git a/app/controllers/exercise_bank_controller.rb b/app/controllers/exercise_bank_controller.rb index e4fa6727..6b8090dd 100644 --- a/app/controllers/exercise_bank_controller.rb +++ b/app/controllers/exercise_bank_controller.rb @@ -104,6 +104,7 @@ class ExerciseBankController < ApplicationController :question_type => params[:question_type] || 1, :question_number => @exercise.exercise_bank_questions.count + 1, :question_score => params[:question_score], + :shixun_name => params[:question_type] == '5' ? params[:shixun_name] : nil, :shixun_id => params[:shixun], :max_choices => params[:max_choices].to_i || 0, :min_choices => params[:min_choices].to_i || 0 @@ -271,6 +272,7 @@ class ExerciseBankController < ApplicationController end end if @exercise_question.question_type == 5 + @exercise_question.shixun_name = params[:shixun_name].strip if !params[:shixun_name].blank? question_score = 0 @exercise_question.exercise_bank_shixun_challenges.each_with_index do |challenge, index| challenge.question_score = params[:question_score][index] diff --git a/app/controllers/exercise_controller.rb b/app/controllers/exercise_controller.rb index 23024a78..ee5705fb 100644 --- a/app/controllers/exercise_controller.rb +++ b/app/controllers/exercise_controller.rb @@ -372,6 +372,7 @@ class ExerciseController < ApplicationController :question_type => params[:question_type] || 1, :question_number => @exercise.exercise_questions.count + 1, :question_score => params[:question_type] == '5' ? 0 : params[:question_score], + :shixun_name => params[:question_type] == '5' ? params[:shixun_name] : nil, :shixun_id => params[:shixun] } @exercise_questions = @exercise.exercise_questions.new option @@ -512,6 +513,7 @@ class ExerciseController < ApplicationController end end if @exercise_question.question_type == 5 + @exercise_question.shixun_name = params[:shixun_name].strip if !params[:shixun_name].blank? question_score = 0 @exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index| challenge.question_score = params[:question_score][index] @@ -1508,7 +1510,8 @@ class ExerciseController < ApplicationController :question_type => q[:question_type] || 1, :question_number => q[:question_number], :question_score => q[:question_score], - :shixun_id => q[:shixun_id] + :shixun_id => q[:shixun_id], + :shixun_name => q[:shixun_name] } exercise_bank_question = exercise_bank.exercise_bank_questions.new option diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb index afb5b7dd..f5beed7b 100644 --- a/app/controllers/forums_controller.rb +++ b/app/controllers/forums_controller.rb @@ -28,7 +28,7 @@ class ForumsController < ApplicationController private def render_react - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end end @@ -163,7 +163,7 @@ end # # id: 1 问题反馈 3 操作指南 5 技术分享 # def index # -# render "/common/index", :layout => false +# render file: 'public/react/build/index.html', :layout => false # end # # # GET /forums/1 diff --git a/app/controllers/homework_common_controller.rb b/app/controllers/homework_common_controller.rb index e404c5ee..0e5ac1d6 100644 --- a/app/controllers/homework_common_controller.rb +++ b/app/controllers/homework_common_controller.rb @@ -12,11 +12,12 @@ class HomeworkCommonController < ApplicationController before_filter :find_homework, :only => [:edit,:update,:alert_anonymous_comment,:start_anonymous_comment,:stop_anonymous_comment,:destroy,:start_evaluation_set, :set_evaluation_attr,:score_rule_set,:alert_forbidden_anonymous_comment,:alert_open_student_works,:open_student_works, :set_score_open,:alert_score_open_modal,:add_to_homework_bank,:publish_notice,:publish_homework,:end_notice,:end_homework, - :setting,:set_public,:homework_setting,:update_explanation,:cancel_publish, :homework_code_repeat, :review_detail,:move_to_category] + :setting,:set_public,:homework_setting,:update_explanation,:cancel_publish, :homework_code_repeat, :review_detail,:move_to_category, + :rename_modal, :rename_homework] before_filter :teacher_of_course, :only => [:new, :create, :edit, :update, :destroy, :start_anonymous_comment, :stop_anonymous_comment, :alert_anonymous_comment, :start_evaluation_set,:set_evaluation_attr,:score_rule_set,:alert_forbidden_anonymous_comment,:alert_open_student_works, :open_student_works,:add_to_homework_bank,:publish_notice,:end_notice,:publish_homework,:end_homework,:update_explanation, - :cancel_publish, :move_to_category,:homework_setting] + :cancel_publish, :move_to_category,:homework_setting, :rename_homework, :rename_modal] # before_filter :member_of_course, :only => [:index,:setting] @@ -275,6 +276,19 @@ class HomeworkCommonController < ApplicationController @groups = paginateHelper @groups, 5 end + def rename_modal + + end + + def rename_homework + if params[:name].blank? + @notice = true + else + @homework.update_attributes(:name => params[:name].strip) + redirect_to homework_common_index_path(:course => @course.id, :homework_type => @homework.homework_type) + end + end + def setting @is_new = params[:is_new].to_i if params[:is_new] @is_empty = @homework.publish_time.nil? diff --git a/app/controllers/managements/schools_controller.rb b/app/controllers/managements/schools_controller.rb index a5c789ff..74202ad5 100644 --- a/app/controllers/managements/schools_controller.rb +++ b/app/controllers/managements/schools_controller.rb @@ -78,5 +78,7 @@ class Managements::SchoolsController < Managements::BaseController @active_course_total = Course.where(is_end: false).count @shixun_homework_total = HomeworkCommon.where(homework_type: 4).count @other_homework_total = HomeworkCommon.where(homework_type: [1, 3]).count + @shixun_total = Shixun.count + @shixun_evaluate_total = SchoolReport.sum(:shixun_evaluate_count) end end diff --git a/app/controllers/managements_controller.rb b/app/controllers/managements_controller.rb index 39e89bd8..483a4ff3 100644 --- a/app/controllers/managements_controller.rb +++ b/app/controllers/managements_controller.rb @@ -2,11 +2,10 @@ class ManagementsController < ApplicationController before_filter :require_business before_filter :require_admin, :only => [:shixun_setting_list, :mirror_repository, :mirror_picture_shixuns, :editmd_template, - :editmd_template, :subject_level_system, :subject_setting_list, :auto_users_trial, - :evaluate_records, :identity_authentication, :identity_authentication, :professional_authentication, - :shixun_authorization, :graduation_standard, :ec_template, :codemirror_template, + :editmd_template, :subject_level_system, :subject_setting_list, + :shixun_authorization, :ec_template, :codemirror_template, :course_guide_template, :shixun_quality_score, :tech_system, :update_notice, :setting_banner, - :training_2018] + :training_2018, :create_standard] layout 'base_management' include ManagementsHelper include SortHelper @@ -32,6 +31,15 @@ class ManagementsController < ApplicationController # 实训课程等级体系 def subject_level_system @levels = SubjectLevelSystem.all + respond_to do |format| + format.js + format.html + format.xls{ + time = Time.now.strftime("%Y%m%d") + filename = "实训课程体系#{time}.xls" + send_data(export_subject_level_system(), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename)) + } + end end # 创建课程等级体系 @@ -2023,7 +2031,7 @@ end # @schools = School.where(:id =>user_exs.map(&:school_id)) # end @search = params[:search] # 搜索字 - @keyword = params[:keyword].blank? ? "u_name" : params[:keyword] # 根据姓名/课程名搜索 + @keyword = params[:keyword].blank? ? "c_name" : params[:keyword] # 根据姓名/课程名搜索 @status = params[:status] @school_id = params[:school_id] @@ -2044,11 +2052,13 @@ end if params[:status] && params[:status]!='' @courses = @courses.where(:is_end => @status.to_i) end - if "u_name" == @keyword + if "c_name" == @keyword + @courses = @courses.where("name like ?", "%#{@search}%") + elsif "u_name" == @keyword if @search.blank? @courses = @courses else - user_id = User.where("concat(lastname, firstname) like '%#{@search}%'") + # user_id = User.where("concat(lastname, firstname) like '%#{@search}%'") @courses = @courses.joins("join users u on courses.tea_id = u.id").where("concat(u.lastname, u.firstname) like '%#{@search}%'") end elsif "dep_name" == @keyword @@ -2818,17 +2828,17 @@ end else "status = 1" end - @users = User.where("#{sql}").includes(:apply_actions, user_extensions: [:department, :school]).order("last_login_on #{@sx_order}") + @users = User.where("#{sql}").includes(:real_name_authentication_apply, :professional_authentication_apply, + user_extensions: [:department, :school]).order("last_login_on #{@sx_order}") @has_cer_count = User.where(:status => 1, :certification => 1).count @reject_cer_count = User.where(:status => 1, :certification => 2).count @deal_cer_count = ApplyAction.where(:status => 0).select("distinct user_id").count - time = Time.at(Time.now.to_i - 86400) - cer = UserDayCertification.where("created_at > '#{time}'").pluck(:user_id) - cer_ids = cer.join(",") - @trial_cer_count = cer.blank? ? 0 : User.where("status = 1 and certification != 1 and id in (#{cer_ids})").count - apply = ApplyAction.where(:container_type => "TrialAuthorization").pluck(:user_id) - apply_ids = apply.join(",") - @nonn_cer_count = apply.blank? ? 0 : User.where("status = 1 and certification = 0 and id not in (#{apply_ids}) ").count + + subquery = UserDayCertification.where("created_at > ?", Time.now.ago(1.days)).select(:user_id).to_sql + @trial_cer_count = User.where("status = 1 and certification != 1 and id in (#{subquery})").count + + apply_subquery = ApplyAction.where(container_type: "TrialAuthorization").select(:user_id).to_sql + @nonn_cer_count = User.where("status = 1 and certification = 0 and id not in (#{apply_subquery}) ").count @page = (params['page'] || 1).to_i @users_count = @users.count @@ -3308,83 +3318,82 @@ end end end - all_user_ids = User.where(:status => 1).pluck(:id) + users = User.where(nil) if params[:trial] == "-1" - apply = ApplyAction.where(:container_type => "TrialAuthorization").pluck(:user_id) - apply_id = apply.blank? ? -1 : "(" + apply.join(",") + ")" - apply_user_id = User.where("status = 1 and certification = 0 and id not in #{apply_id} ").pluck(:id) + users = users.where(status: 1, certification: 0) + .joins('LEFT JOIN apply_actions ON apply_actions.user_id = users.id AND apply_actions.container_type = "TrialAuthorization"') + .where('apply_actions.user_id IS NULL') elsif params[:trial] == "-2" - apply_user_id = all_user_ids + users = users.where(status: 1) elsif params[:trial] == "0" - apply_user_id = ApplyAction.where(:status => 0).pluck(:user_id) + users = users.joins('LEFT JOIN apply_actions ON apply_actions.user_id = users.id').where(apply_actions: { status: 0 }) elsif params[:trial] == "3" - time = Time.at(Time.now.to_i - 86400) - user_cer = UserDayCertification.where("created_at > '#{time}'").pluck(:user_id) - cer_id = user_cer.blank? ? "(-1)" : "(" + user_cer.map{|a| a.user_id}.join(",") + ")" - apply_user_id = User.where("status = 1 and certification != 1 and id in #{cer_id} ").pluck(:id) + users = users.joins('LEFT JOIN user_day_certifications udc ON udc.user_id = users.id') + .where('users.certification != 1').where('udc.created_at > ?', Time.now.ago(1.days)) else - apply_user_id = User.where(:status => 1, :certification => params[:trial]).pluck(:id) + users = users.where(status: 1, certification: params[:trial]) end - if params[:school] == "" - s_user_id = all_user_ids - else - school_ids = School.where("name like '%#{params[:school]}%'").pluck(:id) - s_user_id = UserExtensions.where(:school_id => school_ids).pluck(:user_id) + users = users.joins('LEFT JOIN user_extensions ON user_extensions.user_id = users.id') + .joins('LEFT JOIN departments ON departments.id = user_extensions.department_id') + .joins('LEFT JOIN schools ON schools.id = user_extensions.school_id') + + if params[:school].present? + users = users.where("schools.name LIKE ?", "%#{params[:school]}%") end - if params[:department] == "" - d_user_id = all_user_ids - else - dep_ids = Department.where("name like '%#{params[:department]}%'").pluck(:id) - d_user_id = UserExtensions.where(:department_id => dep_ids).pluck(:user_id) + if params[:department].present? + users = users.where("departments.name LIKE ?", "%#{params[:department]}%") end - ide_user_id = all_user_ids if params[:identity] == "1" || (params[:identity] == "0" && params[:te_technical_title] == "0") || (params[:identity] == "2" && params[:pro_technical_title] == "0") - ide_user_id = UserExtensions.where("identity = #{params[:identity]}").pluck(:user_id) + users = users.where(user_extensions: { identity: params[:identity] }) elsif (params[:identity] == "0" && params[:te_technical_title] != "0") || (params[:identity] == "2" && params[:pro_technical_title] != "0") technical_title = params[:identity] == "0" ? params[:te_technical_title] : params[:pro_technical_title] - ide_user_id = UserExtensions.where("identity = #{params[:identity]} and technical_title = '#{technical_title}'").pluck(:user_id) + users = users.where(user_extensions: { identity: params[:identity], technical_title: technical_title }) end - if params[:student_id] && params[:student_id] != '' - stu_user_id = UserExtensions.where("student_id like '%#{params[:student_id]}%'").pluck(:user_id) - else - stu_user_id = all_user_ids + if params[:student_id].present? + users = users.where('user_extensions.student_id like ?', "%#{params[:student_id]}%") end - user_id = s_user_id & d_user_id & apply_user_id & stu_user_id & ide_user_id - sql = "" - sql = - if params[:research_condition] == "name" - "concat(lastname, firstname) like '%#{params[:research_contents]}%'" - elsif params[:research_condition] == "email" - "mail like '%#{params[:research_contents]}%'" - elsif params[:research_condition] == "phone" - "phone like '%#{params[:research_contents]}%'" - elsif params[:research_condition] == "nickname" - if params[:research_contents].present? - "nickname like '%#{params[:research_contents]}%'" - end - elsif params[:research_condition] == "login" - params[:research_contents].present? ? "login like '%#{params[:research_contents]}%'" : "" - end + if params[:research_contents].present? + keyword = "%#{params[:research_contents]}%" + if params[:research_condition] == "name" + users = users.where('concat(lastname, firstname) like ?', keyword) + elsif params[:research_condition] == "email" + users = users.where("mail like ?", keyword) + elsif params[:research_condition] == "phone" + users = users.where("phone like ?", keyword) + elsif params[:research_condition] == "nickname" + users = users.where("nickname like ?", keyword) + elsif params[:research_condition] == "login" + users = users.where("login like ?", keyword) + end + end + + if params[:province].present? + users = users.where(schools: { province: params[:province] }) + end + + users = users.select('distinct users.*').order("last_login_on desc") - @users = User.where(:id => user_id).where("#{sql}").includes(:apply_actions, user_extensions: [:department, :school]).order("last_login_on desc") - @xls_users = @users.reorder("created_on desc").limit(3000) #导出excel用户 @page = (params['page'] || 1).to_i - @users_count = @users.count + @users_count = users.count @limit = 20 @is_remote = true @users_pages = Paginator.new @users_count, @limit, params['page'] || 1 @offset ||= @users_pages.offset - @users = paginateHelper @users, @limit + @users = paginateHelper users.includes(:real_name_authentication_apply, :professional_authentication_apply, + user_extensions: [:department, :school]), @limit respond_to do |format| format.js format.xls{ # @export_shixun_task = @export_shixun_task.all + @xls_users = users.reorder("created_on desc").limit(3000) #导出excel用户 + @xls_users = @xls_users.includes(:real_name_authentication_apply, :professional_authentication_apply, + user_extensions: [:department, :school]) filename = "用户列表.xls" send_data(user_list_xls(@xls_users), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename)) } @@ -4184,7 +4193,7 @@ end sheet1 = book.create_worksheet :name => "users" blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 sheet1.row(0).default_format = blue - sheet1.row(0).concat(["用户姓名","性别","职业","职称","地区"," 单位","子单位","注册时间","最后登录时间","授权"]) + sheet1.row(0).concat(["用户姓名","性别","职业","职称","地区"," 单位","子单位","注册时间","最后登录时间","授权", "邮箱"]) count_row = 1 users.each do |user| sheet1[count_row,0] = user.try(:show_real_name) @@ -4197,6 +4206,7 @@ end sheet1[count_row,7] = format_time user.created_on sheet1[count_row,8] = format_time user.last_login_on sheet1[count_row,9] = user.trial_authorization + sheet1[count_row,10] = user.mail count_row += 1 end book.write xls_report @@ -4285,6 +4295,33 @@ end return sheet.rows end + def export_subject_level_system + xls_report = StringIO.new + book = Spreadsheet::Workbook.new + sheet1 = book.create_worksheet :name => "实训课程等级体系" + blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 + sheet1.row(0).default_format = blue + count_row = 1 + sheet1.row(0).concat(["序号", "等级", "实训课程名称", "实训课程url", "实训名称"]) + levels = SubjectLevelSystem.includes(subjects: [stage_shixuns: :shixun]).where(nil) + levels.each_with_index do |level, i| + sheet1[count_row, 0] = i + 1 + sheet1[count_row, 1] = level.name + level.subjects.each do |subject| + sheet1[count_row, 2] = subject.name + sheet1[count_row, 3] = "#{Setting.protocol}://#{Setting.host_name}#{subject_path(subject)}" + count_row += 1 + subject.shixuns.each do |shixun| + sheet1[count_row, 4] = shixun.name + count_row += 1 + end + end + count_row += 1 + end + book.write xls_report + xls_report.string + end + def shixun_feedback_xls shixun_ids, beginTime, endTime xls_report = StringIO.new book = Spreadsheet::Workbook.new @@ -4294,7 +4331,7 @@ end count_row = 1 shixuns = Shixun.where(:id => shixun_ids).includes(discusses: [:user]) sheet1.row(0).concat(["序号", "实训ID", "实训名称", "实训作者", "作者单位", "评论数", "评论内容", "关卡", "评论者", "评论者职业", - "评论者单位", "评论时间", "社区导师是否已回复"]) + "评论者单位", "评论时间", "社区导师是否已回复", "我的账号回复内容", "回复时间"]) shixuns.each_with_index do |shixun, i| discusses = shixun.discusses.where("user_id != ?", 1) if beginTime.present? @@ -4312,6 +4349,7 @@ end discusses.each_with_index do |discuss, j| user = discuss.user content = discuss.content.gsub(//, "【图片评论】").gsub(/!\[\].+\)/, "【图片评论】") + myself_discuss = discuss.children.where(user_id: User.current.id).last sheet1[count_row, 6] = strip_html content sheet1[count_row, 7] = "第#{discuss.position}关" sheet1[count_row, 8] = user.show_real_name @@ -4319,6 +4357,8 @@ end sheet1[count_row, 10] = user.school_name sheet1[count_row, 11] = format_time discuss.created_at sheet1[count_row, 12] = discuss.children.pluck(:user_id).include?(1) ? "是" : "否" + sheet1[count_row, 13] = myself_discuss.try(:content) + sheet1[count_row, 14] = myself_discuss ? (format_time myself_discuss.created_at) : "" count_row += 1 end #count_row += 1 diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb index df266efa..d06adb8e 100644 --- a/app/controllers/memos_controller.rb +++ b/app/controllers/memos_controller.rb @@ -29,7 +29,7 @@ class MemosController < ApplicationController # 这样处理是为了 前端react显示图片所使用 def new - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end def create diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index f6854c7a..96f45d3a 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -1,15 +1,19 @@ # encoding: utf-8 class MyshixunsController < ApplicationController layout 'base_myshixun' - skip_before_filter :verify_authenticity_token, :only => [:training_task_status, :close_webssh, :code_runinng_message] - before_filter :require_login, :except => [:training_task_status, :close_webssh, :code_runinng_message] + skip_before_filter :verify_authenticity_token, :only => [:training_task_status, :close_webssh, :code_runinng_message, :vnc] + before_filter :require_login, :except => [:training_task_status, :close_webssh, :code_runinng_message, :vnc] before_filter :check_authentication, :except => [:training_task_status, :close_webssh, :mul_test_home, :mul_test_user, - :mul_test_myshixun, :mul_test_shixun, :mul_test_start, :code_runinng_message] + :mul_test_myshixun, :mul_test_shixun, :mul_test_start, :code_runinng_message, :vnc] before_filter :find_myshixun, :only => [:show, :myshixun_reset, :open_webssh, :sync_reset_time, :destroy, :search_file_list, :vnc] DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) include ApplicationHelper + def archive + + end + def forbidden render_403 return @@ -357,7 +361,8 @@ class MyshixunsController < ApplicationController host = Redmine::Configuration['tomcat_php'] begin uri = "#{shixun_tomcat}/bridge/vnc/getvnc" - params = {tpiID:@myshixun.id} + shixun = @myshixun.shixun + params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(container_limit(shixun.mirror_repositories))}"} res = uri_exec uri, params if res && res['code'].to_i != 0 raise("实训云平台繁忙(繁忙等级:99)") diff --git a/app/controllers/question_banks_controller.rb b/app/controllers/question_banks_controller.rb index 96f6db3b..cffecba1 100644 --- a/app/controllers/question_banks_controller.rb +++ b/app/controllers/question_banks_controller.rb @@ -117,7 +117,7 @@ class QuestionBanksController < ApplicationController else @courses = User.current.courses.where("is_delete = 0 and is_end = 0").select{ |course| User.current.has_teacher_role(course)} end - @homework_ids = params[:check_homework_bank] || params[:bank_id].split(" ") + @homework_ids = params[:check_homework_bank] || params[:bank_id].split(" ") unless params[:is_observe] @search = params[:search] respond_to do |format| format.js diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index c60a9959..e47938ac 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -10,7 +10,7 @@ class ShixunsController < ApplicationController before_filter :view_allow, :only => [:collaborators, :propaedeutics, :shixun_discuss, :ranking_list] before_filter :require_manager, :only => [ :settings, :add_script, :publish, :collaborators_delete, :shixun_members_added, :add_collaborators, :update, :destroy] before_filter :validation_email, :only => [:new] - before_filter :require_admin, :only => [:destroy] + #before_filter :require_manager, :only => [:destroy] # 移动云ToC模式权限控制 # before_filter :ecloud_auth, :except => [:show, :index] @@ -850,7 +850,7 @@ class ShixunsController < ApplicationController begin raise "请先绑定邮箱" if User.current.mail.blank? new_shixun = Shixun.new - new_shixun.attributes = @shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier", "homepage_show","git_url") + new_shixun.attributes = @shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier", "homepage_show","git_url", "propaedeutics") new_shixun.user_id = User.current.id new_shixun.identifier = generate_identifier new_shixun.status = 0 @@ -1088,7 +1088,7 @@ class ShixunsController < ApplicationController def shixun_discuss if User.current.logged? - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false else redirect_to signin_path end @@ -1117,6 +1117,7 @@ class ShixunsController < ApplicationController end def destroy + render_403 if @shixun.status > 1 && !User.current.admin? ActiveRecord::Base.transaction do g = Gitlab.client g.delete_project(@shixun.gpid) if @shixun.try(:gpid).present? diff --git a/app/controllers/statistics_controller.rb b/app/controllers/statistics_controller.rb index 9c5453d0..cd4bc9e1 100644 --- a/app/controllers/statistics_controller.rb +++ b/app/controllers/statistics_controller.rb @@ -6,7 +6,7 @@ class StatisticsController < ApplicationController before_filter :find_rate def index - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end # 用户活跃度(按月份的) @@ -187,7 +187,7 @@ class StatisticsController < ApplicationController unless User.curren.admin? render_403 end - render "/common/index", :layout => false + render file: 'public/react/build/index.html', :layout => false end def set_rate diff --git a/app/controllers/student_work_controller.rb b/app/controllers/student_work_controller.rb index 8885353c..289c122b 100644 --- a/app/controllers/student_work_controller.rb +++ b/app/controllers/student_work_controller.rb @@ -496,7 +496,7 @@ class StudentWorkController < ApplicationController def _index # REDO:分班信息提前查出来,然后循环中根据匹配去取 - @is_teacher = User.current.logged? ? (User.current.allowed_to?(:as_teacher,@course) || User.current.admin?) : false + @is_teacher = User.current.logged? ? (User.current.allowed_to?(:as_teacher,@course) || User.current.admin? || User.current.business?) : false @member = @course.members.where(:user_id => User.current.id).first # 判断学生是否有权限查看(作业未发布、作业已发布但不是统一设置的未分班学生、分班设置的作业未发布) if User.current.member_of_course?(@course) && !@is_teacher @@ -584,16 +584,16 @@ class StudentWorkController < ApplicationController @stundet_works = @stundet_works.where(:work_status => @status) end + @stundet_works = search_work_member @stundet_works, @name + if @stundet_works.size != 0 if @order == "student_id" - @stundet_works = @stundet_works.includes(:user => {:user_extensions => []}).order("user_extensions.student_id #{@b_sort}") + @stundet_works = @stundet_works.joins(:user => {:user_extensions => []}).order("user_extensions.student_id #{@b_sort}") else @stundet_works = @stundet_works.order("#{@order} #{@b_sort}") end end - @stundet_works = search_work_member @stundet_works, @name - @score = @b_sort == "desc" ? "asc" : "desc" # @is_focus = params[:is_focus] ? params[:is_focus].to_i : 0 # 消息传过来的ID @@ -615,6 +615,7 @@ class StudentWorkController < ApplicationController _index @stundet_works = paginateHelper @stundet_works, @limit + @members = @course.members.select([:user_id, :course_group_id]) if @stundet_works.size != 0 @stundet_works = if @homework.homework_type == 1 @stundet_works.includes(:student_works_scores, [user: :user_extensions]) @@ -623,7 +624,6 @@ class StudentWorkController < ApplicationController elsif @homework.homework_type == 4 @stundet_works.includes(:student_works_scores, [myshixun: :games], [user: :user_extensions]) end - @members = @course.members.where(user_id: @stundet_works.pluck(:user_id)).select([:user_id, :course_group_id]) end respond_to do |format| format.js @@ -647,7 +647,7 @@ class StudentWorkController < ApplicationController uid: "#{work.user.user_extensions.student_id}", downloadUrl: '' } - attachment = work.attachments.first + attachment = work.attachments.last if attachment o[:downloadUrl] = "https://#{Setting.host_name}/"+download_named_attachment_path(attachment.id, attachment.filename) end diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb index 36058172..d152ac2c 100644 --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -3,7 +3,6 @@ class TasksController < ApplicationController layout false def show - # redirect_to "/react/build/index.html" - render "/common/index" + render file: 'public/react/build/index.html', :layout => false end end diff --git a/app/controllers/trainings_controller.rb b/app/controllers/trainings_controller.rb index 02a3255d..948d97be 100644 --- a/app/controllers/trainings_controller.rb +++ b/app/controllers/trainings_controller.rb @@ -63,10 +63,9 @@ class TrainingsController < ApplicationController return end - @training.training_payinfo ||= begin - payinfo = TrainingPayinfo.new - payinfo.fee = @training.registration_fee # 默认值价格不对 - payinfo + if @training.training_payinfo.blank? + @training.build_training_payinfo + @training.training_payinfo.fee = @training.registration_fee end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 35449aad..34fa1a8d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7034,7 +7034,8 @@ def quote_exercise_bank exercise, course :question_type => q[:question_type] || 1, :question_number => q[:question_number], :question_score => q[:question_score], - :shixun_id => q[:shixun_id] + :shixun_id => q[:shixun_id], + :shixun_name => q[:shixun_name] } exercise_question = new_exercise.exercise_questions.new option diff --git a/app/models/cnmooc_user.rb b/app/models/cnmooc_user.rb new file mode 100644 index 00000000..e834c768 --- /dev/null +++ b/app/models/cnmooc_user.rb @@ -0,0 +1,8 @@ +class CnmoocUser < UserSource + + private + + def email_prefix + 'cnmooc_' + end +end diff --git a/app/models/discuss.rb b/app/models/discuss.rb index 6d7ada99..b397721e 100644 --- a/app/models/discuss.rb +++ b/app/models/discuss.rb @@ -1,6 +1,7 @@ class Discuss < ActiveRecord::Base belongs_to :user - attr_accessible :user_id, :content, :dis_id, :dis_type, :parent_id, :praise_count, :root_id, :challenge_id, :position, :reward + attr_accessible :user_id, :content, :dis_id, :dis_type, :parent_id, :praise_count, :root_id, :challenge_id, + :position, :reward, :hidden default_scope :order => 'created_at desc' has_many :praise_tread, as: :praise_tread_object, dependent: :destroy diff --git a/app/models/myshixun.rb b/app/models/myshixun.rb index 774caad9..b5e9df62 100644 --- a/app/models/myshixun.rb +++ b/app/models/myshixun.rb @@ -15,7 +15,8 @@ class Myshixun < ActiveRecord::Base belongs_to :user validates_uniqueness_of :shixun_id, :scope => :user_id, :message => "error" # validates :shixun_id, :uniqueness => {:scope => :user_id, :message => "不能被重复开启"} - scope :min, lambda { select([:id, :shixun_id, :identifier, :gpid, :status, :user_id, :commit_id, :modify_time, :reset_time, :system_tip]) } + scope :min, lambda { select([:id, :shixun_id, :identifier, :gpid, :status, :user_id, :commit_id, :modify_time, :reset_time, + :system_tip, :gpid]) } scope :finished, lambda{where(status: 1)} def output_times diff --git a/app/models/school.rb b/app/models/school.rb index 8342039e..293ab4b8 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -26,6 +26,7 @@ class School < ActiveRecord::Base # 报表信息 has_many :school_daily_reports + has_one :school_report has_many :teacher_extensions, conditions: "identity = #{User::TEACHER}", class_name: 'UserExtensions' has_many :student_extensions, conditions: "identity = #{User::STUDENT}", class_name: 'UserExtensions' @@ -80,4 +81,10 @@ class School < ActiveRecord::Base courses.id LEFT JOIN user_extensions ON courses.tea_id=user_extensions.user_id WHERE user_extensions.`school_id` = #{self.id}").first.try(:max_update) end + + def self.provinces + Rails.cache.fetch('china_province_cache', expires_in: 1.days) do + School.pluck('distinct province').select(&:present?) + end + end end diff --git a/app/models/school_daily_active_user.rb b/app/models/school_daily_active_user.rb new file mode 100644 index 00000000..0edd00fa --- /dev/null +++ b/app/models/school_daily_active_user.rb @@ -0,0 +1,3 @@ +class SchoolDailyActiveUser < ActiveRecord::Base + belongs_to :school_daily_report +end \ No newline at end of file diff --git a/app/models/school_daily_report.rb b/app/models/school_daily_report.rb index 494eacfd..6b24d8be 100644 --- a/app/models/school_daily_report.rb +++ b/app/models/school_daily_report.rb @@ -1,3 +1,5 @@ class SchoolDailyReport < ActiveRecord::Base belongs_to :school + + has_many :school_daily_active_users, dependent: :delete_all end \ No newline at end of file diff --git a/app/models/school_report.rb b/app/models/school_report.rb new file mode 100644 index 00000000..1ff8674c --- /dev/null +++ b/app/models/school_report.rb @@ -0,0 +1,3 @@ +class SchoolReport < ActiveRecord::Base + belongs_to :school +end \ No newline at end of file diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 439c0e44..bf06b583 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -57,7 +57,7 @@ class Shixun < ActiveRecord::Base scope :visible, lambda{where(status: [2,3])} scope :min, lambda { select([:id, :name, :gpid, :modify_time, :reset_time, :language, :propaedeutics, :status, :identifier, :test_set_permission, :hide_code, :forbid_copy, :hidden, :webssh, :user_id, :code_hidden, - :task_pass, :exec_time, :multi_webssh]) } + :task_pass, :exec_time, :multi_webssh, :vnc]) } scope :published, lambda{where(status: 2)} scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) } diff --git a/app/models/user.rb b/app/models/user.rb index 752ea113..db1ff58a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -224,6 +224,8 @@ class User < Principal ### has_many :apply_actions, :dependent => :destroy has_many :apply_user_authentications, :dependent => :destroy + has_one :real_name_authentication_apply, conditions: 'auth_type = 1 AND status = 0', class_name: 'ApplyUserAuthentication' + has_one :professional_authentication_apply, conditions: 'auth_type = 2 AND status = 0', class_name: 'ApplyUserAuthentication' has_one :user_wechat @@ -269,6 +271,8 @@ class User < Principal has_many :article_homepages, :dependent => :destroy has_many :competition_lists, :dependent => :destroy + has_one :user_source + ## end # default_scope -> { includes(:user_extensions, :user_score) } @@ -991,12 +995,12 @@ class User < Principal # 实名认证状态 def authentication_status - status = self.authentication ? "已认证" : (self.apply_user_authentications.where(:auth_type => 1, :status => 0).count > 0 ? "待审核" : "未认证") + authentication ? "已认证" : (real_name_authentication_apply.present? ? "待审核" : "未认证") end # 职业认证状态 def professional_status - status = self.professional_certification ? "已认证" : (self.apply_user_authentications.where(:auth_type => 2, :status => 0).count > 0 ? "待审核" : "未认证") + professional_certification ? "已认证" : (professional_authentication_apply.present? ? "待审核" : "未认证") end def logged? @@ -1115,7 +1119,7 @@ class User < Principal end def member_of_course?(course) - courses.to_a.include?(course) + courses.to_a.include?(course) || User.current.business? end def member_of_contest?(contest) @@ -1319,7 +1323,7 @@ class User < Principal if Project === context return false unless context.allows_to?(action) # Admin users are authorized for anything else - return true if admin? + return true if admin? || business? # 课程:作品关联项目的老师也可以访问私有项目 course_ids = context.student_work_projects.blank? ? "(-1)" : "(" + context.student_work_projects.map{|swp| swp.course_id}.join(",") + ")" diff --git a/app/models/user_source.rb b/app/models/user_source.rb new file mode 100644 index 00000000..d8fb350d --- /dev/null +++ b/app/models/user_source.rb @@ -0,0 +1,21 @@ +class UserSource < ActiveRecord::Base + belongs_to :user + + def generate_email + email = rand_email + while User.exists?(mail: email) do + email = rand_email + end + email + end + + private + + def rand_email + email_prefix + Random.rand.to_s[2..8] + '@educoder.com' + end + + def email_prefix + '' + end +end diff --git a/app/services/cnmoocs_service.rb b/app/services/cnmoocs_service.rb new file mode 100644 index 00000000..d380e9d6 --- /dev/null +++ b/app/services/cnmoocs_service.rb @@ -0,0 +1,148 @@ +class CnmoocsService + include ApplicationHelper + include GamesHelper + + def get_resources_data params + + resources = [] + if params[:level].to_s == "1" + subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.status, COUNT(myshixuns.id) AS myshixun_member_count + FROM myshixuns, stage_shixuns, subjects WHERE myshixuns.shixun_id = stage_shixuns.shixun_id + AND stage_shixuns.subject_id = subjects.id AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 + GROUP BY subjects.id ORDER BY myshixun_member_count DESC") + + + subjects.each do |subject| + resources << {resourceId: subject.id, parentId: nil, resourceName: subject.name, accessType: 0, nodeType: 0, + resourceType: 2} + end + + elsif params[:level].to_s == "2" + return {error: -1, messages: "请求二级及其更高目录时,parentId不能为空"} if params[:parentId].blank? + stages = Stage.where(:subject_id => params[:parentId]) + stages.each do |stage| + resources << {resourceId: stage.id, parentId: params[:parentId], resourceName: stage.name, accessType: 0, nodeType: 0, + resourceType: 2} + end + + elsif params[:level].to_s == "3" + return {error: -1, messages: "请求二级及其更高目录时,parentId不能为空"} if params[:parentId].blank? + shixun_ids = StageShixun.where(:stage_id => params[:parentId]).pluck(:shixun_id) + shixuns = Shixun.where(:id => shixun_ids) + shixuns.each do |shixun| + resources << {resourceId: shixun.id, parentId: params[:parentId], resourceName: shixun.name, accessType: 2, + nodeType: 1, resourceType: 1} + end + + end + {error: 0, messages: "请求成功", + data: {resources: resources} } + end + + def search_resources params + shixuns = Shixun.select([:id, :identifier, :name, :myshixuns_count, :averge_star, :challenges_count, :trainee]). + where(status: 2, hidden: 0).where("name like ?", "%#{params[:name]}%") + + shixuns = shixuns.order("myshixuns_count desc") + shixun_list = shixun_data shixuns + {error: 0, messages: "请求成功", + data: shixun_list } + end + + def find_user params + c_user = CnmoocUser.find_by_uuid(params[:userName]) + if c_user + {error: 0, messages: "找到用户", data: { userId: c_user.user_id } } + else + {error: -1, messages: "找不到用户"} + end + end + + def create_user(params) + c_user = CnmoocUser.find_by_uuid(params[:userName]) + + if c_user.present? + return { error: -1, messages: '用户已存在' } + end + c_user = CnmoocUser.new(uuid: params[:userName], name: params[:name]) + + mail = params[:email] || c_user.generate_email + name = params[:name] || "好大学_#{params[:userName]}" + login = generate_login('m') + Rails.logger.info("#######mail: #{mail}, #{name}, #{login}") + create_params = { + lastname: name, + mail: mail, + mail_notification: mail, + password: OauthController::DEFAULT_PASSWORD, + certification: 1 + } + user = User.new(create_params) + # login 有问题,只能这样赋值 + user.login = login + ActiveRecord::Base.transaction do + user.save! + + UserExtensions.create!(user_id: user.id, school_id: School.first.id, identity: 4, gender: 0) + + c_user.user_id = user.id + c_user.save! + end + + { error: 0, messages: "创建成功", data: { userId: user.id } } + end + + def login_educoder params + user, last_login_on = User.try_to_login(params[:mail], params[:password]) + if user + self.logged_user = user + {error: 0, messages: "登录成功"} + else + {error: -1, messages: "登录失败,请检查邮箱和密码是否正确"} + end + + end + + def source_url(params, token) + shixun = Shixun.find_by_id(params[:resourceId]) + if shixun.blank? + return { error: -1, messages: '资源不存在' } + end + { error: 0, messages: '成功', data: {accessUrl: "#{Redmine::Configuration['educoder_domain']}/shixuns/#{shixun.identifier}/challenges?authToken=#{token.value}" }} + end + + def get_students_data params + shixun = Shixun.find_by_id params[:resourceId] + return {error: -1, messages: "资源id不对,请使用资源的id查找"} if shixun.blank? + myshixun = shixun.myshixuns.where(:user_id => params[:userId]).includes(:games).first + if myshixun.present? + score = myshixun.total_score + time = 0 + myshixun.games.each do |game| + time += game.consumes_time_int + end + {error: 0, messages: '成功', data: {experiment: {time: time, totalTime: score * 10}}} + else + {error: -1, messages: '用户还未开始学习此资源'} + end + end + + private + def shixun_data shixuns + shixun_list = [] + shixuns.includes(:tag_repertoires).each do |shixun| + tag_name = shixun.tag_repertoires.first.try(:name) + level = %W(初级 中级 高级 顶级)[shixun.trainee - 1] + shixun_list << {identifier: shixun.identifier, name: shixun.name, students_count: shixun.myshixuns_count, + challenges_count: shixun.challenges_count, score_info: shixun.averge_star, level: level} + + end + {resources: shixun_list} + end + + # 为新创建的用户随机生成以m为前缀的用户名,m表示该用户是用邮箱注册 + def generate_login(login_pre) + us = UsersService.new + us.generate_user_login(login_pre) + end +end \ No newline at end of file diff --git a/app/services/copy_ec_year_service.rb b/app/services/copy_ec_year_service.rb index 7ad46c5f..31bac9f9 100644 --- a/app/services/copy_ec_year_service.rb +++ b/app/services/copy_ec_year_service.rb @@ -224,8 +224,11 @@ to_relate.attributes = relate.attributes.except('id', 'ec_course_achievement_method_id', 'ec_course_target_id', 'ec_course_evaluation_subitem_id', 'created_at', 'updated_at') to_relate.ec_course_target_id = course_target_map[relate.ec_course_target_id] - to_relate.ec_course_evaluation_subitem_id = course_target_map[relate.ec_course_evaluation_subitem_id] + # 可能不存在,所以为 -1 + to_relate.ec_course_evaluation_subitem_id = course_evaluation_subitem_map[relate.ec_course_evaluation_subitem_id] || -1 to_relate.save! + + achievement_evaluation_relates_map[relate.id] = to_relate.id end end @@ -258,14 +261,16 @@ end def copy_year_students! - students = from_year.ec_year_students.includes(:ec_student_achievements) + students = from_year.ec_year_students.includes(:ec_student_achievements, :ec_course_student_scores, :ec_student_score_targets) students.each do |student| to_student = to_year.ec_year_students.new - to_student.attributes = student.attributes.except('id', 'ec_year_id', 'created_at', 'updated') + to_student.attributes = student.attributes.except('id', 'ec_year_id', 'created_at', 'updated_at') to_student.save! copy_student_achievements!(student, to_student) + copy_course_student_scores!(student, to_student) + copy_student_score_targets!(student, to_student) end end @@ -280,6 +285,31 @@ end end + def copy_course_student_scores!(student, to_student) + student.ec_course_student_scores.each do |score| + to_score = to_student.ec_course_student_scores.new + to_score.attributes = score.attributes.except('id', 'ec_year_student_id', 'ec_course_id', 'created_at', 'updated_at') + to_score.ec_course_id = course_map[score.ec_course_id] + to_score.save! + + course_student_score_map[score.id] = to_score.id + end + end + + def copy_student_score_targets!(student, to_student) + student.ec_student_score_targets.each do |target| + to_target = to_student.ec_student_score_targets.new + to_target.attributes = target.attributes.except('id', 'ec_course_id', 'ec_course_student_score_id', + 'ec_course_target_id', 'ec_year_student_id', 'eaer_id', + 'created_at', 'updated_at') + to_target.ec_course_id = course_map[target.ec_course_id] + to_target.ec_course_student_score_id = course_student_score_map[target.ec_course_student_score_id] + to_target.ec_course_target_id = course_target_map[target.ec_course_target_id] + to_target.eaer_id = achievement_evaluation_relates_map[target.eaer_id] + to_target.save! + end + end + def graduation_requirement_map @_graduation_requirement_map ||= {} end @@ -300,7 +330,15 @@ @_course_evaluation_subitem_map ||= {} end + def achievement_evaluation_relates_map + @_achievement_evaluation_relates_map ||= {} + end + def course_target_map @_course_target_map ||= {} end + + def course_student_score_map + @_course_student_score_map ||= {} + end end \ No newline at end of file diff --git a/app/services/discusses_service.rb b/app/services/discusses_service.rb index 415aea1b..a43ccfa8 100644 --- a/app/services/discusses_service.rb +++ b/app/services/discusses_service.rb @@ -56,8 +56,9 @@ class DiscussesService # 添加评论 def create params, current_user begin + hidden = current_user.admin? ? false : true Discuss.create!(:dis_id => params[:shixun_id], :dis_type => "Shixun", :content => params[:content].gsub(" \;", "").strip, :user_id => current_user.id, - :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id]) + :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id], :hidden => hidden) # 发送手机通知 # status = Trustie::Sms.send(mobile:'18173242757', send_type:'discuss', name:'管理员') rescue Exception => e @@ -69,8 +70,9 @@ class DiscussesService def reply params, current_user begin base_dicuss params[:id] + hidden = current_user.admin? ? false : true discuss = Discuss.create!(:content => params[:content].gsub(" \;", "").strip, :user_id => current_user.id, :parent_id => params[:id], - :root_id => @discuss.root_id || params[:id], :praise_count => 0, :challenge_id => @discuss.challenge_id, + :root_id => @discuss.root_id || params[:id], :praise_count => 0, :challenge_id => @discuss.challenge_id, :hidden => hidden, :dis_id => @discuss.dis_id, :dis_type => @discuss.dis_type, :position => @discuss.position) return discuss rescue Exception => e diff --git a/app/services/games_service.rb b/app/services/games_service.rb index 2139715e..f513316e 100644 --- a/app/services/games_service.rb +++ b/app/services/games_service.rb @@ -19,6 +19,7 @@ class GamesService shixun = Shixun.min.find(myshixun.shixun_id) unless ((myshixun.user_id == current_user.id || current_user.business? || current_user.id == shixun.try(:user_id) || current_user.is_certification_teacher) && (shixun.operable?)) || current_user.admin? + Rails.logger.info("######403???") return{:status => 403} end game_challenge = Challenge.min.find(game.challenge_id) @@ -31,7 +32,8 @@ class GamesService # st:判断是选择类型还是实训类型 st = game_challenge.st game_count = myshixun.games.count - discusses_count = shixun.discusses.count + discusses_count = (current_user.admin? ? shixun.discusses.count : + shixun.discusses.where("hidden = false or user_id = :user_id", user_id: current_user.id).count) mirror_name = myshixun.mirror_name user = myshixun.owner username = user.show_name @@ -44,7 +46,7 @@ class GamesService # 高性能取上一关、下一关 prev_game = Game.prev_identifier(shixun.id, game.myshixun_id, game_challenge.position) - next_game = if current_user.is_certification_teacher || shixun_manager(shixun, current_user) || game.status || shixun.task_pass + next_game = if shixun.vnc || current_user.is_certification_teacher || shixun_manager(shixun, current_user) || game.status || shixun.task_pass Game.next_game(shixun.id, game.myshixun_id, game_challenge.position).try(:identifier) end @@ -75,6 +77,29 @@ class GamesService :record => record, :grade => grade, :prev_game => prev_game, :next_game => next_game, :username => username, :image_url => image_url, :user_url => user_url, :praise_count => praise_count, :user_praise => user_praise, :time_limit => time_limit, :tomcat_url => Redmine::Configuration['tomcat_php'], :is_teacher => is_teacher, :power => power, :myshixun_manager => myshixun_manager} + if shixun.vnc + begin + shixun_tomcat = Redmine::Configuration['shixun_tomcat'] + service_host = Redmine::Configuration['tomcat_php'] + uri = "#{shixun_tomcat}/bridge/vnc/getvnc" + params = {tpiID: myshixun.id, :containers => "#{Base64.urlsafe_encode64(container_limit(shixun.mirror_repositories))}"} + res = uri_exec uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:99)") + end + url = "#{service_host}" +":#{res['port']}/vnc_lite.html?password=headless" + Rails.logger.info("66666666sssssss#{url}") + container = container.merge(:vnc_url => url) + Rails.logger.info("777777666sssssss#{container}") + rescue Exception => e + Rails.logger.error(e.message) + end + end + + if st == 0 && shixun.status == 2 && myshixun_manager + zip_path = Gitlab.endpoint.to_s + "/projects/" + myshixun.gpid.to_s + "/repository/archive?&private_token=" + Gitlab.private_token.to_s + container = container.merge(:zip_path => zip_path) + end # 区分选择题和编程题,st:0编程题; if st == 0 @@ -91,7 +116,7 @@ class GamesService # 区分评测过未评测过,未评测过按需求取数据 sql = if max_query_index > 0 - "SELECT + "SELECT b.code, b.actual_output, b.out_put, b.result, b.compile_success, a.is_public, a.input, a.output FROM (SELECT position, input, output, challenge_id, is_public FROM test_sets where challenge_id=#{game_challenge.id}) a @@ -130,7 +155,7 @@ class GamesService Rails.logger.warn(latest_output) output_hash = {:test_sets => test_sets}.merge(:had_test_count => had_test_count, :test_sets_count => test_sets_count, - :had_passed_testsests_error_count => had_passed_testsests_error_count) + :had_passed_testsests_error_count => had_passed_testsests_error_count) multi_webssh = shixun.webssh == 2 && shixun.multi_webssh result = {:tpm_modified => tpm_modified, :tpm_cases_modified => tpm_cases_modified, :hide_code => shixun.hide_code, :forbid_copy => shixun.forbid_copy, :output_sets => output_hash, :latest_output => latest_output, :mirror_name => mirror_name, :multi_webssh => multi_webssh, @@ -371,7 +396,8 @@ class GamesService end if content != last_content content_modified = 1 - code_file = @g.edit_file(@myshixun.gpid, current_user.login, :content => content, :file_path => path, :branch_name => "master", :commit_message => "auto commit") + code_file = @g.edit_file(@myshixun.gpid, current_user.login, :content => content, :file_path => path, :branch_name => "master", + :commit_message => (params[:evaluate] == 1 ? "commit by author" : "auto commit" )) end # REDO:是否有读写分离的问题 if record.present? @@ -668,6 +694,7 @@ class GamesService :evaluate_count]).find_by_identifier(params[:identifier]) # 更新评测次数 game.update_column(:evaluate_count, (game.evaluate_count.to_i + 1)) + game.challenge.shixun.increment!(:evaluate_count) # 选择题如果通关了,则不让再评测 if game.status == 2 @@ -801,6 +828,7 @@ class GamesService # 轮询获取状态 # resubmit是在file_update中生成的,从game_build中传入的 def game_status params, current_user + Rails.logger.info("sec_key is #{params[:sec_key]}**1") game = Game.find_by_identifier(params[:identifier]) resubmit_identifier = game.resubmit_identifier # 如果没有超时并且正在评测中 @@ -812,6 +840,7 @@ class GamesService return {:running_code_status => running_code_status, :running_code_message => running_code_message} end + Rails.logger.info("sec_key is #{params[:sec_key]}**2") Rails.logger.info("##### resubmit_identifier is #{resubmit_identifier}") port = params[:port] score = 0 @@ -838,6 +867,7 @@ class GamesService end end + Rails.logger.info("sec_key is #{params[:sec_key]}**3") # 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集 max_query_index = game.query_index - 1 # 区分评测过未评测过,未评测过按需求取数据 @@ -854,7 +884,7 @@ class GamesService # 能进入到此处,肯定是已经返回了结果,也就是说outputs中肯定有了数据 - + Rails.logger.info("sec_key is #{params[:sec_key]}**4") test_sets_count = qurey_test_sets.size # had_test = Output.where(:game_id => game.id, :query_index => max_query_index) # had_test_count = had_test.count @@ -881,6 +911,7 @@ class GamesService web_route = game_challenge.try(:web_route) mirror_name = shixun.mirror_name + Rails.logger.info("sec_key is #{params[:sec_key]}**5") # 轮询结束,更新评测耗时 e_record = EvaluateRecord.where(:identifier => params[:sec_key]).first if game_status == 0 || game_status == 2 @@ -898,12 +929,14 @@ class GamesService # 实训制作者当前拥有的金币 grade = User.where(:id => game.user_id).pluck(:grade).first + Rails.logger.info("sec_key is #{params[:sec_key]}**6") # 高性能取上一关、下一关 prev_game = Game.prev_identifier(shixun.id, game.myshixun_id, game_challenge.position) next_game = Game.next_game(shixun.id, game.myshixun_id, game_challenge.position).try(:identifier) output_hash = {:test_sets => test_sets, :had_test_count => test_sets_count, :test_sets_count => test_sets_count, :had_passed_testsests_error_count => had_passed_testsests_error_count} + Rails.logger.info("sec_key is #{params[:sec_key]}**7") return {:grade => grade, :gold => score, :experience => experience, :status => game_status, :had_done => had_done, :position => game_challenge.position, :port => port, :power => power, :record => record, :mirror_name => mirror_name, :picture => picture, :web_route => web_route, :latest_output => latest_output, diff --git a/app/services/management/school_data_contrast_service.rb b/app/services/management/school_data_contrast_service.rb index 7637ec4a..da5048b2 100644 --- a/app/services/management/school_data_contrast_service.rb +++ b/app/services/management/school_data_contrast_service.rb @@ -4,7 +4,7 @@ class Management::SchoolDataContrastService PAGE_SIZE = 20 CONTRAST_COLUMN_LIST = %w( teacher_increase_count student_increase_count course_increase_count - shixun_increase_count active_user_count + shixun_increase_count active_user_count shixun_homework_count shixun_evaluate_count ).freeze attr_reader :params, :sort_direction, :contrast_column @@ -56,13 +56,25 @@ class Management::SchoolDataContrastService end def select_columns - "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"\ + 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 percentage #{sort_direction} LIMIT #{PAGE_SIZE} OFFSET #{offset}" + "FROM (#{from_sql}) reports ORDER BY #{order_by} LIMIT #{PAGE_SIZE} OFFSET #{offset}" end -end +end \ No newline at end of file diff --git a/app/services/management/school_data_grow_service.rb b/app/services/management/school_data_grow_service.rb index d9818d52..2baf8087 100644 --- a/app/services/management/school_data_grow_service.rb +++ b/app/services/management/school_data_grow_service.rb @@ -6,7 +6,8 @@ class Management::SchoolDataGrowService attr_reader :params sort_columns :teacher_increase_count, :student_increase_count, - :course_increase_count, :shixun_increase_count, :active_user_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) @@ -14,18 +15,25 @@ class Management::SchoolDataGrowService end def call - reports = query_reports.group('schools.id') + reports = School.where(nil) - count = reports.count.count + 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(active_user_count) active_user_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) @@ -35,33 +43,44 @@ class Management::SchoolDataGrowService def grow_summary @_grow_summary ||= begin - query_reports.select( + 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 query_reports - date = query_date - date_condition = if date.is_a?(Range) - "sdr.date BETWEEN '#{date.min.strftime('%Y-%m-%d')}' AND '#{date.max.strftime('%Y-%m-%d')}'" - else - "sdr.date = '#{date.strftime('%Y-%m-%d')}'" - end - - reports = School.joins("LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id AND #{date_condition}") + def search_filter(relations) 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}%") + relations = relations.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%") end - reports + 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 @@ -86,3 +105,4 @@ class Management::SchoolDataGrowService (params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE end end +# 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,(select count(distinct user_id) from school_daily_active_users sdau left join school_daily_reports sdr on sdr.id = sdau.school_daily_report_id where date BETWEEN '2019-06-02' AND '2019-06-03') uniq_active_user_count,SUM(active_user_count) active_user_count FROM `schools` LEFT JOIN school_daily_reports sdr ON sdr.school_id = schools.id where date BETWEEN '2019-06-02' AND '2019-06-03' LIMIT 1 \ No newline at end of file diff --git a/app/services/management/school_report_service.rb b/app/services/management/school_report_service.rb index 2b18950d..981498cd 100644 --- a/app/services/management/school_report_service.rb +++ b/app/services/management/school_report_service.rb @@ -4,7 +4,7 @@ class Management::SchoolReportService attr_reader :params sort_columns :student_count, :teacher_count, :homework_count, :other_homework_count, - :course_count, :active_course_count, :nearly_course_time, + :course_count, :active_course_count, :nearly_course_time, :shixun_count, :shixun_evaluate_count, default_by: :teacher_count, default_direction: :desc def initialize(params) @@ -47,6 +47,12 @@ class Management::SchoolReportService nearly_course_time_map = courses.joins(:course_activities).maximum('course_activities.updated_at') active_course_map = courses.where(is_end: false).count + shixun_map = Shixun.joins(creator: :user_extensions).where(user_extensions: { identity: User::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, @@ -58,6 +64,8 @@ class Management::SchoolReportService 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 @@ -68,16 +76,30 @@ class Management::SchoolReportService case sort_by_column.to_s when 'teacher_count' then - schools.joins(:teacher_extensions).select("#{base_query_column}, COUNT(*) teacher_count") + 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(:student_extensions).select("#{base_query_column}, COUNT(*) student_count") + 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(courses: :shixun_homework_commons).select("#{base_query_column}, COUNT(*) homework_count") + 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(courses: :other_homework_commons).select("#{base_query_column}, COUNT(*) other_homework_count") + 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') @@ -86,7 +108,8 @@ class Management::SchoolReportService 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(:teacher_extensions).select("#{base_query_column}, COUNT(*) teacher_count") + 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 diff --git a/app/services/shixuns_service.rb b/app/services/shixuns_service.rb index 69bbc431..de4d75b3 100644 --- a/app/services/shixuns_service.rb +++ b/app/services/shixuns_service.rb @@ -69,8 +69,17 @@ class ShixunsService dis = Shixun.select([:id, :user_id]).find(dis_id) dis_type = params[:container_type] # 如:"Shixun" # 总数,分页使用 - disscuss_count = Discuss.where(:dis_id => dis_id, :dis_type => dis_type, :root_id => nil).count - discusses = Discuss.limit(LIMIT).where(:dis_id => dis_id, :dis_type => dis_type, :root_id => nil).includes(:user, :praise_tread).offset(offset) + if current_user.admin? + disscuss_count = Discuss.where(:dis_id => dis_id, :dis_type => dis_type, :root_id => nil).count + discusses = Discuss.limit(LIMIT).where(:dis_id => dis_id, :dis_type => dis_type, + :root_id => nil).includes(:user, :praise_tread).offset(offset) + else + disscusses = Discuss.where("dis_id = :dis_id and dis_type = :dis_type and root_id is null and + (hidden = :hidden or user_id = :user_id)", + {dis_id: dis_id, dis_type: dis_type, hidden: false, user_id: current_user.id}) + disscuss_count = disscusses.count + discusses = disscusses.limit(LIMIT).includes(:user, :praise_tread).offset(offset) + end base_data discusses, dis, current_user return {:children_list => @children_list, :disscuss_count => disscuss_count} @@ -142,7 +151,13 @@ class ShixunsService :user_praise => user_praise, :admin => current_user.admin?} # 现在没有二级回复,所以查询的时候直接从root_id取 - children = Discuss.where(:root_id => d.id).includes(:user).reorder("created_at asc") + children = + if current_user.admin? + Discuss.where(root_id: d.id).includes(:user).reorder("created_at asc") + else + Discuss.where("root_id = :root_id and (hidden = :hidden or user_id = :user_id)", + {root_id: d.id, hidden: false, user_id: current_user.id}).includes(:user).reorder("created_at asc") + end @children_list << parents.merge({:children => (children.map{|child| [:content => child.content, :time => time_from_now(child.created_at), :position => child.position , :reward => child.reward,:hidden => child.hidden, :image_url => url_to_avatar(child.user), :username => child.username, :user_id => child.user_id, :user_login => child.user.try(:login), diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb index 759c7afa..cb278e98 100644 --- a/app/services/zip_service.rb +++ b/app/services/zip_service.rb @@ -52,7 +52,7 @@ module ZipService members = exercise.course.members exercise_users.each do |exercise_user| member = members.where(:user_id => exercise_user.user_id).first - group_name = member.try(:course_group_id).to_i == 0 ? '未分班' : member.course_group.name + group_name = member.try(:course_group_id).to_i == 0 ? '未分班' : member.course_group.try(:name) export_file_name = "#{group_name}-#{exercise.course_id}-#{exercise.exercise_name}-#{exercise_user.user.user_extensions.student_id}-#{exercise_user.user.show_real_name}" + ".pdf" out_file = export_user_exercise(exercise, exercise_user, export_file_name) file_name = File::expand_path(out_file) diff --git a/app/tasks/statistic_school_daily_report_task.rb b/app/tasks/statistic_school_daily_report_task.rb index 138db4d5..c533c55c 100644 --- a/app/tasks/statistic_school_daily_report_task.rb +++ b/app/tasks/statistic_school_daily_report_task.rb @@ -9,24 +9,47 @@ class StatisticSchoolDailyReportTask student_count = users.where(created_on: yesterday, user_extensions: { identity: User::STUDENT }).count # 活跃用户 - active_user_count = users.where(last_login_on: yesterday).count + active_user_ids = users.where(last_login_on: yesterday).pluck(:id) + active_user_count = active_user_ids.size + # 新增课堂 course_count = school.courses.where(created_at: yesterday).count # 新增实训 shixun_count = Shixun.joins(creator: :user_extensions) - .where('user_extensions.school_id = ?', school.id) + .where(user_extensions: { identity: User::TEACHER, school_id: school.id }) .where(created_at: yesterday).count + # 新增实训作业数 + shixun_homework_count = HomeworkCommon.joins(:course).where(courses: { school_id: school.id }) + .where(homework_type: 4, created_at: yesterday).count + + # 新增实训评测数量 + shixun_evaluate_count = EvaluateRecord.joins('LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = evaluate_records.shixun_id') + .joins('LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4') + .joins('LEFT JOIN members ON members.user_id = evaluate_records.user_id') + .joins('LEFT JOIN courses ON members.course_id = courses.id AND hc.course_id = courses.id') + .where(courses: { school_id: school.id }) + .where(created_at: yesterday).reorder(nil).count + # 无有效数据时不记录 - next if [teacher_count, student_count, course_count, shixun_count, active_user_count].all?(&:zero?) + data = [teacher_count, student_count, course_count, shixun_count, active_user_count, + shixun_homework_count, shixun_evaluate_count] + next if data.all?(&:zero?) create_params = { school_id: school.id, school_name: school.name, teacher_increase_count: teacher_count, student_increase_count: student_count, course_increase_count: course_count, + shixun_homework_count: shixun_homework_count, shixun_evaluate_count: shixun_evaluate_count, shixun_increase_count: shixun_count, active_user_count: active_user_count, date: current_date } - SchoolDailyReport.create!(create_params) + report = SchoolDailyReport.create!(create_params) + + if active_user_ids.present? + values = '(' + active_user_ids.join(", #{report.id}),(") + ", #{report.id})" + user_sql = "INSERT INTO school_daily_active_users(user_id, school_daily_report_id) VALUES#{values}" + SchoolDailyActiveUser.connection.execute(user_sql) + end end end diff --git a/app/tasks/statistic_school_report_task.rb b/app/tasks/statistic_school_report_task.rb new file mode 100644 index 00000000..addaa4c5 --- /dev/null +++ b/app/tasks/statistic_school_report_task.rb @@ -0,0 +1,20 @@ +class StatisticSchoolReportTask + def call + School.find_each do |school| + evaluate_count = Game.joins(:challenge) + .joins('LEFT JOIN members ON members.user_id = games.user_id') + .joins('LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = challenges.shixun_id') + .joins('LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4') + .joins('LEFT JOIN courses ON hc.course_id = courses.id AND members.course_id = courses.id') + .where(courses: { school_id: school.id }) + .sum(:evaluate_count) + + report = SchoolReport.find_or_initialize_by_school_id(school.id) + + report.school_name = school.name + report.shixun_evaluate_count = evaluate_count + + report.save + end + end +end diff --git a/app/views/colleges/statistics.html.erb b/app/views/colleges/statistics.html.erb index 0a159d2a..98c5be73 100644 --- a/app/views/colleges/statistics.html.erb +++ b/app/views/colleges/statistics.html.erb @@ -19,7 +19,7 @@ <%= @courses_count %>
  • - 发布实训 + 共建实训 <%= @shixuns_count %>
  • @@ -32,7 +32,7 @@
  • 教师
  • 学生
  • 课堂
  • -
  • 实训
  • +
  • 共建实训
  • 实训报告
  • 学员实战时间
  • diff --git a/app/views/common/index.html.erb b/app/views/common/index.html.erb index 82b976cb..35c63ca6 100644 --- a/app/views/common/index.html.erb +++ b/app/views/common/index.html.erb @@ -1 +1 @@ -Educoder
    \ No newline at end of file +Educoder
    \ No newline at end of file diff --git a/app/views/ec_major_schools/_year_list.html.erb b/app/views/ec_major_schools/_year_list.html.erb index 1e561782..5755d3f6 100644 --- a/app/views/ec_major_schools/_year_list.html.erb +++ b/app/views/ec_major_schools/_year_list.html.erb @@ -49,7 +49,7 @@ - <% if @major_manager && !@major_school.template_major || User.current.admin? %> + <% if @major_manager && !@major_school.template_major || User.current.admin? || User.current.business? %> 删除 <% end %> <%#= link_to '删除', ec_major_school_ec_year_path(year, :ec_major_school_id => @major_school), method: :delete, :class => "mr15 color-grey-c", data: { confirm: '您确定要删除吗' } %> diff --git a/app/views/ec_major_schools/show.html.erb b/app/views/ec_major_schools/show.html.erb index c3e4c924..92e100c2 100644 --- a/app/views/ec_major_schools/show.html.erb +++ b/app/views/ec_major_schools/show.html.erb @@ -8,7 +8,7 @@
  • <%= @major.name %> - <% if @major.schools && User.current.admin? %> + <% if @major.schools && (User.current.admin? || User.current.business?) %>

      <% @major.schools.each do |school| %> diff --git a/app/views/ec_years/_course_lists.html.erb b/app/views/ec_years/_course_lists.html.erb index b39d9bfe..721d1722 100644 --- a/app/views/ec_years/_course_lists.html.erb +++ b/app/views/ec_years/_course_lists.html.erb @@ -17,7 +17,7 @@
        <% @ec_courses.each_with_index do |course, index| %> <% course_manager = course.ec_course_users.pluck(:user_id).include?(User.current.id) %> - <% btn_text = ((@ec_major_school.template_major && User.current.admin?) || (!@ec_major_school.template_major && @template_major) || course_manager) ? "立即配置" : "查看" %> + <% btn_text = ((@ec_major_school.template_major && (User.current.admin? || User.current.business?)) || (!@ec_major_school.template_major && @template_major) || course_manager) ? "立即配置" : "查看" %>
      • <%= index + 1 %> <%= course.name %> diff --git a/app/views/exercise/_edit_shixun.html.erb b/app/views/exercise/_edit_shixun.html.erb index b7caa087..ef96f3b7 100644 --- a/app/views/exercise/_edit_shixun.html.erb +++ b/app/views/exercise/_edit_shixun.html.erb @@ -1,7 +1,10 @@ <%= form_for("",:url => update_exercise_question_exercise_index_path(:exercise_question => exercise_question.id),:html => {:id => "update_exercise_question_#{exercise_question.id}"}) do |f|%>

        实训题

        -

        <%= exercise_question.shixun.name %>

        +

        + + +

      • diff --git a/app/views/exercise/_exercise_form.html.erb b/app/views/exercise/_exercise_form.html.erb index 677e7014..bee149fd 100644 --- a/app/views/exercise/_exercise_form.html.erb +++ b/app/views/exercise/_exercise_form.html.erb @@ -106,11 +106,15 @@ //修改标题时确定按钮 function edit_poll_question(doc,id,quest_type) { + var name = $.trim($("#poll_questions_name_" + id).val()); var title = $.trim($("#poll_questions_title_" + id).val()); var score = $.trim($("#poll_question_score_"+ id).val()); var standard_ans = $.trim($("#exercise_choice_" + id).val()); + if(name===""){ + notice_box("题目标题不能为空"); + } if(title.length == 0 || score.length == 0){ - notice_box("题目标题/分数不能为空"); + notice_box("要求/分数不能为空"); }else if(!/^[1-9][0-9]*$/.test(score)) { notice_box("分数必须是非零开头的数字"); }else if(quest_type !=3 && quest_type !=4 && standard_ans.length == 0) { diff --git a/app/views/exercise/_exercise_student.html.erb b/app/views/exercise/_exercise_student.html.erb index add9d655..ec47f1c0 100644 --- a/app/views/exercise/_exercise_student.html.erb +++ b/app/views/exercise/_exercise_student.html.erb @@ -162,7 +162,7 @@ <% end %> <% if exercise_question.question_type == 5 %> -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <% end %>
        <%= exercise_question.question_title.html_safe %>
        <% case exercise_question.question_type %> diff --git a/app/views/exercise/_exercise_student_result.html.erb b/app/views/exercise/_exercise_student_result.html.erb index 0dd656be..6d48573f 100644 --- a/app/views/exercise/_exercise_student_result.html.erb +++ b/app/views/exercise/_exercise_student_result.html.erb @@ -140,7 +140,7 @@ <% end %> <% if exercise_question.question_type == 5 %> -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <% end %>
        <%= exercise_question.question_title.html_safe %>
        <% case exercise_question.question_type %> diff --git a/app/views/exercise/_new_shixun.html.erb b/app/views/exercise/_new_shixun.html.erb index 1cff068f..6ce2cd68 100644 --- a/app/views/exercise/_new_shixun.html.erb +++ b/app/views/exercise/_new_shixun.html.erb @@ -8,7 +8,10 @@ -

        <%= @shixun.name %>

        +

        + + +

      • diff --git a/app/views/exercise/_show_MC.html.erb b/app/views/exercise/_show_MC.html.erb index 8461374a..1f74be73 100644 --- a/app/views/exercise/_show_MC.html.erb +++ b/app/views/exercise/_show_MC.html.erb @@ -20,7 +20,11 @@ <% exercise_question.exercise_choices.reorder("choice_position").each_with_index do |exercise_choice,index| %>
      • - +
      • <% end %> diff --git a/app/views/exercise/_show_MCQ.html.erb b/app/views/exercise/_show_MCQ.html.erb index e1767b3b..57c36496 100644 --- a/app/views/exercise/_show_MCQ.html.erb +++ b/app/views/exercise/_show_MCQ.html.erb @@ -20,7 +20,11 @@ <% exercise_question.exercise_choices.reorder("choice_position").each_with_index do |exercise_choice,index| %>
      • - +
      • <% end %> diff --git a/app/views/exercise/_show_shixun.html.erb b/app/views/exercise/_show_shixun.html.erb index 92feef9d..75f460ec 100644 --- a/app/views/exercise/_show_shixun.html.erb +++ b/app/views/exercise/_show_shixun.html.erb @@ -16,7 +16,7 @@

        <% end %> -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <%= exercise_question.question_title.html_safe %>
        <% exercise_question.exercise_shixun_challenges.each_with_index do |exercise_challenge,index| %> diff --git a/app/views/exercise/student_exercise_list.html.erb b/app/views/exercise/student_exercise_list.html.erb index 3632b4d7..b8335515 100644 --- a/app/views/exercise/student_exercise_list.html.erb +++ b/app/views/exercise/student_exercise_list.html.erb @@ -256,7 +256,7 @@ <% end %>
        <% if exercise_question.question_type == 5 %> -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <% end %>
        <%= exercise_question.question_title.html_safe %> diff --git a/app/views/exercise_bank/_edit_shixun.html.erb b/app/views/exercise_bank/_edit_shixun.html.erb index 41383767..7aa84e9f 100644 --- a/app/views/exercise_bank/_edit_shixun.html.erb +++ b/app/views/exercise_bank/_edit_shixun.html.erb @@ -1,7 +1,10 @@ <%= form_for("",:url => update_exercise_question_exercise_bank_index_path(:exercise_question => exercise_question.id),:html => {:id => "update_exercise_question_#{exercise_question.id}"}) do |f|%>

        实训题

        -

        <%= exercise_question.shixun.name %>

        +

        + + +

      • diff --git a/app/views/exercise_bank/_new_shixun.html.erb b/app/views/exercise_bank/_new_shixun.html.erb index 36af84ad..140ee9b2 100644 --- a/app/views/exercise_bank/_new_shixun.html.erb +++ b/app/views/exercise_bank/_new_shixun.html.erb @@ -8,7 +8,10 @@ -

        <%= @shixun.name %>

        +

        + + +

      • diff --git a/app/views/exercise_bank/_show_shixun.html.erb b/app/views/exercise_bank/_show_shixun.html.erb index cf2a9b2b..e426fd0e 100644 --- a/app/views/exercise_bank/_show_shixun.html.erb +++ b/app/views/exercise_bank/_show_shixun.html.erb @@ -14,7 +14,7 @@

      • -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <%= exercise_question.question_title.html_safe %>
        <% exercise_question.exercise_bank_shixun_challenges.each_with_index do |exercise_challenge,index| %> diff --git a/app/views/exercise_bank/show.html.erb b/app/views/exercise_bank/show.html.erb index 0fb5e2ca..14712a92 100644 --- a/app/views/exercise_bank/show.html.erb +++ b/app/views/exercise_bank/show.html.erb @@ -80,7 +80,7 @@ <% end %>
        <% if exercise_question.question_type == 5 %> -

        <%= exercise_question.shixun.name %>

        +

        <%= exercise_question.shixun_name %>

        <% end %>
        <%= exercise_question.question_title.html_safe %>
        <% case exercise_question.question_type %> diff --git a/app/views/homework_bank/_send_homework_bank.html.erb b/app/views/homework_bank/_send_homework_bank.html.erb index 3127aecd..6b935521 100644 --- a/app/views/homework_bank/_send_homework_bank.html.erb +++ b/app/views/homework_bank/_send_homework_bank.html.erb @@ -31,4 +31,17 @@
        - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/views/homework_common/_homework_index_list.html.erb b/app/views/homework_common/_homework_index_list.html.erb index 884fd0b9..bcc9bae8 100644 --- a/app/views/homework_common/_homework_index_list.html.erb +++ b/app/views/homework_common/_homework_index_list.html.erb @@ -11,7 +11,8 @@
        # <%= get_hw_index(homework_common, @is_teacher, @homework_type) + 1 %> <% homework_curr_status = homework_curr_time(homework_common) %> - <%= link_to homework_common.name.to_s, student_work_index_path(:homework => homework_common.id,:host=> Setting.host_course), :class => "edu-class-inner-list fl color-grey-3"%> + <%= link_to homework_common.name.to_s, student_work_index_path(:homework => homework_common.id,:host=> Setting.host_course), + :id => "homework_name_#{homework_common.id}", :class => "edu-class-inner-list fl color-grey-3"%> <% unless homework_common.is_public %> <% end %> @@ -144,6 +145,9 @@
      • <%= link_to "设置", student_work_index_path(:homework => homework_common.id, :tab => 4) %>
      • +
      • + <%= link_to "重命名", rename_modal_homework_common_path(homework_common), :remote => true %> +
      • <% if homework_common.homework_detail_manual.try(:comment_status) == 0 %>
      • <%= link_to '立即发布', publish_notice_homework_common_path(homework_common), :remote => true %> diff --git a/app/views/homework_common/_rename_shixun_homework.html.erb b/app/views/homework_common/_rename_shixun_homework.html.erb new file mode 100644 index 00000000..78f8eb27 --- /dev/null +++ b/app/views/homework_common/_rename_shixun_homework.html.erb @@ -0,0 +1,30 @@ +
        +
        + 重命名 +
        +
        + <%= form_for "", :url => rename_homework_homework_common_path(@homework), :remote => true, :html => {:id => "rename_shixun_homework_form"} do |f| %> +
        + 作业名称: +
        + +

        请输入作业名称

        +
        +
        + <% end %> +
      • + 取消 + 确定 +
      • +
        + + \ No newline at end of file diff --git a/app/views/homework_common/rename_homework.js.erb b/app/views/homework_common/rename_homework.js.erb new file mode 100644 index 00000000..1022f747 --- /dev/null +++ b/app/views/homework_common/rename_homework.js.erb @@ -0,0 +1,5 @@ +<% if @notice %> + notice_box("作业名称不能为空"); +<% else %> + $("#homework_name_<%= @homework.id %>").html(<%= @homework.name %>); +<% end %> \ No newline at end of file diff --git a/app/views/homework_common/rename_modal.js.erb b/app/views/homework_common/rename_modal.js.erb new file mode 100644 index 00000000..e691dff3 --- /dev/null +++ b/app/views/homework_common/rename_modal.js.erb @@ -0,0 +1,2 @@ +var html = '<%= escape_javascript(render :partial => "homework_common/rename_shixun_homework") %>'; +pop_box_new(html, 460, 227); \ No newline at end of file diff --git a/app/views/layouts/base_ec.html.erb b/app/views/layouts/base_ec.html.erb index 0e1c6279..10113aa8 100644 --- a/app/views/layouts/base_ec.html.erb +++ b/app/views/layouts/base_ec.html.erb @@ -9,7 +9,13 @@ <%= favicon %> <%= javascript_heads %> <%= heads_for_theme %> - <%= javascript_include_tag 'educoder/edu_application', 'educoder/edu_shixun','educoder/edu_shixunCommentsStar','educoder/jquery.raty' %> + <%= stylesheet_link_tag "/assets/codemirror/codemirror" %> + <%= stylesheet_link_tag '/editormd/css/editormd.min.css' %> + + <%= javascript_include_tag '/editormd/lib/marked.min.js', '/editormd/lib/prettify.min.js', '/editormd/lib/raphael.min.js', '/editormd/lib/underscore.min.js', '/editormd/lib/sequence-diagram.min.js', + '/editormd/lib/flowchart.min.js', '/editormd/lib/jquery.flowchart.min.js', '/editormd/editormd.js' %> + + <%= javascript_include_tag 'educoder/edu_application', 'educoder/edu_shixun','educoder/edu_shixunCommentsStar','educoder/jquery.raty'%> <%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2','css/edu-popup','css/edu-common','educoder/edu-main','educoder/edu-all', "css/edu-public", 'css/ketang', 'css/common', 'css/taskstyle', 'css/structure','scm','css/public', 'css/project','css/popup','repository','css/gantt', 'css/calendar', 'css/moduel', 'css/font-awesome', 'css/edu-tooltipster', 'educoder/magic-check','/assets/iconfont/iconfont.css' %> <%= call_hook :view_layouts_base_html_head %> diff --git a/app/views/layouts/base_edu.html.erb b/app/views/layouts/base_edu.html.erb index 2638a1df..06fa90b9 100644 --- a/app/views/layouts/base_edu.html.erb +++ b/app/views/layouts/base_edu.html.erb @@ -24,7 +24,8 @@ <%= javascript_include_tag '/editormd/lib/marked.min.js', '/editormd/lib/prettify.min.js', '/editormd/lib/raphael.min.js', '/editormd/lib/underscore.min.js', '/editormd/lib/sequence-diagram.min.js', '/editormd/lib/flowchart.min.js', '/editormd/lib/jquery.flowchart.min.js', '/editormd/editormd.js' %> <%= yield :header_tags -%> - + <% Rails.logger.info("########----current_user: #{User.current.id}") %> + <% Rails.logger.info("########----session: #{session[:user_id]}") %> diff --git a/app/views/managements/_subject_level_list.html.erb b/app/views/managements/_subject_level_list.html.erb index 1a4bf6d7..0988bd6e 100644 --- a/app/views/managements/_subject_level_list.html.erb +++ b/app/views/managements/_subject_level_list.html.erb @@ -1,3 +1,6 @@ + diff --git a/app/views/managements/classroom_classment.html.erb b/app/views/managements/classroom_classment.html.erb index 06ea072d..f9417d74 100644 --- a/app/views/managements/classroom_classment.html.erb +++ b/app/views/managements/classroom_classment.html.erb @@ -14,6 +14,7 @@ diff --git a/app/views/managements/evaluate_simple.html.erb b/app/views/managements/evaluate_simple.html.erb index cecfe4a9..6d05aedf 100644 --- a/app/views/managements/evaluate_simple.html.erb +++ b/app/views/managements/evaluate_simple.html.erb @@ -1,54 +1,30 @@ -<% if false %> - -
        -
        -

        耗时详情

        - -
        -
        -
          -
        1. 总耗时:<%= @consume_time %>
        2. -
        3. 作品更新:<%= @student_work %>
        4. -
        5. 文件更新:<%= @file_update %>
        6. -
        7. 中间层总耗时:<%= @brige %>
        8. -
        9. pull代码:<%= @git_pull %>
        10. -
        11. pod启动:<%= @create_pod %>
        12. -
        13. pod执行:<%= @pod_execute %>
        14. -
        15. 中间层回传:<%= @return_back %>--(中间层出结果传Educoder)
        16. -
        17. 前端轮询:<%= @front_js %>--(局部数据查询,Js轮询)
        18. -
        19. 回调结果存储:<%= @test_cases %>
        20. -
        -
        -
        -<% end %> - <% if @recodes.present? %>
        等级
        - - + + - + - - - + + + + + - <% @recodes.each_with_index do |record, index| %> + <% @recodes.each do |record| %> - + @@ -60,6 +36,8 @@ + + <% end %> diff --git a/app/views/managements/graduation_standard.html.erb b/app/views/managements/graduation_standard.html.erb index c61e6bff..a667c7c2 100644 --- a/app/views/managements/graduation_standard.html.erb +++ b/app/views/managements/graduation_standard.html.erb @@ -1,16 +1,18 @@

        毕业要求通用标准<%= @standards.count %>

        -

        + 新增

        -
        -

        - *1 - -

        -

        - 取消 - 保存 -

        -
        + <% if User.current.admin? %> +

        + 新增

        +
        +

        + *1 + +

        +

        + 取消 + 保存 +

        +
        + <% end %>
        序号总耗时ID总耗时 作品更新 文件更新 中间层总耗时 pull代码 pod启动 pod执行中间层回传回传时间 前端轮询回调结果存储创建时间实训名称结果存储创建时间最大执行时间唯一标识实训名称
        <%= index %><%= record.id %> <%= record.consume_time %> <%= record.student_work %> <%= record.file_update %><%= record.front_js %> <%= record.test_cases %> <%= format_time record.created_at %><%= record.shixun.try(:exec_time) %><%= record.shixun.try(:identifier) %> <%= link_to record.shixun.try(:name), task_path(record.game), :target => "_blank", :title => "#{record.shixun.try(:name)}" %>
        diff --git a/app/views/managements/schools/_contrast_search_form.html.erb b/app/views/managements/schools/_contrast_search_form.html.erb index 4d24a810..b77f2dbb 100644 --- a/app/views/managements/schools/_contrast_search_form.html.erb +++ b/app/views/managements/schools/_contrast_search_form.html.erb @@ -12,7 +12,7 @@
        <%= text_field_tag :grow_date_input, params[:grow_date_input], - class: 'grow-date-input winput-220-30', placeholder: '请选择时间段', + class: 'grow-date-input winput-220-30', placeholder: '请选择时间段(具体从当日5:00开始计算)', style: 'width: 400px;' %>
        @@ -26,13 +26,10 @@
        <%= hidden_field_tag :data_type, params[:data_type] || 'grow' %> - <% if params[:data_type] == 'contrast' %> - 时间对比 - 新增数据 - <% else %> - 时间对比 - 新增数据 - <% end %> + 时段对比 + 数据变化
        <%= text_field_tag :keyword, params[:keyword], placeholder: '请输入单位名称或者ID关键字进行搜索', diff --git a/app/views/managements/schools/_data_contrast_list.html.erb b/app/views/managements/schools/_data_contrast_list.html.erb index d77d4b70..c25a8bc4 100644 --- a/app/views/managements/schools/_data_contrast_list.html.erb +++ b/app/views/managements/schools/_data_contrast_list.html.erb @@ -21,8 +21,8 @@
        - - + + - + <% if report['total'].zero? %> + + <% else %> + + <% end %> <% elsif increase.zero? %>
        序号 ID 单位名称时段一
        <%= "(#{params[:begin_date]}至#{params[:end_date]})" %>
        时段二
        <%= "(#{params[:other_begin_date]}至#{params[:other_end_date]})" %>
        时段一
        <%= "(#{params[:begin_date]} 05:00至#{(Time.zone.parse(params[:end_date]) + 1.days).strftime('%Y-%m-%d')} 05:00)" %>
        时段二
        <%= "(#{params[:other_begin_date]} 05:00至#{(Time.zone.parse(params[:other_end_date]) + 1.days).strftime('%Y-%m-%d')} 05:00)" %>
        <%= sort_tag('变化情况', name: 'percentage', path: school_data_contrast_managements_path) %>
        ( 新 增 数 | 新增百分比) @@ -45,7 +45,11 @@
        +<%= increase %> +<%= percentage.round(5) %>%-+<%= percentage.round(5) %>% <%= increase %> diff --git a/app/views/managements/schools/_data_grow_list.html.erb b/app/views/managements/schools/_data_grow_list.html.erb index 27a1ccf3..af1fc200 100644 --- a/app/views/managements/schools/_data_grow_list.html.erb +++ b/app/views/managements/schools/_data_grow_list.html.erb @@ -1,7 +1,7 @@
        统计总计: <% if params[:grow_begin_date].present? %> - <%= params[:grow_date_input] %> + <%= params[:grow_begin_date] %> 05:00至<%= (Time.zone.parse(params[:grow_end_date]) + 1.days).strftime('%Y-%m-%d') %> 05:00 <% else %> <%= (Time.current - 5.hour).beginning_of_day.ago(1.days).strftime('%Y-%m-%d') %> 05:00至 <%= (Time.current - 5.hour).beginning_of_day.strftime('%Y-%m-%d') %> 05:00, @@ -10,7 +10,11 @@ 新增学生<%= @grow_summary.student_increase_count || 0 %>人, 新增课堂<%= @grow_summary.course_increase_count || 0 %>个, 新增实训<%= @grow_summary.shixun_increase_count || 0 %>个, - 活跃用户<%= @grow_summary.active_user_count || 0 %>个 + 新增实训作业<%= @grow_summary.shixun_homework_count || 0 %>个, + 新增实训评测<%= @grow_summary.shixun_evaluate_count || 0 %>个, + 活跃用户 + <%= @grow_summary.uniq_active_user_count.to_i.zero? ? @grow_summary.active_user_count.to_i : @grow_summary.uniq_active_user_count.to_i %> +
        @@ -23,7 +27,9 @@ - + + + @@ -36,7 +42,9 @@ - + + + <% end %> diff --git a/app/views/managements/schools/_statistics_list.html.erb b/app/views/managements/schools/_statistics_list.html.erb index 53c13ed8..7fb6300d 100644 --- a/app/views/managements/schools/_statistics_list.html.erb +++ b/app/views/managements/schools/_statistics_list.html.erb @@ -3,12 +3,17 @@ - + + + @@ -24,6 +29,8 @@ + + diff --git a/app/views/managements/schools/statistics.html.erb b/app/views/managements/schools/statistics.html.erb index 3aba8ab1..1f0d2d36 100644 --- a/app/views/managements/schools/statistics.html.erb +++ b/app/views/managements/schools/statistics.html.erb @@ -21,8 +21,10 @@ 学生总人数<%= @student_total %>人, 课堂总数<%= @course_total %>个, 正在进行课堂总数<%= @active_course_total %>个, + 实训总数<%= @shixun_total %>个, + 实训评测总数<%= @shixun_evaluate_total %>个, 实训作业总数<%= @shixun_homework_total %>个, - 其它作业总数<%= @other_homework_total %>个, + 其它作业总数<%= @other_homework_total %>个 diff --git a/app/views/managements/schools/statistics_xlsx.xlsx.axlsx b/app/views/managements/schools/statistics_xlsx.xlsx.axlsx index a451586d..96470019 100644 --- a/app/views/managements/schools/statistics_xlsx.xlsx.axlsx +++ b/app/views/managements/schools/statistics_xlsx.xlsx.axlsx @@ -1,11 +1,12 @@ wb = xlsx_package.workbook wb.add_worksheet(name: '统计总表') do |sheet| - sheet.add_row %w(ID 单位名称 教师总人数 学生总人数 课堂总数 正在进行课堂数 实训作业总数 其它作业总数 动态时间) + sheet.add_row %w(ID 单位名称 教师总人数 学生总人数 课堂总数 正在进行课堂数 总实训数 实训评测总数 实训作业总数 其它作业总数 动态时间) @schools.each do |school| sheet.add_row([ school[:id].to_s, school[:name].to_s, (school[:teacher_count] || 0).to_s, (school[:student_count] || 0).to_s, - (school[:course_count] || 0).to_s, (school[:active_course_count] || 0).to_s, (school[:homework_count] || 0).to_s, + (school[:course_count] || 0).to_s, (school[:active_course_count] || 0).to_s, + (school[:shixun_count] || 0).to_s,(school[:shixun_evaluate_count] || 0).to_s, (school[:homework_count] || 0).to_s, (school[:other_homework_count] || 0).to_s, format_time(school[:nearly_course_time]) ]) end diff --git a/app/views/managements/update_user.html.erb b/app/views/managements/update_user.html.erb index a2ad1369..4ef8e9e6 100644 --- a/app/views/managements/update_user.html.erb +++ b/app/views/managements/update_user.html.erb @@ -21,11 +21,11 @@ 粉丝<%= @user_fanlist_count %> - + 金币 <%= @user.grade %> - + 经验值 <%= @user.experience %> diff --git a/app/views/managements/users_trial.html.erb b/app/views/managements/users_trial.html.erb index b872ca87..23908eff 100644 --- a/app/views/managements/users_trial.html.erb +++ b/app/views/managements/users_trial.html.erb @@ -19,20 +19,20 @@
        - - - @@ -41,6 +41,8 @@ + <%= select_tag :province, options_for_select(School.provinces.unshift(['请选择地区', ''])), class: 'fr winput-200-40'%> +

        真实姓名搜索

        diff --git a/app/views/shixuns/_form.html.erb b/app/views/shixuns/_form.html.erb index 53d38a63..337ecee2 100644 --- a/app/views/shixuns/_form.html.erb +++ b/app/views/shixuns/_form.html.erb @@ -156,7 +156,7 @@
        - <% if Redmine::Configuration['gitlab_address'].include?("test") %> + <% if User.current.admin? %>

        VNC图形化

      • diff --git a/app/views/shixuns/_settings_edit.html.erb b/app/views/shixuns/_settings_edit.html.erb index 6ebbf633..6ebd6138 100644 --- a/app/views/shixuns/_settings_edit.html.erb +++ b/app/views/shixuns/_settings_edit.html.erb @@ -211,7 +211,7 @@
      • - <% if Redmine::Configuration['gitlab_address'].include?("test") %> + <% if User.current.admin? %>
        VNC图形化: diff --git a/app/views/shixuns/_settings_show.html.erb b/app/views/shixuns/_settings_show.html.erb index 92417f49..72752703 100644 --- a/app/views/shixuns/_settings_show.html.erb +++ b/app/views/shixuns/_settings_show.html.erb @@ -1,3 +1,4 @@ +
        配置 diff --git a/app/views/student_work/index.html.erb b/app/views/student_work/index.html.erb index 99384dfc..0e66401c 100644 --- a/app/views/student_work/index.html.erb +++ b/app/views/student_work/index.html.erb @@ -199,14 +199,11 @@ 不限 > - + > - + > - +
      • diff --git a/app/views/subjects/_subject_item.html.erb b/app/views/subjects/_subject_item.html.erb index 3dbc3605..10a9ce93 100644 --- a/app/views/subjects/_subject_item.html.erb +++ b/app/views/subjects/_subject_item.html.erb @@ -6,7 +6,7 @@ <% if params[:controller] != "welcome" && subject.status < 2 && !User.current.member_of_subject?(subject) %>
        -

        暂未开发

        +

        暂未公开

        <% end %> <%= image_tag(url_to_avatar(subject)) %> diff --git a/app/views/trainings/pay.html.erb b/app/views/trainings/pay.html.erb index 573de6fe..2c384e27 100644 --- a/app/views/trainings/pay.html.erb +++ b/app/views/trainings/pay.html.erb @@ -46,7 +46,7 @@

        发票内容 + value="<%= @training.training_payinfo.try(:invoice_content).presence || '师资培训费' %>"/>

      • @@ -61,7 +61,7 @@ (3人及以上8折优惠) <% end %>

        -

        含会议注册费、场地费、培训费、教材资料费、餐费、专家差率费等

        +

        含会议注册费、场地费、培训费、教材资料费、餐费、专家差旅费等

        @@ -143,10 +143,11 @@ // 2 支付宝支付 // 3 银行卡支付 // payType: <%#= @training.training_payinfo.pay_type.to_i %>, + newPayinfo: <%= @training.training_payinfo.new_record? %>, payType: 3, //发票抬头 //为空则代表不需要发票 - invoiceTitle: '<%= @training.training_payinfo.invoice_title %>', + invoiceTitle: '<%= @training.training_payinfo.invoice_title || @training.school %>', //税号 invoiceNo: '<%= @training.training_payinfo.invoice_no %>' }; @@ -172,9 +173,8 @@ //延迟支付,直接提交 $('#delayPayBtn').on('click', function () { - if($("#billDemand").attr("status")==2){ - $(".billInput").val(''); - } + if(!checkBillInfo()){ return } + alert("报名成功,请尽快支付"); $('form').submit(); }); @@ -184,10 +184,8 @@ }) //立即支付 $('#payBtn').on('click', function () { + if(!checkBillInfo()){ return } - if($("#billDemand").attr("status")==2){ - $(".billInput").val(''); - } var postData = $('form').serialize(); postData += '&js=true' console.log(postData); @@ -236,15 +234,12 @@ //线下支付提交 $('#submitFormBtn').on('click', function () { - if($("#billDemand").attr("status")==2){ - $(".billInput").val(''); - } + if(!checkBillInfo()){ return } $('form').submit(); }); $('#laterSubmitFormBtn').on('click', function () { - if($("#billDemand").attr("status")==2){ - $(".billInput").val(''); - } + if(!checkBillInfo()){ return } + $('#offline_later_pay').val('true'); $('form').submit(); }); @@ -304,15 +299,17 @@ } //页面加载时,初始化发票类型 function InitBill(userInfo){ - var index=2; - $("#billDemand").html("不需要").attr("status",2); - if(userInfo.invoiceTitle != "" && userInfo.invoiceNo != ""){ - index=0; - $("#billDemand").html("单位").attr("status",0); - } - if(userInfo.invoiceTitle != "" && userInfo.invoiceNo == ""){ + var index=0; + $("#billDemand").html("单位").attr("status",0); + if (!userInfo.newPayinfo) { + if(userInfo.invoiceTitle == "" && userInfo.invoiceNo == ""){ + index=2; + $("#billDemand").html("不需要").attr("status",2); + } + if(userInfo.invoiceTitle != "" && userInfo.invoiceNo == ""){ index=1; $("#billDemand").html("个人").attr("status",1); + } } $(".billType li").removeClass("active"); $(".billType li").eq(index).addClass("active"); @@ -379,36 +376,62 @@ var unit = $(".billUnit").val(); var tax = $(".taxNumber").val(); //只有选择了单位时才需要判断三个是否都已经填写 + if (type == "单位" || type == "个人") { + if (unit == "") { + $(".billUnit").addClass("nullVal"); + return; + } else { + $(".billUnit").removeClass("nullVal"); + } + } if (type == "单位") { - if (unit == "") { - $(".billUnit").addClass("nullVal"); - return; - } else { - $(".billUnit").removeClass("nullVal"); - } - if (tax == "") { - $(".taxNumber").addClass("nullVal"); - return; - } else { - $(".taxNumber").removeClass("nullVal"); - } + if (tax == "") { + $(".taxNumber").addClass("nullVal"); + return; + } else { + $(".taxNumber").removeClass("nullVal"); + } } //选择单位或者个人都要判断是否填写了发票内容 - if (type == "单位" || type == "个人") { - var remark = $("input[name='invoice_content']").val(); - if (remark == "") { - $("input[name='invoice_content']").addClass("nullVal"); - return; - } else { - $("input[name='invoice_content']").removeClass("nullVal"); - } - } + // if (type == "单位" || type == "个人") { + // var remark = $("input[name='invoice_content']").val(); + // if (remark == "") { + // $("input[name='invoice_content']").addClass("nullVal"); + // return; + // } else { + // $("input[name='invoice_content']").removeClass("nullVal"); + // } + // } $("#billDemand").html(type); //记录选中的发票类型 $("#billDemand").attr("status",$(".billType li.active").index()); hideNav($(".billDownNav")); } + function checkBillInfo() { + var bill = $("#billLine"); + var billNav = $(".billDownNav"); + var status = $("#billDemand").attr("status"); + if(status == 2){ + $(".billInput").val(''); + } + + var billUnit = $('.billUnit').val(); + var taxNumber = $('.taxNumber').val(); + if(status == 1 && billUnit == ''){ + alert('请将发票信息填写完整'); + showNav(bill, billNav, "down"); + return false; + } + if(status == 0 && (billUnit == '' || taxNumber == '')){ + alert('请将发票信息填写完整'); + showNav(bill, billNav, "down"); + return false; + } + + return true; + } + function InitPhoto() { var tmpl = '

      • ', $gallery = $("#gallery"), $galleryImg = $("#galleryImg"), diff --git a/app/views/users/_course_exercise.html.erb b/app/views/users/_course_exercise.html.erb index 2193ff4d..fadf9bb7 100644 --- a/app/views/users/_course_exercise.html.erb +++ b/app/views/users/_course_exercise.html.erb @@ -28,7 +28,7 @@ <%= link_to '立即发布', publish_notice_exercise_path(activity), :remote => true %> <% end %> - <% if (activity.exercise_status == 2 && activity.end_time > Time.now) || activity.exercise_group_settings.where("publish_time < '#{Time.now}' and end_time > '#{Time.now}'").count > 0 %> + <% if (activity.exercise_status == 2 && (activity.end_time.blank? || activity.end_time > Time.now)) || activity.exercise_group_settings.where("publish_time < '#{Time.now}' and end_time > '#{Time.now}'").count > 0 %>
      • <%= link_to '立即截止', end_notice_exercise_path(activity), :remote => true %>
      • diff --git a/app/views/users/_course_item.html.erb b/app/views/users/_course_item.html.erb index 73c33893..e474a117 100644 --- a/app/views/users/_course_item.html.erb +++ b/app/views/users/_course_item.html.erb @@ -1,5 +1,5 @@ <% objects.each do |object| %> - <% allow_visit = object.is_public == 1 || User.current.admin? || User.current.member_of_course?(object) %> + <% allow_visit = object.is_public == 1 || User.current.admin? || User.current.member_of_course?(object) || User.current.business? %>
        <% if object.is_public == 1 %>
        diff --git a/app/views/users/_l_course.html.erb b/app/views/users/_l_course.html.erb index 1a16703f..b7dcf029 100644 --- a/app/views/users/_l_course.html.erb +++ b/app/views/users/_l_course.html.erb @@ -46,7 +46,7 @@ <%#= render :partial => "users/course_item", :locals => {:objects => @objects} %> <% @objects.each do |object| %> - <% allow_visit = @show_all || object.is_public == 1 || User.current.member_of_course?(object) %> + <% allow_visit = @show_all || object.is_public == 1 || User.current.member_of_course?(object) || User.current.business? %>
        <% if object.is_public == 1 %>
        diff --git a/config/locales/school_daily_reports/zh.yml b/config/locales/school_daily_reports/zh.yml index 57caf343..c622a21f 100644 --- a/config/locales/school_daily_reports/zh.yml +++ b/config/locales/school_daily_reports/zh.yml @@ -4,4 +4,6 @@ zh: student_increase_count: 新增学生 course_increase_count: 新增课堂 shixun_increase_count: 新增实训 + shixun_homework_count: 新增实训作业 + shixun_evaluate_count: 新增实训评测 active_user_count: 活跃用户 \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e4dfe08d..137a1231 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1103,6 +1103,8 @@ RedmineApp::Application.routes.draw do ## oauth相关 match 'move_to_category', :via => [:get,:post] match 'homework_code_repeat', :via => [:get,:post] get 'review_detail' + post 'rename_homework' + get 'rename_modal' end collection do diff --git a/db/migrate/20190525060616_modify_exec_time_for_shixun.rb b/db/migrate/20190525060616_modify_exec_time_for_shixun.rb new file mode 100644 index 00000000..a5602ca8 --- /dev/null +++ b/db/migrate/20190525060616_modify_exec_time_for_shixun.rb @@ -0,0 +1,8 @@ +class ModifyExecTimeForShixun < ActiveRecord::Migration + def up + change_column(:shixuns, :exec_time, :integer, :default => 20) + end + + def down + end +end diff --git a/db/migrate/20190528013018_migrate_course_school_id.rb b/db/migrate/20190528013018_migrate_course_school_id.rb new file mode 100644 index 00000000..b0669591 --- /dev/null +++ b/db/migrate/20190528013018_migrate_course_school_id.rb @@ -0,0 +1,11 @@ +class MigrateCourseSchoolId < ActiveRecord::Migration + def up + courses = Course.includes(teacher: :user_extensions).where("courses.school_id != user_extensions.school_id or courses.school_id is null") + courses.each do |course| + course.update_column('school_id', course.teacher.try(:user_extensions).try(:school_id)) + end + end + + def down + end +end diff --git a/db/migrate/20190528075558_create_user_sources.rb b/db/migrate/20190528075558_create_user_sources.rb new file mode 100644 index 00000000..03f6c12a --- /dev/null +++ b/db/migrate/20190528075558_create_user_sources.rb @@ -0,0 +1,15 @@ +class CreateUserSources < ActiveRecord::Migration + def change + create_table :user_sources do |t| + t.string :type + t.integer :user_id + t.string :uuid + t.string :name + + t.timestamps + end + + add_index :user_sources, [:type, :uuid], unique: true + add_index :user_sources, :user_id + end +end diff --git a/db/migrate/20190529014121_add_shixun_name_to_ex_question.rb b/db/migrate/20190529014121_add_shixun_name_to_ex_question.rb new file mode 100644 index 00000000..8aa02878 --- /dev/null +++ b/db/migrate/20190529014121_add_shixun_name_to_ex_question.rb @@ -0,0 +1,14 @@ +class AddShixunNameToExQuestion < ActiveRecord::Migration + def change + add_column :exercise_questions, :shixun_name, :string + add_column :exercise_bank_questions, :shixun_name, :string + + ExerciseQuestion.where(question_type: 5).each do |question| + question.update_column("shixun_name", question.shixun.try(:name)) + end + + ExerciseBankQuestion.where(question_type: 5).each do |question| + question.update_column("shixun_name", question.shixun.try(:name)) + end + end +end diff --git a/db/migrate/20190530025028_migrate_homework_end_time.rb b/db/migrate/20190530025028_migrate_homework_end_time.rb new file mode 100644 index 00000000..cff8d8d8 --- /dev/null +++ b/db/migrate/20190530025028_migrate_homework_end_time.rb @@ -0,0 +1,93 @@ +class MigrateHomeworkEndTime < ActiveRecord::Migration + def up + homework = HomeworkCommon.where(id: 18615).first + if homework.present? + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '#{homework.end_time}'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + + homework = HomeworkCommon.where(id: 18614).first + if homework.present? + homework.update_column('end_time', '2019-05-20 00:00:00') + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '2019-05-20 00:00:00'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + + homework = HomeworkCommon.where(id: 18617).first + if homework.present? + homework.update_column('end_time', '2019-05-29 00:00:00') + homework.save + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '2019-05-29 00:00:00'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + + homework = HomeworkCommon.where(id: 18616).first + if homework.present? + homework.update_column('end_time', '2019-06-10 00:00:00') + homework.save + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '2019-06-10 00:00:00'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + + homework = HomeworkCommon.where(id: 25901).first + if homework.present? + homework.update_column('end_time', '2019-06-16 00:00:00') + homework.save + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '2019-06-16 00:00:00'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + + homework = HomeworkCommon.where(id: 25902).first + if homework.present? + homework.update_column('end_time', '2019-06-17 00:00:00') + homework.save + transaction do + homework.student_works.where("work_status = 2 and commit_time is not null and commit_time <= '2019-06-17 00:00:00'").each do |work| + work.work_status = 1 + work.late_penalty = 0 + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + end + + def down + end +end diff --git a/db/migrate/20190530050358_migrate_shixun_student_work_score_2.rb b/db/migrate/20190530050358_migrate_shixun_student_work_score_2.rb new file mode 100644 index 00000000..4eb869b4 --- /dev/null +++ b/db/migrate/20190530050358_migrate_shixun_student_work_score_2.rb @@ -0,0 +1,31 @@ +class MigrateShixunStudentWorkScore2 < ActiveRecord::Migration + def up + homeworks = HomeworkCommon.where(id: [18615, 18614, 18617, 18616, 25901, 25902]) + homeworks.each do |homework| + transaction do + homework.student_works.where("work_status > 0").each do |work| + if homework.end_time > Time.now + work.work_status = 1 + work.late_penalty = 0 + else + myshixun = work.myshixun + + if myshixun.status == 1 && myshixun.try(:done_time) < homework.end_time + work.work_status = 1 + work.late_penalty = 0 + else + work.work_status = 2 + work.late_penalty = homework.late_penalty + end + end + score = work.final_score.to_f + work.eff_score.to_f - work.late_penalty.to_f + work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless work.ultimate_score + work.save + end + end + end + end + + def down + end +end diff --git a/db/migrate/20190530055732_add_evaluate_count_to_shixuns.rb b/db/migrate/20190530055732_add_evaluate_count_to_shixuns.rb new file mode 100644 index 00000000..7bd6dcd1 --- /dev/null +++ b/db/migrate/20190530055732_add_evaluate_count_to_shixuns.rb @@ -0,0 +1,24 @@ +class AddEvaluateCountToShixuns < ActiveRecord::Migration + def up + add_column :shixuns, :evaluate_count, :integer, default: 0 + + # limit = 100 + # total = Shixun.count + # + # ((total / 100) + 1).times do |index| + # shixun_ids = Shixun.order(:id).limit(limit).offset(index * limit).pluck(:id) + # return if shixun_ids.blank? + # + # count_map = Game.joins(:challenge).where(challenges: { shixun_id: shixun_ids }).group('shixun_id').sum(:evaluate_count) + # + # id_str = count_map.keys.join(',') + # str = count_map.map { |shixun_id, count| "WHEN #{shixun_id} THEN #{count}" }.join(' ') + # + # execute "UPDATE shixuns SET evaluate_count = CASE id #{str} END WHERE id IN (#{id_str})" + # end + end + + def down + remove_column :shixuns, :evaluate_count + end +end diff --git a/db/migrate/20190530081655_add_columns_to_school_daily_reports.rb b/db/migrate/20190530081655_add_columns_to_school_daily_reports.rb new file mode 100644 index 00000000..d3571f02 --- /dev/null +++ b/db/migrate/20190530081655_add_columns_to_school_daily_reports.rb @@ -0,0 +1,6 @@ +class AddColumnsToSchoolDailyReports < ActiveRecord::Migration + def change + add_column :school_daily_reports, :shixun_homework_count, :integer, default: 0 + add_column :school_daily_reports, :shixun_evaluate_count, :integer, default: 0 + end +end diff --git a/db/migrate/20190531002049_remove_evaluate_count_from_shixuns.rb b/db/migrate/20190531002049_remove_evaluate_count_from_shixuns.rb new file mode 100644 index 00000000..591f2ffd --- /dev/null +++ b/db/migrate/20190531002049_remove_evaluate_count_from_shixuns.rb @@ -0,0 +1,9 @@ +class RemoveEvaluateCountFromShixuns < ActiveRecord::Migration + def up + remove_column :shixuns, :evaluate_count + end + + def down + add_column :shixuns, :evaluate_count, :integer, default: 0 + end +end diff --git a/db/migrate/20190531011258_create_school_daily_active_users.rb b/db/migrate/20190531011258_create_school_daily_active_users.rb new file mode 100644 index 00000000..e03ef5e9 --- /dev/null +++ b/db/migrate/20190531011258_create_school_daily_active_users.rb @@ -0,0 +1,10 @@ +class CreateSchoolDailyActiveUsers < ActiveRecord::Migration + def change + create_table :school_daily_active_users do |t| + t.integer :school_daily_report_id + t.integer :user_id + end + + add_index :school_daily_active_users, :school_daily_report_id + end +end diff --git a/db/migrate/20190603074122_create_school_reports.rb b/db/migrate/20190603074122_create_school_reports.rb new file mode 100644 index 00000000..d025adce --- /dev/null +++ b/db/migrate/20190603074122_create_school_reports.rb @@ -0,0 +1,14 @@ +class CreateSchoolReports < ActiveRecord::Migration + def change + create_table :school_reports do |t| + t.integer :school_id + t.string :school_name + t.integer :shixun_evaluate_count + + t.timestamps + end + + add_index :school_reports, :school_id + add_index :school_reports, :shixun_evaluate_count + end +end diff --git a/db/migrate/20190604115012_migrate_homework_eff_score.rb b/db/migrate/20190604115012_migrate_homework_eff_score.rb new file mode 100644 index 00000000..22e05e65 --- /dev/null +++ b/db/migrate/20190604115012_migrate_homework_eff_score.rb @@ -0,0 +1,41 @@ +class MigrateHomeworkEffScore < ActiveRecord::Migration + def up + homework = HomeworkCommon.where(id: 27641).first + if homework.present? + max_efficiency = homework.max_efficiency + homework.student_works.where(compelete_status: 1).each do |work| + user_total_score = 0 + pass_consume_time = 0 + myshixun = work.myshixun + homework.homework_challenge_settings.each do |setting| + game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first + unless game.nil? + pass_consume_time += (game.cost_time / 60.0).to_f + user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i + end + end + + efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) + work.update_column("efficiency", format("%.2f", efficiency)) + + if max_efficiency < work.efficiency + max_efficiency = work.efficiency + end + end + homework.update_column("max_efficiency", max_efficiency) + + homework.student_works.where("compelete_status != 0").each do |student_work| + eff_score = student_work.efficiency / homework.max_efficiency * homework.eff_score + student_work.eff_score = format("%.2f", eff_score) + unless student_work.ultimate_score + work_score = student_work.final_score.to_f + student_work.eff_score - student_work.late_penalty + student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score) + end + student_work.save + end + end + end + + def down + end +end diff --git a/db/migrate/20190605021834_migration_exercise_bank_question_number.rb b/db/migrate/20190605021834_migration_exercise_bank_question_number.rb new file mode 100644 index 00000000..fb441763 --- /dev/null +++ b/db/migrate/20190605021834_migration_exercise_bank_question_number.rb @@ -0,0 +1,22 @@ +class MigrationExerciseBankQuestionNumber < ActiveRecord::Migration + def up + Exercise.includes(:exercise_questions).find_each do |exercise| + if exercise.exercise_questions.pluck(:question_number).max != exercise.exercise_questions.size + exercise.exercise_questions.each_with_index do |question, j| + question.update_column('question_number', j + 1) + end + end + end + + ExerciseBank.includes(:exercise_bank_questions).find_each do |exercise| + if exercise.exercise_bank_questions.pluck(:question_number).max != exercise.exercise_bank_questions.size + exercise.exercise_bank_questions.each_with_index do |question, j| + question.update_column('question_number', j + 1) + end + end + end + end + + def down + end +end diff --git a/db/migrate/20190605063236_modify_hidden_defualt_for_discusses.rb b/db/migrate/20190605063236_modify_hidden_defualt_for_discusses.rb new file mode 100644 index 00000000..9e026906 --- /dev/null +++ b/db/migrate/20190605063236_modify_hidden_defualt_for_discusses.rb @@ -0,0 +1,8 @@ +class ModifyHiddenDefualtForDiscusses < ActiveRecord::Migration + def up + change_column :discusses, :hidden, :boolean, :default => true + end + + def down + end +end diff --git a/db/migrate/20190606030046_add_index_to_apply_actions.rb b/db/migrate/20190606030046_add_index_to_apply_actions.rb new file mode 100644 index 00000000..ccbdb03a --- /dev/null +++ b/db/migrate/20190606030046_add_index_to_apply_actions.rb @@ -0,0 +1,5 @@ +class AddIndexToApplyActions < ActiveRecord::Migration + def change + add_index :apply_actions, :user_id + end +end diff --git a/db/migrate/20190613043232_modify_input_for_test_sets.rb b/db/migrate/20190613043232_modify_input_for_test_sets.rb new file mode 100644 index 00000000..14d71acc --- /dev/null +++ b/db/migrate/20190613043232_modify_input_for_test_sets.rb @@ -0,0 +1,8 @@ +class ModifyInputForTestSets < ActiveRecord::Migration + def up + change_column :test_sets, :input, :text + end + + def down + end +end diff --git a/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml b/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml index bc8e078e..fecf0773 100644 --- a/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml +++ b/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml @@ -1,4 +1,4 @@ -top_level: +_top_level: id: 1 name: Top Level lft: 1 diff --git a/lib/tasks/school_report.rake b/lib/tasks/school_report.rake new file mode 100644 index 00000000..a517123b --- /dev/null +++ b/lib/tasks/school_report.rake @@ -0,0 +1,8 @@ +#coding=utf-8 + +namespace :school_report do + desc 'statistic school report task' + task statistic: :environment do + StatisticSchoolReportTask.new.call + end +end diff --git a/lib/tasks/statistic_school_daily_report.rake b/lib/tasks/statistic_school_daily_report.rake index 9be09ad6..2d487ff6 100644 --- a/lib/tasks/statistic_school_daily_report.rake +++ b/lib/tasks/statistic_school_daily_report.rake @@ -31,11 +31,12 @@ namespace :school_daily_report do data = reports.map do |report| # 无效数据不记录 - next if %w(teacher_count student_count course_count shixun_count active_user_count).all? { |key| report[key].zero? } + next if %w(teacher_count student_count course_count shixun_count shixun_homework_count shixun_evaluate_count active_user_count).all? { |key| report[key].zero? } [ report['id'], report['name'], report['teacher_count'], report['student_count'], report['course_count'], - report['shixun_count'], report['active_user_count'], date_str, current_datetime, current_datetime + report['shixun_count'], report['shixun_homework_count'], report['shixun_evaluate_count'], + report['active_user_count'], date_str, current_datetime, current_datetime ] end.compact batch_create_school_daily_reports!(data) @@ -69,6 +70,113 @@ namespace :school_daily_report do end end + # 统计学校历史每天实训作业新增数 + desc 'statistic school shixun homework count everyday' + task :statistic_shixun_homework_count, [:date] => :environment do |_, args| + date = Time.zone.parse(args[:date]).beginning_of_day + current_date = (Time.zone.now - 5.hour).beginning_of_day + custom_logger("statistic range: #{date}..#{current_date}") + + while current_date > date + date_str = date.strftime('%Y-%m-%d') + + custom_logger("Start statistic => Date: #{date_str} ~") + + begin_date = (date + 5.hour).strftime('%Y-%m-%d %H:%M:%S') + end_date = (date + 1.day + 5.hour).strftime('%Y-%m-%d %H:%M:%S') + + homework_count_map = HomeworkCommon.joins('LEFT JOIN courses cs ON homework_commons.course_id = cs.id') + .where('cs.school_id IS NOT NULL') + .where(homework_type: 4, created_at: begin_date...end_date).reorder(nil) + .group('cs.school_id').count + + ActiveRecord::Base.transaction do + exist_school_ids = SchoolDailyReport.where(date: date_str).pluck(:school_id) + + updated_school_ids = homework_count_map.keys & exist_school_ids # 需要更新的 + + updated_reports = [] + created_reports = [] + homework_count_map.each do |school_id, homework_count| + if updated_school_ids.include?(school_id) + updated_reports << "WHEN #{school_id} THEN #{homework_count}" + else + created_reports << "(#{school_id}, '#{date_str}', #{homework_count})" + end + end + + if updated_reports.present? + # 这样更新快些 + SchoolDailyReport.connection.execute("UPDATE school_daily_reports SET shixun_homework_count = CASE school_id #{updated_reports.join(' ')} END "\ + "WHERE school_id IN (#{updated_school_ids.join(',')}) AND date = '#{date_str}'") + end + + if created_reports.present? + SchoolDailyReport.connection.execute("INSERT INTO school_daily_reports(school_id, date, shixun_homework_count) VALUES#{created_reports.join(',')}") + end + end + + custom_logger("Statistic complete! date: #{date_str}") + + date += 1.day + end + end + + # 统计学校历史每天实训评测新增数 + desc 'statistic school shixun evaluate count everyday' + task :statistic_shixun_evaluate_count, [:date] => :environment do |_, args| + date = Time.zone.parse(args[:date]).beginning_of_day + current_date = (Time.zone.now - 5.hour).beginning_of_day + custom_logger("statistic range: #{date}..#{current_date}") + + while current_date > date + date_str = date.strftime('%Y-%m-%d') + + custom_logger("Start statistic => Date: #{date_str} ~") + + begin_date = (date + 5.hour).strftime('%Y-%m-%d %H:%M:%S') + end_date = (date + 1.day + 5.hour).strftime('%Y-%m-%d %H:%M:%S') + + evaluate_count_map = EvaluateRecord.joins('LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = evaluate_records.shixun_id') + .joins('LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id AND hc.homework_type = 4') + .joins('LEFT JOIN members ON members.user_id = evaluate_records.user_id') + .joins('LEFT JOIN courses ON members.course_id = courses.id AND hc.course_id = courses.id') + .where(created_at: begin_date...end_date).where('courses.school_id IS NOT NULL') + .reorder(nil).group('courses.school_id').count + + ActiveRecord::Base.transaction do + exist_school_ids = SchoolDailyReport.where(date: date_str).pluck(:school_id) + + updated_school_ids = evaluate_count_map.keys & exist_school_ids # 需要更新的 + + updated_reports = [] + created_reports = [] + evaluate_count_map.each do |school_id, evaluate_count| + if updated_school_ids.include?(school_id) + updated_reports << "WHEN #{school_id} THEN #{evaluate_count}" + else + created_reports << "(#{school_id}, '#{date_str}', #{evaluate_count})" + end + end + + if updated_reports.present? + # 这样更新快些 + SchoolDailyReport.connection.execute("UPDATE school_daily_reports SET shixun_evaluate_count = CASE school_id #{updated_reports.join(' ')} END "\ + "WHERE school_id IN (#{updated_school_ids.join(',')}) AND date = '#{date_str}'") + end + + if created_reports.present? + SchoolDailyReport.connection.execute("INSERT INTO school_daily_reports(school_id, date, shixun_evaluate_count) VALUES#{created_reports.join(',')}") + end + end + + custom_logger("Statistic complete! date: #{date_str}") + + date += 1.day + end + end + + def query_size 100 end @@ -88,7 +196,7 @@ namespace :school_daily_report do def build_insert_report_sql(arr) prefix = 'INSERT INTO school_daily_reports(school_id, school_name, teacher_increase_count, student_increase_count, '\ - 'course_increase_count, shixun_increase_count, active_user_count, date, created_at, updated_at) VALUES' + 'course_increase_count, shixun_increase_count, shixun_homework_count, shixun_evaluate_count, active_user_count, date, created_at, updated_at) VALUES' # [[1,2], [3,4]] => ['"1", "2"', '"3", "4"'] => '("1", "2"),("3", "4")' values = '(' + arr.map { |item| '"' + item.join('","') + '"' }.join('),(') + ')' @@ -120,6 +228,17 @@ namespace :school_daily_report do LEFT JOIN user_extensions ue ON ue.user_id = u.id WHERE ue.school_id = schools.id AND sx.created_at BETWEEN "#{begin_date}" AND "#{end_date}" ) shixun_count, ( + SELECT COUNT(*) FROM homework_commons hc + LEFT JOIN courses cs ON hc.course_id = cs.id + WHERE cs.school_id = schools.id AND hc.homework_type = 4 AND hc.created_at BETWEEN "#{begin_date}" AND "#{end_date}" + ) shixun_homework_count, ( + SELECT COUNT(*) FROM evaluate_records er + LEFT JOIN members ON members.user_id = er.user_id + LEFT JOIN homework_commons_shixuns hcs ON hcs.shixun_id = er.shixun_id + LEFT JOIN homework_commons hc ON hcs.homework_common_id = hc.id + LEFT JOIN courses ON hc.course_id = courses.id AND members.course_id = courses.id + WHERE courses.school_id = schools.id AND er.created_at BETWEEN "#{begin_date}" AND "#{end_date}" + ) shixun_evaluate_count, ( SELECT COUNT(*) FROM users u LEFT JOIN user_extensions ue ON ue.user_id = u.id WHERE ue.school_id = schools.id AND u.last_login_on BETWEEN "#{begin_date}" AND "#{end_date}" diff --git a/lib/trustie/sms/sms.rb b/lib/trustie/sms/sms.rb index 2cab61fa..33584a0c 100644 --- a/lib/trustie/sms/sms.rb +++ b/lib/trustie/sms/sms.rb @@ -31,6 +31,8 @@ module Trustie params['text'] = "" if send_type.nil? params['text'] = "【Edu实训】" + code + "(手机验证码)。如非本人操作,请忽略。" + elsif send_type == "teacher_register" + params['text'] = "【Edu实训】亲爱的#{user_name},有新的老师#{name}注册啦,请尽快处理" elsif send_type == 'competition_start' params['text'] = "【Edu实训】亲爱的#{user_name},你参与的#{name}将于#{result}开始,请及时参赛" Rails.logger.info "#{params['text']}" diff --git a/public/assets/iconfont/demo_index.html b/public/assets/iconfont/demo_index.html index ae1000a0..1ef8180e 100644 --- a/public/assets/iconfont/demo_index.html +++ b/public/assets/iconfont/demo_index.html @@ -48,12 +48,6 @@
        &#xe6d8;
        -
      • - -
        章节
        -
        &#xe60f;
        -
      • -
      • css3
        @@ -72,6 +66,12 @@
        &#xe6b2;
      • +
      • + +
        章节
        +
        &#xe68e;
        +
      • +
      • 关闭
        @@ -90,6 +90,12 @@
        &#xe671;
      • +
      • + +
        pdf
        +
        &#xe740;
        +
      • +
      • 时间
        @@ -168,6 +174,12 @@
        &#xe639;
      • +
      • + +
        复制
        +
        &#xe68f;
        +
      • +
      • 点赞1
        @@ -216,12 +228,24 @@
        &#xe727;
      • +
      • + +
        提示
        +
        &#xe690;
        +
      • +
      • net
        &#xe607;
      • +
      • + +
        edit
        +
        &#xe691;
        +
      • +
      • @@ -234,6 +258,12 @@
        &#xe67f;
      • +
      • + +
        下载
        +
        &#xe6ac;
        +
      • +
      • 撤销
        @@ -246,6 +276,12 @@
        &#xe687;
      • +
      • + +
        标签
        +
        &#xe74f;
        +
      • +
      • 大数据存储
        @@ -258,6 +294,12 @@
        &#xe686;
      • +
      • + +
        添加成员
        +
        &#xe69a;
        +
      • +
      • 三角形
        @@ -306,6 +348,12 @@
        &#xe68b;
      • +
      • + +
        三点
        +
        &#xe6f8;
        +
      • +
      • base
        @@ -396,6 +444,12 @@
        &#xe68d;
      • +
      • + +
        上传图片
        +
        &#xe7fd;
        +
      • +
      • 登录Ip监控
        @@ -996,6 +1050,12 @@
        &#xe68c;
      • +
      • + +
        添加导航
        +
        &#xe604;
        +
      • +

        Unicode 引用

        @@ -1073,15 +1133,6 @@
        -
      • - -
        - 章节 -
        -
        .icon-zhangjie -
        -
      • -
      • @@ -1109,6 +1160,15 @@
      • +
      • + +
        + 章节 +
        +
        .icon-zhangjie1 +
        +
      • +
      • @@ -1136,6 +1196,15 @@
      • +
      • + +
        + pdf +
        +
        .icon-pdf +
        +
      • +
      • @@ -1253,6 +1322,15 @@
      • +
      • + +
        + 复制 +
        +
        .icon-fuzhi +
        +
      • +
      • @@ -1325,6 +1403,15 @@
      • +
      • + +
        + 提示 +
        +
        .icon-tishi1 +
        +
      • +
      • @@ -1334,6 +1421,15 @@
      • +
      • + +
        + edit +
        +
        .icon-edit +
        +
      • +
      • @@ -1352,6 +1448,15 @@
      • +
      • + +
        + 下载 +
        +
        .icon-xiazai1 +
        +
      • +
      • @@ -1370,6 +1475,15 @@
      • +
      • + +
        + 标签 +
        +
        .icon-biaoqian +
        +
      • +
      • @@ -1388,6 +1502,15 @@
      • +
      • + +
        + 添加成员 +
        +
        .icon-tianjiachengyuan +
        +
      • +
      • @@ -1460,6 +1583,15 @@
      • +
      • + +
        + 三点 +
        +
        .icon-sandian +
        +
      • +
      • @@ -1595,6 +1727,15 @@
      • +
      • + +
        + 上传图片 +
        +
        .icon-shangchuantupian1 +
        +
      • +
      • @@ -2495,6 +2636,15 @@
      • +
      • + +
        + 添加导航 +
        +
        .icon-tianjiadaohang +
        +
      • +

        font-class 引用

        @@ -2513,7 +2663,7 @@
        <link rel="stylesheet" href="./iconfont.css">
         

        第二步:挑选相应图标并获取类名,应用于页面:

        -
        <span class="iconfont icon--xxx"></span>
        +
        <span class="iconfont icon-xxx"></span>
         

        " @@ -2548,14 +2698,6 @@

        #icon-roundaddfill
        -
      • - -
        章节
        -
        #icon-zhangjie
        -
      • -
      • #icon-31
      • +
      • + +
        章节
        +
        #icon-zhangjie1
        +
      • +
      • #icon-weibiaoti12
      • +
      • + +
        pdf
        +
        #icon-pdf
        +
      • +
      • #icon-dianzan1
      • +
      • + +
        复制
        +
        #icon-fuzhi
        +
      • +
      • #icon-daimapeizhir
      • +
      • + +
        提示
        +
        #icon-tishi1
        +
      • +
      • #icon-net
      • +
      • + +
        edit
        +
        #icon-edit
        +
      • +
      • #icon-default
      • +
      • + +
        下载
        +
        #icon-xiazai1
        +
      • +
      • #icon-qq
      • +
      • + +
        标签
        +
        #icon-biaoqian
        +
      • +
      • #icon-mstest
      • +
      • + +
        添加成员
        +
        #icon-tianjiachengyuan
        +
      • +
      • #icon-chenggong
      • +
      • + +
        三点
        +
        #icon-sandian
        +
      • +
      • #icon-zhiliangfenxi
      • +
      • + +
        上传图片
        +
        #icon-shangchuantupian1
        +
      • +
      • #icon-shixundaibeijing
      • +
      • + +
        添加导航
        +
        #icon-tianjiadaohang
        +
      • +

        Symbol 引用

        diff --git a/public/assets/iconfont/iconfont.eot b/public/assets/iconfont/iconfont.eot index acf4d561..861e815a 100644 Binary files a/public/assets/iconfont/iconfont.eot and b/public/assets/iconfont/iconfont.eot differ diff --git a/public/assets/iconfont/iconfont.js b/public/assets/iconfont/iconfont.js index c65b3873..4b2ab675 100644 --- a/public/assets/iconfont/iconfont.js +++ b/public/assets/iconfont/iconfont.js @@ -1 +1 @@ -!function(z){var c,o='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!z.__iconfont__svg__cssinject__){z.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(h=c,i=z.document,a=!1,t=function(){a||(a=!0,h())},(o=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(o,50)}t()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,t())});var h,i,a,t,o}(function(){var c,l,h,i,a,t;(c=document.createElement("div")).innerHTML=o,o=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",h=l,(i=document.body).firstChild?(a=h,(t=i.firstChild).parentNode.insertBefore(a,t)):i.appendChild(h))})}(window); \ No newline at end of file +!function(z){var c,h='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!z.__iconfont__svg__cssinject__){z.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(i=c,a=z.document,t=!1,(o=function(){try{a.documentElement.doScroll("left")}catch(c){return void setTimeout(o,50)}h()})(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,h())});function h(){t||(t=!0,i())}var i,a,t,o}(function(){var c,l;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file diff --git a/public/assets/iconfont/iconfont.svg b/public/assets/iconfont/iconfont.svg index a56bc3bb..c4477efd 100644 --- a/public/assets/iconfont/iconfont.svg +++ b/public/assets/iconfont/iconfont.svg @@ -29,9 +29,6 @@ Created by iconfont - - - @@ -41,6 +38,9 @@ Created by iconfont + + + @@ -50,6 +50,9 @@ Created by iconfont + + + @@ -89,6 +92,9 @@ Created by iconfont + + + @@ -113,27 +119,42 @@ Created by iconfont + + + + + + + + + + + + + + + @@ -158,6 +179,9 @@ Created by iconfont + + + @@ -203,6 +227,9 @@ Created by iconfont + + + @@ -503,6 +530,9 @@ Created by iconfont + + + diff --git a/public/assets/iconfont/iconfont.ttf b/public/assets/iconfont/iconfont.ttf index 08cd53af..9e09e9f9 100644 Binary files a/public/assets/iconfont/iconfont.ttf and b/public/assets/iconfont/iconfont.ttf differ diff --git a/public/assets/iconfont/iconfont.woff b/public/assets/iconfont/iconfont.woff index 109a76f5..c9036493 100644 Binary files a/public/assets/iconfont/iconfont.woff and b/public/assets/iconfont/iconfont.woff differ diff --git a/public/assets/iconfont/iconfont.woff2 b/public/assets/iconfont/iconfont.woff2 index 41b9904c..252cbb39 100644 Binary files a/public/assets/iconfont/iconfont.woff2 and b/public/assets/iconfont/iconfont.woff2 differ diff --git a/public/javascripts/edu/base_edu.js b/public/javascripts/edu/base_edu.js index 8167249c..1963d1cb 100644 --- a/public/javascripts/edu/base_edu.js +++ b/public/javascripts/edu/base_edu.js @@ -1361,16 +1361,6 @@ function choose_course_to_send_hb(){ } } -function search_hw_course(url){ - $.ajax({ - url: url, - type: 'post', - data: {search: $("#hb_search_course_input").val(), is_observe: true}, - success: function(data){ - } - }); -} - function submit_send_hb_to_course(){ if($("input[name='course_id']:checked").length >= 1){ $("#search_course_notice_h").html("").hide(); diff --git a/public/javascripts/edu/course.js b/public/javascripts/edu/course.js index 330dbea7..98163bda 100644 --- a/public/javascripts/edu/course.js +++ b/public/javascripts/edu/course.js @@ -1103,6 +1103,15 @@ function add_ex_question(doc,quest_type) var title = $.trim($("#poll_questions_title").val()); var score = $.trim($("#question_score").val()); var standard_ans = $.trim($("#exercise_choice_" + quest_type).val()); + + if (quest_type == 5) { + var name = $.trim($("#poll_questions_name").val()); + if(name===""){ + notice_box("题目标题不能为空"); + result = false; + } + } + if(title.length == 0){ if(quest_type != 5){ notice_box("题目标题不能为空"); @@ -1414,6 +1423,13 @@ function edit_poll_question(doc,id,quest_type) { var title = $.trim($("#poll_questions_title_" + id).val()); var score = $.trim($("#poll_question_score_" + id).val()); var standard_ans = $.trim($("#exercise_choice_" + id).val()); + if (quest_type == 5) { + var name = $.trim($("#poll_questions_name_" + id).val()); + if(name===""){ + notice_box("题目标题不能为空"); + result = false; + } + } if (title.length == 0) { if (quest_type != 5) { notice_box("题目标题不能为空"); diff --git a/public/react/package.json b/public/react/package.json index 107f53c9..a6ac3da8 100644 --- a/public/react/package.json +++ b/public/react/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@novnc/novnc": "^1.1.0", "antd": "^3.6.5", "autoprefixer": "7.1.6", "axios": "^0.18.0", diff --git a/public/react/public/js/edu_tpi.js b/public/react/public/js/edu_tpi.js index d1df64aa..8743a0ac 100644 --- a/public/react/public/js/edu_tpi.js +++ b/public/react/public/js/edu_tpi.js @@ -26,7 +26,7 @@ $(function(){ var nRow = 0; //var nCol = 0; lab.live('mousedown touchstart',function(){ - $('#game_webssh').css('pointer-events', 'none') + $('#contentIframe').css('pointer-events', 'none') dragging = true; leftOffset = $(".labelN").offset().left; wrapWidth = $(".labelN").width(); @@ -35,7 +35,7 @@ $(function(){ ); cen.live('mousedown',function(){ // 使得iframe不捕获事件 - $('#game_webssh').css('pointer-events', 'none') + $('#contentIframe').css('pointer-events', 'none') flag = true; topOffset = $(".centerH").offset().top; wrapHeight = $(".centerH").height(); @@ -111,7 +111,7 @@ $(function(){ doc.live("mouseup touchend", function(e) { // 使得iframe可以继续捕获事件 - $('#game_webssh').css('pointer-events', 'inherit') + $('#contentIframe').css('pointer-events', 'inherit') flag = false; dragging = false; e.cancelBubble = true; diff --git a/public/react/public/js/js_min_all.js b/public/react/public/js/js_min_all.js index 4e33b92c..19daead5 100644 --- a/public/react/public/js/js_min_all.js +++ b/public/react/public/js/js_min_all.js @@ -153,7 +153,11 @@ var EXPAND = 0; // 放大 var SHRINK = 1; // 缩小 var repositoryTabHeight = 40 - +function _resizeTpiPanel () { + var _total = $(".labelN").width(); + $("#game_left_contents").width( _total * 0.35 + 'px'); + $("#game_right_contents").width( _total * 0.65 + 'px'); +} $(function(){ function update_rows_and_cols(rows) { var _iframe = document.getElementById("game_webssh"); @@ -177,6 +181,7 @@ $(function(){ //var nCol = 0; lab.live('mousedown touchstart',function(){ $('#game_webssh').css('pointer-events', 'none') + $('#contentIframe').css('pointer-events', 'none') dragging = true; leftOffset = $(".labelN").offset().left; wrapWidth = $(".labelN").width(); @@ -186,6 +191,7 @@ $(function(){ cen.live('mousedown ',function(){ // 使得iframe不捕获事件 $('#game_webssh').css('pointer-events', 'none') + $('#contentIframe').css('pointer-events', 'none') flag = true; topOffset = $(".centerH").offset().top; wrapHeight = $(".centerH").height(); @@ -262,6 +268,8 @@ $(function(){ doc.live("mouseup touchend", function(e) { // 使得iframe可以继续捕获事件 $('#game_webssh').css('pointer-events', 'inherit') + $('#contentIframe').css('pointer-events', 'inherit') + flag = false; dragging = false; e.cancelBubble = true; diff --git a/public/react/scripts/build.js b/public/react/scripts/build.js index 6dd9d3e5..9267272e 100644 --- a/public/react/scripts/build.js +++ b/public/react/scripts/build.js @@ -184,7 +184,9 @@ function generateNewIndexJsp() { // combinedStream.append(htmlContent); // combinedStream.pipe(fs2.createWriteStream( filePath )); - var outputPath = paths.appBuild + '/../../../app/views/common/index.html.erb' + // var outputPath = paths.appBuild + '/../../../app/views/common/index.html.erb' + var outputPath = paths.appBuild + '/../../../public/react/build/index.html' + fs2.readFile(filePath, 'utf8', function (err,data) { if (err) { return console.log(err); diff --git a/public/react/src/context/TPIContextProvider.js b/public/react/src/context/TPIContextProvider.js index 2dd9267f..75d6b0e2 100644 --- a/public/react/src/context/TPIContextProvider.js +++ b/public/react/src/context/TPIContextProvider.js @@ -307,7 +307,7 @@ pop_box_new(htmlvalue, 480, 182); // 将若干数据重新组织一下 _handleResponseData(resData) { - + let challenge = resData.challenge; challenge.isHtml = false; challenge.isWeb = false; @@ -387,7 +387,11 @@ pop_box_new(htmlvalue, 480, 182); currentGamePassed: false, loading: false, testSetsExpandedArray: testSetsExpandedArrayInitVal.slice(0), - }) + }, () => { + if (resData.shixun.vnc == true) { + window._resizeTpiPanel() + } + }) window.document.title = resData.shixun.name @@ -418,10 +422,21 @@ pop_box_new(htmlvalue, 480, 182); currentGamePassed: false, // 切换game时重置passed字段 }) + // // // test + // const response = {} + // response.data = {"tpm_modified":false,"tpm_cases_modified":false,"hide_code":false,"forbid_copy":false,"output_sets":{"test_sets":"{\"is_public\":1,\"result\":null,\"actual_output\":null,\"compile_success\":null,\"input\":\"9\",\"output\":\"3\\r\\n\"},{\"is_public\":1,\"result\":null,\"actual_output\":null,\"compile_success\":null,\"input\":\"110.25\",\"output\":\"10.5\\r\\n\"},{\"is_public\":0,\"result\":null,\"actual_output\":null,\"compile_success\":null,\"input\":\"-100\",\"output\":\"\\u65e0\\u7b97\\u672f\\u5e73\\u65b9\\u6839\\r\\n\"}","had_test_count":0,"test_sets_count":3,"had_passed_testsests_error_count":0},"latest_output":null,"mirror_name":["C/C++"],"multi_webssh":false,"has_answer":true,"st":0,"discusses_count":8,"game_count":3,"myshixun":{"id":140292,"shixun_id":49,"identifier":"ihprfcq2ta","gpid":156599,"status":0,"user_id":116,"commit_id":"5955e66e34b3b70913b4cb2f62ec5d84cdbe26c9","modify_time":"2017-10-13T15:14:34+08:00","reset_time":"2017-10-13T15:14:34+08:00","system_tip":false},"challenge":{"id":81,"subject":"\u6c42\u4e00\u4e2a\u6570\u7684\u7b97\u672f\u5e73\u65b9\u6839","position":2,"shixun_id":49,"st":0,"score":100,"path":"src/step2/SquareRoot.cpp","task_pass":"[TOC]\r\n\r\n---\r\n\r\n####\u4efb\u52a1\u63cf\u8ff0\r\n\u672c\u5173\u4efb\u52a1\u662f\u901a\u8fc7\u8c03\u7528`sqrt`\u51fd\u6570\u6765\u5b9a\u4e49\u4e00\u4e2a\u6c42\u7b97\u672f\u5e73\u65b9\u6839\u7684\u51fd\u6570\u5e76\u4ee5\u6b64\u6765\u8ba1\u7b97\u4e00\u4e2a\u6570\u7684\u7b97\u672f\u5e73\u65b9\u6839\u3002\r\n\r\n####\u76f8\u5173\u77e5\u8bc6\r\n\u5982\u679c\u4e00\u4e2a\u975e\u8d1f\u6570`x`\u7684\u5e73\u65b9\u7b49\u4e8e`a`\uff0c\u5373`$$x^2 = a$$`\uff0c`(a \u2265 0)`\uff0c\u90a3\u4e48\u8fd9\u4e2a\u975e\u8d1f\u6570`x`\u53eb\u505a`a`\u7684\u7b97\u672f\u5e73\u65b9\u6839\u3002`a`\u7684\u7b97\u672f\u5e73\u65b9\u6839\u8bb0\u4e3a`$$\\sqrt{a}$$`\uff0c\u8bfb\u4f5c`\u6839\u53f7a`\uff0c`a`\u53eb\u505a\u88ab\u5f00\u65b9\u6570\u3002\r\n\r\nC++\u4e2d\uff0c\u53ef\u4ee5\u8c03\u7528\u5e93\u51fd\u6570`sqrt()`\u6765\u6c42\u4e00\u4e2a\u6570\u7684\u7b97\u672f\u5e73\u65b9\u6839\u3002\r\n\r\n####\u7f16\u7a0b\u8981\u6c42\r\n\u672c\u5173\u7684\u7f16\u7a0b\u4efb\u52a1\u662f\u901a\u8fc7\u8c03\u7528`sqrt()`\u51fd\u6570\u6765\u8865\u5168`step2/SquareRoot.cpp`\u6587\u4ef6\u4e2d\u7684`SquareRoot(float n)`\u51fd\u6570\uff0c\u4ee5\u5b9e\u73b0\u8ba1\u7b97\u4e00\u4e2a\u6570\u7684\u7b97\u672f\u5e73\u65b9\u6839\u7684\u8981\u6c42\u3002\r\n\r\n\u6ce8\u610f\uff1a\r\n* \u5982\u679c\u8f93\u5165\u7684\u6570\u6ca1\u6709\u7b97\u6570\u5e73\u65b9\u6839\uff0c\u8fd4\u56de`-1`\u3002\r\n* \u5177\u4f53\u8bf7\u53c2\u89c1\u540e\u7eed\u6d4b\u8bd5\u6837\u4f8b\u3002\r\n\r\n\u672c\u5173\u6d89\u53ca\u7684\u4ee3\u7801\u6587\u4ef6`step2/SquareRoot.cpp`\u4e2d\u7684`SquareRoot`\u51fd\u6570\u7684\u4ee3\u7801\u6846\u67b6\u5982\u4e0b\uff1a\r\n\r\n```cpp\r\n#include \r\n\r\n// \u6c42n\u7684\u7b97\u672f\u5e73\u65b9\u6839\r\ndouble SquareRoot(float n)\r\n{\r\n // \u8bf7\u5728\u6b64\u6dfb\u52a0\u4ee3\u7801\uff0c\u8865\u5168\u51fd\u6570SquareRoot\r\n /********** Begin *********/\r\n\r\n\r\n /********** End **********/\r\n}\r\n```\r\n\r\n####\u6d4b\u8bd5\u8bf4\u660e\r\n\u672c\u5173\u7684\u6d4b\u8bd5\u6587\u4ef6\u662f`step2/SquareRootTest.cpp`\uff0c\u6d4b\u8bd5\u8fc7\u7a0b\u5982\u4e0b\uff1a\r\n1. \u5e73\u53f0\u7f16\u8bd1`step2/SquareRootTest.cpp`\uff0c\u7136\u540e\u94fe\u63a5\u76f8\u5173\u7a0b\u5e8f\u5e93\u5e76\u751f\u6210`SquareRootTest.exe`\uff1b\r\n2. \u5e73\u53f0\u8fd0\u884c`SquareRootTest.exe`\uff0c\u5e76\u4ee5\u6807\u51c6\u8f93\u5165\u65b9\u5f0f\u63d0\u4f9b\u6d4b\u8bd5\u8f93\u5165\uff1b\r\n3. \u5e73\u53f0\u83b7\u53d6`SquareRootTest.exe`\u7684\u8f93\u51fa\uff0c\u7136\u540e\u5c06\u5176\u4e0e\u9884\u671f\u8f93\u51fa\u5bf9\u6bd4\uff0c\u5982\u679c\u4e00\u81f4\u5219\u6d4b\u8bd5\u901a\u8fc7\uff1b\u5426\u5219\u6d4b\u8bd5\u5931\u8d25\u3002\r\n\r\n\u4ee5\u4e0b\u662f\u5e73\u53f0\u5bf9`step2/SquareRootTest.cpp`\u7684\u6837\u4f8b\u6d4b\u8bd5\u96c6\uff1a\r\n\r\n\u6d4b\u8bd5\u8f93\u5165\uff1a`9`\r\n\u9884\u671f\u8f93\u51fa\uff1a`3`\r\n\r\n\u6d4b\u8bd5\u8f93\u5165\uff1a`110.25`\r\n\u9884\u671f\u8f93\u51fa\uff1a`10.5`\r\n\r\n\u6d4b\u8bd5\u8f93\u5165\uff1a`-8`\r\n\u9884\u671f\u8f93\u51fa\uff1a`-1`\r\n\r\n\u5f00\u59cb\u4f60\u7684\u4efb\u52a1\u5427\uff0c\u795d\u4f60\u6210\u529f\uff01\r\n","modify_time":null,"web_route":null,"answer":null},"game":{"id":448025,"status":0,"myshixun_id":140292,"user_id":116,"final_score":0,"challenge_id":81,"identifier":"gih9uzwn8xfc","answer_open":0,"test_sets_view":false,"cost_time":0,"star":0,"modify_time":null,"open_time":"2019-05-30T11:00:19+08:00","updated_at":"2019-05-30T11:00:19+08:00"},"shixun":{"id":49,"name":"C++\u4e4b\u6574\u6570\u8ba1\u7b97\u57fa\u7840","gpid":2018,"modify_time":"2017-10-13T15:14:34+08:00","reset_time":"2017-10-13T15:14:34+08:00","language":"C++","propaedeutics":"####C++\u53d1\u5c55\u5386\u7a0b\r\nC++\u662f\u4e00\u79cd\u901a\u7528\u7684\u7f16\u7a0b\u8bed\u8a00\uff0c\u5b83\u4e0d\u4f46\u62e5\u6709\u6570\u636e\u5c01\u88c5\u3001\u6570\u636e\u9690\u85cf\u3001\u7ee7\u627f\u3001\u91cd\u7528\u3001\u91cd\u8f7d\u4ee5\u53ca\u591a\u6001\u7b49\u7279\u6027\uff0c\u8fd8\u652f\u6301\u8fc7\u7a0b\u5316\u7a0b\u5e8f\u8bbe\u8ba1\u3001\u9762\u5411\u5bf9\u8c61\u7a0b\u5e8f\u8bbe\u8ba1\u3001\u6cdb\u578b\u7a0b\u5e8f\u8bbe\u8ba1\u7b49\u591a\u79cd\u7a0b\u5e8f\u8bbe\u8ba1\u98ce\u683c\uff0c\u540c\u65f6\u8fd8\u63d0\u4f9b\u4e86\u5e95\u5c42\u5185\u5b58\u64cd\u4f5c\u7684\u529f\u80fd\u3002\u5176\u8bbe\u8ba1\u4eae\u70b9\u5728\u4e8e\u4f7f\u7528\u6027\u80fd\uff0c\u6548\u7387\u548c\u7075\u6d3b\u6027\uff0c\u662f\u8fc4\u4eca\u4e3a\u6b62\u6700\u53d7\u5e7f\u5927\u7a0b\u5e8f\u5458\u6b22\u8fce\u7684\u7f16\u7a0b\u8bed\u8a00\u4e4b\u4e00\u3002\r\n\r\n1979\u5e74\uff0c\u4e39\u9ea6\u8ba1\u7b97\u673a\u79d1\u5b66\u5bb6Bjarne Stroustrup\u535a\u58eb\u5728\u7f8e\u56fdAT&T\u8d1d\u5c14\u5b9e\u9a8c\u5ba4\u5f00\u59cb\u4e86\u4ece\u4e8b\u5c06C\u6539\u826f\u4e3a\u5e26\u7c7b\u7684C\uff08C with classes\uff09\u7684\u5de5\u4f5c\u30021983\u5e74\u8be5\u8bed\u8a00\u88ab\u6b63\u5f0f\u547d\u540d\u4e3aC++\uff0c\u5b83\u7684\u547d\u540d\u6765\u6e90\u4e8eC\u8bed\u8a00\u4e2d\u7684\u201c++\u201d\u8fd0\u7b97\u7b26\uff0c\u8fd9\u662f\u4e00\u79cd\u5e38\u89c1\u7684\u547d\u540d\u7ea6\u5b9a\uff0c\u5374\u5145\u5206\u5c55\u793a\u4e86\u5176\u4eceC\u8bed\u8a00\u6539\u8fdb\u7684\u5386\u53f2\uff0c\u66f4\u5f70\u663e\u4e86\u4e00\u79cd\u66f4\u52a0\u5f3a\u5927\u7684\u8ba1\u7b97\u673a\u7f16\u7a0b\u8bed\u8a00\u3002\r\n![](/attachments/download/169261)\r\n\r\nStroustrup\u535a\u58eb\u521b\u9020C++\u7684\u52a8\u673a\u4e3b\u8981\u6765\u6e90\u4e8e\u4ed6\u5728\u535a\u58eb\u671f\u95f4\u7684\u7f16\u7a0b\u7ecf\u9a8c\uff0c\u5c3d\u7ba1\u4ed6\u4f7f\u7528\u8fc7Simula\u548cALGOL\uff0c\u4e5f\u63a5\u89e6\u8fc7C\uff0c\u4f46\u4ed6\u7684\u521d\u8877\u662f\u9700\u8981\u4e00\u95e8\u7f16\u7a0b\u7b80\u5355\u3001\u6b63\u786e\u53ef\u9760\u3001\u9ad8\u6548\u8fd0\u884c\u4e14\u53ef\u79fb\u690d\u7684\u8bed\u8a00\uff0c\u56e0\u6b64\uff0c\u901a\u7528\u6027\u5f3a\u3001\u5feb\u901f\u3001\u4fbf\u643a\u4e14\u5e7f\u6cdb\u4f7f\u7528\u7684C\u8bed\u8a00\u88ab\u9009\u4e2d\u3002 \r\n\r\n####C++\u8bed\u8a00\u7279\u6027\r\n* \u652f\u6301\u6570\u636e\u5c01\u88c5\u548c\u6570\u636e\u9690\u85cf\r\nC++\u4e2d\uff0c\u7c7b\u662f\u652f\u6301\u6570\u636e\u5c01\u88c5\u7684\u5de5\u5177\uff0c\u5bf9\u8c61\u5219\u662f\u6570\u636e\u5c01\u88c5\u7684\u5b9e\u73b0\u3002C++\u901a\u8fc7\u65b0\u5efa\u7528\u6237\u5b9a\u4e49\u7c7b\u6765\u652f\u6301\u6570\u636e\u5c01\u88c5\u548c\u6570\u636e\u9690\u85cf\u3002\r\n\r\n* \u652f\u6301\u7ee7\u627f\u548c\u91cd\u7528\r\nC++\u7ee7\u627f\u548c\u91cd\u7528\u7684\u601d\u60f3\u662f\u5728\u73b0\u6709\u7c7b\u7684\u57fa\u7840\u4e0a\u58f0\u660e\u65b0\u7c7b\u578b\u3002\u901a\u8fc7\u7ee7\u627f\u548c\u91cd\u7528\u53ef\u4ee5\u66f4\u6709\u6548\u5730\u7ec4\u7ec7\u7a0b\u5e8f\u7ed3\u6784\uff0c\u660e\u786e\u7c7b\u95f4\u5173\u7cfb\uff0c\u5e76\u5145\u5206\u5229\u7528\u5df2\u6709\u7c7b\u6765\u5b8c\u6210\u66f4\u590d\u6742\u3001\u6df1\u5165\u7684\u5f00\u53d1\u3002\r\n\r\n* \u652f\u6301\u591a\u6001\u6027\r\nC++\u7684\u591a\u6001\u6027\u4e3a\u6bcf\u4e2a\u7c7b\u6307\u5b9a\u4e86\u8868\u73b0\u884c\u4e3a\uff0c\u4f7f\u5f97\u4e00\u4e2a\u5bf9\u8c61\u53ef\u4ee5\u6709\u72ec\u7279\u7684\u8868\u73b0\u65b9\u5f0f\uff0c\u800c\u53e6\u4e00\u4e2a\u5bf9\u8c61\u6709\u53e6\u4e00\u79cd\u8868\u73b0\u65b9\u5f0f\u3002\r\n\r\n####C++\u77e5\u8bc6\u70b9\u9884\u89c8\r\n\u4f5c\u4e3a\u4e00\u95e8\u6bd4C\u66f4\u5f3a\u5927\u7684\u901a\u7528\u7f16\u7a0b\u8bed\u8a00\uff0cC++\u6db5\u76d6\u4e86\u66f4\u4e3a\u4e30\u5bcc\u7684\u77e5\u8bc6\u70b9\uff0c\u5982\uff1a\u57fa\u672c\u6982\u5ff5\uff0c\u8f93\u5165\u548c\u8f93\u51fa\uff0c\u63a7\u5236\u8bed\u53e5\uff0c\u6570\u7ec4\uff0c\u51fd\u6570\uff0c\u6307\u9488\uff0c\u7ed3\u6784\u3001\u8054\u5408\u548c\u679a\u4e3e\uff0c\u94fe\u8868\uff0c\u7c7b\u548c\u5bf9\u8c61\uff0c\u7c7b\u548c\u5bf9\u8c61\u7684\u4f7f\u7528\uff0c\u8fd0\u7b97\u7b26\u91cd\u8f7d\uff0c\u7ee7\u627f\uff0c\u591a\u6001\uff0c\u5f02\u5e38\uff0c\u6a21\u677f\u7b49\u3002\u5177\u4f53\u5982\u4e0b\uff1a\r\n\r\n* \u57fa\u672c\u6982\u5ff5\uff1a\u5b57\u7b26\u96c6\u548c\u5173\u952e\u5b57\u3001\u57fa\u672c\u6570\u636e\u7c7b\u578b\u3001\u5e38\u91cf\u4e0e\u53d8\u91cf\u3001\u7c7b\u578b\u8f6c\u6362\u3001\u8fd0\u7b97\u7b26\u4e0e\u8868\u8fbe\u5f0f\u3002\r\n\r\n* \u8f93\u5165\u548c\u8f93\u51fa\uff1a\u6807\u51c6\u8f93\u5165\u8f93\u51fa\u51fd\u6570\u3001\u683c\u5f0f\u5316\u8f93\u5165\u8f93\u51fa\u51fd\u6570\u3001\u7528\u6d41\u8fdb\u884c\u8f93\u5165/\u8f93\u51fa\u3001\u6d41\u64cd\u7eb5\u7b97\u5b50\u3002\r\n\r\n* \u63a7\u5236\u8bed\u53e5\uff1a\u9009\u62e9\u8bed\u53e5\uff08`if\u3001if-else\u3001switch`\uff09\u3001\u5faa\u73af\u8bed\u53e5\uff08`for\u3001while\u3001do-while`\uff09\u3001\u8df3\u8f6c\u8bed\u53e5\uff08`break\u3001continue\u3001goto`\uff09\u3002\r\n\r\n* \u6570\u7ec4\uff1a\u4e00\u7ef4\u6570\u7ec4\u3001\u4e8c\u7ef4\u6570\u7ec4\u3001\u591a\u7ef4\u6570\u7ec4\u3001\u5b57\u7b26\u4e32\u3002\r\n\r\n* \u51fd\u6570\uff1a\u9884\u5b9a\u4e49\u51fd\u6570\u3001\u51fd\u6570\u7684\u5b9a\u4e49\u548c\u8c03\u7528\u3001\u51fd\u6570\u91cd\u8f7d\u3001\u5b58\u50a8\u7c7b\u522b\u3001\u4f5c\u7528\u57df\u3001\u9012\u5f52\u51fd\u6570\u3001\u9884\u5904\u7406\u6307\u4ee4\u3002\r\n\r\n* \u6307\u9488\uff1a\u6307\u9488\u7684\u5b9a\u4e49\u3001\u6307\u9488\u7684\u8fd0\u7b97\u3001\u6307\u9488\u4e0e\u6570\u7ec4\u3001\u5b57\u7b26\u6307\u9488\u4e0e\u5b57\u7b26\u6570\u7ec4\u3001\u6307\u9488\u4e0e`const`\u9650\u5b9a\u7b26\u3001\u6307\u9488\u4e0e\u5f15\u7528\u3001\u52a8\u6001\u5185\u5b58\u5206\u914d\u3001\u51fd\u6570\u6307\u9488\u3002\r\n\r\n* \u7ed3\u6784\u3001\u8054\u5408\u548c\u679a\u4e3e\uff1a\u7ed3\u6784\u7684\u5b9a\u4e49\u3001\u7ed3\u6784\u4e0e\u51fd\u6570\u3001\u7ed3\u6784\u4e0e\u6570\u7ec4\u3001\u7ed3\u6784\u4e0e\u6307\u9488\u3001\u8054\u5408\u7684\u5b9a\u4e49\u548c\u4f7f\u7528\u3001\u679a\u4e3e\u548c\u679a\u4e3e\u578b\u53d8\u91cf\u7684\u5b9a\u4e49\u3002\r\n\r\n* \u94fe\u8868\uff1a\u5355\u9879\u94fe\u8868\u3001\u53cc\u5411\u94fe\u8868\u3002\r\n\r\n* \u7c7b\u548c\u5bf9\u8c61\uff1a\u7c7b\u548c\u5bf9\u8c61\u7684\u5b9a\u4e49\u3001\u6784\u9020\u51fd\u6570\u3001\u6790\u6784\u51fd\u6570\u3002\r\n\r\n* \u7c7b\u548c\u5bf9\u8c61\u7684\u4f7f\u7528\uff1a\u7c7b\u7684\u590d\u5408\u3001`this`\u6307\u9488\u3001`const`\u7279\u6027\u3001\u53cb\u5143\u51fd\u6570\u548c\u53cb\u5143\u7c7b\u3002\r\n\r\n* \u8fd0\u7b97\u7b26\u91cd\u8f7d\uff1a\u8fd0\u7b97\u7b26\u91cd\u8f7d\u7684\u6982\u5ff5\u3001\u8fd0\u7b97\u7b26\u6210\u5458\u51fd\u6570\u4e0e\u53cb\u5143\u51fd\u6570\u3001\u5355\u76ee\u8fd0\u7b97\u7b26\u91cd\u8f7d\u3001\u91cd\u8f7d\u6d41\u63d2\u5165\u548c\u6d41\u63d0\u53d6\u8fd0\u7b97\u7b26\u3001\u53cc\u76ee\u8fd0\u7b97\u7b26\u91cd\u8f7d\u3001\u8d4b\u503c\u8fd0\u7b97\u7b26\u91cd\u8f7d\u3001\u7c7b\u578b\u4e4b\u95f4\u7684\u8f6c\u6362\u3002\r\n\r\n* \u7ee7\u627f\uff1a\u7ee7\u627f\u7684\u5b9a\u4e49\u3001\u7c7b\u6307\u9488\u3001\u591a\u91cd\u7ee7\u627f\u3002\r\n\r\n* \u591a\u6001\uff1a\u865a\u51fd\u6570\u3001\u62bd\u8c61\u57fa\u7c7b\u548c\u7eaf\u865a\u51fd\u6570\u3001\u865a\u6790\u6784\u51fd\u6570\u3002\r\n\r\n* \u5f02\u5e38\uff1a\u5f02\u5e38\u7684\u629b\u51fa\u548c\u4f20\u64ad\u3001\u5f02\u5e38\u7684\u6355\u83b7\u548c\u5904\u7406\u3002\r\n\r\n* \u6a21\u677f\uff1a\u51fd\u6570\u6a21\u677f\u3001\u7c7b\u6a21\u677f\u3002\r\n\r\n####C++\u4e0e\u5176\u4ed6\u7f16\u7a0b\u8bed\u8a00\u7684\u5bf9\u6bd4\r\nC++\u8bed\u8a00\u4e0e\u5176\u4ed6\u4e3b\u6d41\u7f16\u7a0b\u8bed\u8a00\u7684\u5bf9\u6bd4\u5982\u4e0b\uff1a\r\n![](/attachments/download/169262)\r\n\r\n![](/attachments/download/169266)\r\n\u5f53\u7136\uff0c\u4e0a\u8ff0\u56fe\u8868\u5217\u51fa\u7684\u7f16\u7a0b\u8bed\u8a00\u4e00\u76f4\u5904\u4e8e\u53d1\u5c55\u548c\u53d8\u5316\u4e2d\uff0c\u5176\u4e2d\u7684\u5bf9\u6bd4\u4ec5\u4f9b\u53c2\u8003\u3002\u6211\u4eec\u5728\u9009\u62e9\u4e00\u79cd\u5f00\u53d1\u8bed\u8a00\u65f6\uff0c\u4e0d\u4ec5\u8981\u8003\u8651\u8bed\u8a00\u672c\u8eab\u7684\u7279\u6027\uff0c\u5f88\u591a\u65f6\u5019\u8fd8\u9700\u8981\u8003\u8651\u5f00\u53d1\u56e2\u961f\u7684\u7279\u70b9\uff0c\u5df2\u6709\u8f6f\u4ef6\u8d44\u4ea7\u7684\u7f16\u7a0b\u8bed\u8a00\u548c\u67b6\u6784\uff0c\u5f53\u5730\u7a0b\u5e8f\u5458\u4eba\u624d\u7684\u5206\u5e03\u7279\u70b9\u7b49\u5404\u79cd\u56e0\u7d20\u3002\r\n\r\n####\u53c2\u8003\u6587\u732e\r\n* \u738b\u633a\u3001\u5468\u4f1a\u5e73\u3001\u8d3e\u4e3d\u4e3d\u3001\u5f90\u9521\u5c71\u8457\uff0cC++\u7a0b\u5e8f\u8bbe\u8ba1\uff08\u7b2c3\u7248\uff09\uff0c\u6e05\u534e\u5927\u5b66\u51fa\u7248\u793e\uff0c2015\u5e742\u6708\u7b2c3\u7248\r\n* \u8c2d\u6d69\u5f3a\u8457\uff0cC++\u9762\u5411\u5bf9\u8c61\u7a0b\u5e8f\u8bbe\u8ba1\uff08\u7b2c2\u7248\uff09\uff0c\u6e05\u534e\u5927\u5b66\u51fa\u7248\u793e\uff0c2014\u5e747\u6708\u7b2c2\u7248\r\n* Wikipeida, C++, https://en.wikipedia.org/wiki/C%2B%2B\r\n* \u767e\u5ea6\u767e\u79d1, C++, http://baike.baidu.com/item/C++","status":2,"identifier":"nf9ja46l","test_set_permission":true,"hide_code":false,"forbid_copy":false,"hidden":false,"webssh":0,"user_id":6,"code_hidden":false,"task_pass":false,"exec_time":40,"multi_webssh":false,"vnc":false},"record":null,"grade":50,"prev_game":"25razqibyps6","next_game":"p9ea4h8zx7fg","username":"\u77f3\u5934","image_url":"avatars/User/b","user_url":"/users/shitou","praise_count":0,"user_praise":false,"time_limit":40,"tomcat_url":"http://10.9.63.225","is_teacher":false,"power":1,"myshixun_manager":true,"vnc":false} + // response.data.shixun.vnc = true + // response.data.vnc_url = 'http://117.50.12.63:43149/vnc_lite.html?password=headless' + // response.data.shixun.zip_path = 'asdfasdfasfd' + // this._handleResponseData(response.data) + // return; + + axios.get(url, { withCredentials: true, }) .then((response) => { + console.log(response); // {"status":1,"message":"Unauthorized. \u7528\u6237\u8ba4\u8bc1\u5931\u8d25."} if (response.data.status == -1) { diff --git a/public/react/src/modules/comment/Comments.js b/public/react/src/modules/comment/Comments.js index 250cf16b..d1ac57d4 100644 --- a/public/react/src/modules/comment/Comments.js +++ b/public/react/src/modules/comment/Comments.js @@ -213,11 +213,12 @@ class Comments extends Component {
        - - { item.hidden && comment.admin === false && comment.manager === false + {/* 改成后端返回了的,都是要显示的,不管hidden的值是true还是false */} + {/* { item.hidden && comment.admin === false && comment.manager === false ?

        违规评论已被屏蔽!

        - :
        - } + : */} +
        + {/* } */}
        @@ -309,10 +310,12 @@ class Comments extends Component {
        - { item.hidden && item.admin === false && (item.manager === false || item.manager == undefined) + {/* 改成后端返回了的,都是要显示的,不管hidden的值是true还是false */} + {/* { item.hidden && item.admin === false && (item.manager === false || item.manager == undefined) ?

        违规评论已被屏蔽!

        - :
        - } + : */} +
        + {/* } */}
        diff --git a/public/react/src/modules/ec/ecStudentList/ecStudentList.js b/public/react/src/modules/ec/ecStudentList/ecStudentList.js index 911ee1c2..4208b2bc 100644 --- a/public/react/src/modules/ec/ecStudentList/ecStudentList.js +++ b/public/react/src/modules/ec/ecStudentList/ecStudentList.js @@ -323,7 +323,7 @@ class ecStudentList extends Component { schooldata={schooldata} ecpath={this.state.ecComponentState} /> -
        +
        学生列表 返回
        diff --git a/public/react/src/modules/ec/ecTitle/ecTitle.css b/public/react/src/modules/ec/ecTitle/ecTitle.css index c6e612bc..3f6796cd 100644 --- a/public/react/src/modules/ec/ecTitle/ecTitle.css +++ b/public/react/src/modules/ec/ecTitle/ecTitle.css @@ -22,6 +22,8 @@ } #traningNav>li>.ecTitles { line-height: 16px !important; + height: 18px!important; + width: 18px!important; } #traningNav>li>.ecTitlefont:hover{ diff --git a/public/react/src/modules/page/Index.js b/public/react/src/modules/page/Index.js index 8653ecd9..42f55df9 100644 --- a/public/react/src/modules/page/Index.js +++ b/public/react/src/modules/page/Index.js @@ -181,9 +181,13 @@ class Index extends Component { challenge={context.challenge} myshixun={context.myshixun} shixun={context.shixun} + vnc_url={context.vnc_url} + zip_path={context.zip_path} + + loading={context.loading} - discusses_count={context.discusses_count} - hide_code={context.hide_code} + discusses_count={context.discusses_count} + hide_code={context.hide_code} readGameAnswer={context.readGameAnswer} @@ -197,7 +201,7 @@ class Index extends Component { time_limit={context.time_limit} - resetTestSetsExpandedArray={context.resetTestSetsExpandedArray} + resetTestSetsExpandedArray={context.resetTestSetsExpandedArray} onRunCodeTestFinish={context.onRunCodeTestFinish} onRunChooseTestFinish={context.onRunChooseTestFinish} testSetUnlock={context.testSetUnlock} diff --git a/public/react/src/modules/page/MainContent.js b/public/react/src/modules/page/MainContent.js index ff9f753d..a0ac70f1 100644 --- a/public/react/src/modules/page/MainContent.js +++ b/public/react/src/modules/page/MainContent.js @@ -13,10 +13,11 @@ import ChooseEvaluateView from './main/ChooseEvaluateView' import { CircularProgress } from 'material-ui/Progress'; import Button from 'material-ui/Button'; - +import VNCDisplay from './VNCDisplay' import './tpiPage.css'; import './tpiPageForMobile.css'; const $ = window.$; +// const showIframeContent = window.location.search.indexOf('vnc=1') != -1; class MainContent extends Component { componentDidMount() { // ios下图标位置有问题 @@ -24,7 +25,7 @@ class MainContent extends Component { if (window.$('.b-label>.resize-helper').position().top < 100) { window.$('.b-label>.resize-helper').css('top', '200px') } - }, 4000) + }, 4000) $("body").css("padding-right","0px!important") } onResizeButtonClick = () => { @@ -32,7 +33,7 @@ class MainContent extends Component { } render() { const { challenge, output_sets, onRunCodeTest, latest_output, record, st, readRepoTimeout, - onTestSetHeaderClick, loading, codeLoading } = this.props + onTestSetHeaderClick, loading, codeLoading, shixun, vnc_url } = this.props // if (output_sets && output_sets.test_sets) { // const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]"); @@ -45,7 +46,7 @@ class MainContent extends Component { } else { games_repository_contents_style = {overflow: 'hidden', height: '445px'} } - + const showIframeContent = shixun && shixun.vnc == true return (
        @@ -65,6 +66,25 @@ class MainContent extends Component {
        + {/* + iframe模式下可以使用样式控制不接收鼠标事件 + 注意 page--body 不能设置index 7999 弹出框的index才1300 + .page--body { z-index: ${showIframeContent ? '7999': '1'} ; } + .b-label>.resize-helper { top: ${showIframeContent ? '10px': '50%'} } + + */} + + {/* */} + { showIframeContent && vnc_url ? + : + {/* 旧版本、评测等待提示--更新提示块*/} {/*
        @@ -74,55 +94,57 @@ class MainContent extends Component {
        */}
        -
        -
        -
        -
        - - {/* 选择题或编程题 */} - {/* readRepoTimeout 如果读取代码超时,显示重新加载按钮,重新拉取代码 */} - { - st === 0 - ? - readRepoTimeout === true ? : - - -
        - -
        -
        - : - } - - {/* */} -
        -
        - {/*
        */} -
        -
        - {/* 测试结果、评测信息区域 */} - { loading ? - : - st === 0 - ? - : - } -
        -
        -
        -
        -
        - -
        - -
        +
        +
        +
        +
        + + {/* 选择题或编程题 */} + {/* readRepoTimeout 如果读取代码超时,显示重新加载按钮,重新拉取代码 */} + { + st === 0 + ? + readRepoTimeout === true ? : + + +
        + +
        +
        + : + } + + {/* */} +
        +
        + {/*
        */} +
        +
        + {/* 测试结果、评测信息区域 */} + { loading ? + : + st === 0 + ? + : + } +
        +
        +
        +
        +
        + +
        + +
        +
        + }
        diff --git a/public/react/src/modules/page/MainContentContainer.js b/public/react/src/modules/page/MainContentContainer.js index b7fcdfa8..bd73d7c0 100644 --- a/public/react/src/modules/page/MainContentContainer.js +++ b/public/react/src/modules/page/MainContentContainer.js @@ -229,6 +229,10 @@ class MainContentContainer extends Component { // arg_path 点击文件目录树时,传入的点击节点对应的path fetchRepositoryCode( props, arg_path, type, isRetry) { const { challenge, showSnackbar, game, shixun, hide_code } = props ? props : this.props; + if (shixun.vnc == true) { + // vnc模式下不需要加载代码 + return true; + } if (hide_code) { // 隐藏code的实训 this.setState({ codeLoading: false }); return; @@ -267,6 +271,15 @@ class MainContentContainer extends Component { // this._cancel = null; } const that = this; + + // test + // console.log('---- fetch code') + // const _code = '"#include\n\n// \u6c42n\u7684\u7b97\u672f\u5e73\u65b9\u6839\ndouble SquareRoot(float n)\n{\n // \u8bf7\u5728\u6b64\u6dfb\u52a0\u4ee3\u7801\uff0c\u8865\u5168\u51fd\u6570SquareRoot\n /********** Begin *********/\n\n\n /********** End **********/\n}"' + // this.oldRepositoryCode = _code; + // this.updateRepositoryCode(_code, updateCodeMirror) + // return + + this.setState({ gameBuilding: false, codeLoading: true }); axios.get(fetchRepoCodeUrl, { withCredentials: true, diff --git a/public/react/src/modules/page/VNCDisplay.js b/public/react/src/modules/page/VNCDisplay.js new file mode 100644 index 00000000..e6dff2f4 --- /dev/null +++ b/public/react/src/modules/page/VNCDisplay.js @@ -0,0 +1,154 @@ +import React, { Component } from 'react'; + +import RFB from '@novnc/novnc/lib/rfb.js'; + +const $ = window.$; +// const showIframeContent = window.location.search.indexOf('vnc=1') != -1; +class VNCDisplay extends Component { + componentDidMount() { + console.log(RFB) + + let rfb; + let desktopName; + // When this function is called we have + // successfully connected to a server + function connectedToServer(e) { + status("Connected to " + desktopName); + } + // This function is called when we are disconnected + function disconnectedFromServer(e) { + if (e.detail.clean) { + status("Disconnected"); + } else { + status("Something went wrong, connection is closed"); + } + } + // When this function is called, the server requires + // credentials to authenticate + function credentialsAreRequired(e) { + const password = prompt("Password Required:"); + rfb.sendCredentials({ password: password }); + } + // When this function is called we have received + // a desktop name from the server + function updateDesktopName(e) { + desktopName = e.detail.name; + } + // Since most operating systems will catch Ctrl+Alt+Del + // before they get a chance to be intercepted by the browser, + // we provide a way to emulate this key sequence. + function sendCtrlAltDel() { + rfb.sendCtrlAltDel(); + return false; + } + // Show a status text in the top bar + function status(text) { + document.getElementById('status').textContent = text; + } + // This function extracts the value of one variable from the + // query string. If the variable isn't defined in the URL + // it returns the default value instead. + function readQueryVariable(name, defaultValue) { + // A URL with a query parameter can look like this: + // https://www.example.com?myqueryparam=myvalue + // + // Note that we use location.href instead of location.search + // because Firefox < 53 has a bug w.r.t location.search + const re = new RegExp('.*[?&]' + name + '=([^&#]*)'), + match = document.location.href.match(re); + if (typeof defaultValue === 'undefined') { defaultValue = null; } + if (match) { + // We have to decode the URL since want the cleartext value + return decodeURIComponent(match[1]); + } + return defaultValue; + } + document.getElementById('sendCtrlAltDelButton') + .onclick = sendCtrlAltDel; + // Read parameters specified in the URL query string + // By default, use the host and port of server that served this file + + // const host = readQueryVariable('host', window.location.hostname); + // let port = readQueryVariable('port', window.location.port); + // const password = readQueryVariable('password', ''); + + const { vnc_url } = this.props; + // http://117.50.12.63:43149/vnc_lite.html?password=headless + let _ar1 = vnc_url.split('/'); + let ipAndPort = _ar1[2].split(':') + let passwordAr = _ar1[3].split('password=') + const host = ipAndPort[0] + let port = ipAndPort[1] + const password = passwordAr[1].split('&')[0] + + const path = readQueryVariable('path', 'websockify'); + // | | | | | | + // | | | Connect | | | + // v v v v v v + status("Connecting"); + // Build the websocket URL used to connect + let url; + // if (window.location.protocol === "https:") { + // url = 'wss'; + // } else { + url = 'ws'; + // } + url += '://' + host; + if(port) { + url += ':' + port; + } + url += '/' + path; + // Creating a new RFB object will start a new connection + rfb = new RFB(document.getElementById('screen'), url, + { credentials: { password: password } }); + // Add listeners to important events from the RFB module + rfb.addEventListener("connect", connectedToServer); + rfb.addEventListener("disconnect", disconnectedFromServer); + rfb.addEventListener("credentialsrequired", credentialsAreRequired); + rfb.addEventListener("desktopname", updateDesktopName); + // Set parameters that can be changed on an active connection + rfb.viewOnly = readQueryVariable('view_only', false); + rfb.scaleViewport = readQueryVariable('scale', false); + } + + render() { + const { challenge, vnc_url } = this.props + + + return ( +
        + +
        +
        Loading
        +
        Send CtrlAltDel
        +
        +
        +
        + ); + } +} + +export default VNCDisplay; diff --git a/public/react/src/modules/page/main/CodeRepositoryView.js b/public/react/src/modules/page/main/CodeRepositoryView.js index d66b5162..5165bf67 100644 --- a/public/react/src/modules/page/main/CodeRepositoryView.js +++ b/public/react/src/modules/page/main/CodeRepositoryView.js @@ -296,7 +296,7 @@ class CodeRepositoryView extends Component { const { repositoryCode, onRepositoryCodeUpdate, showFilesDrawer, drawerOpen, loadingFirstRepoFiles , challenge, evaluateViewExpanded, onRepositoryViewExpand, codeStatus , showResetCodeDialog, showResetPassedCodeDialog, tabIndex, tabIndexChange, game, shixun, isEditablePath, currentPath - , showSettingDrawer, hide_code } = this.props; + , showSettingDrawer, hide_code, myshixun_manager, zip_path } = this.props; // onRequestChange={(drawerOpen) => showFilesDrawer(drawerOpen)} /* @@ -402,11 +402,20 @@ class CodeRepositoryView extends Component { } + + { !shixun.code_hidden && tabIndex === 0 && } + + {/* onClick={showFilesDrawer.bind(this, true)} target='_blank'*/} + { myshixun_manager == true && + + + + } diff --git a/public/stylesheets/educoder/edu-all.css b/public/stylesheets/educoder/edu-all.css index 3da912bb..bbd05a56 100644 --- a/public/stylesheets/educoder/edu-all.css +++ b/public/stylesheets/educoder/edu-all.css @@ -74,7 +74,7 @@ em.vertical-line{display: inline-block;width: 2px;background: #999;height: 10px} .moreitem{position: absolute;right: 5px;top:35px;height: 15px;color:#656565} /*块状列表*/ .square-list{width: 100%;box-sizing: border-box;margin-top:20px} -.square-Item{position: relative;width:280px;margin-right: 26px;margin-bottom: 26px;float: left;border-radius: 6px;background-color:#fff;box-shadow: 0px 0px 12px rgba(0,0,0,0.1); height: 301px;} +.square-Item{position: relative;width:280px;margin-right: 26px;margin-bottom: 26px;float: left;border-radius: 6px;background-color:#fff;box-shadow: 0px 0px 12px rgba(0,0,0,0.1); min-height: 301px;} .square-Item:hover{bottom: 3px; box-shadow: 0px 0px 12px rgba(0,0,0,0.3);} .square-Item:hover .closeSquare{display: block} .square-Item:nth-child(4n+0){margin-right: 0px;}
        <%= sort_tag('新增学生', name: 'student_increase_count', path: school_data_grow_managements_path) %> <%= sort_tag('新增课堂', name: 'course_increase_count', path: school_data_grow_managements_path) %> <%= sort_tag('新增实训', name: 'shixun_increase_count', path: school_data_grow_managements_path) %><%= sort_tag('活跃用户', name: 'active_user_count', path: school_data_grow_managements_path) %><%= sort_tag('新增实训作业', name: 'shixun_homework_count', path: school_data_grow_managements_path) %><%= sort_tag('新增实训评测', name: 'shixun_evaluate_count', path: school_data_grow_managements_path) %><%= sort_tag('活跃用户', name: 'uniq_active_user_count', path: school_data_grow_managements_path) %>
        <%= report.student_increase_count.to_i %> <%= report.course_increase_count.to_i %> <%= report.shixun_increase_count.to_i %><%= report.active_user_count.to_i %><%= report.shixun_homework_count.to_i %><%= report.shixun_evaluate_count.to_i %><%= report.uniq_active_user_count.to_i.zero? ? report.active_user_count.to_i : report.uniq_active_user_count.to_i %>
        序号 ID单位名称单位名称 <%= sort_tag('教师总人数', name: 'teacher_count', path: school_report_managements_path) %> <%= sort_tag('学生总人数', name: 'student_count', path: school_report_managements_path) %> <%= sort_tag('课堂总数', name: 'course_count', path: school_report_managements_path) %> <%= sort_tag('正在进行课堂数', name: 'active_course_count', path: school_report_managements_path) %><%= sort_tag('实训总数', name: 'shixun_count', path: school_report_managements_path) %> + <%= sort_tag('实训评测总数', name: 'shixun_evaluate_count', path: school_report_managements_path) %> + + <%= sort_tag('实训作业总数', name: 'homework_count', path: school_report_managements_path) %> <%= sort_tag('其它作业总数', name: 'other_homework_count', path: school_report_managements_path) %> <%= sort_tag('动态时间', name: 'nearly_course_time', path: school_report_managements_path) %><%= school[:student_count].to_i %> <%= school[:course_count].to_i %> <%= school[:active_course_count].to_i %><%= school[:shixun_count].to_i %><%= school[:shixun_evaluate_count].to_i %> <%= school[:homework_count].to_i %> <%= school[:other_homework_count].to_i %> <%= format_time school[:nearly_course_time] %>