dev_oauth
jingquan huang 6 years ago
commit fd11df826d

@ -33,7 +33,7 @@ class AccountsController < ApplicationController
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
# todo 上线前请删除万能验证码"513231" # todo 上线前请删除万能验证码"513231"
if code != "513231" unless code == "513231" && request.host == "47.96.87.25"
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective? return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
end end

@ -15,8 +15,13 @@ class AttachmentsController < ApplicationController
update_downloads(@file) update_downloads(@file)
redirect_to @file.cloud_url and return redirect_to @file.cloud_url and return
end end
send_file(absolute_path(local_path(@file)), filename: @file.filename, type: @file.content_type.presence || 'application/octet-stream')
pdf_attachment = params[:disposition] || "attachment"
if pdf_attachment == "inline"
send_file absolute_path(local_path(@file)),filename: @file.filename, disposition: 'inline',type: 'application/pdf'
else
send_file(absolute_path(local_path(@file)), filename: @file.filename,stream:false, type: @file.content_type.presence || 'application/octet-stream')
end
update_downloads(@file) update_downloads(@file)
end end
@ -162,11 +167,12 @@ class AttachmentsController < ApplicationController
def attachment_candown def attachment_candown
unless current_user.admin? || current_user.business? unless current_user.admin? || current_user.business?
candown = true candown = true
unless params[:type] == 'history'
if @file.container && current_user.logged? if @file.container && current_user.logged?
# 课堂资源、作业、毕设相关资源的权限判断 # 课堂资源、作业、毕设相关资源的权限判断
if @file.container.is_a?(Course) if @file.container.is_a?(Course)
course = @file.container course = @file.container
candown = current_user.member_of_course?(course) || @file.is_public == 1 candown = current_user.member_of_course?(course) || (course.is_public? && @file.publiced?)
elsif @file.container.is_a?(HomeworkCommon) || @file.container.is_a?(GraduationTask) || @file.container.is_a?(GraduationTopic) elsif @file.container.is_a?(HomeworkCommon) || @file.container.is_a?(GraduationTask) || @file.container.is_a?(GraduationTopic)
course = @file.container&.course course = @file.container&.course
candown = current_user.member_of_course?(course) candown = current_user.member_of_course?(course)
@ -187,4 +193,5 @@ class AttachmentsController < ApplicationController
end end
end end
end end
end
end end

@ -1129,7 +1129,7 @@ class CoursesController < ApplicationController
def validate_course_name def validate_course_name
tip_exception("课堂名称不能为空!") if params[:course][:name].blank? tip_exception("课堂名称不能为空!") if params[:course][:name].blank?
if params[:subject_id].blank? || (@course && @course.subject.blank?) if params[:subject_id].blank? && @course.blank? || (@course && @course.subject.blank?)
tip_exception("课程名称不能为空!") if params[:course_list_name].blank? tip_exception("课程名称不能为空!") if params[:course_list_name].blank?
tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) && tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) &&
params[:course][:name].index(params[:course_list_name]) == 0 params[:course][:name].index(params[:course_list_name]) == 0

@ -339,10 +339,11 @@ class ExerciseQuestionsController < ApplicationController
@exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index| @exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index|
challenge.question_score = params[:question_scores][index].to_f.round(1) challenge.question_score = params[:question_scores][index].to_f.round(1)
challenge.save challenge.save
question_score += challenge.question_score question_score += params[:question_scores][index].to_f.round(1)
end end
@exercise_question.question_score = question_score @exercise_question.question_score = question_score
@exercise_question.shixun_name = shixun_name @exercise_question.shixun_name = shixun_name
@exercise_question.save
end end
#当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数. #当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数.

@ -1566,15 +1566,22 @@ class ExercisesController < ApplicationController
def check_user_id_start_answer #判断用户在开始答题时是否有用户id传入,如果为老师则id必需否则为当前用户的id def check_user_id_start_answer #判断用户在开始答题时是否有用户id传入,如果为老师则id必需否则为当前用户的id
user_login = params[:login] user_login = params[:login]
# exercise_current_user_id = params[:user_id]
if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在且当前为老师/管理员等 if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在且当前为老师/管理员等
normal_status(-1,"请输入学生登陆名!") normal_status(-1,"请输入学生登陆名!")
else else
@ex_answerer = User.find_by(login: user_login) #回答者 if @user_course_identity < Course::STUDENT || @exercise.score_open
@ex_answerer = user_login.blank? ? current_user : User.find_by(login: user_login)
else
@ex_answerer = current_user
end
if @ex_answerer.blank? if @ex_answerer.blank?
normal_status(404,"答题用户不存在") normal_status(404,"答题用户不存在")
elsif @user_course_identity > Course::STUDENT && !@exercise.is_public
normal_status(403,"非公开试卷")
else else
@exercise_current_user_id = @ex_answerer.id || current_user.id # @exercise_current_user_id = @ex_answerer.id || current_user.id
@exercise_current_user_id = @ex_answerer.id
end end
end end
end end

@ -263,12 +263,7 @@ class FilesController < ApplicationController
return normal_status(-2, "该课程下没有id为 #{params[:id]}的资源") if @file.nil? return normal_status(-2, "该课程下没有id为 #{params[:id]}的资源") if @file.nil?
return normal_status(403, "您没有权限进行该操作") if @user != @file.author && !@user.teacher_of_course?(@course) && !@file.public? return normal_status(403, "您没有权限进行该操作") if @user != @file.author && !@user.teacher_of_course?(@course) && !@file.public?
@is_pdf = false
file_content_type = @file.content_type
file_ext_type = File.extname(@file.filename).strip.downcase[1..-1]
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
@is_pdf = true
end
@attachment_histories = @file.attachment_histories @attachment_histories = @file.attachment_histories
end end

@ -86,6 +86,16 @@ class SubjectsController < ApplicationController
@shixuns = @subject.shixuns.published.pluck(:id) @shixuns = @subject.shixuns.published.pluck(:id)
@courses = @subject.courses if @subject.excellent @courses = @subject.courses if @subject.excellent
@members = @subject.subject_members.includes(:user)
shixuns = @subject.shixuns.published.pluck(:id)
challenge_ids = Challenge.where(shixun_id: shixuns).pluck(:id)
# 实训路径中的所有实训标签
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
# 用户获取的实训标签
# @user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq
@user_tags = user_shixun_tags challenge_ids, @user.id
@my_subject_progress = @subject.my_subject_progress
# 访问数变更 # 访问数变更
@subject.increment!(:visits) @subject.increment!(:visits)
end end

@ -26,12 +26,18 @@ class Users::BaseController < ApplicationController
render_forbidden render_forbidden
end end
def require_auth_teacher!
return if current_user.admin_or_business? || observed_user.certification_teacher?
render_forbidden
end
def page_value def page_value
params[:page].to_i <= 0 ? 1 : params[:page].to_i params[:page].to_i <= 0 ? 1 : params[:page].to_i
end end
def per_page_value def per_page_value
params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : 20 params[:per_page].to_i > 0 && params[:per_page].to_i <= 100 ? params[:per_page].to_i : 20
end end
alias_method :limit_value, :per_page_value alias_method :limit_value, :per_page_value

@ -1,5 +1,5 @@
class Users::VideoAuthsController < Users::BaseController class Users::VideoAuthsController < Users::BaseController
before_action :private_user_resources! before_action :private_user_resources!, :check_account, :require_auth_teacher!
def create def create
result = Videos::CreateAuthService.call(observed_user, create_params) result = Videos::CreateAuthService.call(observed_user, create_params)

@ -1,5 +1,6 @@
class Users::VideosController < Users::BaseController class Users::VideosController < Users::BaseController
before_action :private_user_resources! before_action :private_user_resources!, :check_account
before_action :require_auth_teacher!, except: [:index, :review]
helper_method :current_video helper_method :current_video

@ -52,7 +52,8 @@ module ApplicationHelper
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",") shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
in(#{shixun_id}) or homepage_show =1").unhidden.order("myshixuns_count desc, homepage_show asc").limit(3) in(#{shixun_id})").unhidden.order("homepage_show asc, myshixuns_count desc").limit(3)
end end
# 相关推荐 # 相关推荐
@ -257,8 +258,8 @@ module ApplicationHelper
end end
end end
def download_url attachment def download_url attachment,options={}
attachment_path(attachment) attachment_path(attachment,options)
end end
# 耗时:天、小时、分、秒 # 耗时:天、小时、分、秒

@ -10,7 +10,15 @@ module AliyunVod::Service::Base
Rails.logger.info("[AliyunVod] response => status: #{response.status}, result: #{result}") Rails.logger.info("[AliyunVod] response => status: #{response.status}, result: #{result}")
raise AliyunVod::Error, result['Code'] if response.status != 200 if response.status != 200
message =
case result['Code']
when 'InvalidFileName.Extension' then '不支持的文件格式'
when 'IllegalCharacters' then '文件名称包含非法字符'
else raise AliyunVod::Error, result['Message']
end
raise AliyunVod::Error, message if message.present?
end
result result
rescue => ex rescue => ex

@ -115,4 +115,15 @@ class Attachment < ApplicationRecord
end end
end end
#判断是否为pdf文件
def is_pdf?
is_pdf = false
file_content_type = content_type
file_ext_type = File.extname(filename).strip.downcase[1..-1]
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
is_pdf = true
end
is_pdf
end
end end

@ -20,4 +20,14 @@ class AttachmentHistory < ApplicationRecord
is_public == 1 is_public == 1
end end
def is_history_pdf?
is_pdf = false
file_content_type = content_type
file_ext_type = File.extname(filename).strip.downcase[1..-1]
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
is_pdf = true
end
is_pdf
end
end end

@ -36,7 +36,7 @@ class HomeworkCommon < ApplicationRecord
validates :name, length: { maximum: 60 } validates :name, length: { maximum: 60 }
validates :description, length: { maximum: 15000 } validates :description, length: { maximum: 15000 }
validates :reference_answer, length: { maximum: 5000 } validates :reference_answer, length: { maximum: 15000 }
# after_update :update_activity # after_update :update_activity
before_destroy :update_homework_bank_quotes before_destroy :update_homework_bank_quotes

@ -268,7 +268,7 @@ class User < ApplicationRecord
# 实训路径管理员 # 实训路径管理员
def creator_of_subject?(subject) def creator_of_subject?(subject)
subject.user_id == id subject.user_id == id || admin?
end end
# 实训路径合作者、admin # 实训路径合作者、admin

@ -36,9 +36,17 @@ class DuplicateCourseService < ApplicationService
end end
def copy_course_modules! def copy_course_modules!
@second_category_list = {}
origin_course.course_modules.each do |course_module| origin_course.course_modules.each do |course_module|
attrs = course_module.as_json(only: %i[module_type position hidden module_name]) attrs = course_module.as_json(only: %i[module_type position hidden module_name])
CourseModule.create!(attrs.merge(course_id: course.id)) new_course_module = CourseModule.create!(attrs.merge(course_id: course.id))
# 复制子目录
course_module.course_second_categories.each do |second_category|
category_attr = second_category.as_json(only: %i[category_type name position])
new_second_category =
CourseSecondCategory.create!(category_attr.merge(course_id: course.id, course_module_id: new_course_module.id))
@second_category_list[second_category.id] = new_second_category.id
end
end end
end end
@ -50,7 +58,10 @@ class DuplicateCourseService < ApplicationService
origin_course.homework_commons.where(homework_type: %i[normal group practice]).find_each do |origin_homework| origin_course.homework_commons.where(homework_type: %i[normal group practice]).find_each do |origin_homework|
homework_attrs = origin_homework.as_json(only: %i[name description homework_type homework_bank_id reference_answer]) homework_attrs = origin_homework.as_json(only: %i[name description homework_type homework_bank_id reference_answer])
homework = HomeworkCommon.create!(homework_attrs.merge(user_id: user.id, course_id: course.id)) course_second_category_id = @second_category_list[origin_homework.course_second_category_id]
homework = HomeworkCommon.create!(homework_attrs.merge(user_id: user.id, course_id: course.id,
course_second_category_id:course_second_category_id))
origin_homework.attachments.find_each do |origin_attachment| origin_homework.attachments.find_each do |origin_attachment|
attachment = origin_attachment.copy attachment = origin_attachment.copy
@ -71,6 +82,7 @@ class DuplicateCourseService < ApplicationService
HomeworksService.new.create_shixun_homework_cha_setting(homework, origin_homework.shixuns.first) HomeworksService.new.create_shixun_homework_cha_setting(homework, origin_homework.shixuns.first)
end end
origin_homework.increment!(:quotes) origin_homework.increment!(:quotes)
origin_homework.homework_bank.increment!(:quotes) if origin_homework.homework_bank origin_homework.homework_bank.increment!(:quotes) if origin_homework.homework_bank
end end
@ -138,9 +150,9 @@ class DuplicateCourseService < ApplicationService
attachment.copy_from = origin_attachment.copy_from || origin_attachment.id attachment.copy_from = origin_attachment.copy_from || origin_attachment.id
attachment.is_publish = 0 attachment.is_publish = 0
attachment.attachtype ||= 4 attachment.attachtype ||= 4
attachment.course_second_category_id = @second_category_list[origin_attachment.course_second_category_id]
attachment.save! attachment.save!
origin_course.update_quotes(attachment) origin_course.update_quotes(attachment)
end end
end end

@ -51,8 +51,10 @@ class Users::UpdateAccountService < ApplicationService
if first_full_reward if first_full_reward
RewardGradeService.call(user, container_id: user.id, container_type: 'Account', score: 500) RewardGradeService.call(user, container_id: user.id, container_type: 'Account', score: 500)
if user.user_extension.teacher?
sms_notify_admin(user.lastname) if user.user_extension.teacher? join_course(user.id,1309, 2)
sms_notify_admin(user.lastname)
end
end end
user user
@ -73,4 +75,11 @@ class Users::UpdateAccountService < ApplicationService
rescue => ex rescue => ex
Util.logger_error(ex) Util.logger_error(ex)
end end
def join_course(user_id, course_id, identity)
course = Course.find_by(id: course_id)
return unless course
attr = {course_id: course_id, role: identity, user_id: user_id}
CourseMember.create!(attr)
end
end end

@ -35,7 +35,7 @@ class Videos::CreateAuthService < ApplicationService
def upload_video_result def upload_video_result
AliyunVod::Service.create_upload_video(title, filename, params) AliyunVod::Service.create_upload_video(title, filename, params)
rescue AliyunVod::Error => _ rescue AliyunVod::Error => ex
raise Error, '获取视频上传凭证失败' raise Error, ex.message || '获取视频上传凭证失败'
end end
end end

@ -6,4 +6,7 @@ json.publish_time attachment.publish_time
json.quotes attachment.quotes_count json.quotes attachment.quotes_count
json.downloads_count attachment.downloads_count json.downloads_count attachment.downloads_count
json.created_on attachment.created_on json.created_on attachment.created_on
json.url attachment_path(attachment, type: 'history') # json.url attachment_path(attachment, type: 'history').gsub("/api","")
json.is_pdf attachment.is_history_pdf?
json.url attachment.is_history_pdf? ? attachment_path(attachment, type: 'history',disposition:"inline") : attachment_path(attachment, type: 'history')
json.attachment_id attachment.attachment_id

@ -1,7 +1,8 @@
json.id attachment.id json.id attachment.id
json.title attachment.title json.title attachment.title
json.is_public attachment.publiced? json.is_public attachment.publiced?
json.is_lock attachment.locked?(@is_member) # json.is_lock attachment.locked?(@is_member)
json.is_lock !attachment.publiced?
json.is_publish attachment.published? json.is_publish attachment.published?
json.publish_time attachment.publish_time json.publish_time attachment.publish_time
json.unified_setting attachment.unified_setting json.unified_setting attachment.unified_setting
@ -10,4 +11,5 @@ json.quotes attachment.quotes_count
json.description attachment.description json.description attachment.description
json.downloads_count attachment.downloads_count json.downloads_count attachment.downloads_count
json.created_on attachment.created_on json.created_on attachment.created_on
json.url download_url(attachment) unless attachment.locked?(@is_member) json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)

@ -2,5 +2,7 @@ json.id attachment.id
json.title attachment.title json.title attachment.title
json.filesize number_to_human_size attachment.filesize json.filesize number_to_human_size attachment.filesize
json.description attachment.description json.description attachment.description
json.url download_url(attachment) json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)
# json.url download_url(attachment)
json.set! :delete, delete.nil? ? true : delete if defined? delete json.set! :delete, delete.nil? ? true : delete if defined? delete

@ -1,5 +1,6 @@
json.id attachment.id json.id attachment.id
json.title attachment.title json.title attachment.title
json.filesize number_to_human_size(attachment.filesize) json.filesize number_to_human_size(attachment.filesize)
json.url download_url(attachment) json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)
json.created_on attachment.created_on json.created_on attachment.created_on

@ -5,6 +5,7 @@ json.course_id @course.id
json.school @course.school&.name json.school @course.school&.name
json.class_period @course.class_period json.class_period @course.class_period
json.credit @course.credit json.credit @course.credit
json.start_date @course.start_date
json.end_date @course.end_date json.end_date @course.end_date
json.is_public @course.is_public json.is_public @course.is_public
json.course_module_types @course.course_modules.where(hidden: 0).pluck(:module_type) json.course_module_types @course.course_modules.where(hidden: 0).pluck(:module_type)

@ -1,3 +1,3 @@
json.is_pdf @is_pdf
json.partial! 'attachments/attachment_small', attachment: @file json.partial! 'attachments/attachment_small', attachment: @file
json.partial! "attachment_histories/list", attachment_histories: @attachment_histories json.partial! "attachment_histories/list", attachment_histories: @attachment_histories

@ -8,6 +8,7 @@ json.data do
json.course_is_public @course.is_public? json.course_is_public @course.is_public?
json.files do json.files do
json.array! @attachments do |attachment| json.array! @attachments do |attachment|
json.is_history_file attachment.attachment_histories.count > 0 #是否有历史文件
json.partial! "attachments/attachment", attachment: attachment json.partial! "attachments/attachment", attachment: attachment
json.author do json.author do
json.partial! "users/user_simple", user: attachment.author json.partial! "users/user_simple", user: attachment.author

@ -21,7 +21,7 @@ if @type == "image"
elsif @type == "html" elsif @type == "html"
json.iframe_src File.read("#{@user_path}/#{@user_picture[0]}")&.html_safe json.iframe_src File.read("#{@user_path}/#{@user_picture[0]}")&.html_safe
elsif @type == "txt" elsif @type == "txt"
json.contents @contents.html_safe json.contents @contents.to_s
elsif @type =="qrcode" elsif @type =="qrcode"
json.qrcode_str @qrcode_str json.qrcode_str @qrcode_str
elsif @type == "mp3" || @type == "mp4" elsif @type == "mp3" || @type == "mp4"

@ -1,7 +1,6 @@
json.partial! "homework_commons/homework_public_navigation", locals: {homework: @homework, course: @course, user: @current_user} json.partial! "homework_commons/homework_public_navigation", locals: {homework: @homework, course: @course, user: @current_user}
json.work_id @work.id json.work_id @work.id
json.description @work.description json.description @work.description
json.
json.attachments @work.attachments do |atta| json.attachments @work.attachments do |atta|
json.partial! "attachments/attachment_simple", locals: {attachment: atta, delete: @work.delete_atta(atta)} json.partial! "attachments/attachment_simple", locals: {attachment: atta, delete: @work.delete_atta(atta)}

@ -11,6 +11,7 @@ json.allow_statistics @is_manager
json.allow_send @user.logged? json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager json.allow_visit @subject.status > 1 || @is_manager
json.allow_add_member @is_manager json.allow_add_member @is_manager
json.is_creator @is_creator
if @subject.excellent if @subject.excellent
json.courses @courses do |course| json.courses @courses do |course|
@ -23,3 +24,25 @@ if @subject.excellent
json.course_status subject_course_status course json.course_status subject_course_status course
end end
end end
json.members @members do |member|
json.partial! 'subject_member', locals: { user: member.user }
json.role member.role
end
# 技能标签
json.tags @tags do |tag|
unless tag.blank?
json.tag_name tag
json.status @user_tags.include?(tag)
end
end
# 我的进展
json.progress do
json.my_score @subject.my_subject_score
json.all_score @subject.all_score
json.learned @subject.my_subject_progress
json.time @subject.my_consume_time
end

@ -10,6 +10,7 @@ json.tidding_count 0
json.user_phone_binded @user.phone.present? json.user_phone_binded @user.phone.present?
json.phone @user.phone json.phone @user.phone
json.profile_completed @user.profile_completed? json.profile_completed @user.profile_completed?
json.professional_certification @user.professional_certification
if @course if @course
json.course_identity @course_identity json.course_identity @course_identity
json.course_name @course.name json.course_name @course.name

@ -1,25 +1,188 @@
#coding=utf-8 #coding=utf-8
# 执行示例 bundle exec rake excellent_course_exercise:student_answer args=149,2903 # 执行示例 bundle exec rake excellent_course_exercise:student_answer args=2933,1042,823
# args 第一个是course_id, 第二个是参与人数, 第三个是通过人数
desc "同步精品课的学生试卷数据" desc "同步精品课的学生试卷数据"
namespace :excellent_course_exercise do namespace :excellent_course_exercise do
if ENV['args']
course_id = ENV['args'].split(",")[0] # 对应课堂的id
participant_count = ENV['args'].split(",")[1].to_i # 表示参与人数
pass_count = ENV['args'].split(",")[2].to_i # 表示通过人数
end
task :student_answer => :environment do task :student_answer => :environment do
course = Course.find_by(id: 2933) course = Course.find_by(id: course_id)
participant_count = 1042 course.exercises.each_with_index do |exercise, index|
pass_count = 823 # 第一个试卷的参与人数和通过人数都是传的数据,后续的随机
if index == 0
members = course.students.order("id asc").limit(participant_count)
update_exercise_user(exercise, members, pass_count)
else
new_participant_count = rand((participant_count - 423)..participant_count)
new_pass_count = rand((new_participant_count - 113)..new_participant_count)
members_1 = course.students.order("id asc").limit(987) members = course.students.order("id asc").limit(new_participant_count)
members_2 = course.students.order("id asc").limit(1042) update_exercise_user(exercise, members, new_pass_count)
members_1 = course.students.order("id asc").limit(322) end
end
end
exercise_1884 = course.exercises.find_by(id: 1884) def update_exercise_user exercise, members, pass_count
members_1.each_with_index do |member, index| exercise_question_ids = exercise.exercise_questions.where(question_type: 0).pluck(:id)
if index < 821
# index < pass_count 之前的学生都是通关的,之后的未通过
members.each_with_index do |member, index|
exercise_user = exercise.exercise_users.where(user_id: member.user_id).take
if exercise_question_ids.length == 20
rand_num = index < pass_count - 1 ? rand(15..20) : rand(1..10)
elsif exercise_question_ids.length == 17
rand_num = index < pass_count - 1 ? rand(12..17) : rand(1..9)
elsif exercise_question_ids.length == 39
rand_num = index < pass_count - 1 ? rand(30..39) : rand(1..18)
else else
rand_num = exercise_question_ids.length
end
if exercise_user && exercise_user.commit_status == 0
question_ids = exercise_question_ids.sample(rand_num)
questions = exercise.exercise_questions.where(id: question_ids)
create_exercise_answer questions, member.user_id
total_score = calculate_student_score(exercise, member.user)
commit_option = {
:status => 1,
:commit_status => 1,
:start_at => exercise.publish_time,
:end_at => exercise.end_time,
:objective_score => total_score,
:score => total_score,
:subjective_score => 0
}
exercise_user.update_columns(commit_option)
end
end
end
def create_exercise_answer questions, user_id
questions.each do |question|
choice_position = question.exercise_standard_answers.take&.exercise_choice_id
choice = question.exercise_choices.where(choice_position: choice_position).take
answer_option = {
:user_id => user_id,
:exercise_question_id => question.id,
:exercise_choice_id => choice&.id,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
#计算试卷的总分和试卷的答题状态
def calculate_student_score(exercise,user)
score1 = 0.0 #选择题/判断题
score2 = 0.0 #填空题
score5 = 0.0 #实训题
total_score = 0.0
ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions&.each do |q|
begin
if q.question_type != 5
answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案
else
answers_content = q.exercise_shixun_answers.where(user_id: user.id) #学生的答案
end
if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
q_score_1 = q.question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
else
q_score_1 = 0.0
end
answers_content.update_all(:score => q_score_1)
score1 = score1 + q.question_score
else
answers_content.update_all(:score => -1.0)
score1 += 0.0
end
else
score1 += 0.0
end
elsif q.question_type == 5 #实训题时,主观题这里不评分
q.exercise_shixun_challenges&.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡
if game.present?
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id)
code = nil
if exercise_cha.challenge&.path.present?
cha_path = challenge_path(exercise_cha.challenge&.path)
game_challenge = game.game_codes.search_challenge_path(cha_path)&.first
if game_challenge.present?
game_code = game_challenge
code = game_code.try(:new_code)
else
code = git_fle_content(game.myshixun.repo_path,cha_path)
end
end
if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里
### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了涉及到code的多个版本库的修改
sx_option = {
:exercise_question_id => q.id,
:exercise_shixun_challenge_id => exercise_cha.id,
:user_id => user.id,
:score => exercise_cha_score.round(1),
:answer_text => code,
:status => answer_status
}
ExerciseShixunAnswer.create(sx_option)
else
ex_shixun_answer_content.first.update_attributes(score:exercise_cha_score.round(1),answer_text:code)
end
score5 += exercise_cha_score
else
score5 += 0.0
end
end
end
user_scores = answers_content.blank? ? 0.0 : answers_content.score_reviewed.pluck(:score).sum
if user_scores > 0.0
stand_answer = 1
else
stand_answer = 0
end
ques_option = {
"q_id":q.id, #该问题的id
"q_type":q.question_type,
"q_position":q.question_number, #该问题的位置
"stand_status":stand_answer, #该问题是否正确,1为正确0为错误
"user_score":user_scores.round(1) #每个问题的总得分
}
ques_stand.push(ques_option)
rescue Exception => e
Rails.logger.info("calcuclate_score_have_error____________________________#{e}")
next
end end
end end
total_score = score1 + score2 + score5
total_score
end end
end end

@ -29,7 +29,7 @@ const env = getClientEnvironment(publicUrl);
module.exports = { module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools. // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
devtool: "cheap-module-eval-source-map", // devtool: "cheap-module-eval-source-map",
// 开启调试 // 开启调试
// These are the "entry points" to our application. // These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle. // This means they will be the "root" imports that are included in JS bundle.

@ -71,3 +71,8 @@ export function appendFileSizeToUploadFileAll(fileList) {
}) })
} }
export const uploadNameSizeSeperator = '  ' export const uploadNameSizeSeperator = '  '
export const sortDirections = ["ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend",
"ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", "ascend", "descend", ]

@ -17,7 +17,7 @@ export { updatePageParams as updatePageParams } from './RouterUti
export { bytesToSize as bytesToSize } from './UnitUtil'; export { bytesToSize as bytesToSize } from './UnitUtil';
export { markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension, export { markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
downloadFile } from './TextUtil' downloadFile, sortDirections } from './TextUtil'
export { handleDateString, getNextHalfHourOfMoment,formatDuring } from './DateUtil' export { handleDateString, getNextHalfHourOfMoment,formatDuring } from './DateUtil'

@ -27,7 +27,11 @@ class Fileslistitem extends Component{
this.props.Settingtypes(discussMessage.id) this.props.Settingtypes(discussMessage.id)
} }
showfiles=(value)=>{ showfiles=(list)=>{
if(list.is_history_file===false){
// this.props.DownloadFileA(list.title,list.url)
window.location.href=list.url;
}else{
let {discussMessage,coursesId}=this.props let {discussMessage,coursesId}=this.props
let file_id=discussMessage.id let file_id=discussMessage.id
let url="/files/"+file_id+"/histories.json" let url="/files/"+file_id+"/histories.json"
@ -36,27 +40,31 @@ class Fileslistitem extends Component{
course_id:coursesId course_id:coursesId
}, },
}).then((result)=>{ }).then((result)=>{
if(result.data.attachment_histories.length===0){ if(result.data.attachment_histories.length===0){
let link = document.createElement('a'); // if(result.data.is_pdf===true){
document.body.appendChild(link); // this.props.ShowOnlinePdf(result.data.url)
link.href = result.data.url; // //预览pdf
link.download = result.data.title; // }else{
//兼容火狐浏览器 //
let evt = document.createEvent("MouseEvents"); // }
evt.initEvent("click", false, false); // this.props.DownloadFileA(result.data.title,result.data.url)
link.dispatchEvent(evt); window.location.href=list.url;
document.body.removeChild(link);
}else{ }else{
this.setState({ this.setState({
Showoldfiles:true, Showoldfiles:true,
allfiles:result.data allfiles:result.data
}) })
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error) console.log(error)
}) })
} }
}
closaoldfilesprops=()=>{ closaoldfilesprops=()=>{
this.setState({ this.setState({
Showoldfiles:false, Showoldfiles:false,
@ -129,8 +137,6 @@ class Fileslistitem extends Component{
discussMessage, discussMessage,
} = this.props; } = this.props;
return( return(
<div className="graduateTopicList boardsList"> <div className="graduateTopicList boardsList">
@ -144,6 +150,7 @@ class Fileslistitem extends Component{
loadtype={this.state.Loadtype} loadtype={this.state.Loadtype}
/>:""} />:""}
<Showoldfiles <Showoldfiles
{...this.props}
visible={this.state.Showoldfiles} visible={this.state.Showoldfiles}
allfiles={this.state.allfiles} allfiles={this.state.allfiles}
closaoldfilesprops={this.closaoldfilesprops} closaoldfilesprops={this.closaoldfilesprops}
@ -191,13 +198,13 @@ class Fileslistitem extends Component{
{ {
this.props.isAdmin ? <a this.props.isAdmin ? <a
// href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"} // href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
onClick={()=>this.showfiles(discussMessage.title)} onClick={()=>this.showfiles(discussMessage)}
title={discussMessage.title} title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> : "" className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> : ""
} }
{ {
this.props.isStudent? <a this.props.isStudent? <a
onClick={()=>this.showfiles(discussMessage.title)} onClick={()=>this.showfiles(discussMessage)}
title={discussMessage.title} title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :"" className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :""
} }
@ -207,7 +214,7 @@ class Fileslistitem extends Component{
discussMessage.is_lock === true ? discussMessage.is_lock === true ?
<span className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</span> <span className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</span>
:<a :<a
onClick={()=>this.showfiles(discussMessage.title)} onClick={()=>this.showfiles(discussMessage)}
title={discussMessage.title} title={discussMessage.title}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>:"" className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>:""
} }

@ -69,7 +69,7 @@ class CommonWorkPost extends Component{
status: 'done' status: 'done'
} }
}) })
const _memebers = response.data.members.slice(0); const _memebers = response.data.members ? response.data.members.slice(0) : [];
this._edit_init_memebers = _memebers this._edit_init_memebers = _memebers
delete response.data.members; delete response.data.members;
this.setState({ this.setState({

@ -722,15 +722,19 @@ class Coursesleftnav extends Component{
let {url}=this.state; let {url}=this.state;
if (key === this.props.indexs) { if (key === this.props.indexs) {
this.props.unlocationNavfun(undefined) this.props.unlocationNavfun(undefined)
this.props.history.replace(urls);
} else { } else {
this.props.unlocationNavfun(key) this.props.unlocationNavfun(key)
}
if(urls!=url){
this.props.history.replace(urls); this.props.history.replace(urls);
} }
if(this.props.indexs===undefined){ if(urls!=url){
this.props.history.replace(urls); this.props.history.replace(urls);
} }
// if(this.props.indexs===undefined){
//
// }else{
//
// }
} }
maincontent=(item,key)=>{ maincontent=(item,key)=>{

@ -42,6 +42,9 @@ class Showoldfiles extends Component{
this.props.closaoldfilesprops() this.props.closaoldfilesprops()
} }
showfiless=(url)=>{
this.props.ShowOnlinePdf(url)
}
render(){ render(){
let {visible,allfiles}=this.props; let {visible,allfiles}=this.props;
@ -175,7 +178,11 @@ class Showoldfiles extends Component{
<div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" id={allfiles.id}> <div className="clearfix edu-txt-center lineh-40 bor-bottom-greyE" id={allfiles.id}>
<li className="fl fontlefts"> <li className="fl fontlefts">
<a className={"isabox"} href={allfiles.url}>{allfiles.title}</a> <a className={"isabox"} href={allfiles.url} >{allfiles.title}</a>
{/*{allfiles.is_pdf===false?*/}
{/*<a className={"isabox"} href={allfiles.url} >{allfiles.title}</a>:*/}
{/*<a className={"isabox"} onClick={()=>this.showfiless(allfiles.url)} >{allfiles.title}</a>*/}
{/*}*/}
<span className={"newcolor-orange fl"}>当前版本</span> <span className={"newcolor-orange fl"}>当前版本</span>
</li> </li>
@ -192,6 +199,10 @@ class Showoldfiles extends Component{
<li className="fl fontlefts"> <li className="fl fontlefts">
<a className={"isabox"} href={item.url}>{item.title}</a> <a className={"isabox"} href={item.url}>{item.title}</a>
{/*{item.is_pdf===false?*/}
{/*<a className={"isabox"} href={item.url}>{item.title}</a>:*/}
{/*<a className={"isabox"} onClick={()=>this.showfiless(item.url)} >{item.title}</a>*/}
{/*}*/}
</li> </li>
<li className="fl filesves "> <li className="fl filesves ">

@ -8,7 +8,7 @@ import Titlesearchsection from '../common/titleSearch/TitleSearchSection'
import ColorCountText from '../common/titleSearch/ColorCountText' import ColorCountText from '../common/titleSearch/ColorCountText'
import update from 'immutability-helper' import update from 'immutability-helper'
import { WordsBtn, ConditionToolTip, on, off ,trigger} from 'educoder' import { WordsBtn, ConditionToolTip, on, off ,trigger, sortDirections } from 'educoder'
import axios from 'axios' import axios from 'axios'
@ -63,6 +63,7 @@ function buildColumns(that) {
width: 120, width: 120,
key: 'name', key: 'name',
sorter: showSorter, sorter: showSorter,
sortDirections: sortDirections,
sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order, sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
render: (name, record) => { render: (name, record) => {
return <a href={`/users/${record.login}`} target="_blank" className="overflowHidden1" style={{ maxWidth: '110px'}} return <a href={`/users/${record.login}`} target="_blank" className="overflowHidden1" style={{ maxWidth: '110px'}}
@ -75,6 +76,7 @@ function buildColumns(that) {
sorter: showSorter, sorter: showSorter,
// 'ascend' | 'descend' // 'ascend' | 'descend'
defaultSortOrder: 'ascend', defaultSortOrder: 'ascend',
sortDirections: sortDirections,
sortOrder: sortedInfo.columnKey === 'role' && sortedInfo.order, sortOrder: sortedInfo.columnKey === 'role' && sortedInfo.order,
}] }]
@ -116,6 +118,7 @@ function buildColumns(that) {
title: '答辩组', title: '答辩组',
// width: 90, // width: 90,
sorter: showSorter, sorter: showSorter,
sortDirections: sortDirections,
key: 'graduation_group', key: 'graduation_group',
dataIndex: 'graduation_group', dataIndex: 'graduation_group',
sortOrder: sortedInfo.columnKey === 'graduation_group' && sortedInfo.order, sortOrder: sortedInfo.columnKey === 'graduation_group' && sortedInfo.order,

@ -242,7 +242,7 @@ class Index extends Component {
updateChallengePath={context.updateChallengePath} updateChallengePath={context.updateChallengePath}
time_limit={context.time_limit} time_limit={context.time_limit + 5}
resetTestSetsExpandedArray={context.resetTestSetsExpandedArray} resetTestSetsExpandedArray={context.resetTestSetsExpandedArray}
onRunCodeTestFinish={context.onRunCodeTestFinish} onRunCodeTestFinish={context.onRunCodeTestFinish}

@ -226,10 +226,11 @@ class DetailCards extends Component{
startshixunCombattype:true, startshixunCombattype:true,
}) })
} else { } else {
window.location.href = "/tasks/" + response.data.game_identifier; // window.location.href = "/tasks/" + response.data.game_identifier;
// window.location.href = path // window.location.href = path
// let path="/tasks/"+response.data.game_identifier; // let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path); // this.props.history.push(path);
window.open("/tasks/" + response.data.game_identifier);
} }
}).catch((error) => { }).catch((error) => {

@ -727,7 +727,7 @@ submittojoinclass=(value)=>{
src={require('./roundedRectangle.png')} src={require('./roundedRectangle.png')}
/> />
</li> </li>
<li className={`${activeMoopCases === true ? 'pr active' : 'pr'}`}><a href={this.props.Headertop===undefined?"":this.props.Headertop.moop_cases_url}>教学案例</a></li> <li className={`${activeMoopCases === true ? 'pr active' : 'pr'}`}><a href={`/moop_cases`}>教学案例</a></li>
<li className={`${activePackages === true ? 'pr active' : 'pr'}`}> <li className={`${activePackages === true ? 'pr active' : 'pr'}`}>
<a href={'/crowdsourcing'}>众包创新</a> <a href={'/crowdsourcing'}>众包创新</a>
</li> </li>

@ -320,6 +320,34 @@ export function TPMIndexHOC(WrappedComponent) {
} }
checkIfProfileCompleted = () => { checkIfProfileCompleted = () => {
return this.state.current_user && this.state.current_user.profile_completed return this.state.current_user && this.state.current_user.profile_completed
}
ShowOnlinePdf = (url) => {
return axios({
method:'get',
url:url,
responseType: 'arraybuffer',
}).then((result)=>{
var binaryData = [];
binaryData.push(result.data);
this.url =window.URL.createObjectURL(new Blob(binaryData, {type:"application/pdf"}));
window.open(this.url);
})
}
DownloadFileA=(title,url)=>{
let link = document.createElement('a');
document.body.appendChild(link);
link.href =url;
link.download = title;
//兼容火狐浏览器
let evt = document.createEvent("MouseEvents");
evt.initEvent("click", false, false);
link.dispatchEvent(evt);
document.body.removeChild(link);
}
DownloadOpenPdf=(type,url)=>{
type===true?window.open(url):window.location.href=url;
} }
render() { render() {
let{Headertop,Footerdown, isRender, AccountProfiletype}=this.state; let{Headertop,Footerdown, isRender, AccountProfiletype}=this.state;
@ -334,11 +362,13 @@ export function TPMIndexHOC(WrappedComponent) {
isNotMember: this.isNotMember, isNotMember: this.isNotMember,
isUserid:this.state.coursedata&&this.state.coursedata.userid, isUserid:this.state.coursedata&&this.state.coursedata.userid,
fetchUser: this.fetchUser, fetchUser: this.fetchUser,
showLoginDialog: this.showLoginDialog, showLoginDialog: this.showLoginDialog,
checkIfLogin: this.checkIfLogin, checkIfLogin: this.checkIfLogin,
showProfileCompleteDialog: this.showProfileCompleteDialog, showProfileCompleteDialog: this.showProfileCompleteDialog,
checkIfProfileCompleted: this.checkIfProfileCompleted, checkIfProfileCompleted: this.checkIfProfileCompleted,
ShowOnlinePdf:(url)=>this.ShowOnlinePdf(url),
DownloadFileA:(title,url)=>this.DownloadFileA(title,url),
DownloadOpenPdf:(type,url)=>this.DownloadOpenPdf(type,url)
} }
return ( return (
<div> <div>

Loading…
Cancel
Save