Merge branch 'courseware' of http://bdgit.educoder.net/Hjqreturn/educoder into courseware

courseware
dinglink 5 years ago
commit e38adfb861

@ -112,4 +112,4 @@ gem 'request_store'
# 敏感词汇
gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'

@ -1,5 +1,6 @@
class AdminConstraint
def matches?(request)
return true
laboratory = Laboratory.first
return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]

@ -21,7 +21,7 @@ class Admins::BaseController < ApplicationController
def require_admin!
return if current_user.blank? || !current_user.logged?
return if current_user.admin_or_business?
return if current_user.admin_or_business? || current_user.admin_visitable?
render_forbidden
end

@ -13,7 +13,9 @@ class Admins::CoursesController < Admins::BaseController
format.js
format.html
format.xlsx do
@courses = courses.includes(:school, :students, :teacher_course_members, :informs, :course_videos, :attachments, :homework_commons, :course_activities, teacher: [user_extension: :department])
@courses = courses.not_deleted.includes(:school, :students, :teacher_course_members, :informs, :course_videos,
:live_links, :attachments, :homework_commons,
teacher: [user_extension: :department])
filename = "课堂列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end

@ -63,6 +63,6 @@ class Admins::UsersController < Admins::BaseController
def update_params
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
mail phone location location_city school_id department_id admin business is_test
password professional_certification authentication])
password professional_certification authentication admin_visitable])
end
end

@ -52,10 +52,12 @@ class AttendancesController < ApplicationController
current_end_time = Time.current.strftime("%H:%M:%S")
history_attendances = @course.course_attendances.where("attendance_date < '#{current_date}' or
(attendance_date = '#{current_date}' and end_time < '#{current_end_time}')")
all_member_attendances = CourseMemberAttendance.where(course_attendance_id: history_attendances)
if params[:group_id].present?
history_attendances = history_attendances.joins(:course_attendance_groups).where(course_attendance_groups: {course_group_id: [params[:group_id], 0]})
all_member_attendances = all_member_attendances.joins(:course_member).where(course_members: {course_group_id: params[:group_id]})
all_member_attendances = CourseMemberAttendance.where(course_attendance_id: history_attendances)
.joins(:course_member).where(course_members: {course_group_id: params[:group_id]})
else
all_member_attendances = CourseMemberAttendance.where(course_attendance_id: history_attendances)
end
history_attendances = history_attendances.order("attendance_date desc, start_time desc")

@ -164,6 +164,8 @@ class ChallengesController < ApplicationController
@challenges = @shixun.challenges.joins(join_sql).select(base_columns).uniq
@shixun_modify = (@challenges.select{|c| c.status.present? }.size == @challenges.size)
#@challenges = @shixun.challenges.fields_for_list
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user
@ -313,19 +315,27 @@ class ChallengesController < ApplicationController
end
rescue => e
tip_exception("上移失败: #{e.message}")
raise ActiveRecord::Rollback
end
end
def destroy
next_challenges = @shixun.challenges.where("position > #{@challenge.position}")
next_challenges.update_all("position = position - 1")
# Todo: 实训修改后,关卡需要重置
# shixun_modify_status_without_publish(@shixun, 1)
@challenge.destroy
# 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
begin
ActiveRecord::Base.transaction do
next_challenges.update_all("position = position - 1")
# Todo: 实训修改后,关卡需要重置
# shixun_modify_status_without_publish(@shixun, 1)
@challenge.destroy
# 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
rescue => e
tip_exception("删除关卡失败: #{e.message}")
raise ActiveRecord::Rollback
end
end

@ -38,7 +38,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController
student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql
subquery = StudentWork.where('homework_common_id = hcs.id')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
course_ids = Course.where('courses.created_at > ?', start_time)
.where('courses.created_at <= ?', end_time)
@ -149,7 +149,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController
def get_valid_course_count(ids)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Course.joins(practice_homeworks: :homework_commons_shixun)
@ -160,7 +160,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController
def get_valid_shixun_count(ids)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Shixun.joins(homework_commons_shixuns: :homework_common)
.where(homework_commons: { homework_type: 4 })

@ -99,7 +99,7 @@ class CoursesController < ApplicationController
limit = params[:limit] || 16
@courses = @courses.page(page).per(limit)
@courses = @courses.preload(:school, :none_hidden_course_modules, teacher: :user_extension)
@courses = @courses.preload(:school, :teacher_users, :none_hidden_course_modules, teacher: :user_extension)
end
def course_videos
@ -1306,6 +1306,7 @@ class CoursesController < ApplicationController
@user = current_user
@switch_student = Course::BUSINESS < @user_course_identity && @user_course_identity < Course::STUDENT
@is_student = @user_course_identity == Course::STUDENT
@teacher_users = @course.teacher_users.where.not(id: @course.tea_id).map(&:real_name)[0..2]
@course.increment!(:visits)
end

@ -3,7 +3,7 @@ class ExaminationBanksController < ApplicationController
before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item, :cancel_items]
before_action :find_exam, except: [:index, :create, :cancel_items]
before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item, :cancel_items]
before_action :edit_auth, only: [:update, :set_public, :revoke_item, :cancel_items]
before_action :identity_auth, only: [:index]
def index
@ -52,6 +52,7 @@ class ExaminationBanksController < ApplicationController
end
def destroy
tip_exception(403, "无权限") unless current_user.admin? || @item.user == current_user
ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ExaminationBank", container_id: @exam.id).destroy_all
@exam.destroy!
@ -92,6 +93,6 @@ class ExaminationBanksController < ApplicationController
end
def edit_auth
current_user.admin_or_business? || @exam.user == current_user
tip_exception(403, "无权限") unless current_user.admin_or_business? || @exam.user == current_user
end
end

@ -11,7 +11,7 @@ class HomeworkCommonsController < ApplicationController
before_action :find_homework, only: [:edit, :show, :update, :group_list, :homework_code_repeat, :code_review_results,
:code_review_detail, :show_comment, :settings, :works_list, :update_settings,
:reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation,
:update_score, :update_student_score, :batch_comment]
:update_score, :update_student_score, :batch_comment, :get_next_work]
before_action :user_course_identity
before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer,
:update_student_score]
@ -230,7 +230,7 @@ class HomeworkCommonsController < ApplicationController
limit = params[:limit] || 20
@student_works = @student_works.page(page).per(limit)
if @homework.homework_type == "practice"
@student_works = @student_works.includes(:student_works_scores, :shixun_work_comments, user: :user_extension, myshixun: :games)
@student_works = @student_works.includes(:student_works_scores, :shixun_work_comments, :challenge_work_scores, user: :user_extension, myshixun: :games)
else
@student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension)
end
@ -287,6 +287,15 @@ class HomeworkCommonsController < ApplicationController
end
end
def get_next_work
member = @course.course_member(current_user.id)
student_works = @homework.teacher_works(member).where.not(id: @homework.student_works_scores.where(reviewer_role: [1, 2]).pluck(:student_work_id))
if params[:work_id]
student_works = student_works.where.not(id: params[:work_id])
end
@work = student_works.where("work_status > 0").sample(1).first
end
def update_score
tip_exception("作业还未发布,暂不能计算成绩") if @homework.publish_time.nil? || @homework.publish_time > Time.now
@homework.update_homework_work_score

@ -3,7 +3,7 @@ class ItemBanksController < ApplicationController
before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public]
before_action :find_item, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public]
before_action :edit_auth, only: [:update, :set_public]
before_action :identity_auth, only: [:index]
def index
@ -41,6 +41,7 @@ class ItemBanksController < ApplicationController
end
def destroy
tip_exception(403, "无权限") unless current_user.admin? || @item.user == current_user
ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ItemBank", container_id: @item.id).destroy_all
if @item.item_type == "PROGRAM"
@ -67,7 +68,7 @@ class ItemBanksController < ApplicationController
end
def edit_auth
current_user.admin_or_business? || @item.user == current_user
tip_exception(403, "无权限") unless current_user.admin_or_business? || @item.user == current_user
end
def form_params

@ -18,7 +18,8 @@ class MyshixunsController < ApplicationController
# 强制重置实训
# 前段需要按照操作过程提示
def reset_my_game
unless (current_user.admin? || current_user.id == @myshixun.user_id)
course = Course.find_by(id: params[:course_id])
unless (current_user.admin_or_business? || current_user.id == @myshixun.user_id) || (course.present? && current_user.course_identity(course) < Course::STUDENT)
tip_exception("403", "")
end
begin
@ -26,9 +27,15 @@ class MyshixunsController < ApplicationController
ActiveRecord::Base.transaction do
@myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).includes(:shixun_work_comments, :student_works_scores, :challenge_work_scores).each do |work|
work.shixun_work_comments.destroy_all
work.student_works_scores.destroy_all
work.challenge_work_scores.destroy_all
end
StudentWork.where(:myshixun_id => @myshixun.id)
.update_all(myshixun_id: 0, work_status: 0, work_score: nil,
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, ultimate_score: 0, cost_time: 0, compelete_status: -1)
end
# 删除版本库
GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?

@ -557,7 +557,7 @@ class StudentWorksController < ApplicationController
@work.student_works_scores.where.not(score: nil).update_all(is_invalid: 1)
reviewer_role = @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score = StudentWorksScore.new(student_work_id: @work.id, score: params[:score].to_f,
comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}",
comment: params[:comment],
homework_common_id: @work.homework_common_id, user_id: current_user.id,
reviewer_role: reviewer_role, is_ultimate: 1)
new_score.save!

@ -5,7 +5,7 @@ class Users::CoursesController < Users::BaseController
courses = courses.where(id: current_laboratory.all_courses)
@count = courses.count
@courses = paginate(courses.includes(teacher: { user_extension: :school }), special: observed_user.is_teacher?)
@courses = paginate(courses.includes(:teacher_users, teacher: { user_extension: :school }), special: observed_user.is_teacher?)
end
private

@ -4,30 +4,36 @@ class Weapps::CourseMemberAttendancesController < ApplicationController
def index
attendance = CourseAttendance.find params[:attendance_id]
if attendance.course_attendance_groups.first&.course_group_id.to_i == 0
@members = attendance.course.students
else
@members = attendance.course.students.where(course_group_id: attendance.course_attendance_groups.pluck(:course_group_id))
end
@member_attendances = attendance.course_member_attendances
if params[:group_ids].present?
@members = @members.where(course_group_id: params[:group_ids])
end
@page = params[:page] || 1
@limit = params[:limit] || 5
if params[:attendance_status].present?
@members = @members.joins(:course_member_attendances).where(course_member_attendances: {course_attendance_id: attendance.id, attendance_status: params[:attendance_status]})
@member_attendances = attendance.course_member_attendances
if params[:group_ids].present?
@member_attendances = @member_attendances.joins(:course_member).where(course_members: {course_group_id: params[:group_ids]})
end
@member_attendances = @member_attendances.where(attendance_status: params[:attendance_status]) if params[:attendance_status].present?
@member_attendances = @member_attendances.order("attendance_status=1 desc, course_member_attendances.updated_at desc")
@members_count = @member_attendances.uniq.count
@member_attendances = paginate @member_attendances.preload(user: :user_extension)
@members = @members.joins(:course_member_attendances).order("attendance_status=1 desc, course_member_attendances.updated_at desc")
@members_count = @members.uniq.count
@members = paginate @members.preload(user: :user_extension).uniq
# @member_attendances = @member_attendances.where(attendance_status: params[:attendance_status]) if params[:attendance_status].present?
# @member_attendances = @member_attendances.joins(user: :user_extension).order("attendance_status=1 desc, course_member_attendances.updated_at desc, user_extensions.student_id asc")
# @member_attendances = paginate @member_attendances.preload(user: :user_extension)
# if attendance.course_attendance_groups.first&.course_group_id.to_i == 0
# @members = attendance.course.students
# else
# @members = attendance.course.students.where(course_group_id: attendance.course_attendance_groups.pluck(:course_group_id))
# end
# @member_attendances = attendance.course_member_attendances
# if params[:group_ids].present?
# @members = @members.where(course_group_id: params[:group_ids])
# end
#
# if params[:attendance_status].present?
# @members = @members.joins(:course_member_attendances).where(course_member_attendances: {course_attendance_id: attendance.id, attendance_status: params[:attendance_status]})
# end
#
# @members = @members.joins(:course_member_attendances).order("attendance_status=1 desc, course_member_attendances.updated_at desc")
# @members_count = @members.uniq.count
# @members = paginate @members.preload(user: :user_extension).uniq
end
def create

@ -76,6 +76,7 @@ class Weapps::CoursesController < Weapps::BaseController
def show
@course = current_course
@current_user = current_user
@teacher_users = @course.teacher_users.where.not(id: @course.tea_id).map(&:real_name)[0..2]
end
def shixun_homework_category

@ -19,7 +19,7 @@ class Weapps::HomesController < Weapps::BaseController
@courses = @courses.where(id: current_laboratory.all_courses)
@course_count = @courses.count
order_str = "course_members.sticky=1 desc, course_members.sticky_time desc, courses.created_at desc"
@courses = paginate(@courses.order(order_str).includes(:teacher, :school))
@courses = paginate(@courses.order(order_str).includes(:teacher_users, :teacher, :school))
@user = current_user
end
end

@ -251,7 +251,13 @@ module CoursesHelper
# 获取课堂的资源数
def get_attachment_count(course, category_id)
identity = current_user.course_identity(course)
attachments = category_id.to_i == 0 ? course.attachments : course.attachments.where(course_second_category_id: category_id)
if category_id.to_i == 0
attachments = course.attachments
else
# children_ids = CourseSecondCategory.where(parent_id: category_id).pluck(:id)
# category_ids = [category_id] + children_ids
attachments = course.attachments.joins(:course_second_category).where(course_second_categories: {id: category_id}).or(course.attachments.joins(:course_second_category).where(course_second_categories: {parent_id: category_id}))
end
identity > Course::ASSISTANT_PROFESSOR ? attachments.published.size : attachments.size
end

@ -457,7 +457,9 @@ module ExportHelper
course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name)
w_5 = course_name.present? ? course_name : "--"
#0 未提交, 1 按时提交, 2 延迟提交
if w.compelete_status == 0
if w.compelete_status == -1
w_6 = "重做中"
elsif w.compelete_status == 0
w_6 = "未开启"
elsif w.compelete_status == 1
w_6 = "未通关"

@ -240,10 +240,16 @@ module HomeworkCommonsHelper
# 作品状态
def practice_homework_status homework, member
[{id: 0, name: "未开启", count: homework.compelete_status_count(member, 0)},
status_arr = [{id: 0, name: "未开启", count: homework.compelete_status_count(member, 0)},
{id: 1, name: "未通关", count: homework.compelete_status_count(member, 1)},
{id: 2, name: "按时通关", count: homework.compelete_status_count(member, 2)},
{id: 3, name: "迟交通关", count: homework.compelete_status_count(member, 3)}]
redo_count = homework.compelete_status_count(member, -1)
if redo_count > 0
status_arr.insert(1, {id: -1, name: "重做中", count: homework.compelete_status_count(member, -1)})
end
status_arr
end
# 作品状态

@ -0,0 +1,11 @@
class DeleteUnpublishVideoJob < ApplicationJob
queue_as :default
def perform(*args)
# "清理过时视频,一周之前用户还未确定上传的视频"
videos = Video.where(transcoded: false, delete_state: nil, status: 'pending').where("updated_at < '#{Time.now.days_ago(7)}'")
videos.find_each do |d|
d.destroy
end
end
end

@ -69,13 +69,17 @@ class Challenge < ApplicationRecord
end
# 开启挑战
def open_game shixun
def open_game shixun, shixun_modify
# 这里的identifier,status是关联了games取了games的identifier,status
identifier = self.identifier
if identifier.present?
shixun.task_pass || self.status != 3 ? "/tasks/#{identifier}" : ""
if shixun_modify
"/shixuns/#{shixun.identifier}/shixun_exec.json"
else
(shixun.task_pass || self.status != 3) ? "/tasks/#{identifier}" : ""
end
else
self.position == 1 ? "/shixuns/#{shixun.identifier}/shixun_exec.json" : ""
(shixun.task_pass || position == 1) ? "/shixuns/#{shixun.identifier}/shixun_exec.json" : ""
end
end

@ -23,7 +23,7 @@ class CourseMember < ApplicationRecord
# after_destroy :delete_works
# after_create :work_operation
after_create :create_attendance_record
# after_create :create_attendance_record
after_commit :create_attendance_record

@ -223,6 +223,16 @@ class StudentWork < ApplicationRecord
end
end
# 实训作品是否已被评阅过
def shixun_has_comment?
shixun_work_comments.size > 0 || student_works_scores.size > 0 || challenge_work_scores.size > 0
end
# 普通/分组作品是否已被评阅过
def work_has_comment?
student_works_scores.select{|score| score.reviewer_role < 3}.size > 0
end
def scored?
student_works_scores.where.not(reviewer_role: 3, score: nil).exists?
end

@ -3,7 +3,7 @@ class WatchCourseVideo < ApplicationRecord
belongs_to :user
has_many :watch_video_histories
has_one :watch_course_video_detail
validates :course_video_id, uniqueness: {scope: :user_id}
end

@ -0,0 +1,6 @@
class WatchCourseVideoDetail < ApplicationRecord
belongs_to :user
belongs_to :watch_course_video
serialize :times, Array
end

@ -9,6 +9,7 @@ class Admins::UpdateUserService < ApplicationService
end
def call
user.assign_attributes(user_attributes)
user.mail = params[:mail].to_s.presence
user.phone = params[:phone].to_s.presence
@ -36,8 +37,11 @@ class Admins::UpdateUserService < ApplicationService
private
def user_attributes
params.slice(*%i[lastname nickname mail phone admin business is_test
professional_certification authentication is_shixun_marker])
allow_attributes = %i[lastname nickname mail phone business is_test
professional_certification authentication is_shixun_marker admin_visitable]
allow_attributes.push(:admin) if user.admin?
params.slice(*allow_attributes)
end
def user_extension_attributes

@ -20,7 +20,7 @@ class AttendanceStatisticsService < ApplicationService
leave_count = history_member_count(member_attendances, "LEAVE", attendance.id)
all_count = member_attendances.select{|member_attendance| member_attendance.course_attendance_id == attendance.id}.size
normal_rate = cal_rate(normal_count, all_count)
normal_rate = all_count == 0 ? 1 : cal_rate(normal_count, all_count)
all_normal_rate << normal_rate
absence_rate = cal_rate(absence_count, all_count)
all_absence_rate << absence_rate
@ -34,7 +34,7 @@ class AttendanceStatisticsService < ApplicationService
all_history_count = history_attendances.size
history_attendances = history_attendances[0..9].reverse
avg_normal_rate = cal_rate(all_normal_rate.sum, all_history_count)
avg_normal_rate = all_history_count == 0 ? 1 : cal_rate(all_normal_rate.sum, all_history_count)
avg_absence_rate = cal_rate(all_absence_rate.sum, all_history_count)
avg_leave_rate = cal_rate(all_leave_rate.sum, all_history_count)

@ -16,16 +16,17 @@ class CreateWatchVideoService < ApplicationService
if params[:log_id].present?
watch_video_history = user.watch_video_histories.find(params[:log_id])
if params[:total_duration] < params[:watch_duration]
return watch_video_history
end
# if params[:total_duration] < params[:watch_duration]
# return watch_video_history
# end
# 更新观看时长
if watch_video_history.present? && !watch_video_history.is_finished && watch_video_history.watch_duration <= params[:watch_duration] && watch_video_history.total_duration <= params[:total_duration]
if watch_video_history.present? && !watch_video_history.is_finished && watch_video_history.total_duration <= params[:total_duration]
# 如果观看总时长没变,说明视频没有播放,无需再去记录
watch_video_history.end_at = current_time
watch_video_history.total_duration = params[:total_duration]
watch_video_history.watch_duration = params[:watch_duration] > watch_video_history.duration ? watch_video_history.duration : params[:watch_duration]
watch_video_history.is_finished = params[:ed].present?
watch_video_history.last_point = params[:point].to_i
watch_video_history.save!
watch_course_video = watch_video_history.watch_course_video
@ -33,10 +34,29 @@ class CreateWatchVideoService < ApplicationService
if watch_course_video.present?
watch_course_video.total_duration = watch_course_video.watch_video_histories.sum(:total_duration)
watch_course_video.end_at = current_time
if params[:point].to_i > watch_course_video.last_point
detail = WatchCourseVideoDetail.find_or_initialize_by(watch_course_video_id: watch_course_video.id, user_id: user.id) do |d|
d.times = [[ watch_course_video.last_point, params[:point].to_i]]
end
if detail.persisted?
detail.times << [watch_course_video.last_point, params[:point].to_i]
end
detail.save
end
watch_course_video.last_point = params[:point].to_i
if !watch_course_video.is_finished
# 更新课程视频的时长及是否看完状态
watch_course_video.watch_duration = params[:watch_duration] if watch_course_video.watch_duration < params[:watch_duration]
watch_course_video.is_finished = watch_course_video.total_duration >= watch_course_video.duration if params[:ed].present?
if params[:ed].present? || (watch_course_video.duration >= 300 && (watch_course_video.duration - params[:point].to_i) <= 20)
video_duration = watch_video_history.video.duration.to_i
if video_duration > 0
watch_course_video.is_finished = watch_course_video.total_duration.to_i >= video_duration
else
watch_course_video.is_finished = watch_course_video.total_duration.to_i >= watch_course_video.duration.to_i
end
end
end
watch_course_video.save!
end
@ -50,8 +70,8 @@ class CreateWatchVideoService < ApplicationService
d.start_at = current_time
d.duration = params[:duration]
end
watch_course_video.save! unless watch_course_video.persisted?
watch_course_video.last_point = params[:point].to_i
watch_course_video.save!
watch_video_history = build_video_log(current_time, course_video.video_id, watch_course_video.id)
watch_video_history.save!
else

@ -133,9 +133,9 @@ class HomeworksService
# 计算实训作品学生的效率分
def update_student_eff_score homework
if homework.work_efficiency && homework.max_efficiency != 0
max_efficiency = homework.student_works.where("compelete_status != 0").pluck(:efficiency).max
max_efficiency = homework.student_works.where("compelete_status > 0").pluck(:efficiency).max
homework.update_column("max_efficiency", max_efficiency)
homework.student_works.where("compelete_status != 0").each do |student_work|
homework.student_works.where("compelete_status > 0").each do |student_work|
eff_score = student_work.efficiency / max_efficiency * homework.eff_score
student_work.eff_score = format("%.2f", eff_score)
student_work.late_penalty = student_work.work_status == 1 ? 0 : homework.late_penalty
@ -146,7 +146,7 @@ class HomeworksService
student_work.save!
end
else
homework.student_works.where("compelete_status != 0").each do |student_work|
homework.student_works.where("compelete_status > 0").each do |student_work|
student_work.eff_score = 0
student_work.late_penalty = student_work.work_status == 1 ? 0 : homework.late_penalty
unless student_work.ultimate_score

@ -31,16 +31,23 @@ class Videos::BatchPublishService < ApplicationService
# 非MP4 H264编码的都转码
code_info = AliyunVod::Service.get_meta_code_info(video.uuid)
result = AliyunVod::Service.get_play_info(video.uuid) rescue nil
Rails.logger.info("code_info: #{code_info[:format]}, #{code_info[:codecnamne]}")
if code_info[:format] == "mp4" && code_info[:codecnamne].present? && code_info[:codecnamne].start_with?('h264')
video.transcoded = true
result = AliyunVod::Service.get_play_info(video.uuid) rescue nil
play_url = result['PlayInfoList']['PlayInfo'].first['PlayURL'] if result.present?
video.play_url = play_url
if result.present? && result['PlayInfoList']['PlayInfo'].first['PlayURL']
play_url = result['PlayInfoList']['PlayInfo'].first['PlayURL']
video.play_url = play_url
end
else
AliyunVod::Service.submit_transcode_job(video.uuid, Video::NORMAL_TRANSCODE_GROUP_ID)
end
if result.present?
video.duration = result['PlayInfoList']['PlayInfo'][0]['Duration'] if result['PlayInfoList']['PlayInfo'][0]['Duration'].present?
end
video.save!
if param[:course_id].present?

@ -3,17 +3,22 @@ wb = xlsx_package.workbook
wb.styles do |s|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(name: "课堂列表") do |sheet|
sheet.add_row %w(ID 课堂名称 老师 学生 资源 公告 视频 普通作业 分组作业 实训作业 实训作业已发布数 作品数 试卷 评测次数 私有 状态 单位 部门 创建者 创建时间 动态时间), :height => 25,:style => blue_cell
sheet.add_row %w(ID 课堂名称 老师 学生 分班数 资源 公告 视频 视频学习时长 直播 普通作业 分组作业 实训作业 实训作业已发布数 作品数 试卷 评测次数 讨论数 私有 状态 单位 部门 创建者 创建时间), :height => 25,:style => blue_cell
@courses.each do |course|
course_board = course.course_board
topic_count = course_board.present? ? course_board.messages.size : 0
data = [
course.id,
course.name,
course.teacher_course_members.size,
course.students.size,
course.course_groups_count,
get_attachment_count(course, 0),
course.informs.size,
course.course_videos.size,
course.course_videos.map{|cv| cv.watch_course_videos.map(&:total_duration).sum }.sum.round,
course.live_links.size,
course.course_homework_count("normal"),
course.course_homework_count("group"),
course.course_homework_count("practice"),
@ -21,13 +26,13 @@ wb.styles do |s|
course.student_works_count,
course.exercises_count,
course.evaluate_count,
topic_count,
course.is_public == 1 ? "--" : "√",
course.is_end ? "已结束" : "正在进行",
course.school&.name,
course.teacher&.department_name,
course.teacher&.real_name,
course.created_at&.strftime('%Y-%m-%d %H:%M'),
course.max_activity_time ? course.max_activity_time&.strftime('%Y-%m-%d %H:%M') : "--"
]
sheet.add_row(data)
end

@ -111,6 +111,7 @@
<%= f.input :admin, as: :boolean, label: '管理员', checked_value: 1, unchecked_value: 0 %>
<%= f.input :business, as: :boolean, label: '运营人员', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
<%= f.input :is_test, as: :boolean, label: '测试账号', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
<%= f.input :admin_visitable, as: :boolean, label: '允许查看后台', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
</div>
</div>
<% end %>

@ -22,7 +22,7 @@ if @challenges.present?
#json.playing_count @play_games_map.fetch(challenge.id, 0)
json.playing_count (challenge.games.count - user_passed_count)
json.name_url shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)
json.open_game challenge.open_game(@shixun)
json.open_game challenge.open_game(@shixun, @shixun_modify)
#json.open_game challenge.open_game(@shixun, @user.id)
if @editable
json.edit_url edit_shixun_challenge_path(challenge, shixun_identifier: @shixun.identifier)

@ -13,5 +13,7 @@ json.courses @courses do |course|
json.is_end course.is_end
json.first_category_url module_url(course.none_hidden_course_modules.first, course)
json.excellent course.excellent
json.teacher_users course.teacher_users.select{|u| u.id != course.tea_id }.map(&:real_name)[0..2] # 取前3名老师
end
json.courses_count @courses_count

@ -22,6 +22,8 @@ json.switch_to_assistant switch_assistant_role(@is_student, @course, @user)
#json.copy_course !@user.member_of_course?(@course) && @user.is_teacher?
json.course_identity @user_course_identity
json.excellent @course.excellent
# 协作老师
json.teacher_users @teacher_users
if @course.is_end == 0
json.days_remaining (@course.end_date.to_date - Time.now.to_date).to_i
end

@ -17,10 +17,15 @@ json.data do
end
# json.partial! "files/course_groups", attachment_group_settings: attachment.attachment_group_settings
json.category_id attachment.course_second_category_id
if (@course_second_category_id.to_i == 0 && attachment.course_second_category.present?) || (@parent_category_id == 0 && attachment.course_second_category&.parent_id.to_i != 0)
if @course_second_category_id.to_i == 0 && attachment.course_second_category.present?
json.category_name attachment.course_second_category&.name
json.parent_category_name attachment.course_second_category&.parent&.name
end
if @parent_category_id == 0 && attachment.course_second_category&.parent_id.to_i != 0
json.category_name attachment.course_second_category&.name
json.parent_category_name nil
end
end
end
end

@ -0,0 +1,2 @@
json.work_id @work&.id
json.user_name @work&.user&.real_name

@ -103,6 +103,7 @@ if @homework.homework_type == "practice"
json.efficiency work_score_format(work.efficiency, @current_user == work.user, @score_open)
json.eff_score work_score_format(work.eff_score, @current_user == work.user, @score_open)
json.myshixun_identifier work.myshixun&.identifier
json.cost_time work.myshixun.try(:total_spend_time)
json.current_complete_count myshixun.try(:passed_count) if @homework.end_or_late
end_time = @homework.allow_late ? @homework.late_time : @homework.homework_group_setting(work.user_id)&.end_time
@ -114,7 +115,7 @@ if @homework.homework_type == "practice"
json.student_id work.user.try(:student_id)
json.group_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name)
json.work_status work.compelete_status
json.has_comment work.shixun_work_comments.size > 0
json.has_comment work.shixun_has_comment?
end
elsif @homework.homework_type == "group" || @homework.homework_type == "normal"
json.anonymous_comment @homework.anonymous_comment
@ -175,7 +176,7 @@ elsif @homework.homework_type == "group" || @homework.homework_type == "normal"
json.user_login @is_evaluation ? "--" : work.user.try(:login)
json.user_name @is_evaluation ? "匿名" : work.user.try(:real_name)
json.user_img @is_evaluation ? "--" : url_to_avatar(work.user)
json.has_comment work.work_has_comment?
end
end

@ -1,4 +1,5 @@
json.homework_common_id @homework.id
json.course_id @homework.course_id
json.category @homework.category_info
json.course_name @course.name
json.work_id @work.id
@ -88,5 +89,8 @@ if @shixun
end
json.view_tpi @view_tpi
json.myshixun_id @work.myshixun_id
json.myshixun_identifier @work.myshixun&.identifier
json.homework_end @homework.end_or_late

@ -7,6 +7,8 @@ json.homework_commons_count get_tasks_count course
json.attachments_count course.attachments.count
json.visits course.visits
json.school course.school&.name
json.teacher_users course.teacher_users.select{|u| u.id != course.tea_id }.map(&:real_name)[0..2] # 取前3名老师
json.first_category_url module_url(course.course_modules.where(hidden: 0).order(position: :desc).first, course)

@ -1,15 +1,16 @@
# json.member_attendances @member_attendances.each do |member|
# json.(member, :user_id, :attendance_status)
# json.user_name member.user&.real_name
# json.student_id member.user&.student_id
# end
json.member_attendances @members.each_with_index.to_a do |member, index|
json.(member, :user_id)
json.member_attendances @member_attendances.each_with_index.to_a do |member, index|
json.(member, :user_id, :attendance_status)
json.index (@page.to_i - 1) * @limit.to_i + index + 1
json.user_name member.user&.real_name
json.student_id member.user&.student_id
json.attendance_status @member_attendances.select{|attendance| attendance.course_member_id == member.id}.first&.attendance_status || "ABSENCE"
end
# json.member_attendances @members.each_with_index.to_a do |member, index|
# json.(member, :user_id)
# json.index (@page.to_i - 1) * @limit.to_i + index + 1
# json.user_name member.user&.real_name
# json.student_id member.user&.student_id
# json.attendance_status @member_attendances.select{|attendance| attendance.course_member_id == member.id}.first&.attendance_status || "ABSENCE"
# end
json.members_count @members_count

@ -1,4 +1,5 @@
json.(@course, :id, :name, :course_members_count, :credit, :invite_code_halt)
json.teachers_count @course.teachers.count
json.students_count @course.students.count
json.course_identity @current_user.course_identity(@course)
json.course_identity @current_user.course_identity(@course)
json.teacher_users @teacher_users

@ -26,5 +26,6 @@ json.courses @courses.each do |course|
course_member = @category == "study" ? course.students.where(user_id: @user.id).first : course.teachers.where(user_id: @user.id).first
json.sticky course_member.sticky
json.course_identity current_user.course_identity(course)
json.teacher_users course.teacher_users.select{|u| u.id != course.tea_id }.map(&:real_name)[0..2] # 取前3名老师
end

@ -518,7 +518,6 @@ H漫画
胡启立
芮杏文
杨白冰
邹家华
谭绍文
王汉斌
任建新
@ -1377,6 +1376,4 @@ B样
垃 圾
傻 逼
真蠢
蠢猪
蠢猪

@ -597,6 +597,7 @@ Rails.application.routes.draw do
get :update_score
get :update_student_score
post :batch_comment
get :get_next_work
end
collection do

@ -0,0 +1,3 @@
delete_unpublish_video_job:
cron: "0 24 * * *"
class: "DeleteUnpublishVideoJob"

@ -0,0 +1,14 @@
class CreateWatchCourseVideoDetails < ActiveRecord::Migration[5.2]
def change
create_table :watch_course_video_details do |t|
t.references :user, index: true
t.text :times
t.references :watch_course_video, index: true
t.timestamps
end
add_column :watch_course_videos, :last_point, :integer, default: 0
add_column :watch_video_histories, :last_point, :integer, default: 0
end
end

@ -0,0 +1,5 @@
class AddDurationToVideo < ActiveRecord::Migration[5.2]
def change
add_column :videos, :duration, :float, default: 0
end
end

@ -0,0 +1,5 @@
class AddAdminVisitableToUser < ActiveRecord::Migration[5.2]
def change
add_column :users, :admin_visitable, :boolean, default: false
end
end

@ -12,7 +12,7 @@ namespace :competition do
student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql
subquery = StudentWork.where('homework_common_id = hcs.id')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
shixun_user_ids = Shixun.where.not(user_id: old_competition_user_ids).where(status: 2).where('shixuns.created_at > ? && shixuns.created_at <= ?', start_time, end_time).pluck(:user_id).uniq
course_user_ids = Course.where.not(tea_id: old_competition_user_ids).where('courses.created_at > ?', start_time)
@ -109,7 +109,7 @@ namespace :competition do
# =========== Course ===========
student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql
subquery = StudentWork.where('homework_common_id = hcs.id')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
course_ids = Course.where('courses.created_at > ?', start_time)
.where('courses.created_at <= ?', end_time)
@ -173,7 +173,7 @@ namespace :competition do
def get_valid_course_count(ids, end_time)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < ?', end_time)
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Course.joins(practice_homeworks: :homework_commons_shixun)
@ -184,7 +184,7 @@ namespace :competition do
def get_valid_shixun_count(ids, end_time)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < ?', end_time)
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.select('sum(compelete_status >0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Shixun.joins(homework_commons_shixuns: :homework_common)
.where(homework_commons: { homework_type: 4 })

@ -74,4 +74,17 @@ namespace :video do
end
end
end
task :set_duration => :environment do
videos = Video.published.where("duration = 0")
videos.find_each do |v|
result = AliyunVod::Service.get_play_info(v.uuid)
if result.present? && result['PlayInfoList']['PlayInfo'][0]['Duration'].present?
p "-----#{v.id} , #{result['PlayInfoList']['PlayInfo'][0]['Duration']}"
v.update(duration: result['PlayInfoList']['PlayInfo'][0]['Duration'])
end
end
end
end

@ -0,0 +1,31 @@
# 执行示例 bundle exec rake migrate_course_student_work:homework args=2933
desc "创建课堂学生的作业数据"
namespace :migrate_course_student_work do
if ENV['args']
course_id = ENV['args'].split(",")[0] # 对应课堂的id
end
task homework: :environment do
course = Course.find_by(id: course_id)
if course.present?
student_ids = course.students.pluck(:user_id)
# 如果之前存在相关作品则更新is_delete字段
student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id})
student_works.update_all(is_delete: 0)
attrs = %i[homework_common_id user_id created_at updated_at]
StudentWork.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.homework_commons.where(homework_type: %i[normal group practice]).each do |homework|
next if StudentWork.where(user_id: user_id, homework_common_id: homework.id).any?
worker.add same_attrs.merge(homework_common_id: homework.id)
end
end
end
end
end
end

@ -3,18 +3,22 @@ namespace :video_transcode do
desc "视频转码成h264"
task :submit => :environment do
i = []
Video.where.not(uuid: nil, file_url: nil).where(transcoded: false).find_each do |v|
code_info = AliyunVod::Service.get_meta_code_info(v.uuid)
if v.file_url.include?('.mp4') && code_info[:codecnamne]&.include?("h264")
v.update(transcoded: true)
Video.where(transcoded: false).find_each do |v|
if v.uuid.present? && v.file_url.present?
code_info = AliyunVod::Service.get_meta_code_info(v.uuid)
if v.file_url.include?('.mp4') && code_info[:codecnamne]&.include?("h264")
v.update(transcoded: true)
else
puts("uuid: #{v.uuid}")
i << "#{v.id}, #{v.file_url}, #{code_info[:codecnamne]}"
AliyunVod::Service.submit_transcode_job(v.uuid, 'a0277c5c0c7458458e171b0cee6ebf5e') rescue nil
end
else
puts("uuid: #{v.uuid}")
i << "#{v.id}, #{v.file_url}, #{code_info[:codecnamne]}"
AliyunVod::Service.submit_transcode_job(v.uuid, 'a0277c5c0c7458458e171b0cee6ebf5e') rescue nil
v.update_column(:transcoded, true)
end
end
puts "###########转码个数:#{i.size}"
puts "###########id,file_url, codecnamne:#{i}"
Video.where(transcoded: false).update_all(transcoded: true)
#Video.where(transcoded: false).update_all(transcoded: true)
end
end

@ -96,4 +96,4 @@ export function formatDuring(mss){
}
return days + "天" + hours + "小时" + minutes + "分";
}
}

@ -110,7 +110,7 @@ export function configShareForCourses () {
var shareData = {
title: 'EduCoder - 教学课堂',
desc: '自动评测实训任务,支持技能统计,提供教学活动分析报告,减轻教师和助教的辅导压力,免去作业发布和批改的困扰,实时了解学生学习情况,全面提升教师施教效率和水平。',
link: `${host}/courses`,
link: `${host}/classrooms`,
imgUrl: window.__testImageUrl
|| host + '/react/build/images/share_logo_icon.jpg'
};

@ -51,6 +51,7 @@ class Fileslists extends Component{
istowshowid:'',
//新增参数判断几级目录
parent_category_id:'',
isToggleOn:false,
}
}
@ -566,7 +567,7 @@ class Fileslists extends Component{
let {search,order,selectpage,checkAllValue,checkBoxValues}=this.state;
let selectpagetype=selectpage===page&&checkBoxValues.length===15?true:false
console.log(selectpagetype)
this.setState({
page:page,
@ -673,8 +674,10 @@ class Fileslists extends Component{
//判断二级链接是否显示
istowshow(item){
let toggleon=this.state.isToggleOn;
this.setState({
istowshowid:item.value
istowshowid:item.value,
isToggleOn:!toggleon
})
}
@ -1032,9 +1035,9 @@ class Fileslists extends Component{
{course_modules&&course_modules.course_modules.map((item,key)=>{
return(
<li key={key} id={item.value} onClick={() => this.moveTos(0)} title={item.title}>{item.title}</li>
<div style={{display:'inline-block',marginTop:10,height:20}}>
<li key={key} style={{paddingTop:5}} id={item.value} onClick={() => this.moveTos(0)} title={item.title}>{item.title}</li>
</div>
)
})}
@ -1046,23 +1049,23 @@ class Fileslists extends Component{
return(
<div >
<div style={{display:'inline-block',marginTop:10,height:20}}>
<li style={{width:200}} key={key} id={itm.value} onClick={() => this.moveTos(0)} title={itm.title}>{itm.title}</li>
<li style={{width:200,paddingTop:5}} key={key} id={itm.value} onClick={() => this.moveTos(itm.value)} title={itm.title}>{itm.title}</li>
{/* <div onClick={() => this.moveTos(itm.value )} style={{marginLeft:15,width:itm.title.length>13?200:undefined,color:'#000000',overflow: 'hidden',textOverflow:'ellipsis',whiteSpace: 'nowrap'}}>{itm.title}</div> */}
{itm.children.length===0?'':<i style={{marginLeft:15,marginRight:15}} onClick={() => this.istowshow(itm,filesId)} className="iconfont icon-xiajiantou font-12 ml2"></i>}
</div>
{ this.state.istowshowid===itm.value?
itm.children.map((tt,ti) => {
return(
filesId&&filesId===itm.id?"":
<div style={{marginTop:10,height:20}}>
<div style={{display:itm.children.length===1?'none':ti===0?'block':'none',marginLeft:15,width:250,height:1,background:'#c4c4c4'}}></div>
<li style={{marginTop:5,marginBottom:5,paddingLeft:30,width:tt.title.length>13?200:undefined,overflow: 'hidden',textOverflow:'ellipsis',whiteSpace: 'nowrap'}} key={ti} id={tt.value} onClick={() => this.moveTos(tt.value )} title={tt.title}>{tt.title}</li>
<div style={{marginTop:10,height:20,display:this.state.isToggleOn?'block':'none'}}>
<div style={{display:ti===0?'block':'none',marginLeft:15,width:235,marginRight:15,height:1,background:'#EEEEEE'}}></div>
<li style={{marginTop:5,paddingTop:5,marginBottom:5,paddingLeft:30,width:tt.title.length>13?200:undefined,overflow: 'hidden',textOverflow:'ellipsis',whiteSpace: 'nowrap'}} key={ti} id={tt.value} onClick={() => this.moveTos(tt.value )} title={tt.title}>{tt.title}</li>
</div>
)
})
:''}

@ -361,10 +361,11 @@ class VideoIndex extends Component {
{
videoId ?
""
:
:videos&&videos.length>0?
<WordsBtn style="blue" className="ml30 font-16 tongjis"
onClick={() => this.statisticsy(true)}
><i className="iconfont icon-tongji1 mr5 font-14"></i></WordsBtn>
:""
}
</span>

@ -14,7 +14,7 @@ function getTotalEffectTime(pos) {
pos.sort(compareNumbers)
let sum = 0
for (let i = 0; i < pos.length - 1; i++) {
let v = pos[i + 1] - pos[i]
let v = Math.abs(pos[i + 1] - pos[i])
if (v < 21) {
sum += v
}
@ -44,7 +44,9 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
let pos = []//
const log = useCallback((callback, isEnd = false) => {
let params = {}
let params = {
point: el.current.currentTime
}
if (logId) {
params['log_id'] = logId
params['watch_duration'] = getTotalEffectTime(pos) //
@ -113,12 +115,16 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
}
//
async function onEnded() {
pos.push(el.current.currentTime)
log(() => {
logId = null
lastUpdatedTime = 0
initLog = false
isLoging = false
isSeeking = false
pos = [] //
sumTimePlayed = 0
logCount = 1
}, true)
}
@ -127,7 +133,7 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
let newTime = el.current.currentTime
let timeDiff = newTime - lastUpdatedTime
//currenttime update before Seeking & Seeked fired
if (Math.abs(timeDiff) < 0.5) {
if (Math.abs(timeDiff) < 10) {
sumTimePlayed += Math.abs(timeDiff)
lastUpdatedTime = newTime
if (!isLoging) {
@ -137,7 +143,7 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
log()
}
}
}else {
} else {
lastUpdatedTime = newTime
}
}
@ -177,7 +183,8 @@ export default ({ src, videoId, logWatchHistory, courseId = null }) => {
el.current.removeEventListener('seeking', onSeeking)
el.current.removeEventListener('seeked', onSeeked)
el.current.removeEventListener('timeupdate', onTimeupdate)
if(el.current.playing) {
if (el.current.playing) {
pos.push(lastUpdatedTime, el.current.currentTime)
log()
}
}

@ -42,11 +42,11 @@ class Boards extends Component{
})
const _serachText = searchText || this.state.searchValue
const _page = page || this.state.pagination.page
const cid = this.props.match.params.coursesId
const bid = this.props.match.params.boardId
//
//
// hot
const sort_type = this.state.sort_type
// page_size
@ -131,7 +131,7 @@ class Boards extends Component{
const checkBoxValues = this.state.checkBoxValues
const url = `/boards/${bid}/messages/bulk_move.json`
axios.put(url, {
axios.put(url, {
ids: checkBoxValues,
to_board_id: board.id
})
@ -147,7 +147,7 @@ class Boards extends Component{
})
.catch(function (error) {
console.log(error);
});
});
}
onDelete = () => {
const len = this.state.checkBoxValues.length
@ -179,16 +179,16 @@ class Boards extends Component{
})
.catch(function (error) {
console.log(error);
});
});
}
})
}
onSticky = (message) => {
const cid = this.props.match.params.coursesId
const cid = this.props.match.params.coursesId
const url = `/messages/${message.id}/sticky_top.json`
axios.put(url, {
axios.put(url, {
course_id: cid,
})
.then((response) => {
@ -203,7 +203,7 @@ class Boards extends Component{
})
.catch(function (error) {
console.log(error);
});
});
}
onItemClick = (item) => {
const checkBoxValues = this.state.checkBoxValues.slice(0);
@ -219,7 +219,7 @@ class Boards extends Component{
onPressEnter = (e) => {
clearTimeout(this.timeoutHandler)
this.timeoutHandler = null;
this.fetchAll(this.state.searchValue, 1)
}
onInputSearchChange = (e) => {
@ -240,12 +240,12 @@ class Boards extends Component{
trigger('boardAdd', parseInt(boardid))
}
renameDir = () => {
const boardId = this.props.match.params.boardId
const boardId = this.props.match.params.boardId
trigger('boardRename', { category_id: parseInt(boardId), category_name: this.state.boardName})
}
onToBoardsNew = () => {
const courseId = this.state.course_id
const boardId = this.props.match.params.boardId
const courseId = this.state.course_id
const boardId = this.props.match.params.boardId
this.props.toNewPage(courseId, boardId)
}
@ -282,9 +282,18 @@ class Boards extends Component{
console.log('checked = ', checkedValues);
}
onPageChange = (pageNumber) => {
this.setState({
checkBoxValues:[]
})
let {checkAllValue}=this.state;
if(checkAllValue===true){
this.setState({
checkBoxValues:[],
checkAllValue:false
})
}else{
this.setState({
checkBoxValues:[]
})
}
this.fetchAll(null, pageNumber)
}
@ -304,25 +313,25 @@ class Boards extends Component{
}
const boardId = this.props.match.params.boardId
const url = `/boards/${boardId}/messages/bulk_public.json`
axios.put(url, {
axios.put(url, {
ids: checkBoxValues
})
.then((response) => {
if (response.data.status == 0) {
this.props.showNotification('操作成功')
this.props.showNotification('操作成功')
this.fetchAll()
}
})
.catch(function (error) {
console.log(error);
});
}
onSortTypeChange = (sort_type) => {
this.setState({ sort_type }, () => {
this.fetchAll()
})
}
render(){
const isAdmin = this.props.isAdmin()
@ -362,7 +371,7 @@ class Boards extends Component{
onPressEnter={this.onPressEnter}
></Titlesearchsection>
{/* <BoardsListItem></BoardsListItem>
<FilesListItem></FilesListItem> */}
@ -371,7 +380,7 @@ class Boards extends Component{
<div className="clearfix">
{isAdmin&&<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} 不支持跨页勾选</Checkbox>}
<div className="studentList_operation_ul">
{ !!isAdmin &&
{ !!isAdmin &&
<React.Fragment>
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onDelete}>删除</a></li>
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onSendToOtherCourse}>发送</a></li>
@ -379,7 +388,7 @@ class Boards extends Component{
<li className="li_line drop_down">
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu"
<ul className="drop_down_menu"
style={{"right":"0px","left":"unset", maxHeight: '318px', overflowY: 'auto', minWidth: '200px'}}>
{ boards && boards.length > 10 && <p className="drop_down_search">
<Input placeholder="搜索" value={this.state.dirSearchValue} onChange={(e) => {this.setState({dirSearchValue: e.target.value})}}/>
@ -429,7 +438,7 @@ class Boards extends Component{
{ messages.map((item, index) => {
return (
<div className="mt20 edu-back-white padding02010" key={`d_${index}`}>
<BoardsListItem
<BoardsListItem
{...this.props}
discussMessage={item}
checkBox={ isAdmin ? <Checkbox value={item.id} key={item.id}></Checkbox> : ''}
@ -455,10 +464,10 @@ class Boards extends Component{
</Tooltip>
</a>
</p> } */}
{pagination.total_count > 15 && <Pagination className="coursePagination"
{pagination.total_count > 15 && <Pagination className="coursePagination"
current={pagination.page}
showQuickJumper pageSize={15} total={pagination.total_count} onChange={this.onPageChange} />}
</React.Fragment>
)
}

@ -2,6 +2,7 @@ import '../katex.css';
import '../css/Courses.css';
import React,{Component} from "react";
import {markdownToHTML, ImageLayer2 } from 'educoder';
import {Button, Row, Col} from "antd";
import axios from 'axios';
import Modals from '../../modals/Modals';
import moment from 'moment';
@ -19,10 +20,10 @@ class CommonWorkAppraise extends Component{
course_name:"",
homework_name:"",
search: '',
get_next_work:undefined,
attachments: [],
revise_attachments: [],
get_next_worktype:false
}
}
getWork = () => {
@ -87,6 +88,37 @@ class CommonWorkAppraise extends Component{
this.getReviseAttachments()
}
get_next_works=(id)=>{
let workId =this.props.match.params.workId;
let url
if(id){
url=`/homework_commons/${workId}/get_next_work.json?work_id=${id}`;
}else{
url=`/homework_commons/${workId}/get_next_work.json?work_id=${this.props.match.params.studentWorkId}`;
}
axios.get(url).then((result)=> {
this.setState({
get_next_work:result.data,
get_next_worktype:true
})
}).catch((error)=>{
console.log(error)
})
}
gotoget_next_work=(id)=>{
if(this.props.match.path===`/classrooms/:coursesId/common_homeworks/:workId/:studentWorkId/appraise`){
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/common_homeworks/${this.props.match.params.workId}/${id}/appraise`);
}
if(this.props.match.path===`/classrooms/:coursesId/group_homeworks/:workId/:studentWorkId/appraise`){
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/common_homeworks/${this.props.match.params.workId}/${id}/appraise`);
}
this.setState({
get_next_worktype:false
})
}
onAttachmentRemove = (id) => {
this.setState({
Modalstype:true,
@ -128,22 +160,21 @@ class CommonWorkAppraise extends Component{
}
render(){
const dateFormat = 'YYYY-MM-DD HH:mm';
let {course_name, homework_name, search, page, loadingstate, homework_status, reference_answer,
attachments, homework_id, project_info, work_members, is_evaluation,
let {course_name, get_next_work,get_next_worktype,
attachments, project_info, work_members, is_evaluation,
description, update_user_name, commit_user_name, update_time, commit_time, author_name,
revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login,
Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype, is_leader_work
} =this.state;
let courseId=this.props.match.params.coursesId;
let category_id=this.props.match.params.category_id;
// let courseId=this.props.match.params.coursesId;
// let category_id=this.props.match.params.category_id;
let studentWorkId=this.props.match.params.studentWorkId;
const isAdmin = this.props.isAdmin()
document.title=course_name&&course_name;
return(
<div>
<WorkDetailPageHeader
{...this.props} {...this.state}
noTab={true}
@ -271,12 +302,60 @@ class CommonWorkAppraise extends Component{
<CommonWorkAppraiseReply {...this.props} task_id={studentWorkId}
onReplySuccess={this.onReplySuccess} {...this.state}
wrappedComponentRef={(ref) => {this.commonWorkAppraiseReply = ref}}
get_next_works={()=>this.get_next_works()}
></CommonWorkAppraiseReply>
</div>
</WorkDetailPageHeader>
{isAdmin===true&&get_next_worktype===true?<style>
{
`
.newFooter{
display:none !important;
}
.-task-sidebar{
display:none !important;
}
.educontent{
margin-bottom: 0px !important;
}
`
}
</style>:""}
{isAdmin===true&&get_next_worktype===true?<div className="clearfix bor-bottom-greyE edu-back-white orderingbox newshixunbottombtn">
<div className={"educontent mt5"}>
<div>
<Row>
<Col span={12} className={"mt13"}>
{get_next_work&&get_next_work.work_id===null?
<Row type="flex" justify="start">
<Col span={8}><div style={{color:"#333333"}}>已全部评阅完</div></Col>
</Row>:<Row type="flex" justify="start">
<Col><div style={{color:"#333333"}}>{get_next_work&&get_next_work?`下一位待评阅人员:${get_next_work&&get_next_work.user_name}`:""}</div></Col>
<Col span={4}><a className={"ml10 color-blue font-15"} onClick={()=>this.get_next_works(get_next_work&&get_next_work.work_id)}>跳过</a></Col>
</Row>}
</Col>
{get_next_work&&get_next_work.work_id===null?"":<Col span={12} className={"mt8"}>
<Row type="flex" justify="end">
<Col span={4}>
<Button className={"newshixunmode "} type="primary"
onClick={()=>this.gotoget_next_work(get_next_work&&get_next_work.work_id)}
// loading={this.state.hometypepvisible}
>评阅</Button>
</Col>
</Row>
</Col>}
</Row>
</div>
</div>
</div>:""}
</div>
)
}
}

@ -1,6 +1,6 @@
import React,{Component} from "react";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip,Spin, Pagination} from "antd";
import {WordsBtn, ConditionToolTip, queryString, publicSearchs, on, off, NoneData, sortDirections} from 'educoder';
import { Form, Table,Tooltip,Spin, Pagination} from "antd";
import { queryString, publicSearchs, on, off, NoneData, sortDirections} from 'educoder';
import axios from 'axios';
import CheckAllGroup from '../common/button/CheckAllGroup'
import moment from 'moment';
@ -11,7 +11,6 @@ import ModulationModal from "../coursesPublic/ModulationModal";
import AccessoryModal from "../coursesPublic/AccessoryModal";
import LeaderIcon from './common/LeaderIcon'
const $ = window.$;
const Search = Input.Search;
function renderScore(score, content) {
let color = '#747A7F'
@ -369,18 +368,24 @@ function buildColumns(that, student_works, studentData) {
{/* 0 未提交 */}
{/*<React.Fragment>*/}
{/*</React.Fragment>*/}
<div>
<a style={{color: '#4CACFF'}} id={"asdasdasdasd"}
className="font-14"
onMouseDown={(e) => that.props.toWorkDetailPage2(e, courseId, workId, record.id)}
// onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)}
>{isAdmin ? record.has_comment===true?"已评阅":'评阅':"查看"}</a>
</div>
<div>
{ isAdmin && <Tooltip placement="bottom" title={<pre>调整学生当前成绩<br/>其它历史评分将全部失效</pre>}>
<a style={{color: "#4CACFF"}}
<a style={{color: "#32C090"}}
className="font-14"
onClick={() => that.showModulationModal(record)}
>调分</a>
</Tooltip> }
</div>
{/* toWorkDetailPage */}
{/* /classrooms/"+courseId+"/common_homeworks/"+workId+ '/' + record.id +"/appraise */}
<a style={{color: '#4CACFF', marginLeft: '4px'}} id={"asdasdasdasd"}
onMouseDown={(e) => that.props.toWorkDetailPage2(e, courseId, workId, record.id)}
// onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)}
>{isAdmin ? '评阅' : '查看'}</a>
</div>
),
@ -692,7 +697,7 @@ class CommonWorkList extends Component{
modulationModalVisible, work_statuses,
id, user_name, user_login, student_id, group_name, work_status, update_time, teacher_score, teaching_asistant_score, student_score,
ultimate_score, work_score, student_comment_count, appeal_all_count, appeal_deal_count,
ultimate_score, work_score, student_comment_count, appeal_all_count, appeal_deal_count,has_comment,
late_penalty, absence_penalty, appeal_penalty,user_comment_count
, end_immediately, publish_immediately

@ -73,6 +73,9 @@ class commonWork extends Component{
componentDidUpdate(prevProps, prevState) {
if (prevProps.coursesidtype != this.props.coursesidtype||prevProps.match.params.category_id!=this.props.match.params.category_id) {
this.setState({
page:1
})
if (this.props.match.path === "/classrooms/:coursesId/common_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/common_homework/:category_id"||
this.props.match.path === "/classrooms/:coursesId/group_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homework/:category_id"
) {
@ -220,11 +223,21 @@ class commonWork extends Component{
}
onPageChange=(pageNumber)=>{
this.setState({
page:pageNumber,
checkBoxValues:[]
})
let {search,order,category_id}=this.state;
let {search,order,category_id,checkAll}=this.state;
if(checkAll===true){
this.setState({
page:pageNumber,
checkBoxValues:[],
checkAll:false
})
}else{
this.setState({
page:pageNumber,
checkBoxValues:[]
})
}
this.getList(pageNumber,search,order,category_id);
}

@ -20,7 +20,7 @@ import Modals from '../../../modals/Modals';
const REPLY_PAGE_COUNT = 10
const $ = window.$;
/*
/*
*/
class CommonWorkAppraiseReply extends Component{
@ -79,7 +79,7 @@ class CommonWorkAppraiseReply extends Component{
reply.journals.push(reply.appeal_info)
reply.journals = _.orderBy(reply.journals, 'time', 'asc')
}
return {
isSuperAdmin: isSuperAdmin,
admin: isAdmin, //
@ -93,7 +93,7 @@ class CommonWorkAppraiseReply extends Component{
// time: moment(reply.comment_time).fromNow(),
time: moment(reply.comment_time).format('YYYY-MM-DD HH:mm'),
image_url: reply.user_image_url,
image_url: reply.user_image_url,
user_id: reply.user_id,
user_login: reply.user_login,
username: reply.user_name,
@ -131,7 +131,7 @@ class CommonWorkAppraiseReply extends Component{
console.log('Cancel');
},
});
}
showModulationtype=(id)=>{
@ -221,6 +221,7 @@ class CommonWorkAppraiseReply extends Component{
if (!needNiPingEditor && comment_scores.length == 0) {
return ''
}
return(
<React.Fragment>
<div className="edu-back-white padding10-10" style={{marginTop: '16px'}}>
@ -257,13 +258,13 @@ class CommonWorkAppraiseReply extends Component{
{/*{this.props.isStudent()?<a className={"fr color-blue font-16 mt10 mr20"} onClick={this.addAccessory}>补交附件</a>:""}*/}
{/*</div>*/}
{/* {
(!!comment_scores.length &&
(!!comment_scores.length &&
<div className={"color-grey-6 mb10"}>
<span className="labal">全部评阅</span>
<span className="count">{comment_scores.length}</span>
<span className="count">{comment_scores.length}</span>
</div>)} */}
<div className={`padding20-30 ${comment_scores.length ? 'bor-bottom-greyE' : ''}`}>
{!!comment_scores.length && <div className={"color-grey-6 font-16"}>
@ -283,13 +284,14 @@ class CommonWorkAppraiseReply extends Component{
addSuccess={this.addSuccess} ref={this.editorRef} totalCount={comment_scores.length}
onReply={this.onReply} placeholder={"请在此输入对本作品的评语最大限制2000个字符"}
showSameScore={isGroup && isAdmin}
get_next_works={()=>this.props.get_next_works()}
></GraduationTasksappraiseMainEditor> }
</div>
{/* ${!!comment_scores.length ? 'bor-bottom-greyE' : ''} */}
<div className={`padding20 memoReplies commentsDelegateParent course-message`}
style={{ paddingTop: '0px', paddingBottom: '0px' }}
>
{/*
{/*
.course-message .panel-comment_item {
margin-top: ${needNiPingEditor ? 56 : 28}px;
}

@ -1200,14 +1200,13 @@ class Coursesleftnav extends Component{
>
<div>
{this.state.Navmodalziyname==="资源"?<div className="df" style={{marginBottom:50}}>
<div className={"fl mt5"} >上级目录</div>
<div className={"fl mt5"} id="ddd">上级目录</div>
<TreeSelect
className={"input-flex-35 greyInput fl"}
style={{width:300,color:'#000000'}}
style={{width:300,color:'#000000'}}
getPopupContainer={() => document.getElementById('ddd')}
dropdownClassName={{display:this.state.dropdownStyleshow}}
// dropdownMenuStyle={{display:this.state.dropdownStyleshow}}
treeData={this.state.treeData}
placeholder={this.state.treeDataname}
disabled={this.state.showPreson}

@ -36,11 +36,8 @@
display:inline-block;
max-width:200px;
}
.ant-select-tree-title{
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
max-width:200px;
.ant-select-tree{
max-height:300px;
}
/*鼠标悬浮在滚动条上的主干部分*/

@ -121,7 +121,7 @@ class CoursesHome extends Component {
const { order, page, coursesHomelist } = this.state;
const { user, tojoinclass } = this.props
console.log(tojoinclass, '--------------s')
return (
<div>
{this.state.updata === undefined ? "" : <UpgradeModals

@ -67,6 +67,9 @@ class GraduationTasksappraiseMainEditor extends Component{
same_score
}
if (this.props.onReply) {
if(this.props.get_next_works){
this.props.get_next_works()
}
this.props.onReply(params)
} else {
axios.post(url, params).then((response)=>{

@ -170,7 +170,7 @@ class Boards extends Component{
})
let {status,searchValue}=this.state;
this.fetchAll(searchValue,pageNum,status);
console.log(this.state.checkBoxValues);
}
// 筛选

@ -150,12 +150,21 @@ class Poll extends Component{
}
//切换分页
changePage=(pageNumber)=>{
let{type,StudentList_value,checkAllValue}=this.state;
if(checkAllValue===true){
this.setState({
page:pageNumber,
checkBoxValues:[],
checkAllValue:false
})
}else{
this.setState({
page:pageNumber,
checkBoxValues:[]
})
}
this.setState({
page:pageNumber,
checkBoxValues:[]
})
let{type,StudentList_value}=this.state
this.InitList(type,StudentList_value,pageNumber);
}
// 搜索

@ -19,11 +19,13 @@ import '../css/members.css'
import '../css/busyWork.css'
import axios from 'axios'
import Itembankstop from "../../question/component/Itembankstop";
const map={1:"未发布",2:"提交中",3:"已截止",4:"已结束"}
class PollDetailIndex extends Component{
constructor(props){
super(props);
this.pollssubcomRef = React.createRef();
this.state={
tab:["0"],
pollDetail:undefined,
@ -33,7 +35,9 @@ class PollDetailIndex extends Component{
polls_status:3,
}
}
getpollssubcomRef = (Ref) => {
this.pollssubcomRef = Ref;
}
getPollInfo=()=>{
// console.log(this.props);
let pollId=this.props.match.params.pollId;
@ -67,7 +71,17 @@ class PollDetailIndex extends Component{
}catch (e) {
}
this.gettables();
}
gettables=()=>{
try {
this.pollssubcomRef.searchInfo();
}catch (e) {
}
}
newgetPollInfo=()=>{
// console.log(this.props);
let pollId=this.props.match.params.pollId;
@ -263,7 +277,11 @@ class PollDetailIndex extends Component{
{
// 答题列表
parseInt(tab[0])==0 && <PollTabFirst {...this.props} {...this.state}></PollTabFirst>
parseInt(tab[0])==0 && <PollTabFirst
{...this.props}
{...this.state}
getpollssubcomRef={(ref) => this.getpollssubcomRef(ref)}
></PollTabFirst>
}
{
// 统计结果

@ -132,6 +132,11 @@ class PollDetailTabFirst extends Component{
componentDidMount(){
let {order, search, commit_status, poll_group_id, page, order_type} = this.state;
this.getTableList(order, search, commit_status, poll_group_id, page, order_type);
try {
this.props.getpollssubcomRef(this);
} catch (e) {
}
}
// 翻页

@ -3007,9 +3007,9 @@ class PollNew extends Component {
{/*自动生成修改好的获取到的*/}
{/**************************************************************************/}
{this.state.poll_questions === undefined ? "" : this.state.poll_questions.map((item, index) => {
console.log('打印this.state.poll_questions');
console.log(this.state.poll_questions);
console.log(this.state.adddom);
// console.log('打印this.state.poll_questions');
// console.log(this.state.poll_questions);
// console.log(this.state.adddom);
let resultDom;
resultDom = <div >
<p className="clearfix font-16">
@ -3061,7 +3061,7 @@ class PollNew extends Component {
{item.question.answers === undefined ? "" : item.question.answers.map((items, i) => {
return (
<div className="h20 pt20" style={{"clear": "both"}}>
<Radio value={i} className={"fl"} style={{textAlign: "left",marginTop:"3px"}}></Radio>
<Radio value={i} className={"fl"} style={{textAlign: "left"}}></Radio>
<span className={" flex1 "} style={{textAlign: "left","white-space":"pre-wrap","word-break": "break-all","word-wrap": "break-word","float": "left","width":"1116px"}} >{items.answer_text}</span>
</div>

@ -2763,7 +2763,7 @@ class PollNewQuestbank extends Component {
//
// let courseId=this.props.match.params.coursesId;
// if(courseId===undefined){
// this.props.history.push("/courses");
// this.props.history.push("/classrooms");
// }else{
// this.props.history.push(this.props.current_user.first_category_url);
// }

@ -35,7 +35,8 @@ class Immediatelypublish extends Component{
modalsType:false,
modalsTopval:"",
loadtype:false,
chooseId:undefined
chooseId:undefined,
immediatelyopen:false
}
}
//立即发布
@ -73,6 +74,7 @@ class Immediatelypublish extends Component{
Saves:this.homeworkstartend,
course_groups:response.data.course_groups,
starttimesend:response.data.end_time===undefined||response.data.end_time===null||response.data.end_time===""?undefined:response.data.end_time,
immediatelyopen:response.data.course_groups===null||response.data.course_groups.length===0?false:true,
})
}
@ -100,6 +102,7 @@ class Immediatelypublish extends Component{
Saves:this.homeworkstartend,
course_groups:response.data.course_groups,
starttimesend:response.data.end_time===undefined||response.data.end_time===null||response.data.end_time===""?undefined:response.data.end_time,
immediatelyopen:response.data.course_groups===null||response.data.course_groups.length===0?false:true,
})
}
}).catch((error) => {
@ -386,6 +389,7 @@ class Immediatelypublish extends Component{
starttimes={this.state.starttimes}
starttimesend={this.state.starttimesend}
typs={this.state.typs}
immediatelyopen={this.state.immediatelyopen}
/>:""}
{/* 公用的提示弹框 */}

@ -26,4 +26,8 @@
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.color32C090{
color:#32C090 !important;
}

@ -0,0 +1,68 @@
import React from 'react';
import Modals from "../../modals/Modals";
import axios from 'axios';
class Chongzuomodel extends React.Component {
constructor(props) {
super(props);
this.state = {
ModalsType:false,
antIcon:false
}
}
componentDidMount(){
this.setState({
ModalsType:this.props.Chongzuomodeltype,
Modalstopval:`该作业将被打回重做,学生实训记录将被清空!`,
ModalsBottomval:`确定打回?`,
})
}
ModalSaves=()=>{
this.setState({
antIcon:true
})
let zrl=`/myshixuns/${this.props.chongzuoId}/reset_my_game.json?course_id=${this.props.match.params.coursesId}`;
axios.get(zrl).then((response) => {
this.setState({
antIcon:false
})
this.props.showNotification("操作成功");
this.props.hideChongzuomodeltype()
this.props.Isupdatass();
}).catch((error) => {
this.setState({
antIcon:false
})
});
}
ModalCancels=()=>{
this.props.hideChongzuomodeltype()
}
render() {
//console.log(this.props)
// Chongzuomodeltype:undefined,
// chongzuoId:undefined,
return (
<React.Fragment>
<Modals
modalsType={this.state.ModalsType}
modalsTopval={this.state.Modalstopval}
modalsBottomval={this.state.ModalsBottomval}
modalSave={()=>this.ModalSaves()}
modalCancel={()=>this.ModalCancels()}
loadtype={false}
antIcon={this.state.antIcon}
>
</Modals>
</React.Fragment>
);
}
}
export default Chongzuomodel;

@ -1,19 +1,10 @@
import React, {Component} from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
import {getRandomcode, publicSearchs, sortDirections} from 'educoder';
import {
Form,
Select,
Input,
Button,
Checkbox,
Upload,
Icon,
message,
Modal,
Table,
Pagination,
Radio,
Tooltip,
notification,
Spin,
@ -30,18 +21,16 @@ import './Challenges.css';
import {getImageUrl} from 'educoder';
import TraineetraininginformationModal from "./TraineetraininginformationModal";
import DownloadMessageysl from '../../modals/DownloadMessageysl';
import Startshixuntask from "../coursesPublic/Startshixuntask";
import ModulationModal from "../coursesPublic/ModulationModal";
import HomeworkModal from "../coursesPublic/HomeworkModal";
import OneSelfOrderModal from "../coursesPublic/OneSelfOrderModal";
import ShixunWorkModal from "./Shixunworkdetails/ShixunWorkModal";
import NoneData from '../../../modules/courses/coursesPublic/NoneData';
import Chongzuomodel from "./Chongzuomodel";
import NoneDatas from "../signin/component/NoneDatas";
const Search = Input.Search;
const RadioGroup = Radio.Group;
const CheckboxGroup = Checkbox.Group;
const {Option} = Select;
//GraduationTaskssetting.js
//作品列表(学生)
let allow_lates=false;
@ -65,6 +54,8 @@ class Listofworksstudentone extends Component {
//关卡得分final_score
this.state = {
Chongzuomodeltype:undefined,
chongzuoId:undefined,
searchtypes:false,
jobsettingsdata: undefined,
endTime: "2018/11/10 17:10:00",
@ -280,7 +271,11 @@ class Listofworksstudentone extends Component {
width: '98px',
render: (text, record) => (
<span style={{width: '98px',}}>
<span style={record.submitstate === "迟交通关" ? {
<span style={record.submitstate === "重做中" ?{
color: '#FF8432',
textAlign: "center",
width: '98px',
}:record.submitstate === "迟交通关" ? {
color: '#DD1717',
textAlign: "center",
width: '98px',
@ -510,7 +505,7 @@ class Listofworksstudentone extends Component {
),
},
],
orders: "update_time",
orders: "work_score",
columnsstu2: [
{
title: '序号',
@ -675,7 +670,11 @@ class Listofworksstudentone extends Component {
width: '98px',
render: (text, record) => (
<span style={{width: '98px',}}>
<span style={record.submitstate === "迟交通关" ? {
<span style={record.submitstate === "重做中" ?{
color: '#FF8432',
textAlign: "center",
width: '98px',
}:record.submitstate === "迟交通关" ? {
color: '#DD1717',
textAlign: "center",
width: '98px',
@ -906,7 +905,7 @@ class Listofworksstudentone extends Component {
),
},
],
b_order: "desc",
// b_order: "desc",
myorders: "desc",
allow_late: false,
checkedValuesine: undefined,
@ -1029,7 +1028,11 @@ class Listofworksstudentone extends Component {
align: 'center',
className: 'font-14',
render: (text, record) => (
<span style={record.submitstate === "迟交通关" ? {
<span style={record.submitstate === "重做中" ?{
color: '#FF8432',
textAlign: "center",
width: '98px',
}:record.submitstate === "迟交通关" ? {
color: '#DD1717',
textAlign: "center"
} : record.submitstate === "按时通关" ? {color: '#29BD8B', textAlign: "center"}
@ -1294,20 +1297,38 @@ class Listofworksstudentone extends Component {
display: 'block',
align: 'center',
className: 'font-14',
width: '40px',
width: '80px',
render: (text, record) => (
record.submitstate === "未开启" ?
<a style={{textAlign: "center",width: '40px'}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
// onClick={() => this.Viewstudenttraininginformationt(record)}
>{record.has_comment===true?"详情":"评阅 "}</a> :
<span>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
// onClick={() => this.Viewstudenttraininginformationt(record)}
>{record.has_comment===true?"详情":"评阅 "}</a>
</span>
<div>
<a style={{textAlign: "center",width: '40px'}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
>{record.has_comment===true?"已评阅":"评阅 "}</a>
</div>
{this.props.teacherdatapage === undefined ? "": this.props.teacherdatapage.homework_status[0]==="已截止"?"":record.myshixun_id===0?"":<div>
<a style={{textAlign: "center",width: '40px'}} className="color32C090"
onMouseDown={(e) => this.chongzuofun(record.myshixun_identifier)}
>重做</a>
</div>}
</span>:
<span>
<div>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
>{record.has_comment===true?"已评阅":"评阅 "}</a>
</div>
{this.props.teacherdatapage === undefined ? "": this.props.teacherdatapage.homework_status[0]==="已截止"?"":record.myshixun_id===0?"":<div>
<a style={{textAlign: "center",width: '40px'}} className="color32C090"
onMouseDown={(e) => this.chongzuofun(record.myshixun_identifier)}
>重做</a>
</div>}
</span>
)
},
],
@ -1408,7 +1429,11 @@ class Listofworksstudentone extends Component {
align: 'center',
className: 'font-14',
render: (text, record) => (
<span style={record.submitstate === "迟交通关" ? {
<span style={record.submitstate === "重做中" ?{
color: '#FF8432',
textAlign: "center",
width: '98px',
}:record.submitstate === "迟交通关" ? {
color: '#DD1717',
textAlign: "center"
} : record.submitstate === "按时通关" ? {color: '#29BD8B', textAlign: "center"}
@ -1662,19 +1687,37 @@ class Listofworksstudentone extends Component {
display: 'block',
align: 'center',
className: 'font-14',
width: '40px',
width: '80px',
render: (text, record) => (
record.submitstate === "未开启" ?
<a style={{textAlign: "center",width: '40px'}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
// onClick={() => this.Viewstudenttraininginformationt(record)}
>{record.has_comment===true?"详情":"评阅"}</a> :
<span>
<div>
<a style={{textAlign: "center",width: '40px'}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
// onClick={() => this.Viewstudenttraininginformationt(record)}
>{record.has_comment===true?"已评阅":"评阅"}</a>
</div>
{this.props.teacherdatapage === undefined ? "": this.props.teacherdatapage.homework_status[0]==="已截止"?"":record.myshixun_id===0?"":<div>
<a style={{textAlign: "center",width: '40px'}} className="color32C090"
onMouseDown={(e) => this.chongzuofun(record.myshixun_identifier)}
>重做</a>
</div>}
</span>:
<span>
<a style={{textAlign: "center"}} className="color-blue"
<div>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
// onClick={() => this.Viewstudenttraininginformationt(record)}
>{record.has_comment===true?"详情":"评阅"}</a>
</span>
>{record.has_comment===true?"已评阅":"评阅"}</a>
</div>
{this.props.teacherdatapage === undefined ? "": this.props.teacherdatapage.homework_status[0]==="已截止"?"":record.myshixun_id===0?"":<div>
<a style={{textAlign: "center",width: '40px'}} className="color32C090"
onMouseDown={(e) => this.chongzuofun(record.myshixun_identifier)}
>重做</a>
</div>}
</span>
)
},
],
@ -1707,6 +1750,34 @@ class Listofworksstudentone extends Component {
this.Getalistofworks(homeworkid, false);
}
Updatetimedropdon=()=>{
let ooders=""
if(this.state.orders!=="update_time"){
ooders="desc";
}else {
//不是更新时间
if (this.state.myorders === "desc") {
//升序
ooders="asc";
} else if (this.state.myorders === "asc") {
//降序
ooders="desc";
}
}
this.setState({
myorders: ooders,
orders: "update_time",
datajs:undefined,
loadingstate: true,
})
this.Startsortingt("update_time", this.state.course_groupyslstwo, this.state.checkedValuesineinfo, this.state.searchtext, this.state.page, this.state.limit, ooders);
}
//实训作业tbale 列表塞选数据
table1handleChange = (pagination, filters, sorter) => {
//"ascend" 升序
@ -2073,7 +2144,7 @@ class Listofworksstudentone extends Component {
classroom: teacherdata.group_name,
cost_time: teacherdata.cost_time,
has_comment:teacherdata.has_comment,
submitstate: teacherdata.work_status === 0 ? "未开启" : teacherdata.work_status === 1 ? "未通关" : teacherdata.work_status === 2 ? "按时通关" : "迟交通关",
submitstate:teacherdata.work_status === -1 ? "重做中":teacherdata.work_status === 0 ? "未开启" : teacherdata.work_status === 1 ? "未通关" : teacherdata.work_status === 2 ? "按时通关" : "迟交通关",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
@ -2119,7 +2190,9 @@ class Listofworksstudentone extends Component {
classroom: student_works[i].group_name,
cost_time: student_works[i].cost_time,
has_comment:student_works[i].has_comment,
submitstate: student_works[i].work_status === 0 ? "未开启" : student_works[i].work_status === 1 ? "未通关" : student_works[i].work_status === 2 ? "按时通关" : "迟交通关",
myshixun_id:student_works[i].myshixun_id,
myshixun_identifier:student_works[i].myshixun_identifier,
submitstate:student_works[i].work_status === -1 ? "重做中":student_works[i].work_status === 0 ? "未开启" : student_works[i].work_status === 1 ? "未通关" : student_works[i].work_status === 2 ? "按时通关" : "迟交通关",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
@ -2281,7 +2354,7 @@ class Listofworksstudentone extends Component {
classroom: teacherdata.group_name,
cost_time: teacherdata.cost_time,
has_comment:teacherdata.has_comment,
submitstate: teacherdata.work_status === 0 ? "未开启" : teacherdata.work_status === 1 ? "未通关" : teacherdata.work_status === 2 ? "按时通关" : "迟交通关",
submitstate:teacherdata.work_status === -1 ? "重做中":teacherdata.work_status === 0 ? "未开启" : teacherdata.work_status === 1 ? "未通关" : teacherdata.work_status === 2 ? "按时通关" : "迟交通关",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
@ -2614,7 +2687,7 @@ class Listofworksstudentone extends Component {
}).catch((error) => {
console.log(error)
this.setState({
loadingstate: false
loadingstate: false,
})
})
@ -2646,7 +2719,9 @@ class Listofworksstudentone extends Component {
classroom: student_works[i].group_name,
cost_time: student_works[i].cost_time,
has_comment:student_works[i].has_comment,
submitstate: student_works[i].work_status === 0 ? "未开启" : student_works[i].work_status === 1 ? "未通关" : student_works[i].work_status === 2 ? "按时通关" : "迟交通关",
myshixun_id:student_works[i].myshixun_id,
myshixun_identifier:student_works[i].myshixun_identifier,
submitstate:student_works[i].work_status === -1 ? "重做中":student_works[i].work_status === 0 ? "未开启" : student_works[i].work_status === 1 ? "未通关" : student_works[i].work_status === 2 ? "按时通关" : "迟交通关",
// updatetime:this.state.teacherdata.student_works[i].update_time,
// updatetime:"",
updatetime: timedata === "Invalid date" ? "--" : timedata,
@ -3442,6 +3517,19 @@ class Listofworksstudentone extends Component {
})
}
chongzuofun=(id)=>{
this.setState({
chongzuoId:id,
Chongzuomodeltype:true
})
}
hideChongzuomodeltype=()=>{
this.setState({
chongzuoId:undefined,
Chongzuomodeltype:false
})
}
render() {
let {columns,columnss, course_groupysls, datajs, isAdmin, homework_status, course_groupyslstwo, unlimited, unlimitedtwo, course_group_info, orders, task_status, checkedValuesine, searchtext, teacherlist, visible, visibles, game_list, columnsstu, columnsstu2, limit, experience, boolgalist, viewtrainingdata, teacherdata, page, data, jobsettingsdata, styletable, datas, order, loadingstate, computeTimetype} = this.state;
@ -3479,10 +3567,39 @@ class Listofworksstudentone extends Component {
}
}
}
let Teachercolumns=columns;
if(this.state.orders&&this.state.orders==="update_time"){
if(Teachercolumns){
if(Teachercolumns.length>0){
Teachercolumns.map((item,key)=>{
if(item.key){
if(item.key==="work_score"){
//去掉成绩默认排序
item.defaultSortOrder="";
}
}
})
}
}
}
return (
this.props.isAdmin() === true ?
<div className=" clearfix " style={{margin: "auto", minWidth: "1200px"}}>
{this.state.Chongzuomodeltype===true?<Chongzuomodel
{...this.props}
{...this.state}
hideChongzuomodeltype={()=>this.hideChongzuomodeltype()}
Isupdatass={()=>this.Isupdatass()}
/>:""}
{visible === true ? <ModulationModal
visible={visible}
Cancel={() => this.cancelModulationModel()}
@ -3733,12 +3850,34 @@ class Listofworksstudentone extends Component {
</ul>
<style>
{
`
.fiilssort{
position: absolute;
top: -9px;
}
.colorddd{
color:#b7b7b7;
}
`
}
</style>
<div id="graduation_work_list" style={{padding: '0px 20px 10px 20px'}}>
<div className="clearfix">
<span className="fl color-grey-6 font-12"><span
className="color-orange-tip">{teacherdata === undefined ? "" : teacherdata.work_count && teacherdata.work_count}</span>{teacherdata === undefined ? "" : teacherdata.all_member_count && teacherdata.all_member_count} </span>
<div className={"fr drop_down xiaoshou"} onClick={()=>this.Updatetimedropdon()}>
<span className={"color-blue"}>更新时间</span>
<sapn className="relativef ml5"style={{"top":"2px"}} >
<i className={this.state.orders&&this.state.orders==="update_time"&&this.state.myorders==="asc"?
"iconfont icon-sanjiaoxing-up font-12 color-blue fiilssort" :"iconfont icon-sanjiaoxing-up font-12 fiilssort colorddd"}></i>
<i className={this.state.orders&&this.state.orders==="update_time"&&this.state.myorders==="desc"?
"iconfont icon-sanjiaoxing-down font-12 yslbottomsj color-blue":"iconfont icon-sanjiaoxing-down font-12 yslbottomsj colorddd"}></i>
</sapn>
</div>
<style>
{
`
@ -3788,13 +3927,32 @@ class Listofworksstudentone extends Component {
`}</style>
<div className="edu-table edu-back-white ant-tables ysltableo table1">
<Spin tip="正在加载..." spinning={loadingstate}>
{datajs === undefined ? "" : <Table
dataSource={datajs}
columns={columns}
pagination={false}
onChange={this.table1handleChange}
loading={false}
/>}
{datajs === undefined ?
<div style={{
minHeight: "400px",
width:"100%"
}} >
</div>
:
(
this.state.orders&&this.state.orders==="update_time"?
<Table
dataSource={datajs}
columns={Teachercolumns}
pagination={false}
onChange={this.table1handleChange}
loading={false}
/>
:
<Table
dataSource={datajs}
columns={Teachercolumns}
pagination={false}
onChange={this.table1handleChange}
loading={false}
/>
)
}
</Spin>
</div>

@ -279,7 +279,7 @@ class ShixunHomeworkPage extends Component {
typelist={teacherdatapage === undefined ? [""] : teacherdatapage.homework_status}
/>
<a className="color-grey-9 fr font-16 summaryname ml20 mr20" onClick={()=>this.gotohome()}>返回</a>
{teacherdatapage&&teacherdatapage.shixun_status>1?<a className="color-grey-9 fr font-16 mr20"
{teacherdatapage&&teacherdatapage.shixun_status>1?<a className="color-blue fr font-16 mr20"
href={`/shixuns/${teacherdatapage === undefined ? "" : teacherdatapage.shixun_identifier}/challenges`}
target={"_blank"}>实训详情</a>:""}

@ -22,6 +22,7 @@ import "../common/formCommon.css";
import '../css/Courses.css';
import './style.css';
import 'moment/locale/zh-cn';
import Chongzuomodel from "./Chongzuomodel";
class ShixunWorkReport extends Component {
@ -39,7 +40,12 @@ class ShixunWorkReport extends Component {
work_comment:undefined,
has_commit: false,
shixun_detail:[],
view_tpi:false
view_tpi:false,
myshixun_id:undefined,
myshixun_identifier:undefined,
homework_end:undefined,
chongzuoId:undefined,
Chongzuomodeltype:false
}
}
@ -117,7 +123,10 @@ class ShixunWorkReport extends Component {
spinning: false,
has_commit: result.data.has_commit,
shixun_detail:result.data.shixun_detail,
view_tpi:result.data.view_tpi
view_tpi:result.data.view_tpi,
myshixun_id:result.data.myshixun_id,
myshixun_identifier:result.data.myshixun_identifier,
homework_end:result.data.homework_end,
})
}
@ -308,8 +317,22 @@ class ShixunWorkReport extends Component {
}
}
Backtoredo=(id)=>{
this.setState({
chongzuoId:id,
Chongzuomodeltype:true
})
}
hideChongzuomodeltype=()=>{
this.setState({
chongzuoId:undefined,
Chongzuomodeltype:false
})
}
render() {
let {data, showAppraiseModaltype, work_comment_hidden, work_comment, has_commit,shixun_detail,view_tpi} = this.state;
let {data, showAppraiseModaltype, work_comment_hidden, work_comment, has_commit,shixun_detail,view_tpi,myshixun_id,myshixun_identifier,homework_end} = this.state;
let category_id=data===undefined?"":data.category===null?"":data.category.category_id;
let homework_common_id=data===undefined?"":data.homework_common_id;
@ -324,6 +347,13 @@ class ShixunWorkReport extends Component {
return (
data===undefined?"":<Spin indicator={antIcon} spinning={this.state.spinning}>
{this.state.Chongzuomodeltype===true?<Chongzuomodel
{...this.props}
{...this.state}
hideChongzuomodeltype={()=>this.hideChongzuomodeltype()}
Isupdatass={()=>this.getdatalist()}
/>:""}
<Modals
modalsType={this.state.modalsType}
modalsTopval={this.state.modalsTopval}
@ -385,6 +415,12 @@ class ShixunWorkReport extends Component {
{/*className=" color-blue font-14 fr ml20 mt15"*/}
{/*onClick={()=>this.showAppraiseModal(1)}*/}
{/*>评阅</a> : ""}*/}
{this.props.isAdmin()?homework_end===false&&myshixun_id!=0?<a
className=" color-blue font-14 fr ml20 mt15"
onClick={()=>this.Backtoredo(myshixun_identifier)}
>打回重做</a>:"":""}
{this.props.isAdmin() ?<a
className=" color-blue font-14 fr ml20 mt15"
onClick={()=>this.showAppraiseModal("main",undefined,work_comment,work_comment_hidden)}

@ -637,12 +637,19 @@ class ShixunHomework extends Component{
// }
PaginationCourse=(pageNumber)=>{
let {Coursename,order}=this.state;
this.setState({
page:pageNumber,
checkBoxValues:[]
})
let {Coursename,order,checkedtype}=this.state;
if(checkedtype===true){
this.setState({
page:pageNumber,
checkBoxValues:[],
checkedtype:false
})
}else{
this.setState({
page:pageNumber,
checkBoxValues:[],
})
}
this.homeworkupdatalist(Coursename,pageNumber,order);

@ -125,6 +125,15 @@ class Teacherentry extends Component {
</div>
</div>
<style>
{
`
.initials{
cursor: initial !important;
}
`
}
</style>
<div className="ws20s sortinxdirection">
{
isAdmin === true ?
@ -158,9 +167,12 @@ class Teacherentry extends Component {
<div className="qiandaobutton xiaoshou" onClick={(e)=>{e.stopPropagation();this.props.Signin(item.mode,item.id,item.attendance_code)}}>
签到
</div>
:
item.attendance_status==="NORMAL"?
<div className="qiandaobutton" >
: item.attendance_status === "LEAVE" ?
<div className="qjqiandao initials">
请假
</div>
: item.attendance_status==="NORMAL"?
<div className="zcqiandao initials">
正常签到
</div>
:""
@ -175,15 +187,15 @@ class Teacherentry extends Component {
{
item.attendance_status?
item.attendance_status === "NORMAL" ?
<div className="zcqiandao xiaoshou">
<div className="zcqiandao initials">
正常签到
</div>
: item.attendance_status === "LEAVE" ?
<div className="qjqiandao xiaoshou">
<div className="qjqiandao initials">
请假
</div>
: item.attendance_status === "ABSENCE" ?
<div className="kkqiandao xiaoshou">
<div className="kkqiandao initials">
旷课
</div>
:

@ -408,7 +408,7 @@
}
.tbrt{
padding-top: 22px;
padding-left: 28px;
padding-left: 17px;
}
.tbrt .ts {
font-size:12px;
@ -453,6 +453,15 @@
white-space:nowrap;
cursor: default;
}
.maxnamewidth166ss{
max-width: 166px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
cursor: default;
}
.maxnamewidth140s{
width: 140px;
max-width: 140px;
@ -549,3 +558,6 @@
.widh150wpos{
word-break: break-all;
}
a { text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}

@ -101,11 +101,20 @@ class Signedinlist extends Component {
handleChangegroup_ids=(value)=>{
let neval
if(!value){
neval=[]
this.setState({
group_ids: [],
page:1
})
if(value===0){
neval=[0]
this.setState({
group_ids: [0],
page:1
})
}else{
neval=[]
this.setState({
group_ids: [],
page:1
})
}
}else{
neval=[value]
this.setState({
@ -327,11 +336,11 @@ class Signedinlist extends Component {
<Row type="flex" justify="end">
{this.props.defaultActiveKey==="2"?<Col className={"Signedintextright "}>
{this.props.defaultActiveKey==="2"?<Col className={"Signedintextright mr5"}>
<span className={"color26C7C9 mr20"}>正常签到{data&&data.normal_count}</span>
<span className={"colorEAAE4E mr20"}>请假{data&&data.leave_count}</span>
<span className={"colorFF835C"}>旷课{data&&data.absence_count}</span>
</Col>:<Col className={"Signedintextright "}>
</Col>:<Col className={"Signedintextright mr5"}>
<span className={"mr20"}>已签到<span className={"color1890FF"}>{this.state.course_members_count}</span></span>
<span>应签到<span className={"color1890FF"}>{this.state.attendance_count}</span></span>
</Col>}

@ -172,6 +172,8 @@ class Statistics extends Component{
}
})
// console.log(getRandomcode(`${url}?${urllist}`))
this.props.slowDownload(getRandomcode(`${url}?${urllist}`));
}
@ -420,7 +422,7 @@ class Statistics extends Component{
{
this.props.isAdmin()===true?
// 这里是文件下载 不能替换路由
<a className={"ml20 ant-btn-link"} onClick={()=>this.derivefun(this.state.activeKey==="1"?`/classrooms/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`:`/courses/${this.props.match.params.coursesId}/export_member_act_score.xlsx`)}>导出</a>
<a className={"ml20 ant-btn-link"} onClick={()=>this.derivefun(this.state.activeKey==="1"?`/courses/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`:`/courses/${this.props.match.params.coursesId}/export_member_act_score.xlsx`)}>导出</a>
:""
}
</React.Fragment>;

@ -87,6 +87,16 @@ class Videostatistics extends Component{
return(
<React.Fragment>
<div className="ws100s">
<script>
{
`
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
{
tisticsbool===false?
<div className="ws100s" style={{

@ -1,6 +1,6 @@
import React, {Component} from "react";
import '../../signin/css/signincdi.css';
import {Progress, message} from 'antd';
import {Progress, message,Tooltip} from 'antd';
import {getImageUrl,formatSeconds} from 'educoder';
import axios from 'axios';
@ -36,14 +36,9 @@ class Studenticscom extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;//鼠标放上面不显示下划线
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
@ -102,7 +97,9 @@ class Studenticscom extends Component {
<div className="yslshipingshi" style={{width:260,height:100}}>
<div className="ws100s verticallayout tbrt">
<div className="ws100 ts">总观看时长</div>
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
<Tooltip placement="bottom" title={this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}>
<div className="maxnamewidth166ss tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
</Tooltip>
</div>
</div>

@ -38,18 +38,13 @@ class Studentstatistics extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth150s textalignlefts" style={{
<a className="maxnamewidth150s textalignlefts xiaoshout" style={{
color:"#333333"
}} title={record.title}>{record.title}</a>
@ -83,18 +78,13 @@ class Studentstatistics extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s " style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.total_duration}>{record.total_duration}</a>
@ -113,18 +103,13 @@ class Studentstatistics extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s" style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.user_name}>{record.user_name}</a>
@ -297,14 +282,9 @@ class Studentstatistics extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;//鼠标放上面不显示下划线
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>

@ -1,6 +1,6 @@
import React, {Component} from "react";
import '../../signin/css/signincdi.css';
import {Progress, message} from 'antd';
import {Progress, message,Tooltip} from 'antd';
import {getImageUrl,formatSeconds} from 'educoder';
import axios from 'axios';
@ -36,14 +36,9 @@ class Videostatisticscom extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;//鼠标放上面不显示下划线
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
@ -102,8 +97,10 @@ class Videostatisticscom extends Component {
<div className="yslshipingshi" style={{width:260,height:100}}>
<div className="ws100s verticallayout tbrt">
<div className="ws100 ts">总观看时长</div>
<div className="ws100s tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
</div>
<Tooltip placement="bottom" title={this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}>
<div className="maxnamewidth166ss tss">{this.props.watch_staticsdata&&this.props.watch_staticsdata.total_duration?formatSeconds(this.props.watch_staticsdata.total_duration):0}</div>
</Tooltip>
</div>
</div>
</div>

@ -43,18 +43,13 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s" style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.user_name}>{record.user_name}</a>
@ -87,18 +82,13 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s" style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.total_duration}>{record.total_duration}</a></div>
),
@ -117,18 +107,13 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s" style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.feq}>{record.feq}</a>
</div>
@ -145,20 +130,15 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
{
record.start_at?
<a style={{
<a className="xiaoshout" style={{
color:"#333333"
}} title={moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}</a>
:
@ -178,20 +158,15 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
{
record.end_at?
<a style={{
<a className="xiaoshout" style={{
color:"#333333"
}} title={moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}</a>
:
@ -559,14 +534,11 @@ class Videostatisticscomtwo extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;//鼠标放上面不显示下划线
    color:#333;
a{ 
    text-decoration:none !important;
}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>

@ -38,18 +38,13 @@ class Videostatisticslist extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth200ss textalignlefts" style={{
<a className="maxnamewidth200ss textalignlefts xiaoshout" style={{
color:"#333333"
}} title={record.title}>{record.title}</a>
@ -83,18 +78,13 @@ class Videostatisticslist extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth100s " style={{
<a className="maxnamewidth100s xiaoshout" style={{
color:"#333333"
}} title={record.total_time}>{record.total_time}</a>
@ -113,18 +103,13 @@ class Videostatisticslist extends Component {
<script>
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;
    color:#333;
}
a{text-decoration:none !important;}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>
<a className="maxnamewidth150ss" style={{
<a className="maxnamewidth150ss xiaoshout" style={{
color:"#333333"
}} title={record.user_name}>{record.user_name}</a>
@ -294,13 +279,10 @@ class Videostatisticslist extends Component {
{
`
a{ 
    text-decoration:none;
    color:#333;
}
a:hover{
    text-decoration:none;//鼠标放上面不显示下划线
    color:#333;
    text-decoration:none !important;
}
a:hover {text-decoration: none !important;}
a:active{text-decoration:none !important;}
`
}
</script>

@ -272,13 +272,13 @@ class MessagSub extends Component {
return window.open(`/forums/`);
case "Watcher" :
// 用户个人中心页 :id = item.trigger_user.login
return window.open(`/users/${item.trigger_user.login}/courses`)
return window.open(`/users/${item.trigger_user.login}/classrooms`)
case "PraiseTread" :
// 这块太复杂 不好处理
return '';
case "Grade" :
//个人中心页 :id = item.trigger_user.login
// return window.open(`/users/${item.trigger_user.login}/courses`;
// return window.open(`/users/${item.trigger_user.login}/classrooms`;
return "";
case "JoinProject" :
//项目详情-申请加入项目审核页 :id = container_id

@ -269,6 +269,23 @@ class Listjihe extends Component {
}
const types = questionType.filter(item=>item.type === items.item_type);
let Periofters = false;
let Perioftersbols=false;
if (this.props) {
if (this.props.current_user) {
if (this.props.current_user.admin) {
Periofters = true;
}
else if (this.props.current_user.business) {
Perioftersbols = true;
}
}
}
// console.log(this.props);
// console.log("PerioftersPerioftersbols");
// console.log(Periofters);
// console.log(Perioftersbols);
return (
<div key={keindex}
className={chakanjiexiboolindex === keindex ? "w100s borderwds283 pd20 mb20 listjihecolors" : "borderwds pd20 mb20 listjihecolors"}>
@ -595,7 +612,65 @@ class Listjihe extends Component {
}
</div>
: ""
:
//公开需要权限
Periofters===true?
//管理员
<div className="xaxisreverseorder">
<p className="viewparsings xiaoshou mr25" onClick={() => this.props.showmodelysl(items.id)}>
<i className="iconfont icon-shanchu1 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>删除</span>
</p>
{
items.item_type === "PROGRAM" ?
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a onClick={()=>this.seturls(`/problems/${items.program_attr.identifier}/edit`)}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
:
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a onClick={()=>this.seturls(`/problemset/edit/${items.id}`)}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
}
</div>
//运营人员
:Perioftersbols===true?
<div className="xaxisreverseorder">
{
items.item_type === "PROGRAM" ?
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a onClick={()=>this.seturls(`/problems/${items.program_attr.identifier}/edit`)}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
:
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a onClick={()=>this.seturls(`/problemset/edit/${items.id}`)}>
<p className="viewparsings xiaoshou mr25">
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
}
</div>
:""
}
{
items.item_type === "PROGRAM" ?

@ -106,7 +106,18 @@ class Listjihe extends Component {
const quotess =items&&items.quotes&&items.quotes;
const authors=items&&items.author&&items.author.name;
let Periofters = false;
let Perioftersbols=false;
if (this.props) {
if (this.props.current_user) {
if (this.props.current_user.admin) {
Periofters = true;
}
else if (this.props.current_user.business) {
Perioftersbols = true;
}
}
}
return (
<div className={" borderwdsst pd20 mb20 intermediatecenter listjihecolor "} >
{
@ -206,7 +217,43 @@ class Listjihe extends Component {
</p>
}
</div>
:""}
:Periofters===true?
<div className="w35s xaxisreverseorder">
<p className="viewparsings xiaoshou mr25 " onClick={()=>this.props.showmodelysl(items.id)}>
<i className="iconfont icon-shanchu1 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>删除</span>
</p>
{
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a >
<p className="viewparsings xiaoshou mr25 " onClick={()=>this.props.Testpapereditor(items.id)}>
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
}
</div>
:Perioftersbols===true?
<div className="w35s xaxisreverseorder">
{
this.props.Isitapopup&&this.props.Isitapopup==="true"?
""
:
<a >
<p className="viewparsings xiaoshou mr25 " onClick={()=>this.props.Testpapereditor(items.id)}>
<i className="iconfont icon-bianji2 font-17 lg ml7 lh30 icontianjiadaohangcolors mr5"></i>
<span>编辑</span>
</p>
</a>
}
</div>
:
""
}

@ -1123,15 +1123,15 @@ class NewHeader extends Component {
<a href={"/register"} className="mr5 color-white">注册</a>
</span> :
<div className="fr edu-menu-panel mr25" style={{ height: '60px' }}>
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`} className="fl ml15">
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/classrooms`} className="fl ml15">
<img alt="头像" className="radius mt13" height="34" id="nh_user_logo" name="avatar_image"
src={getImageUrl(`images/` + user.image_url)} width="34">
</img>
</a>
<ul className="edu-menu-list" style={{ top: '60px' }}>
{/*<span className="bor-bottom-greyE currentName task-hide">{user.username}</span>*/}
<li><Link to={`/users/${this.props.current_user.login}/courses`}>我的个人主页</Link></li>
{coursestypes === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`}>{this.props.user && this.props.user.main_site === false ? "我的课堂" : "我的教学课堂"}</Link></li>}
<li><Link to={`/users/${this.props.current_user.login}/classrooms`}>我的个人主页</Link></li>
{coursestypes === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/classrooms`}>{this.props.user && this.props.user.main_site === false ? "我的课堂" : "我的教学课堂"}</Link></li>}
{/* p 老师 l 学生 */}
{shixuntype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/shixuns`}>我的实训项目</Link></li>}
{pathstype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/paths`}>{this.props.user && this.props.user.main_site === false ? "我的课程" : "我的实践课程"}</Link></li>}

@ -397,7 +397,7 @@ class TPMIndex extends Component {
newathArray:list
})
}
render() {
render() {
let url = window.location.href;
let flag =false;
@ -671,7 +671,7 @@ class TPMIndex extends Component {
</div>
);
}
}
}
export default SnackbarHOC() (TPMIndexHOC ( TPMIndex ));

@ -86,7 +86,7 @@ class TPMRightSection extends Component {
<p className="font-16 mb20"><i className={"iconfont icon-chuangjianzhe1 audit_situationactive font-14"}></i> </p>
<div className="df">
<a
href={TPMRightSectionData === undefined ? "" : TPMRightSectionData.creator === undefined ? "" : `/users/${TPMRightSectionData.creator.login}/courses`}>
href={TPMRightSectionData === undefined ? "" : TPMRightSectionData.creator === undefined ? "" : `/users/${TPMRightSectionData.creator.login}/classrooms`}>
<img alt="头像" className="radius mr10" height="36"
src={getImageUrl(TPMRightSectionData === undefined ? "" : TPMRightSectionData.creator === undefined ? "" : 'images/' + TPMRightSectionData.creator.image_url + "?1532489442")}
width="36"/>

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

Loading…
Cancel
Save