@x-edu/live-player 0.0.19 → 0.0.21

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 (302) hide show
  1. package/.browserslistrc +10 -10
  2. package/.eslintignore +8 -8
  3. package/.eslintrc.js +26 -26
  4. package/.gem-mine +11 -11
  5. package/.postcssrc.js +6 -6
  6. package/README.md +145 -145
  7. package/babel.config.js +33 -33
  8. package/dist/XEduLivePlayer.common.js +12161 -1154
  9. package/dist/XEduLivePlayerPre.common.js +12369 -1358
  10. package/doc/develop.md +23 -23
  11. package/gem-mine.config.js +86 -86
  12. package/jest.config.js +9 -9
  13. package/jsconfig.json +15 -15
  14. package/mock/helper.js +8 -8
  15. package/mock/index.js +34 -34
  16. package/package.json +99 -99
  17. package/public/3rd/ali-player/alipayercomponents-1.0.8.min.js +26 -26
  18. package/public/3rd/ali-player/aliplayer-hls-min.js +27 -27
  19. package/public/3rd/ali-player/aliplayer-min.js +1 -1
  20. package/public/3rd/im-web-push/index.umd.js +14 -14
  21. package/public/JsBridge.js +1602 -1602
  22. package/public/fish/editor/themes/default/css/ueditor.css +1905 -1905
  23. package/public/fish/editor/third-party/codemirror/codemirror.css +104 -104
  24. package/public/fish/editor/third-party/codemirror/codemirror.js +3581 -3581
  25. package/public/fish/editor/third-party/zeroclipboard/ZeroClipboard.js +1255 -1255
  26. package/public/fish/editor/ueditor.all.min.js +16 -16
  27. package/public/fish/editor/ueditor.config.js +467 -467
  28. package/public/fish/icon/umd-4.1.2.js +1 -1
  29. package/public/fish/video/videoplayer.min.css +6 -6
  30. package/public/fish/video/videoplayer.min.js +31 -31
  31. package/public/fish/video/zh-CN.js +82 -82
  32. package/public/icon/demo.css +539 -539
  33. package/public/icon/demo_index.html +2189 -2189
  34. package/public/icon/iconfont.css +363 -363
  35. package/public/icon/iconfont.json +618 -618
  36. package/public/index.html +50 -50
  37. package/script/image/readme.md +77 -77
  38. package/script/postcss.js +48 -48
  39. package/src/App.jsx +24 -24
  40. package/src/asset/img/course/playing.svg +21 -21
  41. package/src/asset/img/icon-course-white.svg +3 -3
  42. package/src/asset/img/icon-course.svg +3 -3
  43. package/src/asset/img/icon-eye-white.svg +4 -4
  44. package/src/asset/img/icon-eye.svg +4 -4
  45. package/src/asset/img/icon-school-white.svg +3 -3
  46. package/src/asset/img/icon-school.svg +3 -3
  47. package/src/asset/img/loading.svg +52 -52
  48. package/src/asset/img/video-play.svg +6 -6
  49. package/src/asset/style/background.less +19 -19
  50. package/src/asset/style/banner.less +36 -36
  51. package/src/asset/style/base.less +74 -74
  52. package/src/asset/style/index.less +114 -114
  53. package/src/asset/style/reset-theme.less +141 -141
  54. package/src/asset/style/theme/index.less +55 -55
  55. package/src/asset/style/theme/party/global.less +20 -20
  56. package/src/asset/style/theme/party/override.less +57 -57
  57. package/src/asset/style/theme/test/global.less +18 -18
  58. package/src/asset/style/theme/test/override.less +45 -45
  59. package/src/asset/style/variable.less +12 -12
  60. package/src/component/AliPlayer/index.jsx +49 -49
  61. package/src/component/Avatar/index.jsx +50 -50
  62. package/src/component/Empty/index.jsx +34 -34
  63. package/src/component/Empty/index.module.less +37 -37
  64. package/src/component/IMChatroom/component/status/403.jsx +13 -13
  65. package/src/component/IMChatroom/component/status/404.jsx +13 -13
  66. package/src/component/IMChatroom/component/status/Error.jsx +23 -23
  67. package/src/component/IMChatroom/component/status/Loading.jsx +5 -5
  68. package/src/component/IMChatroom/config/app/config.js +118 -118
  69. package/src/component/IMChatroom/config/app/index.js +60 -60
  70. package/src/component/IMChatroom/config/env.js +5 -5
  71. package/src/component/IMChatroom/config/index.js +3 -3
  72. package/src/component/IMChatroom/config/request/config/base.js +124 -124
  73. package/src/component/IMChatroom/config/request/config/chatroom.js +26 -26
  74. package/src/component/IMChatroom/config/request/config/imCoreApi.js +21 -21
  75. package/src/component/IMChatroom/config/request/index.js +21 -21
  76. package/src/component/IMChatroom/config/request/proxy.js +39 -39
  77. package/src/component/IMChatroom/config/url.js +7 -7
  78. package/src/component/IMChatroom/constants/errorCode.js +9 -9
  79. package/src/component/IMChatroom/constants/index.js +84 -84
  80. package/src/component/IMChatroom/constants/origin.js +27 -27
  81. package/src/component/IMChatroom/context/chatroom.js +154 -154
  82. package/src/component/IMChatroom/context/connect.js +28 -28
  83. package/src/component/IMChatroom/i18n/en/index.json +73 -73
  84. package/src/component/IMChatroom/i18n/index.jsx +14 -14
  85. package/src/component/IMChatroom/i18n/language.js +9 -9
  86. package/src/component/IMChatroom/i18n/zh-CN/index.json +73 -73
  87. package/src/component/IMChatroom/index.jsx +49 -49
  88. package/src/component/IMChatroom/page/chat/index.jsx +27 -27
  89. package/src/component/IMChatroom/page/chat/messageEditor/index.jsx +375 -375
  90. package/src/component/IMChatroom/page/chat/messageList/index.jsx +354 -354
  91. package/src/component/IMChatroom/page/chat/stickedMessage/index.jsx +59 -59
  92. package/src/component/IMChatroom/page/chat/stickedMessage/style/index.module.less +7 -7
  93. package/src/component/IMChatroom/page/chat/style/index.module.less +51 -51
  94. package/src/component/IMChatroom/page/home/connect/index.jsx +188 -188
  95. package/src/component/IMChatroom/page/home/connect/status.jsx +124 -124
  96. package/src/component/IMChatroom/page/home/context/cmd.jsx +37 -37
  97. package/src/component/IMChatroom/page/home/context/index.jsx +67 -67
  98. package/src/component/IMChatroom/page/home/index.jsx +164 -164
  99. package/src/component/IMChatroom/page/home/notice/index.jsx +123 -123
  100. package/src/component/IMChatroom/page/home/notice/style/index.module.less +49 -49
  101. package/src/component/IMChatroom/page/home/style/index.module.less +110 -110
  102. package/src/component/IMChatroom/page/member/index.jsx +15 -15
  103. package/src/component/IMChatroom/page/member/memberCount/index.jsx +44 -44
  104. package/src/component/IMChatroom/page/member/memberList/index.jsx +121 -121
  105. package/src/component/IMChatroom/page/member/style/index.module.less +2 -2
  106. package/src/component/IMChatroom/sdk/bridge.js +39 -39
  107. package/src/component/IMChatroom/sdk/cs/constants.js +20 -20
  108. package/src/component/IMChatroom/sdk/cs/index.js +101 -101
  109. package/src/component/IMChatroom/sdk/imChatroom.js +15 -15
  110. package/src/component/IMChatroom/sdk/imcore/constants.js +128 -128
  111. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomDestroyed.js +5 -5
  112. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomInfoGetFail.js +5 -5
  113. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedByAdmin.js +5 -5
  114. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedBySelf.js +5 -5
  115. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginFail.js +5 -5
  116. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginSuccess.js +5 -5
  117. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogin.js +5 -5
  118. package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogout.js +5 -5
  119. package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnected.js +5 -5
  120. package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnecting.js +5 -5
  121. package/src/component/IMChatroom/sdk/imcore/emitters/connectionDisconnect.js +5 -5
  122. package/src/component/IMChatroom/sdk/imcore/emitters/index.js +57 -57
  123. package/src/component/IMChatroom/sdk/imcore/emitters/messageReceive.js +36 -36
  124. package/src/component/IMChatroom/sdk/imcore/index.js +178 -178
  125. package/src/component/IMChatroom/sdk/imcore/interceptors/request.js +7 -7
  126. package/src/component/IMChatroom/sdk/imcore/interceptors/response.js +5 -5
  127. package/src/component/IMChatroom/sdk/imcore/plugins/getAuth.js +64 -64
  128. package/src/component/IMChatroom/sdk/imcore/plugins/getConversationId.js +20 -20
  129. package/src/component/IMChatroom/sdk/imcore/plugins/getExtInfo.js +10 -10
  130. package/src/component/IMChatroom/sdk/imcore/plugins/getLoginInfo.js +48 -48
  131. package/src/component/IMChatroom/sdk/imcore/plugins/getPlatformType.js +12 -12
  132. package/src/component/IMChatroom/sdk/imcore/plugins/index.js +22 -22
  133. package/src/component/IMChatroom/sdk/imcore/util/format.js +177 -177
  134. package/src/component/IMChatroom/sdk/imcore/util/parser.js +35 -35
  135. package/src/component/IMChatroom/sdk/oms.js +18 -18
  136. package/src/component/IMChatroom/sdk/uc.js +3 -3
  137. package/src/component/IMChatroom/subscription/channel/app.js +5 -5
  138. package/src/component/IMChatroom/subscription/channel/ctl.js +22 -22
  139. package/src/component/IMChatroom/subscription/channel/member.js +40 -40
  140. package/src/component/IMChatroom/subscription/channel/message.js +13 -13
  141. package/src/component/IMChatroom/subscription/channel/ntf.js +86 -86
  142. package/src/component/IMChatroom/subscription/channel/tel.js +5 -5
  143. package/src/component/IMChatroom/subscription/channel/websocket.js +5 -5
  144. package/src/component/IMChatroom/subscription/event.js +37 -37
  145. package/src/component/IMChatroom/subscription/index.js +19 -19
  146. package/src/component/IMChatroom/util/account.js +8 -8
  147. package/src/component/IMChatroom/util/chatroom.js +255 -255
  148. package/src/component/IMChatroom/util/jsonBigInt.js +5 -5
  149. package/src/component/IMChatroom/util/location.js +12 -12
  150. package/src/component/Icon/index.jsx +16 -16
  151. package/src/component/Icon/index.module.less +2 -2
  152. package/src/component/Pagination/LocalPagination.jsx +27 -27
  153. package/src/component/Pagination/RemotePagination.jsx +32 -32
  154. package/src/component/Pagination/index.jsx +31 -31
  155. package/src/component/Pagination/index.module.less +110 -110
  156. package/src/component/PlayerTip/index.jsx +34 -34
  157. package/src/component/VideoBase/index.jsx +242 -242
  158. package/src/component/VideoBase/style.less +65 -65
  159. package/src/component/VideoBase/utils.js +81 -81
  160. package/src/component/mixin.less +9 -9
  161. package/src/component/status/403.jsx +15 -15
  162. package/src/component/status/404/index.jsx +73 -73
  163. package/src/component/status/404/index.module.less +36 -36
  164. package/src/component/status/Error/error.module.less +13 -13
  165. package/src/component/status/Error/index.jsx +47 -47
  166. package/src/component/status/Loading/img/loading.svg +52 -52
  167. package/src/component/status/Loading/index.jsx +31 -31
  168. package/src/component/status/Loading/index.less +56 -56
  169. package/src/component/status/None/index.jsx +20 -20
  170. package/src/component/status/None/index.module.less +35 -35
  171. package/src/component/status/Status/index.jsx +26 -26
  172. package/src/component/status/Status/index.module.less +8 -8
  173. package/src/config/constant/commonUrl.js +2 -2
  174. package/src/config/constant/user.js +6 -6
  175. package/src/config/context/site-config.js +48 -48
  176. package/src/config/env/index.js +5 -5
  177. package/src/config/env/local/index.js +13 -13
  178. package/src/config/env/ncet-xedu/api.js +175 -175
  179. package/src/config/env/ncet-xedu/app.js +12 -12
  180. package/src/config/env/ncet-xedu/cs.js +8 -8
  181. package/src/config/env/ncet-xedu/index.js +14 -14
  182. package/src/config/env/ncet-xedu/push.js +5 -5
  183. package/src/config/env/preproduction/api.js +144 -144
  184. package/src/config/env/preproduction/app.js +12 -12
  185. package/src/config/env/preproduction/cs.js +8 -8
  186. package/src/config/env/preproduction/index.js +14 -14
  187. package/src/config/env/preproduction/push.js +5 -5
  188. package/src/config/env/product/api.js +113 -113
  189. package/src/config/env/product/app.js +12 -12
  190. package/src/config/env/product/cs.js +5 -5
  191. package/src/config/env/product/index.js +14 -14
  192. package/src/config/env/product/push.js +5 -5
  193. package/src/config/live.js +80 -80
  194. package/src/config/publicLive.js +53 -53
  195. package/src/config/request/assessments.js +24 -24
  196. package/src/config/request/config-center.js +8 -8
  197. package/src/config/request/helper.js +166 -166
  198. package/src/config/request/im-broadcasts.js +12 -12
  199. package/src/config/request/live-activity-gateway.js +8 -8
  200. package/src/config/request/live-activity.js +13 -13
  201. package/src/config/request/raw.js +6 -6
  202. package/src/config/request/x-cloud-web.js +13 -13
  203. package/src/config/request/x-proxy.js +34 -34
  204. package/src/demo/Detail.jsx +11 -11
  205. package/src/demo/List.jsx +64 -64
  206. package/src/demo/index.jsx +17 -17
  207. package/src/detail/LineSwitch/index.jsx +71 -71
  208. package/src/detail/LiveCountDown/index.jsx +44 -44
  209. package/src/detail/LiveCountDown/index.module.less +31 -31
  210. package/src/detail/LiveOnlineCount/img/icon.svg +15 -15
  211. package/src/detail/LiveOnlineCount/index.jsx +68 -68
  212. package/src/detail/LiveOnlineCount/index.module.less +34 -34
  213. package/src/detail/LiveOnlineCount/util.js +74 -74
  214. package/src/detail/LiveStatus/AnchorOnTheWay.jsx +88 -88
  215. package/src/detail/LiveStatus/index.jsx +202 -202
  216. package/src/detail/LiveStatus/index.module.less +192 -192
  217. package/src/detail/LiveVideo/config.js +37 -37
  218. package/src/detail/LiveVideo/index.jsx +188 -188
  219. package/src/detail/LiveVideo/index.module.less +41 -41
  220. package/src/detail/NotLoginChatroom/index.jsx +37 -37
  221. package/src/detail/NotLoginChatroom/index.module.less +46 -46
  222. package/src/detail/RecordVideo/index.jsx +150 -150
  223. package/src/detail/RecordVideo/index.module.less +31 -31
  224. package/src/detail/ReplayVideo/index.jsx +93 -93
  225. package/src/detail/ReplayVideo/index.module.less +65 -65
  226. package/src/detail/const.js +20 -20
  227. package/src/detail/hook/usePullSource.js +82 -82
  228. package/src/detail/hook/usePullState.js +51 -51
  229. package/src/detail/index.jsx +482 -482
  230. package/src/detail/index.module.less +188 -188
  231. package/src/hook/useAsync.js +84 -84
  232. package/src/hook/useGoToPage.js +83 -83
  233. package/src/hook/useInterval.js +28 -28
  234. package/src/hook/useIsMounted.js +17 -17
  235. package/src/hook/useModuleByRole.js +53 -53
  236. package/src/hook/usePageScrollable.js +52 -52
  237. package/src/hook/usePortal.js +83 -83
  238. package/src/hook/useScrollRestore/index.js +32 -32
  239. package/src/hook/useScrollRestore/scrollContext.js +20 -20
  240. package/src/hook/useTrackRef.js +11 -11
  241. package/src/hook/useWindowSize.js +28 -28
  242. package/src/hook/useZoom.js +47 -47
  243. package/src/index.js +10 -10
  244. package/src/lib/getLiveOnlineCount.js +10 -10
  245. package/src/lib/getServiceConfig.js +102 -102
  246. package/src/list/Empty/index.jsx +20 -20
  247. package/src/list/Empty/index.module.less +23 -23
  248. package/src/list/ListItem/Action/index.jsx +98 -98
  249. package/src/list/ListItem/Action/index.module.less +21 -21
  250. package/src/list/ListItem/img/dianzan.svg +4 -0
  251. package/src/list/ListItem/img/play.svg +15 -15
  252. package/src/list/ListItem/img/yiguankan.svg +3 -0
  253. package/src/list/ListItem/index.jsx +24 -1
  254. package/src/list/ListItem/index.module.less +146 -123
  255. package/src/list/index.jsx +80 -0
  256. package/src/list/index.module.less +35 -35
  257. package/src/service/common.js +73 -73
  258. package/src/service/content-mgr.js +73 -73
  259. package/src/service/im-group.js +12 -12
  260. package/src/service/im.js +7 -7
  261. package/src/service/imBroadcasts.js +33 -33
  262. package/src/service/like.js +134 -134
  263. package/src/service/manageApi.js +7 -7
  264. package/src/service/managePortal.js +6 -6
  265. package/src/service/myStudyRecord.js +93 -93
  266. package/src/service/navigation.js +47 -47
  267. package/src/service/ndMeeting.js +10 -10
  268. package/src/service/ndr.js +122 -122
  269. package/src/service/news.js +93 -93
  270. package/src/service/personalCenter.js +270 -270
  271. package/src/service/qualityCourse.js +31 -31
  272. package/src/service/recommend.js +81 -81
  273. package/src/service/school.js +323 -323
  274. package/src/service/search.js +170 -170
  275. package/src/service/site-config.js +7 -7
  276. package/src/service/socialCensor.js +45 -45
  277. package/src/service/specialEdu.js +31 -31
  278. package/src/service/suggestion.js +85 -85
  279. package/src/service/syncClassroom.js +321 -321
  280. package/src/service/tCourse.js +204 -204
  281. package/src/service/tchTraining.js +37 -37
  282. package/src/service/uc.js +45 -45
  283. package/src/util/app.js +1 -1
  284. package/src/util/array.js +3 -3
  285. package/src/util/auth/func.js +57 -57
  286. package/src/util/date.js +53 -53
  287. package/src/util/env.js +9 -9
  288. package/src/util/getTimestamp.js +10 -10
  289. package/src/util/hof.js +105 -105
  290. package/src/util/live/index.js +42 -42
  291. package/src/util/liveCountUtil.js +52 -0
  292. package/src/util/netUrl.js +35 -35
  293. package/src/util/object.js +13 -13
  294. package/src/util/push/index.js +58 -58
  295. package/src/util/request.js +227 -227
  296. package/src/util/type.js +17 -17
  297. package/src/util/url.js +203 -203
  298. package/src/util/video.js +26 -26
  299. package/test/setup.js +21 -21
  300. package/test/unit/component/header/logo.spec.jsx +8 -8
  301. package/test/unit/helper.jsx +25 -25
  302. package/test/unit/util/date.spec.js +40 -40
@@ -1,482 +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
- 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
- }
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
+ }