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
1402a09b
Commit
1402a09b
authored
Jun 02, 2021
by
guomingpang
Browse files
Options
Browse Files
Download
Plain Diff
fix:merge hotfix/hotfix/pangguoming/20210601/plan_list_add_cover to master
parents
5bd610bd
e340da37
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1661 additions
and
1541 deletions
+1661
-1541
src/core/antd.less
+5
-5
src/core/page.less
+9
-9
src/modules/course-manage/video-course/AddVideoCourse.jsx
+244
-244
src/modules/course-manage/video-course/components/VideoCourseList.jsx
+1
-1
src/modules/home/Home.less
+1
-0
src/modules/knowledge-base/components/KnowledgeBaseList.jsx
+197
-197
src/modules/knowledge-base/index.jsx
+26
-30
src/modules/knowledge-base/modal/AddCourse.jsx
+12
-11
src/modules/knowledge-base/modal/LiveList.less
+6
-6
src/modules/plan-manage/AddPlan.jsx
+4
-0
src/modules/plan-manage/components/BasicInfo.jsx
+332
-310
src/modules/plan-manage/components/EmployeeShareData.jsx
+1
-0
src/modules/plan-manage/components/PlanList.jsx
+312
-291
src/modules/plan-manage/components/PlanList.less
+70
-48
src/modules/plan-manage/modal/relatedCourseModal.jsx
+366
-353
src/modules/plan-manage/modal/relatedCourseModal.less
+41
-1
src/modules/root/WechatLogin.less
+33
-35
src/modules/teach-tool/examination-manager/Index.tsx
+1
-0
No files found.
src/core/antd.less
View file @
1402a09b
...
...
@@ -4,7 +4,7 @@
* @Last Modified by: chenshu
* @Last Modified time: 2020-08-31 14:55:30
*/
@import
"./variables.less"
;
@import
'./variables.less'
;
@active-color: #2966ff;
...
...
@@ -234,7 +234,7 @@
}
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
font-weight: 500!important;
font-weight: 500
!important;
}
.ant-tabs-nav .ant-tabs-tab-active {
...
...
@@ -259,7 +259,7 @@
//display: none!important;
&:after {
content:
""
;
content:
''
;
display: inline-block;
position: absolute;
width: 30px;
...
...
@@ -660,8 +660,8 @@ td.ant-table-column-sort {
background-color: #2966ff !important;
opacity: 0.8 !important;
}
&:active{
background-color:
#5C8AFF
!important;
&:active
{
background-color:
#5c8aff
!important;
}
}
...
...
src/core/page.less
View file @
1402a09b
...
...
@@ -7,7 +7,7 @@
left: 0px;
right: 0;
bottom: 0;
z-index:3;
z-index:
3;
background-color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
...
...
@@ -20,12 +20,12 @@
bottom: 0;
z-index: 102;
overflow: auto;
margin:0 16px;
.box{
&:first-child{
margin:
0 16px;
.box
{
&:first-child
{
margin-bottom: 8px;
}
&:last-child{
&:last-child
{
margin-bottom: 16px;
}
}
...
...
@@ -48,10 +48,10 @@
.content-header {
padding: 16px 16px 8px 16px;
line-height: 30px;
font-size:24px;
color:#333;
font-weight:bold;
background: #
FFF
;
font-size:
24px;
color:
#333;
font-weight:
bold;
background: #
fff
;
h1 {
font-weight: normal;
display: inline-block;
...
...
src/modules/course-manage/video-course/AddVideoCourse.jsx
View file @
1402a09b
...
...
@@ -2,56 +2,56 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: wufan
* @LastEditTime: 2021-05-30
17:33:0
9
* @LastEditTime: 2021-05-30
20:35:4
9
* @Description: 视频课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
Cascader
}
from
'antd'
import
{
DISK_MAP
,
FileTypeIcon
,
FileVerifyMap
}
from
'@/common/constants/academic/lessonEnum'
import
{
ImgCutModalNew
}
from
'@/components'
import
ShowTips
from
'@/components/ShowTips'
import
Breadcrumbs
from
'@/components/Breadcrumbs'
import
AddVideoIntro
from
'./components/AddVideoIntro'
import
SelectStudent
from
'../modal/select-student'
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
import
PreviewCourseModal
from
'../modal/PreviewCourseModal'
import
StoreService
from
'@/domains/store-domain/storeService'
import
CourseService
from
'@/domains/course-domain/CourseService'
import
Service
from
'@/common/js/service'
import
User
from
'@/common/js/user'
import
_
from
'underscore'
import
Upload
from
'@/core/upload'
import
{
randomString
}
from
'@/domains/basic-domain/utils'
import
$
from
'jquery'
import
React
from
'react'
;
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
Cascader
}
from
'antd'
;
import
{
DISK_MAP
,
FileTypeIcon
,
FileVerifyMap
}
from
'@/common/constants/academic/lessonEnum'
;
import
{
ImgCutModalNew
}
from
'@/components'
;
import
ShowTips
from
'@/components/ShowTips'
;
import
Breadcrumbs
from
'@/components/Breadcrumbs'
;
import
AddVideoIntro
from
'./components/AddVideoIntro'
;
import
SelectStudent
from
'../modal/select-student'
;
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
;
import
PreviewCourseModal
from
'../modal/PreviewCourseModal'
;
import
StoreService
from
'@/domains/store-domain/storeService'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
Service
from
'@/common/js/service'
;
import
User
from
'@/common/js/user'
;
import
_
from
'underscore'
;
import
Upload
from
'@/core/upload'
;
import
{
randomString
}
from
'@/domains/basic-domain/utils'
;
import
$
from
'jquery'
;
// import PhotoClip from 'photoclip';
import
'./AddVideoCourse.less'
import
'./AddVideoCourse.less'
;
const
EDIT_BOX_KEY
=
Math
.
random
()
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
}
const
EDIT_BOX_KEY
=
Math
.
random
()
;
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
}
;
//添加课程时课程默认的一些值
const
defaultShelfState
=
'YES'
const
defaultShelfState
=
'YES'
;
const
defaultScheduleMedia
=
[
{
contentType
:
'INTRO'
,
mediaType
:
'TEXT'
,
mediaContent
:
''
,
key
:
EDIT_BOX_KEY
}
]
const
whetherVisitorsJoin
=
'NO'
key
:
EDIT_BOX_KEY
,
}
,
]
;
const
whetherVisitorsJoin
=
'NO'
;
let
cutFlag
=
false
let
cutFlag
=
false
;
class
AddVideoCourse
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
const
id
=
getParameterByName
(
'id'
)
const
pageType
=
getParameterByName
(
'type'
)
const
id
=
getParameterByName
(
'id'
)
;
const
pageType
=
getParameterByName
(
'type'
)
;
this
.
state
=
{
id
,
// 视频课ID,编辑的时候从URL上带过来
...
...
@@ -69,8 +69,8 @@ class AddVideoCourse extends React.Component {
contentType
:
'INTRO'
,
mediaType
:
'TEXT'
,
mediaContent
:
''
,
key
:
EDIT_BOX_KEY
}
key
:
EDIT_BOX_KEY
,
}
,
],
diskList
:
[],
// 机构可见磁盘目录
selectedFileList
:
[],
// 已经从资料云盘中勾选的文件
...
...
@@ -83,15 +83,15 @@ class AddVideoCourse extends React.Component {
whetherVisitorsJoin
:
'NO'
,
// 是否允许游客加入
showSelectCoverModal
:
false
,
cutImageBlob
:
null
,
introduce
:
''
}
introduce
:
''
,
}
;
}
componentWillMount
()
{
const
{
id
,
pageType
}
=
this
.
state
this
.
getCourseCatalogList
()
const
{
id
,
pageType
}
=
this
.
state
;
this
.
getCourseCatalogList
()
;
if
(
pageType
===
'edit'
)
{
this
.
handleFetchScheudleDetail
(
id
)
this
.
handleFetchScheudleDetail
(
id
)
;
}
}
...
...
@@ -99,70 +99,70 @@ class AddVideoCourse extends React.Component {
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
this
.
setState
({
courseCatalogList
:
res
.
result
.
records
})
})
}
courseCatalogList
:
res
.
result
.
records
,
})
;
})
;
}
;
catalogChange
=
(
value
)
=>
{
const
changeValueLength
=
value
.
length
const
changeValueLength
=
value
.
length
;
switch
(
changeValueLength
)
{
case
1
:
this
.
setState
({
categoryId
:
value
[
0
]
})
break
this
.
setState
({
categoryId
:
value
[
0
]
})
;
break
;
case
2
:
this
.
setState
({
categoryId
:
value
[
1
]
})
break
this
.
setState
({
categoryId
:
value
[
1
]
})
;
break
;
default
:
this
.
setState
({
categoryId
:
null
})
break
this
.
setState
({
categoryId
:
null
})
;
break
;
}
}
}
;
// 获取视频课详情
handleFetchScheudleDetail
=
(
courseId
)
=>
{
CourseService
.
videoScheduleDetail
({
courseId
courseId
,
}).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
||
{}
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
categoryOneName
,
categoryTwoName
,
categoryId
}
=
result
let
coverId
let
coverUrl
let
videoType
let
videoDuration
let
videoName
let
scheduleMedia
=
[]
let
scheduleVideoId
let
scheduleVideoUrl
let
hasIntro
const
{
result
=
{}
}
=
res
||
{}
;
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
categoryOneName
,
categoryTwoName
,
categoryId
}
=
result
;
let
coverId
;
let
coverUrl
;
let
videoType
;
let
videoDuration
;
let
videoName
;
let
scheduleMedia
=
[]
;
let
scheduleVideoId
;
let
scheduleVideoUrl
;
let
hasIntro
;
courseMediaVOS
.
map
((
item
)
=>
{
switch
(
item
.
contentType
)
{
case
'COVER'
:
coverId
=
item
.
mediaContent
coverUrl
=
item
.
mediaUrl
break
coverId
=
item
.
mediaContent
;
coverUrl
=
item
.
mediaUrl
;
break
;
case
'SCHEDULE'
:
videoDuration
=
item
.
videoDuration
videoName
=
item
.
mediaName
scheduleVideoId
=
item
.
mediaContent
scheduleVideoUrl
=
item
.
mediaUrl
videoType
=
item
.
mediaType
break
videoDuration
=
item
.
videoDuration
;
videoName
=
item
.
mediaName
;
scheduleVideoId
=
item
.
mediaContent
;
scheduleVideoUrl
=
item
.
mediaUrl
;
videoType
=
item
.
mediaType
;
break
;
case
'INTRO'
:
hasIntro
=
true
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
break
hasIntro
=
true
;
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
;
break
;
default
:
break
break
;
}
return
item
})
return
item
;
})
;
let
categoryName
let
categoryName
;
if
(
categoryTwoName
)
{
categoryName
=
`
${
categoryOneName
}
-
${
categoryTwoName
}
`
categoryName
=
`
${
categoryOneName
}
-
${
categoryTwoName
}
`
;
}
else
{
categoryName
=
`
${
categoryOneName
}
`
categoryName
=
`
${
categoryOneName
}
`
;
}
this
.
setState
({
loadintroduce
:
!
hasIntro
,
...
...
@@ -178,10 +178,10 @@ class AddVideoCourse extends React.Component {
shelfState
,
whetherVisitorsJoin
,
categoryName
,
categoryId
})
})
}
categoryId
,
})
;
})
;
}
;
getTextDetail
=
(
key
,
url
)
=>
{
$
.
ajax
({
...
...
@@ -190,13 +190,13 @@ class AddVideoCourse extends React.Component {
url
,
contentType
:
'application/x-www-form-urlencoded; charset=UTF-8'
,
success
:
(
res
)
=>
{
this
.
setState
({
[
key
]:
res
,
[
`load
${
key
}
`
]:
true
})
}
})
}
this
.
setState
({
[
key
]:
res
,
[
`load
${
key
}
`
]:
true
})
;
}
,
})
;
}
;
handleGoBack
=
()
=>
{
const
{
coverId
,
videoName
,
videoDuration
,
courseName
,
scheduleMedia
,
scheduleVideoId
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
const
{
coverId
,
videoName
,
videoDuration
,
courseName
,
scheduleMedia
,
scheduleVideoId
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
;
if
(
videoName
||
videoDuration
||
...
...
@@ -216,30 +216,30 @@ class AddVideoCourse extends React.Component {
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
onOk
:
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
})
}
})
pathname
:
`/video-course`
,
})
;
}
,
})
;
}
else
{
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
})
pathname
:
`/video-course`
,
})
;
}
}
}
;
// 修改表单
handleChangeForm
=
(
field
,
value
,
coverUrl
)
=>
{
this
.
setState
({
[
field
]:
value
,
coverUrl
:
coverUrl
?
coverUrl
:
this
.
state
.
coverUrl
})
}
coverUrl
:
coverUrl
?
coverUrl
:
this
.
state
.
coverUrl
,
})
;
}
;
// 显示选择学员弹窗
handleShowSelectStuModal
=
()
=>
{
this
.
setState
({
studentModal
:
true
})
this
.
setState
({
studentModal
:
true
})
;
const
{
studentList
,
selectedStuList
}
=
this
.
state
const
{
studentList
,
selectedStuList
}
=
this
.
state
;
const
studentModal
=
(
<
SelectStudent
showTabs=
{
true
}
...
...
@@ -249,38 +249,38 @@ class AddVideoCourse extends React.Component {
studentList=
{
studentList
}
close=
{
()
=>
{
this
.
setState
({
studentModal
:
null
})
studentModal
:
null
,
})
;
}
}
/>
)
this
.
setState
({
studentModal
})
}
)
;
this
.
setState
({
studentModal
})
;
}
;
handleSelectStudent
=
(
studentIds
)
=>
{
let
studentList
=
[]
let
studentList
=
[]
;
_
.
each
(
studentIds
,
(
item
)
=>
{
studentList
.
push
({
studentId
:
item
})
})
studentList
.
push
({
studentId
:
item
})
;
})
;
// this.setState({ studentModal: null });
this
.
setState
({
studentList
})
this
.
setState
({
studentModal
:
false
})
}
this
.
setState
({
studentList
})
;
this
.
setState
({
studentModal
:
false
})
;
}
;
// 显示预览弹窗
handleShowPreviewModal
=
()
=>
{
const
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
scheduleMedia
,
videoDuration
,
introduce
}
=
this
.
state
const
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
scheduleMedia
,
videoDuration
,
introduce
}
=
this
.
state
;
const
courseBasinInfo
=
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
videoDuration
}
videoDuration
,
}
;
const
courseIntroInfo
=
{
liveCourseMediaRequests
:
scheduleMedia
,
introduce
}
introduce
,
}
;
const
previewCourseModal
=
(
<
PreviewCourseModal
...
...
@@ -289,24 +289,24 @@ class AddVideoCourse extends React.Component {
courseIntroInfo=
{
courseIntroInfo
}
close=
{
()
=>
{
this
.
setState
({
previewCourseModal
:
null
})
previewCourseModal
:
null
,
})
;
}
}
/>
)
)
;
this
.
setState
({
previewCourseModal
})
}
this
.
setState
({
previewCourseModal
})
;
}
;
// 选择视频
handleSelectVideo
=
(
file
)
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
const
{
ossUrl
,
resourceId
,
folderName
,
folderFormat
,
folderSize
}
=
file
showSelectFileModal
:
false
,
})
;
const
{
ossUrl
,
resourceId
,
folderName
,
folderFormat
,
folderSize
}
=
file
;
const
videoDom
=
document
.
createElement
(
'video'
)
videoDom
.
src
=
ossUrl
const
videoDom
=
document
.
createElement
(
'video'
)
;
videoDom
.
src
=
ossUrl
;
videoDom
.
onloadedmetadata
=
()
=>
{
this
.
setState
({
size
:
folderSize
,
...
...
@@ -314,14 +314,14 @@ class AddVideoCourse extends React.Component {
videoType
:
folderFormat
,
scheduleVideoUrl
:
ossUrl
,
scheduleVideoId
:
resourceId
,
videoDuration
:
videoDom
.
duration
})
}
}
videoDuration
:
videoDom
.
duration
,
})
;
}
;
}
;
// 保存
handleSubmit
=
()
=>
{
const
{
instId
,
adminId
}
=
window
.
currentUserInstInfo
const
{
instId
,
adminId
}
=
window
.
currentUserInstInfo
;
const
{
id
,
...
...
@@ -340,8 +340,8 @@ class AddVideoCourse extends React.Component {
categoryId
,
shelfState
,
whetherVisitorsJoin
,
introduce
}
=
this
.
state
introduce
,
}
=
this
.
state
;
const
commonParams
=
{
videoName
,
...
...
@@ -355,144 +355,144 @@ class AddVideoCourse extends React.Component {
storeId
:
User
.
getStoreId
(),
shelfState
,
whetherVisitorsJoin
,
courseType
:
'VOICE'
}
courseType
:
'VOICE'
,
}
;
// 校验必填字段:课程名称, 课程视频
this
.
handleValidate
(
courseName
,
scheduleVideoId
,
categoryId
,
scheduleMedia
).
then
((
res
)
=>
{
if
(
!
res
)
return
if
(
!
res
)
return
;
Upload
.
uploadTextToOSS
(
introduce
,
`
${
randomString
()}
.txt`
,
(
introduceId
)
=>
{
this
.
submitRemote
({
id
,
pageType
,
commonParams
:
{
...
commonParams
,
introduceId
}
})
})
})
}
this
.
submitRemote
({
id
,
pageType
,
commonParams
:
{
...
commonParams
,
introduceId
}
})
;
})
;
})
;
}
;
submitRemote
=
({
id
,
pageType
,
commonParams
})
=>
{
if
(
pageType
===
'add'
)
{
Service
.
Hades
(
'public/hades/createMediaCourse'
,
commonParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
message
.
success
(
'新建成功'
)
if
(
!
res
)
return
;
message
.
success
(
'新建成功'
)
;
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
})
})
pathname
:
`/video-course`
,
})
;
})
;
}
else
{
const
editParams
=
{
courseId
:
id
,
...
commonParams
}
...
commonParams
,
}
;
Service
.
Hades
(
'public/hades/editMediaCourse'
,
editParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
message
.
success
(
'保存成功'
)
if
(
!
res
)
return
;
message
.
success
(
'保存成功'
)
;
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
})
})
pathname
:
`/video-course`
,
})
;
})
;
}
}
}
;
handleValidate
=
(
courseName
,
scheduleVideoId
,
categoryId
,
scheduleMedia
)
=>
{
return
new
Promise
((
resolve
)
=>
{
if
(
!
courseName
)
{
message
.
warning
(
'请输入课程名称'
)
resolve
(
false
)
return
false
message
.
warning
(
'请输入课程名称'
)
;
resolve
(
false
)
;
return
false
;
}
if
(
!
scheduleVideoId
)
{
message
.
warning
(
'请上传视频'
)
resolve
(
false
)
return
false
message
.
warning
(
'请上传视频'
)
;
resolve
(
false
)
;
return
false
;
}
if
(
!
categoryId
)
{
message
.
warning
(
'请选择课程分类'
)
resolve
(
false
)
return
false
message
.
warning
(
'请选择课程分类'
)
;
resolve
(
false
)
;
return
false
;
}
const
textMedia
=
scheduleMedia
.
filter
((
item
)
=>
item
.
mediaType
===
'TEXT'
)
const
textMedia
=
scheduleMedia
.
filter
((
item
)
=>
item
.
mediaType
===
'TEXT'
)
;
for
(
let
i
=
0
,
len
=
textMedia
.
length
;
i
<
len
;
i
++
)
{
if
(
textMedia
[
i
].
mediaContentLength
&&
textMedia
[
i
].
mediaContentLength
.
length
>
1000
)
{
message
.
warning
(
`第
${
i
+
1
}
个文字简介的字数超过了1000个字`
)
resolve
(
false
)
return
false
message
.
warning
(
`第
${
i
+
1
}
个文字简介的字数超过了1000个字`
)
;
resolve
(
false
)
;
return
false
;
}
}
resolve
(
true
)
})
}
resolve
(
true
)
;
})
;
}
;
handleSelectCover
=
(
file
)
=>
{
this
.
uploadImage
(
file
)
}
this
.
uploadImage
(
file
)
;
}
;
//上传图片
uploadImage
=
(
imageFile
)
=>
{
const
{
folderName
}
=
imageFile
const
fileName
=
window
.
random_string
(
16
)
+
folderName
.
slice
(
folderName
.
lastIndexOf
(
'.'
))
const
self
=
this
const
{
folderName
}
=
imageFile
;
const
fileName
=
window
.
random_string
(
16
)
+
folderName
.
slice
(
folderName
.
lastIndexOf
(
'.'
))
;
const
self
=
this
;
this
.
setState
(
{
visible
:
true
visible
:
true
,
},
()
=>
{
setTimeout
(()
=>
{
const
okBtnDom
=
document
.
querySelector
(
'#headPicModal'
)
const
okBtnDom
=
document
.
querySelector
(
'#headPicModal'
)
;
const
options
=
{
size
:
[
500
,
282
],
ok
:
okBtnDom
,
maxZoom
:
3
,
style
:
{
jpgFillColor
:
'transparent'
jpgFillColor
:
'transparent'
,
},
done
:
function
(
dataUrl
)
{
clearTimeout
(
self
.
timer
)
clearTimeout
(
self
.
timer
)
;
self
.
timer
=
setTimeout
(()
=>
{
if
(
self
.
state
.
rotate
!=
this
.
rotate
()
||
self
.
state
.
scale
!=
this
.
scale
())
{
const
_dataUrl
=
this
.
clip
()
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
_dataUrl
)
const
_dataUrl
=
this
.
clip
()
;
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
_dataUrl
)
;
self
.
setState
({
cutImageBlob
,
dataUrl
:
_dataUrl
,
rotate
:
this
.
rotate
(),
scale
:
this
.
scale
()
})
scale
:
this
.
scale
()
,
})
;
}
},
500
)
},
500
)
;
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
dataUrl
)
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
dataUrl
)
;
self
.
setState
({
cutImageBlob
,
dataUrl
})
dataUrl
,
})
;
setTimeout
(()
=>
{
cutFlag
=
false
},
2000
)
cutFlag
=
false
;
},
2000
)
;
},
fail
:
(
failInfo
)
=>
{
message
.
error
(
'图片上传失败了,请重新上传'
)
message
.
error
(
'图片上传失败了,请重新上传'
)
;
},
loadComplete
:
function
(
img
)
{
setTimeout
(()
=>
{
const
_dataUrl
=
this
.
clip
()
const
_dataUrl
=
this
.
clip
()
;
self
.
setState
({
dataUrl
:
_dataUrl
,
hasImgReady
:
true
})
},
100
)
}
}
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
hasImgReady
:
true
,
})
;
},
100
)
;
}
,
}
;
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
;
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
'#headPicModal'
,
options
)
_photoclip
.
load
(
imgUrl
)
const
_photoclip
=
new
PhotoClip
(
'#headPicModal'
,
options
)
;
_photoclip
.
load
(
imgUrl
)
;
this
.
setState
({
photoclip
:
_photoclip
})
photoclip
:
_photoclip
,
})
;
}
else
{
this
.
state
.
photoclip
.
clear
()
this
.
state
.
photoclip
.
load
(
imgUrl
)
this
.
state
.
photoclip
.
clear
()
;
this
.
state
.
photoclip
.
load
(
imgUrl
)
;
}
},
200
)
},
200
)
;
}
)
}
)
;
}
;
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
...
...
@@ -501,30 +501,30 @@ class AddVideoCourse extends React.Component {
{
coverClicpPath
:
signInfo
.
fileUrl
,
coverId
:
signInfo
.
resourceId
,
visible
:
false
visible
:
false
,
},
()
=>
this
.
updateCover
()
)
})
}
)
;
})
;
}
;
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
const
{
coverClicpPath
,
coverId
}
=
this
.
state
;
this
.
setState
({
showSelectCoverModal
:
false
,
coverUrl
:
coverClicpPath
,
coverId
:
coverId
})
}
coverId
:
coverId
,
})
;
}
;
// base64转换成blob
convertBase64UrlToBlob
=
(
urlData
)
=>
{
const
bytes
=
window
.
atob
(
urlData
.
split
(
','
)[
1
])
const
ab
=
new
ArrayBuffer
(
bytes
.
length
)
const
ia
=
new
Uint8Array
(
ab
)
const
bytes
=
window
.
atob
(
urlData
.
split
(
','
)[
1
])
;
const
ab
=
new
ArrayBuffer
(
bytes
.
length
)
;
const
ia
=
new
Uint8Array
(
ab
)
;
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
ia
[
i
]
=
bytes
.
charCodeAt
(
i
)
ia
[
i
]
=
bytes
.
charCodeAt
(
i
)
;
}
return
new
Blob
([
ab
],
{
type
:
'image/png'
})
}
return
new
Blob
([
ab
],
{
type
:
'image/png'
})
;
}
;
render
()
{
const
{
pageType
,
...
...
@@ -552,13 +552,13 @@ class AddVideoCourse extends React.Component {
cutImageBlob
,
introduce
,
loadintroduce
,
id
}
=
this
.
state
id
,
}
=
this
.
state
;
// 已选择的上课学员数量
const
hasSelectedStu
=
studentList
.
length
const
hasSelectedStu
=
studentList
.
length
;
const
courseWareIcon
=
FileVerifyMap
[
videoType
]
?
FileTypeIcon
[
FileVerifyMap
[
videoType
].
type
]
:
FileTypeIcon
[
videoType
]
const
courseWareIcon
=
FileVerifyMap
[
videoType
]
?
FileTypeIcon
[
FileVerifyMap
[
videoType
].
type
]
:
FileTypeIcon
[
videoType
]
;
return
(
<
div
className=
'page add-video-course-page'
>
...
...
@@ -578,7 +578,7 @@ class AddVideoCourse extends React.Component {
maxLength=
{
40
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangeForm
(
'courseName'
,
e
.
target
.
value
)
this
.
handleChangeForm
(
'courseName'
,
e
.
target
.
value
)
;
}
}
/>
</
div
>
...
...
@@ -601,8 +601,8 @@ class AddVideoCourse extends React.Component {
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
true
})
showSelectFileModal
:
true
,
})
;
}
}
>
{
`${pageType === 'add' && !scheduleVideoId ? '选择' : '更换'}视频`
}
</
Button
>
<
span
className=
'tips'
>
视频数量限制1个,大小不超过2G
</
span
>
...
...
@@ -627,7 +627,7 @@ class AddVideoCourse extends React.Component {
<
div
className=
'opt-btns'
>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
true
})
this
.
setState
({
showSelectCoverModal
:
true
})
;
}
}
>
{
`${pageType === 'add' && !scheduleVideoId && !coverUrl ? '上传' : '修改'}封面`
}
</
Button
>
<
div
className=
'tips'
>
建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。
</
div
>
</
div
>
...
...
@@ -676,7 +676,7 @@ class AddVideoCourse extends React.Component {
shelfState
,
whetherVisitorsJoin
,
introduce
,
loadintroduce
loadintroduce
,
}
}
onChange=
{
this
.
handleChangeForm
}
/>
...
...
@@ -684,7 +684,7 @@ class AddVideoCourse extends React.Component {
</
div
>
</
div
>
<
div
className=
"footer shrink-footer"
>
<
div
className=
'footer shrink-footer'
>
<
Button
onClick=
{
this
.
handleGoBack
}
>
取消
</
Button
>
<
Button
onClick=
{
this
.
handleShowPreviewModal
}
>
预览
</
Button
>
<
Button
type=
'primary'
onClick=
{
_
.
debounce
(()
=>
this
.
handleSubmit
(),
3000
,
true
)
}
>
...
...
@@ -700,14 +700,14 @@ class AddVideoCourse extends React.Component {
accept=
'video/mp4'
confirm=
{
{
title
:
'文件过大,无法上传'
,
content
:
'为保障学员的观看体验,上传的视频大小不能超过2G'
content
:
'为保障学员的观看体验,上传的视频大小不能超过2G'
,
}
}
tooltip=
{
'格式支持mp4,大小不超过2G'
}
isOpen=
{
showSelectFileModal
}
diskList=
{
diskList
}
addVideo=
{
true
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
this
.
setState
({
showSelectFileModal
:
false
})
;
}
}
onSelect=
{
this
.
handleSelectVideo
}
/>
...
...
@@ -722,7 +722,7 @@ class AddVideoCourse extends React.Component {
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectCoverModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
false
})
this
.
setState
({
showSelectCoverModal
:
false
})
;
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
...
...
@@ -734,14 +734,14 @@ class AddVideoCourse extends React.Component {
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
onCancel=
{
()
=>
{
this
.
setState
({
visible
:
false
})
this
.
setState
({
visible
:
false
})
;
}
}
zIndex=
{
10001
}
footer=
{
[
<
Button
key=
'back'
onClick=
{
()
=>
{
this
.
setState
({
visible
:
false
})
this
.
setState
({
visible
:
false
})
;
}
}
>
重新上传
</
Button
>,
...
...
@@ -751,13 +751,13 @@ class AddVideoCourse extends React.Component {
disabled=
{
!
hasImgReady
}
onClick=
{
()
=>
{
if
(
!
cutFlag
)
{
cutFlag
=
true
this
.
refs
.
hiddenBtn
.
click
()
cutFlag
=
true
;
this
.
refs
.
hiddenBtn
.
click
()
;
}
this
.
getSignature
(
cutImageBlob
)
this
.
getSignature
(
cutImageBlob
)
;
}
}
>
确定
</
Button
>
</
Button
>
,
]
}
>
<
div
className=
'clip-box'
>
<
div
...
...
@@ -766,7 +766,7 @@ class AddVideoCourse extends React.Component {
style=
{
{
width
:
'500px'
,
height
:
'430px'
,
marginBottom
:
0
marginBottom
:
0
,
}
}
></
div
>
<
div
id=
'clipBtn'
style=
{
{
display
:
'none'
}
}
ref=
'hiddenBtn'
></
div
>
<
div
className=
'preview-img'
>
...
...
@@ -784,8 +784,8 @@ class AddVideoCourse extends React.Component {
</
Modal
>
{
this
.
state
.
previewCourseModal
}
</
div
>
)
)
;
}
}
export
default
AddVideoCourse
export
default
AddVideoCourse
;
src/modules/course-manage/video-course/components/VideoCourseList.jsx
View file @
1402a09b
...
...
@@ -450,7 +450,7 @@ class VideoCourseList extends React.Component {
},
()
=>
{
this
.
props
.
onChange
();
}
,
}
);
};
render
()
{
...
...
src/modules/home/Home.less
View file @
1402a09b
...
...
@@ -139,6 +139,7 @@
background: #fff;
width: ~'calc(50% - 8px)';
padding: 16px;
overflow: hidden;
.study-title {
font-size: 14px;
color: #333;
...
...
src/modules/knowledge-base/components/KnowledgeBaseList.jsx
View file @
1402a09b
...
...
@@ -2,207 +2,207 @@
* @Description:
* @Author: zangsuyun
* @Date: 2021-03-12 14:49:40
* @LastEditors:
fusanqiasng
* @LastEditTime: 2021-05-30
18:36:45
* @LastEditors:
wufan
* @LastEditTime: 2021-05-30
20:37:42
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
"react"
import
{
Table
,
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
,
Button
}
from
"antd"
import
{
Route
,
withRouter
}
from
"react-router-dom"
import
{
PageControl
}
from
"@/components"
import
{
LIVE_SHARE_MAP
}
from
"@/common/constants/academic/cloudClass"
import
{
appId
,
shareUrl
,
LIVE_SHARE
}
from
"@/domains/course-domain/constants"
import
ScanFileModal
from
"../../resource-disk/modal/ScanFileModal"
import
WatchData
from
"./WatchData"
import
KnowledgeAPI
from
"@/data-source/knowledge/request-api"
import
ENUM
from
"../ENUM.js"
import
"./KnowledgeBaseList.less"
import
React
from
'react'
;
import
{
Table
,
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
,
Button
}
from
'antd'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
{
PageControl
}
from
'@/components'
;
import
{
LIVE_SHARE_MAP
}
from
'@/common/constants/academic/cloudClass'
;
import
{
appId
,
shareUrl
,
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
ScanFileModal
from
'../../resource-disk/modal/ScanFileModal'
;
import
WatchData
from
'./WatchData'
;
import
KnowledgeAPI
from
'@/data-source/knowledge/request-api'
;
import
ENUM
from
'../ENUM.js'
;
import
'./KnowledgeBaseList.less'
;
const
DEFAULT_SIZE_UNIT
=
1000
*
1000
// 将B转换成M
const
{
confirm
}
=
Modal
const
ENV
=
process
.
env
.
DEPLOY_ENV
||
"dev"
const
DEFAULT_SIZE_UNIT
=
1000
*
1000
;
// 将B转换成M
const
{
confirm
}
=
Modal
;
const
ENV
=
process
.
env
.
DEPLOY_ENV
||
'dev'
;
class
KnowledgeBaseList
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
id
:
""
,
scanFileModal
:
null
}
id
:
''
,
scanFileModal
:
null
,
}
;
}
handleAdminName
=
(
adminArray
)
=>
{
let
adminStr
=
""
let
adminStr
=
''
;
adminArray
.
map
((
item
,
index
)
=>
{
if
(
index
<
adminArray
.
length
-
1
)
{
adminStr
=
adminStr
+
item
.
adminName
+
"、"
adminStr
=
adminStr
+
item
.
adminName
+
'、'
;
}
else
{
adminStr
=
adminStr
+
item
.
adminName
adminStr
=
adminStr
+
item
.
adminName
;
}
})
return
adminStr
}
})
;
return
adminStr
;
}
;
handleUp
=
(
index
,
record
)
=>
{
if
(
index
===
0
&&
this
.
props
.
query
.
current
===
1
)
{
return
return
;
}
const
params
=
{
direction
:
"UP"
,
direction
:
'UP'
,
id
:
record
.
id
,
storeId
:
record
.
storeId
}
storeId
:
record
.
storeId
,
}
;
KnowledgeAPI
.
moveKnowledge
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"更新成功"
)
this
.
props
.
onChange
()
message
.
success
(
'更新成功'
);
this
.
props
.
onChange
()
;
}
})
}
})
;
}
;
handleDown
=
(
record
,
index
)
=>
{
const
{
query
,
totalCount
}
=
this
.
props
const
{
current
,
size
}
=
query
const
{
query
,
totalCount
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
if
(
totalCount
===
size
*
(
current
-
1
)
+
index
+
1
)
{
return
return
;
}
const
params
=
{
direction
:
"DOWN"
,
direction
:
'DOWN'
,
id
:
record
.
id
,
storeId
:
record
.
storeId
}
storeId
:
record
.
storeId
,
}
;
KnowledgeAPI
.
moveKnowledge
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"更新成功"
)
this
.
props
.
onChange
()
message
.
success
(
'更新成功'
);
this
.
props
.
onChange
()
;
}
})
}
})
;
}
;
getBlob
=
(
url
)
=>
{
return
new
Promise
((
resolve
)
=>
{
const
xhr
=
new
XMLHttpRequest
()
const
xhr
=
new
XMLHttpRequest
()
;
xhr
.
open
(
"GET"
,
url
,
true
)
xhr
.
responseType
=
"blob"
xhr
.
open
(
'GET'
,
url
,
true
);
xhr
.
responseType
=
'blob'
;
xhr
.
onload
=
()
=>
{
if
(
xhr
.
status
===
200
)
{
resolve
(
xhr
.
response
)
resolve
(
xhr
.
response
)
;
}
}
xhr
.
send
()
})
}
}
;
xhr
.
send
()
;
})
;
}
;
saveAs
=
(
blob
,
filename
)
=>
{
if
(
window
.
navigator
.
msSaveOrOpenBlob
)
{
navigator
.
msSaveBlob
(
blob
,
filename
)
navigator
.
msSaveBlob
(
blob
,
filename
)
;
}
else
{
const
link
=
document
.
createElement
(
"a"
)
const
body
=
document
.
querySelector
(
"body"
)
const
link
=
document
.
createElement
(
'a'
);
const
body
=
document
.
querySelector
(
'body'
);
// 创建对象url
link
.
href
=
window
.
URL
.
createObjectURL
(
blob
)
link
.
download
=
filename
link
.
href
=
window
.
URL
.
createObjectURL
(
blob
)
;
link
.
download
=
filename
;
body
.
appendChild
(
link
)
body
.
appendChild
(
link
)
;
link
.
click
()
body
.
removeChild
(
link
)
link
.
click
()
;
body
.
removeChild
(
link
)
;
// 通过调用 URL.createObjectURL() 创建的 URL 对象
window
.
URL
.
revokeObjectURL
(
link
.
href
)
window
.
URL
.
revokeObjectURL
(
link
.
href
)
;
}
}
}
;
// 下载文件
handleDownload
=
(
folder
)
=>
{
this
.
getBlob
(
folder
.
ossUrl
).
then
((
blob
)
=>
{
this
.
saveAs
(
blob
,
folder
.
folderName
)
})
}
this
.
saveAs
(
blob
,
folder
.
folderName
)
;
})
;
}
;
// 预览文件
handleScanFile
=
(
folder
)
=>
{
console
.
log
(
folder
)
const
{
folderFormat
,
folderSize
,
ossUrl
}
=
folder
console
.
log
(
folder
)
;
const
{
folderFormat
,
folderSize
,
ossUrl
}
=
folder
;
switch
(
folderFormat
)
{
case
"PDF"
:
window
.
open
(
ossUrl
,
"_blank"
)
break
case
"WORD"
:
case
"DOCX"
:
case
"DOC"
:
case
"EXCEL"
:
case
"PPT"
:
case
"PPTX"
:
case
"PDF"
:
case
'PDF'
:
window
.
open
(
ossUrl
,
'_blank'
);
break
;
case
'WORD'
:
case
'DOCX'
:
case
'DOC'
:
case
'EXCEL'
:
case
'PPT'
:
case
'PPTX'
:
case
'PDF'
:
if
(
((
folderFormat
===
"PPT"
||
folderFormat
===
"PPTX"
||
folderFormat
===
"DOCX"
||
folderFormat
===
"WORD"
||
folderFormat
===
"DOC"
)
&&
((
folderFormat
===
'PPT'
||
folderFormat
===
'PPTX'
||
folderFormat
===
'DOCX'
||
folderFormat
===
'WORD'
||
folderFormat
===
'DOC'
)
&&
folderSize
>
10
*
DEFAULT_SIZE_UNIT
)
||
(
folderFormat
===
"EXCEL"
&&
folderSize
>
5
*
DEFAULT_SIZE_UNIT
)
(
folderFormat
===
'EXCEL'
&&
folderSize
>
5
*
DEFAULT_SIZE_UNIT
)
)
{
Modal
.
confirm
({
title
:
"抱歉,不能在线预览"
,
content
:
"由于文件较大,不支持在线预览,请下载后再查看"
,
title
:
'抱歉,不能在线预览'
,
content
:
'由于文件较大,不支持在线预览,请下载后再查看'
,
// icon: <Icon type="question-circle" theme="filled" style={{ color: '#FF8534' }}></Icon>,
cancelText
:
"取消"
,
okText
:
"下载"
,
cancelText
:
'取消'
,
okText
:
'下载'
,
onOk
:
()
=>
{
this
.
handleDownload
(
folder
)
}
})
break
this
.
handleDownload
(
folder
)
;
}
,
})
;
break
;
}
const
prefixUrl
=
"https://view.officeapps.live.com/op/view.aspx?src="
const
scanUrl
=
`
${
prefixUrl
}${
encodeURIComponent
(
ossUrl
)}
`
window
.
open
(
scanUrl
,
"_blank"
)
break
const
prefixUrl
=
'https://view.officeapps.live.com/op/view.aspx?src='
;
const
scanUrl
=
`
${
prefixUrl
}${
encodeURIComponent
(
ossUrl
)}
`
;
window
.
open
(
scanUrl
,
'_blank'
);
break
;
default
:
const
scanFileModal
=
(
<
ScanFileModal
fileType=
{
folderFormat
}
item=
{
folder
}
close=
{
()
=>
{
this
.
setState
({
scanFileModal
:
null
})
this
.
setState
({
scanFileModal
:
null
})
;
}
}
/>
)
this
.
setState
({
scanFileModal
})
break
)
;
this
.
setState
({
scanFileModal
})
;
break
;
}
}
}
;
// 请求表头
parseColumns
=
()
=>
{
const
{
query
,
totalCount
}
=
this
.
props
const
{
current
,
size
}
=
query
const
{
query
,
totalCount
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
const
columns
=
[
{
title
:
"课程名称"
,
key
:
"name"
,
dataIndex
:
"name"
,
title
:
'课程名称'
,
key
:
'name'
,
dataIndex
:
'name'
,
width
:
391
,
fixed
:
"left"
,
fixed
:
'left'
,
render
:
(
val
,
record
)
=>
{
const
{
coverUrl
,
mediaCourseUrl
,
courseDivision
}
=
record
.
source
let
hasCover
=
false
const
type
=
record
.
type
const
{
coverUrl
,
mediaCourseUrl
,
courseDivision
}
=
record
.
source
;
let
hasCover
=
false
;
const
type
=
record
.
type
;
return
(
<
div
>
{
type
===
"LIVE"
&&
(
{
type
===
'LIVE'
&&
(
<
div
className=
'record__item'
>
{
record
.
source
&&
record
.
source
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
"COVER"
)
{
hasCover
=
true
return
<
img
className=
'course-cover'
key=
{
index
}
src=
{
item
.
mediaUrl
}
/>
if
(
item
.
contentType
===
'COVER'
)
{
hasCover
=
true
;
return
<
img
className=
'course-cover'
key=
{
index
}
src=
{
item
.
mediaUrl
}
/>
;
}
})
}
{
!
hasCover
&&
<
img
className=
'course-cover'
src=
{
"https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png"
}
/>
}
{
!
hasCover
&&
<
img
className=
'course-cover'
src=
{
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
}
/>
}
<
div
>
{
val
.
length
>
17
?
(
<
Tooltip
title=
{
val
}
>
...
...
@@ -213,13 +213,13 @@ class KnowledgeBaseList extends React.Component {
)
}
<
div
>
<
span
className=
'course-time'
>
{
formatDate
(
"YYYY-MM-DD H:i"
,
parseInt
(
record
.
source
.
startTime
))
}
~
{
formatDate
(
"H:i"
,
parseInt
(
record
.
source
.
endTime
))
}
{
formatDate
(
'YYYY-MM-DD H:i'
,
parseInt
(
record
.
source
.
startTime
))
}
~
{
formatDate
(
'H:i'
,
parseInt
(
record
.
source
.
endTime
))
}
</
span
>
<
span
className=
'course-status'
style=
{
{
color
:
ENUM
.
courseStateShow
[
record
.
source
.
courseState
].
color
,
border
:
`1px solid ${ENUM.courseStateShow[record.source.courseState].color}`
border
:
`1px solid ${ENUM.courseStateShow[record.source.courseState].color}`
,
}
}
>
{
ENUM
.
courseStateShow
[
record
.
source
.
courseState
].
title
}
</
span
>
...
...
@@ -228,10 +228,10 @@ class KnowledgeBaseList extends React.Component {
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
"5px"
,
cursor
:
"pointer"
,
color
:
"#FF4F4F"
,
fontSize
:
"14px"
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#FF4F4F'
,
fontSize
:
'14px'
,
}
}
>

</
i
>
...
...
@@ -257,9 +257,9 @@ class KnowledgeBaseList extends React.Component {
{
record
.
source
.
admins
.
map
((
item
,
index
)
=>
{
return
(
<
span
>
{
item
.
adminName
}
{
index
<
record
.
source
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
" "
}
{
item
.
adminName
}
{
index
<
record
.
source
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
)
;
})
}
</
span
>
</
Tooltip
>
...
...
@@ -269,9 +269,9 @@ class KnowledgeBaseList extends React.Component {
{
record
.
source
.
admins
.
map
((
item
,
index
)
=>
{
return
(
<
span
key=
{
index
}
>
{
item
.
adminName
}
{
index
<
record
.
source
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
" "
}
{
item
.
adminName
}
{
index
<
record
.
source
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
)
;
})
}
</
span
>
)
}
...
...
@@ -282,7 +282,7 @@ class KnowledgeBaseList extends React.Component {
</
div
>
)
}
{
type
===
"VOICE"
&&
(
{
type
===
'VOICE'
&&
(
<
div
className=
'record__item'
>
{
/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */
}
<
img
...
...
@@ -290,9 +290,9 @@ class KnowledgeBaseList extends React.Component {
src=
{
coverUrl
?
coverUrl
:
courseDivision
!==
"EXTERNAL"
:
courseDivision
!==
'EXTERNAL'
?
`${mediaCourseUrl}?x-oss-process=video/snapshot,t_0,m_fast`
:
"https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png"
:
'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
}
alt=
''
/>
...
...
@@ -306,9 +306,9 @@ class KnowledgeBaseList extends React.Component {
</
div
>
)
}
{
type
===
"PICTURE"
&&
(
{
type
===
'PICTURE'
&&
(
<
div
className=
'record__item'
>
<
img
className=
'course-cover'
src=
{
coverUrl
||
"https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png"
}
/>
<
img
className=
'course-cover'
src=
{
coverUrl
||
'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'
}
/>
{
val
.
length
>
25
?
(
<
Tooltip
title=
{
val
}
>
<
div
className=
'course-name clamp'
>
{
val
}
</
div
>
...
...
@@ -319,11 +319,11 @@ class KnowledgeBaseList extends React.Component {
</
div
>
)
}
{
type
===
"FOLDER"
&&
(
{
type
===
'FOLDER'
&&
(
<
div
className=
'record__item'
onClick=
{
()
=>
{
this
.
handleScanFile
(
record
.
source
)
this
.
handleScanFile
(
record
.
source
)
;
}
}
>
<
div
className=
{
`folder-type ${record.source && record.source.folderFormat}`
}
/>
{
val
.
length
>
25
?
(
...
...
@@ -336,24 +336,24 @@ class KnowledgeBaseList extends React.Component {
</
div
>
)
}
</
div
>
)
}
)
;
}
,
},
{
title
:
"课程类型"
,
key
:
"type"
,
dataIndex
:
"type"
,
align
:
"center"
,
title
:
'课程类型'
,
key
:
'type'
,
dataIndex
:
'type'
,
align
:
'center'
,
// width: 100,
render
:
(
val
,
record
)
=>
{
return
<
div
className=
''
>
{
val
?
ENUM
.
CourseTypeEnum
[
val
]
:
"-"
}
</
div
>
}
return
<
div
className=
''
>
{
val
?
ENUM
.
CourseTypeEnum
[
val
]
:
'-'
}
</
div
>;
}
,
},
{
title
:
"创建人"
,
key
:
"createName"
,
dataIndex
:
"createName"
,
align
:
"center"
,
title
:
'创建人'
,
key
:
'createName'
,
dataIndex
:
'createName'
,
align
:
'center'
,
render
:
(
val
)
=>
{
return
(
<
div
>
...
...
@@ -363,37 +363,37 @@ class KnowledgeBaseList extends React.Component {
</
Tooltip
>
)
}
</
div
>
)
}
)
;
}
,
},
{
title
:
"观看学员数"
,
key
:
"watchUserCount"
,
dataIndex
:
"watchUserCount"
,
align
:
"right"
,
title
:
'观看学员数'
,
key
:
'watchUserCount'
,
dataIndex
:
'watchUserCount'
,
align
:
'right'
,
render
:
(
val
,
item
)
=>
{
return
val
?
(
<
div
className=
'operate'
style=
{
{
display
:
"block"
}
}
onClick=
{
()
=>
this
.
handleLinkToClassData
(
item
)
}
>
<
div
className=
'operate'
style=
{
{
display
:
'block'
}
}
onClick=
{
()
=>
this
.
handleLinkToClassData
(
item
)
}
>
<
span
className=
'operate__item'
>
{
val
}
</
span
>
</
div
>
)
:
(
0
)
}
)
;
}
,
},
{
title
:
""
,
width
:
48
title
:
''
,
width
:
48
,
},
{
title
:
"操作"
,
key
:
"operate"
,
dataIndex
:
"operate"
,
title
:
'操作'
,
key
:
'operate'
,
dataIndex
:
'operate'
,
width
:
160
,
fixed
:
"right"
,
fixed
:
'right'
,
render
:
(
val
,
record
,
index
)
=>
{
console
.
log
(
this
.
props
.
categoryId
)
return
this
.
props
.
categoryId
===
"0"
?
(
console
.
log
(
this
.
props
.
categoryId
)
;
return
this
.
props
.
categoryId
===
'0'
?
(
<
div
className=
'operate'
>
<
div
className=
'operate__item'
onClick=
{
()
=>
this
.
handleDelete
(
record
)
}
>
移出
...
...
@@ -401,12 +401,12 @@ class KnowledgeBaseList extends React.Component {
</
div
>
)
:
(
<
div
className=
'operate'
>
<
div
className=
{
index
===
0
&&
current
===
1
?
"operate__item disable"
:
"operate__item"
}
onClick=
{
()
=>
this
.
handleUp
(
index
,
record
)
}
>
<
div
className=
{
index
===
0
&&
current
===
1
?
'operate__item disable'
:
'operate__item'
}
onClick=
{
()
=>
this
.
handleUp
(
index
,
record
)
}
>
上移
</
div
>
<
span
className=
'operate__item split'
>
|
</
span
>
<
div
className=
{
totalCount
===
size
*
(
current
-
1
)
+
index
+
1
?
"operate__item disable"
:
"operate__item"
}
className=
{
totalCount
===
size
*
(
current
-
1
)
+
index
+
1
?
'operate__item disable'
:
'operate__item'
}
onClick=
{
()
=>
this
.
handleDown
(
record
,
index
)
}
>
下移
</
div
>
...
...
@@ -415,66 +415,66 @@ class KnowledgeBaseList extends React.Component {
移出
</
div
>
</
div
>
)
}
}
]
return
columns
}
)
;
}
,
}
,
]
;
return
columns
;
}
;
handleDelete
=
(
record
)
=>
{
return
confirm
({
title
:
"移出知识"
,
content
:
"确定将分类中此知识移出吗?"
,
title
:
'移出知识'
,
content
:
'确定将分类中此知识移出吗?'
,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
okText
:
"删除"
,
okType
:
"danger"
,
cancelText
:
"取消"
,
okText
:
'删除'
,
okType
:
'danger'
,
cancelText
:
'取消'
,
width
:
440
,
height
:
188
,
onOk
:
()
=>
{
this
.
deleteConfirm
(
record
)
}
})
}
this
.
deleteConfirm
(
record
)
;
}
,
})
;
}
;
// 前往上课数据页面
handleLinkToClassData
=
(
item
)
=>
{
const
{
match
}
=
this
.
props
console
.
log
(
item
)
localStorage
.
setItem
(
"WatchData_CourseName"
,
item
.
name
)
const
{
match
}
=
this
.
props
;
console
.
log
(
item
)
;
localStorage
.
setItem
(
'WatchData_CourseName'
,
item
.
name
);
window
.
RCHistory
.
push
({
// pathname: `${match.url}/course-data?type=${item.courseType}&id=${item.liveCourseId}`,
pathname
:
`
${
match
.
url
}
/course-data?type=
${
item
.
type
}
&id=
${
item
.
id
}
`
})
}
pathname
:
`
${
match
.
url
}
/course-data?type=
${
item
.
type
}
&id=
${
item
.
id
}
`
,
})
;
}
;
deleteConfirm
=
(
item
)
=>
{
const
params
=
{
id
:
item
.
id
,
storeId
:
item
.
storeId
}
storeId
:
item
.
storeId
,
}
;
KnowledgeAPI
.
delKnowledge
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
"移出成功"
)
this
.
props
.
onChange
()
this
.
props
.
updateCategoryTree
()
message
.
success
(
'移出成功'
);
this
.
props
.
onChange
()
;
this
.
props
.
updateCategoryTree
()
;
}
})
}
})
;
}
;
onShowSizeChange
=
(
current
,
size
)
=>
{
if
(
current
==
size
)
{
return
return
;
}
let
_query
=
this
.
props
.
query
_query
.
size
=
size
this
.
props
.
onChange
(
_query
)
}
let
_query
=
this
.
props
.
query
;
_query
.
size
=
size
;
this
.
props
.
onChange
(
_query
)
;
}
;
render
()
{
const
{
dataSource
=
[],
totalCount
,
query
,
match
}
=
this
.
props
const
{
current
,
size
}
=
query
const
{
dataSource
=
[],
totalCount
,
query
,
match
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
return
(
<
div
className=
'knowledge-base-list'
>
<
Table
...
...
@@ -495,8 +495,8 @@ class KnowledgeBaseList extends React.Component {
pageSize=
{
size
}
total=
{
totalCount
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
query
,
current
:
page
+
1
}
this
.
props
.
onChange
(
_query
)
const
_query
=
{
...
query
,
current
:
page
+
1
}
;
this
.
props
.
onChange
(
_query
)
;
}
}
onShowSizeChange=
{
this
.
onShowSizeChange
}
/>
...
...
@@ -507,8 +507,8 @@ class KnowledgeBaseList extends React.Component {
{
this
.
state
.
scanFileModal
}
</
div
>
)
)
;
}
}
export
default
withRouter
(
KnowledgeBaseList
)
export
default
withRouter
(
KnowledgeBaseList
)
;
src/modules/knowledge-base/index.jsx
View file @
1402a09b
import
React
from
'react'
;
import
React
from
'react'
import
KnowledgeBaseFilter
from
'./components/KnowledgeBaseFilter'
;
import
KnowledgeBaseOpt
from
'./components/KnowledgeBaseOpt'
;
import
KnowledgeBaseList
from
'./components/KnowledgeBaseList'
;
import
Classification
from
'./components/Classification'
;
import
KnowledgeBaseFilter
from
'./components/KnowledgeBaseFilter'
import
KnowledgeBaseOpt
from
'./components/KnowledgeBaseOpt'
import
KnowledgeBaseList
from
'./components/KnowledgeBaseList'
import
Classification
from
'./components/Classification'
import
KnowledgeAPI
from
'@/data-source/knowledge/request-api'
import
User
from
'@/common/js/user'
import
KnowledgeAPI
from
'@/data-source/knowledge/request-api'
;
import
User
from
'@/common/js/user'
;
export
default
class
KnowledgeBase
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
query
:
{
size
:
10
,
...
...
@@ -23,51 +22,51 @@ export default class KnowledgeBase extends React.Component {
totalCount
:
0
,
// 知识库数据总条数
categoryId
:
'0'
,
updateCategoryFlag
:
false
,
}
}
;
}
componentWillMount
()
{
// 获取知识库列表
this
.
handleFetchScheduleList
()
this
.
handleFetchScheduleList
()
;
// this.getCategoryTree()
}
getSelectedCategoryId
=
(
categoryId
)
=>
{
this
.
setState
({
categoryId
,
})
this
.
handleFetchScheduleList
({
categoryId
,
current
:
1
})
}
})
;
this
.
handleFetchScheduleList
({
categoryId
,
current
:
1
})
;
}
;
// 更新分类树
updateCategoryTree
=
()
=>
{
this
.
setState
({
updateCategoryFlag
:
!
this
.
state
.
updateCategoryFlag
,
})
}
})
;
}
;
// 获取知识库列表
handleFetchScheduleList
=
(
_query
=
{},
flag
=
true
)
=>
{
const
query
=
{
...
this
.
state
.
query
,
...
_query
,
}
}
;
// 更新请求参数
this
.
setState
({
query
})
this
.
setState
({
query
})
;
flag
&&
KnowledgeAPI
.
queryPageKnowledgeForManager
(
query
).
then
((
res
)
=>
{
// KnowledgeAPI.videoSchedulePage(query).then((res) => {
const
{
result
=
{}
}
=
res
||
{}
const
{
records
=
[],
total
=
0
}
=
result
const
{
result
=
{}
}
=
res
||
{}
;
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
dataSource
:
records
,
totalCount
:
Number
(
total
),
})
})
}
})
;
})
;
}
;
render
()
{
const
{
dataSource
,
totalCount
,
query
,
categoryId
,
updateCategoryFlag
}
=
this
.
state
const
{
dataSource
,
totalCount
,
query
,
categoryId
,
updateCategoryFlag
}
=
this
.
state
;
return
(
<
div
className=
'page'
>
<
div
className=
'content-header'
>
知识库
</
div
>
...
...
@@ -77,11 +76,8 @@ export default class KnowledgeBase extends React.Component {
<
div
className=
'left'
style=
{
{
width
:
245
}
}
>
<
Classification
updateCategoryFlag=
{
updateCategoryFlag
}
categoryId=
{
categoryId
}
getSelectedCategoryId=
{
this
.
getSelectedCategoryId
}
/>
</
div
>
<
div
className=
"liner"
style=
{
{
backgroundColor
:
"rgb(238, 238, 238)"
,
width
:
0.5
,
margin
:
"1px 16px 1px 2px"
}
}
></
div
>
<
div
className=
"right"
style=
{
{
width
:
"calc(100% - 265px)"
}
}
>
<
div
className=
'liner'
style=
{
{
backgroundColor
:
'rgb(238, 238, 238)'
,
width
:
0.5
,
margin
:
'1px 16px 1px 2px'
}
}
></
div
>
<
div
className=
'right'
style=
{
{
width
:
'calc(100% - 265px)'
}
}
>
<
KnowledgeBaseFilter
onChange=
{
this
.
handleFetchScheduleList
}
/>
{
/* 操作模块 */
}
...
...
@@ -101,6 +97,6 @@ export default class KnowledgeBase extends React.Component {
</
div
>
</
div
>
</
div
>
)
)
;
}
}
src/modules/knowledge-base/modal/AddCourse.jsx
View file @
1402a09b
...
...
@@ -3,7 +3,7 @@
* @Author: zangsuyun
* @Date: 2021-03-13 09:54:26
* @LastEditors: fusanqiasng
* @LastEditTime: 2021-0
5-31 18:23:28
* @LastEditTime: 2021-0
6-01 10:26:46
* @Copyright: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -258,7 +258,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchLiveList
();
}
,
}
);
};
...
...
@@ -272,7 +272,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchVideoList
();
}
,
}
);
};
...
...
@@ -286,7 +286,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchPictureList
();
}
,
}
);
};
...
...
@@ -593,7 +593,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchVideoList
();
}
,
}
);
};
...
...
@@ -615,7 +615,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchLiveList
();
}
,
}
);
};
...
...
@@ -629,7 +629,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchPictureList
();
}
,
}
);
};
handAddCourse
=
()
=>
{
...
...
@@ -696,7 +696,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchVideoList
();
}
,
}
);
};
...
...
@@ -858,7 +858,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchLiveList
();
}
,
}
);
}
}
onShowSizeChange=
{
this
.
onShowLiveSizeChange
}
...
...
@@ -893,6 +893,7 @@ class AddCourse extends React.Component {
<
TreeSelect
treeNodeFilterProp=
'categoryName'
showSearch
value=
{
videoQuery
[
videoCourseDivision
].
categoryId
||
null
}
style=
{
{
minWidth
:
'calc(100% - 75px)'
}
}
value=
{
videoQuery
[
videoCourseDivision
].
categoryId
||
null
}
dropdownMatchSelectWidth=
{
false
}
...
...
@@ -950,7 +951,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchVideoList
();
}
,
}
);
}
}
onShowSizeChange=
{
this
.
onShowVideoSizeChange
}
...
...
@@ -1030,7 +1031,7 @@ class AddCourse extends React.Component {
},
()
=>
{
this
.
handleFetchPictureList
();
}
,
}
);
}
}
onShowSizeChange=
{
this
.
onShowPictureSizeChange
}
...
...
src/modules/knowledge-base/modal/LiveList.less
View file @
1402a09b
...
...
@@ -71,13 +71,13 @@
}
.courseware {
font-size: 14px;
color: #2966
FF
;
color: #2966
ff
;
line-height: 20px;
text-align: right;
cursor: pointer;
}
.quota-icon {
color: #2966
FF
;
color: #2966
ff
;
cursor: pointer;
}
.operate {
...
...
@@ -85,7 +85,7 @@
align-items: center;
flex-wrap: wrap;
.operate__item {
color: #2966
FF
;
color: #2966
ff
;
cursor: pointer;
&.split {
margin: 0 8px;
...
...
@@ -94,7 +94,7 @@
}
}
.operate-text {
color: #2966
FF
;
color: #2966
ff
;
cursor: pointer;
}
.course-start-end {
...
...
@@ -127,8 +127,8 @@
.add-course-modal {
.ant-tabs-nav .ant-tabs-tab-active {
// border: 1px solid #2966FF;
color: #2966
FF
;
}
color: #2966
ff
;
}
.ant-modal-content tr > td {
padding: 12px 8px !important;
}
...
...
src/modules/plan-manage/AddPlan.jsx
View file @
1402a09b
...
...
@@ -2,7 +2,11 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: wufan
<<<<<<< HEAD
* @LastEditTime: 2021-05-30 17:40:39
=======
* @LastEditTime: 2021-05-30 20:39:16
>>>>>>> hotfix/pangguoming/20210601/plan_list_add_cover
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
src/modules/plan-manage/components/BasicInfo.jsx
View file @
1402a09b
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors:
wufan
* @LastEditTime: 2021-0
5-13 16:36:26
* @LastEditors:
fusanqiasng
* @LastEditTime: 2021-0
6-01 15:20:33
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
{
Button
,
Input
,
Switch
,
Radio
,
Row
,
Col
,
Modal
,
message
,
Tooltip
}
from
'antd'
;
import
{
Button
,
Input
,
Switch
,
Radio
,
Row
,
Col
,
Modal
,
message
,
Tooltip
}
from
'antd'
;
import
{
withRouter
}
from
'react-router-dom'
;
import
SelectOperatorModal
from
'../modal/SelectOperatorModal'
;
import
{
ImgCutModalNew
}
from
'@/components'
;
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
;
import
Upload
from
'@/core/upload'
;
// import PhotoClip from 'photoclip'
import
'./BasicInfo.less'
;
const
{
TextArea
}
=
Input
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/
YNfi45JwFA
.png'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/
rEAetaTEh3
.png'
;
let
cutFlag
=
false
;
let
timer
=
null
class
BasicInfo
extends
React
.
Component
{
class
BasicInfo
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
operatorModalVisible
:
false
,
showSelectFileModal
:
false
,
cutImageBlob
:
null
showSelectFileModal
:
false
,
cutImageBlob
:
null
,
};
}
handleShowSelectOperatorModal
=
()
=>
{
handleShowSelectOperatorModal
=
()
=>
{
this
.
setState
({
operatorModalVisible
:
true
})
}
handleCloseSelectOperatorMOdal
=
()
=>
{
operatorModalVisible
:
true
,
})
;
}
;
handleCloseSelectOperatorMOdal
=
()
=>
{
this
.
setState
({
operatorModalVisible
:
false
})
}
handleConfirmSelectOperator
=
(
selectOperatorList
)
=>
{
if
(
selectOperatorList
.
length
===
0
)
{
message
.
warning
(
'请选择运营师'
)
operatorModalVisible
:
false
,
})
;
}
;
handleConfirmSelectOperator
=
(
selectOperatorList
)
=>
{
if
(
selectOperatorList
.
length
===
0
)
{
message
.
warning
(
'请选择运营师'
)
;
return
;
}
this
.
props
.
onChange
(
'selectOperatorList'
,
selectOperatorList
);
this
.
props
.
onChange
(
'selectOperatorList'
,
selectOperatorList
);
this
.
setState
({
operatorModalVisible
:
false
})
}
enableStateChange
=
()
=>
{
if
(
this
.
props
.
data
.
enableState
===
"NO"
)
{
this
.
props
.
onChange
(
'enableState'
,
'YES'
)
}
else
{
this
.
props
.
onChange
(
'enableState'
,
'NO'
)
operatorModalVisible
:
false
,
})
;
}
;
enableStateChange
=
()
=>
{
if
(
this
.
props
.
data
.
enableState
===
'NO'
)
{
this
.
props
.
onChange
(
'enableState'
,
'YES'
);
}
else
{
this
.
props
.
onChange
(
'enableState'
,
'NO'
);
}
}
}
;
// 使用默认封面图
handleResetCoverUrl
=
()
=>
{
const
{
data
:
{
coverUrl
}
}
=
this
.
props
;
handleResetCoverUrl
=
()
=>
{
const
{
data
:
{
coverUrl
},
}
=
this
.
props
;
const
isDefaultCover
=
coverUrl
===
defaultCover
;
// 如果已经是默认图的话,不做任何任何处理
if
(
isDefaultCover
)
return
;
message
.
success
(
'已替换为默认图'
);
this
.
props
.
onChange
(
'coverUrl'
,
defaultCover
);
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'coverUrl'
,
defaultCover
);
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'coverId'
,
null
);
},
1000
)
}
handleSelectCover
=
(
file
)
=>
{
},
1000
);
}
;
handleSelectCover
=
(
file
)
=>
{
this
.
uploadImage
(
file
);
}
}
;
//上传图片
uploadImage
=
(
imageFile
)
=>
{
const
{
folderName
}
=
imageFile
;
const
fileName
=
window
.
random_string
(
16
)
+
folderName
.
slice
(
folderName
.
lastIndexOf
(
"."
));
const
self
=
this
;
this
.
setState
(
{
...
...
@@ -87,57 +83,55 @@ class BasicInfo extends React.Component{
},
()
=>
{
setTimeout
(()
=>
{
const
okBtnDom
=
document
.
querySelector
(
"#headPicModal"
);
const
okBtnDom
=
document
.
querySelector
(
'#headPicModal'
);
const
options
=
{
size
:
[
500
,
282
],
ok
:
okBtnDom
,
maxZoom
:
3
,
style
:
{
jpgFillColor
:
"transparent"
,
jpgFillColor
:
'transparent'
,
},
done
:
function
(
dataUrl
)
{
clearTimeout
(
self
.
timer
);
self
.
timer
=
setTimeout
(()
=>
{
if
(
(
self
.
state
.
rotate
!=
this
.
rotate
())
||
(
self
.
state
.
scale
!=
this
.
scale
()
))
{
console
.
log
(
this
.
scale
(),
'scale'
)
const
_dataUrl
=
this
.
clip
()
if
(
self
.
state
.
rotate
!==
this
.
rotate
()
||
self
.
state
.
scale
!==
this
.
scale
(
))
{
console
.
log
(
this
.
scale
(),
'scale'
)
;
const
_dataUrl
=
this
.
clip
()
;
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
_dataUrl
);
self
.
setState
({
cutImageBlob
,
dataUrl
:
_dataUrl
,
rotate
:
this
.
rotate
(),
scale
:
this
.
scale
()
})
scale
:
this
.
scale
()
,
})
;
}
},
500
)
},
500
);
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
dataUrl
);
self
.
setState
({
cutImageBlob
,
dataUrl
})
dataUrl
,
})
;
setTimeout
(()
=>
{
cutFlag
=
false
;
},
2000
);
},
fail
:
(
failInfo
)
=>
{
message
.
error
(
"图片上传失败了,请重新上传"
);
message
.
error
(
'图片上传失败了,请重新上传'
);
},
loadComplete
:
function
(
img
)
{
setTimeout
(()
=>
{
const
_dataUrl
=
this
.
clip
()
const
_dataUrl
=
this
.
clip
()
;
self
.
setState
({
dataUrl
:
_dataUrl
,
hasImgReady
:
true
})
},
100
)
hasImgReady
:
true
,
});
},
100
);
},
};
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
;
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
"#headPicModal"
,
options
);
const
_photoclip
=
new
PhotoClip
(
'#headPicModal'
,
options
);
_photoclip
.
load
(
imgUrl
);
this
.
setState
({
photoclip
:
_photoclip
,
...
...
@@ -146,7 +140,6 @@ class BasicInfo extends React.Component{
this
.
state
.
photoclip
.
clear
();
this
.
state
.
photoclip
.
load
(
imgUrl
);
}
},
200
);
}
);
...
...
@@ -154,290 +147,319 @@ class BasicInfo extends React.Component{
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
Upload
.
uploadBlobToOSS
(
blob
,
'cover'
+
(
new
Date
()).
valueOf
(),
null
,
'signInfo'
).
then
((
signInfo
)
=>
{
this
.
setState
({
coverClicpPath
:
signInfo
.
fileUrl
,
coverId
:
signInfo
.
resourceId
,
visible
:
false
},()
=>
this
.
updateCover
())
Upload
.
uploadBlobToOSS
(
blob
,
'cover'
+
new
Date
().
valueOf
(),
null
,
'signInfo'
).
then
((
signInfo
)
=>
{
this
.
setState
(
{
coverClicpPath
:
signInfo
.
fileUrl
,
coverId
:
signInfo
.
resourceId
,
visible
:
false
,
},
()
=>
this
.
updateCover
()
);
});
};
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
;
this
.
setState
({
showSelectFileModal
:
false
})
showSelectFileModal
:
false
,
})
;
this
.
props
.
onChange
(
'coverUrl'
,
coverClicpPath
);
setTimeout
(()
=>
{
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'coverId'
,
coverId
);
},
1000
)
}
// base64转换成blob
},
1000
);
}
;
// base64转换成blob
convertBase64UrlToBlob
=
(
urlData
)
=>
{
const
bytes
=
window
.
atob
(
urlData
.
split
(
","
)[
1
]);
const
bytes
=
window
.
atob
(
urlData
.
split
(
','
)[
1
]);
const
ab
=
new
ArrayBuffer
(
bytes
.
length
);
const
ia
=
new
Uint8Array
(
ab
);
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
ia
[
i
]
=
bytes
.
charCodeAt
(
i
);
}
return
new
Blob
([
ab
],
{
type
:
"image/png"
});
return
new
Blob
([
ab
],
{
type
:
'image/png'
});
};
limitNumber
=
value
=>
{
limitNumber
=
(
value
)
=>
{
if
(
typeof
value
===
'string'
)
{
return
!
isNaN
(
Number
(
value
))
?
value
.
replace
(
/^
(
0+
)
|
[^\d]
/g
,
''
)
:
''
return
!
isNaN
(
Number
(
value
))
?
value
.
replace
(
/^
(
0+
)
|
[^\d]
/g
,
''
)
:
''
;
}
else
if
(
typeof
value
===
'number'
)
{
return
!
isNaN
(
value
)
?
String
(
value
).
replace
(
/^
(
0+
)
|
[^\d]
/g
,
''
)
:
''
return
!
isNaN
(
value
)
?
String
(
value
).
replace
(
/^
(
0+
)
|
[^\d]
/g
,
''
)
:
''
;
}
else
{
return
''
return
''
;
}
}
percentCompleteBlur
=
(
e
,
field
)
=>
{
}
;
percentCompleteBlur
=
(
e
,
field
)
=>
{
let
_percentCompleteLive
;
const
{
value
}
=
e
.
target
;
if
(
value
>
100
)
{
if
(
value
>
100
)
{
_percentCompleteLive
=
100
;
}
else
{
if
(
value
<
0
)
{
}
else
{
if
(
value
<
0
)
{
_percentCompleteLive
=
0
;
}
else
{
}
else
{
_percentCompleteLive
=
value
;
}
}
this
.
props
.
onChange
(
field
,
_percentCompleteLive
)
}
render
(){
const
{
operatorModalVisible
,
showSelectFileModal
,
visible
,
hasImgReady
,
cutImageBlob
}
=
this
.
state
;
const
{
data
}
=
this
.
props
;
const
{
planName
,
coverUrl
,
instro
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
}
=
data
;
this
.
props
.
onChange
(
field
,
_percentCompleteLive
);
};
render
()
{
const
{
operatorModalVisible
,
showSelectFileModal
,
visible
,
hasImgReady
,
cutImageBlob
}
=
this
.
state
;
const
{
data
}
=
this
.
props
;
const
{
planName
,
coverUrl
,
instro
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
}
=
data
;
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
return
(
<
div
className=
"plan-basic-info"
>
<
div
className=
"plan-name"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
培训计划名称:
</
span
>
<
Input
value=
{
planName
}
placeholder=
"请输入培训计划名称(20字以内)"
maxLength=
{
20
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
this
.
props
.
onChange
(
'planName'
,
e
.
target
.
value
)
}
/>
</
div
>
<
div
className=
"cover"
>
<
span
className=
"label"
>
封面图:
</
span
>
<
div
className=
"cover__wrap"
>
<
div
className=
"img-content"
>
{
isDefaultCover
&&
<
span
className=
"tag"
>
默认图
</
span
>
}
<
img
src=
{
coverUrl
}
width=
"690"
/>
</
div
>
<
div
className=
"opt-btns"
>
<
Button
onClick=
{
()
=>
{
<
div
className=
'plan-basic-info'
>
<
div
className=
'plan-name'
>
<
span
className=
'label'
>
<
span
className=
'require'
>
*
</
span
>
培训计划名称:
</
span
>
<
Input
value=
{
planName
}
placeholder=
'请输入培训计划名称(20字以内)'
maxLength=
{
20
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
this
.
props
.
onChange
(
'planName'
,
e
.
target
.
value
)
}
/>
</
div
>
<
div
className=
'cover'
>
<
span
className=
'label'
>
封面图:
</
span
>
<
div
className=
'cover__wrap'
>
<
div
className=
'img-content'
>
{
isDefaultCover
&&
<
span
className=
'tag'
>
默认图
</
span
>
}
<
img
src=
{
coverUrl
}
width=
'690'
alt=
''
/>
</
div
>
<
div
className=
'opt-btns'
>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
true
})
}
}
>
上传图片
</
Button
>
<
span
className=
{
`default-btn ${isDefaultCover ? 'disabled' : ''}`
}
onClick=
{
this
.
handleResetCoverUrl
}
>
使用默认图
</
span
>
<
div
className=
"tips"
>
建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。
</
div
>
</
div
>
showSelectFileModal
:
true
,
})
;
}
}
>
上传图片
</
Button
>
<
span
className=
{
`default-btn ${isDefaultCover ? 'disabled' : ''}`
}
onClick=
{
this
.
handleResetCoverUrl
}
>
使用默认图
</
span
>
<
div
className=
'tips'
>
建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。
<
/
div
>
</
div
>
</
div
>
<
div
className=
"introduction"
>
<
span
className=
"label"
>
简介:
</
span
>
<
TextArea
placeholder=
"请输入培训计划简介"
maxLength=
{
200
}
style=
{
{
width
:
'552px'
,
height
:
'110px'
}
}
className=
"instro-textarea"
value=
{
instro
}
onChange=
{
(
e
)
=>
this
.
props
.
onChange
(
'instro'
,
e
.
target
.
value
)
}
</
div
>
<
div
className=
'introduction'
>
<
span
className=
'label'
>
简介:
</
span
>
<
TextArea
placeholder=
'请输入培训计划简介'
maxLength=
{
200
}
style=
{
{
width
:
'552px'
,
height
:
'110px'
}
}
className=
'instro-textarea'
value=
{
instro
}
onChange=
{
(
e
)
=>
this
.
props
.
onChange
(
'instro'
,
e
.
target
.
value
)
}
/>
</
div
>
<
div
className=
'wether-use'
>
<
span
className=
'label'
>
是否启用:
</
span
>
<
div
className=
'content'
>
<
div
>
<
Switch
checked=
{
enableState
===
'YES'
?
true
:
false
}
onChange=
{
()
=>
{
this
.
enableStateChange
();
}
}
/>
</
div
>
<
div
className=
"wether-use"
>
<
span
className=
"label"
>
是否启用:
</
span
>
<
div
className=
"content"
>
<
div
>
<
Switch
checked=
{
enableState
===
"YES"
?
true
:
false
}
onChange=
{
()
=>
{
this
.
enableStateChange
()}
}
/>
</
div
>
<
div
>
<
div
className=
"instro-text"
>
<
div
>
开启:此培训计划可以分享给学员进行学习
</
div
>
<
div
>
关闭:此培训计划暂不可分享给学员进行学习,后续可开启
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"view-range"
>
<
span
className=
"label"
>
<
span
className=
"require"
>
*
</
span
>
可见范围
<
Tooltip
title=
"学院管理员、管理员默认都可见"
>
<
span
className=
"iconfont"
>

</
span
>
</
Tooltip
>
:
</
span
>
<
div
className=
"content"
>
<
Radio
.
Group
value=
{
operateType
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'operateType'
,
e
.
target
.
value
)
}
}
>
<
Row
style=
{
{
marginBottom
:
'5px'
}
}
>
<
Col
span=
{
24
}
>
<
Radio
value=
"All_Operate"
>
所有运营师
<
span
className=
"playback__text"
>
后续新增的运营师都有权限可见
</
span
>
</
Radio
>
</
Col
>
</
Row
>
<
Row
>
<
Col
span=
{
24
}
>
<
Radio
value=
"Assign_Operate"
>
指定运营师
<
span
className=
"playback__text"
>
仅被选择的运营师有权限可见
</
span
>
</
Radio
>
</
Col
>
</
Row
>
</
Radio
.
Group
>
{
operateType
===
"Assign_Operate"
&&
<
div
className=
"choose-business"
>
<
Button
onClick=
{
()
=>
{
this
.
handleShowSelectOperatorModal
()}
}
>
选择运营师
</
Button
>
<
span
>
已选择
<
span
>
{
selectOperatorList
.
length
}
</
span
>
名运营师
</
span
>
</
div
>
}
<
div
>
<
div
className=
'instro-text'
>
<
div
>
开启:此培训计划可以分享给学员进行学习
</
div
>
<
div
>
关闭:此培训计划暂不可分享给学员进行学习,后续可开启
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"done-standard"
>
<
span
className=
"label standard-label"
><
span
className=
"require"
>
*
</
span
>
完成标准:
</
span
>
<
div
>
<
div
className=
"live-standard-info"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"instro"
>
直播课单个课程,学员学习进度达到
<
Input
width=
"40"
value=
{
percentCompleteLive
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompleteLive'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
))
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteLive'
)
}
className=
"input-box"
/>
%,即视为"已完成"学习
</
span
>
</
div
>
<
div
className=
"live-standard-info"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"instro"
>
视频课单个课程,学员学习进度达到
<
Input
width=
"40"
value=
{
percentCompleteVideo
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompleteVideo'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
))
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteVideo'
)
}
className=
"input-box"
/>
%,即视为"已完成"学习
</
span
>
</
div
>
<
div
className=
"live-standard-info"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"instro"
>
图文课单个课程,学员学习进度达到
<
Input
width=
"40"
value=
{
percentCompletePicture
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompletePicture'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
))
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompletePicture'
)
}
className=
"input-box"
/>
%,即视为"已完成"学习
</
span
>
</
div
>
</
div
>
</
div
>
<
div
className=
'view-range'
>
<
span
className=
'label'
>
<
span
className=
'require'
>
*
</
span
>
可见范围
<
Tooltip
title=
'学院管理员、管理员默认都可见'
>
<
span
className=
'iconfont'
>

</
span
>
</
Tooltip
>
:
</
span
>
<
div
className=
'content'
>
<
Radio
.
Group
value=
{
operateType
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'operateType'
,
e
.
target
.
value
);
}
}
>
<
Row
style=
{
{
marginBottom
:
'5px'
}
}
>
<
Col
span=
{
24
}
>
<
Radio
value=
'All_Operate'
>
所有运营师
<
span
className=
'playback__text'
>
后续新增的运营师都有权限可见
</
span
>
</
Radio
>
</
Col
>
</
Row
>
<
Row
>
<
Col
span=
{
24
}
>
<
Radio
value=
'Assign_Operate'
>
指定运营师
<
span
className=
'playback__text'
>
仅被选择的运营师有权限可见
</
span
>
</
Radio
>
</
Col
>
</
Row
>
</
Radio
.
Group
>
{
operateType
===
'Assign_Operate'
&&
(
<
div
className=
'choose-business'
>
<
Button
onClick=
{
()
=>
{
this
.
handleShowSelectOperatorModal
();
}
}
>
选择运营师
</
Button
>
<
span
>
已选择
<
span
>
{
selectOperatorList
.
length
}
</
span
>
名运营师
</
span
>
</
div
>
)
}
</
div
>
{
operatorModalVisible
&&
<
SelectOperatorModal
visible=
{
operatorModalVisible
}
onClose=
{
this
.
handleCloseSelectOperatorMOdal
}
selectOperatorList=
{
selectOperatorList
}
onSelect=
{
this
.
handleConfirmSelectOperator
}
/>
}
{
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
}
visible=
{
visible
}
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
"icon iconfont modal-close-icon"
>

</
span
>
}
onCancel=
{
()
=>
{
this
.
setState
({
visible
:
false
});
</
div
>
<
div
className=
'done-standard'
>
<
span
className=
'label standard-label'
>
<
span
className=
'require'
>
*
</
span
>
完成标准:
</
span
>
<
div
>
<
div
className=
'live-standard-info'
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'instro'
>
直播课单个课程,学员学习进度达到
<
Input
width=
'40'
value=
{
percentCompleteLive
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompleteLive'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
));
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteLive'
)
}
className=
'input-box'
/>
%,即视为"已完成"学习
</
span
>
</
div
>
<
div
className=
'live-standard-info'
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'instro'
>
视频课单个课程,学员学习进度达到
<
Input
width=
'40'
value=
{
percentCompleteVideo
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompleteVideo'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
));
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteVideo'
)
}
className=
'input-box'
/>
%,即视为"已完成"学习
</
span
>
</
div
>
<
div
className=
'live-standard-info'
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'instro'
>
图文课单个课程,学员学习进度达到
<
Input
width=
'40'
value=
{
percentCompletePicture
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'percentCompletePicture'
,
e
.
target
.
value
.
replace
(
/
\D
/g
,
''
));
}
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompletePicture'
)
}
className=
'input-box'
/>
%,即视为"已完成"学习
</
span
>
</
div
>
</
div
>
</
div
>
{
operatorModalVisible
&&
(
<
SelectOperatorModal
visible=
{
operatorModalVisible
}
onClose=
{
this
.
handleCloseSelectOperatorMOdal
}
selectOperatorList=
{
selectOperatorList
}
onSelect=
{
this
.
handleConfirmSelectOperator
}
/>
)
}
{
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
,
});
}
}
zIndex=
{
10001
}
footer=
{
[
<
Button
key=
"back"
onClick=
{
()
=>
{
this
.
setState
({
visible
:
false
});
}
}
>
重新上传
</
Button
>,
<
Button
key=
"submit"
type=
"primary"
disabled=
{
!
hasImgReady
}
onClick=
{
()
=>
{
if
(
!
cutFlag
)
{
cutFlag
=
true
;
this
.
refs
.
hiddenBtn
.
click
();
}
this
.
getSignature
(
cutImageBlob
);
}
}
>
确定
</
Button
>,
]
}
>
<
div
className=
"clip-box"
>
<
div
id=
"headPicModal"
ref=
"headPicModal"
style=
{
{
width
:
"500px"
,
height
:
"430px"
,
marginBottom
:
0
,
}
}
></
div
>
<
div
id=
"clipBtn"
style=
{
{
display
:
"none"
}
}
ref=
"hiddenBtn"
></
div
>
<
div
className=
"preview-img"
>
<
div
className=
"title"
>
效果预览
</
div
>
<
div
id=
"preview-url-box"
style=
{
{
width
:
500
,
height
:
282
}
}
>
<
img
src=
{
this
.
state
.
dataUrl
}
style=
{
{
width
:
'100%'
}
}
alt=
""
/>
</
div
>
<
div
className=
"tip-box"
>
<
div
className=
"tip"
>
温馨提示
</
div
>
<
div
className=
"tip"
>
①预览效果图时可能存在延迟,单击左侧图片刷新即可
</
div
>
<
div
className=
"tip"
>
②设置图片时双击可旋转图片,滚动可放大或缩小图片
</
div
>
</
div
>
onSelect=
{
this
.
handleSelectCover
}
/>
)
}
<
Modal
title=
'设置图片'
width=
{
1080
}
visible=
{
visible
}
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
onCancel=
{
()
=>
{
this
.
setState
({
visible
:
false
});
}
}
zIndex=
{
10001
}
footer=
{
[
<
Button
key=
'back'
onClick=
{
()
=>
{
this
.
setState
({
visible
:
false
});
}
}
>
重新上传
</
Button
>,
<
Button
key=
'submit'
type=
'primary'
disabled=
{
!
hasImgReady
}
onClick=
{
()
=>
{
if
(
!
cutFlag
)
{
cutFlag
=
true
;
this
.
refs
.
hiddenBtn
.
click
();
}
this
.
getSignature
(
cutImageBlob
);
}
}
>
确定
</
Button
>,
]
}
>
<
div
className=
'clip-box'
>
<
div
id=
'headPicModal'
ref=
'headPicModal'
style=
{
{
width
:
'500px'
,
height
:
'430px'
,
marginBottom
:
0
,
}
}
></
div
>
<
div
id=
'clipBtn'
style=
{
{
display
:
'none'
}
}
ref=
'hiddenBtn'
></
div
>
<
div
className=
'preview-img'
>
<
div
className=
'title'
>
效果预览
</
div
>
<
div
id=
'preview-url-box'
style=
{
{
width
:
500
,
height
:
282
}
}
>
<
img
src=
{
this
.
state
.
dataUrl
}
style=
{
{
width
:
'100%'
}
}
alt=
''
/>
</
div
>
<
div
className=
'tip-box'
>
<
div
className=
'tip'
>
温馨提示
</
div
>
<
div
className=
'tip'
>
①预览效果图时可能存在延迟,单击左侧图片刷新即可
</
div
>
<
div
className=
'tip'
>
②设置图片时双击可旋转图片,滚动可放大或缩小图片
</
div
>
</
div
>
</
div
>
</
Modal
>
</
div
>
</
Modal
>
</
div
>
);
}
}
export
default
withRouter
(
BasicInfo
)
export
default
withRouter
(
BasicInfo
)
;
src/modules/plan-manage/components/EmployeeShareData.jsx
View file @
1402a09b
...
...
@@ -134,6 +134,7 @@ class EmployeeShareData extends React.Component {
)
}
},
//产品暂时性隐藏
// {
// title: '手机号',
// key: 'storeUserPhone',
...
...
src/modules/plan-manage/components/PlanList.jsx
View file @
1402a09b
/*
* @Author: zhangleyuan
* @Date: 2021-02-20 16:46:46
* @LastEditors:
wufan
* @LastEditTime: 2021-0
5-14 18:12:50
* @LastEditors:
fusanqiasng
* @LastEditTime: 2021-0
6-01 11:45:34
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
,
{
useState
,
useRef
,
useEffect
}
from
'react'
;
import
{
Table
,
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
'antd'
;
import
React
,
{
useState
}
from
'react'
;
import
{
Table
,
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
'antd'
;
import
{
withRouter
}
from
'react-router-dom'
;
import
{
PageControl
}
from
"@/components"
;
import
PlanService
from
"@/domains/plan-domain/planService"
;
import
{
PageControl
}
from
'@/components'
;
import
PlanService
from
'@/domains/plan-domain/planService'
;
import
SharePlanModal
from
'../modal/SharePlanModal'
;
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
User
from
'@/common/js/user'
;
import
'./PlanList.less'
;
const
{
confirm
}
=
Modal
;
const
userRole
=
User
.
getUserRole
();
function
PlanList
(
props
)
{
const
[
sharePlanModal
,
setSharePlanModal
]
=
useState
(
null
);
function
parseColumns
(){
const
columns
=
[
{
title
:
'培训计划'
,
key
:
'planName'
,
dataIndex
:
'planName'
,
width
:
'18%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"plan-name"
>
{
val
}
</
div
>
)
}
},
{
title
:
'课程总数量'
,
key
:
'courseNum'
,
dataIndex
:
'courseNum'
,
width
:
110
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"course-number"
>
{
val
}
</
div
>
)
}
},
{
title
:
'当前状态'
,
width
:
'10%'
,
dataIndex
:
"status"
,
render
:
(
val
,
item
,
index
)
=>
{
return
(
<
Switch
checked=
{
item
.
enableState
===
"NO"
?
false
:
true
}
onChange=
{
()
=>
changeEnableState
(
item
)
}
disabled=
{
(
User
.
getUserRole
()
===
"CloudManager"
||
User
.
getUserRole
()
===
"StoreManager"
)?
false
:
true
}
/>
)
},
},
{
title
:
'创建人'
,
key
:
'createName'
,
dataIndex
:
'createName'
,
width
:
'10%'
,
render
:
(
val
)
=>
{
return
(
<
div
className=
"create-name"
>
{
val
}
</
div
>
)
}
},
{
title
:
'创建时间'
,
width
:
"12.5%"
,
key
:
'created'
,
dataIndex
:
'created'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
},
{
title
:
'更新时间'
,
width
:
"10%"
,
key
:
'updated'
,
dataIndex
:
'updated'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
},
{
title
:
'参培人数'
,
width
:
76
,
key
:
'cultureCustomerNum'
,
dataIndex
:
'cultureCustomerNum'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
(
<
div
className=
"join-number"
>
{
val
}
</
div
>
)
}
},
{
title
:
'操作'
,
key
:
'operate'
,
dataIndex
:
'operate'
,
fixed
:
'right'
,
width
:
176
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"operate"
>
<
div
className=
"operate__item"
onClick=
{
()
=>
toLearningDataPage
(
record
)
}
>
学习数据
</
div
>
{
record
.
enableState
===
"YES"
&&
<>
<
span
className=
"operate__item split"
>
|
</
span
>
<
div
className=
"operate__item"
onClick=
{
()
=>
{
handleShowShareModal
(
record
);
}
}
>
分享
</
div
>
</>
}
{
(
User
.
getUserRole
()
===
"CloudManager"
||
User
.
getUserRole
()
===
"StoreManager"
)
&&
<>
<
span
className=
"operate__item split"
>
|
</
span
>
<
Dropdown
overlay=
{
renderMoreOperate
(
record
)
}
>
<
span
className=
"more-operate"
>
<
span
className=
"operate-text"
>
更多
</
span
>
<
span
className=
"iconfont icon"
style=
{
{
color
:
"#2966FF"
}
}
>

</
span
>
</
span
>
</
Dropdown
>
</>
}
</
div
>
)
}
}
];
return
columns
;
}
function
renderMoreOperate
(
item
){
return
(
<
div
className=
"live-course-more-menu"
>
<
div
className=
"operate__item"
onClick=
{
()
=>
toEditPlanPage
(
item
)
}
>
编辑
</
div
>
<
div
className=
"operate__item"
onClick=
{
()
=>
handleDelete
(
item
)
}
>
删除
</
div
>
const
[
sharePlanModal
,
setSharePlanModal
]
=
useState
(
null
);
function
parseColumns
()
{
const
columns
=
[
{
title
:
'培训计划'
,
key
:
'planName'
,
dataIndex
:
'planName'
,
width
:
'18%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
'plan_name_item'
>
<
img
className=
'plan-cover'
src=
{
record
.
coverUrl
||
'https://image.xiaomaiketang.com/xm/rEAetaTEh3.png'
}
alt=
''
/>
<
Choose
>
<
When
condition=
{
record
.
planName
.
length
>
25
}
>
<
Tooltip
title=
{
record
.
planName
}
>
<
div
className=
'plan-name'
>
{
val
}
</
div
>
</
Tooltip
>
</
When
>
<
Otherwise
>
<
div
className=
'plan-name'
>
{
val
}
</
div
>
</
Otherwise
>
</
Choose
>
</
div
>
)
}
function
handleChangeTable
(
pagination
,
filters
,
sorter
){
const
{
columnKey
,
order
}
=
sorter
;
const
{
query
}
=
props
;
let
_columnKey
;
let
_order
;
);
},
},
{
title
:
'课程总数量'
,
key
:
'courseNum'
,
dataIndex
:
'courseNum'
,
width
:
110
,
render
:
(
val
,
record
)
=>
{
return
<
div
className=
'course-number'
>
{
val
}
</
div
>;
},
},
{
title
:
'当前状态'
,
width
:
'10%'
,
dataIndex
:
'status'
,
render
:
(
val
,
item
,
index
)
=>
{
return
(
<
Switch
checked=
{
item
.
enableState
===
'NO'
?
false
:
true
}
onChange=
{
()
=>
changeEnableState
(
item
)
}
disabled=
{
User
.
getUserRole
()
===
'CloudManager'
||
User
.
getUserRole
()
===
'StoreManager'
?
false
:
true
}
/>
);
},
},
{
title
:
'创建人'
,
key
:
'createName'
,
dataIndex
:
'createName'
,
width
:
'10%'
,
render
:
(
val
)
=>
{
return
<
div
className=
'create-name'
>
{
val
}
</
div
>;
},
},
{
title
:
'创建时间'
,
width
:
'12.5%'
,
key
:
'created'
,
dataIndex
:
'created'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
);
},
},
{
title
:
'更新时间'
,
width
:
'10%'
,
key
:
'updated'
,
dataIndex
:
'updated'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
);
},
},
{
title
:
'参培人数'
,
width
:
76
,
key
:
'cultureCustomerNum'
,
dataIndex
:
'cultureCustomerNum'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
<
div
className=
'join-number'
>
{
val
}
</
div
>;
},
},
{
title
:
'操作'
,
key
:
'operate'
,
dataIndex
:
'operate'
,
fixed
:
'right'
,
width
:
176
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
'operate'
>
<
div
className=
'operate__item'
onClick=
{
()
=>
toLearningDataPage
(
record
)
}
>
学习数据
</
div
>
{
record
.
enableState
===
'YES'
&&
(
<>
<
span
className=
'operate__item split'
>
|
</
span
>
<
div
className=
'operate__item'
onClick=
{
()
=>
{
handleShowShareModal
(
record
);
}
}
>
分享
</
div
>
</>
)
}
{
(
User
.
getUserRole
()
===
'CloudManager'
||
User
.
getUserRole
()
===
'StoreManager'
)
&&
(
<>
<
span
className=
'operate__item split'
>
|
</
span
>
<
Dropdown
overlay=
{
renderMoreOperate
(
record
)
}
>
<
span
className=
'more-operate'
>
<
span
className=
'operate-text'
>
更多
</
span
>
<
span
className=
'iconfont icon'
style=
{
{
color
:
'#2966FF'
}
}
>

</
span
>
</
span
>
</
Dropdown
>
</>
)
}
</
div
>
);
},
},
];
return
columns
;
}
function
renderMoreOperate
(
item
)
{
return
(
<
div
className=
'live-course-more-menu'
>
<
div
className=
'operate__item'
onClick=
{
()
=>
toEditPlanPage
(
item
)
}
>
编辑
</
div
>
<
div
className=
'operate__item'
onClick=
{
()
=>
handleDelete
(
item
)
}
>
删除
</
div
>
</
div
>
);
}
// 按创建时间升序排序
if
(
columnKey
===
'created'
&&
order
===
'ascend'
)
{
_columnKey
=
"CREATED"
;
_order
=
'SORT_ASC'
;
}
// 按创建时间降序排序
if
(
columnKey
===
'created'
&&
order
===
'descend'
)
{
_columnKey
=
"CREATED"
;
_order
=
'SORT_DESC'
;}
// 按更新时间升序排序
if
(
columnKey
===
'updated'
&&
order
===
'ascend'
)
{
_columnKey
=
"UPDATED"
;
_order
=
'SORT_ASC'
;
}
// 按更新时间降序排序
if
(
columnKey
===
'updated'
&&
order
===
'descend'
)
{
_columnKey
=
"UPDATED"
;
_order
=
'SORT_DESC'
;
}
// 按更新时间升序排序
if
(
columnKey
===
'cultureCustomerNum'
&&
order
===
'ascend'
)
{
_columnKey
=
"CUSTOMER_NUM"
;
_order
=
'SORT_ASC'
;
}
// 按更新时间降序排序
if
(
columnKey
===
'cultureCustomerNum'
&&
order
===
'descend'
)
{
_columnKey
=
"CUSTOMER_NUM"
;
_order
=
'SORT_DESC'
;
}
const
_query
=
{
...
query
,
sortMap
:{}
};
_query
.
sortMap
[
_columnKey
]
=
_order
;
props
.
onChange
(
_query
);
function
handleChangeTable
(
pagination
,
filters
,
sorter
)
{
const
{
columnKey
,
order
}
=
sorter
;
const
{
query
}
=
props
;
let
_columnKey
;
let
_order
;
// 按创建时间升序排序
if
(
columnKey
===
'created'
&&
order
===
'ascend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_ASC'
;
}
// 显示分享弹窗
function
handleShowShareModal
(
item
)
{
const
htmlUrl
=
`
${
LIVE_SHARE
}
training_plan_detail/
${
item
.
planId
}
?id=
${
User
.
getStoreId
()}
&storeUserId=
${
User
.
getStoreUserId
()}
`
;
const
longUrl
=
htmlUrl
const
shareData
=
{
...
item
,
longUrl
};
const
sharePlanModal
=
(
<
SharePlanModal
data=
{
shareData
}
type=
"liveClass"
close=
{
()
=>
{
setSharePlanModal
(
null
)
}
}
/>
)
setSharePlanModal
(
sharePlanModal
)
// 按创建时间降序排序
if
(
columnKey
===
'created'
&&
order
===
'descend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_DESC'
;
}
//改变上架状态
function
changeEnableState
(
item
){
let
_enableState
=
item
.
enableState
if
(
_enableState
===
'NO'
){
_enableState
=
"YES"
;
item
.
enableState
=
"YES"
}
else
{
_enableState
=
"NO"
item
.
enableState
=
"NO"
}
const
params
=
{
"planId"
:
item
.
planId
,
"enableState"
:
_enableState
}
PlanService
.
updateStateTrainingPlan
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
){
if
(
_enableState
===
"YES"
){
message
.
success
(
"已启用此计划"
);
}
else
{
message
.
success
(
"已禁用此计划"
);
}
props
.
onChange
();
}
})
}
function
toEditPlanPage
(
item
){
window
.
RCHistory
.
push
({
pathname
:
`/create-plan?type=edit&id=
${
item
.
planId
}
`
,
})
// 按更新时间升序排序
if
(
columnKey
===
'updated'
&&
order
===
'ascend'
)
{
_columnKey
=
'UPDATED'
;
_order
=
'SORT_ASC'
;
}
function
toLearningDataPage
(
item
){
window
.
RCHistory
.
push
(
{
pathname
:
`/learning-data?id=
${
item
.
planId
}
`
,
})
// 按更新时间降序排序
if
(
columnKey
===
'updated'
&&
order
===
'descend'
)
{
_columnKey
=
'UPDATED'
;
_order
=
'SORT_DESC'
;
}
function
handleDelete
(
record
){
return
confirm
({
title
:
'你确定要删除吗?'
,
content
:
'删除后,此培训计划的学员将无法继续学习,所有学习数据将同步删除不可恢复'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
okText
:
'删除'
,
okType
:
'danger'
,
cancelText
:
'取消'
,
width
:
440
,
height
:
188
,
onOk
:
()
=>
{
if
(
record
.
enableState
===
"YES"
){
Modal
.
warning
({
title
:
'无法删除'
,
content
:
'培训计划启用中,无法直接删除'
,
});
}
else
{
deleteConfirm
(
record
);
}
}
})
// 按更新时间升序排序
if
(
columnKey
===
'cultureCustomerNum'
&&
order
===
'ascend'
)
{
_columnKey
=
'CUSTOMER_NUM'
;
_order
=
'SORT_ASC'
;
}
function
deleteConfirm
(
item
){
const
params
=
{
"planId"
:
item
.
planId
,
}
PlanService
.
deleteTrainingPlan
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
){
message
.
success
(
"删除成功"
);
props
.
onChange
();
}
})
// 按更新时间降序排序
if
(
columnKey
===
'cultureCustomerNum'
&&
order
===
'descend'
)
{
_columnKey
=
'CUSTOMER_NUM'
;
_order
=
'SORT_DESC'
;
}
const
_query
=
{
...
query
,
sortMap
:
{},
};
_query
.
sortMap
[
_columnKey
]
=
_order
;
props
.
onChange
(
_query
);
}
// 显示分享弹窗
function
handleShowShareModal
(
item
)
{
const
htmlUrl
=
`
${
LIVE_SHARE
}
training_plan_detail/
${
item
.
planId
}
?id=
${
User
.
getStoreId
()}
&storeUserId=
${
User
.
getStoreUserId
()}
`
;
const
longUrl
=
htmlUrl
;
const
shareData
=
{
...
item
,
longUrl
};
const
sharePlanModal
=
(
<
SharePlanModal
data=
{
shareData
}
type=
'liveClass'
close=
{
()
=>
{
setSharePlanModal
(
null
);
}
}
/>
);
setSharePlanModal
(
sharePlanModal
);
}
//改变上架状态
function
changeEnableState
(
item
)
{
let
_enableState
=
item
.
enableState
;
if
(
_enableState
===
'NO'
)
{
_enableState
=
'YES'
;
item
.
enableState
=
'YES'
;
}
else
{
_enableState
=
'NO'
;
item
.
enableState
=
'NO'
;
}
function
onShowSizeChange
(
current
,
size
){
if
(
current
===
size
)
{
return
const
params
=
{
planId
:
item
.
planId
,
enableState
:
_enableState
,
};
PlanService
.
updateStateTrainingPlan
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
if
(
_enableState
===
'YES'
)
{
message
.
success
(
'已启用此计划'
);
}
else
{
message
.
success
(
'已禁用此计划'
);
}
props
.
onChange
();
}
});
}
function
toEditPlanPage
(
item
)
{
window
.
RCHistory
.
push
({
pathname
:
`/create-plan?type=edit&id=
${
item
.
planId
}
`
,
});
}
function
toLearningDataPage
(
item
)
{
window
.
RCHistory
.
push
({
pathname
:
`/learning-data?id=
${
item
.
planId
}
`
,
});
}
function
handleDelete
(
record
)
{
return
confirm
({
title
:
'你确定要删除吗?'
,
content
:
'删除后,此培训计划的学员将无法继续学习,所有学习数据将同步删除不可恢复'
,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
okText
:
'删除'
,
okType
:
'danger'
,
cancelText
:
'取消'
,
width
:
440
,
height
:
188
,
onOk
:
()
=>
{
if
(
record
.
enableState
===
'YES'
)
{
Modal
.
warning
({
title
:
'无法删除'
,
content
:
'培训计划启用中,无法直接删除'
,
});
}
else
{
deleteConfirm
(
record
);
}
let
_query
=
props
.
query
_query
.
size
=
size
;
props
.
onChange
(
_query
)
},
});
}
function
deleteConfirm
(
item
)
{
const
params
=
{
planId
:
item
.
planId
,
};
PlanService
.
deleteTrainingPlan
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
'删除成功'
);
props
.
onChange
();
}
});
}
function
onShowSizeChange
(
current
,
size
)
{
if
(
current
===
size
)
{
return
;
}
return
(
<
div
className=
"plan-list"
>
<
Table
rowKey=
{
record
=>
record
.
id
}
showSorterTooltip=
{
false
}
dataSource=
{
props
.
planListData
}
columns=
{
parseColumns
()
}
pagination=
{
false
}
onChange=
{
handleChangeTable
}
bordered
size=
"middle"
scroll=
{
{
x
:
1400
}
}
className=
"plan-list-table"
/>
<
div
className=
"box-footer"
>
<
PageControl
current=
{
props
.
query
.
current
-
1
}
pageSize=
{
props
.
query
.
size
}
total=
{
props
.
totalCount
}
toPage=
{
(
page
)
=>
{
const
_query
=
{...
props
.
query
,
current
:
page
+
1
};
props
.
onChange
(
_query
)
}
}
onShowSizeChange=
{
onShowSizeChange
}
/>
</
div
>
{
sharePlanModal
}
</
div
>
)
let
_query
=
props
.
query
;
_query
.
size
=
size
;
props
.
onChange
(
_query
);
}
export
default
withRouter
(
PlanList
);
\ No newline at end of file
return
(
<
div
className=
'plan-list'
>
<
Table
rowKey=
{
(
record
)
=>
record
.
id
}
showSorterTooltip=
{
false
}
dataSource=
{
props
.
planListData
}
columns=
{
parseColumns
()
}
pagination=
{
false
}
onChange=
{
handleChangeTable
}
bordered
size=
'middle'
scroll=
{
{
x
:
1400
}
}
className=
'plan-list-table'
/>
<
div
className=
'box-footer'
>
<
PageControl
current=
{
props
.
query
.
current
-
1
}
pageSize=
{
props
.
query
.
size
}
total=
{
props
.
totalCount
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
props
.
query
,
current
:
page
+
1
};
props
.
onChange
(
_query
);
}
}
onShowSizeChange=
{
onShowSizeChange
}
/>
</
div
>
{
sharePlanModal
}
</
div
>
);
}
export
default
withRouter
(
PlanList
);
src/modules/plan-manage/components/PlanList.less
View file @
1402a09b
.plan-list{
margin-top:12px;
.course-number{
text-align:right;
margin-right:45px;
.plan-list {
margin-top: 12px;
.course-number {
text-align: right;
margin-right: 45px;
}
.plan-list-table {
thead.ant-table-thead {
tr {
th {
padding: 10px 12px;
}
}
}
.plan-list-table{
tbody {
tr{
&:nth-child(even){
background: transparent !important;
td{
background:#FFF !important;
}
tbody {
tr {
td.ant-table-cell {
padding: 16px 12px;
color: #333;
}
&:nth-child(even) {
background: transparent;
td {
background: #fff;
}
&:nth-child(odd){
background: #FAFAFA !important;
td{
background: #FAFAFA !important;
}
}
&:nth-child(odd) {
background: #fafafa;
td {
background: #fafafa;
}
&:hover{
td
{
background:#F3f6fa !important;
}
}
&:hover
{
td {
background: #f3f6fa;
}
}
}
}
.plan-name{
text-overflow: -o-ellipsis-lastline;
}
.plan_name_item {
display: flex;
align-items: center;
.plan-cover {
width: 106px;
height: 60px;
border-radius: 2px;
margin-right: 8px;
}
.plan-name {
width: 188px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
height: 40px;
}
.operate-text {
color: #2966FF;
}
.operate-text {
color: #2966ff;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #2966ff;
cursor: pointer;
}
.operate {
display: flex;
&__item {
color: #2966FF;
cursor: pointer;
&.split {
margin: 0 8px;
color: #BFBFBF;
}
&.split {
margin: 0 8px;
color: #bfbfbf;
}
}
.join-number{
text-align:right;
margin-right:12px;
}
.more-operate{
line-height:20px;
}
}
\ No newline at end of file
}
.join-number {
text-align: right;
margin-right: 12px;
}
.more-operate {
line-height: 20px;
}
}
src/modules/plan-manage/modal/relatedCourseModal.jsx
View file @
1402a09b
import
React
from
"react"
import
_
from
"underscore"
import
{
Table
,
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
"antd"
import
React
from
'react'
;
import
_
from
'underscore'
;
import
{
Table
,
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
'antd'
;
import
{
PageControl
}
from
"@/components"
import
{
PageControl
}
from
'@/components'
;
import
CourseService
from
"@/domains/course-domain/CourseService"
import
User
from
"@/common/js/user"
import
Service
from
"@/common/js/service"
import
dealTimeDuration
from
"../../course-manage/utils/dealTimeDuration"
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
User
from
'@/common/js/user'
;
import
Service
from
'@/common/js/service'
;
import
dealTimeDuration
from
'../../course-manage/utils/dealTimeDuration'
;
import
"./relatedCourseModal.less"
import
'./relatedCourseModal.less'
;
const
{
Search
}
=
Input
const
{
TabPane
}
=
Tabs
const
{
Search
}
=
Input
;
const
{
TabPane
}
=
Tabs
;
const
courseStateShow
=
{
UN_START
:
{
code
:
1
,
title
:
"待开课"
,
color
:
"#FFB129"
title
:
'待开课'
,
color
:
'#FFB129'
,
},
STARTING
:
{
code
:
2
,
title
:
"上课中"
,
color
:
"#238FFF"
title
:
'上课中'
,
color
:
'#238FFF'
,
},
FINISH
:
{
code
:
3
,
title
:
"已完成"
,
color
:
"#3BBDAA"
title
:
'已完成'
,
color
:
'#3BBDAA'
,
},
EXPIRED
:
{
code
:
4
,
title
:
"未成功开课"
,
color
:
"#999"
}
}
title
:
'未成功开课'
,
color
:
'#999'
,
}
,
}
;
class
SelectOperatorModal
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
liveDataSource
:
[],
liveSize
:
10
,
liveQuery
:
{
current
:
1
current
:
1
,
},
liveTotalCount
:
0
,
selectLive
:
[],
//弹窗内已选择的直播课程
currentCourseListData
:
[],
currentLiveCourseListData
:
[],
//页面中已关联的直播课程
videoCourseDivision
:
"internal"
,
videoCourseDivision
:
'internal'
,
videoDataSource
:
{
external
:
[],
internal
:
[]
internal
:
[]
,
},
videoSize
:
{
external
:
10
,
internal
:
10
internal
:
10
,
},
videoSearchName
:
{
external
:
""
,
internal
:
""
external
:
''
,
internal
:
''
,
},
videoSearchDefalt
:
""
,
videoSearchDefalt
:
''
,
videoQuery
:
{
external
:
{
current
:
1
current
:
1
,
},
internal
:
{
current
:
1
}
current
:
1
,
}
,
},
videoTotalCount
:
{
external
:
0
,
internal
:
0
internal
:
0
,
},
selectVideo
:
{
external
:
[],
internal
:
[]
internal
:
[]
,
},
//弹窗内已选择的视频课程
currentVideoCourseListData
:
{
external
:
[],
internal
:
[]
internal
:
[]
,
},
//页面中已关联的视频课程
pictureDataSource
:
[],
pictureSize
:
10
,
pictureQuery
:
{
current
:
1
current
:
1
,
},
pictureTotalCount
:
0
,
selectPicture
:
[],
//弹窗内已选择的视频课程
currentPictureCourseListData
:
[],
//页面中已关联的视频课程
activeKey
:
"video"
,
currentTaskCourseData
:
this
.
props
.
data
[
this
.
props
.
selectedTaskIndex
].
courseList
||
[]
}
activeKey
:
'video'
,
currentTaskCourseData
:
this
.
props
.
data
[
this
.
props
.
selectedTaskIndex
].
courseList
||
[]
,
}
;
}
componentDidMount
()
{
this
.
handleFetchLiveDataList
()
this
.
handleFetchVideoDataList
()
this
.
handleFetchPictureDataList
()
this
.
handleFetchLiveDataList
()
;
this
.
handleFetchVideoDataList
()
;
this
.
handleFetchPictureDataList
()
;
}
// 获取直播课列表
handleFetchLiveDataList
=
()
=>
{
const
{
liveQuery
,
liveSize
}
=
this
.
state
const
_data
=
[...
this
.
props
.
data
]
let
currentLiveCourseListData
=
[]
const
{
liveQuery
,
liveSize
}
=
this
.
state
;
const
_data
=
[...
this
.
props
.
data
]
;
let
currentLiveCourseListData
=
[]
;
_data
.
map
((
item
)
=>
{
item
.
courseList
.
map
((
childItem
,
childIndex
)
=>
{
if
(
childItem
.
courseType
===
"LIVE"
)
{
currentLiveCourseListData
.
push
(
childItem
.
courseId
)
if
(
childItem
.
courseType
===
'LIVE'
)
{
currentLiveCourseListData
.
push
(
childItem
.
courseId
)
;
}
return
childItem
})
return
item
})
return
childItem
;
})
;
return
item
;
})
;
const
params
=
{
...
liveQuery
,
size
:
liveSize
,
excludeCourseIdList
:
currentLiveCourseListData
}
excludeCourseIdList
:
currentLiveCourseListData
,
}
;
CourseService
.
getLiveCloudCourseBasePage
(
params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
const
{
records
=
[],
total
=
0
}
=
result
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
liveDataSource
:
records
,
liveTotalCount
:
Number
(
total
),
currentLiveCourseListData
})
})
}
currentLiveCourseListData
,
})
;
})
;
}
;
// 获取视频课列表
handleFetchVideoDataList
=
()
=>
{
const
{
videoQuery
,
videoSize
,
videoDataSource
,
videoTotalCount
,
videoCourseDivision
}
=
this
.
state
const
{
videoQuery
,
videoSize
,
videoDataSource
,
videoTotalCount
,
videoCourseDivision
}
=
this
.
state
;
const
_data
=
[...
this
.
props
.
data
]
let
currentVideoCourseListData
=
[]
const
_data
=
[...
this
.
props
.
data
]
;
let
currentVideoCourseListData
=
[]
;
_data
.
map
((
item
,
index
)
=>
{
item
.
courseList
.
map
((
childItem
,
childIndex
)
=>
{
if
(
childItem
.
courseType
===
"VOICE"
)
{
currentVideoCourseListData
.
push
(
childItem
.
courseId
)
if
(
childItem
.
courseType
===
'VOICE'
)
{
currentVideoCourseListData
.
push
(
childItem
.
courseId
)
;
}
return
childItem
})
return
item
})
return
childItem
;
})
;
return
item
;
})
;
const
params
=
{
...
videoQuery
[
videoCourseDivision
],
size
:
videoSize
[
videoCourseDivision
],
courseDivision
:
videoCourseDivision
===
"internal"
?
"INTERNAL"
:
"EXTERNAL"
,
excludeCourseIdList
:
currentVideoCourseListData
}
courseDivision
:
videoCourseDivision
===
'internal'
?
'INTERNAL'
:
'EXTERNAL'
,
excludeCourseIdList
:
currentVideoCourseListData
,
}
;
CourseService
.
videoScheduleBasePage
(
params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
console
.
log
(
"result"
,
result
)
const
{
result
=
{}
}
=
res
;
console
.
log
(
'result'
,
result
);
const
{
records
=
[],
total
=
0
}
=
result
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
videoDataSource
:
{
...
videoDataSource
,
[
videoCourseDivision
]:
records
[
videoCourseDivision
]:
records
,
},
videoTotalCount
:
{
...
videoTotalCount
,
[
videoCourseDivision
]:
Number
(
total
)
[
videoCourseDivision
]:
Number
(
total
)
,
},
currentVideoCourseListData
})
})
}
currentVideoCourseListData
,
})
;
})
;
}
;
// 获取图文课列表
handleFetchPictureDataList
=
()
=>
{
const
{
pictureQuery
,
pictureSize
}
=
this
.
state
const
_data
=
[...
this
.
props
.
data
]
let
currentPictureCourseListData
=
[]
const
{
pictureQuery
,
pictureSize
}
=
this
.
state
;
const
_data
=
[...
this
.
props
.
data
]
;
let
currentPictureCourseListData
=
[]
;
_data
.
map
((
item
,
index
)
=>
{
item
.
courseList
.
map
((
childItem
,
childIndex
)
=>
{
if
(
childItem
.
courseType
===
"PICTURE"
)
{
currentPictureCourseListData
.
push
(
childItem
.
courseId
)
if
(
childItem
.
courseType
===
'PICTURE'
)
{
currentPictureCourseListData
.
push
(
childItem
.
courseId
)
;
}
return
childItem
})
return
item
})
return
childItem
;
})
;
return
item
;
})
;
const
params
=
{
...
pictureQuery
,
size
:
pictureSize
,
courseType
:
"PICTURE"
,
courseType
:
'PICTURE'
,
storeId
:
User
.
getStoreId
(),
excludeCourseIdList
:
currentPictureCourseListData
}
excludeCourseIdList
:
currentPictureCourseListData
,
}
;
Service
.
Hades
(
"public/hades/mediaCoursePage"
,
params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
const
{
records
=
[],
total
=
0
}
=
result
Service
.
Hades
(
'public/hades/mediaCoursePage'
,
params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
pictureDataSource
:
records
,
pictureTotalCount
:
Number
(
total
),
currentPictureCourseListData
})
})
}
currentPictureCourseListData
,
})
;
})
;
}
;
handleChangVideoCourseName
=
(
value
)
=>
{
const
{
videoQuery
,
videoCourseDivision
,
videoSearchName
}
=
this
.
state
videoQuery
[
videoCourseDivision
].
courseName
=
value
videoQuery
[
videoCourseDivision
].
current
=
1
const
{
videoQuery
,
videoCourseDivision
,
videoSearchName
}
=
this
.
state
;
videoQuery
[
videoCourseDivision
].
courseName
=
value
;
videoQuery
[
videoCourseDivision
].
current
=
1
;
this
.
setState
({
...
videoQuery
,
videoSearchDefalt
:
value
,
videoSearchName
:
{
...
videoSearchName
,
[
videoCourseDivision
]:
value
}
})
}
[
videoCourseDivision
]:
value
,
}
,
})
;
}
;
handleChangLiveCourseName
=
(
value
)
=>
{
const
{
liveQuery
}
=
this
.
state
liveQuery
.
courseName
=
value
liveQuery
.
current
=
1
const
{
liveQuery
}
=
this
.
state
;
liveQuery
.
courseName
=
value
;
liveQuery
.
current
=
1
;
this
.
setState
({
liveQuery
})
}
liveQuery
,
})
;
}
;
handleChangPictureCourseName
=
(
value
)
=>
{
const
{
pictureQuery
}
=
this
.
state
pictureQuery
.
courseName
=
value
pictureQuery
.
current
=
1
const
{
pictureQuery
}
=
this
.
state
;
pictureQuery
.
courseName
=
value
;
pictureQuery
.
current
=
1
;
this
.
setState
({
pictureQuery
})
}
pictureQuery
,
})
;
}
;
onShowLiveSizeChange
=
(
current
,
size
)
=>
{
if
(
current
===
size
)
{
return
return
;
}
this
.
setState
(
{
liveSize
:
size
liveSize
:
size
,
},
()
=>
{
this
.
handleFetchLiveDataList
()
this
.
handleFetchLiveDataList
()
;
}
)
}
)
;
}
;
onShowVideoSizeChange
=
(
current
,
size
)
=>
{
if
(
current
===
size
)
{
return
return
;
}
this
.
setState
(
{
videoSize
:
size
videoSize
:
size
,
},
()
=>
{
this
.
handleFetchLiveDataList
()
this
.
handleFetchLiveDataList
()
;
}
)
}
)
;
}
;
onShowPictureSizeChange
=
(
current
,
size
)
=>
{
if
(
current
===
size
)
{
return
return
;
}
this
.
setState
(
{
pictureSize
:
size
pictureSize
:
size
,
},
()
=>
{
this
.
handleFetchPictureDataList
()
this
.
handleFetchPictureDataList
()
;
}
)
}
)
;
}
;
// 请求表头
parseLiveColumns
=
()
=>
{
...
...
@@ -291,28 +291,28 @@ class SelectOperatorModal extends React.Component {
<
span
>
<
span
>
课程信息
</
span
>
<
Tooltip
title=
'仅显示未关联课程,已关联课程不支持重复选择'
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
"5px"
,
cursor
:
"pointer"
,
color
:
"#bfbfbf"
,
fontSize
:
"14px"
,
fontWeight
:
"400"
}
}
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
,
fontWeight
:
'400'
}
}
>

</
i
>
</
Tooltip
>
</
span
>
),
key
:
"course"
,
dataIndex
:
"course"
,
width
:
"40%"
,
key
:
'course'
,
dataIndex
:
'course'
,
width
:
'40%'
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
let
hasCover
=
false
;
return
(
<
div
className=
'course-info'
>
{
record
.
courseMediaVOS
.
map
((
item
)
=>
{
if
(
item
.
contentType
===
"COVER"
)
{
hasCover
=
true
return
<
img
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
if
(
item
.
contentType
===
'COVER'
)
{
hasCover
=
true
;
return
<
img
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
;
}
return
null
return
null
;
})
}
<
If
condition=
{
!
hasCover
}
>
<
img
className=
'course-cover'
src=
{
"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"
}
alt=
''
/>
<
img
className=
'course-cover'
src=
{
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
}
alt=
''
/>
</
If
>
<
div
>
...
...
@@ -324,35 +324,35 @@ class SelectOperatorModal extends React.Component {
</
span
>
</
div
>
</
div
>
)
}
)
;
}
,
},
{
title
:
"上课时间"
,
key
:
"courseTime"
,
dataIndex
:
"courseTime"
,
width
:
"40%"
,
title
:
'上课时间'
,
key
:
'courseTime'
,
dataIndex
:
'courseTime'
,
width
:
'40%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
>
<
div
>
{
formatDate
(
"YYYY-MM-DD"
,
record
.
startTime
)
}
</
div
>
<
div
>
{
formatDate
(
'YYYY-MM-DD'
,
record
.
startTime
)
}
</
div
>
<
div
>
{
formatDate
(
"H:i"
,
record
.
startTime
)
}
~
{
formatDate
(
"H:i"
,
record
.
endTime
)
}
{
formatDate
(
'H:i'
,
record
.
startTime
)
}
~
{
formatDate
(
'H:i'
,
record
.
endTime
)
}
</
div
>
</
div
>
)
}
)
;
}
,
},
{
title
:
"学院展示"
,
key
:
"shelfState"
,
dataIndex
:
"shelfState"
,
width
:
"20%"
,
title
:
'学院展示'
,
key
:
'shelfState'
,
dataIndex
:
'shelfState'
,
width
:
'20%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
span
>
<
Choose
>
<
When
condition=
{
record
.
shelfState
===
"YES"
}
>
<
When
condition=
{
record
.
shelfState
===
'YES'
}
>
<
span
>
开启
</
span
>
</
When
>
<
Otherwise
>
...
...
@@ -360,33 +360,46 @@ class SelectOperatorModal extends React.Component {
</
Otherwise
>
</
Choose
>
</
span
>
)
}
}
]
return
columns
}
)
;
}
,
}
,
]
;
return
columns
;
}
;
// 请求表头
parseVideoColumns
=
()
=>
{
const
{
videoCourseDivision
}
=
this
.
state
const
{
videoCourseDivision
}
=
this
.
state
;
const
columns
=
[
{
title
:
(
<
span
>
<
span
>
课程信息
</
span
>
<
Tooltip
title=
'仅显示未关联课程,已关联课程不支持重复选择'
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
"5px"
,
cursor
:
"pointer"
,
color
:
"#bfbfbf"
,
fontSize
:
"14px"
,
fontWeight
:
"400"
}
}
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
,
fontWeight
:
'400'
}
}
>

</
i
>
</
Tooltip
>
</
span
>
),
key
:
"course"
,
dataIndex
:
"course"
,
width
:
"40%"
,
key
:
'course'
,
dataIndex
:
'course'
,
width
:
'40%'
,
title
:
(
<
span
>
<
span
>
课程信息
</
span
>
<
Tooltip
title=
'仅显示未关联课程,已关联课程不支持重复选择'
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
,
fontWeight
:
'400'
}
}
>

</
i
>
</
Tooltip
>
</
span
>
),
key
:
'course'
,
dataIndex
:
'course'
,
width
:
'60%'
,
render
:
(
val
,
record
)
=>
{
const
{
coverUrl
,
scheduleVideoUrl
}
=
record
const
{
coverUrl
,
scheduleVideoUrl
}
=
record
;
return
(
<
div
className=
'course-info'
>
{
/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */
}
...
...
@@ -394,48 +407,48 @@ class SelectOperatorModal extends React.Component {
className=
'course-cover'
src=
{
coverUrl
||
(
videoCourseDivision
===
"internal"
(
videoCourseDivision
===
'internal'
?
`${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast`
:
"https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png"
)
:
'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png'
)
}
alt=
''
/>
<
div
className=
'course-name'
>
{
record
.
courseName
}
</
div
>
</
div
>
)
}
)
;
}
,
},
{
title
:
"课程时长"
,
key
:
"courseTime"
,
dataIndex
:
"courseTime"
,
width
:
"20%"
,
title
:
'课程时长'
,
key
:
'courseTime'
,
dataIndex
:
'courseTime'
,
width
:
'20%'
,
render
:
(
val
,
record
)
=>
{
return
<
span
className=
'course-status'
>
{
dealTimeDuration
(
record
.
videoDuration
)
}
</
span
>
}
return
<
span
className=
'course-status'
>
{
dealTimeDuration
(
record
.
videoDuration
)
}
</
span
>
;
}
,
},
{
title
:
"学院展示"
,
key
:
"shelfState"
,
dataIndex
:
"shelfState"
,
width
:
"20%"
,
title
:
'学院展示'
,
key
:
'shelfState'
,
dataIndex
:
'shelfState'
,
width
:
'20%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
Choose
>
<
When
condition=
{
record
.
shelfState
===
"YES"
}
>
<
When
condition=
{
record
.
shelfState
===
'YES'
}
>
<
span
>
开启
</
span
>
</
When
>
<
Otherwise
>
<
span
>
关闭
</
span
>
</
Otherwise
>
</
Choose
>
)
}
}
]
return
columns
}
)
;
}
,
}
,
]
;
return
columns
;
}
;
// 请求表头
parsePictureColumns
=
()
=>
{
...
...
@@ -445,201 +458,201 @@ class SelectOperatorModal extends React.Component {
<
span
>
<
span
>
课程信息
</
span
>
<
Tooltip
title=
'仅显示未关联课程,已关联课程不支持重复选择'
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
"5px"
,
cursor
:
"pointer"
,
color
:
"#bfbfbf"
,
fontSize
:
"14px"
,
fontWeight
:
"400"
}
}
>
<
i
className=
'icon iconfont'
style=
{
{
marginLeft
:
'5px'
,
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
,
fontWeight
:
'400'
}
}
>

</
i
>
</
Tooltip
>
</
span
>
),
key
:
"course"
,
dataIndex
:
"course"
,
width
:
"55%"
,
key
:
'course'
,
dataIndex
:
'course'
,
width
:
'55%'
,
render
:
(
val
,
record
)
=>
{
const
{
coverUrl
}
=
record
const
{
coverUrl
}
=
record
;
return
(
<
div
className=
'course-info'
>
{
/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */
}
<
img
className=
'course-cover'
src=
{
coverUrl
||
"https://image.xiaomaiketang.com/xm/YNfi45JwFA.png"
}
alt=
''
/>
<
img
className=
'course-cover'
src=
{
coverUrl
||
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
}
alt=
''
/>
<
div
className=
'course-name'
>
{
record
.
courseName
}
</
div
>
</
div
>
)
}
)
;
}
,
},
{
title
:
"更新时间"
,
key
:
"updated"
,
dataIndex
:
"updated"
,
width
:
"25%"
,
title
:
'更新时间'
,
key
:
'updated'
,
dataIndex
:
'updated'
,
width
:
'25%'
,
render
:
(
val
,
record
)
=>
{
return
<
span
className=
'course-status'
>
{
formatDate
(
"YYYY-MM-DD"
,
record
.
updated
)
}
</
span
>
}
return
<
span
className=
'course-status'
>
{
formatDate
(
'YYYY-MM-DD'
,
record
.
updated
)
}
</
span
>;
}
,
},
{
title
:
"学院展示"
,
key
:
"shelfState"
,
dataIndex
:
"shelfState"
,
width
:
"20%"
,
title
:
'学院展示'
,
key
:
'shelfState'
,
dataIndex
:
'shelfState'
,
width
:
'20%'
,
render
:
(
val
,
record
)
=>
{
return
<
span
>
{
record
.
shelfState
===
"YES"
?
"开启"
:
"关闭"
}
</
span
>
}
}
]
return
columns
}
return
<
span
>
{
record
.
shelfState
===
'YES'
?
'开启'
:
'关闭'
}
</
span
>;
}
,
}
,
]
;
return
columns
;
}
;
selectLiveList
=
(
record
,
selected
)
=>
{
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
}
=
this
.
state
let
_list
=
[]
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
}
=
this
.
state
;
let
_list
=
[]
;
if
(
selected
||
!
_
.
find
(
selectLive
,
(
item
)
=>
item
.
liveCourseId
===
record
.
liveCourseId
))
{
_list
=
_
.
uniq
(
selectLive
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
liveCourseId
)
_list
=
_
.
uniq
(
selectLive
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
liveCourseId
)
;
}
else
{
_list
=
_
.
reject
(
selectLive
,
(
item
)
=>
item
.
liveCourseId
===
record
.
liveCourseId
)
_list
=
_
.
reject
(
selectLive
,
(
item
)
=>
item
.
liveCourseId
===
record
.
liveCourseId
)
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectPicture
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
return
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
return
;
}
this
.
setState
({
selectLive
:
_list
})
}
this
.
setState
({
selectLive
:
_list
})
;
}
;
selectVideoList
=
(
record
,
selected
)
=>
{
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
,
videoCourseDivision
}
=
this
.
state
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
,
videoCourseDivision
}
=
this
.
state
;
let
{
[
videoCourseDivision
]:
selectList
}
=
selectVideo
let
{
[
videoCourseDivision
]:
selectList
}
=
selectVideo
;
let
_list
=
[]
let
_list
=
[]
;
if
(
selected
||
!
_
.
find
(
selectList
,
(
item
)
=>
item
.
id
===
record
.
id
))
{
_list
=
_
.
uniq
(
selectList
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
id
)
_list
=
_
.
uniq
(
selectList
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
id
)
;
}
else
{
_list
=
_
.
reject
(
selectList
,
(
item
)
=>
item
.
id
===
record
.
id
)
_list
=
_
.
reject
(
selectList
,
(
item
)
=>
item
.
id
===
record
.
id
)
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectLive
.
length
+
selectPicture
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
return
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
return
;
}
this
.
setState
({
selectVideo
:
{
...
selectVideo
,
[
videoCourseDivision
]:
_list
}
})
}
[
videoCourseDivision
]:
_list
,
}
,
})
;
}
;
selectPictureList
=
(
record
,
selected
)
=>
{
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
}
=
this
.
state
let
_list
=
[]
const
{
selectVideo
,
currentTaskCourseData
,
selectLive
,
selectPicture
}
=
this
.
state
;
let
_list
=
[]
;
if
(
selected
||
!
_
.
find
(
selectPicture
,
(
item
)
=>
item
.
id
===
record
.
id
))
{
_list
=
_
.
uniq
(
selectPicture
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
id
)
_list
=
_
.
uniq
(
selectPicture
.
concat
([
record
]),
false
,
(
item
)
=>
item
.
id
)
;
}
else
{
_list
=
_
.
reject
(
selectPicture
,
(
item
)
=>
item
.
id
===
record
.
id
)
_list
=
_
.
reject
(
selectPicture
,
(
item
)
=>
item
.
id
===
record
.
id
)
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectLive
.
length
+
selectVideo
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
return
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
return
;
}
this
.
setState
({
selectPicture
:
_list
})
}
this
.
setState
({
selectPicture
:
_list
})
;
}
;
clearSelectCourse
=
()
=>
{
this
.
setState
({
selectLive
:
[],
selectVideo
:
{
internal
:
[],
external
:
[]
external
:
[]
,
},
selectPicture
:
[]
})
}
selectPicture
:
[]
,
})
;
}
;
handleSelectVideo
=
(
selectVideo
)
=>
{
return
selectVideo
.
map
((
item
)
=>
{
let
_item
=
{}
_item
.
courseId
=
item
.
id
_item
.
courseType
=
"VOICE"
_item
.
courseName
=
item
.
courseName
let
_item
=
{}
;
_item
.
courseId
=
item
.
id
;
_item
.
courseType
=
'VOICE'
;
_item
.
courseName
=
item
.
courseName
;
return
_item
})
}
return
_item
;
})
;
}
;
handleSelectLive
=
(
selectLive
)
=>
{
return
selectLive
.
map
((
item
,
index
)
=>
{
let
_item
=
{}
_item
.
courseId
=
item
.
liveCourseId
_item
.
courseType
=
"LIVE"
_item
.
courseName
=
item
.
courseName
_item
.
courseState
=
item
.
courseState
return
_item
})
}
let
_item
=
{}
;
_item
.
courseId
=
item
.
liveCourseId
;
_item
.
courseType
=
'LIVE'
;
_item
.
courseName
=
item
.
courseName
;
_item
.
courseState
=
item
.
courseState
;
return
_item
;
})
;
}
;
videoCourseDivisionChange
=
(
e
)
=>
{
const
{
videoSearchName
}
=
this
.
state
const
{
videoSearchName
}
=
this
.
state
;
this
.
setState
(
{
videoCourseDivision
:
e
.
target
.
value
,
videoSearchDefalt
:
videoSearchName
[
e
.
target
.
value
]
videoSearchDefalt
:
videoSearchName
[
e
.
target
.
value
]
,
},
()
=>
{
this
.
handleFetchVideoDataList
()
this
.
handleFetchVideoDataList
()
;
}
)
}
)
;
}
;
handleSelectPicture
=
(
selectPicture
)
=>
{
return
selectPicture
.
map
((
item
,
index
)
=>
{
let
_item
=
{}
_item
.
courseId
=
item
.
id
_item
.
courseType
=
"PICTURE"
_item
.
courseName
=
item
.
courseName
return
_item
})
}
let
_item
=
{}
;
_item
.
courseId
=
item
.
id
;
_item
.
courseType
=
'PICTURE'
;
_item
.
courseName
=
item
.
courseName
;
return
_item
;
})
;
}
;
renderFooter
=
()
=>
{
const
{
activeKey
}
=
this
.
state
let
href
=
""
const
{
activeKey
}
=
this
.
state
;
let
href
=
''
;
switch
(
activeKey
)
{
case
"live"
:
case
'live'
:
href
=
(
<
a
target=
'_blank'
rel=
'noopener noreferrer'
className=
'link-create-course'
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
"#/create-live-course?type=add"
}
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
'#/create-live-course?type=add'
}
onClick=
{
this
.
props
.
onClose
}
>
没有找到需要的直播课?
<
span
>
去创建
</
span
>
</
a
>
)
break
case
"video"
:
)
;
break
;
case
'video'
:
href
=
(
<
a
target=
'_blank'
rel=
'noopener noreferrer'
className=
'link-create-course'
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
"#/create-video-course?type=add"
}
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
'#/create-video-course?type=add'
}
onClick=
{
this
.
props
.
onClose
}
>
没有找到需要的视频课?
<
span
>
去创建
</
span
>
</
a
>
)
break
case
"picture"
:
)
;
break
;
case
'picture'
:
href
=
(
<
a
target=
'_blank'
rel=
'noopener noreferrer'
className=
'link-create-course'
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
"#/create-graphics-course?type=add"
}
href=
{
window
.
location
.
origin
+
window
.
location
.
pathname
+
'#/create-graphics-course?type=add'
}
onClick=
{
this
.
props
.
onClose
}
>
没有找到需要的图文课?
<
span
>
去创建
</
span
>
</
a
>
)
break
)
;
break
;
default
:
break
break
;
}
return
href
}
return
href
;
}
;
render
()
{
const
{
visible
}
=
this
.
props
const
{
visible
}
=
this
.
props
;
const
{
liveDataSource
,
liveSize
,
...
...
@@ -659,8 +672,8 @@ class SelectOperatorModal extends React.Component {
pictureQuery
,
pictureTotalCount
,
videoCourseDivision
}
=
this
.
state
videoCourseDivision
,
}
=
this
.
state
;
return
(
<
Modal
title=
'关联课程'
...
...
@@ -676,7 +689,7 @@ class SelectOperatorModal extends React.Component {
this.renderFooter(),
<
Button
onClick=
{
()
=>
{
this
.
props
.
onClose
()
this
.
props
.
onClose
()
;
}
}
>
取消
</
Button
>
,
...
...
@@ -687,18 +700,18 @@ class SelectOperatorModal extends React.Component {
...
this
.
handleSelectVideo
(
selectVideo
.
internal
),
...
this
.
handleSelectVideo
(
selectVideo
.
external
),
...
this
.
handleSelectLive
(
selectLive
),
...
this
.
handleSelectPicture
(
selectPicture
)
...
this
.
handleSelectPicture
(
selectPicture
)
,
])
}
>
确定
</
Button
>
</
Button
>
,
]
}
>
<
div
>
<
Tabs
type=
'line'
defaultActiveKey=
'live'
onChange=
{
(
activeKey
)
=>
{
this
.
setState
({
activeKey
:
activeKey
})
this
.
setState
({
activeKey
:
activeKey
})
;
}
}
>
<
TabPane
tab=
'直播课'
key=
'live'
>
<
div
className=
'search-container'
>
...
...
@@ -707,10 +720,10 @@ class SelectOperatorModal extends React.Component {
placeholder=
'搜索课程名称'
style=
{
{
width
:
200
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangLiveCourseName
(
e
.
target
.
value
)
this
.
handleChangLiveCourseName
(
e
.
target
.
value
)
;
}
}
onSearch=
{
()
=>
{
this
.
handleFetchLiveDataList
()
this
.
handleFetchLiveDataList
()
;
}
}
/>
</
div
>
...
...
@@ -741,25 +754,25 @@ class SelectOperatorModal extends React.Component {
pagination=
{
false
}
bordered
rowSelection=
{
{
type
:
"checkbox"
,
selectedRowKeys
:
_
.
pluck
(
selectLive
,
"liveCourseId"
),
type
:
'checkbox'
,
selectedRowKeys
:
_
.
pluck
(
selectLive
,
'liveCourseId'
),
onSelect
:
(
record
,
selected
)
=>
{
this
.
selectLiveList
(
record
,
selected
)
this
.
selectLiveList
(
record
,
selected
)
;
},
onSelectAll
:
(
selected
,
_selectedRows
,
changeRows
)
=>
{
let
_list
=
[]
let
_list
=
[]
;
if
(
selected
)
{
_list
=
_
.
uniq
(
selectLive
.
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
liveCourseId
)
_list
=
_
.
uniq
(
selectLive
.
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
liveCourseId
)
;
}
else
{
_list
=
_
.
reject
(
selectLive
,
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
liveCourseId
===
item
.
liveCourseId
))
_list
=
_
.
reject
(
selectLive
,
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
liveCourseId
===
item
.
liveCourseId
))
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectPicture
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectPicture
.
length
-
20
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectPicture
.
length
-
20
;
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
;
}
this
.
setState
({
selectLive
:
_list
})
}
this
.
setState
({
selectLive
:
_list
})
;
}
,
}
}
/>
{
liveDataSource
.
length
>
0
&&
(
...
...
@@ -770,15 +783,15 @@ class SelectOperatorModal extends React.Component {
size=
'small'
total=
{
liveTotalCount
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
liveQuery
,
current
:
page
+
1
}
const
_query
=
{
...
liveQuery
,
current
:
page
+
1
}
;
this
.
setState
(
{
liveQuery
:
_query
liveQuery
:
_query
,
},
()
=>
{
this
.
handleFetchLiveDataList
()
this
.
handleFetchLiveDataList
()
;
}
)
)
;
}
}
onShowSizeChange=
{
this
.
onShowLiveSizeChange
}
/>
...
...
@@ -799,10 +812,10 @@ class SelectOperatorModal extends React.Component {
placeholder=
'搜索课程名称'
style=
{
{
width
:
200
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangVideoCourseName
(
e
.
target
.
value
)
this
.
handleChangVideoCourseName
(
e
.
target
.
value
)
;
}
}
onSearch=
{
()
=>
{
this
.
handleFetchVideoDataList
()
this
.
handleFetchVideoDataList
()
;
}
}
/>
</
div
>
...
...
@@ -832,30 +845,30 @@ class SelectOperatorModal extends React.Component {
pagination=
{
false
}
bordered
rowSelection=
{
{
type
:
"checkbox"
,
selectedRowKeys
:
_
.
pluck
(
selectVideo
[
videoCourseDivision
],
"id"
),
type
:
'checkbox'
,
selectedRowKeys
:
_
.
pluck
(
selectVideo
[
videoCourseDivision
],
'id'
),
onSelect
:
(
record
,
selected
)
=>
{
this
.
selectVideoList
(
record
,
selected
)
this
.
selectVideoList
(
record
,
selected
)
;
},
onSelectAll
:
(
selected
,
_selectedRows
,
changeRows
)
=>
{
let
_list
=
[]
let
_list
=
[]
;
if
(
selected
)
{
_list
=
_
.
uniq
(
selectVideo
[
videoCourseDivision
].
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
id
)
_list
=
_
.
uniq
(
selectVideo
[
videoCourseDivision
].
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
id
)
;
}
else
{
_list
=
_
.
reject
(
selectVideo
[
videoCourseDivision
],
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
id
===
item
.
id
))
_list
=
_
.
reject
(
selectVideo
[
videoCourseDivision
],
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
id
===
item
.
id
))
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectLive
.
length
+
selectPicture
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectLive
.
length
+
selectPicture
.
length
-
20
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectLive
.
length
+
selectPicture
.
length
-
20
;
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
;
}
this
.
setState
({
selectVideo
:
{
...
selectVideo
,
[
videoCourseDivision
]:
_list
}
})
}
[
videoCourseDivision
]:
_list
,
}
,
})
;
}
,
}
}
/>
{
videoDataSource
[
videoCourseDivision
].
length
>
0
&&
(
...
...
@@ -866,19 +879,19 @@ class SelectOperatorModal extends React.Component {
size=
'small'
total=
{
videoTotalCount
[
videoCourseDivision
]
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
videoQuery
[
videoCourseDivision
],
current
:
page
+
1
}
const
_query
=
{
...
videoQuery
[
videoCourseDivision
],
current
:
page
+
1
}
;
this
.
setState
(
{
videoQuery
:
{
...
videoQuery
,
[
videoCourseDivision
]:
_query
}
[
videoCourseDivision
]:
_query
,
}
,
},
()
=>
{
this
.
handleFetchVideoDataList
()
this
.
handleFetchVideoDataList
()
;
}
)
)
;
}
}
onShowSizeChange=
{
this
.
onShowVideoSizeChange
}
/>
...
...
@@ -893,10 +906,10 @@ class SelectOperatorModal extends React.Component {
placeholder=
'搜索课程名称'
style=
{
{
width
:
200
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangPictureCourseName
(
e
.
target
.
value
)
this
.
handleChangPictureCourseName
(
e
.
target
.
value
)
;
}
}
onSearch=
{
()
=>
{
this
.
handleFetchPictureDataList
()
this
.
handleFetchPictureDataList
()
;
}
}
/>
</
div
>
...
...
@@ -927,25 +940,25 @@ class SelectOperatorModal extends React.Component {
pagination=
{
false
}
bordered
rowSelection=
{
{
type
:
"checkbox"
,
selectedRowKeys
:
_
.
pluck
(
selectPicture
,
"id"
),
type
:
'checkbox'
,
selectedRowKeys
:
_
.
pluck
(
selectPicture
,
'id'
),
onSelect
:
(
record
,
selected
)
=>
{
this
.
selectPictureList
(
record
,
selected
)
this
.
selectPictureList
(
record
,
selected
)
;
},
onSelectAll
:
(
selected
,
_selectedRows
,
changeRows
)
=>
{
let
_list
=
[]
let
_list
=
[]
;
if
(
selected
)
{
_list
=
_
.
uniq
(
selectPicture
.
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
id
)
_list
=
_
.
uniq
(
selectPicture
.
concat
(
changeRows
),
false
,
(
item
)
=>
item
.
id
)
;
}
else
{
_list
=
_
.
reject
(
selectPicture
,
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
id
===
item
.
id
))
_list
=
_
.
reject
(
selectPicture
,
(
item
)
=>
_
.
find
(
changeRows
,
(
data
)
=>
data
.
id
===
item
.
id
))
;
}
if
(
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectLive
.
length
>
20
)
{
message
.
warning
(
"无法继续选择,一个任务最多关联20个课程"
)
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectLive
.
length
-
20
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
message
.
warning
(
'无法继续选择,一个任务最多关联20个课程'
);
const
extraLength
=
_list
.
length
+
currentTaskCourseData
.
length
+
selectVideo
.
length
+
selectLive
.
length
-
20
;
_list
.
splice
(
_list
.
length
-
extraLength
,
extraLength
)
;
}
this
.
setState
({
selectPicture
:
_list
})
}
this
.
setState
({
selectPicture
:
_list
})
;
}
,
}
}
/>
{
pictureDataSource
.
length
>
0
&&
(
...
...
@@ -956,15 +969,15 @@ class SelectOperatorModal extends React.Component {
size=
'small'
total=
{
pictureTotalCount
}
toPage=
{
(
page
)
=>
{
const
_query
=
{
...
pictureQuery
,
current
:
page
+
1
}
const
_query
=
{
...
pictureQuery
,
current
:
page
+
1
}
;
this
.
setState
(
{
pictureQuery
:
_query
pictureQuery
:
_query
,
},
()
=>
{
this
.
handleFetchPictureDataList
()
this
.
handleFetchPictureDataList
()
;
}
)
)
;
}
}
onShowSizeChange=
{
this
.
onShowPictureSizeChange
}
/>
...
...
@@ -975,8 +988,8 @@ class SelectOperatorModal extends React.Component {
</
Tabs
>
</
div
>
</
Modal
>
)
)
;
}
}
export
default
SelectOperatorModal
export
default
SelectOperatorModal
;
src/modules/plan-manage/modal/relatedCourseModal.less
View file @
1402a09b
...
...
@@ -12,7 +12,47 @@
text-align: left;
display: inline-block;
span {
color: #5289fa;
color: #2966ff;
}
}
.search-container {
margin-bottom: 16px;
}
.select-area {
margin-bottom: 12px;
display: flex;
justify-content: space-between;
.select-box {
display: inline-box;
width: 186px;
background: #e9efff;
border-radius: 4px;
padding: 6px 16px;
margin-right: 8px;
display: flex;
justify-content: space-between;
.tip-icon {
color: #2966ff;
font-size: 14px;
margin-right: 4px;
}
.select-num {
color: #666666;
font-size: 14px;
}
.clear-btn {
text-align: right;
color: #2966ff;
font-size: 14px;
}
}
.related-box {
padding: 6px 16px;
background: #e9efff;
border-radius: 4px;
flex: 1;
color: #666666;
font-size: 14px;
}
}
.search-container {
...
...
src/modules/root/WechatLogin.less
View file @
1402a09b
...
...
@@ -9,42 +9,40 @@
color: #999999;
line-height: 20px;
}
.rwm{
position: relative;
width: 210px;
height: 210px;
text-align: center;
display: inline-block;
margin-top: 24px;
border: 1px solid #e8e8e8;
border-radius: 2px;
padding:15px;
.error{
position: absolute;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items:center;
justify-content:center;
left:5px;
top:5px;
div{
margin: 0 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
.ope{
cursor: pointer;
color:rgba(82, 137, 250, 1);
}
}
.rwm {
position: relative;
width: 210px;
height: 210px;
text-align: center;
display: inline-block;
margin-top: 24px;
border: 1px solid #e8e8e8;
border-radius: 2px;
padding: 15px;
.error {
position: absolute;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items: center;
justify-content: center;
left: 5px;
top: 5px;
div {
margin: 0 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
.ope {
cursor: pointer;
color: rgba(82, 137, 250, 1);
}
}
}
.ant-tabs-tab-active {
.ant-tabs-tab-btn {
...
...
src/modules/teach-tool/examination-manager/Index.tsx
View file @
1402a09b
...
...
@@ -129,6 +129,7 @@ function ExaminationManager(props: any) {
{
title
:
"创建时间"
,
dataIndex
:
"examCreateTime"
,
align
:
fixStr
.
right
,
sorter
:
true
,
sortOrder
:
field
===
"examCreateTime"
?
order
:
sortStatus
.
type
,
render
:
(
text
:
any
,
record
:
any
)
=>
<
span
>
{
moment
(
text
).
format
(
"YYYY-MM-DD HH:mm"
)
}
</
span
>,
...
...
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