Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mr-julyedu
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
baiguangyao
mr-julyedu
Commits
4ec71ac5
Commit
4ec71ac5
authored
Mar 06, 2020
by
zhanghaozhe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
限时免费
parent
65adf51c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
924 additions
and
802 deletions
+924
-802
src/components/video/index.js
+824
-801
src/components/video/video.scss
+100
-1
No files found.
src/components/video/index.js
View file @
4ec71ac5
import
React
,
{
Component
}
from
'react'
import
HeaderBar
from
'@/common/HeaderBar'
import
'./video.scss'
import
{
NavLink
,
Route
,
Redirect
,
Switch
,
Link
}
from
'react-router-dom'
import
{
NavLink
,
Route
,
Redirect
,
Switch
}
from
'react-router-dom'
import
{
http
,
getParam
,
browser
}
from
'@/utils'
import
Recommendation
from
'./recommendation'
import
VideoCatalog
from
'./video-catalog'
...
...
@@ -9,8 +9,8 @@ import DatumCatalog from './datum-catalog'
import
{
Toast
}
from
'antd-mobile'
import
videojs
from
'video.js'
import
'video.js/dist/video-js.min.css'
import
{
Modal
}
from
"antd-mobile"
import
{
Loading
,
Popup
}
from
'@/common'
import
{
Modal
}
from
"antd-mobile"
import
{
Loading
}
from
'@/common'
import
{
connect
}
from
"react-redux"
import
jsCookie
from
'js-cookie'
import
Single
from
"@/components/detail/single"
;
...
...
@@ -21,873 +21,896 @@ import './CustomPlayButton'
let
alert
=
Modal
.
alert
function
ProgressShareModal
(
props
)
{
return
(
props
.
isShow
&&
<
div
className
=
'progress-share-modal-wrapper'
>
<
div
className
=
"progress-share-modal"
>
<
div
className
=
"title"
>
每日打卡
<
/div
>
<
ul
className
=
"progress-container"
>
<
li
>
<
div
className
=
"title"
>
累计学习
<
/div
>
<
div
className
=
"number"
><
span
className
=
'num'
>
{
props
.
data
.
learn_day_count
}
<
/span>天</
div
>
<
/li
>
<
li
>
<
div
className
=
"title"
>
行动力超过
<
/div
>
<
div
className
=
"number"
><
span
className
=
'num'
>
{
parseFloat
(
props
.
data
.
action_power
)}
<
/span>
%
<
/div
>
<
/li
>
<
/ul
>
<
div
className
=
"share-container"
>
<
div
className
=
"title"
>
分享到
<
/div
>
<
ul
>
<
li
className
=
'share-icon'
>
<
a
style
=
{{
display
:
'block'
}}
href
=
{
props
.
data
.
url
}
>
<
div
className
=
"icon"
><
i
className
=
'iconfont iconweixinzhifu'
/><
/div
>
<
div
className
=
'text'
>
微信好友
<
/div
>
<
/a
>
<
/li
>
<
li
className
=
'share-icon'
>
<
a
style
=
{{
display
:
'block'
}}
href
=
{
props
.
data
.
url
}
>
<
div
className
=
"icon"
><
i
className
=
'iconfont iconpengyouquaniconx'
/><
/div
>
<
div
className
=
'text'
>
朋友圈
<
/div
>
<
/a
>
<
/li
>
<
/ul
>
<
/div
>
<
i
className
=
"iconfont iconiconfront-2 close"
onClick
=
{
props
.
closeShareModal
}
/
>
return
(
props
.
isShow
&&
<
div
className
=
'progress-share-modal-wrapper'
>
<
div
className
=
"progress-share-modal"
>
<
div
className
=
"title"
>
每日打卡
<
/div
>
<
ul
className
=
"progress-container"
>
<
li
>
<
div
className
=
"title"
>
累计学习
<
/div
>
<
div
className
=
"number"
><
span
className
=
'num'
>
{
props
.
data
.
learn_day_count
}
<
/span>天</
div
>
<
/li
>
<
li
>
<
div
className
=
"title"
>
行动力超过
<
/div
>
<
div
className
=
"number"
><
span
className
=
'num'
>
{
parseFloat
(
props
.
data
.
action_power
)}
<
/span>
%
<
/div
>
<
/li
>
<
/ul
>
<
div
className
=
"share-container"
>
<
div
className
=
"title"
>
分享到
<
/div
>
<
ul
>
<
li
className
=
'share-icon'
>
<
a
style
=
{{
display
:
'block'
}}
href
=
{
props
.
data
.
url
}
>
<
div
className
=
"icon"
><
i
className
=
'iconfont iconweixinzhifu'
/><
/div
>
<
div
className
=
'text'
>
微信好友
<
/div
>
<
/a
>
<
/li
>
<
li
className
=
'share-icon'
>
<
a
style
=
{{
display
:
'block'
}}
href
=
{
props
.
data
.
url
}
>
<
div
className
=
"icon"
><
i
className
=
'iconfont iconpengyouquaniconx'
/><
/div
>
<
div
className
=
'text'
>
朋友圈
<
/div
>
<
/a
>
<
/li
>
<
/ul
>
<
/div
>
)
<
i
className
=
"iconfont iconiconfront-2 close"
onClick
=
{
props
.
closeShareModal
}
/
>
<
/div
>
<
/div
>
)
}
class
Video
extends
Component
{
video
//video element
player
//video player instance
courseID
ws
//websocket instance
timer
token
count
watchSec
previousPlaybackRate
=
1
currentPlaybackRate
=
1
reconnect
=
true
// timeEnough = false
recordSocket
recordTimer
isCurrentVideoFirstPlay
=
true
RECENTLEARN
=
"recent_learn"
state
=
{
title
:
''
,
courseId
:
null
,
videoList
:
[],
datum
:
[],
currentVideoSrc
:
''
,
activeIndex
:
0
,
isAuth
:
true
,
course
:
{},
// course.course_id 为 0 或 '' 时 为免费课程
salePrice
:
null
,
vCourseId
:
null
,
isLoading
:
true
,
isShowShareModal
:
false
,
shareData
:
{},
singleBox
:
false
,
singMess
:
''
,
singleType
:
1
,
// 单集购买需要
nowPrice
:
0
,
// 单集购买需要
laterPrice
:
0
,
// 单集购买需要
video
//video element
player
//video player instance
courseID
ws
//websocket instance
timer
token
count
watchSec
previousPlaybackRate
=
1
currentPlaybackRate
=
1
reconnect
=
true
// timeEnough = false
recordSocket
recordTimer
isCurrentVideoFirstPlay
=
true
RECENTLEARN
=
"recent_learn"
state
=
{
title
:
''
,
courseId
:
null
,
videoList
:
[],
datum
:
[],
currentVideoSrc
:
''
,
activeIndex
:
0
,
isAuth
:
true
,
course
:
{},
// course.course_id 为 0 或 '' 时 为免费课程
salePrice
:
null
,
vCourseId
:
null
,
isLoading
:
true
,
isShowShareModal
:
false
,
shareData
:
{},
singleBox
:
false
,
singMess
:
''
,
singleType
:
1
,
// 单集购买需要
nowPrice
:
0
,
// 单集购买需要
laterPrice
:
0
,
// 单集购买需要
limitFreeNoPromptChecked
:
false
,
showLimitFreePopup
:
true
//todo 联调
}
componentDidMount
()
{
if
(
window
.
location
.
protocol
===
'https:'
)
{
window
.
location
.
replace
(
'http'
+
window
.
location
.
href
.
slice
(
5
))
return
}
componentDidMount
()
{
if
(
window
.
location
.
protocol
===
'https:'
)
{
window
.
location
.
replace
(
'http'
+
window
.
location
.
href
.
slice
(
5
))
return
}
this
.
courseID
=
getParam
(
'id'
)
if
(
!
this
.
courseID
)
{
this
.
props
.
history
.
replace
(
'/'
)
return
}
this
.
setState
({
courseId
:
this
.
courseID
})
const
{
location
,
location
:
{
state
=
{}}}
=
this
.
props
;
if
(
state
.
oid
)
{
this
.
check
(
state
.
oid
);
}
if
(
getParam
(
'is_class'
)
===
1
||
getParam
(
'weixinpay'
))
{
this
.
payCallback
()
}
if
(
browser
.
isWeixin
)
{
this
.
isweixinPay
()
}
this
.
token
=
jsCookie
.
get
(
'token'
)
this
.
getVideoList
()
this
.
getDatumCatalog
()
this
.
showLimitFreePopup
({
title
:
'想领取【AI工程师必备干货礼包】? 想深入了解进阶课程? 职业前景不明朗? 资深规划师免费为你服务!'
,
})
this
.
courseID
=
getParam
(
'id'
)
if
(
!
this
.
courseID
)
{
this
.
props
.
history
.
replace
(
'/'
)
return
}
// 直接购买
tobuy
=
()
=>
{
// 详情页单集购买到该页面,url中的id不是课程id
const
{
course
=
{}}
=
this
.
state
;
http
.
get
(
`
${
API
[
'base-api'
]}
/m/cart/addtopreorder/[
${
course
.
course_id
}
]`
).
then
((
res
)
=>
{
if
(
res
.
data
.
errno
===
0
)
{
this
.
props
.
history
.
push
(
`/order?id=
${
course
.
course_id
}
`
,
{
simple
:
1
})
}
else
{
Toast
.
info
(
res
.
data
.
msg
,
2
);
}
})
this
.
setState
({
courseId
:
this
.
courseID
})
const
{
location
,
location
:
{
state
=
{}}}
=
this
.
props
;
if
(
state
.
oid
)
{
this
.
check
(
state
.
oid
);
}
// 购买单集
toSingleset
=
(
item
)
=>
{
// console.log(item);
this
.
setState
({
singleBox
:
true
,
singleType
:
1
,
singMess
:
item
})
window
.
localStorage
.
setItem
(
'singMess'
,
JSON
.
stringify
(
item
))
if
(
getParam
(
'is_class'
)
===
1
||
getParam
(
'weixinpay'
))
{
this
.
payCallback
()
}
// 自组件传给父组件的boxHide
boxHide
=
(
val
)
=>
{
this
.
setState
({
singleBox
:
val
,
singleType
:
1
})
if
(
browser
.
isWeixin
)
{
this
.
isweixinPay
()
}
// 单集购买 H5支付成功后回调
payCallback
=
()
=>
{
const
_this
=
this
;
if
(
!
getParam
(
'oid'
))
{
return
;
}
else
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
_this
.
intervalPayStatus
=
setInterval
(
function
()
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/orderState/oid/
${
getParam
(
'oid'
)}
`
).
then
(
res
=>
{
if
(
res
.
data
.
errno
===
401
)
{
clearInterval
(
_this
.
intervalPayStatus
);
_this
.
intervalPayStatus
=
null
;
// 获取课程类型
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
getParam
(
'oid'
)}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
// 正常购买单集成功
_this
.
setState
({
singleType
:
6
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
// 0元参团
_this
.
setState
({
singleType
:
4
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
// 0元购
_this
.
setState
({
singleType
:
3
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
// 三天内特价
_this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
})
}
else
{
Toast
.
info
(
res
.
data
.
data
.
msg
,
2
)
}
})
}
})
},
1000
)
}
};
// 单集购买 微信内支付成功后回调
isweixinPay
=
()
=>
{
let
_this
=
this
;
let
weixin_code
=
getParam
(
'code'
);
if
(
weixin_code
)
{
if
(
!
getParam
(
'oid'
))
{
return
}
else
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
// this.props.weixinPay(weixin_code)
http
.
get
(
`
${
API
[
'base-api'
]}
/pay/wxpay/pub_charge/oid/
${
getParam
(
'oid'
)}
/code/
${
weixin_code
}
`
).
then
((
res
)
=>
{
if
(
res
.
data
.
errno
===
0
)
{
const
data
=
res
.
data
.
data
;
function
onBridgeReady
()
{
WeixinJSBridge
.
invoke
(
'getBrandWCPayRequest'
,
{
"appId"
:
data
.
appId
,
//公众号名称,由商户传入
"timeStamp"
:
data
.
timeStamp
,
//时间戳,自1970年以来的秒数
"nonceStr"
:
data
.
nonceStr
,
//随机串
"package"
:
data
.
package
,
"signType"
:
data
.
signType
,
//微信签名方式:
"paySign"
:
data
.
paySign
//微信签名
},
function
(
res
)
{
if
(
res
.
err_msg
==
"get_brand_wcpay_request:ok"
)
{
Toast
.
info
(
'支付成功'
,
2
);
_this
.
intervalPayStatus
=
setInterval
(
function
()
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/orderState/oid/
${
getParam
(
'oid'
)}
`
).
then
(
res
=>
{
if
(
res
.
data
.
errno
===
401
)
{
clearInterval
(
_this
.
intervalPayStatus
);
_this
.
intervalPayStatus
=
null
;
// 获取课程类型
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
getParam
(
'oid'
)}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
// 正常购买单集成功
_this
.
setState
({
singleType
:
6
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
// 0元参团
_this
.
setState
({
singleType
:
4
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
// 0元购
_this
.
setState
({
singleType
:
3
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
// 三天内特价
_this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
})
}
else
{
Toast
.
info
(
res
.
data
.
data
.
msg
,
2
)
}
})
}
})
},
1000
)
}
else
{
alert
(
'支付失败'
)
}
}
)
}
if
(
typeof
WeixinJSBridge
==
"undefined"
)
{
if
(
document
.
addEventListener
)
{
document
.
addEventListener
(
'WeixinJSBridgeReady'
,
onBridgeReady
,
false
)
}
else
if
(
document
.
attachEvent
)
{
document
.
attachEvent
(
'WeixinJSBridgeReady'
,
onBridgeReady
)
document
.
attachEvent
(
'onWeixinJSBridgeReady'
,
onBridgeReady
)
}
}
else
{
onBridgeReady
()
}
}
else
{
Toast
.
info
(
res
.
data
.
msg
,
2
)
}
})
}
}
};
// 判断支付是否成功
check
=
(
oid
)
=>
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
oid
}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
this
.
token
=
jsCookie
.
get
(
'token'
)
this
.
getVideoList
()
this
.
getDatumCatalog
()
}
// 直接购买
tobuy
=
()
=>
{
// 详情页单集购买到该页面,url中的id不是课程id
const
{
course
=
{}}
=
this
.
state
;
http
.
get
(
`
${
API
[
'base-api'
]}
/m/cart/addtopreorder/[
${
course
.
course_id
}
]`
).
then
((
res
)
=>
{
if
(
res
.
data
.
errno
===
0
)
{
this
.
props
.
history
.
push
(
`/order?id=
${
course
.
course_id
}
`
,
{
simple
:
1
})
}
else
{
Toast
.
info
(
res
.
data
.
msg
,
2
);
}
})
}
// 购买单集
toSingleset
=
(
item
)
=>
{
// console.log(item);
this
.
setState
({
singleBox
:
true
,
singleType
:
1
,
singMess
:
item
})
window
.
localStorage
.
setItem
(
'singMess'
,
JSON
.
stringify
(
item
))
}
// 自组件传给父组件的boxHide
boxHide
=
(
val
)
=>
{
this
.
setState
({
singleBox
:
val
,
singleType
:
1
})
}
// 单集购买 H5支付成功后回调
payCallback
=
()
=>
{
const
_this
=
this
;
if
(
!
getParam
(
'oid'
))
{
return
;
}
else
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
_this
.
intervalPayStatus
=
setInterval
(
function
()
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/orderState/oid/
${
getParam
(
'oid'
)}
`
).
then
(
res
=>
{
if
(
res
.
data
.
errno
===
401
)
{
clearInterval
(
_this
.
intervalPayStatus
);
_this
.
intervalPayStatus
=
null
;
// 获取课程类型
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
getParam
(
'oid'
)}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
// 正常购买单集成功
this
.
setState
({
singleType
:
6
,
_this
.
setState
({
singleType
:
6
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
// 0元参团
this
.
setState
({
singleType
:
4
,
_this
.
setState
({
singleType
:
4
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
// 0元购
this
.
setState
({
singleType
:
3
,
_this
.
setState
({
singleType
:
3
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
// 三天内特价
this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
_this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
})
}
else
{
}
else
{
Toast
.
info
(
res
.
data
.
data
.
msg
,
2
)
}
}
})
}
})
},
1000
)
}
// 9502 初始化 监听事件
setupWS
=
()
=>
{
this
.
ws
=
new
WebSocket
(
API
[
"process-api"
]);
this
.
ws
.
addEventListener
(
'error'
,
()
=>
{
this
.
ws
=
null
})
this
.
ws
.
addEventListener
(
'close'
,
()
=>
{
if
(
this
.
reconnect
)
{
this
.
ws
=
null
setTimeout
(()
=>
{
this
.
setupWS
();
},
1000
)
}
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
};
// 单集购买 微信内支付成功后回调
isweixinPay
=
()
=>
{
let
_this
=
this
;
let
weixin_code
=
getParam
(
'code'
);
if
(
weixin_code
)
{
if
(
!
getParam
(
'oid'
))
{
return
}
else
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
this
.
ws
.
addEventListener
(
'message'
,
e
=>
{
const
data
=
JSON
.
parse
(
e
.
data
);
data
.
code
==
4040
&&
(
this
.
reconnect
=
false
);
if
(
data
.
code
===
0
)
{
console
.
log
(
"上次的学习记录"
+
JSON
.
stringify
(
data
));
if
(
data
.
data
&&
data
.
data
.
position
)
{
this
.
player
.
currentTime
(
data
.
data
.
position
);
// this.props.weixinPay(weixin_code)
http
.
get
(
`
${
API
[
'base-api'
]}
/pay/wxpay/pub_charge/oid/
${
getParam
(
'oid'
)}
/code/
${
weixin_code
}
`
).
then
((
res
)
=>
{
if
(
res
.
data
.
errno
===
0
)
{
const
data
=
res
.
data
.
data
;
function
onBridgeReady
()
{
WeixinJSBridge
.
invoke
(
'getBrandWCPayRequest'
,
{
"appId"
:
data
.
appId
,
//公众号名称,由商户传入
"timeStamp"
:
data
.
timeStamp
,
//时间戳,自1970年以来的秒数
"nonceStr"
:
data
.
nonceStr
,
//随机串
"package"
:
data
.
package
,
"signType"
:
data
.
signType
,
//微信签名方式:
"paySign"
:
data
.
paySign
//微信签名
},
function
(
res
)
{
if
(
res
.
err_msg
==
"get_brand_wcpay_request:ok"
)
{
Toast
.
info
(
'支付成功'
,
2
);
_this
.
intervalPayStatus
=
setInterval
(
function
()
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/orderState/oid/
${
getParam
(
'oid'
)}
`
).
then
(
res
=>
{
if
(
res
.
data
.
errno
===
401
)
{
clearInterval
(
_this
.
intervalPayStatus
);
_this
.
intervalPayStatus
=
null
;
// 获取课程类型
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
getParam
(
'oid'
)}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
// 正常购买单集成功
_this
.
setState
({
singleType
:
6
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
// 0元参团
_this
.
setState
({
singleType
:
4
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
// 0元购
_this
.
setState
({
singleType
:
3
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
// 三天内特价
_this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
})
}
else
{
Toast
.
info
(
res
.
data
.
data
.
msg
,
2
)
}
})
}
})
},
1000
)
}
else
{
alert
(
'支付失败'
)
}
}
)
}
})
}
sendMessage
=
message
=>
{
let
readyState
=
this
.
ws
.
readyState
,
_this
=
this
;
if
(
readyState
===
1
)
{
this
.
ws
&&
this
.
ws
.
send
(
JSON
.
stringify
(
message
))
}
else
if
(
readyState
===
3
)
{
this
.
ws
.
close
();
this
.
ws
=
null
;
let
reconnect
=
setTimeout
(
function
()
{
clearTimeout
(
reconnect
);
reconnect
=
null
;
_this
.
ws
=
new
WebSocket
(
PROCESS_URL
);
},
500
);
}
if
(
typeof
WeixinJSBridge
==
"undefined"
)
{
if
(
document
.
addEventListener
)
{
document
.
addEventListener
(
'WeixinJSBridgeReady'
,
onBridgeReady
,
false
)
}
else
if
(
document
.
attachEvent
)
{
document
.
attachEvent
(
'WeixinJSBridgeReady'
,
onBridgeReady
)
document
.
attachEvent
(
'onWeixinJSBridgeReady'
,
onBridgeReady
)
}
}
else
{
onBridgeReady
()
}
}
else
{
Toast
.
info
(
res
.
data
.
msg
,
2
)
}
})
}
}
};
// 判断支付是否成功
check
=
(
oid
)
=>
{
this
.
setState
({
singMess
:
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'singMess'
))
})
http
.
get
(
`
${
API
[
'base-api'
]}
/class_order_status/
${
oid
}
`
).
then
((
res
)
=>
{
if
(
Number
(
res
.
data
.
data
.
errno
)
===
200
)
{
// 正常购买单集成功
this
.
setState
({
singleType
:
6
,
//视频结束请求接口
getShareProgressInfo
=
()
=>
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/aist/share_data/
${
this
.
courseID
}
/
${
this
.
state
.
videoList
[
this
.
state
.
activeIndex
][
'id'
]}
`
)
.
then
(
res
=>
{
const
{
data
}
=
res
if
(
data
.
errno
==
200
)
{
this
.
setState
({
shareData
:
data
.
data
,
isShowShareModal
:
true
})
}
})
}
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
201
)
{
// 0元参团
this
.
setState
({
singleType
:
4
,
//告诉服务端计算进度
countSchedule
=
()
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
if
(
Number
(
course
.
course_id
)
===
0
||
course
.
course_id
===
''
)
{
console
.
log
(
'免费课程 拦截'
);
return
;
}
let
ctype
=
0
;
if
(
course
.
is_aist
)
{
ctype
=
2
;
}
// 计算进度 根据ctype判断 课程类型 0-视频 1-直播 2-AI特训营
this
.
sendMessage
({
mtype
:
'count_schedule'
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
ctype
:
ctype
,
})
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
202
)
{
// 0元购
this
.
setState
({
singleType
:
3
,
}
// 发送时间消息
sendWatchTime
=
(
sec
,
rate
)
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
// 免费课程不发送
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// return;
// }
// 时间为0 不发送消息
if
(
Number
(
sec
)
===
0
)
{
return
;
}
let
ctype
=
0
;
if
(
course
.
is_aist
)
{
ctype
=
2
;
}
// 时间足够不发送
// if(this.timeEnough) {
// console.log('5001 时间足够');
// return;
// }
this
.
sendMessage
({
mtype
:
'watch_time'
,
rate
,
time
:
sec
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
position
:
parseInt
(
this
.
player
.
currentTime
()),
ctype
:
ctype
,
})
}
}
else
if
(
Number
(
res
.
data
.
data
.
errno
)
===
203
)
{
// 三天内特价
this
.
setState
({
nowPrice
:
res
.
data
.
data
.
data
.
now_price
,
laterPrice
:
res
.
data
.
data
.
data
.
three_day_later_price
,
singleType
:
2
,
setupTimer
=
()
=>
{
this
.
count
=
0
this
.
watchSec
=
0
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
this
.
timer
=
setInterval
(()
=>
{
if
(
this
.
player
&&
this
.
player
.
player
())
{
if
(
this
.
count
===
5
)
{
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
)
this
.
count
=
this
.
watchSec
=
0
}
else
{
!
this
.
player
.
paused
()
&&
this
.
watchSec
++
!
this
.
player
.
paused
()
&&
this
.
count
++
}
}
})
}
else
{
Toast
.
info
(
res
.
data
.
data
.
msg
,
2
)
}
})
}
// 9502 初始化 监听事件
setupWS
=
()
=>
{
this
.
ws
=
new
WebSocket
(
API
[
"process-api"
]);
this
.
ws
.
addEventListener
(
'error'
,
()
=>
{
this
.
ws
=
null
})
this
.
ws
.
addEventListener
(
'close'
,
()
=>
{
if
(
this
.
reconnect
)
{
this
.
ws
=
null
setTimeout
(()
=>
{
this
.
setupWS
();
},
1000
)
}
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
})
this
.
ws
.
addEventListener
(
'message'
,
e
=>
{
const
data
=
JSON
.
parse
(
e
.
data
);
data
.
code
==
4040
&&
(
this
.
reconnect
=
false
);
if
(
data
.
code
===
0
)
{
console
.
log
(
"上次的学习记录"
+
JSON
.
stringify
(
data
));
if
(
data
.
data
&&
data
.
data
.
position
)
{
this
.
player
.
currentTime
(
data
.
data
.
position
);
}
}
})
}
sendMessage
=
message
=>
{
let
readyState
=
this
.
ws
.
readyState
,
_this
=
this
;
if
(
readyState
===
1
)
{
this
.
ws
&&
this
.
ws
.
send
(
JSON
.
stringify
(
message
))
}
else
if
(
readyState
===
3
)
{
this
.
ws
.
close
();
this
.
ws
=
null
;
let
reconnect
=
setTimeout
(
function
()
{
clearTimeout
(
reconnect
);
reconnect
=
null
;
_this
.
ws
=
new
WebSocket
(
PROCESS_URL
);
},
500
);
}
// 初始化视频播放器
initializePlayer
=
()
=>
{
window
.
HELP_IMPROVE_VIDEOJS
=
false
;
this
.
player
=
videojs
(
this
.
video
,
{
controls
:
true
,
preload
:
'auto'
,
bigPlayButton
:
false
,
textTrackDisplay
:
false
,
posterImage
:
false
,
errorDisplay
:
false
,
playbackRates
:
[
'0.75'
,
'1'
,
'1.5'
,
'2'
],
controlBar
:
{
pictureInPictureToggle
:
false
}
})
this
.
player
.
addChild
(
'CustomPlayButtonCover'
)
this
.
player
.
on
(
'play'
,
()
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
// 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间)
if
(
this
.
isCurrentVideoFirstPlay
)
{
// 当某些原因导致视频暂停时(用户暂停 网络不好等) 再播放时不需要发送
this
.
isCurrentVideoFirstPlay
=
false
;
// 发送消息 recent_learn
this
.
ws
.
send
(
JSON
.
stringify
({
mtype
:
this
.
RECENTLEARN
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
is_live
:
0
,
}))
}
if
(
!
this
.
timer
)
{
this
.
setupTimer
();
}
})
this
.
player
.
on
(
'ratechange'
,
()
=>
{
this
.
currentPlaybackRate
=
this
.
player
.
playbackRate
()
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
previousPlaybackRate
)
this
.
count
=
this
.
watchSec
=
0
this
.
previousPlaybackRate
=
this
.
currentPlaybackRate
})
this
.
player
.
on
(
'ended'
,
()
=>
{
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
);
this
.
count
=
this
.
watchSec
=
0
;
this
.
countSchedule
();
// 计算进度 -- 播放完毕
// 返现课程才出现打卡记录
if
(
this
.
state
.
course
.
is_aist
)
{
this
.
getShareProgressInfo
()
}
clearInterval
(
this
.
timer
);
this
.
timer
=
null
;
})
}
//视频结束请求接口
getShareProgressInfo
=
()
=>
{
http
.
get
(
`
${
API
[
'base-api'
]}
/m/aist/share_data/
${
this
.
courseID
}
/
${
this
.
state
.
videoList
[
this
.
state
.
activeIndex
][
'id'
]}
`
)
.
then
(
res
=>
{
const
{
data
}
=
res
if
(
data
.
errno
==
200
)
{
this
.
setState
({
shareData
:
data
.
data
,
isShowShareModal
:
true
})
}
})
}
//告诉服务端计算进度
countSchedule
=
()
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
if
(
Number
(
course
.
course_id
)
===
0
||
course
.
course_id
===
''
)
{
console
.
log
(
'免费课程 拦截'
);
return
;
}
sendLastRecord
=
()
=>
{
http
.
post
(
`
${
API
.
home
}
/m/course/record_last_video`
,
{
v_course_id
:
this
.
state
.
course
[
'v_course_id'
],
video_id
:
this
.
state
.
videoList
[
this
.
state
.
activeIndex
].
id
})
let
ctype
=
0
;
if
(
course
.
is_aist
)
{
ctype
=
2
;
}
componentWillUnmount
()
{
this
.
player
&&
this
.
player
.
dispose
()
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
this
.
ws
&&
this
.
ws
.
close
()
this
.
ws
=
null
clearInterval
(
this
.
recordTimer
)
this
.
recordSocket
&&
this
.
recordSocket
.
close
()
this
.
recordSocket
=
null
// 计算进度 根据ctype判断 课程类型 0-视频 1-直播 2-AI特训营
this
.
sendMessage
({
mtype
:
'count_schedule'
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
ctype
:
ctype
,
})
}
// 发送时间消息
sendWatchTime
=
(
sec
,
rate
)
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
// 免费课程不发送
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// return;
// }
// 时间为0 不发送消息
if
(
Number
(
sec
)
===
0
)
{
return
;
}
// 选择新的视频
selectVideo
=
index
=>
{
if
(
index
===
this
.
state
.
activeIndex
)
{
return
let
ctype
=
0
;
if
(
course
.
is_aist
)
{
ctype
=
2
;
}
// 时间足够不发送
// if(this.timeEnough) {
// console.log('5001 时间足够');
// return;
// }
this
.
sendMessage
({
mtype
:
'watch_time'
,
rate
,
time
:
sec
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
position
:
parseInt
(
this
.
player
.
currentTime
()),
ctype
:
ctype
,
})
}
setupTimer
=
()
=>
{
this
.
count
=
0
this
.
watchSec
=
0
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
this
.
timer
=
setInterval
(()
=>
{
if
(
this
.
player
&&
this
.
player
.
player
())
{
if
(
this
.
count
===
5
)
{
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
)
this
.
count
=
this
.
watchSec
=
0
}
else
{
!
this
.
player
.
paused
()
&&
this
.
watchSec
++
!
this
.
player
.
paused
()
&&
this
.
count
++
}
console
.
log
(
'selectVideo 先发送时间 再发送进度 在重置定时器'
);
this
.
isCurrentVideoFirstPlay
=
true
;
// 切换视频则重置这个变量 因为新视频肯定是首次播放
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
)
this
.
countSchedule
();
// 计算进度 -- 选择新视频(可能是M端特有的)
}
},
1000
)
}
// 初始化视频播放器
initializePlayer
=
()
=>
{
window
.
HELP_IMPROVE_VIDEOJS
=
false
;
this
.
player
=
videojs
(
this
.
video
,
{
controls
:
true
,
preload
:
'auto'
,
bigPlayButton
:
false
,
textTrackDisplay
:
false
,
posterImage
:
false
,
errorDisplay
:
false
,
playbackRates
:
[
'0.75'
,
'1'
,
'1.5'
,
'2'
],
controlBar
:
{
pictureInPictureToggle
:
false
}
})
this
.
player
.
addChild
(
'CustomPlayButtonCover'
)
this
.
player
.
on
(
'play'
,
()
=>
{
const
{
videoList
,
activeIndex
,
vCourseId
,
course
=
{}}
=
this
.
state
// 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间)
if
(
this
.
isCurrentVideoFirstPlay
)
{
// 当某些原因导致视频暂停时(用户暂停 网络不好等) 再播放时不需要发送
this
.
isCurrentVideoFirstPlay
=
false
;
// 发送消息 recent_learn
this
.
ws
.
send
(
JSON
.
stringify
({
mtype
:
this
.
RECENTLEARN
,
uid
:
this
.
props
.
user
.
data
.
uid
,
token
:
this
.
token
,
platform
:
5
,
video_id
:
videoList
[
activeIndex
][
'id'
],
course_id
:
this
.
state
.
courseId
,
v_course_id
:
vCourseId
,
is_live
:
0
,
}))
}
if
(
!
this
.
timer
)
{
this
.
setupTimer
();
this
.
setState
(
{
activeIndex
:
index
},
()
=>
{
if
(
this
.
hasAuth
(
this
.
state
.
activeIndex
))
{
this
.
setPlayerSrc
(
this
.
state
.
videoList
[
index
][
'play_url'
])
this
.
sendLastRecord
()
this
.
playVideo
()
}
else
{
this
.
getCoursePrice
();
}
}
);
}
})
this
.
player
.
on
(
'ratechange'
,
()
=>
{
this
.
currentPlaybackRate
=
this
.
player
.
playbackRate
()
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
previousPlaybackRate
)
this
.
count
=
this
.
watchSec
=
0
this
.
previousPlaybackRate
=
this
.
currentPlaybackRate
})
this
.
player
.
on
(
'ended'
,
()
=>
{
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
);
this
.
count
=
this
.
watchSec
=
0
;
this
.
countSchedule
();
// 计算进度 -- 播放完毕
// 返现课程才出现打卡记录
if
(
this
.
state
.
course
.
is_aist
)
{
this
.
getShareProgressInfo
()
}
clearInterval
(
this
.
timer
);
this
.
timer
=
null
;
})
}
sendLastRecord
=
()
=>
{
http
.
post
(
`
${
API
.
home
}
/m/course/record_last_video`
,
{
v_course_id
:
this
.
state
.
course
[
'v_course_id'
],
video_id
:
this
.
state
.
videoList
[
this
.
state
.
activeIndex
].
id
})
}
componentWillUnmount
()
{
this
.
player
&&
this
.
player
.
dispose
()
clearInterval
(
this
.
timer
)
this
.
timer
=
null
;
this
.
ws
&&
this
.
ws
.
close
()
this
.
ws
=
null
clearInterval
(
this
.
recordTimer
)
this
.
recordSocket
&&
this
.
recordSocket
.
close
()
this
.
recordSocket
=
null
}
// 选择新的视频
selectVideo
=
index
=>
{
if
(
index
===
this
.
state
.
activeIndex
)
{
return
}
getLastVideoIndex
=
lastIndex
=>
{
return
this
.
state
.
videoList
.
findIndex
(
item
=>
item
.
id
==
lastIndex
)
}
getVideoList
=
()
=>
{
let
url
=
''
;
if
(
getParam
(
'video_id'
))
{
url
=
`
${
API
.
home
}
/m/course/play/
${
this
.
courseID
+
'?video_id='
+
getParam
(
'video_id'
)}
`
http
.
post
(
`
${
API
[
'base-api'
]}
/sys/get_class_audition`
,
{
video_id
:
getParam
(
'video_id'
)
})
console
.
log
(
'selectVideo 先发送时间 再发送进度 在重置定时器'
);
this
.
isCurrentVideoFirstPlay
=
true
;
// 切换视频则重置这个变量 因为新视频肯定是首次播放
this
.
sendWatchTime
(
this
.
watchSec
,
this
.
currentPlaybackRate
)
this
.
countSchedule
();
// 计算进度 -- 选择新视频(可能是M端特有的)
this
.
setupTimer
();
this
.
setState
(
{
activeIndex
:
index
},
()
=>
{
if
(
this
.
hasAuth
(
this
.
state
.
activeIndex
))
{
this
.
setPlayerSrc
(
this
.
state
.
videoList
[
index
][
'play_url'
])
this
.
sendLastRecord
()
this
.
playVideo
()
}
else
{
url
=
`
${
API
.
home
}
/m/course/play/
${
this
.
courseID
}
`
this
.
getCoursePrice
();
}
http
.
get
(
url
).
then
(
res
=>
{
const
{
data
=
{},
code
}
=
res
.
data
;
if
(
code
===
200
)
{
this
.
setState
(
state
=>
({
videoList
:
data
[
'lessons'
],
currentVideoSrc
:
data
[
'lessons'
][
state
.
activeIndex
][
'play_url'
],
course
:
data
.
course
,
courseId
:
data
.
course
[
'course_id'
],
vCourseId
:
data
.
course
[
'v_course_id'
],
title
:
data
.
course
[
'course_title'
],
isLoading
:
false
}),
this
.
playSetup
)
}
else
{
Toast
.
info
(
data
.
msg
)
}
}
)
}
);
}
getLastVideoIndex
=
lastIndex
=>
{
return
this
.
state
.
videoList
.
findIndex
(
item
=>
item
.
id
==
lastIndex
)
}
getVideoList
=
()
=>
{
let
url
=
''
;
if
(
getParam
(
'video_id'
))
{
url
=
`
${
API
.
home
}
/m/course/play/
${
this
.
courseID
+
'?video_id='
+
getParam
(
'video_id'
)}
`
http
.
post
(
`
${
API
[
'base-api'
]}
/sys/get_class_audition`
,
{
video_id
:
getParam
(
'video_id'
)
})
}
else
{
url
=
`
${
API
.
home
}
/m/course/play/
${
this
.
courseID
}
`
}
playSetup
=
()
=>
{
// is_aist,是否AI特训营
const
{
course
=
{}}
=
this
.
state
;
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// }else{
let
_this
=
this
;
this
.
setupWS
();
this
.
setupTimer
();
let
scheduleTime
=
setTimeout
(
function
()
{
clearTimeout
(
scheduleTime
);
scheduleTime
=
null
;
_this
.
countSchedule
();
// 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度
},
1000
);
// }
let
index
=
this
.
getLastVideoIndex
(
course
.
last_video_id
);
index
=
index
>=
0
?
index
:
0
;
this
.
setState
(
{
activeIndex
:
index
},
()
=>
{
if
(
this
.
lessonAvailable
(
index
))
{
if
(
this
.
hasAuth
(
index
))
{
Promise
.
resolve
().
then
(()
=>
{
this
.
initializePlayer
()
this
.
playWithAuth
()
})
}
else
{
this
.
getCoursePrice
();
}
}
else
{
alert
(
'暂无视频'
,
''
,
[{
text
:
'OK'
,
onPress
:
()
=>
{
this
.
props
.
history
.
push
(
'/'
)
}
}])
}
http
.
get
(
url
).
then
(
res
=>
{
const
{
data
=
{},
code
}
=
res
.
data
;
if
(
code
===
200
)
{
this
.
setState
(
state
=>
({
videoList
:
data
[
'lessons'
],
currentVideoSrc
:
data
[
'lessons'
][
state
.
activeIndex
][
'play_url'
],
course
:
data
.
course
,
courseId
:
data
.
course
[
'course_id'
],
vCourseId
:
data
.
course
[
'v_course_id'
],
title
:
data
.
course
[
'course_title'
],
isLoading
:
false
}),
this
.
playSetup
)
}
else
{
Toast
.
info
(
data
.
msg
)
}
}
)
}
playSetup
=
()
=>
{
// is_aist,是否AI特训营
const
{
course
=
{}}
=
this
.
state
;
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// }else{
let
_this
=
this
;
this
.
setupWS
();
this
.
setupTimer
();
let
scheduleTime
=
setTimeout
(
function
()
{
clearTimeout
(
scheduleTime
);
scheduleTime
=
null
;
_this
.
countSchedule
();
// 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度
},
1000
);
// }
let
index
=
this
.
getLastVideoIndex
(
course
.
last_video_id
);
index
=
index
>=
0
?
index
:
0
;
this
.
setState
(
{
activeIndex
:
index
},
()
=>
{
if
(
this
.
lessonAvailable
(
index
))
{
if
(
this
.
hasAuth
(
index
))
{
Promise
.
resolve
().
then
(()
=>
{
this
.
initializePlayer
()
this
.
playWithAuth
()
})
}
else
{
this
.
getCoursePrice
();
}
}
else
{
alert
(
'暂无视频'
,
''
,
[{
text
:
'OK'
,
onPress
:
()
=>
{
this
.
props
.
history
.
push
(
'/'
)
}
);
}
setPlayerSrc
=
src
=>
{
if
(
!
this
.
player
)
{
this
.
initializePlayer
()
}])
}
this
.
player
.
src
({
src
,
type
:
'application/x-mpegURL'
})
}
}
);
playVideo
=
()
=>
{
this
.
player
.
ready
(()
=>
{
this
.
player
.
play
()
})
}
setPlayerSrc
=
src
=>
{
if
(
!
this
.
player
)
{
this
.
initializePlayer
()
}
this
.
player
.
src
({
src
,
type
:
'application/x-mpegURL'
})
}
playVideo
=
()
=>
{
this
.
player
.
ready
(()
=>
{
this
.
player
.
play
()
})
getDatumCatalog
()
{
http
.
get
(
`
${
API
.
home
}
/m/course/data/
${
this
.
courseID
}
`
)
.
then
(
res
=>
{
const
data
=
res
.
data
if
(
data
.
code
===
200
)
{
}
this
.
setState
({
datum
:
data
.
data
})
}
else
{
Toast
.
info
(
data
.
msg
)
}
})
}
getDatumCatalog
()
{
http
.
get
(
`
${
API
.
home
}
/m/course/data/
${
this
.
courseID
}
`
)
.
then
(
res
=>
{
const
data
=
res
.
data
if
(
data
.
code
===
200
)
{
lessonAvailable
=
index
=>
{
return
this
.
state
.
videoList
[
index
][
'video_size'
]
!==
0
}
this
.
setState
(
{
datum
:
data
.
data
})
getCoursePrice
=
()
=>
{
const
{
course
=
{}}
=
this
.
state
;
http
.
get
(
`
${
API
.
home
}
/sys/course/price/
${
course
.
course_id
}
`
)
.
then
(
res
=>
{
const
{
data
}
=
res
if
(
data
.
code
===
200
)
{
this
.
setState
({
salePrice
:
data
.
data
[
'sale_price'
]
})
}
})
}
}
else
{
Toast
.
info
(
data
.
msg
)
}
})
}
lessonAvailable
=
index
=>
{
return
this
.
state
.
videoList
[
index
][
'video_size'
]
!==
0
}
getCoursePrice
=
()
=>
{
const
{
course
=
{}}
=
this
.
state
;
http
.
get
(
`
${
API
.
home
}
/sys/course/price/
${
course
.
course_id
}
`
)
.
then
(
res
=>
{
const
{
data
}
=
res
if
(
data
.
code
===
200
)
{
this
.
setState
({
salePrice
:
data
.
data
[
'sale_price'
]
})
}
})
}
playWithAuth
=
()
=>
{
const
{
videoList
,
activeIndex
}
=
this
.
state
playWithAuth
=
()
=>
{
const
{
videoList
,
activeIndex
}
=
this
.
state
if
(
this
.
hasAuth
(
activeIndex
))
{
this
.
setPlayerSrc
(
videoList
[
activeIndex
][
'play_url'
])
}
if
(
this
.
hasAuth
(
activeIndex
))
{
this
.
setPlayerSrc
(
videoList
[
activeIndex
][
'play_url'
])
}
}
hasAuth
=
index
=>
{
const
{
videoList
}
=
this
.
state
hasAuth
=
index
=>
{
const
{
videoList
}
=
this
.
state
let
lesson
=
videoList
[
index
]
let
lesson
=
videoList
[
index
]
if
(
lesson
[
'video_auth'
])
{
this
.
setState
({
isAuth
:
true
})
return
true
}
else
{
this
.
setState
({
isAuth
:
false
})
return
false
if
(
lesson
[
'video_auth'
])
{
this
.
setState
({
isAuth
:
true
})
return
true
}
else
{
this
.
setState
({
isAuth
:
false
})
return
false
}
}
showLimitFreePopup
=
(
title
,
id
)
=>
{
Popup
({
title
:
<
span
>
想领取【
AI
工程师必备干货礼包】
?
想深入了解进阶课程?
职业前景不明朗
?
资深规划师免费为你服务
!<
/span>
,
className
:
'free-popup'
,
content
:
<
div
className
=
{
'des'
}
>
<
img
className
=
"qrcode"
src
=
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/tinypng-common/right_weixin.png"
/>
<
/div
>
})
}
render
()
{
let
{
match
,
location
,
history
}
=
this
.
props
const
{
videoList
,
activeIndex
,
isAuth
,
salePrice
,
course
,
singleBox
,
singleType
,
showLimitFreePopup
}
=
this
.
state
;
let
toHref
=
''
;
if
(
location
.
state
&&
location
.
state
.
to
&&
location
.
state
.
to
===
'detail'
)
{
toHref
=
`/detail?id=
${
course
.
course_id
}
`
}
render
()
{
let
{
match
,
location
,
history
}
=
this
.
props
const
{
videoList
,
activeIndex
,
isAuth
,
salePrice
,
course
,
singleBox
,
singleType
}
=
this
.
state
;
let
toHref
=
''
;
if
(
location
.
state
&&
location
.
state
.
to
&&
location
.
state
.
to
===
'detail'
)
{
toHref
=
`/detail?id=
${
course
.
course_id
}
`
}
return
(
<
div
className
=
'play'
>
<
HeaderBar
title
=
{
this
.
state
.
title
}
arrow
=
{
true
}
toHref
=
{()
=>
{
toHref
?
history
.
push
(
toHref
,
{
to
:
'classify'
}
)
:
history
.
go
(
-
1
)
}}
/
>
<
Loading
isLoading
=
{
this
.
state
.
isLoading
}
>
<
div
className
=
"video"
>
<
video
className
=
{
'video-js'
}
ref
=
{
el
=>
this
.
video
=
el
}
webkit
-
playsinline
=
"true"
playsInline
=
{
true
}
x
-
webkit
-
airplay
=
"allow"
x5
-
video
-
player
-
type
=
"h5"
>
<
source
src
=
{
'/'
}
type
=
'application/x-mpegURL'
/>
<
/video
>
{
!
isAuth
&&
!!
videoList
[
activeIndex
][
'is_class'
]
&&
(
<
div
className
=
"purchase-box"
>
<
div
className
=
'hint'
>
您尚未购买该课时,请购买后学习。
<
/div
>
<
div
className
=
'btns'
>
<
button
type
=
'button'
onClick
=
{
this
.
tobuy
}
className
=
'purchase-class'
>
¥
{
salePrice
}
购买课程
<
/button
>
<
button
type
=
'button'
onClick
=
{
this
.
toSingleset
.
bind
(
this
,
videoList
[
activeIndex
])}
className
=
'purchase-episode'
>
¥
{
videoList
.
length
&&
videoList
[
activeIndex
][
'class_price'
]}
购买单集
<
/button
>
<
/div
>
<
/div
>
)
}
{
!
isAuth
&&
!!
course
.
is_aist
&&
(
<
div
className
=
"is-aist-box"
>
<
i
className
=
{
'iconfont iconiconfront-21'
}
><
/i
>
<
p
className
=
{
'time'
}
>
{
videoList
[
activeIndex
][
'aist_start_time'
]}
<
/p
>
<
p
className
=
{
'time'
}
>
请耐心等待
...
<
/p
>
<
/div
>
)
}
<
/div
>
<
div
className
=
'tab'
>
<
div
>
<
NavLink
to
=
{{
pathname
:
`
${
match
.
url
}
/video`
,
search
:
`?id=
${
this
.
courseID
}
`
}}
replace
activeClassName
=
'active'
>
视频
<
/NavLink
>
<
/div
>
<
div
>
<
NavLink
to
=
{{
pathname
:
`
${
match
.
url
}
/datum`
,
search
:
`?id=
${
this
.
courseID
}
`
}}
replace
activeClassName
=
'active'
>
资料
<
/NavLink
>
<
/div
>
<
/div
>
{
/*单集购买*/
}
{
singleBox
&&
<
Single
courseId
=
{
course
.
course_id
}
singleBox
=
{
this
.
state
.
singleBox
}
boxHide
=
{
this
.
boxHide
}
data
=
{
this
.
state
.
singMess
}
singleType
=
{
this
.
state
.
singleType
}
vcourseId
=
{
course
.
v_course_id
}
videoId
=
{
this
.
state
.
singMess
.
video_id
}
check
=
{
this
.
check
}
title
=
{
this
.
state
.
singMess
.
course_tile
}
/
>
}
{
/* 单集购买成功 */
}
{
singleType
!==
1
&&
<
SingleSuccess
courseId
=
{
course
.
course_id
}
boxHide
=
{
this
.
boxHide
}
data
=
{
this
.
state
.
singMess
}
singleType
=
{
singleType
}
vcourseId
=
{
course
.
v_course_id
}
videoId
=
{
this
.
state
.
singMess
.
video_id
}
nowPrice
=
{
this
.
state
.
nowPrice
}
laterPrice
=
{
this
.
state
.
laterPrice
}
/
>
}
<
/Loading
>
<
Switch
>
<
Redirect
exact
from
=
{
'/play'
}
to
=
{{
pathname
:
'/play/video'
,
search
:
location
.
search
}}
/
>
<
Route
path
=
{
`
${
match
.
path
}
/video`
}
render
=
{
props
=>
{
return
(
<
VideoCatalog
activeIndex
=
{
this
.
state
.
activeIndex
}
selectVideo
=
{
this
.
selectVideo
}
videoCatalog
=
{
videoList
}
{...
props
}
/
>
);
}}
/
>
<
Route
path
=
{
`
${
match
.
path
}
/datum`
}
render
=
{
props
=>
{
return
<
DatumCatalog
{...
props
}
datum
=
{
this
.
state
.
datum
}
/
>
}}
/
>
<
/Switch
>
<
Route
render
=
{
props
=>
{
return
this
.
state
.
vCourseId
?
<
Recommendation
{...
props
}
vCourseId
=
{
this
.
state
.
vCourseId
}
/
>
:
null
}}
/
>
<
ProgressShareModal
isShow
=
{
this
.
state
.
isShowShareModal
}
closeShareModal
=
{()
=>
this
.
setState
({
isShowShareModal
:
false
})}
data
=
{
this
.
state
.
shareData
}
return
(
<
div
className
=
'play'
>
<
HeaderBar
title
=
{
this
.
state
.
title
}
arrow
=
{
true
}
toHref
=
{()
=>
{
toHref
?
history
.
push
(
toHref
,
{
to
:
'classify'
}
)
:
history
.
go
(
-
1
)
}}
/
>
<
Loading
isLoading
=
{
this
.
state
.
isLoading
}
>
<
div
className
=
"video"
>
<
video
className
=
{
'video-js'
}
ref
=
{
el
=>
this
.
video
=
el
}
webkit
-
playsinline
=
"true"
playsInline
=
{
true
}
x
-
webkit
-
airplay
=
"allow"
x5
-
video
-
player
-
type
=
"h5"
>
<
source
src
=
{
'/'
}
type
=
'application/x-mpegURL'
/>
<
/video
>
{
!
isAuth
&&
!!
videoList
[
activeIndex
][
'is_class'
]
&&
(
<
div
className
=
"purchase-box"
>
<
div
className
=
'hint'
>
您尚未购买该课时,请购买后学习。
<
/div
>
<
div
className
=
'btns'
>
<
button
type
=
'button'
onClick
=
{
this
.
tobuy
}
className
=
'purchase-class'
>
¥
{
salePrice
}
购买课程
<
/button
>
<
button
type
=
'button'
onClick
=
{
this
.
toSingleset
.
bind
(
this
,
videoList
[
activeIndex
])}
className
=
'purchase-episode'
>
¥
{
videoList
.
length
&&
videoList
[
activeIndex
][
'class_price'
]}
购买单集
<
/button
>
<
/div
>
<
/div
>
)
}
{
!
isAuth
&&
!!
course
.
is_aist
&&
(
<
div
className
=
"is-aist-box"
>
<
i
className
=
{
'iconfont iconiconfront-21'
}
><
/i
>
<
p
className
=
{
'time'
}
>
{
videoList
[
activeIndex
][
'aist_start_time'
]}
<
/p
>
<
p
className
=
{
'time'
}
>
请耐心等待
...
<
/p
>
<
/div
>
)
}
<
/div
>
<
div
className
=
'tab'
>
<
div
>
<
NavLink
to
=
{{
pathname
:
`
${
match
.
url
}
/video`
,
search
:
`?id=
${
this
.
courseID
}
`
}}
replace
activeClassName
=
'active'
>
视频
<
/NavLink
>
<
/div
>
<
div
>
<
NavLink
to
=
{{
pathname
:
`
${
match
.
url
}
/datum`
,
search
:
`?id=
${
this
.
courseID
}
`
}}
replace
activeClassName
=
'active'
>
资料
<
/NavLink
>
<
/div
>
<
/div
>
{
/*单集购买*/
}
{
singleBox
&&
<
Single
courseId
=
{
course
.
course_id
}
singleBox
=
{
this
.
state
.
singleBox
}
boxHide
=
{
this
.
boxHide
}
data
=
{
this
.
state
.
singMess
}
singleType
=
{
this
.
state
.
singleType
}
vcourseId
=
{
course
.
v_course_id
}
videoId
=
{
this
.
state
.
singMess
.
video_id
}
check
=
{
this
.
check
}
title
=
{
this
.
state
.
singMess
.
course_tile
}
/
>
}
{
/* 单集购买成功 */
}
{
singleType
!==
1
&&
<
SingleSuccess
courseId
=
{
course
.
course_id
}
boxHide
=
{
this
.
boxHide
}
data
=
{
this
.
state
.
singMess
}
singleType
=
{
singleType
}
vcourseId
=
{
course
.
v_course_id
}
videoId
=
{
this
.
state
.
singMess
.
video_id
}
nowPrice
=
{
this
.
state
.
nowPrice
}
laterPrice
=
{
this
.
state
.
laterPrice
}
/
>
}
<
/Loading
>
<
Switch
>
<
Redirect
exact
from
=
{
'/play'
}
to
=
{{
pathname
:
'/play/video'
,
search
:
location
.
search
}}
/
>
<
Route
path
=
{
`
${
match
.
path
}
/video`
}
render
=
{
props
=>
{
return
(
<
VideoCatalog
activeIndex
=
{
this
.
state
.
activeIndex
}
selectVideo
=
{
this
.
selectVideo
}
videoCatalog
=
{
videoList
}
{...
props
}
/
>
);
}}
/
>
<
Route
path
=
{
`
${
match
.
path
}
/datum`
}
render
=
{
props
=>
{
return
<
DatumCatalog
{...
props
}
datum
=
{
this
.
state
.
datum
}
/
>
}}
/
>
<
/Switch
>
<
Route
render
=
{
props
=>
{
return
this
.
state
.
vCourseId
?
<
Recommendation
{...
props
}
vCourseId
=
{
this
.
state
.
vCourseId
}
/
>
:
null
}}
/
>
<
ProgressShareModal
isShow
=
{
this
.
state
.
isShowShareModal
}
closeShareModal
=
{()
=>
this
.
setState
({
isShowShareModal
:
false
})}
data
=
{
this
.
state
.
shareData
}
/
>
{
showLimitFreePopup
&&
<
div
className
=
{
'limit-free-cover'
}
>
<
div
className
=
"free-popup"
>
<
div
className
=
"title"
>
<
span
>
想领取【
AI
工程师必备干货礼包】
?
想深入了解进阶课程?
职业前景不明朗
?
资深规划师免费为你服务
!<
/span
>
<
/div
>
<
div
className
=
{
'des'
}
>
<
img
className
=
"qrcode"
src
=
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/tinypng-common/right_weixin.png"
alt
=
''
/>
<
span
>
长按
/
扫码识别
<
/span
>
<
span
>
添加时请备注
<
span
>
142
<
/span>哦</
span
>
<
div
className
=
"no-prompt"
>
<
label
htmlFor
=
"no-prompt"
>
<
span
className
=
{
`checkbox-label
${
this
.
state
.
limitFreeNoPromptChecked
?
'checked'
:
'unchecked'
}
`
}
>
<
i
className
=
{
'iconfont iconiconfront-73'
}
/
>
<
/span
>
<
input
type
=
"checkbox"
id
=
{
'no-prompt'
}
onChange
=
{(
e
)
=>
{
this
.
setState
({
limitFreeNoPromptChecked
:
e
.
target
.
checked
})
}}
/
>
<
span
>
本课程不再提示
<
/span
>
<
/label
>
<
/div
>
<
/div
>
<
i
className
=
{
'close-btn iconfont iconiconfront-2'
}
onClick
=
{()
=>
{
this
.
setState
({
showLimitFreePopup
:
false
})
localStorage
.
setItem
(
'neverShowLimitFreePopup'
,
'1'
)
}}
/
>
<
/div
>
);
}
<
/div
>
}
<
/div
>
);
}
}
export
default
connect
(
state
=>
({
user
:
state
.
user
}),
null
state
=>
({
user
:
state
.
user
}),
null
)(
Video
);
src/components/video/video.scss
View file @
4ec71ac5
...
...
@@ -281,12 +281,26 @@ $tabHeight: 44px;
}
}
.limit-free-cover
{
position
:
fixed
;
top
:
0
;
left
:
0
;
bottom
:
0
;
right
:
0
;
background-color
:
rgba
(
0
,
0
,
0
,
.8
);
z-index
:
999
;
}
.free-popup
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
width
:
290px
;
height
:
366px
;
border-radius
:
5px
!
important
;
padding
:
0
!
important
;
overflow
:
hidden
;
background
:
url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/popup-bg.png")
!
important
;
background-size
:
cover
!
important
;
...
...
@@ -299,5 +313,90 @@ $tabHeight: 44px;
font-size
:
15px
;
}
.des
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
padding-top
:
20px
;
.qrcode
{
margin-bottom
:
10px
;
width
:
118px
;
height
:
118px
;
}
&
>
span
:nth-of-type
(
1
)
{
color
:
#666
;
font-size
:
13px
;
margin-bottom
:
10px
;
}
&
>
span
:nth-of-type
(
2
)
{
color
:
#333
;
font-size
:
15px
;
margin-bottom
:
14px
;
}
span
span
{
color
:
#FF2121
;
}
.no-prompt
{
label
{
position
:
relative
;
padding-left
:
21px
;
height
:
14px
;
}
input
,
.checkbox-label
{
position
:
absolute
;
top
:
50%
;
left
:
0
;
transform
:
translateY
(
-50%
);
width
:
13px
;
height
:
13px
;
-webkit-appearance
:
none
;
outline
:
0
;
background
:
#fff
;
}
input
{
opacity
:
0
;
}
.checkbox-label
{
border
:
1px
solid
rgba
(
84
,
92
,
100
,
.6
);
border-radius
:
1px
;
left
:
-1px
;
box-sizing
:
border-box
;
.iconfont
{
color
:
#fff
;
font-size
:
12px
;
}
}
span
{
color
:
#545C64
;
font-size
:
13px
;
margin-bottom
:
0
;
line-height
:
14px
;
}
.checked
{
background
:
#09f
;
}
}
}
.close-btn
{
position
:
absolute
;
bottom
:
-44px
;
left
:
50%
;
transform
:
translateX
(
-50%
);
font-size
:
26px
;
color
:
#fff
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment