Merge branches 'PCqiandao' and 'dev_chen' of https://bdgit.educoder.net/Hjqreturn/educoder into PCqiandao

PCqiandao
杨树明 5 years ago
commit d7f79405d7

@ -287,21 +287,34 @@ class ChallengesController < ApplicationController
def index_down
next_challenge = @challenge.next_challenge
position = @challenge.position
@challenge.update_attribute(:position, (position + 1))
next_challenge.update_attribute(:position, next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
begin
ActiveRecord::Base.transaction do
@challenge.update_attributes!(position: (position + 1))
next_challenge.update_attributes!(position: next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_attributes!(evaluate_script: script)
end
rescue => e
tip_exception("下移失败: #{e.message}")
end
end
def index_up
position = @challenge.position
last_challenge = @challenge.last_challenge
@challenge.update_attribute(:position, (position - 1))
last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
begin
ActiveRecord::Base.transaction do
@challenge.update_attribute(:position, (position - 1))
last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
rescue => e
tip_exception("上移失败: #{e.message}")
end
end
def destroy

@ -50,11 +50,16 @@ class CourseModulesController < ApplicationController
# 添加二级目录
def add_second_category
tip_exception("子目录名称不能为空") if params[:name].blank?
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
parent_id = params[:parent_id].to_i
if parent_id != 0
parent_node = @course_module.course_second_categories.find_by(id: parent_id)
tip_exception("上级目录不存在") if parent_node.blank?
end
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(parent_id: parent_id, name: params[:name].strip)
ActiveRecord::Base.transaction do
begin
category = @course_module.course_second_categories.create!(name: params[:name].strip, category_type: @course_module.module_type,
course_id: @course.id, position: @course_module.course_second_categories.count + 1)
course_id: @course.id, position: @course_module.course_second_categories.where(parent_id: parent_id).count + 1, parent_id: parent_id)
render :json => {category_id: category.id, status: 0, message: "添加成功"}
rescue Exception => e
uid_logger_error(e.message)

@ -7,7 +7,7 @@ class CourseSecondCategoriesController < ApplicationController
def rename_category
tip_exception("毕设子目录不能重命名") if @category.category_type == "graduation"
tip_exception("名称不能为空") if params[:name].blank?
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(parent_id: @category.parent_id, name: params[:name].strip)
@category.update_attributes!(name: params[:name].strip)
normal_status(0, "更新成功")
end
@ -17,9 +17,13 @@ class CourseSecondCategoriesController < ApplicationController
tip_exception("移动失败") if params[:position].blank?
unless params[:position].to_i == @category.position
if params[:position].to_i < @category.position
@course_module.course_second_categories.where("position < #{@category.position} and position >= ?", params[:position]).update_all("position = position + 1")
@course_module.course_second_categories
.where("parent_id = #{@category.parent_id} and position < #{@category.position} and position >= ?", params[:position])
.update_all("position = position + 1")
else
@course_module.course_second_categories.where("position > #{@category.position} and position <= ?", params[:position]).update_all("position = position - 1")
@course_module.course_second_categories
.where("parent_id = #{@category.parent_id} and position > #{@category.position} and position <= ?", params[:position])
.update_all("position = position - 1")
end
@category.update!(position: params[:position])
normal_status(0, "移动成功")
@ -32,22 +36,30 @@ class CourseSecondCategoriesController < ApplicationController
tip_exception("毕设子目录不能删除") if @category.category_type == "graduation"
ActiveRecord::Base.transaction do
begin
@course_module.course_second_categories.where("position > #{@category.position}").update_all("position = position - 1")
parent_id = @category.parent_id
@course_module.course_second_categories.where("parent_id = #{parent_id} and position > #{@category.position}")
.update_all("position = position - 1")
# 更新相应对象的子目录id
if @course_module.module_type == "shixun_homework"
@category.homework_commons.update_all(course_second_category_id: 0)
@category.homework_commons.update_all(course_second_category_id: parent_id)
@right_url = "/classrooms/#{@course.id}/shixun_homeworks/#{@course_module.id}"
elsif @course_module.module_type == "attachment"
Attachment.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0)
@right_url = "/classrooms/#{@course.id}/files/#{@course_module.id}"
Attachment.where(course_second_category_id: @category.id).update_all(course_second_category_id: parent_id)
if parent_id == 0
@right_url = "/classrooms/#{@course.id}/files/#{@course_module.id}"
else
@right_url = "/classrooms/#{@course.id}/file/#{parent_id}"
end
elsif @course_module.module_type == "video"
@course.course_videos.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0)
@course.course_videos.where(course_second_category_id: @category.id).update_all(course_second_category_id: parent_id)
@right_url = "/classrooms/#{@course.id}/course_videos"
elsif @course_module.module_type == "common_homework"
@category.homework_commons.update_all(course_second_category_id: 0)
@category.homework_commons.update_all(course_second_category_id: parent_id)
@right_url = "/classrooms/#{@course.id}/common_homeworks/#{@course_module.id}"
elsif @course_module.module_type == "group_homework"
@category.homework_commons.update_all(course_second_category_id: 0)
@category.homework_commons.update_all(course_second_category_id: parent_id)
@right_url = "/classrooms/#{@course.id}/group_homeworks/#{@course_module.id}"
end

@ -1297,7 +1297,7 @@ class CoursesController < ApplicationController
def left_banner
@user = current_user
@is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR
@course_modules = @course.course_modules.where(hidden: 0)
@course_modules = @course.course_modules.where(hidden: 0).includes(first_categories: :children)
@hidden_modules = @course.course_modules.where(hidden: 1)
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group", "video", "common_homework", "group_homework"]
end

@ -24,6 +24,7 @@ class FilesController < ApplicationController
get_category(@course, @course_second_category_id)
@total_count = @attachments.size
@unlink_count = @attachments.no_link.size
if @user.course_identity(@course) == 5
member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
@ -43,7 +44,7 @@ class FilesController < ApplicationController
@attachments = @attachments.by_keywords(params[:search])
if params[:no_link]
@attachments = @attachments.where(link: nil)
@attachments = @attachments.no_link
end
@attachments = @attachments.page(@page).per(@page_size)
@ -142,7 +143,7 @@ class FilesController < ApplicationController
end
def public_with_course_and_project
@attachments = Attachment.publiced.simple_columns
@attachments = Attachment.publiced.no_link.simple_columns
.contains_course_and_project
.includes(:container, author: :user_extension)
.by_filename_or_user_name(params[:search])
@ -155,7 +156,7 @@ class FilesController < ApplicationController
def mine_with_course_and_project
@current_user = current_user
@attachments = Attachment.mine(current_user)
@attachments = Attachment.mine(current_user).no_link
.simple_columns
.contains_course_and_project
.by_keywords(params[:search])

@ -114,6 +114,8 @@ class Weapps::AttendancesController < ApplicationController
@course_members = @course.students if @_is_current_attendance
@all_attendances = @attendance.course_member_attendances
@user = @attendance.user
end
def update

@ -81,6 +81,8 @@ module CoursesHelper
"/classrooms/#{course.id}/statistics"
when "video"
"/classrooms/#{course.id}/course_videos"
when "attendance"
"/classrooms/#{course.id}/signin"
end
end
@ -131,31 +133,33 @@ module CoursesHelper
# 课堂模块的任务数
def course_task_count(course, module_type)
case module_type
when "shixun_homework"
get_homework_commons_count(course, 4, 0)
when "common_homework"
get_homework_commons_count(course, 1, 0)
when "group_homework"
get_homework_commons_count(course, 3, 0)
when "graduation"
0
when "exercise"
course.exercises_count
when "poll"
course.polls_count
when "attachment"
get_attachment_count(course, 0)
when "board"
course_board = course.course_board
course_board.present? ? course_board.messages.size : 0
when "course_group"
course.course_groups_count
when "announcement"
course.informs.count
when "online_learning"
course.shixuns.count
when "video"
course.videos_count + course.live_links.count
when "shixun_homework"
get_homework_commons_count(course, 4, 0)
when "common_homework"
get_homework_commons_count(course, 1, 0)
when "group_homework"
get_homework_commons_count(course, 3, 0)
when "graduation"
0
when "exercise"
course.exercises_count
when "poll"
course.polls_count
when "attachment"
get_attachment_count(course, 0)
when "board"
course_board = course.course_board
course_board.present? ? course_board.messages.size : 0
when "course_group"
course.course_groups_count
when "announcement"
course.informs.count
when "online_learning"
course.shixuns.count
when "video"
course.videos_count + course.live_links.count
when "attendance"
course.course_attendances.count
end
end

@ -25,6 +25,7 @@ class Attachment < ApplicationRecord
scope :search_by_container, -> (ids) {where(container_id: ids)}
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
scope :published, -> {where(is_publish: 1)}
scope :no_link, -> {where(link: nil)}
validates_length_of :description, maximum: 100, message: "不能超过100个字符"

@ -226,7 +226,7 @@ class Course < ApplicationRecord
end
def all_course_module_types
%w[activity announcement online_learning shixun_homework common_homework group_homework exercise attachment course_group graduation poll board statistics video]
%w[activity announcement online_learning shixun_homework common_homework group_homework exercise attachment course_group graduation poll board statistics video attendance]
end
def get_course_module_by_type(type)
@ -429,6 +429,7 @@ class Course < ApplicationRecord
when 'video' then '视频直播'
when 'board' then '讨论'
when 'course_group' then '分班'
when 'attendance' then '签到'
when 'statistics' then '统计'
else ''
end
@ -449,7 +450,8 @@ class Course < ApplicationRecord
when 'video' then 11
when 'board' then 12
when 'course_group' then 13
when 'statistics' then 14
when 'attendance' then 14
when 'statistics' then 15
else 100
end
end

@ -4,6 +4,7 @@ class CourseModule < ApplicationRecord
# 二级目录
has_many :course_second_categories
has_many :first_categories, -> { first_categories }, class_name: "CourseSecondCategory"
validates :module_name, length: { maximum: 20, too_long: "不能超过20个字符" }
@ -17,12 +18,14 @@ class CourseModule < ApplicationRecord
scope :shixun_homework_module, -> { where(module_type: 'shixun_homework') }
scope :search_by_module_type, -> (type) {where(module_type:type)}
# 课堂模块的子目录
def course_second_categories
after_create :create_graduation_module
private
def create_graduation_module
if module_type == "graduation" && CourseSecondCategory.where(course_module_id: self.id).count == 0
CourseSecondCategory.create!(course_module_id: self.id, course_id: self.course_id, name: "毕设选题", category_type: "graduation", position: 1)
CourseSecondCategory.create!(course_module_id: self.id, course_id: self.course_id, name: "毕设任务", category_type: "graduation", position: 2)
end
CourseSecondCategory.where(course_module_id: self.id)
end
end

@ -3,7 +3,12 @@ class CourseSecondCategory < ApplicationRecord
belongs_to :course
belongs_to :course_module
belongs_to :parent, class_name: "CourseSecondCategory", foreign_key: "parent_id", optional: true
has_many :homework_commons
has_many :children, -> { order(position: :asc ) }, class_name: "CourseSecondCategory", foreign_key: "parent_id", dependent: :destroy
scope :first_categories, -> { where(parent_id: 0) }
validates :name, length: { maximum: 60, too_long: "不能超过60个字符" }

@ -38,9 +38,9 @@ class CreateWatchVideoService < ApplicationService
end
else
# 开始播放时记录一次
if params[:course_video_id].present?
if params[:course_id].present?
# 课堂视频
course_video = CourseVideo.find(params[:course_video_id])
course_video = CourseVideo.find_by(video_id: params[:video_id], course_id: params[:course_id])
watch_course_video = WatchCourseVideo.find_or_initialize_by(course_video_id: course_video.id, user_id: user.id) do |d|
d.start_at = current_time
d.duration = params[:duration]
@ -52,7 +52,7 @@ class CreateWatchVideoService < ApplicationService
watch_course_video.save! unless watch_course_video.persisted?
else
# 非课堂视频
video = Video.find_by(params[:video_id])
video = Video.find(params[:video_id])
watch_video_history = build_video_log(current_time, video.id)
watch_video_history.save!
end

@ -2,7 +2,10 @@ json.course_module do
json.id @course_module.id
json.module_name @course_module.module_name
json.module_type @course_module.module_type
json.course_second_categories do
json.array! @course_module.course_second_categories, :id, :name
json.course_second_categories @course_module.first_categories do |category|
json.(category, :id, :name)
json.course_third_categories category.children do |child|
json.(child, :id, :name)
end
end
end

@ -0,0 +1,6 @@
json.category_id category.id
json.category_name category.name
json.position category.position
json.category_count category_task_count(@course, category, @user)
json.category_type category.category_type_str
json.second_category_url category_url(category, @course)

@ -25,13 +25,12 @@ json.course_modules @course_modules.each do |mod|
end
end
else
json.second_category mod.course_second_categories.each do |category|
json.category_id category.id
json.category_name category.name
json.position category.position
json.category_count category_task_count(@course, category, @user)
json.category_type category.category_type_str
json.second_category_url category_url(category, @course)
json.second_category mod.first_categories.each do |category|
json.partial! "category_info", category: category
json.third_category category.children do |child|
json.partial! "category_info", category: child
end
end
end
end

@ -5,6 +5,7 @@ json.data do
json.total_count @total_count
json.publish_count @publish_count
json.unpublish_count @unpublish_count
json.unlink_count @unlink_count
json.course_is_public @course.is_public?
json.files do
json.array! @attachments do |attachment|

@ -14,7 +14,7 @@ json.name shixun.name
json.stu_num shixun.myshixuns_count
json.experience shixun.all_score
json.diffcult level_to_s(shixun.trainee)
json.score_info shixun.averge_star # todo: 这块可以改成只显示实训的平均分,不用每次都去取每种星的分数了。
json.score_info shixun.shixun_preference_info # todo: 这块可以改成只显示实训的平均分,不用每次都去取每种星的分数了。
json.is_jupyter shixun.is_jupyter
# 用于是否显示导航栏中的'背景知识'
json.propaedeutics shixun.propaedeutics.present?

@ -9,6 +9,10 @@ json.name @attendance.name
json.attendance_date @attendance.attendance_date.strftime("%Y-%m-%d")
json.start_time @attendance.start_time.strftime("%H:%M")
json.end_time @attendance.end_time.strftime("%H:%M")
json.author do
json.user_name @user.real_name
json.user_login @user.login
end
# json.course_groups @group_ids do |group|
# json.(group, :id, :name, :course_members_count)

@ -0,0 +1,16 @@
class AddAttendanceToCourseModule < ActiveRecord::Migration[5.2]
def change
Course.all.each do |course|
unless course.course_modules.exists?(module_type: "attendance")
atta_position = course.course_modules.find_by(module_type: 'course_group')&.position.to_i
attendance_position = atta_position != 0 ? (atta_position + 1) : 14
course.course_modules.where("position >= #{attendance_position}").update_all("position = position + 1")
if course.is_end
course.course_modules << CourseModule.new(module_type: "attendance", hidden: 1, module_name: "签到", position: attendance_position)
else
course.course_modules << CourseModule.new(module_type: "attendance", hidden: 0, module_name: "签到", position: attendance_position)
end
end
end
end
end

@ -0,0 +1,7 @@
class AddParentIdToSecondCategory < ActiveRecord::Migration[5.2]
def change
add_column :course_second_categories, :parent_id, :integer, default: 0
add_index :course_second_categories, :parent_id
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

@ -13,6 +13,7 @@ import VideoPanel from './video-play'
import './video.css';
import '../../user/usersInfo/video/InfosVideo.css'
import axios from 'axios';
import { logWatchHistory } from "../../../services/video-service";
const DEFAULT_VIDEO_WIDTH_IN_MD = "90%" // 400
const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400
@ -31,8 +32,8 @@ class Video extends Component {
videoVisible: false,
visible: false,
moveVisible:false,
moveVideoId:undefined
moveVisible: false,
moveVideoId: undefined
}
}
@ -70,7 +71,6 @@ class Video extends Component {
}
}
// 编辑成功后回调的方法
editSuccess = () => {
this.props.showNotification("视频信息修改成功!");
@ -82,7 +82,7 @@ class Video extends Component {
let videoId = {
videoId: item.id,
title: item.title,
link:item.link
link: item.link
}
this.setState({
videoId,
@ -118,8 +118,6 @@ class Video extends Component {
_clipboard = null;
}
} else {
// videoEl.current && videoEl.current.play()
setTimeout(() => {
if (!_clipboard) {
_clipboard = new ClipboardJS('.copybtn');
@ -148,7 +146,7 @@ class Video extends Component {
axios.delete(url, {
params: {
video_id: item.id,
is_link:item.link ? true : undefined
is_link: item.link ? true : undefined
}
}).then(result => {
if (result) {
@ -168,30 +166,30 @@ class Video extends Component {
}
// 移动到
moveVideo=(id,flag)=>{
if(!flag){
moveVideo = (id, flag) => {
if (!flag) {
this.setState({
moveVisible:true,
moveVideoId:id
moveVisible: true,
moveVideoId: id
})
}else{
} else {
this.props.define({
title:'提示',
content:"您不是课堂管理员或者视频发布者,暂不能移动视频。",
title: '提示',
content: "您不是课堂管理员或者视频发布者,暂不能移动视频。",
})
}
}
setMoveVisible=(flag)=>{
setMoveVisible = (flag) => {
this.setState({
moveVisible:flag,
moveVideoId:undefined
moveVisible: flag,
moveVideoId: undefined
})
}
render() {
const { visible, videoVisible, videoId , moveVisible , moveVideoId } = this.state;
const { visible, videoVisible, videoId, moveVisible, moveVideoId } = this.state;
const CourseId = this.props.match.params.coursesId;
const VID=this.props.match.params.videoId;
const VID = this.props.match.params.videoId;
const login = this.props.user && this.props.user.login;
const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url);
@ -201,7 +199,7 @@ class Video extends Component {
const { videos, upload, uploadVideo, videoData, changePage, pageSize, page } = this.props;
const operation = admin || business;
const {course_identity} = this.props.coursedata;
const { course_identity } = this.props.coursedata;
const flagMove = parseInt(course_identity) < 5;
return (
@ -214,8 +212,8 @@ class Video extends Component {
{...this.props}
visible={moveVisible}
mainId={videoData && videoData.course_module_id}
setMoveVisible={(flag)=>this.setMoveVisible(flag)}
successFunc={()=>uploadVideo()}
setMoveVisible={(flag) => this.setMoveVisible(flag)}
successFunc={() => uploadVideo()}
id={moveVideoId}
></MoveBox>
<HeadlessModal
@ -224,7 +222,7 @@ class Video extends Component {
className="showVideoModal"
width={800 - 1}
>
{videoId && <VideoPanel src={videoId.file_url} />}
{videoId && <VideoPanel src={videoId.file_url} videoId={videoId.videoId} courseId={CourseId} logWatchHistory={logWatchHistory} />}
<div className="df copyLine">
<Input value={_inputValue}
@ -242,7 +240,7 @@ class Video extends Component {
{
videos && videos.length > 0 ?
<React.Fragment>
<p className="font-grey-9 mt20 mb20 pl5"> <span className="color-orange">{videoData && videoData.count}</span> </p>
<div className="videoContent">
{
@ -259,7 +257,7 @@ class Video extends Component {
getCopyText={this.getCopyText}
operation={operation || item.user_id === user_id}
deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined}
moveVideo={videoData && videoData.has_category && flagMove ? ()=>this.moveVideo(item.id,(course_identity > 2 && item.user_id !== user_id)):undefined}
moveVideo={videoData && videoData.has_category && flagMove ? () => this.moveVideo(item.id, (course_identity > 2 && item.user_id !== user_id)) : undefined}
>
</VideoInReviewItem>
)

@ -1,37 +0,0 @@
import React, { useEffect, useRef } from 'react'
export default ({ url }) => {
const ref = useRef()
useEffect(() => {
let player = null
if (window.flvjs.isSupported) {
player = window.flvjs.createPlayer({
type: 'flv',
volume: 0.8,
cors: true,
url,
muted: false
})
if (ref.current) {
player.attachMediaElement(ref.current)
player.load()
player.play()
}
}
return () => {
if (player) {
player.unload()
player.pause()
player.destroy()
player = null
}
}
}, [url, ref.current])
return (
<video ref={ref} controls autoPlay={true} muted={false} className="flv-player"></video>
)
}

@ -1,18 +1,165 @@
import React, { Fragment } from 'react'
import ReactFlvPlayer from './flv-player'
import React, { useRef, useEffect, useCallback } from 'react'
const regex = /(android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini)/i
// https://www.showdoc.cc/educoder?page_id=4029884447803706
export default ({ src, videoId, logWatchHistory, courseId = null }) => {
export default ({ src }) => {
const suf = src.split('.').pop()
const isFlv = suf === 'flv'
return (
<Fragment>
{
isFlv ? <ReactFlvPlayer url={src} isMuted={true} /> : <video src={src} controls autoPlay={true} controlsList="nodownload">
<source type={`video/${suf}`} src={src} />
您的浏览器不支持 video 标签
</video>
const el = useRef()
const deviceMatch = navigator.userAgent.toLowerCase().match(regex)
const device = deviceMatch ? deviceMatch[0] : 'pc'
let totalDuration = 0
let totalTimePlayed = 0
let sumTimePlayed = 0
let lastUpdatedTime = 0
let lastEffectUpdatedTime = 0
let logId = null
let initLog = false
let timeTick = 20 // 20s
let logCount = 1
let isLoging = false
let isSeeking = false
const log = useCallback((callback) => {
let params = {}
if (logId) {
params['log_id'] = logId
params['watch_duration'] = totalTimePlayed //
params['total_duration'] = sumTimePlayed //
} else {
if (courseId) {
params['video_id'] = parseInt(videoId, 10)
params['course_id'] = parseInt(courseId, 10)
} else {
params['video_id'] = videoId
}
params['duration'] = totalDuration
params['device'] = device
}
async function getLogId() {
isLoging = true
let id = await logWatchHistory(params)
logId = id
isLoging = false
if (callback) {
callback()
}
}
getLogId()
}, [videoId, courseId])
useEffect(() => {
let player = null
if (window.flvjs.isSupported && isFlv) {
player = window.flvjs.createPlayer({
type: 'flv',
volume: 0.8,
cors: true,
url: src,
muted: false
})
if (el.current) {
player.attachMediaElement(el.current)
player.load()
}
} else {
el.current.setAttribute('src', src)
}
return () => {
if (player) {
player.unload()
player.pause()
player.destroy()
player = null
}
}
}, [el, isFlv, src])
useEffect(() => {
function onPlay() {
if (!initLog) {
initLog = true
log()
}
</Fragment>
}
async function onEnded() {
log(() => {
logId = null
logCount = 1
totalTimePlayed = 0
lastUpdatedTime = 0
sumTimePlayed = 0
initLog = false
isLoging = false
lastEffectUpdatedTime = 0
isSeeking = false
})
}
function onTimeupdate() {
if (!isSeeking) {
let newTime = el.current.currentTime
let timeDiff = newTime - lastUpdatedTime
let effectTimeDiff = newTime - lastEffectUpdatedTime
if (effectTimeDiff > 0) {
totalTimePlayed += effectTimeDiff
lastEffectUpdatedTime = newTime
}
sumTimePlayed += Math.abs(timeDiff)
lastUpdatedTime = newTime
if (!isLoging) {
if (sumTimePlayed - logCount * timeTick >= 0) {
logCount++
log()
}
}
}
}
function onSeeking() {
isSeeking = true
lastUpdatedTime = el.current.currentTime
lastEffectUpdatedTime = el.current.currentTime
}
function onSeeked() {
isSeeking = false
}
function onCanPlay() {
totalDuration = el.current.duration
if (totalDuration <= 20) {
timeTick = totalDuration / 3
}
el.current.addEventListener('play', onPlay)
}
el.current.addEventListener('canplay', onCanPlay)
el.current.addEventListener('ended', onEnded)
el.current.addEventListener('seeking', onSeeking)
el.current.addEventListener('seeked', onSeeked)
el.current.addEventListener('timeupdate', onTimeupdate)
return () => {
el.current.removeEventListener('canplay', onCanPlay)
el.current.removeEventListener('play', onPlay)
el.current.removeEventListener('ended', onEnded)
el.current.removeEventListener('seeking', onSeeking)
el.current.removeEventListener('seeked', onSeeked)
el.current.removeEventListener('timeupdate', onTimeupdate)
}
}, [el, src])
return (
<video ref={el} controls autoPlay={false} controlsList="nodownload" muted={false} />
)
}

@ -745,7 +745,7 @@ class Challenges extends Component {
</div>
<div className="challengtes_Item">
<div className="flex1">
<div className="flex1 width0">
<div className="clearfix mb5">
{/*onClick={() => this.EditTraining(this.props.identity, item.challenge_id, "/editquestion")}*/}
{this.props.identity<5?

@ -268,7 +268,7 @@
justify-content: space-between;
align-items: center;
}
.flex1{
.flex1.width0{
flex: 1;
width: 0;
}

@ -1,22 +1,14 @@
import React, { useState, useEffect, useContext, useRef, memo } from 'react';
import {Link} from 'react-router-dom';
import React, { useContext } from 'react';
import { getUrl2, isDev, ThemeContext } from 'educoder'
import { ThemeContext } from 'educoder'
import { Modal } from 'antd'
function HeadlessModal (props) {
// const [ visible, setVisible ] = useState(false)
function HeadlessModal(props) {
const theme = useContext(ThemeContext);
const { category, visible, setVisible, className, width } = props;
useEffect(() => {
}, [])
const { visible, setVisible, className, width } = props;
return (
<Modal
<Modal
visible={visible}
className={`headless ${className}`}
title={null}
@ -48,7 +40,7 @@ function HeadlessModal (props) {
top: -13px;
}
`}</style>
<i className="iconfont icon-htmal5icon19 closeBtn" onClick={ () => setVisible(false) }></i>
<i className="iconfont icon-htmal5icon19 closeBtn" onClick={() => setVisible(false)}></i>
{props.children}
</Modal>
)

@ -10,6 +10,7 @@ import HeadlessModal from '../common/HeadlessModal'
import ClipboardJS from 'clipboard'
import VideoPlay from '../../../courses/Video/video-play';
import { logWatchHistory } from '../../../../services/video-service';
function useModal(initValue) {
const [visible, setVisible] = useState(initValue)
@ -219,32 +220,32 @@ function InfoVideo(props) {
}
function deleteVideo(item){
function deleteVideo(item) {
props.confirm({
content: '该视频将被删除,不可恢复',
subContent: '是否确认删除?',
onOk: () => {
const url = `/users/${user && user.login}/videos/${item.id}.json`;
axios.delete(url).then(result => {
if (result) {
props.showNotification(`视频删除成功!`);
if (pageObj.current === 1) {
if (categoryObj.category === 'all') {
fetchvideos()
} else {
fetchReviewvideos()
}
} else {
pageObj.onChange(1)
const url = `/users/${user && user.login}/videos/${item.id}.json`;
axios.delete(url).then(result => {
if (result) {
props.showNotification(`视频删除成功!`);
if (pageObj.current === 1) {
if (categoryObj.category === 'all') {
fetchvideos()
} else {
fetchReviewvideos()
}
} else {
pageObj.onChange(1)
}
}
}
}).catch(error => {
console.log(error);
})
}).catch(error => {
console.log(error);
})
},
onCancel() {
console.log('Cancel');
console.log('Cancel');
},
});
}
@ -267,7 +268,7 @@ function InfoVideo(props) {
className="showVideoModal"
width={800 - 1}
>
{videoModalObj.visible && <VideoPlay src={videoId.file_url} />}
{videoModalObj.visible && <VideoPlay src={videoId.file_url} videoId={videoId.videoId} logWatchHistory={logWatchHistory} />}
<div className="df copyLine">
<Input value={_inputValue}
className="dark"

@ -0,0 +1,11 @@
import axios from 'axios'
export async function logWatchHistory(params) {
try {
const response = await axios.post('/watch_video_histories.json', params)
return response.data.log_id
} catch (error) {
console.log(error)
}
return 0
}
Loading…
Cancel
Save