Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xiaomai-cloud-class-web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xiaomai-cloud-class
xiaomai-cloud-class-web
Commits
9c1ae54a
Commit
9c1ae54a
authored
Jan 18, 2021
by
zhangleyuan
Browse files
Options
Browse Files
Download
Plain Diff
feat:解决合并代码后的冲突
parents
cb19a47f
0625e798
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
812 additions
and
435 deletions
+812
-435
package-lock.json
+0
-0
src/bu-components/ShareLiveModal.jsx
+0
-1
src/common/js/axios.ts
+3
-3
src/components/DownloadLiveModal.jsx
+13
-28
src/components/ImgCutModalNew.jsx
+2
-0
src/components/MultipleDatePicker.jsx
+2
-2
src/data-source/base/request-apis.ts
+4
-1
src/domains/basic-domain/baseService.ts
+6
-2
src/domains/basic-domain/constants.ts
+4
-4
src/domains/course-domain/constants.ts
+7
-4
src/index.html
+2
-2
src/modules/common/DateRangePicker.jsx
+1
-2
src/modules/course-manage/AddLive.jsx
+17
-31
src/modules/course-manage/DataList/CourseData.jsx
+2
-2
src/modules/course-manage/DataList/DataList.less
+3
-0
src/modules/course-manage/components/AddLiveBasic.jsx
+26
-18
src/modules/course-manage/components/AddLiveClass.jsx
+80
-42
src/modules/course-manage/components/AddLiveIntro.jsx
+16
-12
src/modules/course-manage/components/LiveCourseFilter.jsx
+23
-6
src/modules/course-manage/components/LiveCourseList.jsx
+372
-190
src/modules/course-manage/components/LiveCourseList.less
+10
-2
src/modules/course-manage/components/LiveCourseOpt.jsx
+21
-18
src/modules/course-manage/modal/ManageCoursewareModal.jsx
+2
-2
src/modules/course-manage/modal/PreviewCourseModal.jsx
+23
-10
src/modules/course-manage/modal/ShareLiveModal.jsx
+23
-5
src/modules/course-manage/modal/ShareLiveModal.less
+5
-0
src/modules/course-manage/video-course/AddVideoCourse.jsx
+48
-21
src/modules/course-manage/video-course/components/VideoCourseFilter.jsx
+17
-3
src/modules/course-manage/video-course/components/VideoCourseList.jsx
+41
-13
src/modules/course-manage/video-course/components/VideoCourseList.less
+16
-3
src/modules/prepare-lesson/modal/SelectPrepareFileModal.jsx
+11
-1
src/modules/root/Login.jsx
+1
-1
src/modules/store-manage/StoreH5DecorationTab.jsx
+6
-3
src/modules/store-manage/StoreWebDecorationTab.jsx
+5
-3
No files found.
package-lock.json
0 → 100644
View file @
9c1ae54a
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/bu-components/ShareLiveModal.jsx
View file @
9c1ae54a
...
...
@@ -117,7 +117,6 @@ class ShareLiveModal extends React.Component {
>
{
`【${courseName}】开课啦,快来学习!`
}
</
div
>
<
img
src=
{
coverImgSrc
}
crossOrigin=
"*"
className=
"course-cover"
alt=
"course-cover"
/>
...
...
src/common/js/axios.ts
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-31 09:34:31
* @LastEditors: zhangleyuan
* @LastEditTime: 202
0-12-22 15:24:03
* @LastEditTime: 202
1-01-09 14:39:46
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -27,7 +27,7 @@ interface HeadersType{
storeId
?:
any
,
storeUserId
?:
any
,
userId
?:
any
,
token
?:
any
xm
token
?:
any
}
class
Axios
{
static
post
(
...
...
@@ -49,7 +49,7 @@ class Axios {
headerObject
.
userId
=
User
.
getUserId
();
}
if
(
User
.
getToken
()){
headerObject
.
token
=
User
.
getToken
();
headerObject
.
xm
token
=
User
.
getToken
();
}
const
instance
:
AxiosInstance
=
axios
.
create
({
timeout
:
TIME_OUT
,
...
...
src/components/DownloadLiveModal.jsx
View file @
9c1ae54a
import
React
from
'react'
import
React
from
'react'
;
import
{
Modal
,
Button
}
from
"antd"
;
import
"./DownloadLiveModal.less"
...
...
@@ -12,37 +13,12 @@ class DownloadLiveModal extends React.Component {
type
:
'pre'
,
}
}
downloadLiveClient
(){
if
(
type
===
'pre'
)
{
const
isMac
=
/macintosh|mac os x/i
.
test
(
navigator
.
userAgent
);
if
(
isMac
){
Modal
.
info
({
title
:
"抱歉,暂不支持Mac版"
,
content
:
"Mac版正在开发中,敬请期待"
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
okText
:
'我知道了'
});
return
;
}
url
&&
window
.
open
(
url
);
this
.
setState
({
image
:
'https://image.xiaomaiketang.com/xm/wPwRdaa7MM.png'
,
tip
:
'安装完成后,再次打开即可开始直播。'
,
text
:
'我知道了'
,
type
:
'finish'
,
})
}
else
{
this
.
props
.
onCancel
();
}
}
render
()
{
const
{
url
}
=
this
.
props
;
const
{
image
,
tip
,
text
,
type
}
=
this
.
state
;
return
<
Modal
visible=
{
true
}
maskClosable=
{
false
}
title=
"下载客户端"
className=
"download-live-modal"
footer=
{
null
}
...
...
@@ -56,8 +32,17 @@ class DownloadLiveModal extends React.Component {
type=
"primary"
className=
"download-button"
onClick=
{
()
=>
{
if
(
type
===
'pre'
)
{
url
&&
window
.
open
(
url
);
this
.
setState
({
image
:
'https://image.xiaomaiketang.com/xm/wPwRdaa7MM.png'
,
tip
:
'安装完成后,再次打开即可开始直播。'
,
text
:
'我知道了'
,
type
:
'finish'
,
})
}
else
{
this
.
props
.
onCancel
();
}
}
}
>
{
text
}
</
Button
>
</
Modal
>
...
...
src/components/ImgCutModalNew.jsx
View file @
9c1ae54a
...
...
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import
{
Modal
,
Button
}
from
'antd'
;
import
Service
from
'@/common/js/service'
;
import
User
from
'@/common/js/user'
;
import
PhotoClip
from
'photoclip'
let
cutFlag
=
false
;
class
ImgCutModalNew
extends
React
.
Component
{
...
...
@@ -66,6 +67,7 @@ class ImgCutModalNew extends React.Component {
})
}
};
if
(
!
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
'#imgCutModalNew'
,
options
);
_photoclip
.
load
(
imageFile
);
...
...
src/components/MultipleDatePicker.jsx
View file @
9c1ae54a
...
...
@@ -9,7 +9,6 @@ import React from 'react'
import
{
message
}
from
"antd"
;
import
moment
from
'moment'
;
require
(
"./MultipleDatePicker.less"
);
class
MultipleDatePicker
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
...
...
@@ -245,13 +244,14 @@ class MultipleDatePicker extends React.Component {
</
div
>
)
}
<
ul
className=
"week"
>
<
li
>
日
</
li
>
<
li
>
一
</
li
>
<
li
>
二
</
li
>
<
li
>
三
</
li
>
<
li
>
四
</
li
>
<
li
>
五
</
li
>
<
li
>
六
</
li
>
<
li
>
日
</
li
>
</
ul
>
<
ul
className=
"calendar"
id=
"multiCalendar"
>
{
this
.
state
.
calendar
}
...
...
src/data-source/base/request-apis.ts
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2020-12-01 17:21:21
* @LastEditors: zhangleyuan
* @LastEditTime: 202
0-12-22 15:39:00
* @LastEditTime: 202
1-01-09 11:06:42
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -38,6 +38,9 @@ export function sendNewPhoneAuthCode(params: object) {
export
function
editUserPhone
(
params
:
object
)
{
return
Service
.
Hades
(
"public/hades/editUserPhone"
,
params
);
}
export
function
getLastedVersion
(
params
:
object
)
{
return
Service
.
Hades
(
"public/hades/getLastedVersion"
,
params
);
}
export
const
getOssClient
=
(
data
:
object
,
instId
:
string
,
...
...
src/domains/basic-domain/baseService.ts
View file @
9c1ae54a
...
...
@@ -2,12 +2,12 @@
* @Author: wufan
* @Date: 2020-12-01 17:20:49
* @LastEditors: zhangleyuan
* @LastEditTime: 202
0-12-11 11:36:19
* @LastEditTime: 202
1-01-09 11:08:02
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
{
getUserStore
,
getUserPermission
,
logout
,
getStoreUser
,
sendBizAuthCode
,
editUserPhone
,
checkBizAuthCode
,
sendNewPhoneAuthCode
,
sendLoginAuthCode
,
login
}
from
'@/data-source/base/request-apis'
;
import
{
getUserStore
,
getUserPermission
,
logout
,
getStoreUser
,
sendBizAuthCode
,
editUserPhone
,
checkBizAuthCode
,
sendNewPhoneAuthCode
,
sendLoginAuthCode
,
login
,
getLastedVersion
}
from
'@/data-source/base/request-apis'
;
export
default
class
StoreService
{
// 获取员工列表
...
...
@@ -46,4 +46,7 @@ export default class StoreService {
static
login
(
params
:
any
){
return
login
(
params
);
}
static
getLastedVersion
(
params
:
any
){
return
getLastedVersion
(
params
);
}
}
\ No newline at end of file
src/domains/basic-domain/constants.ts
View file @
9c1ae54a
/*
* @Author: 陈剑宇
* @Date: 2020-05-07 14:43:01
* @LastEditTime: 202
0-12-26 14:10:34
* @LastEditTime: 202
1-01-18 21:05:12
* @LastEditors: zhangleyuan
* @Description:
* @FilePath: /wheat-web-demo/src/domains/basic-domain/constants.ts
...
...
@@ -9,7 +9,7 @@
import
{
MapInterface
}
from
'@/domains/basic-domain/interface'
// 默认是 dev 环境
const
ENV
:
string
=
process
.
env
.
DEPLOY_ENV
||
'
dev
'
;
const
ENV
:
string
=
process
.
env
.
DEPLOY_ENV
||
'
prod
'
;
console
.
log
(
"process.env.DEPLOY_ENV"
,
process
)
const
BASIC_HOST_MAP
:
MapInterface
=
{
dev
:
'https://dev-heimdall.xiaomai5.com/'
,
...
...
@@ -25,5 +25,6 @@ export const USER_TYPE: string = 'B';
export
const
PROJECT
=
'xmzj-web-b'
;
export
const
VERSION
=
'5.4.8'
;
export
const
PREFIX
=
'cloud-class'
;
// host
export
const
BASIC_HOST
:
string
=
BASIC_HOST_MAP
[
ENV
];
\ No newline at end of file
export
const
BASIC_HOST
:
string
=
BASIC_HOST_MAP
[
ENV
];
src/domains/course-domain/constants.ts
View file @
9c1ae54a
/*
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors:
wuf
an
* @LastEditTime: 2021-01-
06 21:16:34
* @LastEditors:
zhangleyu
an
* @LastEditTime: 2021-01-
18 21:05:31
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
{
MapInterface
}
from
'@/domains/basic-domain/interface'
const
ENV
:
string
=
process
.
env
.
DEPLOY_ENV
||
'
dev
'
;
const
ENV
:
string
=
process
.
env
.
DEPLOY_ENV
||
'
prod
'
;
const
appIdMap
:
MapInterface
=
{
dev
:
'wx3ea60e78ddfa277e'
,
...
...
@@ -25,7 +25,7 @@ const shareUrlMap: MapInterface = {
'gray'
:
'https://prod.xiaomai5.com/share/show?appid='
}
const
LIVE_SHARE_MAP
:
MapInterface
=
{
const
LIVE_SHARE_MAP
:
MapInterface
=
{
dev
:
'https://dev.xiaomai5.com/store-live/index.html#/'
,
dev1
:
'https://dev.xiaomai5.com/store-live/index.html#/'
,
rc
:
'https://rc.xiaomai5.com/store-live/index.html#/'
,
...
...
@@ -33,6 +33,9 @@ const shareUrlMap: MapInterface = {
prod
:
'https://res.xiaomai0.com/store-live/index.html#/'
,
}
export
const
appId
:
string
=
appIdMap
[
ENV
];
export
const
shareUrl
:
string
=
shareUrlMap
[
ENV
];
export
const
LIVE_SHARE
:
string
=
LIVE_SHARE_MAP
[
ENV
];
src/index.html
View file @
9c1ae54a
<!--
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors:
wuf
an
* @LastEditTime: 2021-01-12 1
3:52:23
* @LastEditors:
zhangleyu
an
* @LastEditTime: 2021-01-12 1
5:26:36
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
...
...
src/modules/common/DateRangePicker.jsx
View file @
9c1ae54a
...
...
@@ -13,13 +13,12 @@ class DateRangePicker extends React.Component {
}
render
()
{
const
showTime
=
{
showTime
:
tru
e
}
const
showTime
=
{
showTime
:
fals
e
}
return
(
<
RangePicker
{
...
this
.
props
}
format=
{
this
.
props
.
format
||
'YYYY-MM-DD'
}
allowClear=
{
this
.
props
.
allowClear
}
ranges=
{
this
.
props
.
ranges
||
{
'本月'
:
[
moment
().
startOf
(
'month'
),
moment
().
endOf
(
'month'
)],
'本周'
:
[
moment
().
startOf
(
'week'
),
moment
().
endOf
(
'week'
)],
'上月'
:
[
moment
().
subtract
(
1
,
'M'
).
startOf
(
'month'
),
moment
().
subtract
(
1
,
'M'
).
endOf
(
'month'
)],
'上周'
:
[
moment
().
subtract
(
1
,
'w'
).
startOf
(
'week'
),
moment
().
subtract
(
1
,
'w'
).
endOf
(
'week'
)]
}
}
onChange=
{
(
date
)
=>
{
if
(
!
_
.
isEmpty
(
date
))
{
date
[
0
]
=
date
[
0
].
startOf
(
'day'
)
...
...
src/modules/course-manage/AddLive.jsx
View file @
9c1ae54a
...
...
@@ -82,6 +82,8 @@ class AddLive extends React.Component {
teacherId
:
null
,
teacherName
:
null
,
assistant
:[],
assistantStoreUserId
:[],
assistantNames
:[],
liveDate
:
null
,
timeHorizonStart
:
null
,
timeHorizonEnd
:
null
,
...
...
@@ -169,6 +171,8 @@ class AddLive extends React.Component {
const
timeHorizonStart
=
startTime
;
const
timeHorizonEnd
=
endTime
;
const
assistant
=
_
.
pluck
(
admins
,
"adminId"
);
const
assistantStoreUserId
=
_
.
pluck
(
admins
,
"adminStoreUserId"
);
//编辑时的选中的助教的查询用storeUserId查询
const
assistantNames
=
_
.
pluck
(
admins
,
"adminName"
);
const
addLiveClassInfo
=
{
assistant
,
liveDate
,
...
...
@@ -179,6 +183,8 @@ class AddLive extends React.Component {
timeHorizonEnd
,
startTime
,
endTime
,
assistantNames
,
assistantStoreUserId
}
// liveCourseMediaRequests = liveCourseMediaRequests.length
...
...
@@ -220,16 +226,21 @@ handleChangeBasicInfo = (field, value) => {
}
// 修改上课信息
handleChangeClassInfo
=
(
field
,
value
,
_teacherNam
e
)
=>
{
handleChangeClassInfo
=
(
field
,
value
,
type
,
optionValu
e
)
=>
{
const
_value
=
value
?
value
.
valueOf
()
:
null
;
const
{
teacherName
}
=
this
.
state
.
addLiveClassInfo
;
const
{
assistantNames
}
=
this
.
state
.
addLiveClassInfo
;
const
{
assistantStoreUserId
}
=
this
.
state
.
addLiveClassInfo
this
.
setState
({
addLiveClassInfo
:
{
...
this
.
state
.
addLiveClassInfo
,
[
field
]:
_value
,
teacherName
:
_teacherName
?
_teacherName
:
teacherName
[
field
]:
_value
,
teacherName
:
type
===
'teacherType'
?
optionValue
:
teacherName
,
assistantNames
:
type
===
'assistantType'
?
_
.
pluck
(
optionValue
,
"children"
):
assistantNames
,
assistantStoreUserId
:
type
===
'assistantType'
?
_
.
pluck
(
optionValue
,
"key"
):
assistantStoreUserId
,
}
});
// 批量开始时间改变,结束时间自动同步一致
if
(
field
===
'startTime'
)
{
this
.
setState
({
...
...
@@ -388,7 +399,7 @@ handleChangeBasicInfo = (field, value) => {
message
.
warning
(
'请选择上课日期'
);
resolve
(
false
);
return
;
}
else
if
(
startTime
===
endTime
)
{
}
else
if
(
startTime
===
endTime
||
startTime
>
endTime
)
{
message
.
warning
(
'结束时间必须晚于开始时间'
);
resolve
(
false
);
return
;
...
...
@@ -444,36 +455,11 @@ handleChangeBasicInfo = (field, value) => {
}
}
if
(
!
teacherId
){
message
.
warning
(
'
上课老师不能为空
'
);
message
.
warning
(
'
请选择讲师
'
);
resolve
(
false
);
return
;
}
resolve
(
true
)
// if(!teacherId) {
// message.warning('上课老师不能为空');
// resolve(false);
// return;
// } else if(!applyMode) {
// message.warning('请选择分享设置');
// resolve(false);
// return;
// } else {
// const textIntro = liveCourseMediaRequests.filter(item => { return item.mediaType === 'TEXT'; });
// for (let i = 0, len = textIntro.length; i < len; i++) {
// if (textIntro[i].mediaContent && textIntro[i].mediaContentLength.length > 1000) {
// message.warning(`第${i+1}个文字简介的字数超过了1000个字`);
// resolve(false);
// return;
// }
// }
// }
// if(window.NewVersion && type === 'add') {
// this.handleValidateLackConsumeModal(consumeHourNum, calendarTime, consumeStudentList).then(res => {
// resolve(res)
// })
// } else {
// resolve(true);
// }
});
}
...
...
@@ -537,7 +523,7 @@ handleChangeBasicInfo = (field, value) => {
/>
<
div
className=
"box"
>
<
div
className=
"show-tips"
>
<
ShowTips
message=
"请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦
助教
保有依据国家规定及平台规则进行处理的权利"
/>
<
ShowTips
message=
"请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦
企培
保有依据国家规定及平台规则进行处理的权利"
/>
</
div
>
<
div
className=
"add-live-page__form"
>
<
div
className=
"basic-info__wrap"
>
...
...
src/modules/course-manage/DataList/CourseData.jsx
View file @
9c1ae54a
...
...
@@ -151,8 +151,8 @@ class DataList extends React.Component {
},
{
title
:
"累计在线时长"
,
dataIndex
:
"
watch
Duration"
,
sorter
:
(
a
,
b
)
=>
a
.
watchDuration
-
b
.
watch
Duration
,
dataIndex
:
"
total
Duration"
,
sorter
:
(
a
,
b
)
=>
a
.
totalDuration
-
b
.
total
Duration
,
sortDirections
:
[
"descend"
,
"ascend"
],
render
:
(
text
,
record
)
=>
{
//如无离开时间,就置空
...
...
src/modules/course-manage/DataList/DataList.less
View file @
9c1ae54a
...
...
@@ -95,6 +95,9 @@
&.avatar-name-phone {
justify-content: flex-start;
padding-left: 26px;
.avatar{
border-radius:50%;
}
.name {
height: 22px;
font-size: 16px;
...
...
src/modules/course-manage/components/AddLiveBasic.jsx
View file @
9c1ae54a
...
...
@@ -30,10 +30,12 @@ class AddLiveBasic extends React.Component {
showCutModal
:
false
,
courseCatalogList
:[],
showSelectFileModal
:
false
,
cutImageBlob
:
null
cutImageBlob
:
null
,
hasImgReady
:
false
// 图片是否上传成功
}
}
componentWillUnmount
()
{
}
componentDidMount
(){
...
...
@@ -142,20 +144,22 @@ class AddLiveBasic extends React.Component {
const
_dataUrl
=
this
.
clip
()
self
.
setState
({
dataUrl
:
_dataUrl
,
hasImgReady
:
true
})
},
100
)
},
};
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
"#headPicModal"
,
options
);
_photoclip
.
load
(
im
ageFile
.
oss
Url
);
_photoclip
.
load
(
im
g
Url
);
this
.
setState
({
photoclip
:
_photoclip
,
});
}
else
{
this
.
state
.
photoclip
.
clear
();
this
.
state
.
photoclip
.
load
(
im
ageFile
.
oss
Url
);
this
.
state
.
photoclip
.
load
(
im
g
Url
);
}
},
200
);
...
...
@@ -197,7 +201,8 @@ class AddLiveBasic extends React.Component {
}
render
()
{
const
{
showCutModal
,
imageFile
,
courseCatalogList
,
showSelectFileModal
,
visible
,
cutImageBlob
}
=
this
.
state
;
const
{
showCutModal
,
imageFile
,
courseCatalogList
,
showSelectFileModal
,
visible
,
cutImageBlob
,
hasImgReady
}
=
this
.
state
;
const
{
data
,
pageType
,
isEdit
}
=
this
.
props
;
const
{
courseName
,
categoryName
,
coverUrl
}
=
data
;
const
fileName
=
''
;
...
...
@@ -254,7 +259,7 @@ class AddLiveBasic extends React.Component {
<
div
className=
"course-catalog"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
课程分类:
</
span
>
{
pageType
===
'add'
&&
<
Cascader
defaultValue=
{
[
categoryName
]
}
options=
{
courseCatalogList
}
displayRender=
{
label
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
<
Cascader
options=
{
courseCatalogList
}
displayRender=
{
label
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
}
{
(
pageType
===
'edit'
&&
categoryName
)
&&
<
Cascader
disabled=
{
!
isEdit
?
true
:
false
}
defaultValue=
{
[
categoryName
]
}
options=
{
courseCatalogList
}
displayRender=
{
label
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
...
...
@@ -278,19 +283,21 @@ class AddLiveBasic extends React.Component {
onClose=
{
()
=>
this
.
setState
({
showCutModal
:
false
})
}
reUpload=
{
()
=>
{
this
.
state
.
currentInputFile
.
click
()
}
}
/>
<
SelectPrepareFileModal
operateType=
"select"
multiple=
{
false
}
accept=
"image/jpeg,image/png,image/jpg"
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectFileModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
{
showSelectFileModal
&&
<
SelectPrepareFileModal
key=
"basic"
operateType=
"select"
multiple=
{
false
}
accept=
"image/jpeg,image/png,image/jpg"
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectFileModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
}
<
Modal
title=
"设置图片"
width=
{
1080
}
...
...
@@ -311,6 +318,7 @@ class AddLiveBasic extends React.Component {
<
Button
key=
"submit"
type=
"primary"
disabled=
{
!
hasImgReady
}
onClick=
{
()
=>
{
if
(
!
cutFlag
)
{
cutFlag
=
true
;
...
...
src/modules/course-manage/components/AddLiveClass.jsx
View file @
9c1ae54a
...
...
@@ -48,12 +48,19 @@ class AddLiveClass extends React.Component {
this
.
getTeacherList
();
this
.
getAssistantList
();
}
componentWillReceiveProps
(
nextProps
)
{
if
(
nextProps
.
data
.
assistantStoreUserId
.
sort
().
toString
()
!==
this
.
props
.
data
.
assistantStoreUserId
.
sort
().
toString
())
{
console
.
log
(
'我在改变'
)
// 获取助教老师列表
this
.
getAssistantList
(
1
,
nextProps
.
data
.
assistantStoreUserId
);
}
}
getTeacherList
(
current
=
1
,
selectList
){
const
{
teacherQuery
,
teacherList
}
=
this
.
state
;
const
_query
=
{
...
teacherQuery
,
current
,
size
:
1
0
size
:
1
5
};
StoreService
.
getStoreUserBasicPage
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
...
...
@@ -67,17 +74,24 @@ class AddLiveClass extends React.Component {
}
// 获取助教老师列表
getAssistantList
=
(
current
=
1
,
selectList
)
=>
{
console
.
log
(
'zhujiao'
,
current
);
const
{
assistantQuery
,
assistantList
}
=
this
.
state
;
const
{
assistantStoreUserId
}
=
this
.
props
.
data
;
const
idList
=
selectList
?
selectList
:
assistantStoreUserId
;
const
_query
=
{
...
assistantQuery
,
current
,
size
:
10
idList
,
size
:
idList
.
length
<=
10
?
10
:
idList
.
length
+
10
};
StoreService
.
getStoreUserBasicPage
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
,
hasNext
}
=
result
;
const
{
teacherId
}
=
this
.
props
.
data
let
list
=
current
>
1
?
assistantList
.
concat
(
records
)
:
records
;
console
.
log
(
"hasNext"
,
typeof
(
hasNext
),
hasNext
)
this
.
setState
({
assistantHasNext
:
hasNext
,
assistantList
:
list
,
...
...
@@ -92,7 +106,11 @@ class AddLiveClass extends React.Component {
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
;
if
(
scrollToBottom
&&
hasNext
)
{
const
{
teacherQuery
}
=
this
.
state
;
this
.
getTeacherList
(
teacherQuery
.
current
+
1
);
let
_teacherQuery
=
teacherQuery
;
_teacherQuery
.
current
=
_teacherQuery
.
current
+
1
this
.
setState
({
assistantQuery
:{...
_teacherQuery
}
},()
=>
{
this
.
getTeacherList
(
_teacherQuery
.
current
)})
}
}
...
...
@@ -103,7 +121,11 @@ class AddLiveClass extends React.Component {
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
;
if
(
scrollToBottom
&&
assistantHasNext
)
{
const
{
assistantQuery
}
=
this
.
state
;
this
.
getAssistantList
(
assistantQuery
.
current
+
1
);
let
_assistantQuery
=
assistantQuery
;
_assistantQuery
.
current
=
_assistantQuery
.
current
+
1
this
.
setState
({
assistantQuery
:{...
_assistantQuery
}
},()
=>
{
this
.
getAssistantList
(
_assistantQuery
.
current
)})
}
}
...
...
@@ -134,7 +156,9 @@ class AddLiveClass extends React.Component {
liveDate
,
timeHorizonStart
,
timeHorizonEnd
,
assistant
assistant
,
assistantNames
,
teacherName
}
=
data
;
console
.
log
(
"teacherId"
,
teacherId
);
return
(
...
...
@@ -241,19 +265,23 @@ class AddLiveClass extends React.Component {
</
div
>
}
<
div
className=
"teacher"
>
<
div
className=
"teacher"
id=
"teacher"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
讲师:
</
span
>
<
Select
placeholder=
"请选择讲师"
// key={teacherName}
// defaultValue={teacherName}
value=
{
teacherName
}
style=
{
{
width
:
240
,
marginTop
:
6
}
}
disabled=
{
!
isEdit
?
true
:
false
}
showSearch
value=
{
teacherId
}
filterOption=
{
(
input
,
option
)
=>
option
}
onPopupScroll=
{
this
.
handleScrollTeacherList
}
onChange=
{
(
value
,
option
)
=>
{
this
.
props
.
onChange
(
'teacherId'
,
value
,
option
.
children
)
console
.
log
(
"value"
,
value
);
this
.
props
.
onChange
(
'teacherId'
,
value
,
'teacherType'
,
option
.
children
)
}
}
onSearch=
{
(
value
)
=>
{
teacherQuery
.
nickName
=
value
this
.
setState
({
...
...
@@ -262,6 +290,9 @@ class AddLiveClass extends React.Component {
this
.
getTeacherList
()
})
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
"teacher"
)
}
>
{
_
.
map
(
teacherList
,
(
item
,
index
)
=>
{
if
(
!
assistant
.
includes
(
item
.
userId
)
){
...
...
@@ -271,41 +302,48 @@ class AddLiveClass extends React.Component {
}
})
}
</
Select
>
</
div
>
<
div
className=
"assistant-teacher"
>
<
span
className=
"label"
>
助教:
</
span
>
<
Select
id=
"assistant"
placeholder=
"请选择助教老师"
value=
{
assistant
}
disabled=
{
!
isEdit
?
true
:
false
}
mode=
{
'multiple'
}
showSearch
allowClear
style=
{
{
width
:
240
,
marginTop
:
6
}
}
filterOption=
{
(
input
,
option
)
=>
option
}
onPopupScroll=
{
this
.
handleScrollAssistantList
}
onChange=
{
(
value
)
=>
{
this
.
props
.
onChange
(
'assistant'
,
value
)
}
}
onSearch=
{
(
value
)
=>
{
assistantQuery
.
nickName
=
value
this
.
setState
({
assistantQuery
},
()
=>
{
this
.
getAssistantList
()
})
}
}
>
{
_
.
map
(
assistantList
,
(
item
,
index
)
=>
{
if
(
item
.
userId
!==
teacherId
){
return
(
<
Select
.
Option
value=
{
item
.
userId
}
key=
{
item
.
userId
}
>
{
item
.
nickName
}
</
Select
.
Option
>
);
}
})
}
</
Select
>
<
div
className=
"assistant-teacher"
id=
"assistant-teacher"
>
<
span
className=
"label"
>
助教:
</
span
>
<
Select
id=
"assistant"
placeholder=
"请选择助教老师"
// key={assistantNames}
// defaultValue={assistantNames}
value=
{
assistant
}
disabled=
{
!
isEdit
?
true
:
false
}
mode=
{
'multiple'
}
showSearch
allowClear
style=
{
{
width
:
240
,
marginTop
:
6
}
}
filterOption=
{
(
input
,
option
)
=>
option
}
onPopupScroll=
{
this
.
handleScrollAssistantList
}
onChange=
{
(
value
,
option
)
=>
{
console
.
log
(
'option'
,
option
);
this
.
props
.
onChange
(
'assistant'
,
value
,
'assistantType'
,
option
)
}
}
onSearch=
{
(
value
)
=>
{
assistantQuery
.
nickName
=
value
this
.
setState
({
assistantQuery
},
()
=>
{
this
.
getAssistantList
()
})
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
"assistant-teacher"
)
}
>
{
_
.
map
(
assistantList
,
(
item
,
index
)
=>
{
if
(
item
.
userId
!==
teacherId
){
return
(
<
Select
.
Option
value=
{
item
.
userId
}
key=
{
item
.
id
}
>
{
item
.
nickName
}
</
Select
.
Option
>
);
}
})
}
</
Select
>
</
div
>
</
div
>
</
Spin
>
...
...
src/modules/course-manage/components/AddLiveIntro.jsx
View file @
9c1ae54a
...
...
@@ -52,7 +52,7 @@ class AddLiveIntro extends React.Component {
if
(
selectType
===
'WARMUP'
){
const
liveCourseWarmMedia
=
{
contentType
:
'WARMUP'
,
mediaType
:
folderFormat
===
'MP4'
?
'VIDEO'
:
'PICTURE'
,
mediaType
:
folderFormat
===
'MP4'
||
folderFormat
===
'video/mp4'
?
'VIDEO'
:
'PICTURE'
,
mediaContent
:
resourceId
,
mediaUrl
:
ossUrl
,
mediaName
:
folderName
,
...
...
@@ -391,17 +391,21 @@ class AddLiveIntro extends React.Component {
</
div
>
</
div
>
{
/* 选择暖场图文件弹窗 */
}
<
SelectPrepareFileModal
operateType=
"select"
accept=
{
selectType
===
"INTRO"
?
"image/jpeg,image/png,image/jpg"
:
"video/mp4,image/jpeg,image/png,image/jpg"
}
selectTypeList=
{
selectType
===
"INTRO"
?
[
'JPG'
,
'JPEG'
,
'PNG'
]:
[
'MP4'
,
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
{
selectType
===
"INTRO"
?
'支持文件类型:jpg、jpeg、png'
:
'支持文件类型:jpg、jpeg、png、mp4'
}
isOpen=
{
showSelectFileModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectVideo
}
/>
{
showSelectFileModal
&&
<
SelectPrepareFileModal
key=
"instro"
operateType=
"select"
accept=
{
selectType
===
"INTRO"
?
"image/jpeg,image/png,image/jpg"
:
"video/mp4,image/jpeg,image/png,image/jpg"
}
selectTypeList=
{
selectType
===
"INTRO"
?
[
'JPG'
,
'JPEG'
,
'PNG'
]:
[
'MP4'
,
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
{
selectType
===
"INTRO"
?
'支持文件类型:jpg、jpeg、png'
:
'支持文件类型:jpg、jpeg、png、mp4'
}
isOpen=
{
showSelectFileModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectVideo
}
/>
}
</
div
>
)
...
...
src/modules/course-manage/components/LiveCourseFilter.jsx
View file @
9c1ae54a
...
...
@@ -15,6 +15,7 @@ import TeacherSearchSelect from "@/modules/common/TeacherSearchSelect";
import
RangePicker
from
"@/modules/common/DateRangePicker"
;
import
moment
from
'moment'
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
User
from
'@/common/js/user'
;
import
'./LiveCourseFilter.less'
;
const
{
Search
}
=
Input
;
...
...
@@ -98,8 +99,10 @@ class LiveCourseFilter extends React.Component {
query
.
endTime
=
dates
[
1
].
valueOf
();
}
this
.
setState
({
query
,
current
:
1
,
query
:{
...
query
,
current
:
1
,
}
},
()
=>
{
this
.
props
.
onChange
(
this
.
state
.
query
);
})
...
...
@@ -124,7 +127,6 @@ class LiveCourseFilter extends React.Component {
handleReset
=
()
=>
{
this
.
setState
({
query
:
{
...
this
.
state
.
query
,
courseName
:
null
,
startTime
:
null
,
endTime
:
null
,
...
...
@@ -132,6 +134,7 @@ class LiveCourseFilter extends React.Component {
teacherName
:
null
,
courseState
:
undefined
,
current
:
1
,
shelfState
:
null
,
},
},
()
=>
{
this
.
props
.
onChange
(
this
.
state
.
query
);
...
...
@@ -172,8 +175,10 @@ class LiveCourseFilter extends React.Component {
format=
{
"YYYY-MM-DD"
}
onChange=
{
(
dates
)
=>
{
this
.
handleChangeDates
(
dates
)
}
}
style=
{
{
width
:
"calc(100% - 70px)"
}
}
/>
</
div
>
{
User
.
getUserRole
()
!==
"CloudLecturer"
&&
<
div
className=
"search-condition__item"
>
<
span
>
讲师:
</
span
>
<
Select
...
...
@@ -185,7 +190,7 @@ class LiveCourseFilter extends React.Component {
onPopupScroll=
{
this
.
handleScrollTeacherList
}
value=
{
teacherId
}
onChange=
{
(
value
)
=>
{
this
.
handleChangeQuery
(
'teacherId'
,
value
)
this
.
handleChangeQuery
(
'teacherId'
,
value
)
;
}
}
onSearch=
{
(
value
)
=>
{
teacherQuery
.
nickName
=
value
...
...
@@ -195,6 +200,18 @@ class LiveCourseFilter extends React.Component {
this
.
getTeacherList
()
})
}
}
onClear
={(
value
)=
>
{
this
.
setState
({
teacherQuery
:{
size
:
10
,
current
:
1
,
nickName
:
null
}
},
()
=>
{
this
.
getTeacherList
()
})
}
}
>
{
_
.
map
(
teacherList
,
(
item
,
index
)
=>
{
return
(
...
...
@@ -203,8 +220,8 @@ class LiveCourseFilter extends React.Component {
})
}
</
Select
>
</
div
>
{
expandFilter
&&
}
{
((
expandFilter
&&
User
.
getUserRole
()
!==
"CloudLecturer"
)
||
User
.
getUserRole
()
===
"CloudLecturer"
)
&&
<
div
className=
"search-condition__item"
>
<
span
className=
"select-status"
>
上课状态:
</
span
>
<
Select
...
...
src/modules/course-manage/components/LiveCourseList.jsx
View file @
9c1ae54a
...
...
@@ -9,29 +9,23 @@
import
React
from
'react'
;
import
{
Table
,
Modal
,
message
,
Dropdown
,
Button
,
Switch
,
Tooltip
}
from
'antd'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
// import Bus from '@/core/bus';
// import User from "@/core/user";
// import User_t from "@/teacher/core/user";
import
{
PageControl
}
from
"@/components"
;
// import { LIVE_SHARE_MAP } from '@/common/constants/academic/cloudClass';
import
DownloadLiveModal
from
'@/components/DownloadLiveModal'
;
// import LiveStudentListModal from '../modal/LiveStudentListModal';
// import CheckBalanceModal from '../modal/CheckBalanceModal';
// import StartLiveModal from '../modal/StartLiveModal';
// import ClassRecordModal from '../modal/ClassRecordModal';
// import PlayBackRecordModal from '../modal/PlayBackRecordModal';
import
ManageCoursewareModal
from
'../modal/ManageCoursewareModal'
;
import
ShareLiveModal
from
'../modal/ShareLiveModal'
;
// import AccountChargeModal from '../modal/AccountChargeModal';
// import SelectStudent from '../modal/select-student';
import
'./LiveCourseList.less'
;
import
{
QuestionCircleOutlined
}
from
'@ant-design/icons'
;
import
{
appId
,
shareUrl
,
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
{
appId
,
shareUrl
,
LIVE_SHARE
,
LIVE_REPLAY_MAP
}
from
'@/domains/course-domain/constants'
;
import
CourseService
from
"@/domains/course-domain/CourseService"
;
import
BaseService
from
"@/domains/basic-domain/baseService"
;
import
DataList
from
'../DataList/DataList'
;
import
User
from
'@/common/js/user'
;
import
_
from
"underscore"
;
const
{
confirm
}
=
Modal
;
const
courseStateShow
=
{
...
...
@@ -67,9 +61,10 @@ class LiveCourseList extends React.Component {
}
componentWillMount
(){
this
.
parseColumns
();
}
componentDidMount
()
{
this
.
getDownloadVersion
()
}
// 显示分享弹窗
handleShowShareModal
=
(
item
,
needStr
=
false
)
=>
{
...
...
@@ -85,6 +80,7 @@ class LiveCourseList extends React.Component {
<
ShareLiveModal
needStr=
{
needStr
}
data=
{
shareData
}
type=
"liveClass"
close=
{
()
=>
{
this
.
setState
({
shareLiveModal
:
null
...
...
@@ -145,179 +141,338 @@ class LiveCourseList extends React.Component {
</
div
>
</
div
>
);
const
columns
=
[
{
title
:
"直播课"
,
width
:
"25%"
,
key
:
"course"
,
dataIndex
:
"courseName"
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
;
return
(
<
div
className=
"record__item"
>
{
record
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
"COVER"
){
hasCover
=
true
;
return
<
img
className=
"course-cover"
src=
{
item
.
mediaUrl
}
/>
}
})
}
{
!
hasCover
&&
<
img
className=
"course-cover"
src=
{
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
}
/>
}
<
div
>
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
<
div
>
<
span
className=
"course-time"
>
{
formatDate
(
"YYYY-MM-DD H:i"
,
parseInt
(
record
.
startTime
))
}
~
{
formatDate
(
"H:i"
,
parseInt
(
record
.
endTime
))
}
</
span
>
<
span
className=
"course-status"
style=
{
{
color
:
courseStateShow
[
record
.
courseState
].
color
,
border
:
`1px solid ${courseStateShow[record.courseState].color}`
}
}
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
</
div
>
<
div
class=
"teacher-assistant"
>
<
span
className=
"teacher"
>
讲师:
{
record
.
teacherName
}
</
span
>
{
record
.
admins
.
length
>
0
&&
<>
<
span
className=
"split"
>
|
</
span
>
<
span
className=
"assistant"
>
助教:
{
record
.
admins
.
map
((
item
,
index
)
=>
{
return
<
span
>
{
item
.
adminName
}
{
(
index
<
record
.
admins
.
length
-
1
)
&&
(<
span
>
、
</
span
>)
}
</
span
>
})
}
</
span
>
</>
let
columns
const
userRole
=
User
.
getUserRole
();
if
(
userRole
!==
"CloudLecturer"
){
columns
=
[
{
title
:
"直播课"
,
width
:
"25%"
,
key
:
"course"
,
dataIndex
:
"courseName"
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
;
return
(
<
div
className=
"record__item"
>
{
record
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
"COVER"
){
hasCover
=
true
;
return
<
img
className=
"course-cover"
src=
{
item
.
mediaUrl
}
/>
}
})
}
{
!
hasCover
&&
<
img
className=
"course-cover"
src=
{
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
}
/>
}
<
div
>
{
record
.
courseName
.
length
>
17
?
<
Tooltip
title=
{
record
.
courseName
}
>
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
</
Tooltip
>
:
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
}
</
div
>
<
div
>
<
span
className=
"course-time"
>
{
formatDate
(
"YYYY-MM-DD H:i"
,
parseInt
(
record
.
startTime
))
}
~
{
formatDate
(
"H:i"
,
parseInt
(
record
.
endTime
))
}
</
span
>
<
span
className=
"course-status"
style=
{
{
color
:
courseStateShow
[
record
.
courseState
].
color
,
border
:
`1px solid ${courseStateShow[record.courseState].color}`
}
}
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
</
div
>
<
div
className=
"teacher-assistant"
>
{
record
.
teacherName
.
length
>
4
?
<
Tooltip
title=
{
record
.
teacherName
}
>
<
span
className=
"teacher"
>
讲师:
{
record
.
teacherName
}
</
span
>
</
Tooltip
>
:
<
span
className=
"teacher"
>
讲师:
{
record
.
teacherName
}
</
span
>
}
{
record
.
admins
.
length
>
0
&&
<>
<
span
className=
"split"
>
|
</
span
>
{
this
.
handleAdminName
(
record
.
admins
).
length
>
4
?
<
Tooltip
title=
{
this
.
handleAdminName
(
record
.
admins
)
}
>
<
span
className=
"assistant"
>
助教:
{
record
.
admins
.
map
((
item
,
index
)
=>
{
return
<
span
>
{
item
.
adminName
}
{
(
index
<
record
.
admins
.
length
-
1
)
&&
(<
span
>
、
</
span
>)
}
</
span
>
})
}
</
span
>
</
Tooltip
>
:
<
span
className=
"assistant"
>
助教:
{
record
.
admins
.
map
((
item
,
index
)
=>
{
return
<
span
>
{
item
.
adminName
}
{
(
index
<
record
.
admins
.
length
-
1
)
&&
(<
span
>
、
</
span
>)
}
</
span
>
})
}
</
span
>
}
</>
}
</
div
>
</
div
>
</
div
>
</
div
>
)
}
},
{
title
:
"课程分类"
,
width
:
"10%"
,
key
:
"couseCatalog"
,
dataIndex
:
"couseCatalog"
,
render
:
(
val
,
item
)
=>
{
return
(
<
div
className=
"categoryName"
>
{
item
.
categoryName
}
</
div
>
)
)
}
},
},
{
title
:
"课件管理"
,
width
:
"8%"
,
key
:
"courseware"
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"courseware"
onClick=
{
()
=>
{
this
.
setState
({
editData
:
item
,
openCoursewareModal
:
true
,
});
}
}
>
{
item
.
courseDocumentCount
}
个
</
span
>
);
{
title
:
"课程分类"
,
width
:
"10%"
,
key
:
"couseCatalog"
,
dataIndex
:
"couseCatalog"
,
render
:
(
val
,
item
)
=>
{
return
(
<
div
className=
"categoryName"
>
{
item
.
categoryName
}
</
div
>
)
},
},
},
{
title
:
'上课数据'
,
width
:
"9%"
,
key
:
"quota"
,
dataIndex
:
"quota"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"iconfont icon quota-icon"
onClick=
{
()
=>
{
this
.
handleLinkToClassData
(
item
)
}
}
>

</
span
>
);
{
title
:
"课件管理"
,
width
:
"8%"
,
key
:
"courseware"
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"courseware"
onClick=
{
()
=>
{
this
.
setState
({
editData
:
item
,
openCoursewareModal
:
true
,
});
}
}
>
{
item
.
courseDocumentCount
}
个
</
span
>
);
},
},
},
{
title
:
<
span
>
<
span
>
店铺展示
</
span
>
<
Tooltip
title=
"开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。"
><
i
className=
"icon iconfont"
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
}
}
>

</
i
></
Tooltip
>
</
span
>,
width
:
"7%"
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
,
index
)
=>
{
return
(
<
Switch
defaultChecked=
{
item
.
shelfState
===
"YES"
?
true
:
false
}
onChange=
{
()
=>
this
.
changeShelfState
(
item
)
}
/>
)
{
title
:
'上课数据'
,
width
:
"9%"
,
key
:
"quota"
,
dataIndex
:
"quota"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"iconfont icon quota-icon"
onClick=
{
()
=>
{
this
.
handleLinkToClassData
(
item
)
}
}
>

</
span
>
);
},
},
},
{
title
:
"操作"
,
width
:
"15%"
,
key
:
"operate"
,
dataIndex
:
"operate"
,
render
:
(
val
,
item
)
=>
{
return
(
<
div
className=
"operate"
>
{
(
item
.
courseState
===
"UN_START"
||
item
.
courseState
===
"STARTING"
)
&&
<
div
key=
"enter_live_room1"
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleEnterLiveRoom
(
item
)
}
}
>
进入直播间
</
div
>
}
{
(
item
.
courseState
===
"FINISH"
)
&&
{
title
:
<
span
>
<
span
>
店铺展示
</
span
>
<
Tooltip
title=
{
<
div
>
开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。
<
br
/>
关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。
</
div
>
}
><
i
className=
"icon iconfont"
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
}
}
>

</
i
></
Tooltip
>
</
span
>,
width
:
"7%"
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
,
index
)
=>
{
return
(
<
Switch
defaultChecked=
{
item
.
shelfState
===
"YES"
?
true
:
false
}
onChange=
{
()
=>
this
.
changeShelfState
(
item
)
}
/>
)
},
},
{
title
:
"操作"
,
width
:
"15%"
,
key
:
"operate"
,
dataIndex
:
"operate"
,
render
:
(
val
,
item
)
=>
{
return
(
<>
<
div
className=
"operate"
>
{
((
item
.
courseState
===
"UN_START"
||
item
.
courseState
===
"STARTING"
)
&&
(
item
.
teacherId
===
User
.
getUserId
()
||
_
.
pluck
(
item
.
admins
,
"adminId"
).
includes
(
User
.
getUserId
())))
&&
<>
<
div
key=
"
view_play_back
"
key=
"
enter_live_room1
"
className=
"operate__item"
>
查看回放
</
div
>
onClick=
{
()
=>
{
this
.
handleEnterLiveRoom
(
item
)
}
}
>
进入直播间
</
div
>
<
span
className=
"operate__item split"
key=
"view_play_back_split"
>
|
</
span
>
</>
}
{
(
item
.
courseState
===
"FINISH"
&&
item
.
haveRecord
===
"YES"
)
&&
}
{
item
.
courseState
!==
"EXPIRED"
&&
<>
<
div
key=
"view_play_back"
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleViewPlayBack
(
item
)}
}
>
查看回放
</
div
>
<
span
className=
"operate__item split"
key=
"view_play_back_split"
>
|
</
span
>
</>
}
{
item
.
courseState
!==
"EXPIRED"
&&
<>
<
div
key=
"share"
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleShowShareModal
(
item
);
}
}
>
分享
</
div
>
</>
}
{
item
.
courseState
!==
"EXPIRED"
&&
<>
<
span
className=
"operate__item split"
key=
"view_play_back_split"
>
|
</
span
>
<
div
key=
"share"
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleShowShareModal
(
item
);
}
}
>
分享
<
span
key=
"split1"
className=
"operate__item split"
>
|
</
span
>
<
div
className=
"big-live"
>
<
Dropdown
overlay=
{
this
.
renderMoreOperate
(
item
)
}
>
<
span
className=
"more-operate"
>
<
span
className=
"operate-text"
>
更多
</
span
>
<
span
className=
"iconfont icon"
style=
{
{
color
:
"#5289FA"
}
}
>

</
span
>
</
span
>
</
Dropdown
>
</
div
>
</>
}
{
item
.
courseState
!==
"EXPIRED"
&&
<>
<
span
key=
"split1"
className=
"operate__item split"
>
|
</
span
>
<
div
className=
"big-live"
>
<
Dropdown
overlay=
{
this
.
renderMoreOperate
(
item
)
}
>
<
span
className=
"more-operate"
>
<
span
className=
"operate-text"
>
更多
</
span
>
<
span
className=
"iconfont icon"
style=
{
{
color
:
"#5289FA"
}
}
>

</
span
>
</
span
>
</
Dropdown
>
</
div
>
</>
}
{
item
.
courseState
===
"EXPIRED"
&&
<
div
className=
"operate__item"
onClick=
{
()
=>
this
.
handleDelete
(
item
)
}
>
删除
</
div
>
}
</
div
>
)
}
{
item
.
courseState
===
"EXPIRED"
&&
<
div
className=
"operate__item"
onClick=
{
()
=>
this
.
handleDelete
(
item
)
}
>
删除
</
div
>
}
</
div
>
)
}
}
}
];
];
}
else
{
columns
=
[
{
title
:
"直播课"
,
width
:
"25%"
,
key
:
"course"
,
dataIndex
:
"courseName"
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
;
return
(
<
div
className=
"record__item"
>
{
record
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
"COVER"
){
hasCover
=
true
;
return
<
img
className=
"course-cover"
src=
{
item
.
mediaUrl
}
/>
}
})
}
{
!
hasCover
&&
<
img
className=
"course-cover"
src=
{
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
}
/>
}
<
div
>
{
record
.
courseName
.
length
>
17
?
<
Tooltip
title=
{
record
.
courseName
}
>
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
</
Tooltip
>
:
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
}
<
div
>
<
span
className=
"course-time"
>
{
formatDate
(
"YYYY-MM-DD H:i"
,
parseInt
(
record
.
startTime
))
}
~
{
formatDate
(
"H:i"
,
parseInt
(
record
.
endTime
))
}
</
span
>
<
span
className=
"course-status"
style=
{
{
color
:
courseStateShow
[
record
.
courseState
].
color
,
border
:
`1px solid ${courseStateShow[record.courseState].color}`
}
}
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
</
div
>
<
div
className=
"teacher-assistant"
>
{
record
.
teacherName
.
length
>
4
?
<
Tooltip
title=
{
record
.
teacherName
}
>
<
span
className=
"teacher"
>
讲师:
{
record
.
teacherName
}
</
span
>
</
Tooltip
>
:
<
span
className=
"teacher"
>
讲师:
{
record
.
teacherName
}
</
span
>
}
{
record
.
admins
.
length
>
0
&&
<>
<
span
className=
"split"
>
|
</
span
>
{
this
.
handleAdminName
(
record
.
admins
).
length
>
4
?
<
Tooltip
title=
{
this
.
handleAdminName
(
record
.
admins
)
}
>
<
span
className=
"assistant"
>
助教:
{
record
.
admins
.
map
((
item
,
index
)
=>
{
return
<
span
>
{
item
.
adminName
}
{
(
index
<
record
.
admins
.
length
-
1
)
&&
(<
span
>
、
</
span
>)
}
</
span
>
})
}
</
span
>
</
Tooltip
>
:
<
span
className=
"assistant"
>
助教:
{
record
.
admins
.
map
((
item
,
index
)
=>
{
return
<
span
>
{
item
.
adminName
}
{
(
index
<
record
.
admins
.
length
-
1
)
&&
(<
span
>
、
</
span
>)
}
</
span
>
})
}
</
span
>
}
</>
}
</
div
>
</
div
>
</
div
>
)
}
},
{
title
:
"课程分类"
,
width
:
"10%"
,
key
:
"couseCatalog"
,
dataIndex
:
"couseCatalog"
,
render
:
(
val
,
item
)
=>
{
return
(
<
div
className=
"categoryName"
>
{
item
.
categoryName
}
</
div
>
)
},
},
{
title
:
"课件管理"
,
width
:
"8%"
,
key
:
"courseware"
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"courseware"
onClick=
{
()
=>
{
this
.
setState
({
editData
:
item
,
openCoursewareModal
:
true
,
});
}
}
>
{
item
.
courseDocumentCount
}
个
</
span
>
);
},
},
{
title
:
'上课数据'
,
width
:
"9%"
,
key
:
"quota"
,
dataIndex
:
"quota"
,
render
:
(
val
,
item
)
=>
{
return
(
<
span
className=
"iconfont icon quota-icon"
onClick=
{
()
=>
{
this
.
handleLinkToClassData
(
item
)
}
}
>

</
span
>
);
},
},
];
}
this
.
setState
({
columns
})
}
handleAdminName
=
(
adminArray
)
=>
{
let
adminStr
=
""
;
adminArray
.
map
((
item
,
index
)
=>
{
if
(
index
<
adminArray
.
length
-
1
){
adminStr
=
adminStr
+
item
.
adminName
+
'、'
;
}
else
{
adminStr
=
adminStr
+
item
.
adminName
}
})
return
adminStr
}
renderMoreOperate
=
(
item
)
=>
{
return
(
<
div
className=
"live-course-more-menu"
>
...
...
@@ -383,25 +538,24 @@ class LiveCourseList extends React.Component {
),
});
}
else
{
// axios
// .Apollo("public/businessLive/getCourseDetail", {
// liveCourseId: item.liveCourseId,
// })
// .then((res) => {
// const url = `xiaomai5://instId=${instId}&courseId=${item.liveCourseId}&teacherId=${item.teacherId}&uid=${ teacherId ? User_t.uid() : User.uid()}&aid=${teacherId ? "" : User.aid()}&tid=${teacherId || ""}&identity=${identity}&classType=${item.liveType}&xmVersion=${window.NewVersion ? '5.0' : '4.0'}`;
// if (res.result.courseState === "FINISH") {
// Modal.warning({
// title: "刷新页面",
// icon: <QuestionCircleOutlined />,
// content: "课次已结束,请刷新一下",
// onOk: () => {
// this.refreshCourseList();
// }
// });
// } else {
this
.
setState
({
url
:
''
,
openDownloadModal
:
true
});
// }
// });
CourseService
.
getLiveCloudCourseDetail
({
liveCourseId
:
item
.
liveCourseId
,
})
.
then
((
res
)
=>
{
const
url
=
`xmqx://liveCourseId=
${
item
.
liveCourseId
}
`
;
if
(
res
.
result
.
courseState
===
"FINISH"
)
{
Modal
.
warning
({
title
:
"刷新页面"
,
icon
:
<
QuestionCircleOutlined
/>,
content
:
"课次已结束,请刷新一下"
,
onOk
:
()
=>
{
this
.
refreshCourseList
();
}
});
}
else
{
this
.
setState
({
url
,
openDownloadModal
:
true
});
}
});
}
}
onShowSizeChange
=
(
current
,
size
)
=>
{
...
...
@@ -412,7 +566,35 @@ class LiveCourseList extends React.Component {
_query
.
size
=
size
;
this
.
props
.
onChange
(
_query
)
}
getDownloadVersion
()
{
const
isMac
=
/macintosh|mac os x/i
.
test
(
navigator
.
userAgent
);
// 判断用户系统
let
platform
;
if
(
!
isMac
){
platform
=
1
}
else
{
platform
=
4
}
BaseService
.
getLastedVersion
({
model
:
5
,
platform
})
.
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
this
.
setState
({
downloadUrl
:
result
.
releaseUrl
});
})
}
handleViewPlayBack
=
(
item
)
=>
{
let
htmlUrl
;
if
(
item
.
teacherId
===
User
.
getUserId
()){
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?teacherId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
;
}
else
if
(
_
.
pluck
(
item
.
admins
,
"adminId"
).
includes
(
User
.
getUserId
())){
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?userId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
;
}
else
{
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?id=
${
User
.
getStoreId
()}
`
;
}
window
.
open
(
htmlUrl
);
}
render
()
{
const
{
total
,
query
,
courseList
,
loading
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
...
...
@@ -422,7 +604,7 @@ class LiveCourseList extends React.Component {
editData
}
=
this
.
state
;
const
{
match
}
=
this
.
props
;
return
(
<
div
className=
"live-course-list"
>
<
Table
...
...
src/modules/course-manage/components/LiveCourseList.less
View file @
9c1ae54a
...
...
@@ -17,7 +17,7 @@
color: #333333;
line-height: 20px;
font-weight: bold;
max-width:2
38
px;
max-width:2
44
px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
...
...
@@ -77,9 +77,11 @@
color: #5289FA;
line-height: 20px;
text-align:right;
cursor:pointer;
}
.quota-icon{
color:#5289FA;
cursor:pointer;
}
.operate {
display: flex;
...
...
@@ -124,8 +126,14 @@
font-size: 12px;
}
}
}
.ant-tooltip{
max-width:700px !important;
}
.ant-tooltip-inner{
max-width:700px !important;
}
.live-course-more-menu {
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
...
...
src/modules/course-manage/components/LiveCourseOpt.jsx
View file @
9c1ae54a
...
...
@@ -8,7 +8,10 @@
import
React
from
'react'
;
import
{
Button
,
Modal
,
message
}
from
'antd'
;
import
Service
from
'@/common/js/service'
;
import
'./liveCourseOpt.less'
;
import
BaseService
from
"@/domains/basic-domain/baseService"
;
import
User
from
'@/common/js/user'
class
LiveCourseOpt
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
...
...
@@ -22,30 +25,30 @@ class LiveCourseOpt extends React.Component {
handleDownloadClient
=
()
=>
{
const
isMac
=
/macintosh|mac os x/i
.
test
(
navigator
.
userAgent
);
// 判断用户系统
if
(
!
isMac
)
{
// axios
// .Apollo("anon/version/getLastedVersion", { model: 1, platform: 1 })
// .then((res) => {
// const a = document.createElement("a");
// document.body.appendChild(a);
// a.href = res.result.releaseUrl;
// a.click();
// document.body.removeChild(a);
// })
}
else
{
Modal
.
info
({
title
:
"抱歉,暂不支持Mac版"
,
content
:
"Mac版正在开发中,敬请期待"
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
okText
:
'我知道了'
});
let
platform
;
if
(
!
isMac
){
platform
=
1
}
else
{
platform
=
4
}
BaseService
.
getLastedVersion
({
model
:
5
,
platform
})
.
then
((
res
)
=>
{
const
a
=
document
.
createElement
(
"a"
);
document
.
body
.
appendChild
(
a
);
a
.
href
=
res
.
result
.
releaseUrl
;
a
.
click
();
document
.
body
.
removeChild
(
a
);
})
}
render
()
{
const
userRole
=
User
.
getUserRole
();
return
(
<
div
className=
"live-course-opt"
>
<
div
className=
"opt__left"
>
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateLiveCouese
}
>
新建直播课
</
Button
>
{
userRole
!==
"CloudLecturer"
&&
<
Button
type=
"primary"
onClick=
{
this
.
handleCreateLiveCouese
}
>
新建直播课
</
Button
>
}
<
Button
onClick=
{
this
.
handleDownloadClient
}
>
下载直播客户端
</
Button
>
</
div
>
</
div
>
...
...
src/modules/course-manage/modal/ManageCoursewareModal.jsx
View file @
9c1ae54a
...
...
@@ -122,7 +122,7 @@ class ManageCoursewareModal extends React.Component {
// 上传文件
addFile
()
{
// 判断是否早于开课前
45
分钟
// 判断是否早于开课前
30
分钟
const
{
startTime
}
=
this
.
props
.
data
;
const
currentTime
=
new
Date
().
getTime
();
if
(
currentTime
>=
startTime
-
30
*
60
*
1000
)
{
...
...
@@ -313,7 +313,7 @@ class ManageCoursewareModal extends React.Component {
const
uploadFail
=
failObject
[
item
.
id
];
// 上课前45分钟/上课中/已结束的情况下都不可操作
if
(
this
.
props
.
data
.
startTime
<
Date
.
now
()
+
27
00000
||
item
.
progress
||
uploadFail
)
{
if
(
this
.
props
.
data
.
startTime
<
Date
.
now
()
+
18
00000
||
item
.
progress
||
uploadFail
)
{
return
<
span
>
-
</
span
>
}
return
(
...
...
src/modules/course-manage/modal/PreviewCourseModal.jsx
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-07-23 14:54:16
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-01-0
8 17:49:46
* @LastEditTime: 2021-01-0
9 16:26:03
* @Description: 大班直播课预览弹窗
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -36,7 +36,16 @@ class PreviewCourseModal extends React.Component {
}
}
dealTimeDuration
=
(
time
)
=>
{
const
diff
=
Math
.
floor
(
time
%
3600
);
let
hours
=
Math
.
floor
(
time
/
3600
);
let
mins
=
Math
.
floor
(
diff
/
60
);
let
seconds
=
Math
.
floor
(
time
%
60
);
hours
=
hours
<
10
?
(
"0"
+
hours
)
:
hours
;
mins
=
mins
<
10
?
(
"0"
+
mins
)
:
mins
;
seconds
=
seconds
<
10
?
(
"0"
+
seconds
)
:
seconds
;
return
hours
+
":"
+
mins
+
":"
+
seconds
;
}
dealWithTime
=
(
startTime
,
endTime
)
=>
{
const
startDate
=
new
Date
(
Number
(
startTime
));
const
endDate
=
new
Date
(
Number
(
endTime
));
...
...
@@ -64,8 +73,8 @@ class PreviewCourseModal extends React.Component {
render
()
{
const
{
courseBasicInfo
,
courseClassInfo
=
{},
courseIntroInfo
,
type
,
courseState
}
=
this
.
props
;
const
{
coverUrl
,
courseName
,
scheduleVideoUrl
}
=
courseBasicInfo
;
const
{
courseBasicInfo
,
courseClassInfo
=
{},
courseIntroInfo
,
type
,
courseState
,
origin
}
=
this
.
props
;
const
{
coverUrl
,
courseName
,
scheduleVideoUrl
,
videoDuration
}
=
courseBasicInfo
;
const
{
liveDate
,
calendarTime
,
startTime
,
endTime
,
timeHorizonStart
,
timeHorizonEnd
,
teacherName
}
=
courseClassInfo
;
const
{
liveCourseMediaRequests
}
=
courseIntroInfo
;
...
...
@@ -128,13 +137,15 @@ class PreviewCourseModal extends React.Component {
<
img
src=
{
coverUrl
}
className=
"course-cover"
/>
}
</
div
>
{
type
===
'videoCourse'
?
<
div
className=
"container__body"
>
<
div
className=
"title__name"
>
{
courseName
}
</
div
>
<
div
className=
"title__inst-name"
>
{
window
.
currentUserInstInfo
.
name
}
</
div
>
</
div
>
:
{
videoDuration
&&
<
div
>
视频时长:
{
this
.
dealTimeDuration
(
videoDuration
)
}
</
div
>
}
</
div
>
:
<
div
className=
"container__body"
>
<
div
className=
"container__body__title"
>
<
div
className=
"title__name"
>
{
courseName
}
</
div
>
...
...
@@ -144,13 +155,11 @@ class PreviewCourseModal extends React.Component {
<
span
className=
"time__label"
>
上课时间:
</
span
>
<
span
className=
"time__value"
>
{
[
<
span
>
{
liveDateStr
}
</
span
>,
<
span
>
{
startTimeStr
}
~
{
endTimeStr
}
</
span
>
]
}
</
span
>
</
div
>
<
div
className=
"container__body__teacher"
>
...
...
@@ -161,7 +170,11 @@ class PreviewCourseModal extends React.Component {
}
<
div
className=
"container__introduction"
>
<
div
className=
"container__introduction__title"
>
直播简介
</
div
>
{
type
===
'videoCourse'
?
<
div
className=
"container__introduction__title"
>
视频简介
</
div
>
:
<
div
className=
"container__introduction__title"
>
直播简介
</
div
>
}
<
div
className=
"container__introduction__list editor-box"
>
{
liveCourseMediaRequests
.
map
((
item
,
index
)
=>
{
...
...
src/modules/course-manage/modal/ShareLiveModal.jsx
View file @
9c1ae54a
...
...
@@ -93,8 +93,8 @@ class ShareLiveModal extends React.Component {
// 如果是默认图, 显示视频的第一帧, 否则显示上传的视频封面
?
((
!
coverUrl
||
isDefaultCover
)
?
`
${
scheduleVideoUrl
}
?x-oss-process=video/snapshot,t_0,m_fast&anystring=anystring`
:
`
${
coverUrl
}
${
!
needStr
?
'&anystring=anystring'
:
''
}
`
)
:
`
${
coverUrl
}
${(
!
needStr
&&
!
isDefaultCover
)
?
'&anystring=anystring'
:
''
}
`
:
`
${
coverUrl
}
`
)
:
`
${
coverUrl
}
`
return
(
...
...
@@ -113,9 +113,14 @@ class ShareLiveModal extends React.Component {
</
div
>
<
div
className=
"course-name-title"
>
{
type
===
'videoClass'
?
`${courseName}开课啦`
:
`邀请你观看直播:`
}
</
div
>
{
type
===
"liveClass"
&&
<
div
class=
"live-couse-name"
>
{
courseName
}
</
div
>
}
<
img
src=
{
coverImgSrc
}
crossOrigin=
"*"
className=
"course-cover"
/>
...
...
@@ -132,13 +137,26 @@ class ShareLiveModal extends React.Component {
<
div
className=
"right"
>
<
div
className=
"share-poster right__item"
>
<
div
className=
"title"
>
① 海报分享
</
div
>
<
div
className=
"sub-title"
>
学生可通过微信识别二维码,报名观看直播
</
div
>
{
type
===
"liveClass"
&&
<
div
className=
"sub-title"
>
用户可通过微信扫描海报二维码,观看直播
</
div
>
}
{
type
===
"videoClass"
&&
<
div
className=
"sub-title"
>
用户可通过微信识别二维码,报名观看视频
</
div
>
}
<
div
className=
"content"
onClick=
{
this
.
handleDownloadPoster
}
>
下载海报
</
div
>
</
div
>
<
div
className=
"share-url right__item"
>
<
div
className=
"title"
>
② 链接分享
</
div
>
<
div
className=
"sub-title"
>
学生可通过微信打开链接,报名观看直播
</
div
>
{
type
===
"liveClass"
&&
<
div
className=
"sub-title"
>
用户可通过微信打开以下链接,观看直播
</
div
>
}
{
type
===
"videoClass"
&&
<
div
className=
"sub-title"
>
用户可通过打开链接,报名观看视频
</
div
>
}
<
div
className=
"content"
>
<
div
className=
"share-url"
id=
"shareUrl"
>
{
shareUrl
}
</
div
>
<
Button
type=
"primary"
onClick=
{
this
.
handleCopy
}
>
复制
</
Button
>
...
...
src/modules/course-manage/modal/ShareLiveModal.less
View file @
9c1ae54a
...
...
@@ -14,6 +14,11 @@
line-height: 20px;
margin-bottom: 4px;
}
.live-couse-name{
font-size:16px;
color:#333333;
font-weight: 600;
}
.course-name {
color: #333;
font-size: 16px;
...
...
src/modules/course-manage/video-course/AddVideoCourse.jsx
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-01-
08 17:56:17
* @LastEditTime: 2021-01-
18 18:18:49
* @Description: 视频课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -22,11 +22,23 @@ import PreviewCourseModal from '../modal/PreviewCourseModal';
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
CourseService
from
"@/domains/course-domain/CourseService"
;
import
User
from
'@/common/js/user'
;
import
_
from
"underscore"
;
import
'./AddVideoCourse.less'
;
const
EDIT_BOX_KEY
=
Math
.
random
(
16
);
const
EDIT_BOX_KEY
=
Math
.
random
();
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
};
//添加课程时课程默认的一些值
const
defaultShelfState
=
'YES'
;
const
defaultScheduleMedia
=
[{
contentType
:
'INTRO'
,
mediaType
:
'TEXT'
,
mediaContent
:
''
,
key
:
EDIT_BOX_KEY
}]
const
whetherVisitorsJoin
=
'NO'
class
AddVideoCourse
extends
React
.
Component
{
constructor
(
props
)
{
...
...
@@ -39,7 +51,6 @@ class AddVideoCourse extends React.Component {
id
,
// 视频课ID,编辑的时候从URL上带过来
pageType
,
// 页面类型: add->新建 edit->编辑
imageFile
:
null
,
// 需要被截取的图片
courseName
:
null
,
// 视频课名称
scheduleVideoId
:
null
,
// 视频课链接
coverId
:
null
,
// 视频封面的recourceId
...
...
@@ -50,7 +61,7 @@ class AddVideoCourse extends React.Component {
contentType
:
"INTRO"
,
mediaType
:
'TEXT'
,
mediaContent
:
''
,
key
:
Math
.
random
()
key
:
EDIT_BOX_KEY
}],
diskList
:
[],
// 机构可见磁盘目录
selectedFileList
:
[],
// 已经从资料云盘中勾选的文件
...
...
@@ -171,22 +182,36 @@ class AddVideoCourse extends React.Component {
categoryName
,
categoryId
});
})
}
handleGoBack
=
()
=>
{
Modal
.
confirm
({
title
:
'确认要返回吗?'
,
content
:
'返回后,本次编辑的内容将不被保存。'
,
okText
:
'确认返回'
,
cancelText
:
'留在本页'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
onOk
:
()
=>
{
RCHistory
.
goBack
();
}
});
const
{
coverId
,
videoName
,
videoDuration
,
courseName
,
scheduleMedia
,
scheduleVideoId
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
;
if
(
videoName
||
videoDuration
||
scheduleVideoId
||
!
_
.
isEqual
(
scheduleMedia
,
defaultScheduleMedia
)
||
categoryId
||
courseName
||
coverId
||
shelfState
!==
defaultShelfState
||
whetherVisitorsJoin
!==
whetherVisitorsJoin
){
Modal
.
confirm
({
title
:
'确认要返回吗?'
,
content
:
'返回后,本次编辑的内容将不被保存。'
,
okText
:
'确认返回'
,
cancelText
:
'留在本页'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
onOk
:
()
=>
{
RCHistory
.
goBack
();
}
});
}
else
{
RCHistory
.
goBack
();
}
}
// 修改表单
...
...
@@ -239,15 +264,17 @@ class AddVideoCourse extends React.Component {
coverUrl
,
scheduleVideoUrl
,
courseName
,
scheduleMedia
scheduleMedia
,
videoDuration
}
=
this
.
state
;
const
courseBasinInfo
=
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
videoDuration
}
const
courseIntroInfo
=
{
liveCourseMediaRequests
:
scheduleMedia
}
...
...
@@ -409,7 +436,7 @@ class AddVideoCourse extends React.Component {
<
div
className=
"box"
>
<
div
className=
"show-tips"
>
<
ShowTips
message=
"请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦
助教
保有依据国家规定及平台规则进行处理的权利"
/>
<
ShowTips
message=
"请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦
企培
保有依据国家规定及平台规则进行处理的权利"
/>
</
div
>
<
div
className=
"form"
>
...
...
@@ -483,8 +510,8 @@ class AddVideoCourse extends React.Component {
</
div
>
</
div
>
</
div
>
<
div
className=
"course-catalog"
>
<
span
className=
"label"
>
<
span
className=
"require"
>
*
</
span
>
课程分类:
</
span
>
<
div
className=
"course-catalog
required
"
>
<
span
className=
"label"
>
课程分类:
</
span
>
{
(
pageType
===
'add'
)
&&
<
Cascader
defaultValue=
{
[
categoryName
]
}
options=
{
courseCatalogList
}
displayRender=
{
label
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
}
...
...
src/modules/course-manage/video-course/components/VideoCourseFilter.jsx
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:11:57
* @LastEditors: zhangleyuan
* @LastEditTime: 202
0-12-31 18:27:26
* @LastEditTime: 202
1-01-15 13:52:10
* @Description: 视频课-搜索模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -97,8 +97,10 @@ class VideoCourseFilter extends React.Component {
query
.
endTime
=
dates
[
1
].
valueOf
();
}
this
.
setState
({
query
,
current
:
1
,
query
:{
...
query
,
current
:
1
,
}
},
()
=>
{
this
.
props
.
onChange
(
this
.
state
.
query
);
})
...
...
@@ -164,6 +166,18 @@ class VideoCourseFilter extends React.Component {
this
.
getTeacherList
()
})
}
}
onClear
={(
value
)=
>
{
this
.
setState
({
teacherQuery
:{
size
:
10
,
current
:
1
,
nickName
:
null
}
},
()
=>
{
this
.
getTeacherList
()
})
}
}
>
{
_
.
map
(
teacherList
,
(
item
,
index
)
=>
{
return
(
...
...
src/modules/course-manage/video-course/components/VideoCourseList.jsx
View file @
9c1ae54a
/*
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors:
wuf
an
* @LastEditTime: 2021-01-
09 13:59:06
* @LastEditors:
zhangleyu
an
* @LastEditTime: 2021-01-
18 21:03:40
* @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -23,7 +23,7 @@ import User from '@/common/js/user'
import
'./VideoCourseList.less'
;
const
ENV
=
process
.
env
.
DEPLOY_ENV
||
'
dev
'
;
const
ENV
=
process
.
env
.
DEPLOY_ENV
||
'
prod
'
;
class
VideoCourseList
extends
React
.
Component
{
...
...
@@ -68,14 +68,20 @@ class VideoCourseList extends React.Component {
title
:
'视频课'
,
key
:
'scheduleName'
,
dataIndex
:
'scheduleName'
,
width
:
'20
%'
,
width
:
'15
%'
,
render
:
(
val
,
record
)
=>
{
const
{
coverUrl
,
scheduleVideoUrl
}
=
record
;
return
(
<
div
className=
"record__item"
>
{
/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */
}
<
img
className=
"course-cover"
src=
{
coverUrl
||
`${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast`
}
/>
<
span
className=
"course-name"
>
{
record
.
courseName
}
</
span
>
{
record
.
courseName
.
length
>
25
?
<
Tooltip
title=
{
record
.
courseName
}
>
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
</
Tooltip
>
:
<
div
className=
"course-name"
>
{
record
.
courseName
}
</
div
>
}
</
div
>
)
}
...
...
@@ -84,6 +90,7 @@ class VideoCourseList extends React.Component {
title
:
'课程分类'
,
key
:
'categoryName'
,
dataIndex
:
'categoryName'
,
width
:
'10%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"record__item"
>
...
...
@@ -95,14 +102,30 @@ class VideoCourseList extends React.Component {
{
title
:
'创建人'
,
key
:
'createName'
,
dataIndex
:
'createName'
dataIndex
:
'createName'
,
width
:
'8%'
,
render
:
(
val
)
=>
{
return
(
<
div
>
{
val
&&
<
Tooltip
title=
{
val
}
>
<
div
>
{
val
.
length
>
4
?
`${val.slice(0,4)}
...
`
:
val
}
</
div
>
</
Tooltip
>
}
</
div
>
)
}
},
{
title
:
<
span
>
<
span
>
店铺展示
</
span
>
<
Tooltip
title=
"开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。"
><
i
className=
"icon iconfont"
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
}
}
>

</
i
></
Tooltip
>
<
Tooltip
title=
{
<
div
>
开启后,用户可在店铺内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”店铺展示。
<
br
/>
关闭后,店铺内不再展示此课程,但用户仍可通过分享的海报/链接查看此课程。
</
div
>
}
><
i
className=
"icon iconfont"
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
}
}
>

</
i
></
Tooltip
>
</
span
>,
width
:
"7%"
,
width
:
'12%'
,
dataIndex
:
"courseware"
,
render
:
(
val
,
item
,
index
)
=>
{
return
(
...
...
@@ -123,6 +146,7 @@ class VideoCourseList extends React.Component {
},
{
title
:
'创建时间'
,
width
:
"10%"
,
key
:
'created'
,
dataIndex
:
'created'
,
sorter
:
true
,
...
...
@@ -132,6 +156,7 @@ class VideoCourseList extends React.Component {
},
{
title
:
'更新时间'
,
width
:
"10%"
,
key
:
'updated'
,
dataIndex
:
'updated'
,
sorter
:
true
,
...
...
@@ -143,6 +168,7 @@ class VideoCourseList extends React.Component {
title
:
'操作'
,
key
:
'operate'
,
dataIndex
:
'operate'
,
width
:
"20%"
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"operate"
>
...
...
@@ -215,6 +241,8 @@ class VideoCourseList extends React.Component {
title
:
'你确定要删除此视频课吗?'
,
content
:
'删除后,学员将不能进行观看。'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
okText
:
'确定'
,
cancelText
:
'取消'
,
onOk
:
()
=>
{
const
param
=
{
courseId
:
scheduleId
,
...
...
@@ -269,17 +297,17 @@ class VideoCourseList extends React.Component {
const
{
query
}
=
this
.
props
;
let
{
order
:
_order
}
=
query
;
// 按创建时间升序排序
if
(
columnKey
===
'create
Time
'
&&
order
===
'ascend'
)
{
_order
=
'CREATED_ASC'
;
}
if
(
columnKey
===
'create
d
'
&&
order
===
'ascend'
)
{
_order
=
'CREATED_ASC'
;
}
// 按创建时间降序排序
if
(
columnKey
===
'create
Time
'
&&
order
===
'descend'
)
{
_order
=
'CREATED_DESC'
;
}
if
(
columnKey
===
'create
d
'
&&
order
===
'descend'
)
{
_order
=
'CREATED_DESC'
;
}
// 按更新时间升序排序
if
(
columnKey
===
'update
Time
'
&&
order
===
'ascend'
)
{
_order
=
'UPDATED_ASC'
;
}
if
(
columnKey
===
'update
d
'
&&
order
===
'ascend'
)
{
_order
=
'UPDATED_ASC'
;
}
// 按更新时间降序排序
if
(
columnKey
===
'update
Time
'
&&
order
===
'descend'
)
{
_order
=
'UPDATED_DESC'
;
}
if
(
columnKey
===
'update
d
'
&&
order
===
'descend'
)
{
_order
=
'UPDATED_DESC'
;
}
const
_query
=
{
...
query
,
order
:
_order
order
Enum
:
_order
};
this
.
props
.
onChange
(
_query
);
}
...
...
src/modules/course-manage/video-course/components/VideoCourseList.less
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
margin-top: 12px;
.operate-text {
color: #
FF8534
;
color: #
5289FA
;
cursor: pointer;
}
...
...
@@ -10,7 +10,7 @@
display: flex;
&__item {
color: #
FF8534
;
color: #
5289FA
;
cursor: pointer;
&.split {
...
...
@@ -19,7 +19,6 @@
}
}
}
.record__item {
display: flex;
...
...
@@ -34,6 +33,13 @@
.course-name {
color: #666;
width:188px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
height:48px;
}
}
}
...
...
@@ -50,4 +56,10 @@
background: #f3f6fa;
}
}
}
.ant-tooltip{
max-width:700px !important;
}
.ant-tooltip-inner{
max-width:700px !important;
}
\ No newline at end of file
src/modules/prepare-lesson/modal/SelectPrepareFileModal.jsx
View file @
9c1ae54a
...
...
@@ -76,7 +76,17 @@ class SelectPrepareFileModal extends React.Component {
showNonCompliantFileModal
:
false
,
}
}
componentDidMount
()
{
const
{
diskList
=
[],
currentRootDisk
}
=
this
.
props
;
const
_currentRootDisk
=
diskList
[
0
]
||
currentRootDisk
||
defaultRootDisk
;
this
.
setState
({
query
:
defaultQuery
,
currentRootDisk
:
_currentRootDisk
,
folderPathList
:
[
_currentRootDisk
],
},
()
=>
{
this
.
handleFetchFolderList
();
});
}
componentWillReceiveProps
(
nextProps
)
{
const
{
diskList
=
[],
currentRootDisk
}
=
nextProps
;
if
(
nextProps
.
isOpen
)
{
...
...
src/modules/root/Login.jsx
View file @
9c1ae54a
...
...
@@ -115,7 +115,7 @@ function Login(props) {
<
div
className=
"login-page"
>
<
div
className=
"login-main"
>
<
div
className=
"left-banner"
>
<
div
><
img
src=
{
require
(
"../../common/images/logo.png"
)
}
alt=
""
style=
{
{
width
:
60
,
height
:
61
}
}
/></
div
>
<
div
><
img
src=
{
require
(
"../../common/images/logo.png"
)
}
alt=
""
style=
{
{
width
:
60
,
height
:
61
}
}
/></
div
>
<
div
className=
"name"
>
小麦企培
</
div
>
<
div
className=
"desc"
>
一键开启直播授课 让知识更有价值
</
div
>
</
div
>
...
...
src/modules/store-manage/StoreH5DecorationTab.jsx
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: wufan
* @LastEditTime: 2021-01-
03 22:37:32
* @LastEditTime: 2021-01-
18 14:53:17
* @Description: web店铺banner页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -269,15 +269,18 @@ class StoreH5Decoration extends React.Component {
},
};
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
"#headPicModal"
,
options
);
_photoclip
.
load
(
im
ageFile
.
oss
Url
);
_photoclip
.
load
(
im
g
Url
);
this
.
setState
({
photoclip
:
_photoclip
,
});
}
else
{
this
.
state
.
photoclip
.
clear
();
this
.
state
.
photoclip
.
load
(
im
ageFile
.
oss
Url
);
this
.
state
.
photoclip
.
load
(
im
g
Url
);
}
},
200
);
...
...
src/modules/store-manage/StoreWebDecorationTab.jsx
View file @
9c1ae54a
...
...
@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2020-11-30 10:47:38
* @LastEditors: wufan
* @LastEditTime: 2021-01-
04 11:11:38
* @LastEditTime: 2021-01-
18 14:59:57
* @Description: web店铺banner页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -268,15 +268,17 @@ class StoreWebDecoration extends React.Component {
},
};
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
"#headPicModal"
,
options
);
_photoclip
.
load
(
im
ageFile
.
oss
Url
);
_photoclip
.
load
(
im
g
Url
);
this
.
setState
({
photoclip
:
_photoclip
,
});
}
else
{
this
.
state
.
photoclip
.
clear
();
this
.
state
.
photoclip
.
load
(
im
ageFile
.
oss
Url
);
this
.
state
.
photoclip
.
load
(
im
g
Url
);
}
},
200
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment