jingquan huang 6 years ago
commit 0e61bcf818

@ -239,7 +239,7 @@ class ApplicationController < ActionController::Base
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
if !User.current.logged? && Rails.env.development?
User.current = User.find 12
User.current = User.find 1
end
@ -567,6 +567,10 @@ class ApplicationController < ActionController::Base
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
end
def strf_date(date)
date.blank? ? '' : date.strftime("%Y-%m-%d")
end
def logger_error(error)
Rails.logger.error(error.message)
error.backtrace.each { |msg| Rails.logger.error(msg) }

@ -14,7 +14,7 @@ module RenderExpand
kit.stylesheets << Rails.root.join('app/templates', path)
end
send_data kit.to_pdf, filename: options[:filename], type: 'application/pdf'
send_data kit.to_pdf, filename: options[:filename], disposition: options[:disposition] || 'attachment', type: 'application/pdf'
end
end
end

@ -13,7 +13,7 @@ class CoursesController < ApplicationController
before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
:left_banner, :top_banner]
before_action :check_account, only: [:new, :create, :apply_to_join_course]
before_action :check_account, only: [:new, :create, :apply_to_join_course, :join_excellent_course]
before_action :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups,
:left_banner, :top_banner, :apply_to_join_course, :exit_course]
before_action :set_course, :user_course_identity, only: [:show, :update, :destroy, :settings, :set_invite_code_halt,
@ -25,12 +25,13 @@ class CoursesController < ApplicationController
:transfer_to_course_group, :delete_from_course, :search_users, :add_students_by_search,
:base_info, :get_historical_courses, :create_group_by_importing_file,
:attahcment_category_list,:export_member_scores_excel, :duplicate_course,
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course]
:switch_to_teacher, :switch_to_assistant, :switch_to_student, :exit_course,
:informs, :update_informs, :join_excellent_course, :online_learning]
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :create_group_by_importing_file]
:set_course_group, :create_group_by_importing_file, :update_informs]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group,
:change_course_teacher, :export_member_scores_excel, :course_group_list,
:teacher_application_review, :apply_teachers, :delete_course_teacher]
@ -117,13 +118,19 @@ class CoursesController < ApplicationController
authentication: params[:authentication], professional_certification: params[:professional_certification])
@course.tea_id = current_user.id
@course_list_name = params[:course_list_name].strip
@course_list = CourseList.find_by(name: @course_list_name)
if @course_list
@course.course_list_id = @course_list.id
if params[:subject_id].blank?
@course_list_name = params[:course_list_name].strip
@course_list = CourseList.find_by(name: @course_list_name)
if @course_list
@course.course_list_id = @course_list.id
else
new_course_list = CourseList.create!(name: @course_list_name, user_id: current_user.id, is_admin: 0)
@course.course_list_id = new_course_list.id
end
else
new_course_list = CourseList.create!(name: @course_list_name, user_id: current_user.id, is_admin: 0)
@course.course_list_id = new_course_list.id
@course.start_date = params[:start_date]
@course.subject_id = params[:subject_id]
@course.excellent = true
end
@course.is_end = @course.end_date.present? && @course.end_date < Date.today
@ -133,6 +140,13 @@ class CoursesController < ApplicationController
CourseInfo.create!(user_id: current_user.id, course_id: @course.id)
CourseMember.create!(course_id: @course.id, user_id: current_user.id, role: 1)
# 将实践课程的教学团队成员以教师身份加入课堂
if @course.subject
@course.subject.subject_members.where.not(user_id: current_user.id).each do |s_member|
CourseMember.create!(course_id: @course.id, user_id: s_member.user_id, role: 2)
end
end
course_module_types = params[:course_module_types]
@course.create_course_modules(course_module_types)
end
@ -151,7 +165,6 @@ class CoursesController < ApplicationController
begin
extra_params = Hash.new
extra_params[:school_id] = @school.id
extra_params[:is_public] = params[:is_public].present? ? params[:is_public] : 0
if @course.is_end && (course_params[:end_date].blank? || course_params[:end_date].to_date > Date.today)
extra_params[:is_end] = 0
@ -162,13 +175,18 @@ class CoursesController < ApplicationController
extra_params[:authentication] = params[:authentication]
extra_params[:professional_certification] = params[:professional_certification]
@course_list_name = params[:course_list_name].strip
@course_list = CourseList.find_by(name: @course_list_name)
if @course_list
extra_params[:course_list_id] = @course_list.id
if @course.subject
@course.start_date = params[:start_date]
else
new_course_list = CourseList.create(name: @course_list_name, user_id: current_user.id, is_admin: 0)
extra_params[:course_list_id] = new_course_list.id
extra_params[:is_public] = params[:is_public].present? ? params[:is_public] : 0
@course_list_name = params[:course_list_name].strip
@course_list = CourseList.find_by(name: @course_list_name)
if @course_list
extra_params[:course_list_id] = @course_list.id
else
new_course_list = CourseList.create(name: @course_list_name, user_id: current_user.id, is_admin: 0)
extra_params[:course_list_id] = new_course_list.id
end
end
@course.update_attributes!(course_params.merge(extra_params))
@ -183,6 +201,42 @@ class CoursesController < ApplicationController
end
end
def join_excellent_course
tip_exception("您已是课堂成员") if current_user.member_of_course?(@course)
tip_exception("请通过邀请码加入课堂") unless @course.excellent
tip_exception("该课堂已结束") if @course.is_end
begin
new_student = CourseMember.new(user_id: current_user.id, course_id: @course.id, role: 4)
new_student.save!
CourseAddStudentCreateWorksJob.perform_later(@course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, @course.id)
normal_status(0, "加入成功")
rescue => e
uid_logger_error(e.message)
tip_exception(e.message)
end
end
def informs
end
def update_informs
tip_exception("公告内容不能为空") if params[:description].blank?
inform = @course.inform || Inform.new(container: @course)
inform.description = params[:description]
inform.save!
normal_status("更新成功")
end
def online_learning
@subject = @course.subject
@stages = @subject&.stages
@user = current_user
@start_learning = @user_course_identity == Course::STUDENT && @subject&.learning?(current_user.id)
end
def search_course_list
search = params[:search] ? "%#{params[:search].strip}%" : "%%"
@course_lists = CourseList.where("name like ?", "#{search}")
@ -1075,14 +1129,31 @@ class CoursesController < ApplicationController
def validate_course_name
tip_exception("课堂名称不能为空!") if params[:course][:name].blank?
tip_exception("课程名称不能为空!") if params[:course_list_name].blank?
tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) &&
if params[:subject_id].blank? || (@course && @course.subject.blank?)
tip_exception("课程名称不能为空!") if params[:course_list_name].blank?
tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) &&
params[:course][:name].index(params[:course_list_name]) == 0
else
@subject = @course.present? ? @course.subject : Subject.find_by!(id: params[:subject_id])
tip_exception("开始时间不能为空") if params[:start_date].blank?
tip_exception("结束时间不能为空") if params[:end_date].blank?
tip_exception("结束时间必须晚于开始时间") if params[:end_date] <= params[:start_date]
tip_exception("开始时间和结束时间不能与往期开课时间重叠") if @course.nil? && @subject.max_course_end_date && params[:start_date] <= strf_date(@subject.max_course_end_date)
validate_start_end_date if @course.present?
tip_exception("开放课堂必须包含公告栏和在线学习模块") unless params[:course_module_types].include?("announcement") && params[:course_module_types].include?("online_learning")
end
tip_exception("课堂所属单位不能为空!") if params[:school].blank?
tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank?
@school = School.find_by!(name: params[:school].strip)
end
def validate_start_end_date
prev_course = @subject.courses.where("id < #{@course.id}").last
next_course = @subject.courses.where("id > #{@course.id}").first
tip_exception("开始时间和结束时间不能与其他期开课时间重叠") if prev_course && params[:start_date] <= strf_date(prev_course.end_date)
tip_exception("开始时间和结束时间不能与其他期开课时间重叠") if next_course && params[:end_date] >= strf_date(next_course.start_date)
end
# 超级管理员和课堂管理员的权限判断
def admin_allowed
unless @user_course_identity < Course::PROFESSOR

@ -1291,7 +1291,7 @@ class ExercisesController < ApplicationController
normal_status(0,"正在下载中")
else
set_export_cookies
render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets
render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
end

@ -260,7 +260,12 @@ class FilesController < ApplicationController
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?
@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
end

@ -171,6 +171,14 @@ class HomeworkCommonsController < ApplicationController
@student_works = @student_works.where(user_id: group_user_ids)
end
if @homework.homework_type == "group" && !params[:member_work].blank?
if params[:member_work].to_i == 1
@student_works = @student_works.where("user_id = commit_user_id")
elsif params[:member_work].to_i == 0
@student_works = @student_works.where("user_id != commit_user_id")
end
end
# 输入姓名和学号搜索
# TODO user_extension 如果修改 请调整
unless params[:search].blank?

@ -23,24 +23,19 @@ class MyshixunsController < ApplicationController
begin
ActiveRecord::Base.transaction do
begin
@shixun = Shixun.select(:id, :identifier).find(@myshixun.shixun_id)
@shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
@myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0)
# 实训在申请发布前,是否玩过实训,如果玩过需要更改记录,防止二次重置
shixun_mod = ShixunModify.where(:shixun_id => @shixun.id, :myshixun_id => @myshixun.id, :status => 1).take
shixun_mod.update_column(:status, 0) if shixun_mod
rescue Exception => e
logger.error("######reset_my_game_failed:#{e.message}")
raise("ActiveRecord::RecordInvalid")
end
end
# 删除版本库
GitService.delete_repository(repo_path: @repo_path)
GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?
rescue Exception => e
if e.message != "ActiveRecord::RecordInvalid"
logger.error("######delete_repository_error:#{e.message}")
logger.error("######delete_repository_error-:#{e.message}")
end
raise "delete_repository_error:#{e.message}"
end

@ -4,7 +4,7 @@ class StudentWorksController < ApplicationController
before_action :require_login, :check_auth
before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project]
:cancel_relate_project, :delete_work]
before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des,
:adjust_score, :show, :adjust_score, :supply_attachments, :revise_attachment,
:comment_list, :add_score, :add_score_reply, :destroy_score, :appeal_anonymous_score,
@ -15,12 +15,12 @@ class StudentWorksController < ApplicationController
before_action :teacher_allowed, only: [:adjust_score, :adjust_review_score, :deal_appeal_score]
before_action :course_student, only: [:new, :commit_des, :update_des, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :relate_project]
:cancel_relate_project, :relate_project, :delete_work]
before_action :my_work, only: [:commit_des, :update_des, :edit, :update, :revise_attachment, :appeal_anonymous_score,
:cancel_appeal]
before_action :edit_duration, only: [:edit, :update]
before_action :edit_duration, only: [:edit, :update, :delete_work]
before_action :end_or_late, only: [:new, :create, :search_member_list, :commit_des, :update_des]
before_action :require_score_id, only: [:destroy_score, :add_score_reply, :appeal_anonymous_score, :deal_appeal_score, :cancel_appeal]
@ -60,6 +60,25 @@ class StudentWorksController < ApplicationController
@members = @members.page(page).per(limit).includes(:course_group, user: :user_extension)
end
def delete_work
ActiveRecord::Base.transaction do
begin
work = @homework.student_works.find_by!(user_id: params[:user_id])
tip_exception("只有组长才能删除组员") if work.commit_user_id != current_user.id
work.update_attributes(description: nil, project_id: 0,
late_penalty: 0, work_status: 0,
commit_time: nil, update_time: nil, group_id: 0,
commit_user_id: nil, final_score: nil, work_score: nil, teacher_score: nil, teaching_asistant_score: nil)
work.attachments.destroy_all
work.tidings.destroy_all
normal_status("删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
end
end
end
def create
student_work = @homework.student_works.find_or_create_by(user_id: current_user.id)
@ -123,8 +142,9 @@ class StudentWorksController < ApplicationController
@current_user = current_user
if @homework.homework_type == "group"
# todo user_extension
@commit_user_id = @work.commit_user_id
@work_members = @course.students.where(user_id: @homework.student_works.where(group_id: @work.group_id).pluck(:user_id)).
order("course_members.id=#{@work.user_id} desc").includes(:course_group, user: :user_extension)
order("course_members.user_id=#{@work.commit_user_id} desc").includes(:course_group, user: :user_extension)
end
end
@ -136,7 +156,7 @@ class StudentWorksController < ApplicationController
begin
@work.description = params[:description]
@work.update_time = Time.now
@work.commit_user_id = current_user.id
# @work.commit_user_id = current_user.id
if @work.save!
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class)
@ -151,7 +171,8 @@ class StudentWorksController < ApplicationController
# 原成员更新描述、更新时间以及附件
@homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work|
work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id)
# work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id)
work.update_attributes(update_time: Time.now, description: @work.description)
work.attachments.destroy_all
@work.attachments.each do |attachment|
att = attachment.copy
@ -179,7 +200,7 @@ class StudentWorksController < ApplicationController
stu_work.update_attributes(user_id: user_id, description: @work.description, homework_common_id: @homework.id,
project_id: @work.project_id, late_penalty: @work.late_penalty,
work_status: @work.work_status, commit_time: Time.now, update_time: Time.now,
group_id: @work.group_id, commit_user_id: current_user.id)
group_id: @work.group_id, commit_user_id: @work.commit_user_id)
@work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
@ -460,7 +481,7 @@ class StudentWorksController < ApplicationController
filename_ = "#{@use&.student_id}_#{@use&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
filename = Base64.urlsafe_encode64(filename_.strip)
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# 作品调分

@ -25,13 +25,13 @@ class SubjectsController < ApplicationController
if reorder == "myshixun_count"
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")

@ -28,6 +28,10 @@ module CoursesHelper
def module_url mod, course
return nil if mod.blank? or course.blank?
case mod.module_type
when "announcement"
"/courses/#{course.id}/informs"
when "online_learning"
"/courses/#{course.id}/online_learning"
when "shixun_homework"
"/courses/#{course.id}/shixun_homeworks/#{mod.id}"
when "common_homework"
@ -261,4 +265,10 @@ module CoursesHelper
group_info
end
def last_subject_shixun user_id, subject
myshixun = Myshixun.where(user_id: user_id, shixun_id: subject&.shixuns).order("updated_at desc").first
return "" unless myshixun
stage_shixun = subject&.stage_shixuns.where(shixun_id: myshixun.shixun_id).take
progress = stage_shixun&.position.to_s + "-" + stage_shixun&.position.to_s + " " + myshixun.shixun&.name
end
end

@ -146,8 +146,8 @@ module ExportHelper
w_6 = "--"
end
w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges_count.to_s
w_8 = myshixun ? myshixun.try(:passed_time) == "--" ? "--" : format_time(myshixun.try(:passed_time)) : "--" # 通关时间
w_9 = myshixun ? (myshixun.try(:passed_count) > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时
w_8 = myshixun ? myshixun.try(:passed_time).to_s == "--" ? "--" : format_time(myshixun.try(:passed_time)) : "--" # 通关时间
w_9 = myshixun ? (myshixun.try(:passed_count).to_i > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时
w_10 = myshixun ? myshixun.output_times : 0 #评测次数
w_11 = myshixun ? myshixun.total_score : "--" #获得经验值
w_12 = w.final_score.present? ? w.final_score : 0
@ -543,7 +543,7 @@ module ExportHelper
end
def format_sheet_name name
name = name.gsub(":", "-")
name = name.gsub(":", "-").gsub("/", "_")
end
def rename_same_file(name, index)

@ -2,7 +2,7 @@ module StagesHelper
# 章节实训的通关情况
def stage_myshixun_status shixun, user
myshixun = Myshixun.where(user_id: user.id, shixun_id: shixun.id).first
myshixun = Myshixun.where(user_id: user.id, shixun_id: shixun.id).take
myshixun.try(:status) == 1 ? 1 : 0
end

@ -5,7 +5,11 @@ class Course < ApplicationRecord
belongs_to :teacher, class_name: 'User', foreign_key: :tea_id # 定义一个方法teacher该方法通过tea_id来调用User表
belongs_to :school, class_name: 'School', foreign_key: :school_id #定义一个方法school该方法通过school_id来调用School表
belongs_to :course_list
belongs_to :course_list, optional: true
# 所属实践课程
belongs_to :subject, optional: true
has_one :inform, as: :container, dependent: :destroy
has_many :course_infos, dependent: :destroy
# 课堂左侧导航栏的模块
@ -87,7 +91,7 @@ class Course < ApplicationRecord
NORMAL = 6 # 普通用户
Anonymous = 7 # 普未登录
validates :name, presence: true, length: { maximum: 30 }
validates :name, presence: true, length: { maximum: 60 }
after_create :create_board_sync, :act_as_course_activity, :send_tiding
@ -176,7 +180,7 @@ class Course < ApplicationRecord
end
def all_course_module_types
%w[activity shixun_homework common_homework group_homework graduation exercise poll attachment board course_group]
%w[activity announcement online_learning shixun_homework common_homework group_homework graduation exercise poll attachment board course_group]
end
def get_course_module_by_type(type)
@ -334,6 +338,8 @@ class Course < ApplicationRecord
def get_name_by_type(type)
case type
when 'activity' then '动态'
when 'announcement' then '公告栏'
when 'online_learning' then '在线学习'
when 'shixun_homework' then '实训作业'
when 'common_homework' then '普通作业'
when 'group_homework' then '分组作业'
@ -350,15 +356,17 @@ class Course < ApplicationRecord
def get_position_by_type(type)
case type
when 'activity' then 1
when 'shixun_homework' then 2
when 'common_homework' then 3
when 'group_homework' then 4
when 'graduation' then 5
when 'exercise' then 6
when 'poll' then 7
when 'attachment' then 8
when 'board' then 9
when 'course_group' then 10
when 'announcement' then 2
when 'online_learning' then 3
when 'shixun_homework' then 4
when 'common_homework' then 5
when 'group_homework' then 6
when 'graduation' then 7
when 'exercise' then 8
when 'poll' then 9
when 'attachment' then 10
when 'board' then 11
when 'course_group' then 12
else 100
end
end

@ -0,0 +1,3 @@
class Inform < ApplicationRecord
belongs_to :container, polymorphic: true, optional: true
end

@ -82,7 +82,7 @@ class Myshixun < ApplicationRecord
# 通关时间
def passed_time
self.status == 1 ? self.games.map(&:end_time).max : "--"
self.status == 1 ? self.games.select{|game| game.status == 2}.map(&:end_time).max : "--"
end
# 耗时

@ -0,0 +1,3 @@
class Partner < ApplicationRecord
has_many :users
end

@ -21,11 +21,12 @@ module Searchable::Course
def to_searchable_json
{
id: id,
author_name: teacher.real_name,
author_school_name: teacher.school_name,
author_name: teacher&.real_name,
author_school_name: teacher&.school_name,
visits_count: visits,
members_count: members_count,
is_public: is_public == 1
is_public: is_public == 1,
first_category_url: ApplicationController.helpers.module_url(none_hidden_course_modules.first, self)
}
end

@ -18,6 +18,9 @@ class Subject < ApplicationRecord
has_many :tidings, as: :container, dependent: :destroy
has_many :stages, -> { order("stages.position ASC") }, dependent: :destroy
# 开放课堂
has_many :courses, -> { order("courses.id ASC") }
validates :name, length: { maximum: 40 }
validates :description, length: { maximum: 5000 }
validates :learning_notes, length: { maximum: 500 }
@ -31,6 +34,11 @@ class Subject < ApplicationRecord
self.tidings << Tiding.new(user_id: self.user_id, trigger_user_id: self.user_id, belong_container_id: self.id, belong_container_type: 'Subject', tiding_type: "System", viewed: 0)
end
# 所有开课课堂的最大结束时间
def max_course_end_date
courses.pluck(:end_date).max
end
# 挑战过路径的成员数
def member_count
shixuns.pluck(:myshixuns_count).sum
@ -92,4 +100,8 @@ class Subject < ApplicationRecord
challenges = Challenge.where(shixun_id: shixuns.unhidden)
@tags = ChallengeTag.where(challenge_id: challenges).pluck(:name).uniq
end
def learning? user_id
Myshixun.where(user_id: user_id, shixun_id: shixuns).exists?
end
end

@ -138,6 +138,9 @@ class User < ApplicationRecord
# 视频
has_many :videos, dependent: :destroy
# 客户管理
belongs_to :partner
# Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) }
@ -378,6 +381,8 @@ class User < ApplicationRecord
@identity =
if admin?
User::EDU_ADMIN
elsif business?
User::EDU_BUSINESS
elsif creator_of_shixun?(shixun)
User::EDU_SHIXUN_MANAGER
elsif member_of_shixun?(shixun)

@ -12,5 +12,6 @@ json.courses @courses do |course|
json.is_accessible course.is_public == 1 || @user.course_identity(course) < Course::NORMAL
json.is_end course.is_end
json.first_category_url module_url(course.none_hidden_course_modules.first, course)
json.excellent course.excellent
end
json.courses_count @courses_count

@ -0,0 +1 @@
json.description @course.inform&.description

@ -0,0 +1,11 @@
json.stages @stages do |stage|
json.partial! 'stages/stage', locals: {stage: stage, user:@user, subject:@subject}
end
json.description @subject&.description
json.start_learning @start_learning
json.learned @start_learning ? @subject&.my_subject_progress : 0
json.last_shixun @start_learning ? last_subject_shixun(@user.id, @subject) : ""

@ -1,5 +1,5 @@
json.course_list_id @course.course_list.id
json.course_list_name @course.course_list.name
json.course_list_id @course.course_list&.id
json.course_list_name @course.course_list&.name
json.name @course.name
json.course_id @course.id
json.school @course.school&.name
@ -9,4 +9,6 @@ json.end_date @course.end_date
json.is_public @course.is_public
json.course_module_types @course.course_modules.where(hidden: 0).pluck(:module_type)
json.authentication @course.authentication
json.professional_certification @course.professional_certification
json.professional_certification @course.professional_certification
json.subject_id @course.subject_id
json.excellent @course.excellent

@ -21,6 +21,7 @@ json.switch_to_assistant switch_assistant_role(@is_student, @course, @user)
#json.join_course !@user.member_of_course?(@course)
#json.copy_course !@user.member_of_course?(@course) && @user.is_teacher?
json.course_identity @user_course_identity
json.excellent @course.excellent
if @course.is_end == 0
json.days_remaining (@course.end_date.to_date - Time.now.to_date).to_i
end

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

@ -17,6 +17,8 @@ json.homeworks @homework_commons.each do |homework|
json.status_time curr_status[:time]
json.time_status curr_status[:time_status]
json.allow_late homework.allow_late
# 只有在主目录才显示
json.upper_category_name homework.course_second_category&.name unless params[:category]
unless curr_status[:status].include?("未发布")
json.commit_count studentwork_count homework, 1, @member

@ -69,6 +69,7 @@ elsif @user_course_identity == Course::STUDENT
json.project_info project_info @work, @current_user, @user_course_identity
end
json.work_group @work.work_group_name
json.is_leader @work.user_id == @work.commit_user_id
end
end
@ -140,6 +141,7 @@ elsif @homework.homework_type == "group" || @homework.homework_type == "normal"
if @homework.homework_detail_group.base_on_project
json.project_info project_info work, @current_user, @user_course_identity
end
json.is_leader work.user_id == work.commit_user_id
json.work_group work.work_group_name
end

@ -11,7 +11,7 @@ json.array! @members do |member|
json.partial! 'users/user', locals: { user: member.user }
json.user_shixuns_count member.user.shixuns.published.count
#json.fans_count member.user.fan_count
json.brief_introduction member.user.user_extension.brief_introduction
#json.brief_introduction member.user.user_extension.brief_introduction
json.identity member.user.identity
json.school_name member.user.school_name
json.shixun_manager member.role == 1

@ -1,12 +1,14 @@
json.partial! "homework_commons/homework_public_navigation", locals: {homework: @homework, course: @course, user: @current_user}
json.work_id @work.id
json.description @work.description
json.
json.attachments @work.attachments do |atta|
json.partial! "attachments/attachment_simple", locals: {attachment: atta, delete: @work.delete_atta(atta)}
end
if @homework.homework_type == "group"
json.is_leader_work @work.user_id == @commit_user_id
json.min_num @homework.homework_detail_group.try(:min_num)
json.max_num @homework.homework_detail_group.try(:max_num)
@ -15,5 +17,6 @@ if @homework.homework_type == "group"
json.user_name member.user.real_name
json.group_name member.course_group_name
json.student_id member.user.student_id
json.is_leader member.user_id == @commit_user_id
end
end

@ -3,6 +3,7 @@ json.(@work, :description, :commit_time, :update_time)
json.is_evaluation @is_evaluation
json.author_name @is_evaluation ? "匿名" : @work.user.real_name
json.is_leader_work @work.user_id == @work.commit_user_id if @homework.homework_type == "group"
json.is_author @is_author
json.update_user_name @is_evaluation ? "匿名" : @work.commit_user.try(:real_name)
@ -17,8 +18,10 @@ unless @is_evaluation
json.project_info project_info @work, @current_user, @user_course_identity
end
json.work_members @work_members.each do |member|
json.user_name member.user.real_name
json.user_login member.user.login
json.work_members @work_members.each do |work|
json.user_name work.user.real_name
json.user_login work.user.login
json.work_id work.id
json.is_leader work.user_id == work.commit_user_id
end
end

@ -1,5 +1,6 @@
json.array! subjects do |subject|
json.id subject.id
json.excellent subject.excellent
json.image_url url_to_avatar(subject)
json.name subject.name
json.tag_name subject.repertoire.try(:name)

@ -1,3 +1,4 @@
json.members @subject.subject_members do |member|
json.partial! 'subject_member', locals: { user: member.user }
json.role member.role
end

@ -6,7 +6,7 @@ json.subject_score @subject.all_score
json.member_count @subject.member_count
json.allow_delete (@subject.status != 2 && @is_creator) || @user.admin?
json.publish_status publish_status(@subject, @is_creator, @user, @shixuns)
json.publish_status publish_status(@subject, @is_manager, @user, @shixuns)
json.allow_statistics @is_manager
json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager

@ -1,4 +1,4 @@
json.id user.id
json.name user.full_name
json.name user.real_name
json.login user.login
json.image_url url_to_avatar(user)

@ -16,6 +16,9 @@ json.top do
json.moop_cases_url "#{@old_domain}/moop_cases"
json.crowdsourcing_url "/crowdsourcing"
# 客户管理
json.customer_management_url current_user.partner ? "#{@old_domain}/cooperates/#{current_user.partner.try(:id)}/partner_list" : nil
json.career_url do
json.array! @career.to_a do |c|
if c[1].present?

@ -14,6 +14,7 @@ if @course
json.course_identity @course_identity
json.course_name @course.name
json.course_public @course.is_public
json.course_excellent @course.excellent
if params[:group_info]
json.group_info @course.teacher_group(@user.id) if @course_identity < Course::STUDENT
end

@ -7,7 +7,7 @@ json.grade @user.grade
json.follow_count @user.follow_count
json.fan_count @user.fan_count
json.identity @user.identity
json.brief_introduction @user.user_extension&.brief_introduction
#json.brief_introduction @user.user_extension&.brief_introduction
json.authentication @user.authentication
json.professional_certification @user.professional_certification
json.phone_binded @user.phone_binded?

@ -0,0 +1,16 @@
defaults: &defaults
access_key_id: 'test'
access_key_secret: 'test'
base_url: 'http://vod.cn-shanghai.aliyuncs.com'
cate_id: '-1'
callback_url: 'http://47.96.87.25:48080/api/callbacks/aliyun_vod.json'
signature_key: 'test12345678'
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *defaults

@ -346,6 +346,10 @@ Rails.application.routes.draw do
post 'switch_to_assistant'
post 'switch_to_student'
post 'exit_course'
get 'informs'
post 'update_informs'
get 'online_learning'
post 'join_excellent_course'
end
collection do
@ -432,6 +436,7 @@ Rails.application.routes.draw do
get :check_project
get :cancel_relate_project
post :relate_project
delete :delete_work
end
end
end

@ -0,0 +1,8 @@
class AddNewColumnToCourse < ActiveRecord::Migration[5.2]
def change
add_column :courses, :start_date, :date
add_column :courses, :subject_id, :integer, default: 0
add_index :courses, :subject_id
end
end

@ -0,0 +1,5 @@
class AddExcellentToCourses < ActiveRecord::Migration[5.2]
def change
add_column :courses, :excellent, :boolean, default: false
end
end

@ -0,0 +1,8 @@
class ModifyClassPeriodForCourses < ActiveRecord::Migration[5.2]
def change
Course.find_each do |c|
c.update_column(:class_period, c.class_period.to_i)
end
change_column :courses, :class_period, :integer
end
end

@ -0,0 +1,5 @@
class ModifyPathForChallenges < ActiveRecord::Migration[5.2]
def change
change_column :challenges, :path, :text
end
end

Binary file not shown.

@ -10,6 +10,7 @@ broadcastChannelOnmessage('refreshPage', () => {
})
function locationurl(list){
debugger
if (window.location.port === "3007") {
} else {
@ -158,7 +159,8 @@ export function initAxiosInterceptors(props) {
// console.log("401401401")
// }
if (response.data.status === 403||response.data.status === "403") {
locationurl('/403');
locationurl('/403');
}
if (response.data.status === 404) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -69,19 +69,33 @@ class ListPageIndex extends Component{
super(props);
this.state={
yslGuideone:undefined,
mysearch:undefined,
}
}
componentDidMount(){
var yslGuideone = window.sessionStorage.getItem('yslGuideone');
console.log("77");
var yslGuideone = window.localStorage.getItem('yslGuideone');
console.log("78");
console.log(yslGuideone);
var mysearchs= this.props.location.search===""?undefined:this.props.location.search===undefined?undefined:this.props.location.search==="?exhibition=true"?true:undefined;
this.setState({
yslGuideone:yslGuideone,
mysearch:mysearchs,
})
try {
if (yslGuideone === "true") {
console.log("true 字符串");
this.setState({
yslGuideone:true,
})
} else {
this.setState({
yslGuideone:false,
});
console.log("false 字符串");
}
}catch (e) {
console.log(e);
this.setState({
yslGuideone:false,
});
}
}
//
@ -93,20 +107,33 @@ class ListPageIndex extends Component{
// })
// }
componentWillUnmount(){
window.sessionStorage.setItem('yslGuideone', false);
// window.localStorage.setItem('yslGuideone', "false");
}
setwindowlocal=(bool)=>{
window.sessionStorage.setItem('yslGuideone', bool);
this.setState({
yslGuideone:bool,
mysearch:undefined,
});
var currenturl = this.props.location.pathname;
var newUrl = (currenturl.split("?"))[0];
window.history.pushState('','',newUrl);
window.localStorage.setItem('yslGuideone', bool);
try {
if (bool === "true") {
console.log("115");
console.log("true 字符串");
this.setState({
yslGuideone:true,
})
} else {
this.setState({
yslGuideone:false,
});
console.log("124");
console.log("false 字符串");
}
}catch (e) {
console.log(e);
this.setState({
yslGuideone:false,
});
}
}
render() {
let {yslGuideone,mysearch} =this.state;
let {yslGuideone} =this.state;
// console.log("98");
// console.log(yslGuideone);
// console.log(this.props.isAdmin());
@ -118,10 +145,10 @@ class ListPageIndex extends Component{
<div className="newMain clearfix">
{/*头部banner*/}
<CoursesBanner {...this.props}></CoursesBanner>
{/*{mysearch!==undefined?*/}
{/*下面是指引哦*/}
{/*{yslGuideone!==undefined?*/}
{/*(*/}
{/* mysearch===true?*/}
{/* yslGuideone===true?*/}
{/* <Guide*/}
{/* setwindowlocal={(b)=>this.setwindowlocal(b)}*/}
{/* >*/}

@ -261,9 +261,9 @@ class Fileslistitem extends Component{
</p>}
<p className="color-grey panel-lightgrey mt8 fl ml30" style={{width:'100%'}}>
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}>
<span className="mr50">
<span className="mr15 color-dark">{discussMessage.author.login}</span>
<span className="mr15 color-dark">{discussMessage.author.name}</span>
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</span>
<span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span>
<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span>
@ -302,7 +302,7 @@ class Fileslistitem extends Component{
<p className="color-grey panel-lightgrey mt8 fl ml30" style={{width:'100%'}}>
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}>
<pre className="color-dark">资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}</pre>
{/*<span className="mr50">*/}
{/*/!*<span className="mr15 color-dark"></span>*!/*/}

@ -310,7 +310,7 @@ class BoardsNew extends Component{
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}帖子</span>
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
onClick={() => this.props.history.goBack()}>
返回
{/*返回*/}
</a>
</p>
{/* notRequired */}

@ -5,6 +5,8 @@ import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
import { WordsBtn, getUploadActionUrl, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from 'educoder';
import axios from 'axios';
import Modals from '../../modals/Modals';
import _ from 'lodash'
const Search = Input.Search;
const CheckboxGroup = Checkbox.Group;
@ -67,15 +69,19 @@ class CommonWorkPost extends Component{
status: 'done'
}
})
const _memebers = response.data.members.slice(0);
this._edit_init_memebers = _memebers
delete response.data.members;
this.setState({
...response.data,
selectmemberslist: response.data.members || [],
selectmemberslist: _memebers || [],
// members: [],
task_status: response.data.members ? response.data.members.map(item => item.user_id) : [],
task_status: [], //_memebers ? _memebers.map(item => item.user_id) : [],
fileList: _fileList,
memberNumMin: response.data.min_num,
memberNumMax: response.data.max_num,
})
this.mine = _memebers.length ? _memebers[0] : null
// 分组
// this.setState({
// task_status:checkedValues,
@ -99,6 +105,11 @@ class CommonWorkPost extends Component{
group_name: response.data.group_name,
}
this.mine = mine
// const _memebers = response.data.members.slice(0);
if (response.data.members) {
delete response.data.members;
}
this.setState({
...response.data,
selectmemberslist: [mine],
@ -157,7 +168,7 @@ class CommonWorkPost extends Component{
}
if(isGroup){
if(userids!=undefined){
if(userids.length + 1<memberNumMin){
if(userids.length < memberNumMin){
this.setState({
minvalue: memberNumMin,
setvalue:"小于",
@ -165,7 +176,7 @@ class CommonWorkPost extends Component{
})
return
}else if(userids.length + 1>memberNumMax){
}else if(userids.length > memberNumMax){
this.setState({
minvalue: memberNumMax,
setvalue:"大于",
@ -424,30 +435,53 @@ class CommonWorkPost extends Component{
}
funtaskstatus=(checkedValues)=>{
let{members}=this.state;
let newlist =members.concat(this.state.selectmemberslist);
let newcheckedValues=checkedValues;
let selects=[];
// const selectobjct = this._findByUserId(check)
// selects.push(selectobjct)
for(var z=0; z<newcheckedValues.length; z++){
for(var i=0; i<newlist.length; i++){
if(newlist[i].user_id===newcheckedValues[z]){
selects.push(newlist[i])
break;
/**
比较 checkedValues this.state.selectmemberslist
checkedValues length > this.state.task_status.length 是新增 反之是删除
比较找到不同的id
去除重复的checkedValues留下的是新增task_status留下的是删除
*/
const _checkedValues = checkedValues.slice(0)
const _task_status = this.state.task_status.slice(0);
checkedValues.forEach(item => {
this.state.task_status.forEach(_item => {
if (item == _item) {
_.remove(_checkedValues, (item)=> item == _item)
_.remove(_task_status, (item)=> item == _item)
}
}
}
})
})
let _selectmemberslist = this.state.selectmemberslist.slice(0)
if (_checkedValues.length) { // 新增
_selectmemberslist.push( this.state.members.filter(item => item.user_id == _checkedValues[0])[0])
} else if (_task_status.length) { // 删除
_.remove(_selectmemberslist, (item)=> item.user_id == _task_status[0])
}
// let{members}=this.state;
// let newlist =members.concat(this.state.selectmemberslist);
// let newcheckedValues=checkedValues;
// let selects= this.mine ? [this.mine] : [];
// // const selectobjct = this._findByUserId(check)
// // selects.push(selectobjct)
// for(var z=0; z<newcheckedValues.length; z++){
// for(var i=0; i<newlist.length; i++){
// if(newlist[i].user_id===newcheckedValues[z]){
// selects.push(newlist[i])
// break;
// }
// }
// }
this.setState({
task_status:checkedValues,
selectmemberslist: selects
selectmemberslist: _selectmemberslist
// selectmemberslist:checkedValues
})
}
delecttask_status=(id)=>{
doDelete = (id) => {
let{selectmemberslist,task_status}=this.state;
let newlist=task_status.slice(0);
let selects=selectmemberslist;
@ -468,6 +502,52 @@ class CommonWorkPost extends Component{
selectmemberslist:selects
})
}
delecttask_status=(id)=>{
if (this.isEdit) {
let deleteOldMemberIndex = -1;
if (this._edit_init_memebers && this._edit_init_memebers.length) {
this._edit_init_memebers.some((item, index) => {
if (item.user_id == id) {
deleteOldMemberIndex = index;
return true
}
})
if (deleteOldMemberIndex == -1) {
this.doDelete(id)
return;
} else {
}
}
this.props.confirm({
content: <div>
<div>TA的作品将被删除</div>
<div>是否确认删除</div>
</div>,
onOk: () => {
let workId=this.props.match.params.workId;
const url = `/homework_commons/${workId}/student_works/delete_work.json`;
axios.delete(url, { data: {
user_id: id
}})
.then((response) => {
if (response.data.status == 0) {
this.searchValue()
this.doDelete(id)
deleteOldMemberIndex != -1 && this._edit_init_memebers.splice(deleteOldMemberIndex, 1)
}
})
.catch(function (error) {
console.log(error);
});
}
})
} else {
this.doDelete(id)
}
}
gocannel=()=>{
this.props.history.goBack()

@ -248,30 +248,16 @@ class CoursesBanner extends Component {
axios.post(url).then((response) => {
if(response!==undefined){
window.location.href = "/courses/" + response.data.new_course_id+"/students";
}else {
this.modalCancel();
return
}
this.modalCancel();
// window.location.href = "/courses/" + response.data.new_course_id;
}).catch(function (error) {
}).catch( (error)=> {
this.modalCancel();
console.log(252);
console.log(error);
});
// axios.interceptors.response.use((response) => {
// if (response != undefined)
// if (response && response.data.status === -1) {
// this.setState({
// antIcon: false,
// })
//
// }
// return response;
// }, (error) => {
// //TODO 这里如果样式变了会出现css不加载的情况
//
// });
}
if(this.state.metype===6){

@ -683,7 +683,7 @@ class Coursesleftnav extends Component{
}else if(result.source.droppableId==="course_group"){
let url ="/course_groups/"+result.draggableId+"/move_category.json"
this.droppablepost(url,result.destination.index)
this.droppablepost(url,result.destination.index+1)
}
@ -837,7 +837,7 @@ class Coursesleftnav extends Component{
.droppableul{
max-height: 500px;
overflow-y:auto;
overflow:hidden auto;
overflow-x:hidden;
}
.mr13{
@ -928,8 +928,9 @@ class Coursesleftnav extends Component{
<a className="fl pl46 pd0 Draggablelichild">
<span className={this.props.location.pathname===iem.second_category_url?"color-blue fl ml38 maxwidth155 task-hide Draggablelichild":"fl ml38 maxwidth155 task-hide Draggablelichild"}>{iem.category_name}</span>
<span className={twosandiantype===undefined?this.props.location.pathname===iem.second_category_url?"fr mr20 color-blue Draggablelichild font-14":"fr mr20 color999 Draggablelichild font-14":item.type===twosandiantypes&&twosandiantype===index?"none":this.props.location.pathname===iem.second_category_url?"fr mr20 color-blue Draggablelichild font-14":"fr mr20 color999 Draggablelichild font-14"} >{iem.category_count===0?"":iem.category_count}</span>
<span className={twosandiantype===undefined?this.props.location.pathname===iem.second_category_url?"fr mr20 color-blue Draggablelichild font-14":"fr mr20 color999 Draggablelichild font-14":item.type===twosandiantypes&&twosandiantype===index&&iem.category_name!="未分班"?"none":this.props.location.pathname===iem.second_category_url?"fr mr20 color-blue Draggablelichild font-14":"fr mr20 color999 Draggablelichild font-14"} >{iem.category_count===0?"":iem.category_count}</span>
{item.type===twosandiantypes&&twosandiantype===index?
iem.category_name==="未分班"?"":
iem.category_type==="graduation_topics"||iem.category_type==="graduation_tasks"?
<span className={"fr mr20 color999 Draggablelichild font-14"} >{iem.category_count===0?"":iem.category_count}</span>
:<Popover placement="right" content={this.content(item,iem,index)} trigger="hover" key={index}>

@ -336,6 +336,16 @@ class ExerciseReviewAndAnswer extends Component{
}
// 选择题,切换答案
changeOption = (index,ids) =>{
//console.log(index+" "+ids);
this.setState(
(prevState) => ({
exercise_questions : update(prevState.exercise_questions, {[index]: { user_answer: {$set: ids} }}),
})
)
}
//简答题 显示和隐藏答案
changeA_flag=(index,status)=>{
this.setState(
@ -726,6 +736,7 @@ class ExerciseReviewAndAnswer extends Component{
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
changeOption={(index,ids)=>this.changeOption(index,ids)}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
index={key}
></Single>
@ -739,6 +750,7 @@ class ExerciseReviewAndAnswer extends Component{
exercise={exercise}
questionType={item}
user_exercise_status={user_exercise_status}
changeOption={(index,ids)=>this.changeOption(index,ids)}
changeQuestionStatus={(No,flag)=>this.changeQuestionStatus(No,flag)}
index={key}

@ -163,6 +163,10 @@ class Testpapersettinghomepage extends Component{
}
}
//打开pdf
confpdf = (url) =>{
window.open(url);
}
/// 确认是否下载
confirmysl(url,child){
let params ={}
@ -372,7 +376,7 @@ class Testpapersettinghomepage extends Component{
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right":"-34px","left":"unset","height":"auto"}}>
<li><a onClick={()=>this.confirmysl(`/exercises/${this.props.match.params.Id}/exercise_lists.xlsx`,this.child)}>学生成绩</a></li>
<li><a onClick={()=>this.confirmysl(`/exercises/${this.props.match.params.Id}/export_exercise`,this.child)} >空白试卷</a></li>
<li><a onClick={()=>this.confpdf(`/api/exercises/${this.props.match.params.Id}/export_exercise`)} >空白试卷</a></li>
{/*<li><a onClick={()=>this.confirmysl(`/zip/export_exercises?exercise_id=${this.props.match.params.Id}${this.state.groupyslsval===null||this.state.groupyslsval===undefined?null:this.state.groupyslsval}`)}>学生答题试卷</a></li>*/}
</ul>
</li></Spin>:""}

@ -15,6 +15,7 @@ class Multiple extends Component{
saveId=(value)=>{
let question_id=this.props.questionType.question_id;
let url=`/exercise_questions/${question_id}/exercise_answers.json`;
let {index}=this.props;
axios.post((url),{
exercise_choice_id:value
}).then((result)=>{
@ -25,6 +26,7 @@ class Multiple extends Component{
}else{
k=0;
}
this.props.changeOption && this.props.changeOption(index,value);
this.props.changeQuestionStatus && this.props.changeQuestionStatus(parseInt(this.props.questionType.q_position)-1,k);
}
}).catch((error)=>{
@ -42,14 +44,14 @@ class Multiple extends Component{
console.log(questionType);
return(
<div className="pl30 pr30 singleDisplay">
<Checkbox.Group disabled={ user_exercise_status == 1 ? true : false } onChange={this.saveId} defaultValue={questionType.user_answer}>
<Checkbox.Group disabled={ user_exercise_status == 1 ? true : false } onChange={this.saveId} value={questionType.user_answer}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = `${tagArray[key]}.`
return(
<p className="clearfix mb15 df">
<Checkbox className="fl lineh-20 " value={item.choice_id}>{prefix}</Checkbox>
<Checkbox className="fl lineh-15 df mr8 mt2" value={item.choice_id}>{prefix}</Checkbox>
{/* <span class="fl lineh-20 mt1"></span> */}
{/* <span style={{display:"inline-block"}} className="markdown-body " dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}
<MarkdownToHtml content={item.choice_text} selector={'multiple_' + (this.props.index + 1) + (key + 1)}

@ -16,11 +16,13 @@ class single extends Component{
changeItem=(e)=>{
let choiceId=e.target.value;
let question_id=this.props.questionType.question_id;
let {index}=this.props;
let url=`/exercise_questions/${question_id}/exercise_answers.json`;
axios.post((url),{
exercise_choice_id:choiceId
}).then((result)=>{
if(result){
this.props.changeOption && this.props.changeOption(index,[choiceId]);
this.props.changeQuestionStatus && this.props.changeQuestionStatus(parseInt(this.props.questionType.q_position)-1,1);
}
}).catch((error)=>{
@ -38,12 +40,12 @@ class single extends Component{
let isJudge = questionType.question_type == 2
return(
<div className="pl30 pr30 singleDisplay">
<Radio.Group disabled={ user_exercise_status == 1 ? true : false } defaultValue={questionType.user_answer[0]} onChange={this.changeItem}>
<Radio.Group disabled={ user_exercise_status == 1 ? true : false } value={questionType.user_answer[0]} onChange={this.changeItem}>
{
questionType.question_choices && questionType.question_choices.map((item,key)=>{
let prefix = isJudge ? undefined : `${tagArray[key]}.`
return(
<p className={parseInt(questionType.question_type) == 0 ? "clearfix mb15 df" : "fl mr40"}>
<p className={parseInt(questionType.question_type) == 0 ? "clearfix mb15 df" : "fl mr40 df"}>
<Radio className="fl lineh-20" value={item.choice_id}>{prefix}</Radio>
{/* <span className="fl lineh-20 mr3 "></span> */}
{/* <span style={{display:"inline-block", 'margin-top': '-1px'}} className="markdown-body fl " dangerouslySetInnerHTML={{__html: markdownToHTML1(item.choice_text)}}></span> */}

@ -283,11 +283,11 @@ class GraduateTaskItem extends Component{
{this.props.isAdmin?
<div className="mt13">
<WordsBtn style="blue" to={"/courses/"+coursesId+"/graduation_tasks/"+taskid+"/edit"} className="colorblue font-16 mrf4 fr">
<a className="btn colorblue">编辑</a>
<WordsBtn style="blue" to={"/courses/"+coursesId+"/graduation_tasks/"+categoryid+"/"+taskid+"/setting"} className="colorblue font-16 mrf4 fr">
<a className="btn colorblue">设置</a>
</WordsBtn>
<WordsBtn style="blue" to={"/courses/"+coursesId+"/graduation_tasks/"+categoryid+"/"+taskid+"/setting"} className="colorblue font-16 mr20 fr">
<a className="btn colorblue" >设置</a>
<WordsBtn style="blue" to={"/courses/"+coursesId+"/graduation_tasks/"+taskid+"/edit"} className="colorblue font-16 mr20 fr">
<a className="btn colorblue" >编辑</a>
</WordsBtn>
</div>

@ -439,10 +439,24 @@ class GraduationTasksSubmitnew extends Component{
).then((response) => {
this.setState({
spinnings:false
})
if(response!==undefined){
this.goback()
});
// /courses/2915/graduation_tasks/1301/appraise
// window.location.href
if(response){
if(response.data){
if(response.data.work_id){
window.location.href=`/courses/${this.props.match.params.coursesId}/graduation_tasks/${response.data.work_id}/appraise`
}
}
}
// console.log(this.props);
// console.log(response);
// 新需求
// https://www.trustie.net/issues/23015
// if(response!==undefined){
// this.goback()
// }
// if(response.status===200) {
// GraduationTasksnewtype=false;
// if(response.data.status===0){
@ -458,6 +472,9 @@ class GraduationTasksSubmitnew extends Component{
// }
// }
}).catch((error) => {
this.setState({
spinnings:false
});
console.log(error)
})

@ -179,8 +179,13 @@ class GraduationTasks extends Component{
})
.then((result)=>{
if(result.data.status==0){
this.setState({
checkBoxValues:[],
checkAllValue:false
})
this.fetchAll(search,page,order,15)
this.props.showNotification(`${result.data.message}`);
this.fetchAll(search,page,order,15)
}
}).catch((error)=>{
console.log(error);
@ -554,9 +559,10 @@ class GraduationTasks extends Component{
}
// 题库选用成功后刷新页面
useBankSuccess=(checkBoxValues,object_ids)=>{
// debugger
//debugger
let {search,page,order,all_count} = this.state;
this.fetchAll(search,page,order,all_count)
}
getcourse_groupslist=(id)=>{
this.setState({
@ -651,7 +657,7 @@ class GraduationTasks extends Component{
</Link>
</WordsBtn> : ""}
{this.props.isAdmin() ?<UseBank {...this.props} {...this.state} object_type={"gtask"} useBankSuccess={(checkBoxValues,object_ids)=>this.useBankSuccess=(checkBoxValues,object_ids)}></UseBank>:""}
{this.props.isAdmin() ?<UseBank {...this.props} {...this.state} object_type={"gtask"} useBankSuccess={(checkBoxValues,object_ids)=>this.useBankSuccess(checkBoxValues,object_ids)}></UseBank>:""}
</React.Fragment>
}

@ -355,6 +355,13 @@ onBoardsNew=()=>{
DownloadMessageval:undefined
})
}
// 题库选用成功后刷新页面
useBankSuccess=(checkBoxValues,object_ids)=>{
//debugger
let {searchValue,page,status} =this.state
this.fetchAll(searchValue,page,status);
}
render(){
let {
searchValue,

@ -218,9 +218,9 @@ class studentsList extends Component{
})
this.fetchAll()
const isAdmin = this.props.isAdmin()
if (isAdmin) {
this.fetchCourseGroups()
}
// if (isAdmin) {
this.fetchCourseGroups();
// }
isAdmin && on('addStudentSuccess', this.addStudentSuccessListener)
isAdmin && on('updateNavSuccess', this.updateNavSuccess)

@ -41,7 +41,8 @@ class CoursesNew extends Component {
searchlist: [],
searchlistscholl:[],
listvalue: undefined,
fetching:false
fetching:false,
boolxinjian:false,
}
}
@ -80,6 +81,9 @@ class CoursesNew extends Component {
}).catch((error) => {
console.log(error);
})
this.setState({
boolxinjian:false,
});
}else{
let url = "/courses/new.json"
axios.get(url).then((result) => {
@ -96,18 +100,25 @@ class CoursesNew extends Component {
});
this.handleSearchschool(user_school);
this.setState({
boolxinjian:true,
});
}
}
componentDidUpdate(prevProps){
// if(prevProps.current_user!=this.props.current_user){
// if(this.props.current_user.user_identity==="学生"){
// window.location.href ="/403"
// }
// }
}
componentDidUpdate(prevProps) {
if(prevProps.current_user !== this.props.current_user){
let user_school=this.props.current_user&&this.props.current_user.user_school;
this.props.form.setFieldsValue({
school:user_school,
});
this.setState({
school:user_school,
});
this.handleSearchschool(user_school);
}
}
onChangeTimepublishs = (date, dateString) => {
if(dateString===""){
this.setState({
@ -206,8 +217,23 @@ class CoursesNew extends Component {
if (response.data.status === 0) {
// this.goback()
window.location.href=first_category_url+"?exhibition=true";
window.sessionStorage.setItem('yslGuideone', true);
window.location.href=first_category_url;
if(this.state.boolxinjian===true) {
var yslGuideone = window.localStorage.getItem('yslGuideone');
try {
if (yslGuideone === null) {
window.localStorage.setItem('yslGuideone', "true");
return
}
if (yslGuideone === undefined) {
window.localStorage.setItem('yslGuideone', "true");
return
}
} catch (e) {
}
}
}
}).catch((error) => {
console.log(error)
@ -251,8 +277,24 @@ class CoursesNew extends Component {
).then((response) => {
if (response.status === 200) {
// this.goback
window.location.href=response.data.first_category_url+"?exhibition=true";
window.sessionStorage.setItem('yslGuideone', true);
window.location.href=response.data.first_category_url;
if(this.state.boolxinjian===true){
var yslGuideone = window.localStorage.getItem('yslGuideone');
try {
if(yslGuideone=== null){
window.localStorage.setItem('yslGuideone', "true");
return
}
if(yslGuideone=== undefined){
window.localStorage.setItem('yslGuideone', "true");
return
}
}catch (e) {
}
}
}
}).catch((error) => {
console.log(error)
@ -405,9 +447,10 @@ class CoursesNew extends Component {
const propsWithoutForm = Object.assign({}, this.props)
delete propsWithoutForm.form
const options = this.state.searchlist && this.state.searchlist.map(d => <Option key={d.name} value={d.name}>{d.name}</Option>);
const optionschool = this.state.searchlistscholl&&this.state.searchlistscholl.map(z => <Option key={z} value={z}>{z}</Option>);
const optionschool = this.state.searchlistscholl===undefined?"":this.state.searchlistscholl===null?"":this.state.searchlistscholl==="[]"?"":this.state.searchlistscholl.map(z => <Option key={z} value={z}>{z}</Option>);
// console.log(this.props.current_user.user_school)
// form合并了
console.log("获取到的数据");
console.log(this.state);
console.log(this.props);
console.log(this.props.current_user);

@ -6,7 +6,9 @@ import guihome2 from "../../../images/guideimg/guihome2.jpg";
import guihome3 from "../../../images/guideimg/guihome3.jpg";
import guihome4 from "../../../images/guideimg/guihome4.jpg";
import guihome5 from "../../../images/guideimg/guihome5.jpg";
import guihome6 from "../../../images/guideimg/guihome6.jpg";
import guihome6 from "../../../images/guideimg/guihome6.jpg";
// import guihome6 from "../../../images/guideimg/guihome6.png";
// import guihome7 from "../../../images/guideimg/guihome7.png";
class Guide extends Component {
@ -60,7 +62,7 @@ class Guide extends Component {
page:i,
})
if(i===7){
this.props.setwindowlocal(false);
this.props.setwindowlocal("false");
}
}
render() {
@ -123,6 +125,7 @@ class Guide extends Component {
page===6?
<div className="guide-content">
<img className={mywidth===1?"ysldiv61024":mywidth===2?"ysldiv61280":mywidth===3?"ysldiv61440":mywidth===4?"ysldiv61680":mywidth===5?"ysldiv61900":mywidth===6?"ysldiv61366":mywidth===7?"ysldiv61600":"ysldiv61900"} src={guihome6} onClick={(i)=>this.thissetPage(7)}/>
{/*<img className={mywidth===1?"ysldiv71024":mywidth===2?"ysldiv71280":mywidth===3?"ysldiv71440":mywidth===4?"ysldiv71680":mywidth===5?"ysldiv71900":mywidth===6?"ysldiv71366":mywidth===7?"ysldiv71600":"ysldiv71900"} src={guihome7} onClick={(i)=>this.thissetPage(7)}/>*/}
</div>
:
""

@ -369,7 +369,7 @@ class Listofworksstudentone extends Component {
{
record.submitstate === "未提交" ?<span style={{ color: '#9A9A9A'}}>--</span>
:
<span style={{"text-align": "center"}}
<span style={{textAlign: "center"}}
className="color-blue"
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</span>
}
@ -693,7 +693,7 @@ class Listofworksstudentone extends Component {
render: (text, record) => (
record.submitstate === "未提交" ? <span style={{ color: '#9A9A9A'}}>--</span> :
<span>
<a style={{"text-align": "center"}} className="color-blue"
<a style={{textAlign: "center"}} className="color-blue"
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a>
</span>
)
@ -987,7 +987,7 @@ class Listofworksstudentone extends Component {
render: (text, record) => (
record.submitstate === "未提交" ? <span style={{ color: '#9A9A9A'}}>--</span> :
<span>
<a style={{"text-align": "center"}} className="color-blue"
<a style={{textAlign: "center"}} className="color-blue"
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a>
</span>
)

@ -157,6 +157,7 @@ class ShixunStudentWork extends Component {
lunxun:false,
duplicatechecking:false,
});
return;
}
}
}
@ -177,6 +178,9 @@ class ShixunStudentWork extends Component {
description: response.data.message
});
}
this.setState({
lunxun:true,
})
setInterval(() => {
console.log("开始轮询了");
if(this.state.lunxun===true){

@ -470,4 +470,49 @@
margin-left: 27%;
margin-right: 0;
height: 40%;
}
.ysldiv71900{
margin-top: 16%;
margin-left: 34%;
margin-right: 19%
}
.ysldiv71680{
margin-top: 18%;
margin-left: 31%;
margin-right: 14%;
}
.ysldiv71600{
margin-top: 19%;
margin-left: 30%;
margin-right: 12%;
}
.ysldiv71440{
margin-top: 21%;
margin-left: 28%;
margin-right: 8%;
}
.ysldiv71280{
margin-top: 24%;
margin-left: 25%;
margin-right: 3%;
height: 53%;
}
.ysldiv71366{
margin-top: 22%;
margin-left: 26%;
margin-right: 6%;
height: 53%;
}
.ysldiv71024{
margin-top: 31%;
margin-left: 27%;
margin-right: 0;
height: 40%;
}

@ -686,6 +686,7 @@ class ShixunHomework extends Component{
ModalSave:this.cancelmodel,
Loadtype:false,
checkBoxValues:[],
checkedtype:false,
})
this.props.showNotification(response.data.message)
this.homeworkupdatalist(Coursename,page,order);
@ -1018,8 +1019,9 @@ class ShixunHomework extends Component{
<div className="edu-back-white">
<p className="clearfix padding30 bor-bottom-greyE">
<p style={{height: '20px'}}>
<span className="font-18 fl color-dark-21">{datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:datas&&datas.category_name+" 作业列表"}</span>
<li className="fr">
{/*<span className="font-18 fl color-dark-21">{datas&&datas.category_name===undefined||datas&&datas.category_name===null?datas&&datas.main_category_name:datas&&datas.category_name+" 作业列表"}</span>*/}
<span className="font-18 fl color-dark-21">实训作业</span>
<li className="fr">
{this.props.isAdmin()===true?datas&&datas.category_name===undefined||datas&&datas.category_name===null?
<span>
<WordsBtn style="blue" onClick={()=>this.addDir()} className={"mr30 font-16"}>添加目录</WordsBtn>

@ -370,7 +370,7 @@ class Shixunechart extends Component {
</div>
<div className="fl with65" style={{paddingLeft: "5%"}}>
<li className="mt5 mb5">{data&&data.username}</li>
<li className="mt5 mb5">{data!==undefined?"":data.student_id===undefined?"":data.student_id===null?"":data.student_id}</li>
<li className="mt5 mb5">{data!==undefined?"--":data.student_id===undefined?"--":data.student_id===null?"--":data.student_id}</li>
<li className="mt5 mb5 color-orange03"><span className="color-orange03">{data&&data.echart_data===undefined?"":data&&data.echart_data.myself_eff[1]}</span></li>
<li className="mt5 mb5 color-orange03"><span className="color-orange03">{data&&data.echart_data===undefined?"":data&&data.echart_data.myself_eff[0]}</span></li>
</div>
@ -396,7 +396,7 @@ class Shixunechart extends Component {
</div>
<div className="fl with65" style={{paddingLeft: "5%"}}>
<li className="mt5 mb5">{data&&data.username}</li>
<li className="mt5 mb5">{data!==undefined?"":data.student_id===undefined?"":data.student_id===null?"":data.student_id}</li>
<li className="mt5 mb5">{data!==undefined?"--":data.student_id===undefined?"--":data.student_id===null?"--":data.student_id}</li>
<li className="mt5 mb5 color-orange03"><span className="color-orange03">{data&&data.echart_data===undefined?"":data&&data.echart_data.myself_object[1]}</span></li>
</div>
</div>

@ -500,8 +500,8 @@ class PathDetailIndex extends Component{
</div>
{
detailInfoList===undefined?"":detailInfoList.allow_add_member===true? <div>
<div className="fr ml15 flex1"><a onClick={()=>this.moveup(item)}><Tooltip title="上移"><i className="color-green font-18 iconfont icon-xiangshangyi"></i></Tooltip></a></div>
<div className="fr ml15 flex1 "><a onClick={()=>this.movedown(item)}><Tooltip title="下移"><i className="color-green font-18 iconfont icon-xiangxiayi"></i></Tooltip></a></div>
{key!=0?<div className="fr ml15 flex1"><a onClick={()=>this.moveup(item)}><Tooltip title="上移"><i className="color-green font-18 iconfont icon-xiangshangyi"></i></Tooltip></a></div>:""}
{key+1!=detailInfoList.members.length?<div className="fr ml15 flex1 "><a onClick={()=>this.movedown(item)}><Tooltip title="下移"><i className="color-green font-18 iconfont icon-xiangxiayi"></i></Tooltip></a></div>:""}
</div>
:""
}

@ -826,6 +826,9 @@ submittojoinclass=(value)=>{
{/* p 老师 l 学生 */}
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/shixuns`}>我的实训</Link></li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/paths`}>我的实践课程</Link></li>
<li style={{display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.customer_management_url===null || this.props.Headertop.customer_management_url===""? 'none' : 'block'}}>
<a href={this.props.Headertop === undefined ? '' : this.props.Headertop.customer_management_url}>客户管理</a>
</li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/projects`}>我的项目</Link></li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/package`}>我的众包</Link></li>
<li><a href={`/account/profile`}>账号管理</a></li>

@ -362,6 +362,7 @@ export function TPMIndexHOC(WrappedComponent) {
overflow: hidden;
}
.newHeaders{
// position: fixed;
max-width: unset;
background: #24292D !important;
width: 100%;

@ -113,7 +113,7 @@ class Collaborators extends Component {
onSearchcalue:""
})
let admintype = this.props.identity;
if (admintype>3) {
if (admintype>4) {
this.props.showSnackbar("您没有权限");
return
}
@ -329,6 +329,10 @@ class Collaborators extends Component {
let id = this.props.match.params.shixunId;
let url = "/shixuns/" + id + "/collaborators_delete.json?user_id=" + collaborators_deletevalue;
axios.delete(url).then((response) => {
if (this.props.current_user.user_id == collaborators_deletevalue) {
this.props.history.push('/shixuns')
return;
}
this.props.showSnackbar(response.data.message);
this.updatacomponentDiddata();
this.setState({

@ -183,7 +183,7 @@ class SearchPage extends Component{
return (
<a key={key}
href={
item.type==="shixun"?`/shixuns/${item.identifier}/challenges`:item.type==="course"?`/courses/${item.id}/students`:item.type==="subject"?`/paths/${item.id}`:item.type==="memo"?`/forums/${item.id}`:""
item.type==="shixun"?`/shixuns/${item.identifier}/challenges`:item.type==="course"?`${item.first_category_url}`:item.type==="subject"?`/paths/${item.id}`:item.type==="memo"?`/forums/${item.id}`:""
}
target="_blank"
>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Inform, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Partner, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save