Merge remote-tracking branch 'origin/develop' into develop

Adjustreact
杨树明 5 years ago
commit 8d923c34ac

2
.gitignore vendored

@ -43,7 +43,7 @@
/public/react/config/stats.json /public/react/config/stats.json
/public/react/stats.json /public/react/stats.json
/public/react/.idea/* /public/react/.idea/*
/public/h5build
/public/npm-debug.log /public/npm-debug.log
# avatars # avatars

@ -7,17 +7,17 @@ class LiveLinksController < ApplicationController
def index def index
lives = @course.live_links lives = @course.live_links
order_str = "on_status desc,id desc" order_str = "on_status desc, live_time desc"
@total_count = lives.size @total_count = lives.size
@my_live_id = @course.live_links.find_by(user_id: current_user.id)&.id @my_live_id = @course.live_links.find_by(user_id: current_user.id)&.id
order_str = "live_links.id = #{@my_live_id} desc, #{order_str}" if @my_live_id.present? # order_str = "live_links.id = #{@my_live_id} desc, #{order_str}" if @my_live_id.present?
lives = lives.order("#{order_str}") lives = lives.order("#{order_str}")
@lives = paginate lives.includes(user: :user_extension) @lives = paginate lives.includes(user: :user_extension)
end end
def create def create
tip_exception("一个老师只能设置一个直播间") if @course.live_links.where(user_id: current_user.id).exists? on_status = params[:live_time].present? && params[:live_time].to_time <= Time.now ? 1 : 0
@course.live_links.create!(create_params.merge(user_id: current_user.id)) @course.live_links.create!(create_params.merge(user_id: current_user.id, on_status: on_status))
render_ok render_ok
end end
@ -38,7 +38,8 @@ class LiveLinksController < ApplicationController
end end
end end
else else
current_live.update!(create_params) on_status = params[:live_time].present? && params[:live_time].to_time <= Time.now ? 1 : 0
current_live.update!(create_params.merge(on_status: on_status))
end end
render_ok render_ok
end end
@ -51,7 +52,7 @@ class LiveLinksController < ApplicationController
private private
def create_params def create_params
params.permit(:url, :description) params.permit(:url, :description, :course_name, :platform, :live_time, :duration)
end end
def current_live def current_live

@ -265,7 +265,9 @@ class MyshixunsController < ApplicationController
uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end end
# 隐藏代码文件 和 VNC的都不需要走版本库 # 隐藏代码文件 和 VNC的都不需要走版本库
unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?) vnc = @myshixun.shixun&.vnc
unless @hide_code || (vnc && params[:evaluate].present?)
# 远程版本库文件内容 # 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
@ -275,8 +277,8 @@ class MyshixunsController < ApplicationController
else else
params[:content] params[:content]
end end
uid_logger_dubug("###11222333####{content}") uid_logger_dubug("content_#{@myshixun.identifier}: #{content}")
uid_logger_dubug("###222333####{last_content}") uid_logger_dubug("###last_content_#{@myshixun.identifier}####{last_content}")
if content != last_content if content != last_content
@content_modified = 1 @content_modified = 1
@ -286,6 +288,7 @@ class MyshixunsController < ApplicationController
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted" message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
uid_logger_dubug("112233#{author_name}") uid_logger_dubug("112233#{author_name}")
uid_logger_dubug("112233#{author_email}") uid_logger_dubug("112233#{author_email}")
uid_logger_dubug("daiao_debug_#{@myshixun.identifier}: #{@repo_path}: #{path}; #{message}; #{content}; ")
@content = GitService.update_file(repo_path: @repo_path, @content = GitService.update_file(repo_path: @repo_path,
file_path: path, file_path: path,
message: message, message: message,

@ -474,7 +474,7 @@ class ShixunsController < ApplicationController
if params[:shixun][:vnc] if params[:shixun][:vnc]
shixun_params.merge(vnc_evaluate: 1) shixun_params.merge(vnc_evaluate: 1)
else else
shixun_params shixun_params.merge(vnc_evaluate: 0)
end end
@shixun.update_attributes!(update_params) @shixun.update_attributes!(update_params)
end end

@ -72,7 +72,7 @@ class SubjectsController < ApplicationController
end end
# 排序 # 排序
order_str = reorder == "publish_time" ? "status = 2 desc, publish_time asc" : "updated_at desc" order_str = (reorder == "publish_time" ? "homepage_show desc, excellent desc, status = 2 desc, publish_time asc" : "homepage_show desc, excellent desc, updated_at desc")
@subjects = @subjects.reorder(order_str) @subjects = @subjects.reorder(order_str)
end end

@ -322,7 +322,7 @@ module TidingDecorator
end end
def live_link_content def live_link_content
I18n.t(locale_format) % container&.user.try(:show_real_name) I18n.t(locale_format) % container&.course_name
end end
def student_graduation_topic_content def student_graduation_topic_content

@ -4,8 +4,12 @@ class LiveLink < ApplicationRecord
has_many :tidings, as: :container, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy
validates :url, presence: true, format: { with: CustomRegexp::URL, message: "必须为网址超链接" } # validates :url, format: { with: CustomRegexp::URL, message: "必须为网址超链接" }
validates :description, length: { maximum: 100, too_long: "不能超过100个字符" } validates :description, length: { maximum: 100, too_long: "不能超过100个字符" }
validates :course_name, presence: true
validates :platform, presence: true
# validates :live_time, presence: true
validates :duration, numericality: { only_integer: true, greater_than: 0}, allow_blank: true
def op_auth? def op_auth?
user == User.current || User.current.admin_or_business? user == User.current || User.current.admin_or_business?

@ -22,7 +22,7 @@ class Subjects::CourseUsedInfoService < ApplicationService
# choice_shixun_frequency: 选用该课程实训的次数 # choice_shixun_frequency: 选用该课程实训的次数
course_info = [] course_info = []
schools.find_in_batches do |s| schools.find_in_batches do |s|
Parallel.each(s) do |school| s.each do |school|
name = school.name name = school.name
course_count = school.course_count course_count = school.course_count
student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size

@ -11,7 +11,7 @@ class Subjects::ShixunUsedInfoService < ApplicationService
position = stage.position position = stage.position
shixuns = stage.shixuns.includes(myshixuns: :games, homework_commons: :course) shixuns = stage.shixuns.includes(myshixuns: :games, homework_commons: :course)
shixuns.find_in_batches(batch_size: 1000) do |s| shixuns.find_in_batches(batch_size: 1000) do |s|
Parallel.each_with_index(s, in_processes: 2) do |shixun, index| s.each_with_index do |shixun, index|
stage = "#{position}-#{index+1}" stage = "#{position}-#{index+1}"
name = shixun.name name = shixun.name
myshixuns = shixun.myshixuns myshixuns = shixun.myshixuns

@ -13,7 +13,7 @@ class Subjects::UserUsedInfoService < ApplicationService
users_info = [] users_info = []
users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2}, users: {is_test: false}) users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2}, users: {is_test: false})
users.find_in_batches(batch_size: 500) do |u| users.find_in_batches(batch_size: 500) do |u|
Parallel.each(u, in_processes: 2) do |user| u.each do |user|
myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)} myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)}
name = "#{user.lastname}#{user.firstname}" name = "#{user.lastname}#{user.firstname}"
passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size

@ -25,7 +25,9 @@ class Videos::BatchPublishService < ApplicationService
video.title = param[:title].to_s.strip.presence || video.title video.title = param[:title].to_s.strip.presence || video.title
video.apply_publish video.apply_publish
if param[:course_id].present?
video.status = "published"
end
video.save! video.save!
if param[:course_id].present? if param[:course_id].present?

@ -40,10 +40,14 @@ json.exam do
json.all_questions_count @items.size json.all_questions_count @items.size
json.discipline do json.discipline do
json.(@exam.sub_discipline&.discipline, :id, :name) if @exam.sub_discipline&.discipline.present?
json.(@exam.sub_discipline&.discipline, :id, :name)
end
end end
json.sub_discipline do json.sub_discipline do
json.(@exam.sub_discipline, :id, :name) if @exam.sub_discipline.present?
json.(@exam.sub_discipline, :id, :name)
end
end end
json.tag_disciplines @exam.tag_disciplines do |tag| json.tag_disciplines @exam.tag_disciplines do |tag|
json.(tag, :id, :name) json.(tag, :id, :name)

@ -17,7 +17,10 @@ json.homeworks @homework_commons.each do |homework|
json.status_time curr_status[:time] json.status_time curr_status[:time]
json.time_status curr_status[:time_status] json.time_status curr_status[:time_status]
json.allow_late homework.allow_late json.allow_late homework.allow_late
json.author homework.user.real_name json.author homework.user&.real_name
json.author_img url_to_avatar(homework.user)
json.author_login homework.user&.login
json.created_at homework.created_at.strftime("%Y-%m-%d")
# 只有在主目录才显示 # 只有在主目录才显示
json.upper_category_name homework.course_second_category&.name unless params[:category] json.upper_category_name homework.course_second_category&.name unless params[:category]

@ -84,6 +84,7 @@ elsif @user_course_identity == Course::STUDENT
json.user_login @work.user.login json.user_login @work.user.login
json.student_id @work.user.student_id json.student_id @work.user.student_id
json.user_name @work.user.real_name json.user_name @work.user.real_name
json.user_img url_to_avatar(@work.user)
json.group_name @member.course_group_name json.group_name @member.course_group_name
end end
@ -108,6 +109,7 @@ if @homework.homework_type == "practice"
json.view_answer_count work.myshixun.try(:view_answer_count).to_i json.view_answer_count work.myshixun.try(:view_answer_count).to_i
json.user_login work.user.try(:login) json.user_login work.user.try(:login)
json.user_name work.user.try(:real_name) json.user_name work.user.try(:real_name)
json.user_img url_to_avatar(work.user)
json.student_id work.user.try(:student_id) 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.group_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name)
json.work_status work.compelete_status json.work_status work.compelete_status
@ -169,6 +171,7 @@ elsif @homework.homework_type == "group" || @homework.homework_type == "normal"
json.user_login @is_evaluation ? "--" : work.user.try(:login) json.user_login @is_evaluation ? "--" : work.user.try(:login)
json.user_name @is_evaluation ? "匿名" : work.user.try(:real_name) json.user_name @is_evaluation ? "匿名" : work.user.try(:real_name)
json.user_img url_to_avatar(@is_evaluation ? "0" : work.user)
end end
end end

@ -1 +1 @@
json.(@live, :id, :description, :url) json.(@live, :id, :description, :url, :platform, :live_time, :duration, :course_name)

@ -1,12 +1,12 @@
json.lives @lives do |live| json.lives @lives do |live|
json.(live, :id, :description, :on_status) json.(live, :id, :description, :on_status, :duration, :course_name, :platform)
json.url live.on_status ? live.url : "" json.url live.on_status ? live.url : ""
json.author_name live.user.show_real_name json.author_name live.user.show_real_name
json.author_login live.user.login json.author_login live.user.login
json.author_img url_to_avatar(live.user) json.author_img url_to_avatar(live.user)
json.op_auth live.op_auth? json.op_auth live.op_auth?
json.delete_auth live.delete_auth? json.delete_auth live.delete_auth?
json.created_at live.created_at.strftime('%Y-%m-%d') json.live_time live.live_time&.strftime('%Y-%m-%d %H:%M:%S')
end end
json.my_live_id @my_live_id json.my_live_id @my_live_id
json.total_count @total_count json.total_count @total_count

@ -238,4 +238,4 @@
2_end: "你提交的发布视频申请:%s审核未通过<br/><span>原因:%{reason}</span>" 2_end: "你提交的发布视频申请:%s审核未通过<br/><span>原因:%{reason}</span>"
PublicCourseStart_end: "你报名参与的开放课程:%s将于%s正式开课" PublicCourseStart_end: "你报名参与的开放课程:%s将于%s正式开课"
SubjectStartCourse_end: "您创建的开放课程:%s 已达到开课人数要求。您可以在24小时内自主开设新一期课程。如果超过24小时未开课平台将自动开课并复制您上一期的课程内容。" SubjectStartCourse_end: "您创建的开放课程:%s 已达到开课人数要求。您可以在24小时内自主开设新一期课程。如果超过24小时未开课平台将自动开课并复制您上一期的课程内容。"
LiveLink_end: "%s老师正在直播中" LiveLink_end: "%s 直播将于30分钟后开始"

@ -173,7 +173,10 @@ zh-CN:
live_link: live_link:
description: '说明' description: '说明'
url: '链接' url: '链接'
course_name: '课程名称'
platform: '直播平台'
live_time: '开播时间'
duration: '直播时长'

@ -0,0 +1,8 @@
class AddColumnsToLiveLinks < ActiveRecord::Migration[5.2]
def change
add_column :live_links, :course_name, :string
add_column :live_links, :platform, :string
add_column :live_links, :live_time, :datetime
add_column :live_links, :duration, :integer
end
end

@ -0,0 +1,11 @@
class MigrateUserLocation < ActiveRecord::Migration[5.2]
def change
UserExtension.where("location like '%省'").each do |ue|
ue.update_column("location", ue.location.chop)
end
UserExtension.where("location_city like '%市'").each do |ue|
ue.update_column("location_city", ue.location_city.chop)
end
end
end

@ -0,0 +1,10 @@
class ModifyVncEvaluteForShixuns < ActiveRecord::Migration[5.2]
def change
Shixun.find_each do |shixun|
if !shixun.vnc && shixun.vnc_evaluate
puts "####shixun_id: #{shixun.id}"
shixun.update_column(:vnc_evaluate, false)
end
end
end
end

@ -0,0 +1,13 @@
namespace :live_notice do
desc "send a live message to students before 30 minutes"
task message: :environment do
lives = LiveLink.where(on_status: 0).where("live_time <= '#{Time.now + 30*60}' and live_time > '#{Time.now}'")
lives.each do |live|
LivePublishJob.perform_later(live.id)
end
end
task on_status: :environment do
LiveLink.where(on_status: 0).where("live_time <= '#{Time.now}'").update_all(on_status: 1)
end
end

@ -5,12 +5,14 @@ namespace :subjects do
puts("---------------------data_statistic_begin") puts("---------------------data_statistic_begin")
Rails.logger.info("---------------------data_statistic_begin") Rails.logger.info("---------------------data_statistic_begin")
subjects = Subject.where(status: 2, hidden: 0) subjects = Subject.where(status: 2, hidden: 0)
str = "" if ENV['subject_id'].present?
buffer_size = 0 subjects = subjects.where(id:ENV['subject_id'])
end
column_value = "subject_id, study_count, course_study_count, initiative_study, passed_count, course_used_count, " + column_value = "subject_id, study_count, course_study_count, initiative_study, passed_count, course_used_count, " +
"school_used_count, created_at, updated_at" "school_used_count, created_at, updated_at"
subjects.find_in_batches(batch_size: 50) do |s| subjects.find_in_batches(batch_size: 50) do |s|
Parallel.each_with_index(s, in_processes: 4) do |subject, index| str = []
Parallel.each_with_index(s, in_threads: 4) do |subject, index|
puts("---------------------data_statistic: #{subject.id}") puts("---------------------data_statistic: #{subject.id}")
Rails.logger.info("---------------------data_statistic: #{subject.id}") Rails.logger.info("---------------------data_statistic: #{subject.id}")
data = Subjects::DataStatisticService.new(subject) data = Subjects::DataStatisticService.new(subject)
@ -18,26 +20,19 @@ namespace :subjects do
next if study_count == 0 next if study_count == 0
course_study_count = data.course_study_count course_study_count = data.course_study_count
initiative_study = study_count - course_study_count initiative_study = study_count - course_study_count
str += ", " unless str.empty? str << ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " +
str += ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " +
"#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " + "#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1 puts "index: #{index}; worker_number: #{Parallel.worker_number}"
puts "buffer_size: #{buffer_size}; subjects_count: #{s.count}; index:#{index+1}" puts "####str: #{str}"
if buffer_size == 1000 || s.count == (index+1) end
sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}" if str.size > 0
puts sql sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str.uniq.join(",")}"
ActiveRecord::Base.connection.execute sql puts sql
str = "" ActiveRecord::Base.connection.execute sql
buffer_size = 0
end
end end
end end
if buffer_size > 0
sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
end
puts("---------------------data_statistic_end") puts("---------------------data_statistic_end")
Rails.logger.info("---------------------data_statistic_end") Rails.logger.info("---------------------data_statistic_end")
end end
@ -46,38 +41,37 @@ namespace :subjects do
puts("---------------------course_info_statistic_begin") puts("---------------------course_info_statistic_begin")
Rails.logger.info("---------------------course_info_statistic_begin") Rails.logger.info("---------------------course_info_statistic_begin")
subjects = Subject.where(status: 2, hidden: 0) subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "subject_id, school_id, school_name, course_count, student_count, choice_shixun_num, " + column_value = "subject_id, school_id, school_name, course_count, student_count, choice_shixun_num, " +
"choice_shixun_frequency, created_at, updated_at" "choice_shixun_frequency, created_at, updated_at"
if ENV['subject_id'].present?
subjects.find_in_batches(batch_size: 50) do |s| subjects = subjects.where(id:ENV['subject_id'])
Parallel.each(s, in_processes: 4) do |subject| end
subjects.find_in_batches(batch_size: 20) do |s|
str = []
Parallel.each(s, in_processes: 6) do |subject|
puts("---------------------course_info_statistic: #{subject.id}") puts("---------------------course_info_statistic: #{subject.id}")
Rails.logger.info("---------------------course_info_statistic: #{subject.id}") Rails.logger.info("---------------------course_info_statistic: #{subject.id}")
data = Subjects::CourseUsedInfoService.call(subject) data = Subjects::CourseUsedInfoService.call(subject)
Parallel.map_with_index(data) do |key, index| data.each do |key|
next if key[:school_id].nil? next if key[:school_id].nil?
str += ", " unless str.empty? str << ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " +
str += ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " +
"#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " + "#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1 # if str.size == 1000
if buffer_size == 1000 || (index + 1) == data.size # sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str.uniq.join(",")}"
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}" # str_c = str
puts sql # puts sql
ActiveRecord::Base.connection.execute sql # ActiveRecord::Base.connection.execute sql
str = "" # str -= str_c
buffer_size = 0 # end
end end
if str.size > 0
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str.uniq.join(",")}"
puts sql
ActiveRecord::Base.connection.execute sql
end end
end end
end end
if buffer_size > 0
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
end
puts("---------------------course_info_statistic_end") puts("---------------------course_info_statistic_end")
Rails.logger.info("---------------------course_info_statistic_end") Rails.logger.info("---------------------course_info_statistic_end")
end end
@ -86,38 +80,35 @@ namespace :subjects do
puts("---------------------shixun_info_statistic_begin") puts("---------------------shixun_info_statistic_begin")
Rails.logger.info("---------------------shixun_info_statistic_begin") Rails.logger.info("---------------------shixun_info_statistic_begin")
subjects = Subject.where(status: 2, hidden: 0) subjects = Subject.where(status: 2, hidden: 0)
str = "" if ENV['subject_id'].present?
buffer_size = 0 subjects = subjects.where(id:ENV['subject_id'])
end
column_value = "subject_id, shixun_id, stage, shixun_name, challenge_count, course_count, " + column_value = "subject_id, shixun_id, stage, shixun_name, challenge_count, course_count, " +
"school_count, used_count, passed_count, evaluate_count, passed_ave_time, created_at, updated_at" "school_count, used_count, passed_count, evaluate_count, passed_ave_time, created_at, updated_at"
subjects.find_in_batches(batch_size: 50) do |s| subjects.find_in_batches(batch_size: 20) do |s|
Parallel.each_with_index(s, in_processes: 4) do |subject| Parallel.each_with_index(s, in_processes: 4) do |subject, index, str = []|
puts("---------------------shixun_info_statistic: #{subject.id}") puts("---------------------shixun_info_statistic: #{subject.id}")
Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}") Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}")
data = Subjects::ShixunUsedInfoService.call(subject) data = Subjects::ShixunUsedInfoService.call(subject)
data.each_with_index do |key, index| data.each do |key|
next if key[:shixun_id].nil? next if key[:shixun_id].nil?
str += ", " unless str.empty? str << ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " +
str += ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " +
"#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " + "#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " +
"#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " + "#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1 # if str.size == 1000
if buffer_size == 1000 || (index+1) == data.size # sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str.join(",")}"
sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}" # puts sql
puts sql # ActiveRecord::Base.connection.execute sql
ActiveRecord::Base.connection.execute sql # end
str = "" end
buffer_size = 0 if str.size > 0
end sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str.join(",")}"
puts sql
ActiveRecord::Base.connection.execute sql
end end
end end
end end
if buffer_size > 0
sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
end
puts("---------------------shixun_info_statistic_end") puts("---------------------shixun_info_statistic_end")
Rails.logger.info("---------------------shixun_info_statistic_end") Rails.logger.info("---------------------shixun_info_statistic_end")
end end
@ -126,36 +117,29 @@ namespace :subjects do
puts("---------------------user_info_statistic_begin") puts("---------------------user_info_statistic_begin")
Rails.logger.info("---------------------user_info_statistic_begin") Rails.logger.info("---------------------user_info_statistic_begin")
subjects = Subject.where(status: 2, hidden: 0) subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "user_id, subject_id, username, passed_myshixun_count, passed_games_count, " + column_value = "user_id, subject_id, username, passed_myshixun_count, passed_games_count, " +
"code_line_count, evaluate_count, cost_time, created_at, updated_at" "code_line_count, evaluate_count, cost_time, created_at, updated_at"
subjects.find_in_batches(batch_size: 20) do |s|
subjects.find_in_batches(batch_size: 50) do |s| Parallel.each_with_index(s, in_processes: 4) do |subject, index, str = []|
Parallel.each_with_index(s, in_processes: 4) do |subject, index|
puts("---------------------user_info_statistic: #{subject.id}") puts("---------------------user_info_statistic: #{subject.id}")
data = Subjects::UserUsedInfoService.call(subject) data = Subjects::UserUsedInfoService.call(subject)
data.each do |key| data.each do |key|
next if key[:user_id].nil? str << ("(#{key[:user_id]}, #{subject.id}, '#{key[:name].gsub(/'/, '"')}', #{key[:passed_myshixun_count]}, " +
str += ", " unless str.empty?
str += ("(#{key[:user_id]}, #{subject.id}, '#{key[:name].gsub(/'/, '"')}', #{key[:passed_myshixun_count]}, " +
"#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " + "#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1 # if str.size == 1000
if buffer_size == 1000 || (index+1 == data.size) # sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str.join(",")}"
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}" # ActiveRecord::Base.connection.execute sql
ActiveRecord::Base.connection.execute sql # str = []
str = "" # end
buffer_size = 0 end
end if str.size > 0
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str.join(",")}"
puts sql
ActiveRecord::Base.connection.execute sql
end end
end end
end end
if buffer_size > 0
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
end
puts("---------------------user_info_statistic_end") puts("---------------------user_info_statistic_end")
Rails.logger.info("---------------------user_info_statistic_end") Rails.logger.info("---------------------user_info_statistic_end")
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 66 KiB

@ -1195,6 +1195,9 @@ const options = [{
children: [{ children: [{
value: "太原", value: "太原",
label: '太原' label: '太原'
},{
value: "吕梁",
label: '吕梁'
},{ },{
value: '长治', value: '长治',
label: '长治' label: '长治'

@ -36,6 +36,12 @@ class Live extends Component{
</a> </a>
<a href="https://www.douyu.com/special/guide/anchor" target="_blank" className="color-blue ml20">(简明手册)</a> <a href="https://www.douyu.com/special/guide/anchor" target="_blank" className="color-blue ml20">(简明手册)</a>
</li> </li>
<li>
<a href="https://lenovo325000.d17.cc/" target="_blank"><img alt="" src={WeiBaiTong} className="mr8" width="28px"/>
<label className="color-grey-3 pointer">威佰通</label>
</a>
<a href="https://www.educoder.net/forums/3734" target="_blank" className="color-blue ml20">(简明手册)</a>
</li>
</ul> </ul>
{ {
lives && lives.length > 0 ? lives && lives.length > 0 ?

@ -1,25 +1,17 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Switch } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import { Modal } from 'antd';
import { WordsBtn } from 'educoder'; import { WordsBtn } from 'educoder';
import axios from 'axios'; import axios from 'axios';
class LiveItem extends Component{ class LiveItem extends Component{
constructor(props) {
changeStatus=(flag,event,id)=>{ super(props);
const url = `/live_links/${id}.json`; this.state = {
axios.put(url,{ visible:false
on_status:flag?1:0 }
}).then(result=>{
if(result){
this.props.showNotification(`直播已${flag?"开启":"关闭"}!`);
const { successFunc } = this.props;
successFunc && successFunc(1);
}
}).catch(error=>{
console.log(error);
})
} }
deleteLive=(id)=>{ deleteLive=(id)=>{
this.props.confirm({ this.props.confirm({
content: '是否确认删除?', content: '是否确认删除?',
@ -40,39 +32,87 @@ class LiveItem extends Component{
console.log('Cancel'); console.log('Cancel');
}, },
}); });
}
alertInfo=()=>{
console.log("dddd");
this.setState({
visible:true
})
}
onDialogOkBtnClick=()=>{
this.setState({
visible:false,
})
} }
render(){ render(){
const { key, item , setLiveId } = this.props; const { key, item , setLiveId } = this.props;
// let flag = false; const { visible } = this.state;
// flag = item.on_status;
return( return(
<div className="liveItem" key={key}> <div className="liveItem" key={key}>
<Modal
title="提示"
visible={visible}
closable={false}
footer={null}
keyboard={false}
centered={true}
>
<div className="task-popup-content">
<p className="task-popup-text-center font-16 pb20">直播链接失效</p >
</div>
<div className="task-popup-submit clearfix edu-txt-center">
<a className="task-btn task-btn-orange mr51" onClick={this.onDialogOkBtnClick}>知道了</a >
</div>
</Modal>
{
visible ?
<style>{
`
body{
width: calc(100% - 7px)!important;
overflow: hidden!important;
}
.-task-sidebar{
right:42px!important
}
`}
</style>
:
""
}
<div className="lineMiddle livesMain"> <div className="lineMiddle livesMain">
<span className="lineMiddle"> <span className="lineMiddle">
<img alt={`${item.author_name}`} className="liveAuthor" src={getImageUrl(`images/${item.author_img}`)}/> <span className="font-18 task-hide" style={{maxWidth:"759px"}}>{item.course_name}</span>
<label>{item.author_name}</label>
<span className={item.on_status?"labels living":"labels lived"}>{item.on_status?'已开播':'未开播'}</span> <span className={item.on_status?"labels living":"labels lived"}>{item.on_status?'已开播':'未开播'}</span>
</span> </span>
{
item.op_auth ?
<Switch checkedChildren="on" key={key} className="switchStyle" unCheckedChildren="off" checked={item.on_status} onChange={(flag,event)=>this.changeStatus(flag,event,item.id)}></Switch>:""
}
</div> </div>
<div className="lineMiddle mt15"> <div className="lineMiddle mt15">
<div className="liveDesc"> <div className="liveDesc">
<p><span className="task-hide-2 break_word">{item.description}</span></p> <p><span className="task-hide-2 break_word">{item.description}</span></p>
</div> </div>
{ {
item.on_status? item.on_status ?
<a className="btns going" target="_blank" href={`${item.url}`}>进入</a> <React.Fragment>
{
item.url ?
<a className="btns going" target="_blank" href={`${item.url}`}>进入</a>
:
<a className="btns going" onClick={this.alertInfo}>进入</a>
}
</React.Fragment>
: :
<span className="btns ect">进入</span> <span className="btns ect">进入</span>
} }
</div> </div>
<p className="lineMiddle livesMain mt15 font-12"> <p className="lineMiddle livesMain mt15 font-12">
<span className="color-grey-9">创建时间{item.created_at}</span> <span className="lineMiddle color-grey-9">
<img alt={`${item.author_name}`} className="liveAuthor" src={getImageUrl(`images/${item.author_img}`)}/>
<label className="mr50">{item.author_name}</label>
{ item.platform && <span className="mr50">直播平台{item.platform}</span> }
{ item.live_time && <span className="mr50">开播时间{item.live_time}</span>}
{ item.duration && <span className="mr50">直播时长{item.duration}</span> }
</span>
<span> <span>
{ {
item.op_auth ? item.op_auth ?
@ -80,7 +120,7 @@ class LiveItem extends Component{
} }
{ {
item.delete_auth ? item.delete_auth ?
<WordsBtn style="s" className="ml30" onClick={()=>this.deleteLive(item.id)}>删除</WordsBtn> <WordsBtn style="grey" className="ml30" onClick={()=>this.deleteLive(item.id)}>删除</WordsBtn>
:"" :""
} }
</span> </span>

@ -1,19 +1,47 @@
import React,{ Component } from "react"; import React,{ Component } from "react";
import { Modal , Form , Input , Spin } from 'antd'; import { Modal , Form , Input , Spin , Select , AutoComplete , DatePicker , InputNumber } from 'antd';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import moment from 'moment';
import { handleDateString } from 'educoder';
import './video.css'; import './video.css';
import axios from 'axios'; import axios from 'axios';
const { TextArea } = Input; const { TextArea } = Input;
const { Option } = Select;
const array=['腾讯课堂','B站','斗鱼','威佰通'];
function range(start, end) {
const result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
}
function disabledDateTime() {
return {
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
};
}
function disabledDate(current) {
return current && current < moment().endOf('day').subtract(1, 'days');
}
class LiveNew extends Component{ class LiveNew extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
isSpining:false isSpining:false,
beginTime:undefined,
} }
} }
componentDidMount=()=>{
this.checkType();
}
componentDidUpdate=(prevState)=>{ componentDidUpdate=(prevState)=>{
if(prevState && prevState.liveId !== this.props.liveId){ if(prevState && prevState.liveId !== this.props.liveId){
this.setState({ this.setState({
@ -25,7 +53,7 @@ class LiveNew extends Component{
checkType=()=>{ checkType=()=>{
const { liveId } = this.props; const { liveId } = this.props;
this.clearAll();
if(liveId){ if(liveId){
const url =`/live_links/${liveId}/edit.json`; const url =`/live_links/${liveId}/edit.json`;
axios.get(url).then(result=>{ axios.get(url).then(result=>{
@ -33,14 +61,15 @@ class LiveNew extends Component{
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
url:result.data.url, url:result.data.url,
description:result.data.description, description:result.data.description,
platform:result.data.platform || "腾讯课堂",
duration:result.data.duration,
course_name:result.data.course_name
})
this.setState({
beginTime:result.data.live_time && moment(result.data.live_time,"YYYY-MM-DD HH:mm")
}) })
} }
}) })
}else{
this.props.form.setFieldsValue({
url:undefined,
description:undefined
})
} }
this.setState({ this.setState({
isSpining:false isSpining:false
@ -50,7 +79,9 @@ class LiveNew extends Component{
handleSubmit=()=>{ handleSubmit=()=>{
this.props.form.validateFields((err, values) => { this.props.form.validateFields((err, values) => {
if(!err){ if(!err){
console.log("2") this.setState({
isSpining:true
})
const { liveId } = this.props; const { liveId } = this.props;
if(liveId){ if(liveId){
// 修改 // 修改
@ -64,15 +95,23 @@ class LiveNew extends Component{
// 修改 // 修改
updateFunc=(id,values)=>{ updateFunc=(id,values)=>{
const url = `/live_links/${id}.json`; const url = `/live_links/${id}.json`;
const { beginTime } = this.state;
axios.put(url,{ axios.put(url,{
...values ...values,
live_time:beginTime
}).then(result=>{ }).then(result=>{
if(result){ if(result){
this.props.showNotification("修改成功!"); this.props.showNotification("修改成功!");
const { setliveVisibel } = this.props; const { setliveVisibel } = this.props;
setliveVisibel && setliveVisibel(false,true); setliveVisibel && setliveVisibel(false,true);
} }
this.setState({
isSpining:false
})
}).catch(error=>{ }).catch(error=>{
this.setState({
isSpining:false
})
console.log(error); console.log(error);
}) })
} }
@ -81,15 +120,23 @@ class LiveNew extends Component{
creatFunc=(values)=>{ creatFunc=(values)=>{
const CourseId=this.props.match.params.coursesId; const CourseId=this.props.match.params.coursesId;
const url = `/courses/${CourseId}/live_links.json`; const url = `/courses/${CourseId}/live_links.json`;
const { beginTime } = this.state;
axios.post(url,{ axios.post(url,{
...values ...values,
live_time:beginTime
}).then(result=>{ }).then(result=>{
if(result){ if(result){
this.props.showNotification("添加成功!"); this.props.showNotification("添加成功!");
const { setliveVisibel } = this.props; const { setliveVisibel } = this.props;
setliveVisibel && setliveVisibel(false,true); setliveVisibel && setliveVisibel(false,true);
} }
this.setState({
isSpining:false
})
}).catch(error=>{ }).catch(error=>{
this.setState({
isSpining:false
})
console.log(error); console.log(error);
}) })
} }
@ -107,23 +154,44 @@ class LiveNew extends Component{
cancelNew=()=>{ cancelNew=()=>{
const { setliveVisibel } = this.props; const { setliveVisibel } = this.props;
this.clearAll();
setliveVisibel && setliveVisibel(false);
}
clearAll=()=>{
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
course_name:undefined,
platform:"腾讯课堂",
url:undefined, url:undefined,
description:undefined description:undefined,
duration:undefined
})
this.setState({
beginTime:undefined
})
}
onChangeTime=(data,dateString)=>{
this.setState({
beginTime:handleDateString(dateString)
}) })
setliveVisibel && setliveVisibel(false);
} }
render(){ render(){
const { isSpining } = this.state; const { isSpining , beginTime } = this.state;
const {getFieldDecorator} = this.props.form; const {getFieldDecorator} = this.props.form;
const { visible } = this.props; const { visible } = this.props;
const dataSource = array.map((item,key)=>{
return(
<Option value={item}>{item}</Option>
)
})
return( return(
<Modal <Modal
visible={visible} visible={visible}
width="560px" width="560px"
title={'直播设置'} title={'添加直播'}
footer={null} footer={null}
closable={false} closable={false}
className="liveModal" className="liveModal"
@ -131,13 +199,58 @@ class LiveNew extends Component{
<Spin spinning={isSpining}> <Spin spinning={isSpining}>
<div className="task-popup-content"> <div className="task-popup-content">
<Form onSubmit={this.handleSubmit}> <Form onSubmit={this.handleSubmit}>
<Form.Item label={`直播课程`}>
{getFieldDecorator('course_name', {
rules: [{required: true, message: "请输入课程名称"}],
})(
<Input placeholder="请输入课程名称" />
)}
</Form.Item>
<Form.Item label={`直播平台`}>
{getFieldDecorator('platform', {
rules: [{required: true, message: "请选择直播平台"}],
})(
<AutoComplete
placeholder="请选择或输入直播平台名称"
dataSource={dataSource}
>
</AutoComplete>
)}
</Form.Item>
<Form.Item label={`直播链接`}> <Form.Item label={`直播链接`}>
{getFieldDecorator('url', { {getFieldDecorator('url', {
rules: [{required: true, message: "请输入第三方直播链接"}], rules: [],
})( })(
<Input placeholder="请输入第三方直播链接,如:腾讯课堂播放链接等。" /> <Input placeholder="请输入第三方直播链接,如:腾讯课堂播放链接等。" />
)} )}
</Form.Item> </Form.Item>
<div className="flex-bottom">
<div className="flex1">
<p className="ant-col ant-form-item-label color-grey-3 font-16 setStyle">开播时间</p>
<DatePicker
dropdownClassName="hideDisable"
className="timeStyle mb20"
placeholder="如2020/02/02 12:00"
style={{width:"220px"}}
showTime={{ format: 'HH:mm' }}
locale={locale}
format="YYYY-MM-DD HH:mm"
showToday={false}
disabledTime={disabledDateTime}
disabledDate={disabledDate}
value={beginTime && moment(beginTime,"YYYY-MM-DD HH:mm")}
onChange={this.onChangeTime}
></DatePicker>
</div>
<Form.Item label={`直播时长`}>
{getFieldDecorator('duration', {
rules: [],
})(
<InputNumber placeholder="请输入直播时长" style={{width:"220px"}}/>
)}
</Form.Item>
<span className="mb20 ml5">分钟</span>
</div>
<Form.Item label={`直播说明`}> <Form.Item label={`直播说明`}>
{getFieldDecorator('description', { {getFieldDecorator('description', {
rules: [{ rules: [{
@ -147,10 +260,7 @@ class LiveNew extends Component{
<TextArea rows={4} placeholder="可在此介绍开播具体事项,如开播时间安排等。" /> <TextArea rows={4} placeholder="可在此介绍开播具体事项,如开播时间安排等。" />
)} )}
</Form.Item> </Form.Item>
{/* <p className="flex-middle" style={{justifyContent:"space-between"}}>
<span>EduCoder推荐您使用<a href="https://ke.qq.com/" target="_blank" className="color-blue">腾讯课堂</a></span>
<a href="https://pub.idqqimg.com/pc/misc/files/20200204/2e4cb765bef54f0c919c0ab8ab79d969.pdf" target="_blank" className="color-blue">操作指引</a>
</p> */}
</Form> </Form>
<div className="clearfix mt30 edu-txt-center"> <div className="clearfix mt30 edu-txt-center">
<a onClick={this.cancelNew} className="task-btn mr30">取消</a> <a onClick={this.cancelNew} className="task-btn mr30">取消</a>

@ -28,7 +28,6 @@ class VideoIndex extends Component{
lives:undefined, lives:undefined,
liveData:undefined, liveData:undefined,
my_liveId:undefined,
liveId:undefined, liveId:undefined,
liveVisible:false liveVisible:false
@ -48,8 +47,17 @@ class VideoIndex extends Component{
} }
componentDidMount=()=>{ componentDidMount=()=>{
const { type ,page } = this.state; const { search } = this.props.location;
this.checkType(type,page); const { page } = this.state;
if(search && search === "?open=live"){
this.setState({
type:"live"
})
this.checkType("live",page);
}else{
this.checkType("video",page);
}
} }
// 获取直播列表 // 获取直播列表
getLiveList=(page)=>{ getLiveList=(page)=>{
@ -66,8 +74,6 @@ class VideoIndex extends Component{
liveData:result.data, liveData:result.data,
lives:result.data.lives, lives:result.data.lives,
isSpining:false, isSpining:false,
my_liveId:result.data.my_live_id,
liveId:result.data.my_live_id
}) })
} }
}).catch(error=>{ }).catch(error=>{
@ -155,9 +161,8 @@ class VideoIndex extends Component{
// } // }
// 直播设置 // 直播设置
liveSetting=()=>{ liveSetting=()=>{
const { my_liveId } = this.state;
this.setState({ this.setState({
liveId:my_liveId liveId:undefined
}) })
this.setliveVisibel(true); this.setliveVisibel(true);
} }
@ -166,6 +171,11 @@ class VideoIndex extends Component{
this.setState({ this.setState({
liveVisible:flag liveVisible:flag
}) })
if(flag === false){
this.setState({
liveId:undefined
})
}
if(changetypeFlag){ if(changetypeFlag){
this.checkType("live",1); this.checkType("live",1);
} }
@ -195,10 +205,22 @@ class VideoIndex extends Component{
<style>{ <style>{
` `
body{ body{
width: 100%!important; width: calc(100% - 7px)!important;
overflow: hidden!important; overflow: hidden!important;
} }
`}</style>:"" .-task-sidebar{
right:42px!important
}
`}</style>:
<style>{
`
.-task-sidebar{
right:35px
}
body{
width: 100%!important;
}
`}</style>
} }
<div className="edu-back-white" style={{marginBottom:"1px"}}> <div className="edu-back-white" style={{marginBottom:"1px"}}>
@ -223,7 +245,7 @@ class VideoIndex extends Component{
} }
</React.Fragment> </React.Fragment>
: :
<WordsBtn style="blue" className="font-16 ml30" onClick={this.liveSetting}>直播设置</WordsBtn> <WordsBtn style="blue" className="font-16 ml30" onClick={this.liveSetting}>添加直播</WordsBtn>
} }
</li> </li>
} }

@ -42,6 +42,11 @@
align-items: center; align-items: center;
height: 25px; height: 25px;
} }
.flex-bottom{
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.square-main .buttonRow i { .square-main .buttonRow i {
vertical-align: top; vertical-align: top;
font-size: 16px; font-size: 16px;
@ -68,8 +73,8 @@
align-items: center; align-items: center;
} }
.liveAuthor{ .liveAuthor{
width: 36px; width: 20px;
height: 36px; height: 20px;
border-radius: 50%; border-radius: 50%;
margin-right: 20px; margin-right: 20px;
} }
@ -117,6 +122,16 @@
line-clamp: 2; line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
.timeStyle{
transition: 0.5s;
}
.borderRed{
border:1px solid #f5222d;
border-radius: 4px;
}
.setStyle{
margin-bottom: 5px!important;
}
.switchStyle.ant-switch-checked{ .switchStyle.ant-switch-checked{
background-color: #25C03B; background-color: #25C03B;
} }
@ -128,7 +143,7 @@
} }
.liveModal .ant-row.ant-form-item{ .liveModal .ant-row.ant-form-item{
position: relative; position: relative;
margin-bottom: 20px; margin-bottom: 16px;
} }
.liveModal .ant-form-explain{ .liveModal .ant-form-explain{
position: absolute; position: absolute;
@ -136,8 +151,8 @@
left: 0px; left: 0px;
} }
.liveModal .ant-col.ant-form-item-label{ .liveModal .ant-col.ant-form-item-label{
height: 30px; height: 22px;
line-height: 30px; line-height: 22px;
} }
.platform{ .platform{
background: #fff; background: #fff;
@ -147,7 +162,7 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
.platform > li{ .platform > li{
margin-right: 80px; margin-right: 50px;
display: flex; display: flex;
align-items: center; align-items: center;
} }

@ -399,15 +399,15 @@ class ShixunhomeWorkItem extends Component{
</WordsBtn>:"":"":"":"" </WordsBtn>:"":"":"":""
} }
{ this.props.isAdmin?<a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr">查看详情</a>:""} { this.props.isAdmin?<a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr">作品详情</a>:""}
{ {
this.props.isStudent? <a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr mt2">查看详情</a>:"" this.props.isStudent? <a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr mt2">作品详情</a>:""
} }
{ {
this.props.isNotMember===true? this.props.discussMessage.private_icon===true?"" this.props.isNotMember===true? this.props.discussMessage.private_icon===true?""
:<a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr">查看详情</a>:"" :<a onClick={()=>this.hrefjumpskip("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+discussMessage.homework_id+"/list?tab=0")} className="btn colorblue font-16 fontweight400 mr20 fr">作品详情</a>:""
} }

@ -510,6 +510,8 @@ class MessagSub extends Component {
//分组作业 //分组作业
return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}`); return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}`);
} }
case 'LiveLink':
return window.open(`/courses/${item.belong_container_id}/course_videos?open=live`);
case 'Hack': case 'Hack':
if (item.extra && item.parent_container_type !== 'HackDelete') { if (item.extra && item.parent_container_type !== 'HackDelete') {
return window.open(`/problems/${item.extra}/edit`); return window.open(`/problems/${item.extra}/edit`);

Loading…
Cancel
Save