@x-edu/live-player 0.0.10 → 0.0.11
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.
- package/.gem-mine +11 -11
- package/README.md +41 -1
- package/dist/XEduLivePlayer.common.js +48865 -25596
- package/dist/XEduLivePlayerPre.common.js +49071 -25802
- package/package.json +1 -1
- package/public/JsBridge.js +1602 -1602
- package/src/App.jsx +3 -1
- package/src/component/Avatar/index.jsx +1 -3
- package/src/component/Icon/index.jsx +16 -0
- package/src/component/Icon/index.module.less +3 -0
- package/src/component/Pagination/LocalPagination.jsx +27 -0
- package/src/component/Pagination/RemotePagination.jsx +32 -0
- package/src/component/Pagination/index.jsx +31 -0
- package/src/component/Pagination/index.module.less +110 -0
- package/src/config/request/live-activity.js +1 -1
- package/src/demo/Detail.jsx +11 -0
- package/src/demo/List.jsx +62 -0
- package/src/demo/index.jsx +17 -0
- package/src/index.js +2 -7
- package/src/list/Empty/img/empty.png +0 -0
- package/src/list/Empty/index.jsx +20 -0
- package/src/list/Empty/index.module.less +23 -0
- package/src/list/ListItem/Action/index.jsx +98 -0
- package/src/list/ListItem/Action/index.module.less +22 -0
- package/src/list/ListItem/img/live.png +0 -0
- package/src/list/ListItem/img/play.svg +16 -0
- package/src/list/ListItem/index.jsx +95 -0
- package/src/list/ListItem/index.module.less +123 -0
- package/src/list/index.jsx +150 -0
- package/src/list/index.module.less +36 -0
- package/src/service/live.js +57 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
padding: 24px 0;
|
|
3
|
+
margin: 0 24px;
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: flex-start;
|
|
6
|
+
border-top: 1px solid #eee;
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
|
|
9
|
+
&:first-child {
|
|
10
|
+
border-top: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.left {
|
|
14
|
+
margin-right: 24px;
|
|
15
|
+
border-radius: 8px;
|
|
16
|
+
position: relative;
|
|
17
|
+
|
|
18
|
+
.avatar {
|
|
19
|
+
width: 204px;
|
|
20
|
+
height: 120px;
|
|
21
|
+
border-radius: 4px;
|
|
22
|
+
object-fit: cover;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.tag {
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 0px;
|
|
28
|
+
border-radius: 4px 0px;
|
|
29
|
+
font-size: 12px;
|
|
30
|
+
line-height: 12px;
|
|
31
|
+
height: 20px;
|
|
32
|
+
padding: 0 8px;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
color: #fff;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.tag0 { // 预告
|
|
39
|
+
background-color: #FF7826;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.tag1 { // 直播中
|
|
43
|
+
background-color: #1E62EC;
|
|
44
|
+
padding: 0 5px;
|
|
45
|
+
|
|
46
|
+
img {
|
|
47
|
+
transform: rotate(180deg);
|
|
48
|
+
height: 10px;
|
|
49
|
+
width: 10px;
|
|
50
|
+
margin-right: 5px;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.tag2 { // 回放
|
|
55
|
+
background-color: rgba(0, 0, 0, 0.60);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.right {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
justify-content: space-between;
|
|
63
|
+
width: calc(100% - 228px);
|
|
64
|
+
|
|
65
|
+
&-top {
|
|
66
|
+
.title {
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
text-overflow: ellipsis;
|
|
69
|
+
display: -webkit-box;
|
|
70
|
+
-webkit-box-orient: vertical;
|
|
71
|
+
word-wrap: break-word;
|
|
72
|
+
line-height: 28px;
|
|
73
|
+
-webkit-line-clamp: 2;
|
|
74
|
+
font-size: 20px;
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
color: #333;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&-bottom {
|
|
81
|
+
display: flex;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
align-items: center;
|
|
84
|
+
|
|
85
|
+
.time {
|
|
86
|
+
font-size: 14px;
|
|
87
|
+
color: #999;
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
&-icon {
|
|
91
|
+
width: 16px;
|
|
92
|
+
height: 16px;
|
|
93
|
+
color: #ccc;
|
|
94
|
+
margin-right: 4px;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.container:hover {
|
|
102
|
+
.title {
|
|
103
|
+
color: #1E62EC;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.action {
|
|
108
|
+
font-size: 14px;
|
|
109
|
+
line-height: 22px;
|
|
110
|
+
color: #1E62EC;
|
|
111
|
+
border-radius: 144.889px;
|
|
112
|
+
border: 1px solid #1E62EC;
|
|
113
|
+
width: 88px;
|
|
114
|
+
height: 32px;
|
|
115
|
+
display: flex;
|
|
116
|
+
align-items: center;
|
|
117
|
+
justify-content: center;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.action-subscribe {
|
|
121
|
+
background: #1E62EC;
|
|
122
|
+
color: #fff;
|
|
123
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import classNames from 'classnames'
|
|
3
|
+
import { Tabs } from 'fish'
|
|
4
|
+
import { OpenLiveSearchFront, getSubscription } from '@/service/live'
|
|
5
|
+
import { setUC } from '@/util/auth/func'
|
|
6
|
+
import config from '@/config/env'
|
|
7
|
+
import Loading from '@/component/status/Loading'
|
|
8
|
+
import Empty from './Empty'
|
|
9
|
+
import Pagination from '@/component/Pagination'
|
|
10
|
+
import ListItem from './ListItem'
|
|
11
|
+
import style from './index.module.less'
|
|
12
|
+
|
|
13
|
+
const PageSize = 7
|
|
14
|
+
|
|
15
|
+
const StatusEnum = [
|
|
16
|
+
{
|
|
17
|
+
label: '全部',
|
|
18
|
+
value: 'all'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: '直播中',
|
|
22
|
+
value: 1
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: '预告',
|
|
26
|
+
value: 0
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: '回放',
|
|
30
|
+
value: 2
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
export default function PublicLiveList({
|
|
35
|
+
scopeType,
|
|
36
|
+
scopeId,
|
|
37
|
+
containerClassName,
|
|
38
|
+
uc,
|
|
39
|
+
loginInfo,
|
|
40
|
+
sdpAppId: propSdpAppId,
|
|
41
|
+
onDetailClick,
|
|
42
|
+
handleLogin = () => {},
|
|
43
|
+
onSubscribe = () => {}
|
|
44
|
+
}) {
|
|
45
|
+
setUC(uc, loginInfo?.userInfo)
|
|
46
|
+
if (propSdpAppId) {
|
|
47
|
+
config.app.appid = propSdpAppId
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const [list, setList] = useState([])
|
|
51
|
+
const [total, setTotal] = useState(0)
|
|
52
|
+
const [loading, setLoading] = useState(true)
|
|
53
|
+
const [page, setPage] = useState(1)
|
|
54
|
+
const [status, setStatus] = useState('all')
|
|
55
|
+
const [subscription, setSubscription] = useState([])
|
|
56
|
+
const [isLogin, setIsLogin] = useState(false)
|
|
57
|
+
|
|
58
|
+
const handleTabChange = (value) => {
|
|
59
|
+
setStatus(value)
|
|
60
|
+
setPage(1)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const handlePageChange = (value) => {
|
|
64
|
+
setPage(value)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 分页获取直播列表
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
async function getList() {
|
|
70
|
+
setLoading(true)
|
|
71
|
+
const data = await OpenLiveSearchFront({
|
|
72
|
+
status,
|
|
73
|
+
scopeType,
|
|
74
|
+
scopeId,
|
|
75
|
+
offset: (page - 1) * PageSize,
|
|
76
|
+
limit: PageSize
|
|
77
|
+
})
|
|
78
|
+
const { items, count } = data
|
|
79
|
+
if (uc) {
|
|
80
|
+
const curIsLogin = await uc.isLogin()
|
|
81
|
+
if (curIsLogin) {
|
|
82
|
+
const curSubscription = await getSubscription()
|
|
83
|
+
setSubscription(curSubscription)
|
|
84
|
+
setIsLogin(true)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
setList(items)
|
|
88
|
+
setTotal(count)
|
|
89
|
+
setLoading(false)
|
|
90
|
+
}
|
|
91
|
+
getList()
|
|
92
|
+
}, [page, status])
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div
|
|
96
|
+
className={classNames(
|
|
97
|
+
containerClassName,
|
|
98
|
+
style.container
|
|
99
|
+
)}
|
|
100
|
+
>
|
|
101
|
+
<Tabs
|
|
102
|
+
accessKey={status}
|
|
103
|
+
onChange={handleTabChange}
|
|
104
|
+
>
|
|
105
|
+
{StatusEnum.map((item) => (
|
|
106
|
+
<Tabs.TabPane
|
|
107
|
+
key={item.value}
|
|
108
|
+
tab={item.label}
|
|
109
|
+
>
|
|
110
|
+
<Loading
|
|
111
|
+
loading={loading}
|
|
112
|
+
>
|
|
113
|
+
<div className={style.list}>
|
|
114
|
+
{loading ? null : (
|
|
115
|
+
<>
|
|
116
|
+
{!loading && list.length ? (
|
|
117
|
+
<>
|
|
118
|
+
{list.map((listItem) => (
|
|
119
|
+
<ListItem
|
|
120
|
+
data={listItem}
|
|
121
|
+
key={listItem.live_id}
|
|
122
|
+
subscription={subscription}
|
|
123
|
+
onDetailClick={onDetailClick}
|
|
124
|
+
handleLogin={handleLogin}
|
|
125
|
+
isLogin={isLogin}
|
|
126
|
+
onSubscribe={onSubscribe}
|
|
127
|
+
/>
|
|
128
|
+
))}
|
|
129
|
+
<Pagination
|
|
130
|
+
total={total}
|
|
131
|
+
pageSize={PageSize}
|
|
132
|
+
current={page}
|
|
133
|
+
onChange={handlePageChange}
|
|
134
|
+
/>
|
|
135
|
+
</>
|
|
136
|
+
) : (
|
|
137
|
+
<Empty
|
|
138
|
+
tip="暂无内容"
|
|
139
|
+
/>
|
|
140
|
+
)}
|
|
141
|
+
</>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
</Loading>
|
|
145
|
+
</Tabs.TabPane>
|
|
146
|
+
))}
|
|
147
|
+
</Tabs>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
max-width: 1300px;
|
|
3
|
+
margin: 0 auto;
|
|
4
|
+
padding: 24px 24px 0px 24px;
|
|
5
|
+
width: 956px;
|
|
6
|
+
|
|
7
|
+
:global {
|
|
8
|
+
.fish-tabs-nav {
|
|
9
|
+
margin-bottom: 24px;
|
|
10
|
+
}
|
|
11
|
+
.fish-tabs-nav::before {
|
|
12
|
+
display: none;
|
|
13
|
+
}
|
|
14
|
+
.fish-tabs-ink-bar {
|
|
15
|
+
display: none;
|
|
16
|
+
}
|
|
17
|
+
.fish-tabs-tab + .fish-tabs-tab {
|
|
18
|
+
margin-left: 0px;
|
|
19
|
+
}
|
|
20
|
+
.fish-tabs-tab {
|
|
21
|
+
padding: 9px 20px;
|
|
22
|
+
}
|
|
23
|
+
.fish-tabs-tab-btn {
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
line-height: 14px;
|
|
26
|
+
color: #666
|
|
27
|
+
}
|
|
28
|
+
.fish-tabs-tab-active {
|
|
29
|
+
border-radius: 16px;
|
|
30
|
+
background: var(--f-3-f-7-ff, #F3F7FF);
|
|
31
|
+
.fish-tabs-tab-btn {
|
|
32
|
+
color: #1E62EC;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/service/live.js
CHANGED
|
@@ -234,3 +234,60 @@ export async function getLiveInfo(ids) {
|
|
|
234
234
|
return result.map((res) => res.data)
|
|
235
235
|
// return result?.data || {}
|
|
236
236
|
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 查询直播列表-前台
|
|
240
|
+
*/
|
|
241
|
+
export async function OpenLiveSearchFront({
|
|
242
|
+
status,
|
|
243
|
+
scopeType,
|
|
244
|
+
scopeId,
|
|
245
|
+
offset,
|
|
246
|
+
limit
|
|
247
|
+
}) {
|
|
248
|
+
try {
|
|
249
|
+
const url = '/v1/open_class_lives/search_front'
|
|
250
|
+
const response = await proxyApi.get(url, {
|
|
251
|
+
params: {
|
|
252
|
+
status: status === 'all' ? undefined : status,
|
|
253
|
+
scope_type: scopeType,
|
|
254
|
+
scope_id: scopeId,
|
|
255
|
+
offset,
|
|
256
|
+
limit
|
|
257
|
+
}
|
|
258
|
+
})
|
|
259
|
+
return response?.data || {
|
|
260
|
+
count: 0,
|
|
261
|
+
items: []
|
|
262
|
+
}
|
|
263
|
+
} catch (_) {
|
|
264
|
+
return {
|
|
265
|
+
count: 0,
|
|
266
|
+
items: []
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* 获取预约直播
|
|
273
|
+
*/
|
|
274
|
+
export async function getSubscription() {
|
|
275
|
+
try {
|
|
276
|
+
const url = '/v1/open_class_lives/actions/get_subscription'
|
|
277
|
+
const response = await liveActivityAPI.get(url)
|
|
278
|
+
return response.data
|
|
279
|
+
} catch (_) {
|
|
280
|
+
return []
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 预约直播
|
|
286
|
+
*/
|
|
287
|
+
export async function openLiveSubscribe({
|
|
288
|
+
liveId
|
|
289
|
+
}) {
|
|
290
|
+
const url = `/v1/open_class_lives/${liveId}/actions/subscribe`
|
|
291
|
+
const response = await liveActivityAPI.post(url)
|
|
292
|
+
return response?.data
|
|
293
|
+
}
|