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
05f7474b
Commit
05f7474b
authored
Dec 17, 2020
by
zhangleyuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:创建课程条助教选项改为多选
parent
9df2307f
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1049 additions
and
6 deletions
+1049
-6
src/bu-components/SelectPrepareFileModal.jsx
+1
-1
src/modules/course-manage/components/AddLiveBasic.jsx
+164
-0
src/modules/course-manage/components/AddLiveClass.jsx
+360
-0
src/modules/course-manage/components/AddLiveIntro.jsx
+387
-0
src/modules/course-manage/components/LiveCourseList.less
+127
-0
src/modules/course-manage/modal/SelectPrepareFileModal.jsx
+8
-3
src/modules/resource-disk/components/FolderManage.jsx
+2
-2
No files found.
src/bu-components/SelectPrepareFileModal.jsx
View file @
05f7474b
...
...
@@ -405,7 +405,7 @@ class SelectPrepareFileModal extends React.Component {
parentId
:
id
}
Service
.
Hades
(
'public/
apollo
/saveFolder'
,
params
).
then
((
res
)
=>
{
Service
.
Hades
(
'public/
hadesStore
/saveFolder'
,
params
).
then
((
res
)
=>
{
const
{
query
,
selectedFileList
,
currentRootDisk
}
=
this
.
state
;
const
_query
=
_
.
clone
(
query
);
const
_selectedFileList
=
[...
selectedFileList
,
res
.
result
];
...
...
src/modules/course-manage/components/AddLiveBasic.jsx
0 → 100644
View file @
05f7474b
/*
* @Author: 吴文洁
* @Date: 2020-07-15 17:29:12
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-15 18:16:05
* @Description: 新建/编辑直播课-基本信息
*/
import
React
from
'react'
;
import
{
Input
,
Button
,
message
,
Cascader
}
from
'antd'
;
import
UploadOss
from
"@/core/upload"
;
import
{
ImgCutModalNew
}
from
'@/components'
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
'./AddLiveBasic.less'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
;
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
};
class
AddLiveBasic
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
imageFile
:
null
,
showCutModal
:
false
,
courseCatalogList
:[]
}
}
componentWillUnmount
()
{
}
componentDidMount
(){
this
.
getCourseCatalogList
();
}
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
this
.
setState
({
courseCatalogList
:
res
.
result
.
records
})
});
}
// 上传封面图
handleShowImgCutModal
=
(
event
)
=>
{
const
imageFile
=
event
.
target
.
files
[
0
];
if
(
!
imageFile
)
return
;
this
.
setState
({
imageFile
,
showCutModal
:
true
,
});
}
// 使用默认封面图
handleResetCoverUrl
=
()
=>
{
const
{
data
:
{
coverUrl
}
}
=
this
.
props
;
const
isDefaultCover
=
coverUrl
===
defaultCover
;
// 如果已经是默认图的话,不做任何任何处理
if
(
isDefaultCover
)
return
;
message
.
success
(
'已替换为默认图'
);
this
.
props
.
onChange
(
'coverId'
,
null
,
defaultCover
);
}
catalogChange
=
(
value
)
=>
{
const
changeValueLength
=
value
.
length
;
switch
(
changeValueLength
){
case
1
:
this
.
props
.
onChange
(
'categoryId'
,
value
[
0
]);
break
;
case
2
:
this
.
props
.
onChange
(
'categoryId'
,
value
[
1
]);
break
;
default
:
break
;
}
}
render
()
{
const
{
showCutModal
,
imageFile
,
courseCatalogList
}
=
this
.
state
;
const
{
data
,
pageType
,
isEdit
}
=
this
.
props
;
const
{
courseName
,
coverUrl
,
categoryName
}
=
data
;
console
.
log
(
'categoryName'
,
categoryName
);
const
fileName
=
''
;
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
return
(
<
div
className=
"add-live__basic-info"
>
<
div
className=
"course-name"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
课程名称:
</
span
>
<
Input
value=
{
courseName
}
placeholder=
"请输入直播名称(40字以内)"
maxLength=
{
40
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'courseName'
,
e
.
target
.
value
)}
}
/>
</
div
>
<
div
className=
"course-cover"
>
<
span
className=
"label"
>
封面图:
</
span
>
<
div
className=
"course-cover__wrap"
>
<
div
className=
"img-content"
>
{
isDefaultCover
&&
<
span
className=
"tag"
>
默认图
</
span
>
}
<
img
src=
{
coverUrl
}
/>
</
div
>
<
div
className=
"opt-btns"
>
<
input
type=
"file"
value=
{
fileName
}
// 避免选择同一文件 value不改变 不触发onChange事件
accept=
"image/png, image/jpeg, image/bmp, image/jpg"
ref=
"stagePicInputFile"
style=
{
{
display
:
'none'
}
}
onChange=
{
(
event
)
=>
{
this
.
handleShowImgCutModal
(
event
)
}
}
/>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
currentInputFile
:
this
.
refs
.
stagePicInputFile
});
this
.
refs
.
stagePicInputFile
.
click
();
}
}
>
上传图片
</
Button
>
<
span
className=
{
`default-btn ${isDefaultCover ? 'disabled' : ''}`
}
onClick=
{
this
.
handleResetCoverUrl
}
>
使用默认图
</
span
>
<
div
className=
"tips"
>
建议尺寸690*398像素,图片支持jpg、jpeg、png格式。
</
div
>
</
div
>
</
div
>
</
div
>
<
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=
"请选择课程分类"
/>
}
{
(
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=
"请选择课程分类"
/>
}
</
div
>
<
ImgCutModalNew
title=
"裁剪"
width=
{
550
}
cutWidth=
{
500
}
cutHeight=
{
282
}
cutContentWidth=
{
500
}
cutContentHeight=
{
300
}
visible=
{
showCutModal
}
imageFile=
{
imageFile
}
bizCode=
'LIVE_COURSE_MEDIA'
onOk=
{
(
urlStr
,
resourceId
)
=>
{
this
.
setState
({
showCutModal
:
false
});
this
.
props
.
onChange
(
'coverId'
,
resourceId
,
urlStr
);
this
.
state
.
currentInputFile
.
value
=
''
;
}
}
onClose=
{
()
=>
this
.
setState
({
showCutModal
:
false
})
}
reUpload=
{
()
=>
{
this
.
state
.
currentInputFile
.
click
()
}
}
/>
</
div
>
)
}
}
export
default
AddLiveBasic
;
\ No newline at end of file
src/modules/course-manage/components/AddLiveClass.jsx
0 → 100644
View file @
05f7474b
/*
* @Author: 吴文洁
* @Date: 2020-07-15 17:44:24
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2020-11-23 22:06:33
* @Description: 添加直播课-上课信息
*/
import
React
from
'react'
;
import
{
TimePicker
,
Select
,
Spin
,
Tooltip
,
DatePicker
}
from
'antd'
;
import
{
InfoCircleFilled
}
from
'@ant-design/icons'
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
// import TeacherSelectV5 from "@/modules/classManage_V5/classDetail/TeacherSelectV5";
import
ChargeExplainModal
from
'../modal/ChargeExplainModal'
;
import
SelectStudent
from
'../modal/select-student/index'
;
import
MultipleDatePicker
from
'@/components/MultipleDatePicker'
;
import
moment
from
'moment'
;
import
'./AddLiveClass.less'
;
const
defaultTeacherQuery
=
{
size
:
10
,
current
:
1
,
nickName
:
null
}
const
defaultAssistantQuery
=
{
size
:
10
,
current
:
1
,
nickName
:
null
}
class
AddLiveClass
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
loading
:
false
,
hasNext
:
false
,
assistantHasNext
:
false
,
teacherQuery
:
defaultTeacherQuery
,
teacherList
:[],
assistantQuery
:
defaultAssistantQuery
,
assistantList
:
[],
// 助教老师列表
addLiveType
:
props
.
addLiveType
}
}
componentDidMount
()
{
this
.
getTeacherList
();
this
.
getAssistantList
();
}
getTeacherList
(
current
=
1
,
selectList
){
const
{
teacherQuery
,
teacherList
}
=
this
.
state
;
const
_query
=
{
...
teacherQuery
,
current
,
size
:
10
};
StoreService
.
getEmployeeList
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
,
hasNext
}
=
result
;
const
list
=
current
>
1
?
teacherList
.
concat
(
records
)
:
records
;
this
.
setState
({
hasNext
,
teacherList
:
list
,
})
});
}
// 获取助教老师列表
getAssistantList
=
(
current
=
1
,
selectList
)
=>
{
const
{
assistantQuery
,
assistantList
}
=
this
.
state
;
const
_query
=
{
...
assistantQuery
,
current
,
size
:
10
};
StoreService
.
getEmployeeList
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
,
hasNext
}
=
result
;
const
list
=
current
>
1
?
assistantList
.
concat
(
records
)
:
records
;
this
.
setState
({
assistantHasNext
:
hasNext
,
assistantList
:
list
,
})
});
}
// 滑动加载更多讲师列表
handleScrollTeacherList
=
(
e
)
=>
{
const
{
hasNext
}
=
this
.
state
;
const
container
=
e
.
target
;
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
;
if
(
scrollToBottom
&&
hasNext
)
{
const
{
teacherQuery
}
=
this
.
state
;
this
.
getTeacherList
(
teacherQuery
.
current
+
1
);
}
}
// 滑动加载更多助教列表
handleScrollAssistantList
=
(
e
)
=>
{
const
{
assistantHasNext
}
=
this
.
state
;
const
container
=
e
.
target
;
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
;
if
(
scrollToBottom
&&
assistantHasNext
)
{
const
{
assistantQuery
}
=
this
.
state
;
this
.
getAssistantList
(
assistantQuery
.
current
+
1
);
}
}
disabledDate
=
(
current
)
=>
{
return
current
.
valueOf
()
<
moment
().
subtract
(
1
,
"days"
)
};
selectMultiDate
=
(
calendarTime
)
=>
{
this
.
setState
({
calendarTime
})
}
render
()
{
const
{
loading
,
teacherList
,
assistantList
,
teacherQuery
,
assistantQuery
}
=
this
.
state
;
const
{
pageType
,
data
,
isEdit
}
=
this
.
props
;
const
{
endTime
,
startTime
,
calendarTime
,
teacherId
,
liveDate
,
timeHorizonStart
,
timeHorizonEnd
,
assistant
}
=
data
;
console
.
log
(
"teacherId"
,
teacherId
);
return
(
<
Spin
spinning=
{
loading
}
>
<
div
className=
"add-live__class-info"
>
{
/* <div className="course">
<div className="day">
<span className="label">
<span className="require">*</span>
上课日期
<Tooltip
overlayStyle={{maxWidth: 300, zIndex: '9999'}}
title={<div style={{width: '266px'}}>支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:<br/>张三的语文课_9月18日<br/>张三的语文课_9月19日......</div>}>
<InfoCircleFilled className="tip-icon"/>
</Tooltip>:
</span>
<div>
<div className='select-day'>
已选
<span className="mark-day">
{isLongArr(calendarTime)
? calendarTime.length : 0
}
</span> 天
</div>
<MultipleDatePicker
selectDateList={calendarTime}
onSelect={this.selectMultiDate}
canSelectTodayBefore={false}
/>
</div>
</div>
<div className="hour" id="hour">
<span className="label"><span className="require">*</span>上课时间:</span>
<TimePicker
format="HH:mm"
value={startTime ? moment(startTime) : null}
placeholder="开始时间"
style={{ width: 100, minWidth: 100}}
onChange={(time) => {
this.props.onChange('startTime', time);
}}
/> ~
<TimePicker
format="HH:mm"
value={endTime ? moment(endTime) : null}
placeholder="结束时间"
style={{ width: 100, minWidth: 100 }}
onChange={(time) => {
this.props.onChange('endTime', time)
}}
/>
</div>
</div> */
}
{
pageType
===
'add'
&&
<
div
className=
"course"
>
<
div
className=
"day"
>
<
span
className=
"label"
>
<
span
className=
"require"
>
*
</
span
>
上课日期
<
Tooltip
overlayStyle=
{
{
maxWidth
:
300
,
zIndex
:
'9999'
}
}
title=
{
<
div
style=
{
{
width
:
'266px'
}
}
>
支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:
<
br
/>
张三的语文课_9月18日
<
br
/>
张三的语文课_9月19日......
</
div
>
}
>
<
span
className=
"iconfont"
>

</
span
>
</
Tooltip
>
:
</
span
>
<
div
>
<
div
className=
'select-day'
>
已选
<
span
className=
"mark-day"
>
{
isLongArr
(
calendarTime
)
?
calendarTime
.
length
:
0
}
</
span
>
天
</
div
>
<
MultipleDatePicker
selectDateList=
{
calendarTime
}
onSelect=
{
this
.
selectMultiDate
}
canSelectTodayBefore=
{
false
}
/>
</
div
>
</
div
>
<
div
className=
"hour"
id=
"hour"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
上课时间:
</
span
>
<
TimePicker
format=
"HH:mm"
value=
{
startTime
?
moment
(
startTime
)
:
null
}
placeholder=
"开始时间"
style=
{
{
width
:
100
,
minWidth
:
100
}
}
onChange=
{
(
time
)
=>
{
this
.
props
.
onChange
(
'startTime'
,
time
);
}
}
/>
~
<
TimePicker
format=
"HH:mm"
value=
{
endTime
?
moment
(
endTime
)
:
null
}
placeholder=
"结束时间"
style=
{
{
width
:
100
,
minWidth
:
100
}
}
onChange=
{
(
time
)
=>
{
this
.
props
.
onChange
(
'endTime'
,
time
)
}
}
/>
</
div
>
</
div
>
}
{
pageType
===
'edit'
&&
<
div
className=
"time"
id=
"time"
>
<
div
className=
"content"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
上课时间:
</
span
>
<
DatePicker
disabled=
{
!
isEdit
}
format=
"YYYY-MM-DD"
value=
{
liveDate
?
moment
(
Number
(
liveDate
))
:
null
}
style=
{
{
width
:
160
,
minWidth
:
130
,
marginRight
:
10
}
}
placeholder=
"上课日期"
getCalendarContainer=
{
()
=>
document
.
getElementById
(
"time"
)
}
disabledDate=
{
this
.
disabledDate
}
onChange=
{
(
date
)
=>
{
this
.
props
.
onChange
(
'liveDate'
,
date
)
}
}
/>
<
TimePicker
disabled=
{
!
isEdit
}
format=
"HH:mm"
value=
{
timeHorizonStart
?
moment
(
Number
(
timeHorizonStart
))
:
null
}
defaultOpenValue=
{
moment
(
new
Date
().
setHours
(
0
,
0
,
0
,
0
))
}
placeholder=
"开始时间"
style=
{
{
width
:
100
,
minWidth
:
100
,
marginRight
:
10
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
"time"
)
}
onChange=
{
(
time
)
=>
{
this
.
props
.
onChange
(
'timeHorizonStart'
,
time
)
}
}
/>
<
TimePicker
disabled=
{
!
isEdit
}
format=
"HH:mm"
value=
{
timeHorizonEnd
?
moment
(
Number
(
timeHorizonEnd
))
:
null
}
defaultOpenValue=
{
moment
(
new
Date
().
setHours
(
0
,
0
,
0
,
0
))
}
placeholder=
"结束时间"
style=
{
{
width
:
100
,
minWidth
:
100
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
"time"
)
}
onChange=
{
(
time
)
=>
{
this
.
props
.
onChange
(
'timeHorizonEnd'
,
time
)
}
}
/>
</
div
>
</
div
>
}
<
div
className=
"teacher"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
讲师:
</
span
>
<
Select
placeholder=
"请选择讲师"
style=
{
{
width
:
240
,
marginTop
:
6
}
}
disabled=
{
!
isEdit
?
true
:
false
}
showSearch
allowClear
value=
{
teacherId
}
filterOption=
{
(
input
,
option
)
=>
option
}
onPopupScroll=
{
this
.
handleScrollTeacherList
}
onChange=
{
(
value
)
=>
{
this
.
props
.
onChange
(
'teacherId'
,
value
)
}
}
onSearch=
{
(
value
)
=>
{
teacherQuery
.
nickName
=
value
this
.
setState
({
teacherQuery
},
()
=>
{
this
.
getTeacherList
()
})
}
}
>
{
_
.
map
(
teacherList
,
(
item
,
index
)
=>
{
return
(
<
Select
.
Option
value=
{
item
.
userId
}
key=
{
item
.
userId
}
>
{
item
.
nickName
}
</
Select
.
Option
>
);
})
}
</
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
)
=>
{
return
(
<
Select
.
Option
value=
{
item
.
userId
}
key=
{
item
.
userId
}
>
{
item
.
nickName
}
</
Select
.
Option
>
);
})
}
</
Select
>
</
div
>
</
div
>
</
Spin
>
)
}
}
export
default
AddLiveClass
;
\ No newline at end of file
src/modules/course-manage/components/AddLiveIntro.jsx
0 → 100644
View file @
05f7474b
/*
* @Author: 吴文洁
* @Date: 2020-07-16 11:05:17
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2020-11-24 14:29:52
* @Description: 添加直播-简介
*/
import
React
from
'react'
;
import
{
Input
,
message
,
Upload
,
Radio
,
Row
,
Col
,
Button
,
Popover
,
Switch
}
from
'antd'
;
import
Service
from
'@/common/js/service'
;
import
EditorBox
from
'../components/EditorBox'
;
import
User
from
'@/common/js/user'
;
import
UploadOss
from
'@/core/upload'
;
import
'./AddLiveIntro.less'
;
// import SelectPrepareFileModal from '../modal/SelectPrepareFileModal';
import
{
DISK_MAP
}
from
'@/common/constants/academic/lessonEnum'
;
import
{
ImgCutModalNew
}
from
'@/components'
;
const
{
TextArea
}
=
Input
;
const
defaultCover
=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1599635741526.png'
;
class
AddLiveIntro
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
warmUrl
:
defaultCover
,
showSelectFileModal
:
false
,
diskList
:
[],
}
}
// 上传封面图
handleShowImgCutModal
=
(
event
)
=>
{
const
imageFile
=
event
.
target
.
files
[
0
];
if
(
!
imageFile
)
return
;
this
.
setState
({
imageFile
,
showCutModal
:
true
,
});
}
// 选择暖场资源
handleSelectVideo
=
(
file
)
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
const
{
ossUrl
,
resourceId
,
folderName
,
folderFormat
,
folderSize
}
=
file
;
const
liveCourseWarmMedia
=
{
contentType
:
'WARMUP'
,
mediaType
:
folderFormat
===
'MP4'
?
'VIDEO'
:
'PICTURE'
,
mediaContent
:
resourceId
,
mediaUrl
:
ossUrl
,
mediaName
:
folderName
,
size
:
folderSize
}
this
.
props
.
onChange
(
'liveCourseWarmMedia'
,
liveCourseWarmMedia
);
}
// 获取机构可见的磁盘
handleFetchDiskList
=
()
=>
{
// axios.Apollo('public/apollo/getUserDisk', {}).then((res) => {
// const { result = [] } = res;
// const diskList = result.map((item) => {
// return {
// ...item,
// folderName: DISK_MAP[item.disk]
// }
// });
// this.setState({ diskList });
// });
}
// 删除简介
handleDeleteIntro
=
(
index
)
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
liveCourseMediaRequests
.
splice
(
index
,
1
);
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
}
// 上移简介
handleMoveUpIntro
=
(
index
)
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
const
prevItem
=
liveCourseMediaRequests
[
index
];
const
nextItem
=
liveCourseMediaRequests
[
index
+
1
];
liveCourseMediaRequests
.
splice
(
index
,
2
,
nextItem
,
prevItem
);
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
}
// 下移简介
handleMoveDownIntro
=
(
index
)
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
const
prevItem
=
liveCourseMediaRequests
[
index
-
1
];
const
nextItem
=
liveCourseMediaRequests
[
index
];
liveCourseMediaRequests
.
splice
(
index
-
1
,
2
,
nextItem
,
prevItem
);
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
}
renderLittleIcon
=
(
index
)
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
return
(
<
div
className=
"little-icon"
>
<
span
className=
"icon iconfont close"
onClick=
{
()
=>
{
this
.
handleDeleteIntro
(
index
);
}
}
></
span
>
{
index
>
0
&&
<
span
className=
"icon iconfont"
onClick=
{
()
=>
{
this
.
handleMoveDownIntro
(
index
);
}
}
>

</
span
>
}
{
index
!==
liveCourseMediaRequests
.
length
-
1
&&
<
span
className=
"icon iconfont"
onClick=
{
()
=>
{
this
.
handleMoveUpIntro
(
index
);
}
}
>

</
span
>
}
</
div
>
)
}
handleChangeIntro
=
(
index
,
value
,
length
)
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
liveCourseMediaRequests
[
index
].
mediaContent
=
value
;
liveCourseMediaRequests
[
index
].
mediaContentLength
=
length
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
}
handleAddIntroText
=
()
=>
{
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
liveCourseMediaRequests
.
push
({
contentType
:
"INTRO"
,
mediaType
:
'TEXT'
,
mediaContent
:
''
,
key
:
window
.
random_string
(
16
)
});
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
}
handleUpload
=
(
Blob
)
=>
{
// 最多添加九图片
const
{
liveCourseMediaRequests
}
=
this
.
props
.
data
;
const
list
=
_
.
filter
(
liveCourseMediaRequests
,
(
item
)
=>
{
return
item
.
mediaType
==
"PICTURE"
;
});
if
(
list
.
length
>
8
)
{
message
.
warning
(
"最多添加9张图片"
);
return
;
}
const
{
instId
}
=
window
.
currentUserInstInfo
;
const
{
name
,
size
}
=
Blob
;
const
resourceName
=
window
.
random_string
(
16
)
+
name
.
slice
(
name
.
lastIndexOf
(
'.'
));
// UploadOss.uploadBlobToOSS(Blob, 'avatar' + (new Date()).valueOf(),'', 'id').then((imgAddress) => {
// liveCourseMediaRequests.push({
// contentType:"INTRO",
// size,
// mediaName: name,
// mediaContent: imgAddress.resourceId,
// mediaType: 'PICTURE',
// });
// this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
// });
const
params
=
{
resourceName
,
accessTypeEnum
:
'PUBLIC'
,
bizCode
:
'LIVE_COURSE_MEDIA'
,
instId
:
User
.
getStoreId
(),
}
Service
.
Hades
(
"public/hades/commonOssAuthority"
,
params
).
then
((
res
)
=>
{
const
{
resourceId
}
=
res
.
result
;
const
signInfo
=
res
.
result
;
// 构建上传的表单
const
xhr
=
new
XMLHttpRequest
();
const
formData
=
new
FormData
();
formData
.
append
(
"OSSAccessKeyId"
,
signInfo
.
accessId
);
formData
.
append
(
"policy"
,
signInfo
.
policy
);
formData
.
append
(
"callback"
,
signInfo
.
callback
);
formData
.
append
(
"Signature"
,
signInfo
.
signature
);
formData
.
append
(
"key"
,
signInfo
.
key
);
formData
.
append
(
"file"
,
Blob
);
formData
.
append
(
"success_action_status"
,
200
);
xhr
.
open
(
"POST"
,
signInfo
.
host
);
xhr
.
onload
=
()
=>
{
liveCourseMediaRequests
.
push
({
size
,
mediaName
:
name
,
mediaContent
:
resourceId
,
mediaType
:
'PICTURE'
,
mediaUrl
:
window
.
URL
.
createObjectURL
(
Blob
),
});
this
.
props
.
onChange
(
'liveCourseMediaRequests'
,
liveCourseMediaRequests
);
};
xhr
.
onerror
=
()
=>
{
xhr
.
abort
();
};
xhr
.
send
(
formData
);
this
.
setState
({
xhr
})
});
}
whetherVisitorsJoinChange
=
()
=>
{
if
(
this
.
props
.
data
.
whetherVisitorsJoin
===
"NO"
){
this
.
props
.
onChange
(
'whetherVisitorsJoin'
,
'YES'
)
}
else
{
this
.
props
.
onChange
(
'whetherVisitorsJoin'
,
'NO'
)
}
}
componentWillMount
()
{
this
.
handleFetchDiskList
();
}
// componentWillUnmount() {
// const { xhr } = this.state;
// xhr && xhr.abort();
// }
render
()
{
const
{
liveType
,
isXiaomai
,
isEdit
,
data
:
{
introduction
,
needRecord
,
whetherVisitorsJoin
,
liveCourseMediaRequests
=
[],
liveCourseWarmMedia
=
{}
}
}
=
this
.
props
;
console
.
log
(
"whetherVisitorsJoin"
,
whetherVisitorsJoin
);
const
{
showCutModal
,
warmUrl
,
showSelectFileModal
,
diskList
,
imageFile
}
=
this
.
state
return
(
<
div
className=
"add-live__intro-info"
>
<
div
className=
"playback"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
直播回放:
</
span
>
<
div
className=
"content"
>
<
Radio
.
Group
value=
{
needRecord
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'needRecord'
,
e
.
target
.
value
)
}
}
disabled=
{
!
isEdit
?
true
:
false
}
>
<
Row
style=
{
{
marginBottom
:
'5px'
}
}
>
<
Col
span=
{
8
}
>
<
Radio
value=
"YES"
>
自动录制
</
Radio
>
</
Col
>
<
Col
span=
{
16
}
>
<
span
className=
"playback__text"
>
系统自助进行全程直播录制
</
span
>
</
Col
>
</
Row
>
<
Row
>
<
Col
span=
{
8
}
>
<
Radio
value=
"NO"
>
手动录制
</
Radio
>
</
Col
>
<
Col
span=
{
16
}
>
<
span
className=
"playback__text"
>
讲师手动选择何时开始录制
</
span
>
</
Col
>
</
Row
>
</
Radio
.
Group
>
</
div
>
</
div
>
<
div
className=
"allow-tourist-join"
>
<
span
className=
"label"
>
允许游客加入:
</
span
>
<
div
className=
"content"
>
<
Row
>
<
Col
span=
{
3
}
>
<
Switch
checked=
{
whetherVisitorsJoin
===
"YES"
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
</
Col
>
<
Col
span=
{
21
}
>
<
div
>
开启:用户可直接进入直播间观看直播
</
div
>
<
div
>
关闭:用户需先填写手机号并短信验证,通过后才可进入直播间观看直播
</
div
>
</
Col
>
</
Row
>
</
div
>
</
div
>
<
div
className=
"warmup"
>
<
span
className=
"label"
>
直播暖场图:
</
span
>
<
div
className=
"course-cover__wrap"
>
<
div
className=
"img-content"
style=
{
liveCourseWarmMedia
.
mediaUrl
?
{
background
:
'#000'
}
:
{}
}
>
<
img
src=
{
liveCourseWarmMedia
.
mediaType
===
'VIDEO'
?
`${liveCourseWarmMedia.mediaUrl}?x-oss-process=video/snapshot,t_0,m_fast`
:
(
liveCourseWarmMedia
.
mediaUrl
?
liveCourseWarmMedia
.
mediaUrl
:
defaultCover
)
}
/>
{
liveCourseWarmMedia
.
mediaUrl
&&
<
div
className=
"img-delete-wrap"
>
<
img
src=
"https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1600073872956.png"
onClick=
{
()
=>
{
this
.
props
.
onChange
(
'liveCourseWarmMedia'
,
{});
}
}
/>
</
div
>
}
</
div
>
<
div
className=
"opt-btns"
>
<
Button
disabled=
{
!
isEdit
}
onClick=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
true
})
}
}
>
上传图片/视频
</
Button
>
<
div
className=
"tips"
>
建议尺寸1280*720px或16:9。图片最大5M,支持jpg、jpeg和png;视频最大500M,支持mp4。
</
div
>
<
Popover
content=
{
<
div
className=
"example-wrap"
>
<
p
className=
"title"
>
直播间暖场图示例
</
p
>
<
p
className=
"text"
>
直播开始前,展示在直播间视频区域
</
p
>
<
img
src=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1599644482652.png'
></
img
>
</
div
>
}
>
<
div
className=
"checkExample"
>
查看示例
</
div
>
</
Popover
>
</
div
>
</
div
>
</
div
>
<
div
className=
"introduce"
>
<
span
className=
"label"
>
直播简介:
</
span
>
<
div
className=
"content"
>
<
div
className=
"intro-list"
>
{
liveCourseMediaRequests
.
map
((
item
,
index
)
=>
{
if
(
item
.
mediaType
===
'TEXT'
)
{
return
(
<
div
className=
"intro-list__item"
key=
{
item
.
key
}
>
<
EditorBox
detail=
{
{
content
:
item
.
mediaContent
}
}
onChange=
{
(
val
,
length
)
=>
{
this
.
handleChangeIntro
(
index
,
val
,
length
)
}
}
/>
{
this
.
renderLittleIcon
(
index
)
}
</
div
>
)
}
if
(
item
.
mediaType
===
'PICTURE'
)
{
return
(
<
div
className=
"intro-list__item picture"
key=
{
index
}
>
<
div
className=
"img__wrap"
>
<
img
src=
{
item
.
mediaUrl
}
/>
</
div
>
{
this
.
renderLittleIcon
(
index
)
}
</
div
>
)
}
})
}
</
div
>
<
div
className=
"operate"
>
<
div
className=
"operate__item"
onClick=
{
this
.
handleAddIntroText
}
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
>
文字
</
span
>
</
div
>
<
Upload
fileList=
{
[]
}
accept=
"image/jpeg, image/png, image/jpg, image/gif"
beforeUpload=
{
(
Blob
)
=>
{
this
.
handleUpload
(
Blob
);
return
false
;
}
}
>
<
div
className=
"operate__item"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
>
图片
</
span
>
</
div
>
</
Upload
>
</
div
>
<
div
className=
"tips"
>
• 图片支持jpeg、jpg、png、gif格式
</
div
>
</
div
>
</
div
>
{
/* 选择暖场图文件弹窗 */
}
{
/* <SelectPrepareFileModal
operateType="select"
accept="video/mp4,image/jpeg,image/png,image/jpg"
selectTypeList={['MP4', 'JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png、mp4'
isOpen={showSelectFileModal}
diskList={diskList}
onClose={() => {
this.setState({ showSelectFileModal: false })
}}
onSelect={this.handleSelectVideo}
/> */
}
</
div
>
)
}
}
export
default
AddLiveIntro
;
src/modules/course-manage/components/LiveCourseList.less
0 → 100644
View file @
05f7474b
.live-course-list {
margin-top: 16px;
.record__item {
display: flex;
align-items: center;
.course-cover {
min-width: 90px;
max-width: 90px;
height: 50px;
border-radius: 2px;
margin-right: 8px;
}
.course-name{
font-size: 14px;
font-weight: 500;
color: #333333;
line-height: 20px;
font-weight: bold;
}
.course-time{
font-size: 12px;
font-weight: 400;
color: #666666;
line-height: 20px;
}
.course-status {
font-size:12px;
line-height:18px;
display:inline-block;
border-radius:2px;
padding:0 8px;
margin-left:4px;
}
.teacher{
font-size: 12px;
color: #666666;
line-height: 20px;
}
.assistant{
font-size: 12px;
color: #666666;
line-height: 20px;
}
.split {
margin: 0 4px;
color: #BFBFBF;
}
}
.categoryName{
font-size: 14px;
color: #666666;
line-height: 20px;
}
.courseware{
font-size: 14px;
color: #5289FA;
line-height: 20px;
}
.quota-icon{
color:#5289FA;
}
.operate {
display: flex;
align-items: center;
flex-wrap: wrap;
.operate__item {
color: #5289FA;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
}
}
.operate-text {
color: #5289FA;
cursor: pointer;
}
.course-start-end {
margin-left: 16px;
width: 78px;
height: 20px;
border-radius: 2px;
border: 1px solid rgba(204, 204, 204, 1);
display: flex;
align-items: center;
cursor: pointer;
white-space: nowrap;
.start-icon {
color: #3296fa;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.end-icon {
color: #00d700;
font-size: 12px;
transform: scale(0.8);
margin: 0 5px;
}
.start-end-text {
font-size: 12px;
}
}
}
.live-course-more-menu {
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border-radius: 4px;
div {
line-height: 30px;
padding: 0 15px;
cursor: pointer;
&:hover {
background: #f3f6fa;
}
}
}
.tipTitle {
.type {
font-weight: 700;
}
}
\ No newline at end of file
src/modules/course-manage/modal/SelectPrepareFileModal.jsx
View file @
05f7474b
...
...
@@ -15,7 +15,7 @@ import { getEllipsText } from "@/core/util";
import
DefaultIcon
from
'@/modules/common/DefaultIcon'
;
import
UploadProgressModal
from
'./UploadProgressModal'
;
import
NonCompliantFileModal
from
'./NonCompliantFileModal'
;
import
Service
from
'@/common/js/service'
;
import
{
DEFAULT_SIZE_UNIT
,
FileTypeIcon
,
NonCompliantFileMap
,
DISK_LIST
,
SupportFileType
,
LocalFileType
...
...
@@ -38,8 +38,13 @@ const defaultRootDisk = {
}
const
FOLDERLIST_URL_MAP
=
{
<<
<
<<<<
HEAD
'
MYSELF
':
'
public
/
apollo
/
folderList
',
'
COMMON
':
'
public
/
hadesStore
/
folderList
',
=======
'
MYSELF
':
'
public
/
hadesStore
/
folderList
',
'
COMMON
':
'
public
/
apollo
/
commonFolderList
',
>
>>>>>>
1c42770... feat:创建课程条助教选项改为多选
'EMPLOYEE': 'public/apollo/employeeFolderList'
};
...
...
@@ -110,7 +115,7 @@ class SelectPrepareFileModal extends React.Component {
_params
.
folderFileType
=
selectTypeList
}
axios
.
Apollo
(
FOLDERLIST_URL_MAP
[
currentRootDisk
.
disk
],
_params
).
then
((
res
)
=>
{
Service
.
Hades
(
FOLDERLIST_URL_MAP
[
currentRootDisk
.
disk
],
_params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
...
...
@@ -423,7 +428,7 @@ class SelectPrepareFileModal extends React.Component {
parentId
:
id
}
axios
.
Apollo
(
'public/apollo
/saveFolder'
,
params
).
then
((
res
)
=>
{
Service
.
Hades
(
'public/hadesStore
/saveFolder'
,
params
).
then
((
res
)
=>
{
const
{
query
,
selectedFileList
,
currentRootDisk
}
=
this
.
state
;
const
_query
=
_
.
clone
(
query
);
{
/* TODO:麦麦打卡类目申请下来后解开视频入口 */
}
...
...
src/modules/resource-disk/components/FolderManage.jsx
View file @
05f7474b
...
...
@@ -189,7 +189,7 @@ class FolderManage extends React.Component {
parentId
:
id
}
Service
.
Hades
(
'public/
apollo
/saveFolder'
,
params
).
then
((
res
)
=>
{
Service
.
Hades
(
'public/
hadesStore
/saveFolder'
,
params
).
then
((
res
)
=>
{
const
query
=
_
.
clone
(
this
.
state
.
query
);
query
.
current
=
1
;
this
.
setState
({
query
},
()
=>
{
...
...
@@ -214,7 +214,7 @@ class FolderManage extends React.Component {
if
(
selectFolderPathList
.
length
>
1
)
{
params
.
newParentId
=
id
}
Service
.
Hades
(
'public/
apollo/moveFolde
r'
,
params
).
then
((
res
)
=>
{
Service
.
Hades
(
'public/
hadesStore/moveFolder
r'
,
params
).
then
((
res
)
=>
{
// 判断是否将文件移动到了自身或者子目录
const
{
result
=
{}
}
=
res
;
...
...
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