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
f95a3d4e
Commit
f95a3d4e
authored
Jul 05, 2021
by
yuananting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:课程改造培训计划部分更改
parent
62d535e8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
640 additions
and
605 deletions
+640
-605
src/modules/course-manage/components/GraphicsEditor.jsx
+94
-89
src/modules/course-manage/components/GraphicsEditor.less
+11
-3
src/modules/plan-manage/components/BasicInfo.jsx
+39
-16
src/modules/plan-manage/components/BasicInfo.less
+71
-68
src/modules/plan-manage/components/TrainingTask.jsx
+171
-160
src/modules/plan-manage/modal/UserLearnDetailModal.jsx
+187
-110
src/modules/plan-manage/modal/UserLearnDetailModal.less
+47
-136
src/modules/plan-manage/modal/relatedCourseModal.jsx
+20
-23
No files found.
src/modules/course-manage/components/GraphicsEditor.jsx
View file @
f95a3d4e
/*
* @Author: yuananting
* @Date: 2021-07-05 10:47:19
* @LastEditors: yuananting
* @LastEditTime: 2021-07-05 11:00:28
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
{
message
}
from
'antd'
;
import
{
message
}
from
'antd'
;
import
React
from
'react'
;
import
React
from
'react'
;
import
E
from
'wangeditor'
;
import
E
from
'wangeditor'
;
...
@@ -9,25 +18,23 @@ const { BtnMenu } = E;
...
@@ -9,25 +18,23 @@ const { BtnMenu } = E;
class
GraphicsEditor
extends
React
.
Component
{
class
GraphicsEditor
extends
React
.
Component
{
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
this
.
state
=
{
editorId
:
window
.
random_string
(
16
),
editorId
:
window
.
random_string
(
16
),
textLength
:
0
,
textLength
:
0
,
showSelectImageModal
:
false
,
showSelectImageModal
:
false
,
showSelectVideoModal
:
false
,
showSelectVideoModal
:
false
,
diskList
:
[],
diskList
:
[],
}
}
;
this
.
editorInt
=
null
;
this
.
editorInt
=
null
;
}
}
componentDidMount
()
{
componentDidMount
()
{
this
.
renderEditor
()
this
.
renderEditor
()
;
this
.
resetIndex
(
true
);
this
.
resetIndex
(
true
);
this
.
initBus
();
this
.
initBus
();
}
}
componentWillUnmount
()
{
componentWillUnmount
()
{
this
.
resetIndex
();
this
.
resetIndex
();
this
.
removeBus
();
this
.
removeBus
();
...
@@ -38,7 +45,7 @@ class GraphicsEditor extends React.Component {
...
@@ -38,7 +45,7 @@ class GraphicsEditor extends React.Component {
const
leftDom
=
document
.
querySelector
(
'.left-container'
);
const
leftDom
=
document
.
querySelector
(
'.left-container'
);
// topDom.style.zIndex = bool ? 'auto' : 112;
// topDom.style.zIndex = bool ? 'auto' : 112;
// leftDom.style.zIndex = bool ? 'auto' : 2;
// leftDom.style.zIndex = bool ? 'auto' : 2;
}
}
;
renderEditor
()
{
renderEditor
()
{
const
{
editorId
}
=
this
.
state
;
const
{
editorId
}
=
this
.
state
;
...
@@ -50,17 +57,15 @@ class GraphicsEditor extends React.Component {
...
@@ -50,17 +57,15 @@ class GraphicsEditor extends React.Component {
`<div class="w-e-menu" data-title="图片">
`<div class="w-e-menu" data-title="图片">
<i class="w-e-icon-image"></i>
<i class="w-e-icon-image"></i>
</div>`
</div>`
)
)
;
super
(
$elem
,
editor
)
super
(
$elem
,
editor
)
;
}
}
// 菜单点击事件
// 菜单点击事件
clickHandler
()
{
clickHandler
()
{
Bus
.
trigger
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
)
Bus
.
trigger
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
)
;
}
}
tryChangeActive
()
{
tryChangeActive
()
{}
}
}
}
class
VideoMenu
extends
BtnMenu
{
class
VideoMenu
extends
BtnMenu
{
...
@@ -70,40 +75,24 @@ class GraphicsEditor extends React.Component {
...
@@ -70,40 +75,24 @@ class GraphicsEditor extends React.Component {
`<div class="w-e-menu" data-title="视频">
`<div class="w-e-menu" data-title="视频">
<i class="w-e-icon-play"></i>
<i class="w-e-icon-play"></i>
</div>`
</div>`
)
)
;
super
(
$elem
,
editor
)
super
(
$elem
,
editor
)
;
}
}
// 菜单点击事件
// 菜单点击事件
clickHandler
()
{
clickHandler
()
{
Bus
.
trigger
(
'graphicsEditorVideo'
)
Bus
.
trigger
(
'graphicsEditorVideo'
)
;
}
}
tryChangeActive
()
{
tryChangeActive
()
{}
}
}
}
this
.
editorInt
=
new
E
(
`#editor
${
editorId
}
`
);
this
.
editorInt
=
new
E
(
`#editor
${
editorId
}
`
);
this
.
editorInt
.
config
.
focus
=
false
;
this
.
editorInt
.
config
.
focus
=
false
;
this
.
editorInt
.
config
.
showFullScreen
=
!
isIntro
this
.
editorInt
.
config
.
showFullScreen
=
!
isIntro
;
this
.
editorInt
.
menus
.
extend
(
'xmimage'
,
ImageMenu
);
this
.
editorInt
.
menus
.
extend
(
'xmimage'
,
ImageMenu
);
!
isIntro
&&
this
.
editorInt
.
menus
.
extend
(
'xmvideo'
,
VideoMenu
);
!
isIntro
&&
this
.
editorInt
.
menus
.
extend
(
'xmvideo'
,
VideoMenu
);
this
.
editorInt
.
config
.
menus
=
isIntro
?
this
.
editorInt
.
config
.
menus
=
isIntro
[
?
[
'head'
,
'bold'
,
'fontSize'
,
'fontName'
,
'italic'
,
'underline'
,
'strikeThrough'
,
'foreColor'
,
'backColor'
,
'list'
,
'justify'
,
'emoticon'
,
'xmimage'
]
'head'
,
'bold'
,
'fontSize'
,
'fontName'
,
'italic'
,
'underline'
,
'strikeThrough'
,
'foreColor'
,
'backColor'
,
'list'
,
'justify'
,
'emoticon'
,
'xmimage'
,
]
:
[
:
[
'head'
,
'head'
,
'bold'
,
'bold'
,
...
@@ -134,33 +123,47 @@ class GraphicsEditor extends React.Component {
...
@@ -134,33 +123,47 @@ class GraphicsEditor extends React.Component {
{
{
title
:
'emoji'
,
title
:
'emoji'
,
type
:
'emoji'
,
type
:
'emoji'
,
content
:
[
'😀'
,
'😃'
,
'😄'
,
'😁'
,
'😆'
,
'😅'
,
'😂'
,
'😊'
,
'🙂'
,
'🙃'
,
'😉'
,
'😓'
,
'😅'
,
'😪'
,
'🤔'
,
'😬'
,
'🤐'
]
content
:
[
'😀'
,
'😃'
,
'😄'
,
'😁'
,
'😆'
,
'😅'
,
'😂'
,
'😊'
,
'🙂'
,
'🙃'
,
'😉'
,
'😓'
,
'😅'
,
'😪'
,
'🤔'
,
'😬'
,
'🤐'
]
,
}
}
,
]
]
;
this
.
editorInt
.
config
.
zIndex
=
1
;
this
.
editorInt
.
config
.
zIndex
=
1
;
this
.
editorInt
.
config
.
pasteFilterStyle
=
false
;
this
.
editorInt
.
config
.
pasteFilterStyle
=
false
;
this
.
editorInt
.
config
.
pasteIgnoreImg
=
true
;
this
.
editorInt
.
config
.
pasteIgnoreImg
=
true
;
// 自定义处理粘贴的文本内容
// 自定义处理粘贴的文本内容
this
.
editorInt
.
config
.
pasteTextHandle
=
function
(
content
)
{
this
.
editorInt
.
config
.
pasteTextHandle
=
(
content
)
=>
{
if
(
content
==
''
&&
!
content
)
return
''
if
(
content
==
''
&&
!
content
)
return
''
;
var
str
=
content
var
str1
=
content
;
// 去除所有特殊字符
str
=
str
.
replace
(
/<xml>
[\s\S]
*
?
<
\/
xml>/ig
,
''
)
str1
=
str1
.
replace
(
/<xml>
[\s\S]
*
?
<
\/
xml>/gi
,
''
);
str
=
str
.
replace
(
/<style>
[\s\S]
*
?
<
\/
style>/ig
,
''
)
str1
=
str1
.
replace
(
/<style>
[\s\S]
*
?
<
\/
style>/gi
,
''
);
str
=
str
.
replace
(
/
[
|
]
*
\n
/g
,
'
\
n'
)
str1
=
str1
.
replace
(
/<
\/?[^
>
]
*>/g
,
''
);
str
=
str
.
replace
(
/
\&
nbsp
\;
/ig
,
' '
)
str1
=
str1
.
replace
(
/
[
|
]
*
\n
/g
,
'
\
n'
);
return
str
str1
=
str1
.
replace
(
/
\&
nbsp
\;
/gi
,
' '
);
str1
=
str1
.
replace
(
/
[\r\n]
/g
,
''
);
str1
=
str1
.
replace
(
/<
\/?
a.*
?
>/g
,
''
);
var
str2
=
content
;
// 保留空格和换行的其他字符
str2
=
str2
.
replace
(
/<xml>
[\s\S]
*
?
<
\/
xml>/gi
,
''
);
str2
=
str2
.
replace
(
/<style>
[\s\S]
*
?
<
\/
style>/gi
,
''
);
str2
=
str2
.
replace
(
/<
\/?
a.*
?
>/g
,
''
);
const
videoCount
=
((
content
||
''
).
match
(
/<iframe/g
)
||
[]).
length
;
const
imageCount
=
((
content
||
''
).
match
(
/<img/g
)
||
[]).
length
;
const
textLength
=
this
.
editorInt
.
txt
.
text
().
length
+
str1
.
length
+
videoCount
+
imageCount
;
if
(
textLength
>
maxLimit
)
{
message
.
warning
(
`内容过长,不能超过
${
maxLimit
}
字`
);
}
}
return
str2
;
};
this
.
editorInt
.
config
.
onchange
=
(
html
)
=>
{
this
.
editorInt
.
config
.
onchange
=
(
html
)
=>
{
const
videoCount
=
((
html
||
''
).
match
(
/<iframe/g
)
||
[]).
length
;
const
videoCount
=
((
html
||
''
).
match
(
/<iframe/g
)
||
[]).
length
;
const
imageCount
=
((
html
||
''
).
match
(
/<img/g
)
||
[]).
length
;
const
imageCount
=
((
html
||
''
).
match
(
/<img/g
)
||
[]).
length
;
const
textLength
=
this
.
editorInt
.
txt
.
text
().
replace
(
/
\&
nbsp
\;
/
ig
,
' '
).
length
+
videoCount
+
imageCount
;
const
textLength
=
this
.
editorInt
.
txt
.
text
().
replace
(
/
\&
nbsp
\;
/
gi
,
' '
).
length
+
videoCount
+
imageCount
;
this
.
setState
({
textLength
},
()
=>
{
this
.
setState
({
textLength
},
()
=>
{
if
(
textLength
>
maxLimit
)
{
if
(
textLength
>
maxLimit
)
{
// message.warning('超过字数限定');
// message.warning('超过字数限定');
}
}
onChange
(
html
,
this
.
state
.
textLength
);
onChange
(
html
,
this
.
state
.
textLength
);
})
})
;
}
}
;
this
.
editorInt
.
create
();
this
.
editorInt
.
create
();
this
.
editorInt
.
txt
.
html
(
detail
.
content
);
this
.
editorInt
.
txt
.
html
(
detail
.
content
);
}
}
...
@@ -170,59 +173,60 @@ class GraphicsEditor extends React.Component {
...
@@ -170,59 +173,60 @@ class GraphicsEditor extends React.Component {
const
{
ossUrl
}
=
file
||
{};
const
{
ossUrl
}
=
file
||
{};
if
(
!
ossUrl
)
return
null
;
if
(
!
ossUrl
)
return
null
;
this
.
setState
({
this
.
setState
({
showSelectVideoModal
:
false
showSelectVideoModal
:
false
,
})
})
;
const
{
detail
}
=
this
.
props
;
const
{
detail
}
=
this
.
props
;
this
.
editorInt
&&
this
.
editorInt
.
txt
.
html
(
`
${
detail
.
content
}
<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="
${
ossUrl
}
"></iframe><br/></p><p><br/></p>`
)
this
.
editorInt
&&
}
this
.
editorInt
.
txt
.
html
(
`
${
detail
.
content
}
<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="
${
ossUrl
}
"></iframe><br/></p><p><br/></p>`
);
};
handleSelectImage
=
(
file
)
=>
{
handleSelectImage
=
(
file
)
=>
{
const
{
ossUrl
}
=
file
||
{};
const
{
ossUrl
}
=
file
||
{};
if
(
!
ossUrl
)
return
null
;
if
(
!
ossUrl
)
return
null
;
this
.
setState
({
this
.
setState
({
showSelectImageModal
:
false
showSelectImageModal
:
false
,
})
})
;
const
{
detail
}
=
this
.
props
;
const
{
detail
}
=
this
.
props
;
this
.
editorInt
&&
this
.
editorInt
.
txt
.
html
(
`
${
detail
.
content
}
<p><img style="max-width: 100%;" src="
${
ossUrl
}
" /><br/><p>`
)
this
.
editorInt
&&
this
.
editorInt
.
txt
.
html
(
`
${
detail
.
content
}
<p><img style="max-width: 100%;" src="
${
ossUrl
}
" /><br/><p>`
)
;
}
}
;
initBus
=
()
=>
{
initBus
=
()
=>
{
const
{
isIntro
}
=
this
.
props
;
const
{
isIntro
}
=
this
.
props
;
Bus
.
bind
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
,
this
.
uploadImage
)
Bus
.
bind
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
,
this
.
uploadImage
)
;
!
isIntro
&&
Bus
.
bind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
!
isIntro
&&
Bus
.
bind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
;
}
}
;
removeBus
=
()
=>
{
removeBus
=
()
=>
{
const
{
isIntro
}
=
this
.
props
;
const
{
isIntro
}
=
this
.
props
;
Bus
.
unbind
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
,
this
.
uploadImage
)
Bus
.
unbind
(
`graphicsEditorImage
${
isIntro
?
''
:
'Content'
}
`
,
this
.
uploadImage
)
;
!
isIntro
&&
Bus
.
unbind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
!
isIntro
&&
Bus
.
unbind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
;
}
}
;
uploadImage
=
()
=>
{
uploadImage
=
()
=>
{
this
.
setState
({
showSelectImageModal
:
true
})
this
.
setState
({
showSelectImageModal
:
true
})
;
}
}
;
uploadVideo
=
()
=>
{
uploadVideo
=
()
=>
{
this
.
setState
({
showSelectVideoModal
:
true
})
this
.
setState
({
showSelectVideoModal
:
true
})
;
}
}
;
render
()
{
render
()
{
const
{
const
{
editorId
,
textLength
,
showSelectImageModal
,
showSelectVideoModal
,
diskList
}
=
this
.
state
;
editorId
,
const
{
isIntro
,
maxLimit
}
=
this
.
props
;
textLength
,
return
(
showSelectImageModal
,
<
div
className=
{
`graphics-editor-container${isIntro ? ' introduce' : ''} ${textLength > maxLimit && 'warning'}`
}
>
showSelectVideoModal
,
<
div
className=
'editor-box'
id=
{
`editor${editorId}`
}
></
div
>
diskList
,
<
div
className=
'editor-tips'
>
}
=
this
.
state
;
(
{
textLength
>
maxLimit
?
<
span
style=
{
{
color
:
'red'
}
}
>
{
textLength
}
</
span
>
:
textLength
}
/
{
maxLimit
||
1000
}
)
const
{
limitLength
=
1000
,
isIntro
,
maxLimit
}
=
this
.
props
;
</
div
>
return
<
div
className=
{
`graphics-editor-container${isIntro ? ' introduce' : ''} ${(textLength > maxLimit)&& 'warning'}`
}
>
{
textLength
>
maxLimit
&&
<
div
className=
'editor-warning'
>
最多只能输入
{
maxLimit
||
1000
}
字
</
div
>
}
<
div
className=
"editor-box"
id=
{
`editor${editorId}`
}
></
div
>
{
showSelectVideoModal
&&
(
<
div
className=
"editor-tips"
>
(
{
(
textLength
>
maxLimit
)
?
<
span
style=
{
{
color
:
'red'
}
}
>
{
textLength
}
</
span
>
:
textLength
}
/
{
maxLimit
||
1000
}
)
</
div
>
{
showSelectVideoModal
&&
<
SelectPrepareFileModal
<
SelectPrepareFileModal
operateType=
"select"
operateType=
'select'
selectTypeList=
{
[
'MP4'
]
}
selectTypeList=
{
[
'MP4'
]
}
accept=
"video/mp4"
accept=
'video/mp4'
confirm=
{
{
confirm=
{
{
title
:
'文件过大,无法上传'
,
title
:
'文件过大,无法上传'
,
content
:
'为保障学员的观看体验,上传的图文大小不能超过2G'
,
content
:
'为保障学员的观看体验,上传的图文大小不能超过2G'
,
...
@@ -232,27 +236,28 @@ class GraphicsEditor extends React.Component {
...
@@ -232,27 +236,28 @@ class GraphicsEditor extends React.Component {
diskList=
{
diskList
}
diskList=
{
diskList
}
addVideo=
{
true
}
addVideo=
{
true
}
onClose=
{
()
=>
{
onClose=
{
()
=>
{
this
.
setState
({
showSelectVideoModal
:
false
})
this
.
setState
({
showSelectVideoModal
:
false
});
}
}
}
}
onSelect=
{
this
.
handleSelectVideo
}
onSelect=
{
this
.
handleSelectVideo
}
/>
/>
}
)
}
{
showSelectImageModal
&&
{
showSelectImageModal
&&
(
<
SelectPrepareFileModal
<
SelectPrepareFileModal
key=
"basic"
key=
'basic'
operateType=
"select"
operateType=
'select'
multiple=
{
false
}
multiple=
{
false
}
accept=
"image/jpeg,image/png,image/jpg"
accept=
'image/jpeg,image/png,image/jpg'
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
'支持文件类型:jpg、jpeg、png'
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectImageModal
}
isOpen=
{
showSelectImageModal
}
onClose=
{
()
=>
{
onClose=
{
()
=>
{
this
.
setState
({
showSelectImageModal
:
false
})
this
.
setState
({
showSelectImageModal
:
false
});
}
}
}
}
onSelect=
{
this
.
handleSelectImage
}
onSelect=
{
this
.
handleSelectImage
}
/>
/>
}
)
}
</
div
>
</
div
>
);
}
}
}
}
...
...
src/modules/course-manage/components/GraphicsEditor.less
View file @
f95a3d4e
.graphics-editor-container {
.graphics-editor-container {
border: 1px solid #
E8E8E
8;
border: 1px solid #
e8e8e
8;
border-radius: 4px;
border-radius: 4px;
width: 702px;
width: 702px;
height: 510px;
height: 510px;
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
.w-e-toolbar {
.w-e-toolbar {
background-color: #fff !important;
background-color: #fff !important;
border: none !important;
border: none !important;
border-bottom: 1px solid #
E8E8E
8 !important;
border-bottom: 1px solid #
e8e8e
8 !important;
}
}
.w-e-text-container {
.w-e-text-container {
...
@@ -38,6 +38,14 @@
...
@@ -38,6 +38,14 @@
color: #666;
color: #666;
z-index: 1;
z-index: 1;
}
}
.editor-warning {
position: absolute;
right: 0;
top: 205px;
color: red;
}
.w-e-full-screen-editor {
.w-e-full-screen-editor {
.w-e-text-container {
.w-e-text-container {
height: ~'calc(100vh - 109px)' !important;
height: ~'calc(100vh - 109px)' !important;
...
@@ -50,7 +58,7 @@
...
@@ -50,7 +58,7 @@
}
}
}
}
&.warning{
&.warning
{
border-color: red;
border-color: red;
}
}
}
}
src/modules/plan-manage/components/BasicInfo.jsx
View file @
f95a3d4e
/*
/*
* @Author: yuananting
* @Date: 2021-07-05 10:48:08
* @LastEditors: yuananting
* @LastEditTime: 2021-07-05 11:01:19
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
/*
* @Author: zhangleyuan
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @Date: 2021-02-20 16:45:51
* @LastEditors:
fusanqias
ng
* @LastEditors:
yuananti
ng
* @LastEditTime: 2021-0
6-01 15:20:33
* @LastEditTime: 2021-0
7-02 17:16:06
* @Description: 描述一下
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
...
@@ -12,7 +21,7 @@ import { withRouter } from 'react-router-dom';
...
@@ -12,7 +21,7 @@ import { withRouter } from 'react-router-dom';
import
SelectOperatorModal
from
'../modal/SelectOperatorModal'
;
import
SelectOperatorModal
from
'../modal/SelectOperatorModal'
;
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
;
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
;
import
Upload
from
'@/core/upload'
;
import
Upload
from
'@/core/upload'
;
// import PhotoClip from 'photoclip'
import
GraphicsEditor
from
'@/modules/course-manage/components/GraphicsEditor'
;
import
'./BasicInfo.less'
;
import
'./BasicInfo.less'
;
const
{
TextArea
}
=
Input
;
const
{
TextArea
}
=
Input
;
...
@@ -202,10 +211,14 @@ class BasicInfo extends React.Component {
...
@@ -202,10 +211,14 @@ class BasicInfo extends React.Component {
this
.
props
.
onChange
(
field
,
_percentCompleteLive
);
this
.
props
.
onChange
(
field
,
_percentCompleteLive
);
};
};
changeIntro
=
(
value
)
=>
{
this
.
props
.
onChange
(
'introduce'
,
value
);
};
render
()
{
render
()
{
const
{
operatorModalVisible
,
showSelectFileModal
,
visible
,
hasImgReady
,
cutImageBlob
}
=
this
.
state
;
const
{
operatorModalVisible
,
showSelectFileModal
,
visible
,
hasImgReady
,
cutImageBlob
}
=
this
.
state
;
const
{
data
}
=
this
.
props
;
const
{
data
}
=
this
.
props
;
const
{
planName
,
coverUrl
,
in
stro
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
}
=
const
{
planName
,
coverUrl
,
in
troduce
,
enableState
,
operateType
,
selectOperatorList
,
percentCompleteLive
,
percentCompleteVideo
,
percentCompletePicture
}
=
data
;
data
;
// 当前是否使用的是默认图片
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
const
isDefaultCover
=
coverUrl
===
defaultCover
;
...
@@ -226,10 +239,6 @@ class BasicInfo extends React.Component {
...
@@ -226,10 +239,6 @@ class BasicInfo extends React.Component {
<
div
className=
'cover'
>
<
div
className=
'cover'
>
<
span
className=
'label'
>
封面图:
</
span
>
<
span
className=
'label'
>
封面图:
</
span
>
<
div
className=
'cover__wrap'
>
<
div
className=
'cover__wrap'
>
<
div
className=
'img-content'
>
{
isDefaultCover
&&
<
span
className=
'tag'
>
默认图
</
span
>
}
<
img
src=
{
coverUrl
}
width=
'690'
alt=
''
/>
</
div
>
<
div
className=
'opt-btns'
>
<
div
className=
'opt-btns'
>
<
Button
<
Button
onClick=
{
()
=>
{
onClick=
{
()
=>
{
...
@@ -244,17 +253,32 @@ class BasicInfo extends React.Component {
...
@@ -244,17 +253,32 @@ class BasicInfo extends React.Component {
</
span
>
</
span
>
<
div
className=
'tips'
>
建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。
</
div
>
<
div
className=
'tips'
>
建议尺寸1280*720px或16:9。封面图最大5M,支持jpg、jpeg和png。
</
div
>
</
div
>
</
div
>
<
div
className=
'img-content'
>
{
isDefaultCover
&&
<
span
className=
'tag'
>
默认图
</
span
>
}
<
img
src=
{
coverUrl
}
width=
'690'
alt=
''
/>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
'introduction'
>
<
div
className=
'introduction'
>
<
span
className=
'label'
>
简介:
</
span
>
<
span
className=
'label'
>
课程
简介:
</
span
>
<
TextArea
{
/*
<TextArea
placeholder='请输入培训计划简介'
placeholder='请输入培训计划简介'
maxLength={200}
maxLength={200}
style={{ width: '552px', height: '110px' }}
style={{ width: '552px', height: '110px' }}
className='instro-textarea'
className='instro-textarea'
value={instro}
value={instro}
onChange={(e) => this.props.onChange('instro', e.target.value)}
onChange={(e) => this.props.onChange('instro', e.target.value)}
/> */
}
<
GraphicsEditor
id=
'intro'
isIntro=
{
true
}
maxLimit=
{
1000
}
detail=
{
{
content
:
introduce
,
}
}
onChange=
{
(
val
)
=>
{
this
.
changeIntro
(
val
);
}
}
/>
/>
</
div
>
</
div
>
<
div
className=
'wether-use'
>
<
div
className=
'wether-use'
>
...
@@ -270,8 +294,7 @@ class BasicInfo extends React.Component {
...
@@ -270,8 +294,7 @@ class BasicInfo extends React.Component {
</
div
>
</
div
>
<
div
>
<
div
>
<
div
className=
'instro-text'
>
<
div
className=
'instro-text'
>
<
div
>
开启:此培训计划可以分享给学员进行学习
</
div
>
<
div
>
{
enableState
===
'YES'
?
'已开启,培训计划可正常分享给学员学习'
:
'已关闭,培训计划暂不进行分享和学习'
}
</
div
>
<
div
>
关闭:此培训计划暂不可分享给学员进行学习,后续可开启
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -291,7 +314,7 @@ class BasicInfo extends React.Component {
...
@@ -291,7 +314,7 @@ class BasicInfo extends React.Component {
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'operateType'
,
e
.
target
.
value
);
this
.
props
.
onChange
(
'operateType'
,
e
.
target
.
value
);
}
}
>
}
}
>
<
Row
style=
{
{
marginBottom
:
'
5
px'
}
}
>
<
Row
style=
{
{
marginBottom
:
'
16
px'
}
}
>
<
Col
span=
{
24
}
>
<
Col
span=
{
24
}
>
<
Radio
value=
'All_Operate'
>
<
Radio
value=
'All_Operate'
>
所有运营师
所有运营师
...
@@ -317,7 +340,7 @@ class BasicInfo extends React.Component {
...
@@ -317,7 +340,7 @@ class BasicInfo extends React.Component {
选择运营师
选择运营师
</
Button
>
</
Button
>
<
span
>
<
span
>
已选择
<
span
>
{
selectOperatorList
.
length
}
</
span
>
名运营师
已选择
<
span
style=
{
{
color
:
'#2966FF'
}
}
>
{
selectOperatorList
.
length
}
</
span
>
名运营师
</
span
>
</
span
>
</
div
>
</
div
>
)
}
)
}
...
@@ -347,7 +370,7 @@ class BasicInfo extends React.Component {
...
@@ -347,7 +370,7 @@ class BasicInfo extends React.Component {
<
div
className=
'live-standard-info'
>
<
div
className=
'live-standard-info'
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'instro'
>
<
span
className=
'instro'
>
线上课单个课
程
,学员学习进度达到
线上课单个课
节
,学员学习进度达到
<
Input
<
Input
width=
'40'
width=
'40'
value=
{
percentCompleteVideo
}
value=
{
percentCompleteVideo
}
...
@@ -357,7 +380,7 @@ class BasicInfo extends React.Component {
...
@@ -357,7 +380,7 @@ class BasicInfo extends React.Component {
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteVideo'
)
}
onBlur=
{
(
e
)
=>
this
.
percentCompleteBlur
(
e
,
'percentCompleteVideo'
)
}
className=
'input-box'
className=
'input-box'
/>
/>
%,即视为"已完成"学习
%,即
课节
视为"已完成"学习
</
span
>
</
span
>
</
div
>
</
div
>
<
div
className=
'live-standard-info'
>
<
div
className=
'live-standard-info'
>
...
...
src/modules/plan-manage/components/BasicInfo.less
View file @
f95a3d4e
.plan-basic-info{
.plan-basic-info
{
.label {
.label {
width: 110px;
width: 110px;
text-align: right;
text-align: right;
display:
inline-block;
display:
inline-block;
font-size:
14px;
font-size:
14px;
color:
#666;
color:
#666;
.require {
.require {
color: #EC4B
35;
color: #ec4b
35;
}
}
.iconfont
{
.iconfont
{
font-size:
14px;
font-size:
14px;
color:#BFBFBF
;
color: #bfbfbf
;
}
}
}
}
.cover {
.cover {
display: flex;
display: flex;
margin-top: 16
px;
margin-top: 24
px;
&__wrap {
&__wrap {
position: relative;
position: relative;
display: flex;
.tag {
.tag {
border-radius: 2px;
border-radius: 2px;
background: #D6D6D
6;
background: #d6d6d
6;
font-size: 12px;
font-size: 12px;
height: 18px;
height: 18px;
width: 52px;
width: 52px;
text-align: center;
text-align: center;
color: #FFF
;
color: #fff
;
position: absolute;
position: absolute;
top: 8px;
top: 8px;
left: 8px;
left: 8px;
}
}
}
}
.img-content {
.img-content {
margin-right: 20px;
position: relative;
margin-top: 8px;
width: 299px;
width: 299px;
height: 169px;
height: 169px;
img {
img {
...
@@ -42,90 +42,93 @@
...
@@ -42,90 +42,93 @@
object-fit: contain;
object-fit: contain;
}
}
}
}
.opt-btns
{
.opt-btns
{
.default-btn {
.default-btn {
margin:
0 8px;
margin:
0 8px;
color: #2966FF
;
color: #2966ff
;
cursor: pointer;
cursor: pointer;
&.disabled {
&.disabled {
color: #CCC
;
color: #ccc
;
cursor: not-allowed;
cursor: not-allowed;
}
}
}
}
.tips
{
.tips
{
margin-top:
8px;
margin-top:
8px;
font-size:
14px;
font-size:
14px;
color:
#999;
color:
#999;
}
}
}
}
}
}
.introduction{
.introduction {
margin-top:16px;
display: flex;
.instro-textarea{
margin-top: 24px;
.instro-textarea {
vertical-align: top;
vertical-align: top;
}
}
}
}
.wether-use
{
.wether-use
{
display:
flex;
display:
flex;
margin-top:16
px;
margin-top: 34
px;
.instro-text
{
.instro-text
{
color:
#999;
color:
#999;
margin-left:
12px;
margin-left:
12px;
}
}
.content
{
.content
{
display:
flex;
display:
flex;
}
}
}
}
.view-range
{
.view-range
{
display:
flex;
display:
flex;
margin-top:16
px;
margin-top: 24
px;
.label
{
.label
{
margin-top:
2px;
margin-top:
2px;
}
}
.instro-text
{
.instro-text
{
color:
#999;
color:
#999;
margin-left:
12px;
margin-left:
12px;
}
}
.choose-business{
.choose-business {
margin-top:16px;
margin-top: 12px;
.ant-btn {
margin-right: 12px;
}
}
.playback__text{
margin-left:12px;
color:#999999;
}
}
.playback__text {
margin-left: 12px;
color: #999999;
}
}
.done-standard{
}
.done-standard {
display: flex;
display: flex;
margin-top:
22px;
margin-top:
22px;
.standard-label
{
.standard-label
{
margin-top:
3px;
margin-top:
3px;
}
}
.live-standard-info
{
.live-standard-info
{
margin-bottom:
10px;
margin-bottom:
10px;
}
}
input
{
input
{
display:
inline-block;
display:
inline-block;
width:
90px;
width:
90px;
height:
32px;
height:
32px;
}
}
.icon
{
.icon
{
color:#A0A0A
0;
color: #a0a0a
0;
font-size:
14px;
font-size:
14px;
margin-right:
4px;
margin-right:
4px;
}
}
.instro
{
.instro
{
color:
#333333;
color:
#333333;
font-size:
14px;
font-size:
14px;
}
}
.input-box
{
.input-box
{
width: 60px;
width: 60px;
height: 32px;
height: 32px;
border-radius: 4px;
border-radius: 4px;
border: 1px solid #E8E8E
8;
border: 1px solid #e8e8e
8;
color:
#333333;
color:
#333333;
font-size:
14px;
font-size:
14px;
margin:
0 2px;
margin:
0 2px;
}
}
}
}
}
}
src/modules/plan-manage/components/TrainingTask.jsx
View file @
f95a3d4e
/*
/*
* @Author: yuananting
* @Date: 2021-07-05 10:49:01
* @LastEditors: yuananting
* @LastEditTime: 2021-07-05 11:02:04
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
/*
* @Author: zhangleyuan
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @Date: 2021-02-20 16:45:51
* @LastEditors:
fusanqias
ng
* @LastEditors:
yuananti
ng
* @LastEditTime: 2021-0
5-24 15:15:06
* @LastEditTime: 2021-0
7-01 17:16:50
* @Description: 描述一下
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
*/
import
React
from
'react'
import
React
from
'react'
;
import
{
Input
,
Form
,
Modal
}
from
'antd'
import
{
Input
,
Form
,
Modal
}
from
'antd'
;
import
{
sortableContainer
,
sortableElement
,
sortableHandle
}
from
'react-sortable-hoc'
import
{
sortableContainer
,
sortableElement
,
sortableHandle
}
from
'react-sortable-hoc'
;
import
arrayMove
from
'array-move'
import
arrayMove
from
'array-move'
;
import
RelatedCourseModal
from
'../modal/relatedCourseModal'
import
RelatedCourseModal
from
'../modal/relatedCourseModal'
;
import
{
withRouter
}
from
'react-router-dom'
import
{
withRouter
}
from
'react-router-dom'
;
import
'./TrainingTask.less'
import
'./TrainingTask.less'
;
const
{
confirm
}
=
Modal
const
{
confirm
}
=
Modal
;
const
CourseType
=
{
const
CourseType
=
{
LIVE
:
{
LIVE
:
{
text
:
'直播课'
text
:
'直播课'
,
},
},
VOICE
:
{
VOICE
:
{
text
:
'线上课'
text
:
'线上课'
,
},
},
RECORD
:
{
RECORD
:
{
text
:
'录播课'
text
:
'录播课'
,
},
},
PICTURE
:
{
PICTURE
:
{
text
:
'图文课'
text
:
'图文课'
,
}
}
,
}
}
;
const
courseStateShow
=
{
const
courseStateShow
=
{
UN_START
:
{
UN_START
:
{
title
:
'待开播'
title
:
'待开播'
,
},
},
STARTING
:
{
STARTING
:
{
title
:
'直播中'
title
:
'直播中'
,
},
},
FINISH
:
{
FINISH
:
{
title
:
'回放'
title
:
'回放'
,
},
},
EXPIRED
:
{
EXPIRED
:
{
title
:
'未成功开课'
title
:
'未成功开课'
,
}
}
,
}
}
;
const
DragHandle
=
sortableHandle
(()
=>
(
const
DragHandle
=
sortableHandle
(()
=>
(
<
span
className=
'operate__item'
>
<
span
className=
'operate__item'
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'text'
>
移动
</
span
>
<
span
className=
'text'
>
移动
</
span
>
</
span
>
</
span
>
))
))
;
const
SortableTaskItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
taskitem
}
</
div
>)
const
SortableTaskItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
taskitem
}
</
div
>)
;
const
SortableTaskContainer
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>)
const
SortableTaskContainer
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>)
;
const
SortableCourseItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
courseitem
}
</
div
>)
const
SortableCourseItem
=
sortableElement
((
props
)
=>
<
div
{
...
props
}
>
{
props
.
courseitem
}
</
div
>)
;
const
SortableCourseContainer
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>)
const
SortableCourseContainer
=
sortableContainer
((
props
)
=>
<
div
{
...
props
}
></
div
>)
;
class
TrainingTask
extends
React
.
Component
{
class
TrainingTask
extends
React
.
Component
{
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
)
super
(
props
)
;
this
.
state
=
{
this
.
state
=
{
dataSource
:
this
.
props
.
data
,
dataSource
:
this
.
props
.
data
,
selectedTaskIndex
:
0
,
selectedTaskIndex
:
0
,
relatedCourseModalVisible
:
false
relatedCourseModalVisible
:
false
,
}
}
;
}
}
componentWillMount
()
{}
componentWillMount
()
{}
componentWillReceiveProps
(
nextProps
)
{}
componentWillReceiveProps
(
nextProps
)
{}
onTaskSortEnd
=
({
oldIndex
,
newIndex
})
=>
{
onTaskSortEnd
=
({
oldIndex
,
newIndex
})
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
if
(
oldIndex
!==
newIndex
)
{
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMove
([].
concat
(
dataSource
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
const
newData
=
arrayMove
([].
concat
(
dataSource
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
}
}
};
onCourseSortEnd
=
({
oldIndex
,
newIndex
},
parentIndex
)
=>
{
onCourseSortEnd
=
({
oldIndex
,
newIndex
},
parentIndex
)
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
_dataSource
=
[...
dataSource
]
const
_dataSource
=
[...
dataSource
]
;
if
(
oldIndex
!==
newIndex
)
{
if
(
oldIndex
!==
newIndex
)
{
_dataSource
[
parentIndex
].
courseList
=
arrayMove
([].
concat
(
dataSource
[
parentIndex
].
courseList
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
_dataSource
[
parentIndex
].
courseList
=
arrayMove
([].
concat
(
dataSource
[
parentIndex
].
courseList
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
_dataSource
dataSource
:
_dataSource
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
_dataSource
)
this
.
props
.
onChange
(
_dataSource
);
}
)
}
}
);
}
}
};
addTask
=
()
=>
{
addTask
=
()
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
taskObj
=
{
const
taskObj
=
{
taskName
:
''
,
taskName
:
''
,
index
:
dataSource
.
length
,
index
:
dataSource
.
length
,
type
:
'input'
,
type
:
'input'
,
open
:
true
,
open
:
true
,
courseList
:
[]
courseList
:
[]
,
}
}
;
const
newData
=
[...
dataSource
,
taskObj
]
const
newData
=
[...
dataSource
,
taskObj
]
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
};
handleRenameTaskName
=
(
e
,
record
)
=>
{
handleRenameTaskName
=
(
e
,
record
)
=>
{
const
{
value
}
=
e
.
target
const
{
value
}
=
e
.
target
;
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
record
.
taskName
=
value
record
.
taskName
=
value
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
dataSource
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
dataSource
)
this
.
props
.
onChange
(
dataSource
);
}
)
}
}
);
};
handleTaskNameBlur
=
(
e
,
record
)
=>
{
handleTaskNameBlur
=
(
e
,
record
)
=>
{
const
{
value
}
=
e
.
target
const
{
value
}
=
e
.
target
;
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
let
input
=
/^
[\s]
*$/
let
input
=
/^
[\s]
*$/
;
if
(
value
&&
!
input
.
test
(
value
))
{
if
(
value
&&
!
input
.
test
(
value
))
{
record
.
type
=
'text'
record
.
type
=
'text'
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
dataSource
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
dataSource
)
this
.
props
.
onChange
(
dataSource
);
}
)
}
}
);
}
}
};
handleRenameCourseName
=
(
e
,
record
)
=>
{
handleRenameCourseName
=
(
e
,
record
)
=>
{
const
{
value
}
=
e
.
target
const
{
value
}
=
e
.
target
;
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
record
.
courseName
=
value
record
.
courseName
=
value
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
dataSource
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
dataSource
)
this
.
props
.
onChange
(
dataSource
);
}
)
}
}
);
};
handleCourseNameBlur
=
(
e
,
record
)
=>
{
handleCourseNameBlur
=
(
e
,
record
)
=>
{
const
{
value
}
=
e
.
target
const
{
value
}
=
e
.
target
;
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
let
input
=
/^
[\s]
*$/
let
input
=
/^
[\s]
*$/
;
if
(
value
&&
!
input
.
test
(
value
))
{
if
(
value
&&
!
input
.
test
(
value
))
{
record
.
type
=
'text'
record
.
type
=
'text'
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
dataSource
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
dataSource
)
this
.
props
.
onChange
(
dataSource
);
}
)
}
}
);
}
}
};
handleDeleteTask
=
(
index
)
=>
{
handleDeleteTask
=
(
index
)
=>
{
return
confirm
({
return
confirm
({
title
:
'删除任务'
,
title
:
'删除任务'
,
...
@@ -191,23 +200,23 @@ class TrainingTask extends React.Component {
...
@@ -191,23 +200,23 @@ class TrainingTask extends React.Component {
okType
:
'danger'
,
okType
:
'danger'
,
cancelText
:
'取消'
,
cancelText
:
'取消'
,
onOk
:
()
=>
{
onOk
:
()
=>
{
this
.
handleConfirmDeleteTask
(
index
)
this
.
handleConfirmDeleteTask
(
index
)
;
}
}
,
})
})
;
}
}
;
handleConfirmDeleteTask
=
(
index
)
=>
{
handleConfirmDeleteTask
=
(
index
)
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
newData
=
[...
dataSource
]
const
newData
=
[...
dataSource
]
;
newData
.
splice
(
index
,
1
)
newData
.
splice
(
index
,
1
)
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
};
handleDeleteCourse
=
(
parentIndex
,
index
)
=>
{
handleDeleteCourse
=
(
parentIndex
,
index
)
=>
{
return
confirm
({
return
confirm
({
...
@@ -218,82 +227,82 @@ class TrainingTask extends React.Component {
...
@@ -218,82 +227,82 @@ class TrainingTask extends React.Component {
okType
:
'danger'
,
okType
:
'danger'
,
cancelText
:
'取消'
,
cancelText
:
'取消'
,
onOk
:
()
=>
{
onOk
:
()
=>
{
this
.
handleConfirmDeleteCourse
(
parentIndex
,
index
)
this
.
handleConfirmDeleteCourse
(
parentIndex
,
index
)
;
}
}
,
})
})
;
}
}
;
handleConfirmDeleteCourse
=
(
parentIndex
,
index
)
=>
{
handleConfirmDeleteCourse
=
(
parentIndex
,
index
)
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
newData
=
[...
dataSource
]
const
newData
=
[...
dataSource
]
;
const
selectData
=
[...
newData
[
parentIndex
].
courseList
]
const
selectData
=
[...
newData
[
parentIndex
].
courseList
]
;
selectData
.
splice
(
index
,
1
)
selectData
.
splice
(
index
,
1
)
;
newData
[
parentIndex
].
courseList
=
selectData
newData
[
parentIndex
].
courseList
=
selectData
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
};
showRelatedCourseModal
=
(
index
)
=>
{
showRelatedCourseModal
=
(
index
)
=>
{
this
.
setState
({
this
.
setState
({
selectedTaskIndex
:
index
,
selectedTaskIndex
:
index
,
relatedCourseModalVisible
:
true
relatedCourseModalVisible
:
true
,
})
})
;
}
}
;
closeRelatedCourseModal
=
(
index
)
=>
{
closeRelatedCourseModal
=
(
index
)
=>
{
this
.
setState
({
this
.
setState
({
relatedCourseModalVisible
:
false
relatedCourseModalVisible
:
false
,
})
})
;
}
}
;
confirmSelectCourse
=
(
selectList
)
=>
{
confirmSelectCourse
=
(
selectList
)
=>
{
console
.
log
(
'selectList'
,
selectList
)
console
.
log
(
'selectList'
,
selectList
)
;
const
{
selectedTaskIndex
}
=
this
.
state
const
{
selectedTaskIndex
}
=
this
.
state
;
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
newData
=
[...
dataSource
]
const
newData
=
[...
dataSource
]
;
const
selectData
=
[...
newData
[
selectedTaskIndex
].
courseList
]
const
selectData
=
[...
newData
[
selectedTaskIndex
].
courseList
]
;
const
_selectData
=
[...
selectData
,
...
selectList
]
const
_selectData
=
[...
selectData
,
...
selectList
]
;
newData
[
selectedTaskIndex
].
courseList
=
_selectData
newData
[
selectedTaskIndex
].
courseList
=
_selectData
;
this
.
setState
(
this
.
setState
(
{
{
relatedCourseModalVisible
:
false
,
relatedCourseModalVisible
:
false
,
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
};
openOrCloseTask
=
(
index
)
=>
{
openOrCloseTask
=
(
index
)
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
const
newData
=
[...
dataSource
]
const
newData
=
[...
dataSource
]
;
newData
[
index
].
open
=
!
newData
[
index
].
open
newData
[
index
].
open
=
!
newData
[
index
].
open
;
this
.
setState
(
this
.
setState
(
{
{
dataSource
:
newData
dataSource
:
newData
,
},
},
()
=>
{
()
=>
{
this
.
props
.
onChange
(
newData
)
this
.
props
.
onChange
(
newData
);
}
)
}
}
);
};
handleValidatorTaskName
=
(
rule
,
value
)
=>
{
handleValidatorTaskName
=
(
rule
,
value
)
=>
{
let
input
=
/^
[\s]
*$/
let
input
=
/^
[\s]
*$/
;
if
(
input
.
test
(
value
)
||
!
value
)
{
if
(
input
.
test
(
value
)
||
!
value
)
{
return
Promise
.
reject
(
new
Error
(
'请输入任务名称'
))
return
Promise
.
reject
(
new
Error
(
'请输入任务名称'
));
}
return
Promise
.
resolve
()
}
}
return
Promise
.
resolve
();
};
handleValidatorCourseName
=
(
rule
,
value
)
=>
{
handleValidatorCourseName
=
(
rule
,
value
)
=>
{
let
input
=
/^
[\s]
*$/
let
input
=
/^
[\s]
*$/
;
if
(
input
.
test
(
value
)
||
!
value
)
{
if
(
input
.
test
(
value
)
||
!
value
)
{
return
Promise
.
reject
(
new
Error
(
'请输入课程名称'
))
return
Promise
.
reject
(
new
Error
(
'请输入课程名称'
));
}
return
Promise
.
resolve
()
}
}
return
Promise
.
resolve
();
};
renderTaskItem
=
(
record
,
index
)
=>
{
renderTaskItem
=
(
record
,
index
)
=>
{
return
(
return
(
...
@@ -314,8 +323,8 @@ class TrainingTask extends React.Component {
...
@@ -314,8 +323,8 @@ class TrainingTask extends React.Component {
name=
{
[
'taskName'
]
}
name=
{
[
'taskName'
]
}
rules=
{
[
rules=
{
[
{
{
validator
:
(
rule
,
value
)
=>
this
.
handleValidatorTaskName
(
rule
,
value
)
validator
:
(
rule
,
value
)
=>
this
.
handleValidatorTaskName
(
rule
,
value
)
,
}
}
,
]
}
>
]
}
>
<
Input
<
Input
className=
'task-name-input'
className=
'task-name-input'
...
@@ -323,10 +332,10 @@ class TrainingTask extends React.Component {
...
@@ -323,10 +332,10 @@ class TrainingTask extends React.Component {
placeholder=
'请输入任务名称(20字以内)'
placeholder=
'请输入任务名称(20字以内)'
maxLength=
{
20
}
maxLength=
{
20
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
this
.
handleRenameTaskName
(
e
,
record
)
this
.
handleRenameTaskName
(
e
,
record
)
;
}
}
}
}
onBlur=
{
(
e
)
=>
{
onBlur=
{
(
e
)
=>
{
this
.
handleTaskNameBlur
(
e
,
record
)
this
.
handleTaskNameBlur
(
e
,
record
)
;
}
}
}
}
/>
/>
</
Form
.
Item
>
</
Form
.
Item
>
...
@@ -346,9 +355,9 @@ class TrainingTask extends React.Component {
...
@@ -346,9 +355,9 @@ class TrainingTask extends React.Component {
<
span
<
span
className=
'operate__item'
className=
'operate__item'
onClick=
{
()
=>
{
onClick=
{
()
=>
{
const
{
dataSource
}
=
this
.
state
const
{
dataSource
}
=
this
.
state
;
record
.
type
=
'input'
record
.
type
=
'input'
;
this
.
setState
({
dataSource
})
this
.
setState
({
dataSource
})
;
}
}
>
}
}
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'text'
>
重命名
</
span
>
<
span
className=
'text'
>
重命名
</
span
>
...
@@ -356,7 +365,7 @@ class TrainingTask extends React.Component {
...
@@ -356,7 +365,7 @@ class TrainingTask extends React.Component {
<
span
<
span
className=
'operate__item'
className=
'operate__item'
onClick=
{
()
=>
{
onClick=
{
()
=>
{
this
.
handleDeleteTask
(
index
)
this
.
handleDeleteTask
(
index
)
;
}
}
>
}
}
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'text'
>
删除
</
span
>
<
span
className=
'text'
>
删除
</
span
>
...
@@ -377,7 +386,7 @@ class TrainingTask extends React.Component {
...
@@ -377,7 +386,7 @@ class TrainingTask extends React.Component {
<
span
<
span
className=
'add-course-btn-disabled'
className=
'add-course-btn-disabled'
onClick=
{
()
=>
{
onClick=
{
()
=>
{
this
.
showRelatedCourseModal
(
index
)
this
.
showRelatedCourseModal
(
index
)
;
}
}
>
}
}
>
<
span
>
+
</
span
>
<
span
>
+
</
span
>
<
span
>
关联课程
</
span
>
<
span
>
关联课程
</
span
>
...
@@ -387,7 +396,7 @@ class TrainingTask extends React.Component {
...
@@ -387,7 +396,7 @@ class TrainingTask extends React.Component {
<
span
<
span
className=
'add-course-btn'
className=
'add-course-btn'
onClick=
{
()
=>
{
onClick=
{
()
=>
{
this
.
showRelatedCourseModal
(
index
)
this
.
showRelatedCourseModal
(
index
)
;
}
}
>
}
}
>
<
span
>
+
</
span
>
<
span
>
+
</
span
>
<
span
>
关联课程
</
span
>
<
span
>
关联课程
</
span
>
...
@@ -398,9 +407,10 @@ class TrainingTask extends React.Component {
...
@@ -398,9 +407,10 @@ class TrainingTask extends React.Component {
</
div
>
</
div
>
)
}
)
}
</
div
>
</
div
>
)
)
;
}
}
;
renderCourseItem
=
(
record
,
index
,
parentIndex
)
=>
{
renderCourseItem
=
(
record
,
index
,
parentIndex
)
=>
{
console
.
log
(
record
);
return
(
return
(
<
div
className=
'plan-course-sort-item'
>
<
div
className=
'plan-course-sort-item'
>
<
div
className=
'course-info'
>
<
div
className=
'course-info'
>
...
@@ -414,8 +424,8 @@ class TrainingTask extends React.Component {
...
@@ -414,8 +424,8 @@ class TrainingTask extends React.Component {
name=
{
[
'courseName'
]
}
name=
{
[
'courseName'
]
}
rules=
{
[
rules=
{
[
{
{
validator
:
(
rule
,
value
)
=>
this
.
handleValidatorCourseName
(
rule
,
value
)
validator
:
(
rule
,
value
)
=>
this
.
handleValidatorCourseName
(
rule
,
value
)
,
}
}
,
]
}
>
]
}
>
<
Input
<
Input
className=
'course-name-input'
className=
'course-name-input'
...
@@ -423,10 +433,10 @@ class TrainingTask extends React.Component {
...
@@ -423,10 +433,10 @@ class TrainingTask extends React.Component {
placeholder=
'请输入课程名称(40字以内)'
placeholder=
'请输入课程名称(40字以内)'
maxLength=
{
40
}
maxLength=
{
40
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
this
.
handleRenameCourseName
(
e
,
record
)
this
.
handleRenameCourseName
(
e
,
record
)
;
}
}
}
}
onBlur=
{
(
e
)
=>
{
onBlur=
{
(
e
)
=>
{
this
.
handleCourseNameBlur
(
e
,
record
)
this
.
handleCourseNameBlur
(
e
,
record
)
;
}
}
}
}
/>
/>
</
Form
.
Item
>
</
Form
.
Item
>
...
@@ -441,6 +451,7 @@ class TrainingTask extends React.Component {
...
@@ -441,6 +451,7 @@ class TrainingTask extends React.Component {
{
record
.
courseState
===
'EXPIRED'
&&
<
span
className=
'icon iconfont tip'
>

</
span
>
}
{
record
.
courseState
===
'EXPIRED'
&&
<
span
className=
'icon iconfont tip'
>

</
span
>
}
{
record
.
courseType
===
'LIVE'
&&
<
span
className=
'course-state'
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
}
{
record
.
courseType
===
'LIVE'
&&
<
span
className=
'course-state'
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
}
{
record
.
courseType
===
'VOICE'
&&
<
span
>
(共
{
record
.
courseChapterNum
||
1
}
小节)
</
span
>
}
</
div
>
</
div
>
<
div
className=
'course-operate'
>
<
div
className=
'course-operate'
>
<
DragHandle
/>
<
DragHandle
/>
...
@@ -448,18 +459,18 @@ class TrainingTask extends React.Component {
...
@@ -448,18 +459,18 @@ class TrainingTask extends React.Component {
<
span
<
span
className=
'operate__item'
className=
'operate__item'
onClick=
{
()
=>
{
onClick=
{
()
=>
{
this
.
handleDeleteCourse
(
parentIndex
,
index
)
this
.
handleDeleteCourse
(
parentIndex
,
index
)
;
}
}
>
}
}
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
<
span
className=
'text'
>
删除
</
span
>
<
span
className=
'text'
>
删除
</
span
>
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
)
)
;
}
}
;
render
()
{
render
()
{
const
{
dataSource
,
selectedTaskIndex
,
relatedCourseModalVisible
}
=
this
.
state
const
{
dataSource
,
selectedTaskIndex
,
relatedCourseModalVisible
}
=
this
.
state
;
console
.
log
(
'dataSource'
,
dataSource
)
console
.
log
(
'dataSource'
,
dataSource
)
;
return
(
return
(
<
div
className=
'training-task'
>
<
div
className=
'training-task'
>
<
SortableTaskContainer
useDragHandle
disableAutoscroll
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onTaskSortEnd
}
className=
'plan-task-sort-container'
>
<
SortableTaskContainer
useDragHandle
disableAutoscroll
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onTaskSortEnd
}
className=
'plan-task-sort-container'
>
...
@@ -494,8 +505,8 @@ class TrainingTask extends React.Component {
...
@@ -494,8 +505,8 @@ class TrainingTask extends React.Component {
/>
/>
)
}
)
}
</
div
>
</
div
>
)
)
;
}
}
}
}
export
default
withRouter
(
TrainingTask
)
export
default
withRouter
(
TrainingTask
)
;
src/modules/plan-manage/modal/UserLearnDetailModal.jsx
View file @
f95a3d4e
/*
* @Author: yuananting
* @Date: 2021-07-05 10:50:30
* @LastEditors: yuananting
* @LastEditTime: 2021-07-05 11:05:31
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
React
from
'react'
;
import
{
Table
,
Modal
,
Input
}
from
'antd'
;
import
{
Table
,
Modal
,
Input
}
from
'antd'
;
import
{
PageControl
}
from
"@/components"
;
import
PlanService
from
'@/domains/plan-domain/planService'
;
import
PlanService
from
'@/domains/plan-domain/planService'
import
User
from
'@/common/js/user'
;
import
User
from
'@/common/js/user'
import
'./UserLearnDetailModal.less'
;
import
'./UserLearnDetailModal.less'
;
import
_
from
"underscore"
;
import
_
from
'underscore'
;
const
{
Search
}
=
Input
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
;
const
CourseType
=
{
const
CourseType
=
{
LIVE
:
{
LIVE
:
{
text
:
"直播课"
text
:
'直播课'
,
},
},
VOICE
:
{
VOICE
:
{
text
:
"线上课"
text
:
'线上课'
,
},
},
RECORD
:
{
RECORD
:
{
text
:
'录播课'
text
:
'录播课'
,
},
PICTURE
:
{
text
:
'图文课'
,
},
},
PICTURE
:{
text
:
'图文课'
}
};
};
const
courseStateShow
=
{
const
courseStateShow
=
{
UN_START
:
{
UN_START
:
{
title
:
"待开播"
,
title
:
'待开播'
,
},
},
STARTING
:
{
STARTING
:
{
title
:
"直播中"
,
title
:
'直播中'
,
},
},
FINISH
:
{
FINISH
:
{
title
:
"回放"
,
title
:
'回放'
,
},
},
EXPIRED
:
{
EXPIRED
:
{
title
:
"未成功开课"
,
title
:
'未成功开课'
,
},
},
};
};
class
UserLearnDetailModal
extends
React
.
Component
{
class
UserLearnDetailModal
extends
React
.
Component
{
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
planDataSource
:{},
planDataSource
:
{},
taskDataSource
:[],
taskDataSource
:
[],
taskSize
:
10
,
taskSize
:
10
,
taskQuery
:
{
taskQuery
:
{
current
:
1
,
current
:
1
,
},
},
taskTotalCount
:
0
,
taskTotalCount
:
0
,
courseDataSource
:[],
courseDataSource
:
[],
storeCustomerName
:
''
,
storeCustomerName
:
''
,
storeCustomerPhone
:
''
storeCustomerPhone
:
''
,
};
};
}
}
componentDidMount
()
{
componentDidMount
()
{
this
.
getPlanCustomerDetail
();
this
.
getPlanCustomerDetail
();
}
}
getPlanCustomerDetail
=
()
=>
{
getPlanCustomerDetail
=
()
=>
{
PlanService
.
getPlanCustomerDetail
({
PlanService
.
getPlanCustomerDetail
({
planId
:
getParameterByName
(
"id"
),
planId
:
getParameterByName
(
'id'
),
storeCustomerId
:
this
.
props
.
storeCustomerId
,
storeCustomerId
:
this
.
props
.
storeCustomerId
,
storeId
:
User
.
getStoreId
()
storeId
:
User
.
getStoreId
(),
}).
then
((
res
)
=>
{
}).
then
((
res
)
=>
{
const
{
const
{
storeCustomerName
,
storeCustomerPhone
,
planName
,
learnFinishPercentage
,
taskCustomerVOList
,
courseMediaVOS
}
=
res
.
result
;
storeCustomerName
,
storeCustomerPhone
,
planName
,
learnFinishPercentage
,
taskCustomerVOList
,
courseMediaVOS
,
}
=
res
.
result
;
let
coverUrl
;
let
coverUrl
;
courseMediaVOS
.
map
((
item
)
=>
{
courseMediaVOS
.
map
((
item
)
=>
{
if
(
item
.
contentType
===
"COVER"
)
{
if
(
item
.
contentType
===
'COVER'
)
{
coverUrl
=
item
.
mediaUrl
;
coverUrl
=
item
.
mediaUrl
;
}
}
return
item
;
return
item
;
})
});
const
planDataSource
=
{
const
planDataSource
=
{
planName
,
planName
,
learnFinishPercentage
,
learnFinishPercentage
,
coverUrl
:
coverUrl
||
defaultCover
coverUrl
:
coverUrl
||
defaultCover
,
}
};
taskCustomerVOList
.
map
((
item
)
=>
{
let
videoClass
=
item
.
courseVOList
&&
item
.
courseVOList
.
filter
((
childItem
,
childIndex
)
=>
{
return
(
childItem
.
courseType
=
'VOICE'
);
});
videoClass
.
map
((
chapterItem
,
chapterIndex
)
=>
{
chapterItem
.
chapterList
=
[
{
chapterName
:
'第一节1'
,
percentage
:
'80%'
,
},
{
chapterName
:
'第一节2'
,
percentage
:
'10%'
,
},
];
return
chapterItem
;
});
return
item
;
});
this
.
setState
({
this
.
setState
({
storeCustomerName
,
storeCustomerName
,
storeCustomerPhone
,
storeCustomerPhone
,
planDataSource
,
planDataSource
,
taskDataSource
:
taskCustomerVOList
taskDataSource
:
taskCustomerVOList
,
})
});
})
});
}
};
parsePlanDataColumns
=
()
=>
{
const
columns
=
[
{
title
:
'培训计划名称'
,
key
:
'planName'
,
dataIndex
:
'planName'
,
width
:
'77%'
,
render
:
(
val
,
record
,
index
)
=>
{
return
(
<
div
className=
'record-name'
>
<
div
className=
'img-con'
>
<
img
src=
{
record
.
coverUrl
}
/>
</
div
>
<
div
>
{
record
.
planName
}
</
div
>
</
div
>
);
},
},
{
title
:
'学习进度'
,
key
:
'learnFinishPercentage'
,
dataIndex
:
'learnFinishPercentage'
,
render
:
(
val
,
record
,
index
)
=>
{
return
<
div
>
{
val
}
%
</
div
>;
},
},
];
return
columns
;
};
parseTaskColumns
=
()
=>
{
parseTaskColumns
=
()
=>
{
const
columns
=
[
const
columns
=
[
...
@@ -95,133 +146,159 @@ class UserLearnDetailModal extends React.Component {
...
@@ -95,133 +146,159 @@ class UserLearnDetailModal extends React.Component {
title
:
'培训任务'
,
title
:
'培训任务'
,
key
:
'taskName'
,
key
:
'taskName'
,
dataIndex
:
'taskName'
,
dataIndex
:
'taskName'
,
render
:
(
val
,
record
,
index
)
=>
{
width
:
'68%'
,
render
:
(
val
,
record
,
index
)
=>
{
return
(
return
(
<
div
className=
"taskName"
>
<
div
className=
'taskName'
>
{
index
+
1
}
.
{
record
.
taskName
}
{
index
+
1
}
.
{
record
.
taskName
}
</
div
>
</
div
>
)
)
;
}
}
,
},
},
{
{
title
:
'学习进度'
,
title
:
'学习进度'
,
key
:
'learnFinishPercentage'
,
key
:
'learnFinishPercentage'
,
dataIndex
:
'learnFinishPercentage'
,
dataIndex
:
'learnFinishPercentage'
,
width
:
167
,
render
:
(
val
,
record
)
=>
{
render
:
(
val
,
record
)
=>
{
return
(
return
<
div
className=
'task-learn-percentage'
>
{
val
===
100
?
<
span
>
已完成
</
span
>
:
<
span
>
{
val
}
%
</
span
>
}
</
div
>;
<
div
className=
"task-learn-percentage"
>
},
{
val
===
100
?<
span
>
已完成
</
span
>:<
span
>
{
val
}
%
</
span
>
}
},
</
div
>
)
}
}
];
];
return
columns
;
return
columns
;
}
};
parseCoursecolumns
=
(
parentIndex
)
=>
{
parseCourseColumns
=
(
parentIndex
)
=>
{
const
columns
=
[
const
columns
=
[
{
{
title
:
'课程'
,
title
:
'课程'
,
key
:
'courseName'
,
key
:
'courseName'
,
dataIndex
:
'courseName'
,
dataIndex
:
'courseName'
,
render
:
(
val
,
record
,
index
)
=>
{
width
:
'70%'
,
render
:
(
val
,
record
,
index
)
=>
{
return
(
return
(
<
div
className=
"course-info"
>
<
div
className=
'course-info'
>
<
div
>
<
div
>
<
span
className=
"course-type"
>
{
CourseType
[
record
.
courseType
].
text
}
</
span
>
<
span
className=
'course-type'
>
{
CourseType
[
record
.
courseType
].
text
}
</
span
>
<
span
>
{
parentIndex
+
1
}
.
{
index
+
1
}
</
span
>
<
span
>
{
parentIndex
+
1
}
.
{
index
+
1
}
</
span
>
</
div
>
</
div
>
<
div
className=
"name-and-state"
>
<
div
className=
'name-and-state'
>
<
span
className=
"course-name"
>
{
record
.
courseName
}
</
span
>
<
span
className=
'course-name'
>
{
record
.
courseName
}
</
span
>
{
record
.
courseType
===
"LIVE"
&&
{
record
.
courseType
===
'LIVE'
&&
<
span
className=
'course-state'
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
}
<
span
className=
"course-state"
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
}
</
div
>
</
div
>
</
div
>
</
div
>
)
)
;
}
}
,
},
},
{
{
title
:
'学习进度'
,
title
:
'学习进度'
,
key
:
'learnFinishPercentage'
,
key
:
'learnFinishPercentage'
,
dataIndex
:
'learnFinishPercentage'
,
dataIndex
:
'learnFinishPercentage'
,
width
:
152
,
render
:
(
val
,
record
)
=>
{
render
:
(
val
,
record
)
=>
{
return
(
return
<
div
className=
'course-learn-percentage'
>
{
record
.
learnState
===
'FINISH'
?
<
span
>
已完成
</
span
>
:
<
span
>
{
val
}
%
</
span
>
}
</
div
>;
<
div
className=
"course-learn-percentage"
>
},
{
record
.
learnState
===
"FINISH"
?<
span
>
已完成
</
span
>:<
span
>
{
val
}
%
</
span
>
}
},
</
div
>
)
}
}
];
];
return
columns
;
return
columns
;
}
};
parseChapterColumns
=
(
chapterIndex
)
=>
{
const
columns
=
[
{
title
:
'课节名称'
,
key
:
'chapterName'
,
dataIndex
:
'chapterName'
,
width
:
'80%'
,
},
{
title
:
'学习进度'
,
key
:
'percentage'
,
dataIndex
:
'percentage'
,
},
];
return
columns
;
};
render
()
{
render
()
{
const
{
storeCustomerName
,
storeCustomerPhone
,
planDataSource
,
taskDataSource
,
taskQuery
,
taskTotalCount
}
=
this
.
state
;
const
{
storeCustomerName
,
storeCustomerPhone
,
planDataSource
,
taskDataSource
,
taskQuery
,
taskTotalCount
}
=
this
.
state
;
const
{
visible
}
=
this
.
props
;
const
{
visible
}
=
this
.
props
;
return
(
return
(
<
Modal
<
Modal
title=
"学员学习详情"
title=
'学员学习详情'
onCancel=
{
this
.
props
.
onClose
}
onCancel=
{
this
.
props
.
onClose
}
onOk=
{
this
.
props
.
onClose
}
onOk=
{
this
.
props
.
onClose
}
maskClosable=
{
false
}
maskClosable=
{
false
}
visible=
{
visible
}
visible=
{
visible
}
className=
"user-Learn-modal"
className=
'user-Learn-modal'
closable=
{
true
}
closable=
{
true
}
width=
{
800
}
width=
{
800
}
closeIcon=
{
<
span
className=
"icon iconfont modal-close-icon"
>

</
span
>
}
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
>
>
<
div
className=
'customer-info'
>
<
div
className=
"customer-info"
>
<
span
className=
'customer-name'
>
<
span
className=
"customer-name"
>
<
span
>
学员:
</
span
>
<
span
>
学员:
</
span
>
<
span
>
{
storeCustomerName
}
</
span
>
<
span
>
{
storeCustomerName
}
</
span
>
</
span
>
</
span
>
<
span
className=
"customer-phone"
>
<
span
className=
'customer-phone'
>
<
span
>
手机号:
</
span
>
<
span
>
手机号:
</
span
>
<
span
>
{
storeCustomerPhone
}
</
span
>
<
span
>
{
storeCustomerPhone
}
</
span
>
</
span
>
</
span
>
</
div
>
</
div
>
<
div
className=
"plan-instro"
>
<
div
className=
'table-box'
>
<
div
className=
"img-con"
>
<
Table
className=
'plan-table'
dataSource=
{
[
planDataSource
]
}
columns=
{
this
.
parsePlanDataColumns
()
}
pagination=
{
false
}
/>
<
img
src=
{
planDataSource
.
coverUrl
}
/>
</
div
>
<
div
>
<
div
className=
"plan-name"
>
{
planDataSource
.
planName
}
</
div
>
<
div
className=
"task-learn-percentage"
>
<
span
>
学习进度:
{
planDataSource
.
learnFinishPercentage
}
%
</
span
>
</
div
>
</
div
>
</
div
>
<
div
>
<
Table
<
Table
className=
'task-table'
rowKey=
{
(
record
)
=>
record
.
taskId
}
rowKey=
{
(
record
)
=>
record
.
taskId
}
className=
"task-table"
dataSource=
{
taskDataSource
}
dataSource=
{
taskDataSource
}
columns=
{
this
.
parseTaskColumns
()
}
columns=
{
this
.
parseTaskColumns
()
}
pagination=
{
false
}
pagination=
{
false
}
expandedRowRender=
{
(
record
,
index
)
=>
{
expandedRowRender=
{
(
record
,
index
)
=>
{
if
(
!
record
.
courseVOList
)
{
if
(
!
record
.
courseVOList
)
{
return
return
;
}
}
if
(
record
.
courseVOList
.
length
!==
0
){
if
(
record
.
courseVOList
.
length
!==
0
)
{
return
<
div
>
return
(
<
div
>
<
Table
<
Table
showHeader=
{
false
}
pagination=
{
false
}
pagination=
{
false
}
dataSource=
{
record
.
courseVOList
}
dataSource=
{
record
.
courseVOList
}
columns=
{
this
.
parseCoursecolumns
(
index
)
}
columns=
{
this
.
parseCourseColumns
(
index
)
}
className=
"child-table"
className=
'child-table'
expandedRowRender=
{
(
chapterRecord
,
chapterIndex
)
=>
{
if
(
!
chapterRecord
.
chapterList
)
{
return
;
}
if
(
chapterRecord
.
chapterList
.
length
!==
0
)
{
return
(
<
div
>
<
Table
showHeader=
{
false
}
pagination=
{
false
}
dataSource=
{
chapterRecord
.
chapterList
}
columns=
{
this
.
parseChapterColumns
(
chapterIndex
)
}
className=
'chapter-table'
/>
</
div
>
);
}
}
}
/>
/>
</
div
>
</
div
>
);
}
}
}
rowClassName=
{
(
record
,
index
)
=>
{
if
(
index
%
2
===
0
)
{
return
'odd-row'
;
}
else
{
return
'even-row'
;
}
}
}
}
}
}
rowClassName=
{
(
record
,
index
)
=>
{
if
(
index
%
2
===
0
){
return
'odd-row'
}
else
{
return
'even-row'
}}
}
/>
/>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
)
)
;
}
}
}
}
...
...
src/modules/plan-manage/modal/UserLearnDetailModal.less
View file @
f95a3d4e
.user-Learn-modal{
.user-Learn-modal {
.customer-info {
.customer-info{
margin-bottom: 16px;
margin-bottom:16px;
.customer-name {
.customer-name{
font-size: 14px;
font-size:14px;
color: #333;
color:#333;
margin-right: 32px;
margin-right:32px;
}
}
.customer-phone
{
.customer-phone
{
font-size:
14px;
font-size:
14px;
color:
#333;
color:
#333;
}
}
}
}
.plan-instro
{
.plan-instro
{
display: flex;
display: flex;
align-items: center;
align-items: center;
margin-bottom:
16px;
margin-bottom:
16px;
.img-con
{
.img-con
{
margin-right:
8px;
margin-right:
8px;
img
{
img
{
width: 97px;
width: 97px;
height: 54px;
height: 54px;
display: inline-block;
display: inline-block;
border-radius:4px;
border-radius: 4px;
}
}
.plan-name{
color:#333;
font-size:16px;
}
.plan-learn-percentage{
color:#333;
font-size:14px;
}
}
.task-table{
.ant-table-thead{
tr {
th{
padding:9px 16px;
}
}
}
}
.plan-name {
color: #333;
font-size: 16px;
}
}
tr{
.plan-learn-percentage {
td{
color: #333;
padding:14px 16px;
font-size: 14px;
}
}
.taskName{
color:#333;
font-size:14px;
}
.task-learn-percentage{
color:#333;
font-size:14px;
}
.course-info{
display:flex;
margin-left:57px;
align-items: center;
.course-type{
font-size:11px;
color:#666666;
padding:0px 6px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
line-height: 16px;
}
.name-and-state{
flex:1;
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
}
.course-state{
color:#999;
font-size:14px;
}
}
}
}
.table-box {
.child-table {
margin-left: 40px;
tr > td {
&:first-child {
padding-right: 0 !important;
}
}
.ant-table-expanded-row{
&:nth-child(2) {
td{
padding-left: 0 !important;
padding:0 16px;
}
}
}
}
.ant-table-content{
.course-info {
border:1px solid #e8e8e8;
display: flex;
tr{
.course-type {
td{
border-radius: 2px;
border:none;
border: 1px solid #999999;
}
font-size: 11px;
.child-table{
color: #666666;
padding: 1px 8px;
.ant-table-content{
margin-right: 6px;
border:none;
thead{
display:none;
}
tbody tr {
td{
border-bottom:none;
padding:14px 16px;
}
}
}
}
}
.odd-row{
background:transparent;
td{
background: #FFF;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FFF;
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
.even-row{
background:transparent;
td{
background: #FAFAFA;
}
& + .ant-table-expanded-row{
background:transparent;
td{
background: #FAFAFA;
}
}
}
&:hover{
& + .ant-table-expanded-row{
background:transparent;
td{
background: #F3f6fa !important;
}
}
}
}
.record-name {
display: flex;
.img-con {
margin-right: 8px;
img {
width: 97px;
height: 54px;
border-radius: 4px;
}
}
}
}
}
}
...
...
src/modules/plan-manage/modal/relatedCourseModal.jsx
View file @
f95a3d4e
/*
* @Author: yuananting
* @Date: 2021-07-05 10:50:10
* @LastEditors: yuananting
* @LastEditTime: 2021-07-05 11:02:28
* @Description: 描述一下咯
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
React
from
'react'
;
import
_
from
'underscore'
;
import
_
from
'underscore'
;
import
{
Table
,
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
'antd'
;
import
{
Table
,
Radio
,
Tabs
,
Modal
,
Input
,
message
,
Button
,
Tooltip
}
from
'antd'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
import
{
PageControl
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
User
from
'@/common/js/user'
;
import
User
from
'@/common/js/user'
;
...
@@ -79,11 +87,11 @@ class SelectOperatorModal extends React.Component {
...
@@ -79,11 +87,11 @@ class SelectOperatorModal extends React.Component {
selectVideo
:
{
selectVideo
:
{
external
:
[],
external
:
[],
internal
:
[],
internal
:
[],
},
//弹窗内已选择的
视频
课程
},
//弹窗内已选择的
线上
课程
currentVideoCourseListData
:
{
currentVideoCourseListData
:
{
external
:
[],
external
:
[],
internal
:
[],
internal
:
[],
},
//页面中已关联的
视频
课程
},
//页面中已关联的
线上
课程
pictureDataSource
:
[],
pictureDataSource
:
[],
pictureSize
:
10
,
pictureSize
:
10
,
...
@@ -408,12 +416,13 @@ class SelectOperatorModal extends React.Component {
...
@@ -408,12 +416,13 @@ class SelectOperatorModal extends React.Component {
},
},
},
},
{
{
title
:
'课
程时长
'
,
title
:
'课
节数
'
,
key
:
'course
Time
'
,
key
:
'course
ChapterNum
'
,
dataIndex
:
'course
Time
'
,
dataIndex
:
'course
ChapterNum
'
,
width
:
'20%'
,
width
:
'20%'
,
align
:
'right'
,
render
:
(
val
,
record
)
=>
{
render
:
(
val
,
record
)
=>
{
return
<
span
className=
'course-status'
>
{
dealTimeDuration
(
record
.
videoDuration
)
}
</
span
>;
return
<
span
>
{
val
||
1
}
</
span
>;
},
},
},
},
{
{
...
@@ -734,11 +743,7 @@ class SelectOperatorModal extends React.Component {
...
@@ -734,11 +743,7 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
</
div
>
</
div
>
<
div
>
<
div
>
<
XMTable
<
Table
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
liveCourseId
}
rowKey=
{
(
record
)
=>
record
.
liveCourseId
}
dataSource=
{
liveDataSource
}
dataSource=
{
liveDataSource
}
columns=
{
this
.
parseLiveColumns
()
}
columns=
{
this
.
parseLiveColumns
()
}
...
@@ -829,11 +834,7 @@ class SelectOperatorModal extends React.Component {
...
@@ -829,11 +834,7 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
</
div
>
</
div
>
<
div
>
<
div
>
<
XMTable
<
Table
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
id
}
rowKey=
{
(
record
)
=>
record
.
id
}
dataSource=
{
videoDataSource
[
videoCourseDivision
]
}
dataSource=
{
videoDataSource
[
videoCourseDivision
]
}
columns=
{
this
.
parseVideoColumns
()
}
columns=
{
this
.
parseVideoColumns
()
}
...
@@ -928,11 +929,7 @@ class SelectOperatorModal extends React.Component {
...
@@ -928,11 +929,7 @@ class SelectOperatorModal extends React.Component {
</
div
>
</
div
>
</
div
>
</
div
>
<
div
>
<
div
>
<
XMTable
<
Table
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
,
}
}
rowKey=
{
(
record
)
=>
record
.
id
}
rowKey=
{
(
record
)
=>
record
.
id
}
dataSource=
{
pictureDataSource
}
dataSource=
{
pictureDataSource
}
columns=
{
this
.
parsePictureColumns
()
}
columns=
{
this
.
parsePictureColumns
()
}
...
...
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