diff --git a/app/controllers/watch_video_histories_controller.rb b/app/controllers/watch_video_histories_controller.rb new file mode 100644 index 000000000..996c76d24 --- /dev/null +++ b/app/controllers/watch_video_histories_controller.rb @@ -0,0 +1,8 @@ +class WatchVideoHistoriesController < ApplicationController + before_action :require_login + + def create + watch_log = CreateWatchVideoService.new(current_user, request, params).call + render_ok(log_id: watch_log&.id) + end +end diff --git a/app/models/course_video.rb b/app/models/course_video.rb index 2cfa151ce..e192cf7f8 100644 --- a/app/models/course_video.rb +++ b/app/models/course_video.rb @@ -5,4 +5,6 @@ class CourseVideo < ApplicationRecord validates :title, length: { maximum: 60, too_long: "不能超过60个字符" }, allow_blank: true validates :link, format: { with: CustomRegexp::URL, message: "必须为网址超链接" }, allow_blank: true + + has_many :watch_course_videos end diff --git a/app/models/user.rb b/app/models/user.rb index b0bd191d2..fb4cc50da 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -162,6 +162,10 @@ class User < ApplicationRecord has_many :teacher_group_records, dependent: :destroy + # 视频观看记录 + has_many :watch_video_histories, dependent: :destroy + has_many :watch_course_video, dependent: :destroy + # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } diff --git a/app/models/watch_course_video.rb b/app/models/watch_course_video.rb new file mode 100644 index 000000000..cf2d67028 --- /dev/null +++ b/app/models/watch_course_video.rb @@ -0,0 +1,9 @@ +class WatchCourseVideo < ApplicationRecord + belongs_to :course_video + belongs_to :user + + has_many :watch_video_histories + + + validates :course_video_id, uniqueness: {scope: :user_id} +end diff --git a/app/models/watch_video_history.rb b/app/models/watch_video_history.rb new file mode 100644 index 000000000..0f9ab4a8a --- /dev/null +++ b/app/models/watch_video_history.rb @@ -0,0 +1,5 @@ +class WatchVideoHistory < ApplicationRecord + belongs_to :user + belongs_to :video + belongs_to :watch_course_video, optional: true +end diff --git a/app/services/create_watch_video_service.rb b/app/services/create_watch_video_service.rb new file mode 100644 index 000000000..b16a65535 --- /dev/null +++ b/app/services/create_watch_video_service.rb @@ -0,0 +1,71 @@ +class CreateWatchVideoService < ApplicationService + attr_reader :user, :params, :request + + def initialize(user, request, params) + @user = user + @request = request + @params = params + end + + def call + ActiveRecord::Base.transaction do + current_time = Time.now + if params[:log_id].present? + # 更新观看时长 + watch_video_history = user.watch_video_histories.find(params[:log_id]) + + if watch_video_history.present? && watch_video_history.watch_duration < params[:watch_duration].to_f + # 如果观看时长少于原有的,说明拖放到前面重新观看了,不必再去记录 + watch_video_history.end_at = current_time + watch_video_history.watch_duration = params[:watch_duration] + watch_video_history.is_finished = (watch_video_history.duration <= params[:watch_duration].to_f) + watch_video_history.save! + + watch_course_video = watch_video_history.watch_course_video + + if watch_course_video.present? && !watch_course_video.is_finished && watch_course_video.watch_duration < params[:watch_duration].to_f + # 更新课程视频的时长及是否看完 + watch_course_video.watch_duration = params[:watch_duration] + watch_course_video.is_finished = (watch_course_video.duration <= params[:watch_duration].to_f) + watch_course_video.end_at = current_time + watch_course_video.save! + end + end + else + # 开始播放时记录一次 + if params[:course_id].present? + # 课堂视频 + course_video = CourseVideo.find_by(course_id: params[:course_id], video_id: params[:video_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] + end + + watch_video_history = build_video_log(current_time, course_video.video_id, watch_course_video.id) + watch_video_history.save! + + watch_course_video.save! unless watch_course_video.persisted? + else + # 非课堂视频 + video = Video.find_by(params[:video_id]) + watch_video_history = build_video_log(current_time, video.id) + watch_video_history.save! + end + end + watch_video_history + end + end + + + def build_video_log(current_time, video_id, watch_course_video_id) + WatchVideoHistory.new( + user_id: user.id, + watch_course_video_id: watch_course_video_id, + start_at: current_time, + duration: params[:duration], + video_id: video_id, + device: params[:device], + ip: request.remote_ip + ) + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index db9b74bd2..bcab93203 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,6 +29,8 @@ Rails.application.routes.draw do put 'commons/unhidden', to: 'commons#unhidden' delete 'commons/delete', to: 'commons#delete' + resources :watch_video_histories, only: [:create] + resources :jupyters do collection do get :save_with_tpi diff --git a/db/migrate/20200305072442_create_watch_course_videos.rb b/db/migrate/20200305072442_create_watch_course_videos.rb new file mode 100644 index 000000000..5695344fc --- /dev/null +++ b/db/migrate/20200305072442_create_watch_course_videos.rb @@ -0,0 +1,15 @@ +class CreateWatchCourseVideos < ActiveRecord::Migration[5.2] + def change + create_table :watch_course_videos do |t| + t.references :course_video, index: true + t.references :user, index: true + t.boolean :is_finished, default: false + t.float :duration, default: 0 + t.float :watch_duration, default: 0 + t.datetime :start_at + t.datetime :end_at + + t.timestamps + end + end +end diff --git a/db/migrate/20200305074638_create_watch_video_histories.rb b/db/migrate/20200305074638_create_watch_video_histories.rb new file mode 100644 index 000000000..ad9645a6a --- /dev/null +++ b/db/migrate/20200305074638_create_watch_video_histories.rb @@ -0,0 +1,18 @@ +class CreateWatchVideoHistories < ActiveRecord::Migration[5.2] + def change + create_table :watch_video_histories do |t| + t.references :watch_course_video, index: true + t.references :user, index: true + t.references :video, index: true + t.boolean :is_finished, default: false + t.float :duration, default: 0 + t.float :watch_duration, default: 0 + t.datetime :start_at + t.datetime :end_at + t.string :device + t.string :ip + + t.timestamps + end + end +end