@x-edu/live-player 0.0.18 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/.browserslistrc +10 -10
  2. package/.eslintignore +8 -8
  3. package/.eslintrc.js +26 -26
  4. package/.postcssrc.js +6 -6
  5. package/README.md +145 -145
  6. package/babel.config.js +33 -33
  7. package/dist/XEduLivePlayer.common.js +11651 -1000
  8. package/dist/XEduLivePlayerPre.common.js +11841 -1190
  9. package/doc/develop.md +23 -23
  10. package/gem-mine.config.js +86 -86
  11. package/jest.config.js +9 -9
  12. package/jsconfig.json +15 -15
  13. package/mock/helper.js +8 -8
  14. package/mock/index.js +34 -34
  15. package/package.json +99 -99
  16. package/public/3rd/ali-player/alipayercomponents-1.0.8.min.js +26 -26
  17. package/public/3rd/ali-player/aliplayer-hls-min.js +27 -27
  18. package/public/3rd/ali-player/aliplayer-min.js +1 -1
  19. package/public/3rd/im-web-push/index.umd.js +14 -14
  20. package/public/fish/editor/themes/default/css/ueditor.css +1905 -1905
  21. package/public/fish/editor/third-party/codemirror/codemirror.css +104 -104
  22. package/public/fish/editor/third-party/codemirror/codemirror.js +3581 -3581
  23. package/public/fish/editor/third-party/zeroclipboard/ZeroClipboard.js +1255 -1255
  24. package/public/fish/editor/ueditor.all.min.js +16 -16
  25. package/public/fish/editor/ueditor.config.js +467 -467
  26. package/public/fish/icon/umd-4.1.2.js +1 -1
  27. package/public/fish/video/videoplayer.min.css +6 -6
  28. package/public/fish/video/videoplayer.min.js +31 -31
  29. package/public/fish/video/zh-CN.js +82 -82
  30. package/public/icon/demo.css +539 -539
  31. package/public/icon/demo_index.html +2189 -2189
  32. package/public/icon/iconfont.css +363 -363
  33. package/public/icon/iconfont.json +618 -618
  34. package/public/index.html +50 -50
  35. package/script/image/readme.md +77 -77
  36. package/script/postcss.js +48 -48
  37. package/src/App.jsx +24 -24
  38. package/src/asset/img/course/playing.svg +21 -21
  39. package/src/asset/img/icon-course-white.svg +3 -3
  40. package/src/asset/img/icon-course.svg +3 -3
  41. package/src/asset/img/icon-eye-white.svg +4 -4
  42. package/src/asset/img/icon-eye.svg +4 -4
  43. package/src/asset/img/icon-school-white.svg +3 -3
  44. package/src/asset/img/icon-school.svg +3 -3
  45. package/src/asset/img/loading.svg +52 -52
  46. package/src/asset/img/video-play.svg +6 -6
  47. package/src/asset/style/background.less +19 -19
  48. package/src/asset/style/banner.less +36 -36
  49. package/src/asset/style/base.less +74 -74
  50. package/src/asset/style/index.less +114 -114
  51. package/src/asset/style/reset-theme.less +141 -141
  52. package/src/asset/style/theme/index.less +55 -55
  53. package/src/asset/style/theme/party/global.less +20 -20
  54. package/src/asset/style/theme/party/override.less +57 -57
  55. package/src/asset/style/theme/test/global.less +18 -18
  56. package/src/asset/style/theme/test/override.less +45 -45
  57. package/src/asset/style/variable.less +12 -12
  58. package/src/component/AliPlayer/index.jsx +49 -49
  59. package/src/component/Avatar/index.jsx +50 -50
  60. package/src/component/Empty/index.jsx +34 -34
  61. package/src/component/Empty/index.module.less +37 -37
  62. package/src/component/IMChatroom/component/status/403.jsx +13 -13
  63. package/src/component/IMChatroom/component/status/404.jsx +13 -13
  64. package/src/component/IMChatroom/component/status/Error.jsx +23 -23
  65. package/src/component/IMChatroom/component/status/Loading.jsx +5 -5
  66. package/src/component/IMChatroom/config/app/config.js +118 -118
  67. package/src/component/IMChatroom/config/app/index.js +60 -60
  68. package/src/component/IMChatroom/config/env.js +5 -5
  69. package/src/component/IMChatroom/config/index.js +3 -3
  70. package/src/component/IMChatroom/config/request/config/base.js +124 -124
  71. package/src/component/IMChatroom/config/request/config/chatroom.js +26 -26
  72. package/src/component/IMChatroom/config/request/config/imCoreApi.js +21 -21
  73. package/src/component/IMChatroom/config/request/index.js +21 -21
  74. package/src/component/IMChatroom/config/request/proxy.js +39 -39
  75. package/src/component/IMChatroom/config/url.js +7 -7
  76. package/src/component/IMChatroom/constants/errorCode.js +9 -9
  77. package/src/component/IMChatroom/constants/index.js +84 -84
  78. package/src/component/IMChatroom/constants/origin.js +27 -27
  79. package/src/component/IMChatroom/context/chatroom.js +154 -154
  80. package/src/component/IMChatroom/context/connect.js +28 -28
  81. package/src/component/IMChatroom/i18n/en/index.json +73 -73
  82. package/src/component/IMChatroom/i18n/index.jsx +14 -14
  83. package/src/component/IMChatroom/i18n/language.js +9 -9
  84. package/src/component/IMChatroom/i18n/zh-CN/index.json +73 -73
  85. package/src/component/IMChatroom/index.jsx +49 -49
  86. package/src/component/IMChatroom/page/chat/index.jsx +27 -27
  87. package/src/component/IMChatroom/page/chat/messageEditor/index.jsx +375 -375
  88. package/src/component/IMChatroom/page/chat/messageList/index.jsx +354 -354
  89. package/src/component/IMChatroom/page/chat/stickedMessage/index.jsx +59 -59
  90. package/src/component/IMChatroom/page/chat/stickedMessage/style/index.module.less +7 -7
  91. package/src/component/IMChatroom/page/chat/style/index.module.less +51 -51
  92. package/src/component/IMChatroom/page/home/connect/index.jsx +188 -188
  93. package/src/component/IMChatroom/page/home/connect/status.jsx +124 -124
  94. package/src/component/IMChatroom/page/home/context/cmd.jsx +37 -37
  95. package/src/component/IMChatroom/page/home/context/index.jsx +67 -67
  96. package/src/component/IMChatroom/page/home/index.jsx +164 -164
  97. package/src/component/IMChatroom/page/home/notice/index.jsx +123 -123
  98. package/src/component/IMChatroom/page/home/notice/style/index.module.less +49 -49
  99. package/src/component/IMChatroom/page/home/style/index.module.less +110 -110
  100. package/src/component/IMChatroom/page/member/index.jsx +15 -15
  101. package/src/component/IMChatroom/page/member/memberCount/index.jsx +44 -44
  102. package/src/component/IMChatroom/page/member/memberList/index.jsx +121 -121
  103. package/src/component/IMChatroom/page/member/style/index.module.less +2 -2
  104. package/src/component/IMChatroom/sdk/bridge.js +39 -39
  105. package/src/component/IMChatroom/sdk/cs/constants.js +20 -20
  106. package/src/component/IMChatroom/sdk/cs/index.js +101 -101
  107. package/src/component/IMChatroom/sdk/imChatroom.js +15 -15
  108. package/src/component/IMChatroom/sdk/imcore/constants.js +128 -128
  109. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomDestroyed.js +5 -5
  110. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomInfoGetFail.js +5 -5
  111. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedByAdmin.js +5 -5
  112. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedBySelf.js +5 -5
  113. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginFail.js +5 -5
  114. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginSuccess.js +5 -5
  115. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogin.js +5 -5
  116. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogout.js +5 -5
  117. package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnected.js +5 -5
  118. package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnecting.js +5 -5
  119. package/src/component/IMChatroom/sdk/imcore/emitters/connectionDisconnect.js +5 -5
  120. package/src/component/IMChatroom/sdk/imcore/emitters/index.js +57 -57
  121. package/src/component/IMChatroom/sdk/imcore/emitters/messageReceive.js +36 -36
  122. package/src/component/IMChatroom/sdk/imcore/index.js +178 -178
  123. package/src/component/IMChatroom/sdk/imcore/interceptors/request.js +7 -7
  124. package/src/component/IMChatroom/sdk/imcore/interceptors/response.js +5 -5
  125. package/src/component/IMChatroom/sdk/imcore/plugins/getAuth.js +64 -64
  126. package/src/component/IMChatroom/sdk/imcore/plugins/getConversationId.js +20 -20
  127. package/src/component/IMChatroom/sdk/imcore/plugins/getExtInfo.js +10 -10
  128. package/src/component/IMChatroom/sdk/imcore/plugins/getLoginInfo.js +48 -48
  129. package/src/component/IMChatroom/sdk/imcore/plugins/getPlatformType.js +12 -12
  130. package/src/component/IMChatroom/sdk/imcore/plugins/index.js +22 -22
  131. package/src/component/IMChatroom/sdk/imcore/util/format.js +177 -177
  132. package/src/component/IMChatroom/sdk/imcore/util/parser.js +35 -35
  133. package/src/component/IMChatroom/sdk/oms.js +18 -18
  134. package/src/component/IMChatroom/sdk/uc.js +3 -3
  135. package/src/component/IMChatroom/subscription/channel/app.js +5 -5
  136. package/src/component/IMChatroom/subscription/channel/ctl.js +22 -22
  137. package/src/component/IMChatroom/subscription/channel/member.js +40 -40
  138. package/src/component/IMChatroom/subscription/channel/message.js +13 -13
  139. package/src/component/IMChatroom/subscription/channel/ntf.js +86 -86
  140. package/src/component/IMChatroom/subscription/channel/tel.js +5 -5
  141. package/src/component/IMChatroom/subscription/channel/websocket.js +5 -5
  142. package/src/component/IMChatroom/subscription/event.js +37 -37
  143. package/src/component/IMChatroom/subscription/index.js +19 -19
  144. package/src/component/IMChatroom/util/account.js +8 -8
  145. package/src/component/IMChatroom/util/chatroom.js +255 -255
  146. package/src/component/IMChatroom/util/jsonBigInt.js +5 -5
  147. package/src/component/IMChatroom/util/location.js +12 -12
  148. package/src/component/Icon/index.jsx +16 -16
  149. package/src/component/Icon/index.module.less +2 -2
  150. package/src/component/Pagination/LocalPagination.jsx +27 -27
  151. package/src/component/Pagination/RemotePagination.jsx +32 -32
  152. package/src/component/Pagination/index.jsx +31 -31
  153. package/src/component/Pagination/index.module.less +110 -110
  154. package/src/component/PlayerTip/index.jsx +34 -34
  155. package/src/component/VideoBase/index.jsx +242 -242
  156. package/src/component/VideoBase/style.less +65 -65
  157. package/src/component/VideoBase/utils.js +81 -81
  158. package/src/component/mixin.less +9 -9
  159. package/src/component/status/403.jsx +15 -15
  160. package/src/component/status/404/index.jsx +73 -73
  161. package/src/component/status/404/index.module.less +36 -36
  162. package/src/component/status/Error/error.module.less +13 -13
  163. package/src/component/status/Error/index.jsx +47 -47
  164. package/src/component/status/Loading/img/loading.svg +52 -52
  165. package/src/component/status/Loading/index.jsx +31 -31
  166. package/src/component/status/Loading/index.less +56 -56
  167. package/src/component/status/None/index.jsx +20 -20
  168. package/src/component/status/None/index.module.less +35 -35
  169. package/src/component/status/Status/index.jsx +26 -26
  170. package/src/component/status/Status/index.module.less +8 -8
  171. package/src/config/constant/commonUrl.js +2 -2
  172. package/src/config/constant/user.js +6 -6
  173. package/src/config/context/site-config.js +48 -48
  174. package/src/config/env/index.js +5 -5
  175. package/src/config/env/local/index.js +13 -13
  176. package/src/config/env/ncet-xedu/api.js +175 -175
  177. package/src/config/env/ncet-xedu/app.js +12 -12
  178. package/src/config/env/ncet-xedu/cs.js +8 -8
  179. package/src/config/env/ncet-xedu/index.js +14 -14
  180. package/src/config/env/ncet-xedu/push.js +5 -5
  181. package/src/config/env/preproduction/api.js +144 -144
  182. package/src/config/env/preproduction/app.js +12 -12
  183. package/src/config/env/preproduction/cs.js +8 -8
  184. package/src/config/env/preproduction/index.js +14 -14
  185. package/src/config/env/preproduction/push.js +5 -5
  186. package/src/config/env/product/api.js +113 -113
  187. package/src/config/env/product/app.js +12 -12
  188. package/src/config/env/product/cs.js +5 -5
  189. package/src/config/env/product/index.js +14 -14
  190. package/src/config/env/product/push.js +5 -5
  191. package/src/config/live.js +80 -80
  192. package/src/config/publicLive.js +53 -53
  193. package/src/config/request/assessments.js +24 -24
  194. package/src/config/request/config-center.js +8 -8
  195. package/src/config/request/helper.js +166 -166
  196. package/src/config/request/im-broadcasts.js +12 -12
  197. package/src/config/request/live-activity-gateway.js +8 -8
  198. package/src/config/request/live-activity.js +13 -13
  199. package/src/config/request/raw.js +6 -6
  200. package/src/config/request/x-cloud-web.js +13 -13
  201. package/src/config/request/x-proxy.js +34 -34
  202. package/src/demo/Detail.jsx +11 -11
  203. package/src/demo/List.jsx +64 -64
  204. package/src/demo/index.jsx +17 -17
  205. package/src/detail/LineSwitch/index.jsx +71 -71
  206. package/src/detail/LiveCountDown/index.jsx +44 -44
  207. package/src/detail/LiveCountDown/index.module.less +31 -31
  208. package/src/detail/LiveOnlineCount/img/icon.svg +15 -15
  209. package/src/detail/LiveOnlineCount/index.jsx +68 -68
  210. package/src/detail/LiveOnlineCount/index.module.less +34 -34
  211. package/src/detail/LiveOnlineCount/util.js +74 -74
  212. package/src/detail/LiveStatus/AnchorOnTheWay.jsx +88 -88
  213. package/src/detail/LiveStatus/index.jsx +202 -202
  214. package/src/detail/LiveStatus/index.module.less +192 -192
  215. package/src/detail/LiveVideo/config.js +37 -37
  216. package/src/detail/LiveVideo/index.jsx +188 -188
  217. package/src/detail/LiveVideo/index.module.less +41 -41
  218. package/src/detail/NotLoginChatroom/index.jsx +37 -37
  219. package/src/detail/NotLoginChatroom/index.module.less +46 -46
  220. package/src/detail/RecordVideo/index.jsx +150 -150
  221. package/src/detail/RecordVideo/index.module.less +31 -31
  222. package/src/detail/ReplayVideo/index.jsx +93 -93
  223. package/src/detail/ReplayVideo/index.module.less +65 -65
  224. package/src/detail/const.js +20 -20
  225. package/src/detail/hook/usePullSource.js +82 -82
  226. package/src/detail/hook/usePullState.js +51 -51
  227. package/src/detail/index.jsx +482 -483
  228. package/src/detail/index.module.less +188 -188
  229. package/src/hook/useAsync.js +84 -84
  230. package/src/hook/useGoToPage.js +83 -83
  231. package/src/hook/useInterval.js +28 -28
  232. package/src/hook/useIsMounted.js +17 -17
  233. package/src/hook/useModuleByRole.js +53 -53
  234. package/src/hook/usePageScrollable.js +52 -52
  235. package/src/hook/usePortal.js +83 -83
  236. package/src/hook/useScrollRestore/index.js +32 -32
  237. package/src/hook/useScrollRestore/scrollContext.js +20 -20
  238. package/src/hook/useTrackRef.js +11 -11
  239. package/src/hook/useWindowSize.js +28 -28
  240. package/src/hook/useZoom.js +47 -47
  241. package/src/index.js +10 -10
  242. package/src/lib/getLiveOnlineCount.js +10 -10
  243. package/src/lib/getServiceConfig.js +102 -102
  244. package/src/list/Empty/index.jsx +20 -20
  245. package/src/list/Empty/index.module.less +23 -23
  246. package/src/list/ListItem/Action/index.jsx +98 -98
  247. package/src/list/ListItem/Action/index.module.less +21 -21
  248. package/src/list/ListItem/img/dianzan.svg +4 -0
  249. package/src/list/ListItem/img/play.svg +15 -15
  250. package/src/list/ListItem/img/yiguankan.svg +3 -0
  251. package/src/list/ListItem/index.jsx +24 -1
  252. package/src/list/ListItem/index.module.less +146 -123
  253. package/src/list/index.jsx +85 -3
  254. package/src/list/index.module.less +35 -35
  255. package/src/service/common.js +73 -73
  256. package/src/service/content-mgr.js +73 -73
  257. package/src/service/im-group.js +12 -12
  258. package/src/service/im.js +7 -7
  259. package/src/service/imBroadcasts.js +33 -33
  260. package/src/service/like.js +134 -134
  261. package/src/service/manageApi.js +7 -7
  262. package/src/service/managePortal.js +6 -6
  263. package/src/service/myStudyRecord.js +93 -93
  264. package/src/service/navigation.js +47 -47
  265. package/src/service/ndMeeting.js +10 -10
  266. package/src/service/ndr.js +122 -122
  267. package/src/service/news.js +93 -93
  268. package/src/service/personalCenter.js +270 -270
  269. package/src/service/qualityCourse.js +31 -31
  270. package/src/service/recommend.js +81 -81
  271. package/src/service/school.js +323 -323
  272. package/src/service/search.js +170 -170
  273. package/src/service/site-config.js +7 -7
  274. package/src/service/socialCensor.js +45 -45
  275. package/src/service/specialEdu.js +31 -31
  276. package/src/service/suggestion.js +85 -85
  277. package/src/service/syncClassroom.js +321 -321
  278. package/src/service/tCourse.js +204 -204
  279. package/src/service/tchTraining.js +37 -37
  280. package/src/service/uc.js +45 -45
  281. package/src/util/app.js +1 -1
  282. package/src/util/array.js +3 -3
  283. package/src/util/auth/func.js +57 -57
  284. package/src/util/date.js +53 -53
  285. package/src/util/env.js +9 -9
  286. package/src/util/getTimestamp.js +10 -10
  287. package/src/util/hof.js +105 -105
  288. package/src/util/live/index.js +42 -42
  289. package/src/util/liveCountUtil.js +52 -0
  290. package/src/util/netUrl.js +35 -35
  291. package/src/util/object.js +13 -13
  292. package/src/util/push/index.js +58 -58
  293. package/src/util/request.js +227 -227
  294. package/src/util/type.js +17 -17
  295. package/src/util/url.js +203 -203
  296. package/src/util/video.js +26 -26
  297. package/test/setup.js +21 -21
  298. package/test/unit/component/header/logo.spec.jsx +8 -8
  299. package/test/unit/helper.jsx +25 -25
  300. package/test/unit/util/date.spec.js +40 -40
@@ -1,483 +1,482 @@
1
- /* eslint-disable camelcase */
2
- import React, { useState, useEffect } from 'react'
3
- import { Icon } from 'fish'
4
- import dayjs from 'dayjs'
5
- import classNames from 'classnames'
6
- // import Empty from '@/component/Empty'
7
- import {
8
- getOpenClassLive
9
- // getServerTime
10
- } from '@/service/live'
11
- import { getIMLiveInfo, getGuestIMLiveInfo } from '@/service/imBroadcasts'
12
- import Loading from '@/component/status/Loading'
13
- import {
14
- PUBLIC_LIVE_STATUS, PUBLIC_LIVE_MODE, SUB_TYPE
15
- } from '@/config/publicLive'
16
- import { getUrlQuery } from '@/util/url'
17
- import { getRecordLiveStatus } from '@/util/live'
18
- import { isEmpty } from '@/util/object'
19
- // import IMChatroom from '@/component/IMChatroom'
20
- import RecordVideo from './RecordVideo'
21
- import LiveVideo from './LiveVideo'
22
- import LineSwitch from './LineSwitch'
23
- import ReplayVideo from './ReplayVideo'
24
- import style from './index.module.less'
25
- import LiveOnlineCount from './LiveOnlineCount'
26
- import { LOGIN_STATUS } from '@/config/constant/user'
27
- import { USER_IDENTITY_NAME } from '@/config/live'
28
- // import NotLoginChatroom from './NotLoginChatroom'
29
- import netUrl from '@/util/netUrl'
30
- import { ShortUrlMap } from './const'
31
- import { setUC } from '@/util/auth/func'
32
- import config from '@/config/env'
33
-
34
- const TrackPageName = 'edu_Platform_publiclive_detail_page'
35
-
36
- export default function PublicLiveDetail({
37
- containerClassName,
38
- className,
39
- infoClassName,
40
- playerClassName,
41
- descriptionClassName,
42
- errorCover, // 当直播不存在或者错误时候的封面展示
43
- errorText,
44
- replay: propRelay,
45
- liveId: propLiveId,
46
- sdpAppId: propSdpAppId,
47
- uc,
48
- loginInfo = {},
49
- handleLogin,
50
- onOnlineCountChange = () => {},
51
- onStateChange = () => {},
52
- onReportProgress = () => {},
53
- onReportTeacherTrain = () => {},
54
- onSendSensors = () => {}
55
- }) {
56
- setUC(uc, loginInfo?.userInfo)
57
- if (propSdpAppId) {
58
- config.app.appid = propSdpAppId
59
- }
60
-
61
- const { replay, live_id } = getUrlQuery()
62
- const matchId = propLiveId || live_id
63
- const replayMode = propRelay || replay
64
- const liveId = ShortUrlMap[matchId] || matchId
65
-
66
- const [liveInfo, setLiveInfo] = useState()
67
- const [visitTime, setVisitTime] = useState()
68
- const [diffTime, setDiffTime] = useState()
69
- const [isReplayMode, setIsReplayMode] = useState(!!replayMode)
70
- const [isExist, setIsExist] = useState(true)
71
- const [lineChanging, setLineChanging] = useState(false) // 线路切换中标识
72
-
73
- const {
74
- userInfo,
75
- userRole,
76
- loginStatus
77
- } = loginInfo
78
- const isLiveToReplay = !replay
79
- const isStreamLive = liveInfo
80
- && liveInfo.type === PUBLIC_LIVE_MODE.LIVING
81
-
82
- const handleStatusChange = async (status) => {
83
- const newLiveInfo = {
84
- ...liveInfo,
85
- status
86
- }
87
- setLiveInfo(newLiveInfo)
88
- onStateChange(newLiveInfo)
89
- const isRecordLive = liveInfo.type === PUBLIC_LIVE_MODE.RECORDED
90
- if (!isRecordLive
91
- && [
92
- PUBLIC_LIVE_STATUS.NOSTARTED,
93
- PUBLIC_LIVE_STATUS.LIVEING,
94
- PUBLIC_LIVE_STATUS.PASUED
95
- ].includes(status)
96
- && isEmpty(liveInfo.imInfo)
97
- ) {
98
- const {
99
- sub_type: subType,
100
- bid,
101
- room_id: roomId
102
- } = liveInfo
103
- let imLiveInfoResp = {}
104
- // 如果类型为外部推流, 则去请求新的直播详情接口
105
- if (subType === SUB_TYPE.OUTSIDE || subType === SUB_TYPE.REBROADCAST) {
106
- imLiveInfoResp = await getGuestIMLiveInfo(bid)
107
- .catch(() => ({}))
108
-
109
- // 默认使用lines[0] 作为直播源
110
- imLiveInfoResp = {
111
- ...imLiveInfoResp,
112
- param: {
113
- ...imLiveInfoResp.param,
114
- ...imLiveInfoResp.param?.lines?.[0]
115
- }
116
- }
117
- } else {
118
- imLiveInfoResp = await getIMLiveInfo(roomId)
119
- .catch(() => ({}))
120
- }
121
- setLiveInfo({
122
- ...liveInfo,
123
- status,
124
- imInfo: imLiveInfoResp
125
- })
126
- }
127
- }
128
-
129
- const handleSelectChange = (lineSource) => {
130
- setLineChanging(true)
131
- setTimeout(() => {
132
- setLiveInfo({
133
- ...liveInfo,
134
- imInfo: {
135
- ...liveInfo.imInfo,
136
- param: {
137
- ...liveInfo.imInfo.param,
138
- ...lineSource
139
- }
140
- }
141
- })
142
- setLineChanging(false)
143
- }, 0)
144
- }
145
-
146
- useEffect(() => {
147
- const init = async () => {
148
- const [data, error] = await getOpenClassLive(liveId)
149
- .then((v) => [v], (err) => [null, err])
150
- if (error) {
151
- const { response } = error
152
- if (response.status === 404 || response.status === 400) {
153
- setIsExist(false)
154
- }
155
- return
156
- }
157
-
158
- // 调试代码 模拟直播倒计时结束
159
- // data.status = PUBLIC_LIVE_STATUS.NOSTARTED
160
-
161
- const isRecordLive = data.type === PUBLIC_LIVE_MODE.RECORDED
162
- const isNoStarted = data.status === PUBLIC_LIVE_STATUS.NOSTARTED
163
- const isCompleted = data.status === PUBLIC_LIVE_STATUS.COMPLETEED
164
- const isOffline = data.status === PUBLIC_LIVE_STATUS.OFFLINE
165
-
166
- // 录播未完成或未下架,直播未开始时需要服务器时间
167
- let serverTime
168
- if ((isRecordLive && (!isCompleted || !isOffline)) || (!isRecordLive && !isReplayMode && isNoStarted)) {
169
- // const response = await getServerTime()
170
- serverTime = data.serverTime
171
- setDiffTime(data.diffTime)
172
- setVisitTime(serverTime)
173
- }
174
- // 录播计算状态
175
- if (isRecordLive) {
176
- const status = getRecordLiveStatus(data.status, serverTime, data.begin_time, data.end_time)
177
- data.status = status
178
- }
179
- if (!isRecordLive) {
180
- const {
181
- sub_type: subType,
182
- bid,
183
- room_id: roomId
184
- } = data
185
- let imLiveInfoResp = {}
186
- // 如果类型为外部推流, 则去请求新的直播详情接口
187
- if (subType === SUB_TYPE.OUTSIDE || subType === SUB_TYPE.REBROADCAST) {
188
- // if (subType === SUB_TYPE.OUTSIDE) {
189
- imLiveInfoResp = await getGuestIMLiveInfo(bid)
190
- .catch(() => ({}))
191
- // 默认使用lines[0] 作为直播源
192
- imLiveInfoResp = {
193
- ...imLiveInfoResp,
194
- param: {
195
- ...imLiveInfoResp.param,
196
- ...imLiveInfoResp.param?.lines?.[0]
197
- }
198
- }
199
- } else if (data.status === PUBLIC_LIVE_STATUS.LIVEING) {
200
- imLiveInfoResp = await getIMLiveInfo(roomId)
201
- .catch(() => ({}))
202
- }
203
- data.imInfo = imLiveInfoResp
204
- }
205
- // 如果是转播或者是推流 直接播放(用于调试模式)
206
- const { preview } = getUrlQuery() // 后台点预览会加这个参数
207
- const generateInfo = preview ? Object.assign(data, {
208
- status: 1
209
- }) : data
210
- setLiveInfo(generateInfo)
211
- }
212
- init()
213
- }, [])
214
-
215
- useEffect(() => {
216
- if (userInfo) {
217
- onReportProgress()
218
- }
219
- }, [userInfo])
220
-
221
- useEffect(() => {
222
- if (loginStatus !== LOGIN_STATUS.WAIT && liveInfo) {
223
- onSendSensors({
224
- pageName: TrackPageName,
225
- eventName: 'edu_Platform_publiclive_detail_page',
226
- params: {
227
- publiclive_id: liveInfo.live_id,
228
- publiclive_name: liveInfo.live_name,
229
- // 1-直播, 2-录播
230
- publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播',
231
- identity: userRole
232
- ? USER_IDENTITY_NAME[userRole]
233
- : '游客'
234
- }
235
- })
236
- }
237
- }, [!!userRole, !!liveInfo, loginStatus])
238
-
239
- if (!isExist) {
240
- return (
241
- <div
242
- className={classNames(
243
- style['public-live-detail-wrapper'],
244
- style['live-empty'],
245
- containerClassName
246
- )}
247
- style={{
248
- backgroundImage: `url(${errorCover})`
249
- }}
250
- >
251
- <div className={style['empty-marker']} />
252
- <div className={style['empty-content']}>
253
- {/* eslint-disable-next-line max-len */}
254
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADYAAAA2CAYAAACMRWrdAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAALOSURBVHgB7VqLbeMwDGVugctt4BEygje4bFBv0G5y2SC5Rc4jpBNEneDaLtBXCVIA16asL50U8AMEA7ZF6pG0PqSJVqxYIYkNCQHAVl8a3Xa6/dTt1+Dxs25v5rrZbN7o3qHJtLoddDsjHmfXp6V7gvGMbo+JZHxQuj3QraEHsXeDqQ11E4JaaaNbD3kcjS5aAlrRDmEvmefmu+lgjbAd9N86GXv3ToysHUlCK3hA2MItJcIRPQVky4RmgFSPCiED693TYuScRX14osowMnV79eirE5bOimqG2JEEMKNX1YgOQjj2b0GupxLAzmqxkCJnPgMuLPeUC4+1TPyfFib3xOhSGCwjKcK6uYHfgFzP6EqfuMB7qxm9sxg52O9tjHOqkDZ2sAuT43S1KQIOjIBdosLq5DwGP6QIGB9BVESfpcipkfy4cITdpGZZZQly4KMpPDt63P2bIiFNDvxsHd5mwR4n0jt+lSFGDvzs2I3f+8H05Ui8UAJ0gqbTl7/Mo64COS75MwlFjtgEOZkkKXKeseQRKxhER3KemwVHbGIR5OzJHGqTix1LFDFiXJ2CyuQa5t5kLeOIPTP3WipERXINc++dQkDBAh2D0qUAuQu065y8pUpBCTnkbqlcZ84qLVVEDjnwSaWkTXD0saUEqeRQemxxQrgiQ0OVEUsO/FbqQqkAn2coyw75dQXJed5JT6DCzo6KEVY9QUo0Tw62TFXurYEybqdvUmEiRQLE5TDzvTVS1jNCFYTKO1gqQQvpVDOvc47cpZpe+LOx5p5EUeLRQ+oDtT8DzKe7j6hXRupnSHUkAYRz+ccci8JuCObC778YqcEgUkq1e/f+uFTbOCPFlGovkC7VDgbXIG1qzoEJvX9Yqrg+ImisrlAXhpDxUn6Z6M4IXj1kZsSiE3t1IP+Xoz+ofCyS/knMfPTX6xWvZI/yJgXx8i1+EluxYsUEn1PRdSb/XhDOAAAAAElFTkSuQmCC" alt="" />
255
- <p>{errorText || '内容已失效'}</p>
256
- </div>
257
-
258
- </div>
259
- )
260
- }
261
-
262
- if (!liveInfo) {
263
- return <Loading />
264
- }
265
-
266
- const isRecordLive = liveInfo.type === PUBLIC_LIVE_MODE.RECORDED
267
- const beginTime = dayjs(liveInfo.begin_time)
268
-
269
- const handlePlayReplay = (needReport) => {
270
- if (needReport) {
271
- onSendSensors({
272
- pageName: TrackPageName,
273
- eventName: 'edu_Platform_publiclive_detail_replay_click',
274
- params: {
275
- publiclive_id: liveInfo.live_id,
276
- publiclive_name: liveInfo.live_name,
277
- // 1-直播, 2-录播
278
- publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播'
279
- }
280
- })
281
- }
282
-
283
- setIsReplayMode(true)
284
- }
285
-
286
- const handleRequestFullScreen = () => {
287
- onSendSensors({
288
- pageName: TrackPageName,
289
- eventName: 'edu_Platform_publiclive_detail_fullscreen_click'
290
- })
291
- }
292
-
293
- const handleVideoPlay = (needReport) => {
294
- if (needReport) {
295
- onSendSensors({
296
- pageName: TrackPageName,
297
- eventName: 'edu_Platform_publiclive_detail_play_click',
298
- params: {
299
- publiclive_id: liveInfo.live_id,
300
- publiclive_name: liveInfo.live_name,
301
- // 1-直播, 2-录播
302
- publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播'
303
- }
304
- })
305
- }
306
- if (userInfo) {
307
- // 登录且播放后上报
308
- onReportTeacherTrain(userInfo?.user_id, liveId)
309
- }
310
- }
311
-
312
- return (
313
- <>
314
- <div
315
- className={classNames(
316
- style['public-live-detail-wrapper'],
317
- containerClassName
318
- )}
319
- >
320
- <div
321
- className={classNames(
322
- className, style['live-panel']
323
- )}
324
- >
325
- <div className={infoClassName}>
326
-
327
- <div className={style['live-title']}>
328
- <div className={style['live-name']}>
329
- {liveInfo.live_name}
330
- </div>
331
- {
332
- // eslint-disable-next-line no-nested-ternary
333
- liveInfo.status === PUBLIC_LIVE_STATUS.LIVEING
334
- ? (
335
- <LiveOnlineCount
336
- className={style['live-online-count']}
337
- resId={liveId}
338
- onOnlineCountChange={onOnlineCountChange}
339
- />
340
- )
341
- : (
342
- liveInfo.status === PUBLIC_LIVE_STATUS.COMPLETEED
343
- ? (<div className={style['live-end']}>已结束</div>)
344
- : (<></>)
345
- )
346
- }
347
- </div>
348
- <div className={style['live-info']}>
349
- {/*
350
- 暂时隐藏主播
351
- <div className={classNames(style['live-user'], {
352
- [style['empty-user']]: !liveInfo.lecture_user_id && !liveInfo.lecture_user_name
353
- })}
354
- >
355
- <Avatar className={style.avatar} src={getAvatarURL(liveInfo.lecture_user_id)} />
356
- <span title={liveInfo.lecture_user_name}>{liveInfo.lecture_user_name}</span>
357
- </div> */
358
- }
359
- <div className={style['live-time']}>
360
- <Icon
361
- className={style['icon-time']}
362
- type="clock-circle"
363
- />
364
- <span>
365
- {`${beginTime.format(beginTime.isSame(dayjs(), 'day') ? '[今天] HH:mm' : 'YYYY-MM-DD HH:mm')} 开始`}
366
- </span>
367
- </div>
368
- </div>
369
- </div>
370
- <div
371
- className={classNames(style['live-video-wrapper'], playerClassName)}
372
- >
373
- <div className={style['live-wrap']}>
374
- {
375
- // eslint-disable-next-line no-nested-ternary
376
- isReplayMode
377
- ? (
378
- <ReplayVideo
379
- userInfo={userInfo}
380
- handleLogin={handleLogin}
381
- liveInfo={liveInfo}
382
- autoplay={isLiveToReplay}
383
- onVideoPlay={() => {
384
- handleVideoPlay(false)
385
- }}
386
- onRequestFullScreen={handleRequestFullScreen}
387
- />
388
- )
389
- : isRecordLive
390
- ? (
391
- <RecordVideo
392
- isStreamLive={isStreamLive}
393
- userInfo={userInfo}
394
- liveInfo={liveInfo}
395
- visitTime={visitTime}
396
- diffTime={diffTime}
397
- onStatusChange={handleStatusChange}
398
- onPlayReplay={() => {
399
- handlePlayReplay(true)
400
- }}
401
- onVideoPlay={() => {
402
- handleVideoPlay(true)
403
- }}
404
- onRequestFullScreen={handleRequestFullScreen}
405
- />
406
- )
407
- : (
408
- <LiveVideo
409
- isStreamLive={isStreamLive}
410
- handleLogin={handleLogin}
411
- userInfo={userInfo}
412
- liveInfo={liveInfo}
413
- visitTime={visitTime}
414
- lineChanging={lineChanging}
415
- onStatusChange={handleStatusChange}
416
- onPlayReplay={() => {
417
- handlePlayReplay(true)
418
- }}
419
- onVideoPlay={() => {
420
- handleVideoPlay(true)
421
- }}
422
- onRequestFullScreen={handleRequestFullScreen}
423
- />
424
- )
425
- }
426
- {/* {
427
- liveInfo?.chat_type && (
428
- <div className={style['chatroom-wrap']}>
429
- <div className={style['chatroom-title']}>
430
- 讨论区
431
- </div>
432
- {
433
- userInfo ? (
434
- <>
435
- <div className={style['chatroom-top-hint']}>
436
- 系统提示:倡导建康的直播环境,若发布违法、违规、低俗等不良消息,我们会对违规内容及帐号进行封禁处理。
437
- </div>
438
- <IMChatroom
439
- roomId={liveInfo.chat_room_id}
440
- disableEditor={!liveInfo.chat_enabled}
441
- />
442
- </>
443
- ) : (
444
- <NotLoginChatroom
445
- handleLogin={handleLogin}
446
- />
447
- )
448
- }
449
- </div>
450
- )
451
- } */}
452
- </div>
453
- {
454
- !isReplayMode && !isRecordLive
455
- && liveInfo.sub_type !== SUB_TYPE.NET_DRAGON
456
- && liveInfo.status !== PUBLIC_LIVE_STATUS.COMPLETEED
457
- && (
458
- <LineSwitch
459
- className={style['live-line-switch']}
460
- liveInfo={liveInfo}
461
- onChange={handleSelectChange}
462
- />
463
- )
464
- }
465
- </div>
466
- </div>
467
- <div
468
- className={classNames(
469
- style['live-description-panel'],
470
- descriptionClassName
471
- )}
472
- >
473
- <div className={style['desc-title']}>开播介绍</div>
474
- <div className={style['desc-content']}>
475
- {!liveInfo.desc_pic_web_url ? '暂无介绍' : (
476
- <img className={style['desc-content-img']} src={netUrl(liveInfo.desc_pic_web_url)} alt="" />
477
- )}
478
- </div>
479
- </div>
480
- </div>
481
- </>
482
- )
483
- }
1
+ /* eslint-disable camelcase */
2
+ import React, { useState, useEffect } from 'react'
3
+ import { Icon } from 'fish'
4
+ import dayjs from 'dayjs'
5
+ import classNames from 'classnames'
6
+ // import Empty from '@/component/Empty'
7
+ import {
8
+ getOpenClassLive
9
+ // getServerTime
10
+ } from '@/service/live'
11
+ import { getIMLiveInfo, getGuestIMLiveInfo } from '@/service/imBroadcasts'
12
+ import Loading from '@/component/status/Loading'
13
+ import {
14
+ PUBLIC_LIVE_STATUS, PUBLIC_LIVE_MODE, SUB_TYPE
15
+ } from '@/config/publicLive'
16
+ import { getUrlQuery } from '@/util/url'
17
+ import { getRecordLiveStatus } from '@/util/live'
18
+ import { isEmpty } from '@/util/object'
19
+ // import IMChatroom from '@/component/IMChatroom'
20
+ import RecordVideo from './RecordVideo'
21
+ import LiveVideo from './LiveVideo'
22
+ import LineSwitch from './LineSwitch'
23
+ import ReplayVideo from './ReplayVideo'
24
+ import style from './index.module.less'
25
+ import LiveOnlineCount from './LiveOnlineCount'
26
+ import { LOGIN_STATUS } from '@/config/constant/user'
27
+ import { USER_IDENTITY_NAME } from '@/config/live'
28
+ // import NotLoginChatroom from './NotLoginChatroom'
29
+ import netUrl from '@/util/netUrl'
30
+ import { ShortUrlMap } from './const'
31
+ import { setUC } from '@/util/auth/func'
32
+ import config from '@/config/env'
33
+
34
+ const TrackPageName = 'edu_Platform_publiclive_detail_page'
35
+
36
+ export default function PublicLiveDetail({
37
+ containerClassName,
38
+ className,
39
+ infoClassName,
40
+ playerClassName,
41
+ descriptionClassName,
42
+ errorCover, // 当直播不存在或者错误时候的封面展示
43
+ errorText,
44
+ replay: propRelay,
45
+ liveId: propLiveId,
46
+ sdpAppId: propSdpAppId,
47
+ uc,
48
+ loginInfo = {},
49
+ handleLogin,
50
+ onOnlineCountChange = () => {},
51
+ onStateChange = () => {},
52
+ onReportProgress = () => {},
53
+ onReportTeacherTrain = () => {},
54
+ onSendSensors = () => {}
55
+ }) {
56
+ setUC(uc, loginInfo?.userInfo)
57
+ if (propSdpAppId) {
58
+ config.app.appid = propSdpAppId
59
+ }
60
+
61
+ const { replay, live_id } = getUrlQuery()
62
+ const matchId = propLiveId || live_id
63
+ const replayMode = propRelay || replay
64
+ const liveId = ShortUrlMap[matchId] || matchId
65
+
66
+ const [liveInfo, setLiveInfo] = useState()
67
+ const [visitTime, setVisitTime] = useState()
68
+ const [diffTime, setDiffTime] = useState()
69
+ const [isReplayMode, setIsReplayMode] = useState(!!replayMode)
70
+ const [isExist, setIsExist] = useState(true)
71
+ const [lineChanging, setLineChanging] = useState(false) // 线路切换中标识
72
+
73
+ const {
74
+ userInfo,
75
+ userRole,
76
+ loginStatus
77
+ } = loginInfo
78
+ const isLiveToReplay = !replay
79
+ const isStreamLive = liveInfo
80
+ && liveInfo.type === PUBLIC_LIVE_MODE.LIVING
81
+
82
+ const handleStatusChange = async (status) => {
83
+ const newLiveInfo = {
84
+ ...liveInfo,
85
+ status
86
+ }
87
+ setLiveInfo(newLiveInfo)
88
+ onStateChange(newLiveInfo)
89
+ const isRecordLive = liveInfo.type === PUBLIC_LIVE_MODE.RECORDED
90
+ if (!isRecordLive
91
+ && [
92
+ PUBLIC_LIVE_STATUS.NOSTARTED,
93
+ PUBLIC_LIVE_STATUS.LIVEING,
94
+ PUBLIC_LIVE_STATUS.PASUED
95
+ ].includes(status)
96
+ && isEmpty(liveInfo.imInfo)
97
+ ) {
98
+ const {
99
+ sub_type: subType,
100
+ bid,
101
+ room_id: roomId
102
+ } = liveInfo
103
+ let imLiveInfoResp = {}
104
+ // 如果类型为外部推流, 则去请求新的直播详情接口
105
+ if (subType === SUB_TYPE.OUTSIDE || subType === SUB_TYPE.REBROADCAST) {
106
+ imLiveInfoResp = await getGuestIMLiveInfo(bid)
107
+ .catch(() => ({}))
108
+
109
+ // 默认使用lines[0] 作为直播源
110
+ imLiveInfoResp = {
111
+ ...imLiveInfoResp,
112
+ param: {
113
+ ...imLiveInfoResp.param,
114
+ ...imLiveInfoResp.param?.lines?.[0]
115
+ }
116
+ }
117
+ } else {
118
+ imLiveInfoResp = await getIMLiveInfo(roomId)
119
+ .catch(() => ({}))
120
+ }
121
+ setLiveInfo({
122
+ ...liveInfo,
123
+ status,
124
+ imInfo: imLiveInfoResp
125
+ })
126
+ }
127
+ }
128
+
129
+ const handleSelectChange = (lineSource) => {
130
+ setLineChanging(true)
131
+ setTimeout(() => {
132
+ setLiveInfo({
133
+ ...liveInfo,
134
+ imInfo: {
135
+ ...liveInfo.imInfo,
136
+ param: {
137
+ ...liveInfo.imInfo.param,
138
+ ...lineSource
139
+ }
140
+ }
141
+ })
142
+ setLineChanging(false)
143
+ }, 0)
144
+ }
145
+
146
+ useEffect(() => {
147
+ const init = async () => {
148
+ const [data, error] = await getOpenClassLive(liveId)
149
+ .then((v) => [v], (err) => [null, err])
150
+ if (error) {
151
+ const { response } = error
152
+ if (response.status === 404 || response.status === 400) {
153
+ setIsExist(false)
154
+ }
155
+ return
156
+ }
157
+
158
+ // 调试代码 模拟直播倒计时结束
159
+ // data.status = PUBLIC_LIVE_STATUS.NOSTARTED
160
+
161
+ const isRecordLive = data.type === PUBLIC_LIVE_MODE.RECORDED
162
+ const isNoStarted = data.status === PUBLIC_LIVE_STATUS.NOSTARTED
163
+ const isCompleted = data.status === PUBLIC_LIVE_STATUS.COMPLETEED
164
+ const isOffline = data.status === PUBLIC_LIVE_STATUS.OFFLINE
165
+
166
+ // 录播未完成或未下架,直播未开始时需要服务器时间
167
+ let serverTime
168
+ if ((isRecordLive && (!isCompleted || !isOffline)) || (!isRecordLive && !isReplayMode && isNoStarted)) {
169
+ // const response = await getServerTime()
170
+ serverTime = data.serverTime
171
+ setDiffTime(data.diffTime)
172
+ setVisitTime(serverTime)
173
+ }
174
+ // 录播计算状态
175
+ if (isRecordLive) {
176
+ const status = getRecordLiveStatus(data.status, serverTime, data.begin_time, data.end_time)
177
+ data.status = status
178
+ }
179
+ if (!isRecordLive) {
180
+ const {
181
+ sub_type: subType,
182
+ bid,
183
+ room_id: roomId
184
+ } = data
185
+ let imLiveInfoResp = {}
186
+ // 如果类型为外部推流, 则去请求新的直播详情接口
187
+ if (subType === SUB_TYPE.OUTSIDE || subType === SUB_TYPE.REBROADCAST) {
188
+ // if (subType === SUB_TYPE.OUTSIDE) {
189
+ imLiveInfoResp = await getGuestIMLiveInfo(bid)
190
+ .catch(() => ({}))
191
+ // 默认使用lines[0] 作为直播源
192
+ imLiveInfoResp = {
193
+ ...imLiveInfoResp,
194
+ param: {
195
+ ...imLiveInfoResp.param,
196
+ ...imLiveInfoResp.param?.lines?.[0]
197
+ }
198
+ }
199
+ } else if (data.status === PUBLIC_LIVE_STATUS.LIVEING) {
200
+ imLiveInfoResp = await getIMLiveInfo(roomId)
201
+ .catch(() => ({}))
202
+ }
203
+ data.imInfo = imLiveInfoResp
204
+ }
205
+ // 如果是转播或者是推流 直接播放(用于调试模式)
206
+ const { preview } = getUrlQuery() // 后台点预览会加这个参数
207
+ const generateInfo = preview ? Object.assign(data, {
208
+ status: 1
209
+ }) : data
210
+ setLiveInfo(generateInfo)
211
+ }
212
+ init()
213
+ }, [])
214
+
215
+ useEffect(() => {
216
+ if (userInfo) {
217
+ onReportProgress()
218
+ }
219
+ }, [userInfo])
220
+
221
+ useEffect(() => {
222
+ if (loginStatus !== LOGIN_STATUS.WAIT && liveInfo) {
223
+ onSendSensors({
224
+ pageName: TrackPageName,
225
+ eventName: 'edu_Platform_publiclive_detail_page',
226
+ params: {
227
+ publiclive_id: liveInfo.live_id,
228
+ publiclive_name: liveInfo.live_name,
229
+ // 1-直播, 2-录播
230
+ publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播',
231
+ identity: userRole
232
+ ? USER_IDENTITY_NAME[userRole]
233
+ : '游客'
234
+ }
235
+ })
236
+ }
237
+ }, [!!userRole, !!liveInfo, loginStatus])
238
+
239
+ if (!isExist) {
240
+ return (
241
+ <div
242
+ className={classNames(
243
+ style['public-live-detail-wrapper'],
244
+ style['live-empty'],
245
+ containerClassName
246
+ )}
247
+ style={{
248
+ backgroundImage: `url(${errorCover})`
249
+ }}
250
+ >
251
+ <div className={style['empty-marker']} />
252
+ <div className={style['empty-content']}>
253
+ {/* eslint-disable-next-line max-len */}
254
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADYAAAA2CAYAAACMRWrdAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAALOSURBVHgB7VqLbeMwDGVugctt4BEygje4bFBv0G5y2SC5Rc4jpBNEneDaLtBXCVIA16asL50U8AMEA7ZF6pG0PqSJVqxYIYkNCQHAVl8a3Xa6/dTt1+Dxs25v5rrZbN7o3qHJtLoddDsjHmfXp6V7gvGMbo+JZHxQuj3QraEHsXeDqQ11E4JaaaNbD3kcjS5aAlrRDmEvmefmu+lgjbAd9N86GXv3ToysHUlCK3hA2MItJcIRPQVky4RmgFSPCiED693TYuScRX14osowMnV79eirE5bOimqG2JEEMKNX1YgOQjj2b0GupxLAzmqxkCJnPgMuLPeUC4+1TPyfFib3xOhSGCwjKcK6uYHfgFzP6EqfuMB7qxm9sxg52O9tjHOqkDZ2sAuT43S1KQIOjIBdosLq5DwGP6QIGB9BVESfpcipkfy4cITdpGZZZQly4KMpPDt63P2bIiFNDvxsHd5mwR4n0jt+lSFGDvzs2I3f+8H05Ui8UAJ0gqbTl7/Mo64COS75MwlFjtgEOZkkKXKeseQRKxhER3KemwVHbGIR5OzJHGqTix1LFDFiXJ2CyuQa5t5kLeOIPTP3WipERXINc++dQkDBAh2D0qUAuQu065y8pUpBCTnkbqlcZ84qLVVEDjnwSaWkTXD0saUEqeRQemxxQrgiQ0OVEUsO/FbqQqkAn2coyw75dQXJed5JT6DCzo6KEVY9QUo0Tw62TFXurYEybqdvUmEiRQLE5TDzvTVS1jNCFYTKO1gqQQvpVDOvc47cpZpe+LOx5p5EUeLRQ+oDtT8DzKe7j6hXRupnSHUkAYRz+ccci8JuCObC778YqcEgUkq1e/f+uFTbOCPFlGovkC7VDgbXIG1qzoEJvX9Yqrg+ImisrlAXhpDxUn6Z6M4IXj1kZsSiE3t1IP+Xoz+ofCyS/knMfPTX6xWvZI/yJgXx8i1+EluxYsUEn1PRdSb/XhDOAAAAAElFTkSuQmCC" alt="" />
255
+ <p>{errorText || '内容已失效'}</p>
256
+ </div>
257
+
258
+ </div>
259
+ )
260
+ }
261
+
262
+ if (!liveInfo) {
263
+ return <Loading />
264
+ }
265
+
266
+ const isRecordLive = liveInfo.type === PUBLIC_LIVE_MODE.RECORDED
267
+ const beginTime = dayjs(liveInfo.begin_time)
268
+
269
+ const handlePlayReplay = (needReport) => {
270
+ if (needReport) {
271
+ onSendSensors({
272
+ pageName: TrackPageName,
273
+ eventName: 'edu_Platform_publiclive_detail_replay_click',
274
+ params: {
275
+ publiclive_id: liveInfo.live_id,
276
+ publiclive_name: liveInfo.live_name,
277
+ // 1-直播, 2-录播
278
+ publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播'
279
+ }
280
+ })
281
+ }
282
+
283
+ setIsReplayMode(true)
284
+ }
285
+
286
+ const handleRequestFullScreen = () => {
287
+ onSendSensors({
288
+ pageName: TrackPageName,
289
+ eventName: 'edu_Platform_publiclive_detail_fullscreen_click'
290
+ })
291
+ }
292
+
293
+ const handleVideoPlay = (needReport) => {
294
+ if (needReport) {
295
+ onSendSensors({
296
+ pageName: TrackPageName,
297
+ eventName: 'edu_Platform_publiclive_detail_play_click',
298
+ params: {
299
+ publiclive_id: liveInfo.live_id,
300
+ publiclive_name: liveInfo.live_name,
301
+ // 1-直播, 2-录播
302
+ publiclive_type: liveInfo.type === 1 ? '实时直播' : '录播直播'
303
+ }
304
+ })
305
+ }
306
+ if (userInfo) {
307
+ // 登录且播放后上报
308
+ onReportTeacherTrain(userInfo?.user_id, liveId)
309
+ }
310
+ }
311
+
312
+ return (
313
+ <>
314
+ <div
315
+ className={classNames(
316
+ style['public-live-detail-wrapper'],
317
+ containerClassName
318
+ )}
319
+ >
320
+ <div
321
+ className={classNames(
322
+ className, style['live-panel']
323
+ )}
324
+ >
325
+ <div className={infoClassName}>
326
+
327
+ <div className={style['live-title']}>
328
+ <div className={style['live-name']}>
329
+ {liveInfo.live_name}
330
+ </div>
331
+ {
332
+ // eslint-disable-next-line no-nested-ternary
333
+ liveInfo.status === PUBLIC_LIVE_STATUS.LIVEING
334
+ ? (
335
+ <LiveOnlineCount
336
+ className={style['live-online-count']}
337
+ resId={liveId}
338
+ onOnlineCountChange={onOnlineCountChange}
339
+ />
340
+ )
341
+ : (
342
+ liveInfo.status === PUBLIC_LIVE_STATUS.COMPLETEED
343
+ ? (<div className={style['live-end']}>已结束</div>)
344
+ : (<></>)
345
+ )
346
+ }
347
+ </div>
348
+ <div className={style['live-info']}>
349
+ {/*
350
+ 暂时隐藏主播
351
+ <div className={classNames(style['live-user'], {
352
+ [style['empty-user']]: !liveInfo.lecture_user_id && !liveInfo.lecture_user_name
353
+ })}
354
+ >
355
+ <Avatar className={style.avatar} src={getAvatarURL(liveInfo.lecture_user_id)} />
356
+ <span title={liveInfo.lecture_user_name}>{liveInfo.lecture_user_name}</span>
357
+ </div> */
358
+ }
359
+ <div className={style['live-time']}>
360
+ <Icon
361
+ className={style['icon-time']}
362
+ type="clock-circle"
363
+ />
364
+ <span>
365
+ {`${beginTime.format(beginTime.isSame(dayjs(), 'day') ? '[今天] HH:mm' : 'YYYY-MM-DD HH:mm')} 开始`}
366
+ </span>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ <div
371
+ className={classNames(style['live-video-wrapper'], playerClassName)}
372
+ >
373
+ <div className={style['live-wrap']}>
374
+ {
375
+ // eslint-disable-next-line no-nested-ternary
376
+ isReplayMode
377
+ ? (
378
+ <ReplayVideo
379
+ handleLogin={handleLogin}
380
+ liveInfo={liveInfo}
381
+ autoplay={isLiveToReplay}
382
+ onVideoPlay={() => {
383
+ handleVideoPlay(false)
384
+ }}
385
+ onRequestFullScreen={handleRequestFullScreen}
386
+ />
387
+ )
388
+ : isRecordLive
389
+ ? (
390
+ <RecordVideo
391
+ isStreamLive={isStreamLive}
392
+ userInfo={userInfo}
393
+ liveInfo={liveInfo}
394
+ visitTime={visitTime}
395
+ diffTime={diffTime}
396
+ onStatusChange={handleStatusChange}
397
+ onPlayReplay={() => {
398
+ handlePlayReplay(true)
399
+ }}
400
+ onVideoPlay={() => {
401
+ handleVideoPlay(true)
402
+ }}
403
+ onRequestFullScreen={handleRequestFullScreen}
404
+ />
405
+ )
406
+ : (
407
+ <LiveVideo
408
+ isStreamLive={isStreamLive}
409
+ handleLogin={handleLogin}
410
+ userInfo={userInfo}
411
+ liveInfo={liveInfo}
412
+ visitTime={visitTime}
413
+ lineChanging={lineChanging}
414
+ onStatusChange={handleStatusChange}
415
+ onPlayReplay={() => {
416
+ handlePlayReplay(true)
417
+ }}
418
+ onVideoPlay={() => {
419
+ handleVideoPlay(true)
420
+ }}
421
+ onRequestFullScreen={handleRequestFullScreen}
422
+ />
423
+ )
424
+ }
425
+ {/* {
426
+ liveInfo?.chat_type && (
427
+ <div className={style['chatroom-wrap']}>
428
+ <div className={style['chatroom-title']}>
429
+ 讨论区
430
+ </div>
431
+ {
432
+ userInfo ? (
433
+ <>
434
+ <div className={style['chatroom-top-hint']}>
435
+ 系统提示:倡导建康的直播环境,若发布违法、违规、低俗等不良消息,我们会对违规内容及帐号进行封禁处理。
436
+ </div>
437
+ <IMChatroom
438
+ roomId={liveInfo.chat_room_id}
439
+ disableEditor={!liveInfo.chat_enabled}
440
+ />
441
+ </>
442
+ ) : (
443
+ <NotLoginChatroom
444
+ handleLogin={handleLogin}
445
+ />
446
+ )
447
+ }
448
+ </div>
449
+ )
450
+ } */}
451
+ </div>
452
+ {
453
+ !isReplayMode && !isRecordLive
454
+ && liveInfo.sub_type !== SUB_TYPE.NET_DRAGON
455
+ && liveInfo.status !== PUBLIC_LIVE_STATUS.COMPLETEED
456
+ && (
457
+ <LineSwitch
458
+ className={style['live-line-switch']}
459
+ liveInfo={liveInfo}
460
+ onChange={handleSelectChange}
461
+ />
462
+ )
463
+ }
464
+ </div>
465
+ </div>
466
+ <div
467
+ className={classNames(
468
+ style['live-description-panel'],
469
+ descriptionClassName
470
+ )}
471
+ >
472
+ <div className={style['desc-title']}>开播介绍</div>
473
+ <div className={style['desc-content']}>
474
+ {!liveInfo.desc_pic_web_url ? '暂无介绍' : (
475
+ <img className={style['desc-content-img']} src={netUrl(liveInfo.desc_pic_web_url)} alt="" />
476
+ )}
477
+ </div>
478
+ </div>
479
+ </div>
480
+ </>
481
+ )
482
+ }