From 81fdc31f8be26110e913268a9e604b443f58eaf3 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Wed, 12 Feb 2020 16:12:20 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/migrate/20200212072045_add_columns_to_live_links.rb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 db/migrate/20200212072045_add_columns_to_live_links.rb diff --git a/db/migrate/20200212072045_add_columns_to_live_links.rb b/db/migrate/20200212072045_add_columns_to_live_links.rb new file mode 100644 index 000000000..e0c59dcfa --- /dev/null +++ b/db/migrate/20200212072045_add_columns_to_live_links.rb @@ -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 From e69e8902a7cb7a42cfd76fe512a5fd630478ce57 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 13 Feb 2020 12:06:05 +0800 Subject: [PATCH 02/23] 1 --- public/favicon.ico | Bin 67646 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 public/favicon.ico diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100755 index 9c65fe8c7b77e9399a75f48500339c9bf2f74cb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67646 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 Date: Thu, 13 Feb 2020 12:07:17 +0800 Subject: [PATCH 03/23] 1 --- public/favicon.ico | Bin 0 -> 67646 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 public/favicon.ico diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..9c65fe8c7b77e9399a75f48500339c9bf2f74cb4 GIT binary patch literal 67646 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 Date: Thu, 13 Feb 2020 12:36:39 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/live_links_controller.rb | 13 +++++++------ app/decorators/tiding_decorator.rb | 2 +- app/models/live_link.rb | 19 ++++++++++++++++++- app/views/live_links/edit.json.jbuilder | 2 +- app/views/live_links/index.json.jbuilder | 5 +++-- config/locales/tidings/zh-CN.yml | 2 +- config/locales/zh-CN.yml | 5 ++++- lib/tasks/live_notice.rake | 13 +++++++++++++ 8 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 lib/tasks/live_notice.rake diff --git a/app/controllers/live_links_controller.rb b/app/controllers/live_links_controller.rb index fe2de4afe..f5af80ead 100644 --- a/app/controllers/live_links_controller.rb +++ b/app/controllers/live_links_controller.rb @@ -7,17 +7,17 @@ class LiveLinksController < ApplicationController def index lives = @course.live_links - order_str = "on_status desc,id desc" + order_str = "on_status desc, live_time desc" @total_count = lives.size @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 = paginate lives.includes(user: :user_extension) end def create - tip_exception("一个老师只能设置一个直播间") if @course.live_links.where(user_id: current_user.id).exists? - @course.live_links.create!(create_params.merge(user_id: current_user.id)) + 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, on_status: on_status)) render_ok end @@ -38,7 +38,8 @@ class LiveLinksController < ApplicationController end end 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 render_ok end @@ -51,7 +52,7 @@ class LiveLinksController < ApplicationController private def create_params - params.permit(:url, :description) + params.permit(:url, :description, :course_name, :platform, :live_time, :duration) end def current_live diff --git a/app/decorators/tiding_decorator.rb b/app/decorators/tiding_decorator.rb index 771df3aa2..8d266b7df 100644 --- a/app/decorators/tiding_decorator.rb +++ b/app/decorators/tiding_decorator.rb @@ -322,7 +322,7 @@ module TidingDecorator end def live_link_content - I18n.t(locale_format) % container&.user.try(:show_real_name) + I18n.t(locale_format) % container&.course_name end def student_graduation_topic_content diff --git a/app/models/live_link.rb b/app/models/live_link.rb index 52c1e3657..27963a0bb 100644 --- a/app/models/live_link.rb +++ b/app/models/live_link.rb @@ -4,8 +4,25 @@ class LiveLink < ApplicationRecord 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 :course_name, presence: true + validates :platform, presence: true, inclusion: {in: %W(tencent douyu bilibili vbt)} + # validates :live_time, presence: true + validates :duration, numericality: { only_integer: true, greater_than: 0}, allow_blank: true + + def platform_name + case platform + when "tencent" + "腾讯课堂" + when "douyu" + "斗鱼直播" + when "vbt" + "威佰通" + else + platform + end + end def op_auth? user == User.current || User.current.admin_or_business? diff --git a/app/views/live_links/edit.json.jbuilder b/app/views/live_links/edit.json.jbuilder index 047a226e8..6b0fd385d 100644 --- a/app/views/live_links/edit.json.jbuilder +++ b/app/views/live_links/edit.json.jbuilder @@ -1 +1 @@ -json.(@live, :id, :description, :url) +json.(@live, :id, :description, :url, :platform, :live_time, :duration, :course_name) diff --git a/app/views/live_links/index.json.jbuilder b/app/views/live_links/index.json.jbuilder index e497a068b..419fb49bb 100644 --- a/app/views/live_links/index.json.jbuilder +++ b/app/views/live_links/index.json.jbuilder @@ -1,12 +1,13 @@ json.lives @lives do |live| - json.(live, :id, :description, :on_status) + json.(live, :id, :description, :on_status, :duration, :course_name) json.url live.on_status ? live.url : "" json.author_name live.user.show_real_name json.author_login live.user.login json.author_img url_to_avatar(live.user) json.op_auth live.op_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') + json.platform live.platform_name end json.my_live_id @my_live_id json.total_count @total_count \ No newline at end of file diff --git a/config/locales/tidings/zh-CN.yml b/config/locales/tidings/zh-CN.yml index 92c815a05..cda146780 100644 --- a/config/locales/tidings/zh-CN.yml +++ b/config/locales/tidings/zh-CN.yml @@ -238,4 +238,4 @@ 2_end: "你提交的发布视频申请:%s,审核未通过
原因:%{reason}" PublicCourseStart_end: "你报名参与的开放课程:%s,将于%s正式开课" SubjectStartCourse_end: "您创建的开放课程:%s 已达到开课人数要求。您可以在24小时内自主开设新一期课程。如果超过24小时未开课,平台将自动开课并复制您上一期的课程内容。" - LiveLink_end: "%s老师正在直播中" + LiveLink_end: "%s 直播将于30分钟后开始" diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 6900f6c51..4f41df0c5 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -173,7 +173,10 @@ zh-CN: live_link: description: '说明' url: '链接' - + course_name: '课程名称' + platform: '直播平台' + live_time: '开播时间' + duration: '直播时长' diff --git a/lib/tasks/live_notice.rake b/lib/tasks/live_notice.rake new file mode 100644 index 000000000..da57ebd4b --- /dev/null +++ b/lib/tasks/live_notice.rake @@ -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 \ No newline at end of file From c81391e8db0ef5c328f3c8b80e16714729ad407c Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 13 Feb 2020 12:53:59 +0800 Subject: [PATCH 05/23] =?UTF-8?q?=E6=99=AE=E9=80=9A=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/homework_commons/index.json.jbuilder | 5 ++++- app/views/homework_commons/works_list.json.jbuilder | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/homework_commons/index.json.jbuilder b/app/views/homework_commons/index.json.jbuilder index db3603746..a508659e8 100644 --- a/app/views/homework_commons/index.json.jbuilder +++ b/app/views/homework_commons/index.json.jbuilder @@ -17,7 +17,10 @@ json.homeworks @homework_commons.each do |homework| json.status_time curr_status[:time] json.time_status curr_status[:time_status] json.allow_late homework.allow_late - json.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] diff --git a/app/views/homework_commons/works_list.json.jbuilder b/app/views/homework_commons/works_list.json.jbuilder index f5e6ca01a..cd2f17cf5 100644 --- a/app/views/homework_commons/works_list.json.jbuilder +++ b/app/views/homework_commons/works_list.json.jbuilder @@ -84,6 +84,7 @@ elsif @user_course_identity == Course::STUDENT json.user_login @work.user.login json.student_id @work.user.student_id json.user_name @work.user.real_name + json.user_img url_to_avatar(@work.user) json.group_name @member.course_group_name end @@ -108,6 +109,7 @@ if @homework.homework_type == "practice" json.view_answer_count work.myshixun.try(:view_answer_count).to_i json.user_login work.user.try(:login) 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.group_name @students.select{|student| student.user_id == work.user_id}.first.try(:course_group_name) 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_name @is_evaluation ? "匿名" : work.user.try(:real_name) + json.user_img url_to_avatar(@is_evaluation ? "0" : work.user) end end From ae062a49739a9dbf65d6da5662a96aba93cf865a Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 13 Feb 2020 13:08:51 +0800 Subject: [PATCH 06/23] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E7=9A=84=E8=A7=86=E9=A2=91=E5=BC=84=E5=9C=A8=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/videos/batch_publish_service.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/services/videos/batch_publish_service.rb b/app/services/videos/batch_publish_service.rb index ce6bdb163..0523097a2 100644 --- a/app/services/videos/batch_publish_service.rb +++ b/app/services/videos/batch_publish_service.rb @@ -25,7 +25,9 @@ class Videos::BatchPublishService < ApplicationService video.title = param[:title].to_s.strip.presence || video.title video.apply_publish - + if param[:course_id].present? + video.status = "published" + end video.save! if param[:course_id].present? From 6d69031da936cefba92acb0e30bcc55514745fb0 Mon Sep 17 00:00:00 2001 From: caicai8 <1149225589@qq.com> Date: Thu, 13 Feb 2020 14:03:12 +0800 Subject: [PATCH 07/23] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/courses/Video/LiveItem.js | 37 ++--- .../src/modules/courses/Video/LiveNew.js | 141 +++++++++++++++--- .../src/modules/courses/Video/VideoIndex.js | 13 +- .../react/src/modules/courses/Video/video.css | 25 +++- .../shixunHomework/ShixunhomeWorkItem.js | 6 +- 5 files changed, 164 insertions(+), 58 deletions(-) diff --git a/public/react/src/modules/courses/Video/LiveItem.js b/public/react/src/modules/courses/Video/LiveItem.js index a2fff5b98..0bee79fe2 100644 --- a/public/react/src/modules/courses/Video/LiveItem.js +++ b/public/react/src/modules/courses/Video/LiveItem.js @@ -1,25 +1,12 @@ import React,{ Component } from "react"; -import { Switch } from 'antd'; import { getImageUrl } from 'educoder'; import { WordsBtn } from 'educoder'; +import moment from 'moment'; import axios from 'axios'; class LiveItem extends Component{ - changeStatus=(flag,event,id)=>{ - const url = `/live_links/${id}.json`; - axios.put(url,{ - 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)=>{ this.props.confirm({ content: '是否确认删除?', @@ -44,20 +31,13 @@ class LiveItem extends Component{ } render(){ const { key, item , setLiveId } = this.props; - // let flag = false; - // flag = item.on_status; return(
- {`${item.author_name}`} - + {item.course_name} {item.on_status?'已开播':'未开播'} - { - item.op_auth ? - this.changeStatus(flag,event,item.id)}>:"" - }
@@ -71,8 +51,13 @@ class LiveItem extends Component{ }

- 创建时间:{item.created_at} - + + {`${item.author_name}`} + + { item.platform && 直播平台:{item.platform} } + { item.live_time && 开播时间:{item.live_time}} + { item.duration && 直播时长:{item.duration} } + { item.op_auth ? @@ -80,7 +65,7 @@ class LiveItem extends Component{ } { item.delete_auth ? - this.deleteLive(item.id)}>删除 + this.deleteLive(item.id)}>删除 :"" } diff --git a/public/react/src/modules/courses/Video/LiveNew.js b/public/react/src/modules/courses/Video/LiveNew.js index 2cd23f049..d505f052d 100644 --- a/public/react/src/modules/courses/Video/LiveNew.js +++ b/public/react/src/modules/courses/Video/LiveNew.js @@ -1,20 +1,50 @@ import React,{ Component } from "react"; -import { Modal , Form , Input , Spin } from 'antd'; +import { Modal , Form , Input , Spin , Select , 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 axios from 'axios'; + const { TextArea } = Input; +const { Option } = Select; + +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{ constructor(props){ super(props); this.state={ - isSpining:false + isSpining:false, + beginTime:undefined, + beginTimeFlag:false, } } + componentDidMount=()=>{ + console.log("1",this.props.liveId) + this.checkType(); + } + componentDidUpdate=(prevState)=>{ + console.log("2",prevState.liveId); if(prevState && prevState.liveId !== this.props.liveId){ this.setState({ isSpining:true @@ -25,7 +55,8 @@ class LiveNew extends Component{ checkType=()=>{ const { liveId } = this.props; - + console.log("3",this.props.liveId); + this.clearAll(); if(liveId){ const url =`/live_links/${liveId}/edit.json`; axios.get(url).then(result=>{ @@ -33,14 +64,15 @@ class LiveNew extends Component{ this.props.form.setFieldsValue({ url:result.data.url, description:result.data.description, + platform:result.data.platform || "tencent", + 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({ isSpining:false @@ -50,7 +82,13 @@ class LiveNew extends Component{ handleSubmit=()=>{ this.props.form.validateFields((err, values) => { if(!err){ - console.log("2") + const { beginTime } = this.state; + if(!beginTime){ + this.setState({ + beginTimeFlag:true + }) + return; + } const { liveId } = this.props; if(liveId){ // 修改 @@ -64,8 +102,10 @@ class LiveNew extends Component{ // 修改 updateFunc=(id,values)=>{ const url = `/live_links/${id}.json`; + const { beginTime } = this.state; axios.put(url,{ - ...values + ...values, + live_time:beginTime }).then(result=>{ if(result){ this.props.showNotification("修改成功!"); @@ -81,8 +121,10 @@ class LiveNew extends Component{ creatFunc=(values)=>{ const CourseId=this.props.match.params.coursesId; const url = `/courses/${CourseId}/live_links.json`; + const { beginTime } = this.state; axios.post(url,{ - ...values + ...values, + live_time:beginTime }).then(result=>{ if(result){ this.props.showNotification("添加成功!"); @@ -107,15 +149,31 @@ class LiveNew extends Component{ cancelNew=()=>{ const { setliveVisibel } = this.props; + this.clearAll(); + setliveVisibel && setliveVisibel(false); + } + + clearAll=()=>{ this.props.form.setFieldsValue({ + course_name:undefined, + platform:"tencent", url:undefined, - description:undefined + description:undefined, + duration:undefined + }) + this.setState({ + beginTime:undefined + }) + } + + onChangeTime=(data,dateString)=>{ + this.setState({ + beginTime:handleDateString(dateString) }) - setliveVisibel && setliveVisibel(false); } render(){ - const { isSpining } = this.state; + const { isSpining , beginTime , beginTimeFlag } = this.state; const {getFieldDecorator} = this.props.form; const { visible } = this.props; @@ -131,6 +189,24 @@ class LiveNew extends Component{

+ + {getFieldDecorator('course_name', { + rules: [{required: true, message: "请输入课程名字"}], + })( + + )} + + + {getFieldDecorator('platform', { + rules: [{required: true, message: "请选择直播平台"}], + })( + + )} + {getFieldDecorator('url', { rules: [{required: true, message: "请输入第三方直播链接"}], @@ -138,6 +214,38 @@ class LiveNew extends Component{ )} +
+
+

*开播时间

+ +

+ { + beginTimeFlag && 请选择开播时间 + } +

+
+ + {getFieldDecorator('duration', { + rules: [], + })( + + )} + + 分钟 +
{getFieldDecorator('description', { rules: [{ @@ -147,10 +255,7 @@ class LiveNew extends Component{