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
39be164c
Commit
39be164c
authored
Jul 29, 2021
by
guomingpang
Browse files
Options
Browse Files
Download
Plain Diff
feat:课程管理5级分类,学院装修banner尺寸修改
parents
5d6962e4
95bec18d
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
2544 additions
and
2770 deletions
+2544
-2770
src/index.html
+2
-2
src/modules/common/CourseCatalogSelect.jsx
+61
-0
src/modules/common/index.js
+2
-0
src/modules/course-manage/components/AddLiveBasic.jsx
+68
-105
src/modules/course-manage/components/LiveCourseList.jsx
+172
-172
src/modules/course-manage/graphics-course/AddGraphicsCourse.jsx
+173
-246
src/modules/course-manage/graphics-course/components/GraphicsCourseList.jsx
+10
-13
src/modules/course-manage/modal/ChargeExplainModal.jsx
+45
-61
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
+270
-262
src/modules/course-manage/offline-course/components/OfflineCourseFilter.jsx
+2
-2
src/modules/course-manage/offline-course/components/OfflineCourseFilter.less
+9
-9
src/modules/course-manage/offline-course/components/OfflineCourseList.jsx
+119
-119
src/modules/course-manage/offline-course/components/OfflineCourseOpt.jsx
+11
-11
src/modules/course-manage/offline-course/index.jsx
+25
-33
src/modules/course-manage/offline-course/modal/PreviewOfflineModal.jsx
+83
-82
src/modules/course-manage/video-course/AddVideoCourse.jsx
+372
-399
src/modules/course-manage/video-course/components/VideoCourseList.jsx
+136
-150
src/modules/home/Home.jsx
+71
-84
src/modules/prepare-lesson/components/DiskList.jsx
+29
-44
src/modules/prepare-lesson/index.jsx
+58
-66
src/modules/resource-disk/components/FolderList.jsx
+441
-443
src/modules/resource-disk/index.jsx
+22
-31
src/modules/store-manage/StoreDecorationPage.less
+9
-10
src/modules/store-manage/StoreH5DecorationTab.jsx
+153
-189
src/modules/store-manage/StoreWebDecorationTab.jsx
+154
-190
src/routes/config/mainRoutes.tsx
+34
-34
src/routes/config/menuList.tsx
+5
-5
src/routes/config/redirectRoutes.tsx
+8
-8
No files found.
src/index.html
View file @
39be164c
...
...
@@ -13,14 +13,13 @@
<link
rel=
"icon"
href=
""
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
/>
<meta
name=
"theme-color"
content=
"#000000"
/>
<title>
小麦企学院_搭建数字化企业大学
</title>
<meta
name=
"description"
content=
"小麦企学院,一站式企业培训数字化服务商,通过“工具+内容”,帮助企业快速从0到1搭建数字化培训体系,并让整个培训过程可视化,降低培训成本,提升培训效率。"
/>
<meta
name=
"keywords"
content=
"
企业培训,员工培训,企业大学,内训,外训,培训计划,企培,企训,资料云盘,定制培训计划,学习数据,资料共享,数字化,培训saas,,企业学院平台,酷学院,小鹅通,云学堂,时代光华,云课堂,魔学院,云大学,米知云
"
content=
"
小麦企学院,企业培训,员工培训,企业大学,企业内训,企业外训,培训计划,培训素材,企培,企训,素材库,培训课程,培训任务,直播课,线上课,图文课,线下活动,知识库,作业,考试,排行榜,培训类别管理,定制培训计划,管理数据,学习数据,企学院,资料共享,培训数字化,数字化培训,培训工具,在线培训,线上培训,培训saas,培训管理,企业微信培训,对客培训,客户培训,直播培训,互联网培训,新员工培训,管理培训,管理者培训,工人培训,制造业培训,餐饮培训,服务业培训,零售培训,门店培训,工厂培训,车间培训,培训补贴,人事培训,财务培训,职场培训,企业学院平台,教育企业学院,教育企业平台,教育平台学院,企业学习,酷学院,小鹅通,企业学院,云学堂,时代光华,云课堂,魔学院,云大学,米知云,授课学堂
"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link
rel=
"shortcut icon"
href=
"https://image.xiaomaiketang.com/xm/c4KiP2epBP.png"
/>
...
...
@@ -41,6 +40,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>
小麦企学院
</title>
<script
type=
"text/javascript"
src=
"https://image.xiaomaiketang.com/xm/iscroll-zoom-min.js"
></script>
<script
type=
"text/javascript"
src=
"https://image.xiaomaiketang.com/xm/hammer.min.js"
></script>
<script
type=
"text/javascript"
src=
"https://image.xiaomaiketang.com/xm/lrz.all.bundle.js"
></script>
...
...
src/modules/common/CourseCatalogSelect.jsx
0 → 100644
View file @
39be164c
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
TreeSelect
}
from
'antd'
import
User
from
'@/common/js/user'
import
Service
from
'@/common/js/service'
function
CourseCatalogSelect
(
props
)
{
let
{
showSearch
=
true
,
value
=
''
,
treeNodeFilterProp
=
'title'
,
style
=
{
width
:
240
},
dropdownStyle
=
{
maxHeight
:
300
,
overflow
:
'auto'
},
placeholder
=
'请选择课程类型'
,
allowClear
=
true
,
onChange
=
()
=>
{},
}
=
props
let
[
courseCatalogList
,
setCourseCatalogList
]
=
useState
([])
useEffect
(()
=>
{
//获取分类列表
function
getCourseCatalogList
()
{
Service
.
Hades
(
'public/hades/queryCategoryTree'
,
{
source
:
0
,
tenantId
:
User
.
getStoreId
(),
count
:
false
,
userId
:
User
.
getUserId
()
}).
then
((
res
)
=>
{
const
{
categoryList
=
[]
}
=
res
.
result
let
list
=
renderTreeNodes
(
categoryList
)
setCourseCatalogList
(
list
)
})
}
function
renderTreeNodes
(
list
)
{
let
newTreeData
=
list
.
map
((
item
)
=>
{
item
.
title
=
item
.
categoryName
item
.
value
=
item
.
id
item
.
key
=
item
.
id
console
.
log
(
value
,
item
.
value
,
value
===
item
.
value
,
'item.categoryName'
)
if
(
item
.
sonCategoryList
)
{
item
.
children
=
renderTreeNodes
(
item
.
sonCategoryList
)
}
return
item
})
return
newTreeData
}
getCourseCatalogList
()
},
[])
return
(
<
TreeSelect
treeNodeLabelProp=
'categoryName'
showSearch=
{
showSearch
}
treeNodeFilterProp=
{
treeNodeFilterProp
}
style=
{
style
}
value=
{
value
}
dropdownStyle=
{
dropdownStyle
}
treeData=
{
courseCatalogList
}
placeholder=
{
placeholder
}
allowClear=
{
allowClear
}
treeDefaultExpandAll
onChange=
{
(
value
,
label
)
=>
{
onChange
(
value
,
label
)
}
}
/>
)
}
export
default
CourseCatalogSelect
src/modules/common/index.js
0 → 100644
View file @
39be164c
export
{
default
as
RangePicker
}
from
'./DateRangePicker'
export
{
default
as
CourseCatalogSelect
}
from
'./CourseCatalogSelect'
src/modules/course-manage/components/AddLiveBasic.jsx
View file @
39be164c
...
...
@@ -6,25 +6,21 @@
* @Description: 新建/编辑直播课-基本信息
*/
import
React
from
'react'
;
import
{
Input
,
Button
,
message
,
Cascader
,
Modal
}
from
'antd'
;
import
UploadOss
from
'@/core/upload'
;
import
{
ImgCutModalNew
}
from
'@/components'
;
import
StoreService
from
'@/domains/store-domain/storeService'
;
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
;
import
Upload
from
'@/core/upload'
;
import
Cropper
from
'react-cropper'
;
import
React
from
'react'
import
{
Input
,
Button
,
message
,
Cascader
}
from
'antd'
import
{
CourseCatalogSelect
}
from
'@/modules/common'
import
StoreService
from
'@/domains/store-domain/storeService'
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
import
Upload
from
'@/core/upload'
import
ImgClipModal
from
'@/components/ImgClipModal'
import
'cropperjs/dist/cropper.css'
;
import
'./AddLiveBasic.less'
;
import
'cropperjs/dist/cropper.css'
import
'./AddLiveBasic.less'
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
;
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
};
let
cutFlag
=
false
;
let
timer
=
null
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
}
class
AddLiveBasic
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
imageFile
:
null
,
showCutModal
:
false
,
...
...
@@ -32,63 +28,50 @@ class AddLiveBasic extends React.Component {
showSelectFileModal
:
false
,
cutImageBlob
:
null
,
hasImgReady
:
false
,
// 图片是否上传成功
cropperInstace
:
null
cropperInstace
:
null
,
}
}
componentWillUnmount
()
{}
componentDidMount
()
{
this
.
getCourseCatalogList
()
;
this
.
getCourseCatalogList
()
}
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
this
.
setState
({
courseCatalogList
:
res
.
result
.
records
,
})
;
})
;
})
})
}
// 使用默认封面图
handleResetCoverUrl
=
()
=>
{
const
{
data
:
{
coverUrl
},
}
=
this
.
props
;
const
isDefaultCover
=
coverUrl
===
defaultCover
;
}
=
this
.
props
const
isDefaultCover
=
coverUrl
===
defaultCover
// 如果已经是默认图的话,不做任何任何处理
if
(
isDefaultCover
)
return
;
message
.
success
(
'已替换为默认图'
)
;
this
.
props
.
onChange
(
'coverUrl'
,
defaultCover
)
;
if
(
isDefaultCover
)
return
message
.
success
(
'已替换为默认图'
)
this
.
props
.
onChange
(
'coverUrl'
,
defaultCover
)
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'coverId'
,
null
);
},
1000
);
};
this
.
props
.
onChange
(
'coverId'
,
null
)
},
1000
)
}
handleChangeCatalogList
=
(
value
)
=>
{
this
.
props
.
onChange
(
'categoryId'
,
value
)
}
catalogChange
=
(
value
)
=>
{
const
changeValueLength
=
value
.
length
;
switch
(
changeValueLength
)
{
case
1
:
this
.
props
.
onChange
(
'categoryId'
,
value
[
0
]);
break
;
case
2
:
this
.
props
.
onChange
(
'categoryId'
,
value
[
1
]);
break
;
default
:
this
.
props
.
onChange
(
'categoryId'
,
null
);
break
;
}
};
handleSelectCover
=
(
file
)
=>
{
this
.
setState
({
visible
:
true
,
imageFile
:
file
})
;
imageFile
:
file
,
})
}
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
const
{
choosedBannerId
}
=
this
.
state
;
getSignature
=
(
blob
)
=>
{
Upload
.
uploadBlobToOSS
(
blob
,
'cover'
+
new
Date
().
valueOf
(),
null
,
'signInfo'
).
then
((
signInfo
)
=>
{
this
.
setState
(
{
...
...
@@ -97,26 +80,25 @@ class AddLiveBasic extends React.Component {
visible
:
false
,
},
()
=>
this
.
updateCover
()
)
;
})
;
}
;
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
)
})
}
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
this
.
setState
({
showSelectFileModal
:
false
,
})
;
this
.
props
.
onChange
(
'coverUrl'
,
coverClicpPath
)
;
})
this
.
props
.
onChange
(
'coverUrl'
,
coverClicpPath
)
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'coverId'
,
coverId
)
;
},
1000
)
;
}
;
this
.
props
.
onChange
(
'coverId'
,
coverId
)
},
1000
)
}
render
()
{
const
{
showCutModal
,
imageFile
,
courseCatalogList
,
showSelectFileModal
,
visible
,
cutImageBlob
,
hasImgReady
}
=
this
.
state
;
const
{
data
,
pageType
,
isEdit
}
=
this
.
props
;
const
{
courseName
,
categoryName
,
coverUrl
}
=
data
;
const
fileName
=
''
;
const
{
imageFile
,
showSelectFileModal
,
visible
}
=
this
.
state
const
{
data
}
=
this
.
props
const
{
courseName
,
coverUrl
,
categoryId
}
=
data
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
const
isDefaultCover
=
coverUrl
===
defaultCover
return
(
<
div
className=
'add-live__basic-info'
>
<
div
className=
'course-name'
>
...
...
@@ -129,7 +111,7 @@ class AddLiveBasic extends React.Component {
maxLength=
{
40
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
{
this
.
props
.
onChange
(
'courseName'
,
e
.
target
.
value
)
;
this
.
props
.
onChange
(
'courseName'
,
e
.
target
.
value
)
}
}
/>
</
div
>
...
...
@@ -142,7 +124,7 @@ class AddLiveBasic extends React.Component {
onClick=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
true
,
})
;
})
}
}
>
上传图片
</
Button
>
...
...
@@ -161,40 +143,14 @@ class AddLiveBasic extends React.Component {
<
span
className=
'label'
>
<
span
className=
'require'
>
*
</
span
>
课程分类:
</
span
>
{
pageType
===
'add'
&&
(
<
Cascader
options=
{
courseCatalogList
}
displayRender=
{
(
label
)
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
'请选择课程分类'
suffixIcon=
{
<
span
className=
'icon iconfont'
style=
{
{
fontSize
:
'12px'
,
color
:
'#BFBFBF'
}
}
>

</
span
>
}
/>
)
}
{
pageType
===
'edit'
&&
categoryName
&&
(
<
Cascader
disabled=
{
!
isEdit
?
true
:
false
}
defaultValue=
{
[
categoryName
]
}
options=
{
courseCatalogList
}
displayRender=
{
(
label
)
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
'请选择课程分类'
suffixIcon=
{
<
span
className=
'icon iconfont'
style=
{
{
fontSize
:
'12px'
,
color
:
'#BFBFBF'
}
}
>

</
span
>
}
/>
)
}
<
CourseCatalogSelect
value=
{
categoryId
}
onChange=
{
(
value
,
label
)
=>
{
this
.
handleChangeCatalogList
(
value
,
label
)
}
}
/>
</
div
>
{
showSelectFileModal
&&
{
showSelectFileModal
&&
(
<
SelectPrepareFileModal
key=
'basic'
operateType=
'select'
...
...
@@ -204,17 +160,24 @@ class AddLiveBasic extends React.Component {
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectFileModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
;
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
}
{
visible
&&
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
});}
}
/>
}
)
}
{
visible
&&
(
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
</
div
>
)
;
)
}
}
export
default
AddLiveBasic
;
export
default
AddLiveBasic
src/modules/course-manage/components/LiveCourseList.jsx
View file @
39be164c
...
...
@@ -6,25 +6,25 @@
* @Description: 大班直播、互动班课的直播课列表
*/
import
User
from
'@/common/js/user'
;
import
college
from
'@/common/lottie/college'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
import
DownloadLiveModal
from
'@/components/DownloadLiveModal'
;
import
BaseService
from
'@/domains/basic-domain/baseService'
;
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
{
QuestionCircleOutlined
}
from
'@ant-design/icons'
;
import
{
Dropdown
,
message
,
Modal
,
Switch
,
Tooltip
}
from
'antd'
;
import
React
from
'react'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
_
from
'underscore'
;
import
DataList
from
'../DataList/DataList'
;
import
ManageCoursewareModal
from
'../modal/ManageCoursewareModal'
;
import
RelatedPlanModal
from
'../modal/RelatedPlanModal'
;
import
ShareLiveModal
from
'../modal/ShareLiveModal'
;
import
'./LiveCourseList.less'
;
import
User
from
'@/common/js/user'
import
college
from
'@/common/lottie/college'
import
{
PageControl
,
XMTable
}
from
'@/components'
import
DownloadLiveModal
from
'@/components/DownloadLiveModal'
import
BaseService
from
'@/domains/basic-domain/baseService'
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
import
CourseService
from
'@/domains/course-domain/CourseService'
import
{
QuestionCircleOutlined
}
from
'@ant-design/icons'
import
{
Dropdown
,
message
,
Modal
,
Switch
,
Tooltip
}
from
'antd'
import
React
from
'react'
import
{
Route
,
withRouter
}
from
'react-router-dom'
import
_
from
'underscore'
import
DataList
from
'../DataList/DataList'
import
ManageCoursewareModal
from
'../modal/ManageCoursewareModal'
import
RelatedPlanModal
from
'../modal/RelatedPlanModal'
import
ShareLiveModal
from
'../modal/ShareLiveModal'
import
'./LiveCourseList.less'
const
{
confirm
}
=
Modal
;
const
{
confirm
}
=
Modal
const
courseStateShow
=
{
UN_START
:
{
code
:
1
,
...
...
@@ -46,33 +46,33 @@ const courseStateShow = {
title
:
'未成功开课'
,
color
:
'#999'
,
},
}
;
}
class
LiveCourseList
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
columns
:
[],
openDownloadModal
:
false
,
url
:
''
,
RelatedPlanModalVisible
:
false
,
selectPlanList
:
{},
}
;
}
}
componentWillMount
()
{
this
.
parseColumns
()
;
this
.
parseColumns
()
}
componentDidMount
()
{
this
.
getDownloadVersion
()
;
this
.
getDownloadVersion
()
}
// 显示分享弹窗
handleShowShareModal
=
(
item
,
needStr
=
false
)
=>
{
const
{
liveCourseId
}
=
item
;
const
{
liveCourseId
}
=
item
const
htmlUrl
=
`
${
LIVE_SHARE
}
live_detail/
${
liveCourseId
}
?id=
${
User
.
getStoreId
()}
`
;
const
longUrl
=
htmlUrl
;
console
.
log
(
'htmlUrl'
,
htmlUrl
,
longUrl
)
;
const
htmlUrl
=
`
${
LIVE_SHARE
}
live_detail/
${
liveCourseId
}
?id=
${
User
.
getStoreId
()}
`
const
longUrl
=
htmlUrl
console
.
log
(
'htmlUrl'
,
htmlUrl
,
longUrl
)
const
shareData
=
{
...
item
,
longUrl
}
;
const
shareData
=
{
...
item
,
longUrl
}
const
shareLiveModal
=
(
<
ShareLiveModal
needStr=
{
needStr
}
...
...
@@ -82,45 +82,45 @@ class LiveCourseList extends React.Component {
close=
{
()
=>
{
this
.
setState
({
shareLiveModal
:
null
,
})
;
localStorage
.
setItem
(
'largeLiveCourseItem'
,
''
)
;
})
localStorage
.
setItem
(
'largeLiveCourseItem'
,
''
)
}
}
/>
)
;
)
this
.
setState
({
shareLiveModal
})
;
}
;
this
.
setState
({
shareLiveModal
})
}
//改变上架状态
changeShelfState
=
(
index
,
item
,
checked
)
=>
{
let
_shelfState
=
checked
?
'YES'
:
'NO'
;
let
_shelfState
=
checked
?
'YES'
:
'NO'
const
params
=
{
liveCourseId
:
item
.
liveCourseId
,
shelfState
:
_shelfState
,
}
;
}
CourseService
.
turnOnOrOffLiveCloudCourse
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
if
(
_shelfState
===
'YES'
)
{
message
.
success
(
'已开启展示'
)
;
message
.
success
(
'已开启展示'
)
}
else
{
message
.
success
(
'已取消展示'
)
;
message
.
success
(
'已取消展示'
)
}
this
.
props
.
changeShelfState
(
index
,
_shelfState
)
;
this
.
props
.
changeShelfState
(
index
,
_shelfState
)
}
})
;
}
;
})
}
// 前往上课数据页面
handleLinkToClassData
=
(
item
)
=>
{
const
{
match
}
=
this
.
props
;
const
{
match
}
=
this
.
props
window
.
RCHistory
.
push
({
pathname
:
`
${
match
.
url
}
/live-course-data?type=large&id=
${
item
.
liveCourseId
}
`
,
})
;
}
;
})
}
parseColumns
=
()
=>
{
let
columns
;
const
userRole
=
User
.
getUserRole
()
;
let
columns
const
userRole
=
User
.
getUserRole
()
if
(
userRole
!==
'CloudLecturer'
)
{
columns
=
[
{
...
...
@@ -130,15 +130,15 @@ class LiveCourseList extends React.Component {
fixed
:
'left'
,
dataIndex
:
'courseName'
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
;
let
hasCover
=
false
return
(
<
div
className=
'record__item'
>
{
record
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
'COVER'
)
{
hasCover
=
true
;
return
<
img
key=
{
item
.
mediaContent
+
index
}
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
;
hasCover
=
true
return
<
img
key=
{
item
.
mediaContent
+
index
}
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
}
else
{
return
null
;
return
null
}
})
}
{
!
hasCover
&&
<
img
className=
'course-cover'
src=
{
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
}
alt=
''
/>
}
...
...
@@ -189,7 +189,7 @@ class LiveCourseList extends React.Component {
<
span
key=
{
item
.
adminId
+
index
}
>
{
item
.
adminName
}
{
index
<
record
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
span
>
</
Tooltip
>
...
...
@@ -202,7 +202,7 @@ class LiveCourseList extends React.Component {
<
span
>
{
item
.
adminName
}
{
index
<
record
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
span
>
</
Otherwise
>
...
...
@@ -211,7 +211,7 @@ class LiveCourseList extends React.Component {
</
div
>
</
div
>
</
div
>
)
;
)
},
},
{
...
...
@@ -220,7 +220,7 @@ class LiveCourseList extends React.Component {
key
:
'couseCatalog'
,
dataIndex
:
'couseCatalog'
,
render
:
(
val
,
item
)
=>
{
return
<
div
className=
'categoryName'
>
{
item
.
category
Name
}
</
div
>;
return
<
div
className=
'categoryName'
>
{
item
.
category
SonName
}
</
div
>
},
},
{
...
...
@@ -236,11 +236,11 @@ class LiveCourseList extends React.Component {
this
.
setState
({
editData
:
item
,
openCoursewareModal
:
true
,
})
;
})
}
}
>
{
item
.
courseDocumentCount
}
个
</
span
>
)
;
)
},
},
{
...
...
@@ -253,11 +253,11 @@ class LiveCourseList extends React.Component {
<
span
className=
'iconfont icon quota-icon'
onClick=
{
()
=>
{
this
.
handleLinkToClassData
(
item
)
;
this
.
handleLinkToClassData
(
item
)
}
}
>

</
span
>
)
;
)
},
},
{
...
...
@@ -289,7 +289,7 @@ class LiveCourseList extends React.Component {
defaultChecked=
{
item
.
shelfState
===
'YES'
?
true
:
false
}
onChange=
{
(
checked
)
=>
this
.
changeShelfState
(
index
,
item
,
checked
)
}
/>
)
;
)
},
},
{
...
...
@@ -300,7 +300,7 @@ class LiveCourseList extends React.Component {
sorter
:
true
,
render
:
(
val
,
item
)
=>
{
// -29000:与后端约定 在初始化学院时,创建时间(标志位-29000)默认展示为'-'
return
<
span
style=
{
{
whiteSpace
:
'nowrap'
}
}
>
{
val
===
-
29000
?
'-'
:
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
;
return
<
span
style=
{
{
whiteSpace
:
'nowrap'
}
}
>
{
val
===
-
29000
?
'-'
:
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
},
},
{
...
...
@@ -319,7 +319,7 @@ class LiveCourseList extends React.Component {
<
span
>
{
item
.
planName
}
{
index
<
record
.
relatedPlanList
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
Tooltip
>
</
When
>
...
...
@@ -328,7 +328,7 @@ class LiveCourseList extends React.Component {
</
Otherwise
>
</
Choose
>
</
div
>
)
;
)
},
},
{
...
...
@@ -347,7 +347,7 @@ class LiveCourseList extends React.Component {
key=
'enter_live_room1'
className=
'operate__item'
onClick=
{
()
=>
{
this
.
handleEnterLiveRoom
(
item
)
;
this
.
handleEnterLiveRoom
(
item
)
}
}
>
进入直播间
</
div
>
...
...
@@ -363,7 +363,7 @@ class LiveCourseList extends React.Component {
key=
'view_play_back'
className=
'operate__item'
onClick=
{
()
=>
{
this
.
handleViewPlayBack
(
item
)
;
this
.
handleViewPlayBack
(
item
)
}
}
>
查看回放
</
div
>
...
...
@@ -379,7 +379,7 @@ class LiveCourseList extends React.Component {
key=
'share'
className=
'operate__item'
onClick=
{
()
=>
{
this
.
handleShowShareModal
(
item
)
;
this
.
handleShowShareModal
(
item
)
}
}
>
分享
</
div
>
...
...
@@ -409,10 +409,10 @@ class LiveCourseList extends React.Component {
</
div
>
)
}
</
div
>
)
;
)
},
},
]
;
]
}
else
{
columns
=
[
{
...
...
@@ -421,13 +421,13 @@ class LiveCourseList extends React.Component {
key
:
'course'
,
dataIndex
:
'courseName'
,
render
:
(
val
,
record
)
=>
{
let
hasCover
=
false
;
let
hasCover
=
false
return
(
<
div
className=
'record__item'
>
{
record
.
courseMediaVOS
.
map
((
item
,
index
)
=>
{
if
(
item
.
contentType
===
'COVER'
)
{
hasCover
=
true
;
return
<
img
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
;
hasCover
=
true
return
<
img
className=
'course-cover'
src=
{
item
.
mediaUrl
}
alt=
''
/>
}
})
}
{
!
hasCover
&&
<
img
className=
'course-cover'
src=
{
'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'
}
alt=
''
/>
}
...
...
@@ -477,7 +477,7 @@ class LiveCourseList extends React.Component {
<
span
>
{
item
.
adminName
}
{
index
<
record
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
span
>
</
Tooltip
>
...
...
@@ -490,7 +490,7 @@ class LiveCourseList extends React.Component {
<
span
>
{
item
.
adminName
}
{
index
<
record
.
admins
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
span
>
</
Otherwise
>
...
...
@@ -499,7 +499,7 @@ class LiveCourseList extends React.Component {
</
div
>
</
div
>
</
div
>
)
;
)
},
},
{
...
...
@@ -508,7 +508,7 @@ class LiveCourseList extends React.Component {
key
:
'couseCatalog'
,
dataIndex
:
'couseCatalog'
,
render
:
(
val
,
item
)
=>
{
return
<
div
className=
'categoryName'
>
{
item
.
category
Name
}
</
div
>;
return
<
div
className=
'categoryName'
>
{
item
.
category
SonName
}
</
div
>
},
},
{
...
...
@@ -524,11 +524,11 @@ class LiveCourseList extends React.Component {
this
.
setState
({
editData
:
item
,
openCoursewareModal
:
true
,
})
;
})
}
}
>
{
item
.
courseDocumentCount
}
个
</
span
>
)
;
)
},
},
{
...
...
@@ -541,11 +541,11 @@ class LiveCourseList extends React.Component {
<
span
className=
'iconfont icon quota-icon'
onClick=
{
()
=>
{
this
.
handleLinkToClassData
(
item
)
;
this
.
handleLinkToClassData
(
item
)
}
}
>

</
span
>
)
;
)
},
},
{
...
...
@@ -555,7 +555,7 @@ class LiveCourseList extends React.Component {
dataIndex
:
'created'
,
sorter
:
true
,
render
:
(
val
,
item
)
=>
{
return
<
span
>
{
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
;
return
<
span
>
{
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
},
},
{
...
...
@@ -574,7 +574,7 @@ class LiveCourseList extends React.Component {
<
span
>
{
item
.
planName
}
{
index
<
record
.
relatedPlanList
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
)
;
)
})
}
</
Tooltip
>
</
When
>
...
...
@@ -583,36 +583,36 @@ class LiveCourseList extends React.Component {
</
Otherwise
>
</
Choose
>
</
div
>
)
;
)
},
},
]
;
]
}
this
.
setState
({
columns
})
;
}
;
this
.
setState
({
columns
})
}
handleAdminName
=
(
adminArray
)
=>
{
let
adminStr
=
''
;
let
adminStr
=
''
adminArray
.
forEach
((
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
}
handlePlanName
=
(
planArray
)
=>
{
let
planStr
=
''
;
let
planStr
=
''
planArray
.
forEach
((
item
,
index
)
=>
{
if
(
index
<
planArray
.
length
-
1
)
{
planStr
=
planStr
+
item
.
planName
+
'、'
;
planStr
=
planStr
+
item
.
planName
+
'、'
}
else
{
planStr
=
planStr
+
item
.
planName
;
planStr
=
planStr
+
item
.
planName
}
})
;
return
planStr
;
}
;
})
return
planStr
}
renderMoreOperate
=
(
item
)
=>
{
return
(
...
...
@@ -631,8 +631,8 @@ class LiveCourseList extends React.Component {
</
div
>
)
}
</
div
>
)
;
}
;
)
}
handleDelete
=
(
record
)
=>
{
return
confirm
({
title
:
'你确定要删除直播课?'
,
...
...
@@ -644,29 +644,29 @@ class LiveCourseList extends React.Component {
width
:
440
,
height
:
188
,
onOk
:
()
=>
{
this
.
deleteConfirm
(
record
)
;
this
.
deleteConfirm
(
record
)
},
})
;
}
;
})
}
deleteConfirm
=
(
item
)
=>
{
const
params
=
{
liveCourseId
:
item
.
liveCourseId
,
}
;
}
CourseService
.
delLiveCloudCourse
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
message
.
success
(
'已删除'
)
;
this
.
props
.
onChange
()
;
message
.
success
(
'已删除'
)
this
.
props
.
onChange
()
}
})
;
}
;
})
}
toEditCoursePage
=
(
item
)
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/create-live-course?type=edit&id=
${
item
.
liveCourseId
}
`
,
})
;
}
;
})
}
refreshCourseList
=
()
=>
{
this
.
props
.
onChange
(
this
.
props
.
query
)
;
}
;
this
.
props
.
onChange
(
this
.
props
.
query
)
}
//进入直播间
handleEnterLiveRoom
=
(
item
)
=>
{
if
(
item
.
startTime
-
Date
.
now
()
>
1800000
)
{
...
...
@@ -679,124 +679,124 @@ class LiveCourseList extends React.Component {

</
span
>
),
})
;
})
}
else
{
CourseService
.
getLiveCloudCourseDetail
({
liveCourseId
:
item
.
liveCourseId
,
}).
then
((
res
)
=>
{
const
url
=
`xmqx://liveCourseId=
${
item
.
liveCourseId
}
`
;
const
url
=
`xmqx://liveCourseId=
${
item
.
liveCourseId
}
`
if
(
res
.
result
.
courseState
===
'FINISH'
)
{
Modal
.
warning
({
title
:
'刷新页面'
,
icon
:
<
QuestionCircleOutlined
/>,
content
:
'课次已结束,请刷新一下'
,
onOk
:
()
=>
{
this
.
refreshCourseList
()
;
this
.
refreshCourseList
()
},
})
;
})
}
else
{
this
.
setState
({
url
,
openDownloadModal
:
true
})
;
this
.
setState
({
url
,
openDownloadModal
:
true
})
}
})
;
})
}
}
;
}
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
)
}
getDownloadVersion
()
{
const
isMac
=
/macintosh|mac os x/i
.
test
(
navigator
.
userAgent
)
;
const
isMac
=
/macintosh|mac os x/i
.
test
(
navigator
.
userAgent
)
// 判断学员系统
let
platform
;
let
platform
if
(
!
isMac
)
{
platform
=
1
;
platform
=
1
}
else
{
platform
=
4
;
platform
=
4
}
BaseService
.
getLastedVersion
({
model
:
5
,
platform
}).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
this
.
setState
({
downloadUrl
:
result
.
releaseUrl
})
;
})
;
const
{
result
=
{}
}
=
res
this
.
setState
({
downloadUrl
:
result
.
releaseUrl
})
})
}
handleViewPlayBack
=
(
item
)
=>
{
let
htmlUrl
;
let
htmlUrl
if
(
item
.
teacherId
===
User
.
getUserId
())
{
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?teacherId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
;
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?teacherId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
}
else
if
(
_
.
pluck
(
item
.
admins
,
'adminId'
).
includes
(
User
.
getUserId
()))
{
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?userId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
;
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?userId=
${
User
.
getUserId
()}
&id=
${
User
.
getStoreId
()}
`
}
else
{
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?id=
${
User
.
getStoreId
()}
`
;
htmlUrl
=
`
${
LIVE_SHARE
}
replay/
${
item
.
liveCourseId
}
?id=
${
User
.
getStoreId
()}
`
}
window
.
open
(
htmlUrl
)
;
}
;
window
.
open
(
htmlUrl
)
}
handleRelatedModalShow
=
(
item
)
=>
{
const
selectPlanList
=
{}
;
const
selectPlanList
=
{}
if
(
item
.
relatedPlanList
)
{
item
.
relatedPlanList
.
map
((
item
,
index
)
=>
{
selectPlanList
[
item
.
planId
]
=
{}
;
selectPlanList
[
item
.
planId
].
planId
=
item
.
planId
;
selectPlanList
[
item
.
planId
].
taskBaseVOList
=
[{
taskId
:
item
.
taskId
}]
;
return
item
;
})
;
selectPlanList
[
item
.
planId
]
=
{}
selectPlanList
[
item
.
planId
].
planId
=
item
.
planId
selectPlanList
[
item
.
planId
].
taskBaseVOList
=
[{
taskId
:
item
.
taskId
}]
return
item
})
}
this
.
setState
({
RelatedPlanModalVisible
:
true
,
selectCourseId
:
item
.
liveCourseId
,
selectPlanList
:
selectPlanList
,
})
;
}
;
})
}
closeRelatedPlanModalVisible
=
()
=>
{
this
.
setState
({
RelatedPlanModalVisible
:
false
,
})
;
}
;
})
}
onChangeSelectPlanList
=
(
selectPlanList
)
=>
{
this
.
setState
({
selectPlanList
:
selectPlanList
,
})
;
}
;
})
}
onConfirmSelectPlanList
=
()
=>
{
this
.
setState
(
{
RelatedPlanModalVisible
:
false
,
},
()
=>
{
this
.
props
.
onChange
()
;
this
.
props
.
onChange
()
}
)
;
}
;
)
}
handleChangeTable
=
(
pagination
,
filters
,
sorter
)
=>
{
const
{
columnKey
,
order
}
=
sorter
;
const
{
query
}
=
this
.
props
;
let
_columnKey
;
let
_order
;
const
{
columnKey
,
order
}
=
sorter
const
{
query
}
=
this
.
props
let
_columnKey
let
_order
// 按创建时间升序排序
if
(
columnKey
===
'created'
&&
order
===
'ascend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_ASC'
;
_columnKey
=
'CREATED'
_order
=
'SORT_ASC'
}
// 按创建时间降序排序
if
(
columnKey
===
'created'
&&
order
===
'descend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_DESC'
;
_columnKey
=
'CREATED'
_order
=
'SORT_DESC'
}
const
_query
=
{
...
query
,
sortMap
:
{},
}
;
_query
.
sortMap
[
_columnKey
]
=
_order
;
this
.
props
.
onChange
(
_query
)
;
}
;
}
_query
.
sortMap
[
_columnKey
]
=
_order
this
.
props
.
onChange
(
_query
)
}
render
()
{
const
{
total
,
query
,
courseList
,
loading
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
const
{
openDownloadModal
,
downloadUrl
,
url
,
columns
,
openCoursewareModal
,
editData
,
RelatedPlanModalVisible
,
selectCourseId
,
selectPlanList
}
=
this
.
state
;
const
{
match
}
=
this
.
props
;
const
{
total
,
query
,
courseList
,
loading
}
=
this
.
props
const
{
current
,
size
}
=
query
const
{
openDownloadModal
,
downloadUrl
,
url
,
columns
,
openCoursewareModal
,
editData
,
RelatedPlanModalVisible
,
selectCourseId
,
selectPlanList
}
=
this
.
state
const
{
match
}
=
this
.
props
return
(
<
div
className=
'live-course-list'
>
...
...
@@ -822,8 +822,8 @@ class LiveCourseList extends React.Component {
pageSize=
{
size
}
total=
{
parseInt
(
total
)
}
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
}
/>
...
...
@@ -834,8 +834,8 @@ class LiveCourseList extends React.Component {
<
ManageCoursewareModal
data=
{
editData
}
onCancel=
{
()
=>
{
this
.
props
.
onChange
()
;
this
.
setState
({
openCoursewareModal
:
false
})
;
this
.
props
.
onChange
()
this
.
setState
({
openCoursewareModal
:
false
})
}
}
/>
)
}
...
...
@@ -846,7 +846,7 @@ class LiveCourseList extends React.Component {
this
.
setState
({
url
:
''
,
openDownloadModal
:
false
,
})
;
})
}
}
/>
)
}
...
...
@@ -863,8 +863,8 @@ class LiveCourseList extends React.Component {
<
iframe
src=
{
url
}
style=
{
{
display
:
'none'
}
}
title=
'navigation'
/>
<
Route
path=
{
`${match.url}/live-course-data`
}
component=
{
DataList
}
/>
</
div
>
)
;
)
}
}
export
default
withRouter
(
LiveCourseList
)
;
export
default
withRouter
(
LiveCourseList
)
src/modules/course-manage/graphics-course/AddGraphicsCourse.jsx
View file @
39be164c
...
...
@@ -7,44 +7,35 @@
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
Cascader
}
from
'antd'
;
import
$
from
'jquery'
;
import
moment
from
'moment'
;
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
AddGraphicsIntro
from
'./components/AddGraphicsIntro'
;
import
SelectStudent
from
'../modal/select-student'
;
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
;
import
PreviewGraphicsModal
from
'../modal/PreviewGraphicsModal'
;
import
StoreService
from
'@/domains/store-domain/storeService'
;
import
Service
from
'@/common/js/service'
;
import
{
randomString
}
from
'@/domains/basic-domain/utils'
;
import
User
from
'@/common/js/user'
;
import
_
from
'underscore'
;
import
Upload
from
'@/core/upload'
;
import
React
from
'react'
import
{
Button
,
Input
,
message
,
Modal
}
from
'antd'
import
$
from
'jquery'
import
moment
from
'moment'
import
{
CourseCatalogSelect
}
from
'@/modules/common'
import
ShowTips
from
'@/components/ShowTips'
import
Breadcrumbs
from
'@/components/Breadcrumbs'
import
AddGraphicsIntro
from
'./components/AddGraphicsIntro'
import
SelectStudent
from
'../modal/select-student'
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
import
PreviewGraphicsModal
from
'../modal/PreviewGraphicsModal'
import
Service
from
'@/common/js/service'
import
{
randomString
}
from
'@/domains/basic-domain/utils'
import
User
from
'@/common/js/user'
import
_
from
'underscore'
import
Upload
from
'@/core/upload'
import
ImgClipModal
from
'@/components/ImgClipModal'
import
'./AddGraphicsCourse.less'
;
import
Bus
from
'@/core/bus'
;
const
EDIT_BOX_KEY
=
Math
.
random
();
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
};
import
'./AddGraphicsCourse.less'
import
Bus
from
'@/core/bus'
//添加课程时课程默认的一些值
const
defaultShelfState
=
'YES'
;
const
whetherVisitorsJoin
=
'NO'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'
;
let
cutFlag
=
false
;
const
defaultShelfState
=
'YES'
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'
class
AddGraphicsCourse
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
const
id
=
getParameterByName
(
'id'
);
const
pageType
=
getParameterByName
(
'type'
);
super
(
props
)
const
id
=
getParameterByName
(
'id'
)
const
pageType
=
getParameterByName
(
'type'
)
this
.
state
=
{
id
,
// 图文课ID,编辑的时候从URL上带过来
pageType
,
// 页面类型: add->新建 edit->编辑
...
...
@@ -61,103 +52,72 @@ class AddGraphicsCourse extends React.Component {
showCutModal
:
false
,
// 是否显示截图弹窗
showSelectVideoModal
:
false
,
studentModal
:
false
,
categoryName
:
null
,
//分类名称
courseCatalogList
:
[],
//分类列表
categoryName
:
''
,
categoryId
:
null
,
//分类的Id值
whetherVisitorsJoin
:
'NO'
,
// 是否允许游客加入
}
;
}
}
componentWillMount
()
{
const
{
id
,
pageType
}
=
this
.
state
;
this
.
getCourseCatalogList
();
const
{
id
,
pageType
}
=
this
.
state
if
(
pageType
===
'edit'
)
{
this
.
handleFetchScheudleDetail
(
id
)
;
this
.
handleFetchScheudleDetail
(
id
)
}
Bus
.
bind
(
'editorLimit'
,
(
editorTextLength
,
editorType
)
=>
{
this
.
setState
({
[
editorType
]:
editorTextLength
,
})
;
})
;
})
})
}
initBus
=
()
=>
{
Bus
.
bind
(
'graphicsEditorImage'
,
this
.
uploadImage
)
;
Bus
.
bind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
;
}
;
Bus
.
bind
(
'graphicsEditorImage'
,
this
.
uploadImage
)
Bus
.
bind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
}
removeBus
=
()
=>
{
Bus
.
unbind
(
'graphicsEditorImage'
,
this
.
uploadImage
)
;
Bus
.
unbind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
;
}
;
Bus
.
unbind
(
'graphicsEditorImage'
,
this
.
uploadImage
)
Bus
.
unbind
(
'graphicsEditorVideo'
,
this
.
uploadVideo
)
}
uploadImage
=
()
=>
{
this
.
setState
({
showSelectImageModal
:
true
})
;
}
;
this
.
setState
({
showSelectImageModal
:
true
})
}
uploadVideo
=
()
=>
{
this
.
setState
({
showSelectVideoModal
:
true
})
;
}
;
this
.
setState
({
showSelectVideoModal
:
true
})
}
//获取分类列表
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
this
.
setState
({
courseCatalogList
:
res
.
result
.
records
,
});
});
};
catalogChange
=
(
value
,
options
)
=>
{
const
changeValueLength
=
value
.
length
;
switch
(
changeValueLength
)
{
case
1
:
this
.
setState
({
categoryId
:
value
[
0
],
categoryName
:
options
[
0
].
categoryName
});
break
;
case
2
:
this
.
setState
({
categoryId
:
value
[
1
],
categoryName
:
`
${
options
[
0
].
categoryName
}
-
${
options
[
1
].
categoryName
}
`
});
break
;
default
:
this
.
setState
({
categoryId
:
null
,
categoryName
:
''
});
break
;
}
};
// 获取图文课详情
handleFetchScheudleDetail
=
(
courseId
)
=>
{
Service
.
Hades
(
'public/hades/mediaCourseDetail'
,
{
courseId
,
}).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
||
{}
;
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
category
OneName
,
categoryTwoName
,
categoryId
}
=
result
;
let
coverId
;
let
coverUrl
=
this
.
state
.
coverUrl
;
let
hasIntro
=
false
;
const
{
result
=
{}
}
=
res
||
{}
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
category
Id
}
=
result
let
coverId
let
coverUrl
=
this
.
state
.
coverUrl
let
hasIntro
=
false
courseMediaVOS
.
map
((
item
)
=>
{
switch
(
item
.
contentType
)
{
case
'COVER'
:
coverId
=
item
.
mediaContent
;
coverUrl
=
item
.
mediaUrl
;
break
;
coverId
=
item
.
mediaContent
coverUrl
=
item
.
mediaUrl
break
case
'SCHEDULE'
:
this
.
getTextDetail
(
'courseMedia'
,
item
.
mediaUrl
)
;
break
;
this
.
getTextDetail
(
'courseMedia'
,
item
.
mediaUrl
)
break
case
'INTRO'
:
hasIntro
=
true
;
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
;
break
;
hasIntro
=
true
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
break
default
:
break
;
break
}
return
item
;
});
let
categoryName
;
if
(
categoryTwoName
)
{
categoryName
=
`
${
categoryOneName
}
-
${
categoryTwoName
}
`
;
}
else
{
categoryName
=
`
${
categoryOneName
}
`
;
}
return
item
})
this
.
setState
({
loadintroduce
:
!
hasIntro
,
coverId
,
...
...
@@ -165,11 +125,10 @@ class AddGraphicsCourse extends React.Component {
courseName
,
shelfState
,
whetherVisitorsJoin
,
categoryName
,
categoryId
,
})
;
})
;
}
;
})
})
}
getTextDetail
=
(
key
,
url
)
=>
{
$
.
ajax
({
...
...
@@ -178,13 +137,13 @@ class AddGraphicsCourse 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
,
courseMediaId
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
;
const
{
coverId
,
videoName
,
videoDuration
,
courseName
,
courseMediaId
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
if
(
videoName
||
videoDuration
||
...
...
@@ -204,32 +163,28 @@ class AddGraphicsCourse extends React.Component {
onOk
:
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/graphics-course`
,
})
;
})
},
})
;
})
}
else
{
window
.
RCHistory
.
push
({
pathname
:
`/graphics-course`
,
})
;
})
}
}
;
}
// 修改表单
handleChangeForm
=
(
field
,
value
,
coverUrl
)
=>
{
this
.
setState
({
[
field
]:
value
,
coverUrl
:
coverUrl
?
coverUrl
:
this
.
state
.
coverUrl
,
})
;
}
;
})
}
// 显示选择学员弹窗
handleShowSelectStuModal
=
()
=>
{
this
.
setState
({
studentModal
:
true
});
const
{
studentList
,
selectedStuList
}
=
this
.
state
;
// const _studentList = _.map(studentList, (item) => {
// return item.studentId
// })
this
.
setState
({
studentModal
:
true
})
const
{
studentList
,
selectedStuList
}
=
this
.
state
const
studentModal
=
(
<
SelectStudent
showTabs=
{
true
}
...
...
@@ -240,36 +195,40 @@ class AddGraphicsCourse extends React.Component {
close=
{
()
=>
{
this
.
setState
({
studentModal
:
null
,
})
;
})
}
}
/>
);
this
.
setState
({
studentModal
});
};
)
this
.
setState
({
studentModal
})
}
handleChangeCatalogList
=
(
value
,
label
)
=>
{
this
.
setState
({
categoryId
:
value
,
categoryName
:
label
[
0
]
})
}
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
,
courseName
,
courseMedia
,
introduce
,
categoryName
}
=
this
.
state
;
const
{
coverUrl
,
courseName
,
courseMedia
,
introduce
,
categoryName
}
=
this
.
state
const
courseBasinInfo
=
{
coverUrl
,
courseName
,
categoryName
,
}
;
}
const
courseIntroInfo
=
{
courseMedia
,
introduce
,
}
;
}
const
previewGraphicsModal
=
(
<
PreviewGraphicsModal
courseBasicInfo=
{
courseBasinInfo
}
...
...
@@ -277,23 +236,23 @@ class AddGraphicsCourse extends React.Component {
close=
{
()
=>
{
this
.
setState
({
previewGraphicsModal
:
null
,
})
;
})
}
}
/>
)
;
)
this
.
setState
({
previewGraphicsModal
})
;
}
;
this
.
setState
({
previewGraphicsModal
})
}
handleSelectCover
=
(
file
)
=>
{
this
.
setState
({
visible
:
true
,
imageFile
:
file
})
;
}
;
imageFile
:
file
,
})
}
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
getSignature
=
(
blob
)
=>
{
Upload
.
uploadBlobToOSS
(
blob
,
'cover'
+
new
Date
().
valueOf
(),
null
,
'signInfo'
).
then
((
signInfo
)
=>
{
this
.
setState
(
{
...
...
@@ -302,18 +261,18 @@ class AddGraphicsCourse extends React.Component {
visible
:
false
,
},
()
=>
this
.
updateCover
()
)
;
})
;
}
;
)
})
}
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
;
const
{
coverClicpPath
,
coverId
}
=
this
.
state
this
.
setState
({
showSelectCoverModal
:
false
,
coverUrl
:
coverClicpPath
,
coverId
:
coverId
,
})
;
}
;
})
}
// 保存
handleSubmit
=
()
=>
{
...
...
@@ -323,10 +282,10 @@ class AddGraphicsCourse extends React.Component {
title
:
'服务已到期'
,
content
:
'当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买'
,
okText
:
'我知道了'
,
})
;
return
;
})
return
}
const
{
id
,
coverId
,
pageType
,
courseName
,
courseMedia
,
introduce
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
;
const
{
id
,
coverId
,
pageType
,
courseName
,
courseMedia
,
introduce
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
const
commonParams
=
{
categoryId
,
...
...
@@ -337,10 +296,10 @@ class AddGraphicsCourse extends React.Component {
shelfState
,
whetherVisitorsJoin
,
courseType
:
'PICTURE'
,
}
;
}
// 校验必填字段:课程名称, 课程图文
this
.
handleValidate
(
courseName
,
courseMedia
,
categoryId
).
then
((
res
)
=>
{
if
(
!
res
)
return
;
if
(
!
res
)
return
Upload
.
uploadTextToOSS
(
courseMedia
,
`
${
randomString
()}
.txt`
,
...
...
@@ -355,95 +314,87 @@ class AddGraphicsCourse extends React.Component {
commonParams
,
courseMediaId
,
introduceId
,
})
;
})
},
()
=>
message
.
warning
(
'上传课程简介失败'
)
)
;
)
},
()
=>
message
.
warning
(
'上传课程内容失败'
)
)
;
})
;
}
;
)
})
}
submitRemote
=
(
data
)
=>
{
const
{
id
,
pageType
,
commonParams
,
courseMediaId
,
introduceId
}
=
data
;
commonParams
.
courseMediaId
=
courseMediaId
;
commonParams
.
introduceId
=
introduceId
;
const
{
id
,
pageType
,
commonParams
,
courseMediaId
,
introduceId
}
=
data
commonParams
.
courseMediaId
=
courseMediaId
commonParams
.
introduceId
=
introduceId
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
:
`/graphics-course`
,
})
;
})
;
})
})
}
else
{
const
editParams
=
{
courseId
:
id
,
...
commonParams
,
}
;
}
Service
.
Hades
(
'public/hades/editMediaCourse'
,
editParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
;
message
.
success
(
'保存成功'
)
;
if
(
!
res
)
return
message
.
success
(
'保存成功'
)
window
.
RCHistory
.
push
({
pathname
:
`/graphics-course`
,
})
;
})
;
})
})
}
}
;
}
handleValidate
=
(
courseName
,
courseMedia
,
categoryId
)
=>
{
const
{
graphicsCourseIntor
,
graphicsCourseContent
}
=
this
.
state
;
const
{
graphicsCourseIntor
,
graphicsCourseContent
}
=
this
.
state
return
new
Promise
((
resolve
)
=>
{
if
(
!
courseName
)
{
message
.
warning
(
'请输入课程名称'
)
;
resolve
(
false
)
;
return
false
;
message
.
warning
(
'请输入课程名称'
)
resolve
(
false
)
return
false
}
if
(
!
courseMedia
)
{
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
}
if
(
graphicsCourseContent
>
1000
)
{
message
.
warning
(
'课程内容超过字数限定'
)
;
resolve
(
false
)
;
return
;
message
.
warning
(
'课程内容超过字数限定'
)
resolve
(
false
)
return
}
if
(
graphicsCourseIntor
>
1000
)
{
message
.
warning
(
'课程简介超过字数限定'
)
;
resolve
(
false
)
;
return
;
message
.
warning
(
'课程简介超过字数限定'
)
resolve
(
false
)
return
}
// 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
// }
// }
resolve
(
true
);
});
};
resolve
(
true
)
})
}
// 使用默认封面图
handleResetCoverUrl
=
()
=>
{
const
{
coverUrl
}
=
this
.
state
;
const
isDefaultCover
=
coverUrl
===
defaultCover
;
const
{
coverUrl
}
=
this
.
state
const
isDefaultCover
=
coverUrl
===
defaultCover
// 如果已经是默认图的话,不做任何任何处理
if
(
isDefaultCover
)
return
;
if
(
isDefaultCover
)
return
this
.
setState
({
coverUrl
:
defaultCover
,
coverId
:
null
},
()
=>
{
message
.
success
(
'已替换为默认图'
)
;
})
;
}
;
message
.
success
(
'已替换为默认图'
)
})
}
render
()
{
const
{
...
...
@@ -451,29 +402,20 @@ class AddGraphicsCourse extends React.Component {
pageType
,
courseName
,
coverUrl
,
studentList
,
courseMedia
,
introduce
,
showCutModal
,
imageFile
,
videoType
,
shelfState
,
categoryName
,
courseCatalogList
,
whetherVisitorsJoin
,
loadcourseMedia
,
loadintroduce
,
showSelectCoverModal
,
visible
,
hasImgReady
,
cutImageBlob
,
}
=
this
.
state
;
categoryId
,
}
=
this
.
state
// 已选择的上课学员数量
const
hasSelectedStu
=
studentList
.
length
;
const
courseWareIcon
=
FileVerifyMap
[
videoType
]
?
FileTypeIcon
[
FileVerifyMap
[
videoType
].
type
]
:
FileTypeIcon
[
videoType
];
// 当前是否使用的是默认图片
const
isDefaultCover
=
coverUrl
===
defaultCover
;
const
isDefaultCover
=
coverUrl
===
defaultCover
return
(
<
div
className=
'page add-graphics-course-page'
>
...
...
@@ -493,34 +435,20 @@ class AddGraphicsCourse extends React.Component {
maxLength=
{
40
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
{
this
.
handleChangeForm
(
'courseName'
,
e
.
target
.
value
)
;
this
.
handleChangeForm
(
'courseName'
,
e
.
target
.
value
)
}
}
/>
</
div
>
<
div
className=
'cover-url flex mt16'
>
<
div
className=
'label'
>
封面图:
</
div
>
{
/* <div className='cover-url__wrap'>
<div className='opt-btns'>
<Button
onClick={() => {
this.setState({
showSelectCoverModal: true,
});
}}>{`${pageType === 'add' && !coverUrl ? '上传' : '修改'}封面`}</Button>
<div className='tips'></div>
</div>
<div className='img-content'>
<img src={coverUrl} />
</div>
</div> */
}
<
div
className=
'course-cover__wrap'
>
<
div
className=
'opt-btns'
>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
true
,
})
;
})
}
}
>
上传图片
</
Button
>
...
...
@@ -537,19 +465,11 @@ class AddGraphicsCourse extends React.Component {
</
div
>
<
div
className=
'course-catalog required'
>
<
span
className=
'label'
>
课程分类:
</
span
>
<
Cascader
value=
{
categoryName
?
[
categoryName
]
:
undefined
}
options=
{
courseCatalogList
}
displayRender=
{
(
label
)
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
'请选择课程分类'
suffixIcon=
{
<
span
className=
'icon iconfont'
style=
{
{
fontSize
:
'12px'
,
color
:
'#BFBFBF'
}
}
>

</
span
>
}
<
CourseCatalogSelect
value=
{
categoryId
}
onChange=
{
(
value
,
label
)
=>
{
this
.
handleChangeCatalogList
(
value
,
label
)
}
}
/>
</
div
>
<
div
className=
'intro-info mt16'
>
...
...
@@ -587,18 +507,25 @@ class AddGraphicsCourse extends React.Component {
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectCoverModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
false
})
;
this
.
setState
({
showSelectCoverModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
)
}
{
visible
&&
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
});}
}
/>
}
{
visible
&&
(
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
{
this
.
state
.
previewGraphicsModal
}
</
div
>
)
;
)
}
}
export
default
AddGraphicsCourse
;
export
default
AddGraphicsCourse
src/modules/course-manage/graphics-course/components/GraphicsCourseList.jsx
View file @
39be164c
/*
* @Author: 吴文洁
* @Date: 2020-08-05 10:12:45
* @LastEditors: wufan
* @LastEditTime: 2021-07-05 10:23:10
* @Description: 线上课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
User
from
'@/common/js/user'
;
import
college
from
'@/common/lottie/college'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
...
...
@@ -94,12 +101,7 @@ class GraphicsCourseList extends React.Component {
dataIndex
:
'categoryName'
,
width
:
120
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
'record__item'
>
{
record
.
categoryOneName
}
{
record
.
categoryTwoName
?
`-${record.categoryTwoName}`
:
''
}
</
div
>
);
return
<
div
className=
'record__item'
>
{
record
.
categorySonName
}
</
div
>;
},
},
{
...
...
@@ -192,7 +194,7 @@ class GraphicsCourseList extends React.Component {
<
Tooltip
title=
{
this
.
handlePlanName
(
record
.
relatedPlanList
)
}
placement=
'top'
arrowPointAtCenter
>
{
record
.
relatedPlanList
.
map
((
item
,
index
)
=>
{
return
(
<
span
>
<
span
key=
{
item
.
planId
}
>
{
item
.
planName
}
{
index
<
record
.
relatedPlanList
.
length
-
1
&&
<
span
>
、
</
span
>
}{
' '
}
</
span
>
);
...
...
@@ -311,11 +313,6 @@ class GraphicsCourseList extends React.Component {
//改变上架状态
changeShelfState
=
(
index
,
item
,
checked
)
=>
{
let
_shelfState
=
checked
?
'YES'
:
'NO'
;
// if(_shelfState==='NO'){
// _shelfState = "YES";
// }else{
// _shelfState = "NO"
// }
const
params
=
{
courseId
:
item
.
id
,
shelfState
:
_shelfState
,
...
...
src/modules/course-manage/modal/ChargeExplainModal.jsx
View file @
39be164c
...
...
@@ -6,66 +6,54 @@
* @LastEditTime: 2020-12-22 20:30:54
*/
import
React
from
'react'
import
{
Modal
,
Button
,
Table
}
from
"antd"
;
import
"./AccountChargeModal"
;
import
{
Modal
,
Button
,
Table
}
from
'antd'
import
'./AccountChargeModal'
const
data
=
[
{
person
:
"上台人数1v1"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v2"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v3"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v4"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v5"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v6"
,
price
:
"3元/人/小时"
},
{
person
:
"上台人数1v7"
,
price
:
"4元/人/小时"
},
{
person
:
"上台人数1v8"
,
price
:
"4元/人/小时"
},
{
person
:
"上台人数1v9"
,
price
:
"8元/人/小时"
},
{
person
:
"上台人数1v10"
,
price
:
"8元/人/小时"
},
{
person
:
"上台人数1v11"
,
price
:
"8元/人/小时"
},
{
person
:
"上台人数1v12"
,
price
:
"8元/人/小时"
},
]
;
{
person
:
'上台人数1v1'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v2'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v3'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v4'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v5'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v6'
,
price
:
'3元/人/小时'
},
{
person
:
'上台人数1v7'
,
price
:
'4元/人/小时'
},
{
person
:
'上台人数1v8'
,
price
:
'4元/人/小时'
},
{
person
:
'上台人数1v9'
,
price
:
'8元/人/小时'
},
{
person
:
'上台人数1v10'
,
price
:
'8元/人/小时'
},
{
person
:
'上台人数1v11'
,
price
:
'8元/人/小时'
},
{
person
:
'上台人数1v12'
,
price
:
'8元/人/小时'
},
]
function
ChargeExplainModal
(
props
)
{
return
(
<
Modal
title=
"计费说明"
title=
'计费说明'
visible=
{
true
}
className=
"charge-explain-modal"
className=
'charge-explain-modal'
width=
{
880
}
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
"icon iconfont modal-close-icon"
>

</
span
>
}
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
onCancel=
{
()
=>
{
props
.
close
()
;
props
.
close
()
}
}
footer=
{
[
<
Button
type=
"primary"
type=
'primary'
onClick=
{
()
=>
{
props
.
close
();
}
}
>
props
.
close
()
}
}
>
关闭
</
Button
>,
]
}
>
]
}
>
<
div
>
<
div
className=
"explain-title"
>
1)直播课时费
</
div
>
<
p
className=
"main-explain-block"
>
每节课上课费用 = 上台人数单价 × 有效出勤学生和老师人数 × 排课时长
</
p
>
<
div
className=
'explain-title'
>
1)直播课时费
</
div
>
<
p
className=
'main-explain-block'
>
每节课上课费用 = 上台人数单价 × 有效出勤学生和老师人数 × 排课时长
</
p
>
<
ul
>
<
li
>
1. 上课老师、学生和助教在教室中的累计时长满10分钟即为有效出勤;
</
li
>
<
li
>
2.
排课时长指创建课节设置的课节时长,最小计费单位为0.5小时,不足0.5小时按0.5小时计算;
</
li
>
<
li
>
3.
上台人数单价:以排课时设定的上台人数上限为准,不同直播教室类型的课时单价不同。
</
li
>
<
li
>
1. 上课老师、学生和助教在教室中的累计时长满10分钟即为有效出勤;
</
li
>
<
li
>
2. 排课时长指创建课节设置的课节时长,最小计费单位为0.5小时,不足0.5小时按0.5小时计算;
</
li
>
<
li
>
3. 上台人数单价:以排课时设定的上台人数上限为准,不同直播教室类型的课时单价不同。
</
li
>
</
ul
>
<
p
className=
"main-explain-text"
style=
{
{
marginTop
:
16
,
marginBottom
:
8
}
}
>
<
p
className=
'main-explain-text'
style=
{
{
marginTop
:
16
,
marginBottom
:
8
}
}
>
温馨提醒:上台人数1vN,1为授课老师,N为同时与老师视频互动学生数;直播课时费将在老师下课后立即结算。
</
p
>
<
table
style=
{
{
width
:
333
}
}
>
...
...
@@ -82,47 +70,43 @@ function ChargeExplainModal(props) {
<
td
>
{
item
.
person
}
</
td
>
<
td
>
{
item
.
price
}
</
td
>
</
tr
>
)
;
)
})
}
</
tbody
>
</
table
>
<
p
className=
"main-explain-text"
>
<
p
className=
'main-explain-text'
>
示例:王老师排了一节45分钟的课程,选择的直播教室类型为5人上台,安排了1位助教、12位学生。那么,排课时长45分钟记为1小时;全员累计在线时长≥10min,老师+助教+学生共计1+1+12=14人;课时单价3元/人/小时。所以,此节课的直播课时费=1x14x3=42元
</
p
>
<
div
className=
"explain-title mt16"
>
2)录制费
</
div
>
<
p
className=
"main-explain-block"
>
录制费 = 录课单价 × 回放视频时长
</
p
>
<
div
className=
'explain-title mt16'
>
2)录制费
</
div
>
<
p
className=
'main-explain-block'
>
录制费 = 录课单价 × 回放视频时长
</
p
>
<
ul
>
<
li
>
1. 结算时间:从回放视频生成后立即结算
</
li
>
<
li
>
2. 回放视频时长:0.5h起收,不足0.5h的按0.5h结算
</
li
>
<
li
>
3. 单价:2元/小时
</
li
>
</
ul
>
<
p
className=
"main-explain-text"
>
示例:生成了49分26秒的回放视频,不足1h按1h计算,总费用=1(h)*2元/h=2元
</
p
>
<
div
className=
"explain-title mt16"
>
3)流量费
</
div
>
<
p
className=
"main-explain-block"
>
观看回放视频流量费 = 流量单价 × 回放流量
</
p
>
<
p
className=
"main-explain-text"
>
<
p
className=
'main-explain-text'
>
示例:生成了49分26秒的回放视频,不足1h按1h计算,总费用=1(h)*2元/h=2元
</
p
>
<
div
className=
'explain-title mt16'
>
3)流量费
</
div
>
<
p
className=
'main-explain-block'
>
观看回放视频流量费 = 流量单价 × 回放流量
</
p
>
<
p
className=
'main-explain-text'
>
目前收费报价:0元(限时免费)
<
br
/>
若后续变更收费,将提前30日通告收费方式及价格标准
</
p
>
<
div
className=
"explain-title mt16"
>
4)存储费
</
div
>
<
p
className=
"main-explain-block"
>
存储实际扣费 = 存储单价 × 存储文件大小
</
p
>
<
p
className=
"main-explain-text"
>
<
div
className=
'explain-title mt16'
>
4)存储费
</
div
>
<
p
className=
'main-explain-block'
>
存储实际扣费 = 存储单价 × 存储文件大小
</
p
>
<
p
className=
'main-explain-text'
>
目前收费报价:0元(限时免费)
<
br
/>
若后续变更收费,将提前30日通告收费方式及价格标准
</
p
>
<
div
className=
"explain-title mt16"
>
5)其他说明
</
div
>
<
div
className=
"main-explain-text"
>
余额不足时将限制使用创建直播课、老师和学生进入直播间、老师和学生观看回放视频、在
资料云盘
或直播间上传文件等功能,请注意及时充值。(余额<300元时将发送短信提醒,请注意查看。)
<
div
className=
'explain-title mt16'
>
5)其他说明
</
div
>
<
div
className=
'main-explain-text'
>
余额不足时将限制使用创建直播课、老师和学生进入直播间、老师和学生观看回放视频、在
素材库
或直播间上传文件等功能,请注意及时充值。(余额<300元时将发送短信提醒,请注意查看。)
</
div
>
</
div
>
</
Modal
>
)
;
)
}
export
default
ChargeExplainModal
;
export
default
ChargeExplainModal
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
View file @
39be164c
...
...
@@ -3,55 +3,55 @@
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-22 18:29:55
* @Description: 线下
课
新增/编辑页
* @Description: 线下
活动
新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
TreeSelect
,
Select
,
Switch
,
TimePicker
,
InputNumber
,
Tooltip
}
from
'antd'
;
import
$
from
'jquery'
;
import
React
from
'react'
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
Select
,
Switch
,
TimePicker
,
InputNumber
,
Tooltip
}
from
'antd'
import
$
from
'jquery'
import
RangePicker
from
'@/modules/common/DateRangePicker'
;
import
ShowTips
from
'@/components/ShowTips'
;
import
Breadcrumbs
from
'@/components/Breadcrumbs'
;
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
;
import
PreviewOfflineModal
from
'./modal/PreviewOfflineModal'
;
import
StoreService
from
'@/domains/store-domain/storeService'
;
import
Service
from
'@/common/js/service'
;
import
{
randomString
}
from
'@/domains/basic-domain/utils'
;
import
User
from
'@/common/js/user'
;
import
_
from
'underscore'
;
import
moment
from
'moment'
;
import
Upload
from
'@/core/upload'
;
import
GraphicsEditor
from
'../components/GraphicsEditor'
;
import
MultipleDatePicker
from
'@/components/MultipleDatePicker'
;
import
ImgClipModal
from
'@/components/ImgClipModal'
;
import
'./AddOfflineCourse.less'
;
import
Bus
from
'@/core/bus'
;
import
{
RangePicker
,
CourseCatalogSelect
}
from
'@/modules/common'
import
ShowTips
from
'@/components/ShowTips'
import
Breadcrumbs
from
'@/components/Breadcrumbs'
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
import
PreviewOfflineModal
from
'./modal/PreviewOfflineModal'
import
StoreService
from
'@/domains/store-domain/storeService'
import
Service
from
'@/common/js/service'
import
{
randomString
}
from
'@/domains/basic-domain/utils'
import
User
from
'@/common/js/user'
import
_
from
'underscore'
import
moment
from
'moment'
import
Upload
from
'@/core/upload'
import
GraphicsEditor
from
'../components/GraphicsEditor'
import
MultipleDatePicker
from
'@/components/MultipleDatePicker'
import
ImgClipModal
from
'@/components/ImgClipModal'
import
'./AddOfflineCourse.less'
import
Bus
from
'@/core/bus'
const
{
Option
}
=
Select
;
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
const
{
Option
}
=
Select
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
const
unitList
=
[
{
key
:
'HOUR'
,
value
:
'小时'
},
{
key
:
'MINUTE'
,
value
:
'分钟'
},
]
;
]
class
AddOfflineCourse
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
const
courseId
=
window
.
getParameterByName
(
'id'
)
;
const
pageType
=
window
.
getParameterByName
(
'type'
)
;
const
courseId
=
window
.
getParameterByName
(
'id'
)
const
pageType
=
window
.
getParameterByName
(
'type'
)
this
.
state
=
{
courseId
,
// 线下
课
ID,编辑的时候从URL上带过来
courseId
,
// 线下
活动
ID,编辑的时候从URL上带过来
pageType
,
// 页面类型: add->新建 edit->编辑
imageFile
:
null
,
// 需要被截取的图片
courseName
:
null
,
// 线下
课
名称
courseName
:
null
,
// 线下
活动
名称
courseMedia
:
''
,
introduce
:
''
,
coverId
:
null
,
// 线下封面的recourceId
coverUrl
:
defaultCoverUrl
,
// 线下
课
封面
coverUrl
:
defaultCoverUrl
,
// 线下
活动
封面
studentList
:
[],
// 上课学员列表
diskList
:
[],
// 机构可见磁盘目录
selectedFileList
:
[],
// 已经从资料云盘中勾选的文件
...
...
@@ -87,74 +87,74 @@ class AddOfflineCourse extends React.Component {
isEditDisablie
:
false
,
startTime
:
new
Date
().
getTime
()
+
300000
,
// 批量开始时分
endTime
:
new
Date
().
getTime
()
+
300000
,
// 批量结束时分
}
;
}
}
componentWillMount
()
{
const
{
courseId
,
pageType
}
=
this
.
state
;
this
.
getCourseCatalogList
()
;
this
.
getTeacherList
()
;
const
{
courseId
,
pageType
}
=
this
.
state
this
.
getCourseCatalogList
()
this
.
getTeacherList
()
if
(
pageType
===
'edit'
)
{
this
.
handleFetchScheudleDetail
(
courseId
)
;
this
.
handleFetchScheudleDetail
(
courseId
)
}
Bus
.
bind
(
'editorLimit'
,
(
editorTextLength
)
=>
{
this
.
setState
({
editorTextLength
,
})
;
})
;
})
})
}
initBus
=
()
=>
{
Bus
.
bind
(
'offlineEditorImage'
,
this
.
uploadImage
)
;
}
;
Bus
.
bind
(
'offlineEditorImage'
,
this
.
uploadImage
)
}
removeBus
=
()
=>
{
Bus
.
unbind
(
'offlineEditorImage'
,
this
.
uploadImage
)
;
}
;
Bus
.
unbind
(
'offlineEditorImage'
,
this
.
uploadImage
)
}
uploadImage
=
()
=>
{
this
.
setState
({
showSelectImageModal
:
true
})
;
}
;
this
.
setState
({
showSelectImageModal
:
true
})
}
//获取分类列表
getCourseCatalogList
=
()
=>
{
Service
.
Hades
(
'public/hades/queryCategoryTree'
,
{
source
:
0
,
tenantId
:
User
.
getStoreId
(),
count
:
false
,
userId
:
User
.
getUserId
()
}).
then
((
res
)
=>
{
const
{
categoryList
=
[]
}
=
res
.
result
;
const
{
categoryList
=
[]
}
=
res
.
result
this
.
setState
({
categoryList
,
courseCatalogList
:
this
.
renderTreeNodes
(
categoryList
),
})
;
})
;
}
;
})
})
}
renderTreeNodes
=
(
data
)
=>
{
let
newTreeData
=
data
.
map
((
item
)
=>
{
item
.
title
=
item
.
categoryName
;
item
.
value
=
item
.
id
;
item
.
key
=
item
.
id
;
item
.
title
=
item
.
categoryName
item
.
value
=
item
.
id
item
.
key
=
item
.
id
if
(
item
.
sonCategoryList
)
{
item
.
children
=
this
.
renderTreeNodes
(
item
.
sonCategoryList
)
;
item
.
children
=
this
.
renderTreeNodes
(
item
.
sonCategoryList
)
}
return
item
;
})
;
return
newTreeData
;
}
;
return
item
})
return
newTreeData
}
checkDetail
=
(
courseId
)
=>
{
return
Service
.
Hades
(
'public/hades/getOfflineCourseDetail'
,
{
courseId
,
}).
then
((
res
)
=>
{
const
{
courseState
}
=
res
.
result
;
return
courseState
===
'UN_START'
;
})
;
}
;
const
{
courseState
}
=
res
.
result
return
courseState
===
'UN_START'
})
}
// 获取线下
课
详情
// 获取线下
活动
详情
handleFetchScheudleDetail
=
(
courseId
)
=>
{
return
Service
.
Hades
(
'public/hades/getOfflineCourseDetail'
,
{
courseId
,
}).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
||
{}
;
const
{
result
=
{}
}
=
res
||
{}
const
{
courseName
,
categoryId
,
...
...
@@ -183,29 +183,29 @@ class AddOfflineCourse extends React.Component {
signInType
,
signOutType
,
whetherHaveApply
,
}
=
result
;
let
coverId
;
let
coverUrl
=
this
.
state
.
coverUrl
;
let
hasIntro
=
false
;
}
=
result
let
coverId
let
coverUrl
=
this
.
state
.
coverUrl
let
hasIntro
=
false
courseMediaVOS
.
map
((
item
)
=>
{
switch
(
item
.
contentType
)
{
case
'COVER'
:
coverId
=
item
.
mediaContent
;
coverUrl
=
item
.
mediaUrl
;
break
;
coverId
=
item
.
mediaContent
coverUrl
=
item
.
mediaUrl
break
case
'SCHEDULE'
:
this
.
getTextDetail
(
'courseMedia'
,
item
.
mediaUrl
)
;
break
;
this
.
getTextDetail
(
'courseMedia'
,
item
.
mediaUrl
)
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
})
this
.
setState
({
loadintroduce
:
!
hasIntro
,
coverId
,
...
...
@@ -237,9 +237,9 @@ class AddOfflineCourse extends React.Component {
signInType
,
signOutType
,
isEditDisablie
:
whetherHaveApply
===
'YES'
,
})
;
})
;
}
;
})
})
}
getTextDetail
=
(
key
,
url
)
=>
{
$
.
ajax
({
...
...
@@ -248,13 +248,13 @@ class AddOfflineCourse 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
,
categoryId
,
whetherVisitorsJoin
}
=
this
.
state
;
const
{
coverId
,
videoName
,
videoDuration
,
courseName
,
categoryId
,
whetherVisitorsJoin
}
=
this
.
state
if
(
videoName
||
videoDuration
||
categoryId
||
courseName
||
coverId
||
whetherVisitorsJoin
!==
whetherVisitorsJoin
)
{
Modal
.
confirm
({
title
:
'确认要返回吗?'
,
...
...
@@ -265,15 +265,15 @@ class AddOfflineCourse extends React.Component {
onOk
:
()
=>
{
window
.
RCHistory
.
push
({
pathname
:
`/offline-course`
,
})
;
})
},
})
;
})
}
else
{
window
.
RCHistory
.
push
({
pathname
:
`/offline-course`
,
})
;
})
}
}
;
}
// 显示预览弹窗
handleShowPreviewModal
=
()
=>
{
...
...
@@ -299,7 +299,7 @@ class AddOfflineCourse extends React.Component {
signOutStartTimeUnit
,
signOutEndTimeNum
,
signOutEndTimeUnit
,
}
=
this
.
state
;
}
=
this
.
state
const
data
=
{
coverUrl
,
...
...
@@ -323,27 +323,27 @@ class AddOfflineCourse extends React.Component {
signOutStartTimeUnit
,
signOutEndTimeNum
,
signOutEndTimeUnit
,
}
;
}
const
previewOfflineModal
=
(
<
PreviewOfflineModal
data=
{
data
}
close=
{
()
=>
{
this
.
setState
({
previewOfflineModal
:
null
,
})
;
})
}
}
/>
)
;
)
this
.
setState
({
previewOfflineModal
})
;
}
;
this
.
setState
({
previewOfflineModal
})
}
handleSelectCover
=
(
file
)
=>
{
this
.
setState
({
visible
:
true
,
imageFile
:
file
})
;
}
;
imageFile
:
file
,
})
}
//获取resourceId
getSignature
=
(
blob
,
fileName
)
=>
{
...
...
@@ -355,18 +355,18 @@ class AddOfflineCourse extends React.Component {
visible
:
false
,
},
()
=>
this
.
updateCover
()
)
;
})
;
}
;
)
})
}
updateCover
=
()
=>
{
const
{
coverClicpPath
,
coverId
}
=
this
.
state
;
const
{
coverClicpPath
,
coverId
}
=
this
.
state
this
.
setState
({
showSelectCoverModal
:
false
,
coverUrl
:
coverClicpPath
,
coverId
:
coverId
,
})
;
}
;
})
}
preSubmit
=
()
=>
{
//过期判断
...
...
@@ -375,16 +375,16 @@ class AddOfflineCourse extends React.Component {
title
:
'服务已到期'
,
content
:
'当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买'
,
okText
:
'我知道了'
,
})
;
return
;
})
return
}
const
{
courseId
}
=
this
.
state
;
const
{
courseId
}
=
this
.
state
if
(
courseId
)
{
this
.
checkDetail
(
courseId
).
then
((
bool
)
=>
(
bool
?
this
.
handleSubmit
()
:
message
.
warning
(
'课程已开始,无法继续编辑'
)))
;
this
.
checkDetail
(
courseId
).
then
((
bool
)
=>
(
bool
?
this
.
handleSubmit
()
:
message
.
warning
(
'课程已开始,无法继续编辑'
)))
}
else
{
this
.
handleSubmit
()
;
this
.
handleSubmit
()
}
}
;
}
// 保存
handleSubmit
=
()
=>
{
...
...
@@ -419,22 +419,22 @@ class AddOfflineCourse extends React.Component {
signOutEndTimeUnit
,
// isMore,
editorTextLength
,
}
=
this
.
state
;
}
=
this
.
state
let
coverObj
=
{
contentType
:
'COVER'
,
mediaContent
:
coverId
,
mediaType
:
'PICTURE'
,
mediaUrl
:
coverUrl
,
}
;
let
scheduleMediaRequests
=
[]
;
}
let
scheduleMediaRequests
=
[]
if
(
coverId
)
{
scheduleMediaRequests
=
[
coverObj
]
;
scheduleMediaRequests
=
[
coverObj
]
}
// 编辑且使用默认图时不传
if
(
pageType
===
'edit'
&&
coverUrl
===
defaultCoverUrl
)
{
scheduleMediaRequests
=
[]
;
scheduleMediaRequests
=
[]
}
const
commonParams
=
{
categoryId
,
...
...
@@ -453,33 +453,33 @@ class AddOfflineCourse extends React.Component {
calendarTime
,
editorTextLength
,
// isMore,
}
;
}
if
(
whetherSetApply
===
'YES'
)
{
commonParams
.
startTimeApply
=
startTimeApply
;
commonParams
.
endTimeApply
=
endTimeApply
;
commonParams
.
quota
=
quota
;
commonParams
.
startTimeApply
=
startTimeApply
commonParams
.
endTimeApply
=
endTimeApply
commonParams
.
quota
=
quota
}
if
(
whetherSetSignIn
===
'YES'
)
{
commonParams
.
signInType
=
signInType
;
commonParams
.
signInTimeNum
=
signInTimeNum
;
commonParams
.
signInTimeUnit
=
signInTimeUnit
;
commonParams
.
signInType
=
signInType
commonParams
.
signInTimeNum
=
signInTimeNum
commonParams
.
signInTimeUnit
=
signInTimeUnit
}
if
(
whetherSetSignOut
===
'YES'
)
{
commonParams
.
signOutType
=
signOutType
;
commonParams
.
signOutType
=
signOutType
if
(
commonParams
.
signOutType
===
'START_LATER'
)
{
commonParams
.
signOutStartTimeNum
=
signOutStartTimeNum
;
commonParams
.
signOutStartTimeUnit
=
signOutStartTimeUnit
;
commonParams
.
signOutStartTimeNum
=
signOutStartTimeNum
commonParams
.
signOutStartTimeUnit
=
signOutStartTimeUnit
}
commonParams
.
signOutEndTimeNum
=
signOutEndTimeNum
;
commonParams
.
signOutEndTimeUnit
=
signOutEndTimeUnit
;
commonParams
.
signOutEndTimeNum
=
signOutEndTimeNum
commonParams
.
signOutEndTimeUnit
=
signOutEndTimeUnit
}
// 校验必填字段:课程名称, 课程线下
this
.
handleValidate
(
commonParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
;
if
(
!
res
)
return
Upload
.
uploadTextToOSS
(
introduce
,
`
${
randomString
()}
.txt`
,
...
...
@@ -489,182 +489,182 @@ class AddOfflineCourse extends React.Component {
pageType
,
commonParams
,
introduceId
,
})
;
})
},
()
=>
message
.
warning
(
'上传课程简介失败'
)
)
;
})
;
}
;
)
})
}
submitRemote
=
(
data
)
=>
{
const
{
courseId
,
pageType
,
commonParams
,
introduceId
}
=
data
;
commonParams
.
introduceId
=
introduceId
;
const
{
courseId
,
pageType
,
commonParams
,
introduceId
}
=
data
commonParams
.
introduceId
=
introduceId
if
(
pageType
===
'add'
)
{
Service
.
Hades
(
'public/hades/createOfflineCourse'
,
commonParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
;
message
.
success
(
'新建成功'
)
;
if
(
!
res
)
return
message
.
success
(
'新建成功'
)
window
.
RCHistory
.
push
({
pathname
:
`/offline-course`
,
})
;
})
;
})
})
}
else
{
const
editParams
=
{
courseId
:
courseId
,
...
commonParams
,
}
;
}
Service
.
Hades
(
'public/hades/updateOfflineCourse'
,
editParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
;
message
.
success
(
'保存成功'
)
;
if
(
!
res
)
return
message
.
success
(
'保存成功'
)
window
.
RCHistory
.
push
({
pathname
:
`/offline-course`
,
})
;
})
;
})
})
}
}
;
}
handleValidate
=
(
data
)
=>
{
return
new
Promise
((
resolve
)
=>
{
if
(
!
data
.
courseName
)
{
message
.
warning
(
'请输入课程名称'
)
;
resolve
(
false
)
;
message
.
warning
(
'请输入课程名称'
)
resolve
(
false
)
}
else
if
(
!
data
.
categoryId
)
{
message
.
warning
(
'请选择课程分类'
)
;
resolve
(
false
)
;
message
.
warning
(
'请选择课程分类'
)
resolve
(
false
)
}
else
if
(
!
data
.
offlinePlace
)
{
message
.
warning
(
'请输入上课地点'
)
;
resolve
(
false
)
;
message
.
warning
(
'请输入上课地点'
)
resolve
(
false
)
}
else
if
(
!
data
.
teacherId
)
{
message
.
warning
(
'请选择讲师'
)
;
resolve
(
false
)
;
message
.
warning
(
'请选择讲师'
)
resolve
(
false
)
}
else
if
(
_
.
isEmpty
(
data
.
calendarTime
))
{
message
.
warning
(
'请选择上课日期'
)
;
resolve
(
false
)
;
message
.
warning
(
'请选择上课日期'
)
resolve
(
false
)
}
else
if
(
!
data
.
startTime
||
!
data
.
endTime
)
{
message
.
warning
(
'请选择上课时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'请选择上课时间'
)
resolve
(
false
)
}
else
if
(
moment
(
moment
(
data
.
calendarTime
[
0
]).
format
(
'YYYY-MM-DD'
)
+
moment
(
data
.
startTime
).
format
(
' HH:mm'
)).
valueOf
()
<
Date
.
now
())
{
message
.
warning
(
'上课时间不能早于现在'
)
;
resolve
(
false
)
;
message
.
warning
(
'上课时间不能早于现在'
)
resolve
(
false
)
}
else
if
(
data
.
startTime
>=
data
.
endTime
)
{
message
.
warning
(
'上课结束时间不能早于上课开始时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'上课结束时间不能早于上课开始时间'
)
resolve
(
false
)
}
else
if
(
data
.
whetherSetApply
===
'YES'
&&
!
data
.
startTimeApply
)
{
message
.
warning
(
'请选择报名时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'请选择报名时间'
)
resolve
(
false
)
}
else
if
(
data
.
whetherSetApply
===
'YES'
&&
data
.
startTimeApply
>=
data
.
endTimeApply
)
{
message
.
warning
(
'报名结束时间需大于报名开始时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'报名结束时间需大于报名开始时间'
)
resolve
(
false
)
}
else
if
(
data
.
whetherSetApply
===
'YES'
&&
data
.
endTimeApply
>
moment
(
moment
(
data
.
calendarTime
[
0
]).
format
(
'YYYY-MM-DD'
)
+
moment
(
data
.
endTime
).
format
(
' HH:mm:ss'
)).
valueOf
()
)
{
message
.
warning
(
'报名结束时间需小于上课开始时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'报名结束时间需小于上课开始时间'
)
resolve
(
false
)
}
else
if
(
data
.
whetherSetSignIn
===
'YES'
&&
!
data
.
signInTimeNum
)
{
message
.
warning
(
'请输入签到时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'请输入签到时间'
)
resolve
(
false
)
}
else
if
(
data
.
whetherSetSignOut
===
'YES'
&&
((
data
.
signOutType
===
'START_LATER'
&&
!
data
.
signOutStartTimeNum
)
||
!
data
.
signOutEndTimeNum
))
{
message
.
warning
(
'请输入签退时间'
)
;
resolve
(
false
)
;
message
.
warning
(
'请输入签退时间'
)
resolve
(
false
)
}
else
if
(
data
.
editorTextLength
>
1000
)
{
message
.
warning
(
'课程简介超过字数限定'
)
;
resolve
(
false
)
;
message
.
warning
(
'课程简介超过字数限定'
)
resolve
(
false
)
}
else
{
resolve
(
true
)
;
resolve
(
true
)
}
})
;
}
;
})
}
// 使用默认封面图
handleResetCoverUrl
=
()
=>
{
const
{
coverUrl
}
=
this
.
state
;
const
isDefaultCover
=
coverUrl
===
defaultCoverUrl
;
const
{
coverUrl
}
=
this
.
state
const
isDefaultCover
=
coverUrl
===
defaultCoverUrl
// 如果已经是默认图的话,不做任何任何处理
if
(
isDefaultCover
)
return
;
message
.
success
(
'已替换为默认图'
)
;
this
.
setState
({
coverUrl
:
defaultCoverUrl
})
;
}
;
if
(
isDefaultCover
)
return
message
.
success
(
'已替换为默认图'
)
this
.
setState
({
coverUrl
:
defaultCoverUrl
})
}
// 滑动加载更多讲师列表
handleScrollTeacherList
=
(
e
)
=>
{
const
{
hasNext
}
=
this
.
state
;
const
container
=
e
.
target
;
const
{
hasNext
}
=
this
.
state
const
container
=
e
.
target
//判定元素是否滚动到底部
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
;
const
scrollToBottom
=
container
&&
container
.
scrollHeight
<=
container
.
clientHeight
+
container
.
scrollTop
if
(
scrollToBottom
&&
hasNext
)
{
const
{
teacherQuery
}
=
this
.
state
;
let
_teacherQuery
=
teacherQuery
;
_teacherQuery
.
current
=
_teacherQuery
.
current
+
1
;
const
{
teacherQuery
}
=
this
.
state
let
_teacherQuery
=
teacherQuery
_teacherQuery
.
current
=
_teacherQuery
.
current
+
1
this
.
setState
(
{
teacherQuery
:
{
...
_teacherQuery
},
},
()
=>
{
this
.
getTeacherList
(
_teacherQuery
.
current
)
;
this
.
getTeacherList
(
_teacherQuery
.
current
)
}
)
;
)
}
}
;
}
getTeacherList
(
current
=
1
,
selectList
)
{
const
{
teacherQuery
,
teacherList
}
=
this
.
state
;
const
{
teacherQuery
,
teacherList
}
=
this
.
state
const
_query
=
{
...
teacherQuery
,
current
,
size
:
15
,
}
;
}
StoreService
.
getStoreUserBasicPage
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
hasNext
}
=
result
;
const
list
=
current
>
1
?
teacherList
.
concat
(
records
)
:
records
;
const
{
result
=
{}
}
=
res
const
{
records
=
[],
hasNext
}
=
result
const
list
=
current
>
1
?
teacherList
.
concat
(
records
)
:
records
this
.
setState
({
hasNext
,
teacherList
:
list
,
teacherQuery
:
{
...
_query
},
})
;
})
;
})
})
}
changeIntro
=
(
value
)
=>
{
this
.
setState
({
introduce
:
value
})
;
}
;
this
.
setState
({
introduce
:
value
})
}
selectMultiDate
=
(
calendarTime
)
=>
{
const
dateList
=
_
.
sortBy
(
calendarTime
)
;
const
dateList
=
_
.
sortBy
(
calendarTime
)
this
.
setState
({
calendarTime
:
dateList
,
})
;
}
;
})
}
handleChangeDates
=
(
dates
)
=>
{
const
data
=
{}
;
const
data
=
{}
if
(
_
.
isEmpty
(
dates
))
{
data
.
startTimeApply
=
undefined
;
data
.
endTimeApply
=
undefined
;
data
.
startTimeApply
=
undefined
data
.
endTimeApply
=
undefined
}
else
{
data
.
startTimeApply
=
dates
[
0
].
valueOf
()
;
data
.
endTimeApply
=
dates
[
1
].
startOf
(
'minute'
).
valueOf
()
+
59000
;
data
.
startTimeApply
=
dates
[
0
].
valueOf
()
data
.
endTimeApply
=
dates
[
1
].
startOf
(
'minute'
).
valueOf
()
+
59000
}
this
.
setState
(
data
)
;
}
;
this
.
setState
(
data
)
}
whetherVisitorsJoinChange
=
()
=>
{
const
{
whetherSetApply
,
whetherVisitorsJoin
}
=
this
.
state
;
if
(
whetherSetApply
==
'NO'
)
{
const
{
whetherSetApply
,
whetherVisitorsJoin
}
=
this
.
state
if
(
whetherSetApply
==
'NO'
)
{
message
.
warning
(
'关闭报名无法获取手机号!'
)
return
}
if
(
this
.
state
.
whetherVisitorsJoin
===
'NO'
)
{
this
.
setState
({
whetherVisitorsJoin
:
'YES'
})
;
this
.
setState
({
whetherVisitorsJoin
:
'YES'
})
}
else
{
this
.
setState
({
whetherVisitorsJoin
:
'NO'
})
;
this
.
setState
({
whetherVisitorsJoin
:
'NO'
})
}
}
;
}
handleChangeCatalogList
=
(
value
,
label
)
=>
{
this
.
setState
({
categoryId
:
value
,
categoryName
:
label
[
0
]
})
;
}
;
this
.
setState
({
categoryId
:
value
,
categoryName
:
label
[
0
]
})
}
render
()
{
const
{
...
...
@@ -703,11 +703,11 @@ class AddOfflineCourse extends React.Component {
offlinePlace
,
isEditDisablie
,
imageFile
,
}
=
this
.
state
;
const
isDefaultCover
=
coverUrl
===
defaultCoverUrl
;
}
=
this
.
state
const
isDefaultCover
=
coverUrl
===
defaultCoverUrl
return
(
<
div
className=
'page add-offline-course-page'
>
<
Breadcrumbs
navList=
{
pageType
===
'add'
?
'新建线下
课'
:
'编辑线下课
'
}
goBack=
{
this
.
handleGoBack
}
/>
<
Breadcrumbs
navList=
{
pageType
===
'add'
?
'新建线下
活动'
:
'编辑线下活动
'
}
goBack=
{
this
.
handleGoBack
}
/>
<
div
className=
'box'
>
<
div
className=
'show-tips'
>
...
...
@@ -723,11 +723,11 @@ class AddOfflineCourse extends React.Component {
</
span
>
<
Input
value=
{
courseName
}
placeholder=
'请输入线下
课
的名称(40字以内)'
placeholder=
'请输入线下
活动
的名称(40字以内)'
maxLength=
{
40
}
style=
{
{
width
:
240
}
}
onChange=
{
(
e
)
=>
{
this
.
setState
({
courseName
:
e
.
target
.
value
})
;
this
.
setState
({
courseName
:
e
.
target
.
value
})
}
}
/>
</
div
>
...
...
@@ -740,7 +740,7 @@ class AddOfflineCourse extends React.Component {
onClick=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
true
,
})
;
})
}
}
>
上传图片
</
Button
>
...
...
@@ -759,7 +759,13 @@ class AddOfflineCourse extends React.Component {
<
span
className=
'label special'
>
<
span
className=
'require'
>
*
</
span
>
课程分类:
</
span
>
<
TreeSelect
<
CourseCatalogSelect
value=
{
categoryId
}
onChange=
{
(
value
,
label
)
=>
{
this
.
handleChangeCatalogList
(
value
,
label
)
}
}
/>
{
/* <TreeSelect
showSearch
treeNodeFilterProp='title'
style={{ width: 240 }}
...
...
@@ -770,9 +776,9 @@ class AddOfflineCourse extends React.Component {
value={categoryId}
treeDefaultExpandAll
onChange={(value, label) => {
this
.
handleChangeCatalogList
(
value
,
label
)
;
this.handleChangeCatalogList(value, label)
}}
/>
/>
*/
}
</
div
>
<
div
className=
'course-catalog'
>
<
span
className=
'label special'
>
...
...
@@ -784,7 +790,7 @@ class AddOfflineCourse extends React.Component {
style=
{
{
width
:
240
}
}
placeholder=
'请输入上课地点(40字以内)'
onChange=
{
(
e
)
=>
{
this
.
setState
({
offlinePlace
:
e
.
target
.
value
})
;
this
.
setState
({
offlinePlace
:
e
.
target
.
value
})
}
}
/>
</
div
>
...
...
@@ -808,22 +814,22 @@ class AddOfflineCourse extends React.Component {
}
onChange=
{
(
value
,
option
)
=>
{
if
(
option
)
{
this
.
setState
({
teacherId
:
value
,
teacherName
:
option
.
children
})
;
this
.
setState
({
teacherId
:
value
,
teacherName
:
option
.
children
})
}
else
{
this
.
setState
({
teacherId
:
value
,
teacherName
:
''
})
;
this
.
setState
({
teacherId
:
value
,
teacherName
:
''
})
}
}
}
onSearch=
{
(
value
)
=>
{
let
_teacherQuery
=
{
...
this
.
state
.
teacherQuery
}
;
_teacherQuery
.
nickName
=
value
;
let
_teacherQuery
=
{
...
this
.
state
.
teacherQuery
}
_teacherQuery
.
nickName
=
value
this
.
setState
(
{
teacherQuery
:
_teacherQuery
,
},
()
=>
{
this
.
getTeacherList
()
;
this
.
getTeacherList
()
}
)
;
)
}
}
onClear=
{
(
value
)
=>
{
this
.
setState
(
...
...
@@ -835,9 +841,9 @@ class AddOfflineCourse extends React.Component {
},
},
()
=>
{
this
.
getTeacherList
()
;
this
.
getTeacherList
()
}
)
;
)
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
'teacher'
)
}
>
{
_
.
map
(
teacherList
,
(
item
)
=>
{
...
...
@@ -845,7 +851,7 @@ class AddOfflineCourse extends React.Component {
<
Option
value=
{
item
.
id
}
key=
{
item
.
id
}
>
{
item
.
nickName
}
</
Option
>
)
;
)
})
}
</
Select
>
</
div
>
...
...
@@ -863,7 +869,7 @@ class AddOfflineCourse extends React.Component {
content
:
introduce
,
}
}
onChange=
{
(
val
)
=>
{
this
.
changeIntro
(
val
)
;
this
.
changeIntro
(
val
)
}
}
/>
)
}
...
...
@@ -900,7 +906,7 @@ class AddOfflineCourse extends React.Component {
showNow=
{
false
}
style=
{
{
width
:
100
,
minWidth
:
100
}
}
onSelect=
{
(
time
)
=>
{
this
.
setState
({
startTime
:
time
})
;
this
.
setState
({
startTime
:
time
})
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
'hour'
)
}
/>
...
...
@@ -914,7 +920,7 @@ class AddOfflineCourse extends React.Component {
showNow=
{
false
}
style=
{
{
width
:
100
,
minWidth
:
100
}
}
onSelect=
{
(
time
)
=>
{
this
.
setState
({
endTime
:
time
})
;
this
.
setState
({
endTime
:
time
})
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
'hour'
)
}
/>
...
...
@@ -927,7 +933,7 @@ class AddOfflineCourse extends React.Component {
style=
{
{
display
:
'inline-block'
}
}
value=
{
offlineCourseType
}
onChange=
{
(
e
)
=>
{
this
.
setState
({
offlineCourseType
:
e
.
target
.
value
})
;
this
.
setState
({
offlineCourseType
:
e
.
target
.
value
})
}
}
className=
'mt5'
disabled=
{
isEditDisablie
}
>
...
...
@@ -952,8 +958,8 @@ class AddOfflineCourse extends React.Component {
startTimeApply
:
undefined
,
endTimeApply
:
undefined
,
quota
:
null
,
whetherVisitorsJoin
:
value
?
whetherVisitorsJoin
:
'YES'
})
;
whetherVisitorsJoin
:
value
?
whetherVisitorsJoin
:
'YES'
,
})
}
}
/>
<
span
className=
'switch-tip'
>
开启后可设置课程报名时间,获取报名数据
</
span
>
...
...
@@ -968,7 +974,7 @@ class AddOfflineCourse extends React.Component {
value=
{
startTimeApply
?
[
moment
(
startTimeApply
),
moment
(
endTimeApply
)]
:
null
}
format=
{
'YYYY-MM-DD HH:mm'
}
onChange=
{
(
dates
)
=>
{
this
.
handleChangeDates
(
dates
)
;
this
.
handleChangeDates
(
dates
)
}
}
renderExtraFooter=
{
()
=>
(
<
If
condition=
{
calendarTime
[
0
]
}
>
...
...
@@ -1055,7 +1061,7 @@ class AddOfflineCourse extends React.Component {
style=
{
{
margin
:
'0 4px'
,
width
:
90
}
}
disabled=
{
oldQuta
<
0
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
quota
:
value
})
;
this
.
setState
({
quota
:
value
})
}
}
/>
<
span
className=
'switch-label'
>
人
</
span
>
...
...
@@ -1068,7 +1074,9 @@ class AddOfflineCourse extends React.Component {
<
span
className=
'label'
>
观看设置:
</
span
>
<
div
className=
'content'
>
<
Switch
checked=
{
whetherVisitorsJoin
===
'NO'
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
<
div
className=
'desc'
>
{
whetherVisitorsJoin
===
'NO'
?
'已开启,仅限绑定了手机号的学员报名线下课'
:
'已关闭,允许未绑定手机号的学员报名线下课'
}
</
div
>
<
div
className=
'desc'
>
{
whetherVisitorsJoin
===
'NO'
?
'已开启,仅限绑定了手机号的学员报名线下活动'
:
'已关闭,允许未绑定手机号的学员报名线下活动'
}
</
div
>
</
div
>
</
div
>
<
div
className=
'course-catalog'
>
...
...
@@ -1083,7 +1091,7 @@ class AddOfflineCourse extends React.Component {
signInType
:
'START_AGO'
,
signInTimeNum
:
null
,
signInTimeUnit
:
'MINUTE'
,
})
;
})
}
}
/>
<
span
className=
'switch-tip'
>
开启后可设置获取签到考勤数据
</
span
>
...
...
@@ -1095,7 +1103,7 @@ class AddOfflineCourse extends React.Component {
style=
{
{
display
:
'inline-block'
}
}
value=
{
signInType
}
onChange=
{
(
e
)
=>
{
this
.
setState
({
signInType
:
e
.
target
.
value
})
;
this
.
setState
({
signInType
:
e
.
target
.
value
})
}
}
className=
'mt5'
>
<
Radio
value=
'START_AGO'
className=
'mr-16'
>
...
...
@@ -1117,18 +1125,18 @@ class AddOfflineCourse extends React.Component {
precision=
{
0
}
style=
{
{
margin
:
'0 4px'
,
width
:
90
}
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
signInTimeNum
:
value
})
;
this
.
setState
({
signInTimeNum
:
value
})
}
}
/>
<
Select
style=
{
{
width
:
72
,
marginRight
:
4
}
}
value=
{
signInTimeUnit
}
onChange=
{
(
value
)
=>
{
const
data
=
{
signInTimeUnit
:
value
}
;
const
data
=
{
signInTimeUnit
:
value
}
if
(
value
===
'HOUR'
&&
signInTimeNum
>
24
)
{
data
.
signInTimeNum
=
24
;
data
.
signInTimeNum
=
24
}
this
.
setState
(
data
)
;
this
.
setState
(
data
)
}
}
>
{
unitList
.
map
((
item
)
=>
(
<
Option
value=
{
item
.
key
}
key=
{
item
.
key
}
>
...
...
@@ -1155,7 +1163,7 @@ class AddOfflineCourse extends React.Component {
signOutStartTimeUnit
:
'MINUTE'
,
signOutEndTimeNum
:
null
,
signOutEndTimeUnit
:
'MINUTE'
,
})
;
})
}
}
/>
<
span
className=
'switch-tip'
>
开启后可设置获取签退考勤数据
</
span
>
...
...
@@ -1167,7 +1175,7 @@ class AddOfflineCourse extends React.Component {
style=
{
{
display
:
'inline-block'
}
}
value=
{
signOutType
}
onChange=
{
(
e
)
=>
{
this
.
setState
({
signOutType
:
e
.
target
.
value
})
;
this
.
setState
({
signOutType
:
e
.
target
.
value
})
}
}
className=
'mt5'
>
<
Radio
value=
'START_LATER'
className=
'mr-16'
>
...
...
@@ -1190,7 +1198,7 @@ class AddOfflineCourse extends React.Component {
precision=
{
0
}
style=
{
{
margin
:
'0 4px'
,
width
:
90
}
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
signOutStartTimeNum
:
value
})
;
this
.
setState
({
signOutStartTimeNum
:
value
})
}
}
/>
)
}
...
...
@@ -1199,11 +1207,11 @@ class AddOfflineCourse extends React.Component {
style=
{
{
width
:
72
,
marginRight
:
4
}
}
value=
{
signOutStartTimeUnit
}
onChange=
{
(
value
)
=>
{
const
data
=
{
signOutStartTimeUnit
:
value
}
;
const
data
=
{
signOutStartTimeUnit
:
value
}
if
(
value
===
'HOUR'
&&
signOutStartTimeNum
>
24
)
{
data
.
signOutStartTimeNum
=
24
;
data
.
signOutStartTimeNum
=
24
}
this
.
setState
(
data
)
;
this
.
setState
(
data
)
}
}
>
{
unitList
.
map
((
item
)
=>
(
<
Option
value=
{
item
.
key
}
key=
{
item
.
key
}
>
...
...
@@ -1220,18 +1228,18 @@ class AddOfflineCourse extends React.Component {
precision=
{
0
}
style=
{
{
margin
:
'0 4px'
,
width
:
90
}
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
signOutEndTimeNum
:
value
})
;
this
.
setState
({
signOutEndTimeNum
:
value
})
}
}
/>
<
Select
style=
{
{
width
:
72
,
marginRight
:
4
}
}
value=
{
signOutEndTimeUnit
}
onChange=
{
(
value
)
=>
{
const
data
=
{
signOutEndTimeUnit
:
value
}
;
const
data
=
{
signOutEndTimeUnit
:
value
}
if
(
value
===
'HOUR'
&&
signOutEndTimeNum
>
24
)
{
data
.
signOutEndTimeNum
=
24
;
data
.
signOutEndTimeNum
=
24
}
this
.
setState
(
data
)
;
this
.
setState
(
data
)
}
}
>
{
unitList
.
map
((
item
)
=>
(
<
Option
value=
{
item
.
key
}
key=
{
item
.
key
}
>
...
...
@@ -1266,7 +1274,7 @@ class AddOfflineCourse extends React.Component {
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectCoverModal
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
false
})
;
this
.
setState
({
showSelectCoverModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectCover
}
/>
...
...
@@ -1277,14 +1285,14 @@ class AddOfflineCourse extends React.Component {
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
})
;
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
{
this
.
state
.
previewOfflineModal
}
</
div
>
)
;
)
}
}
export
default
AddOfflineCourse
;
export
default
AddOfflineCourse
src/modules/course-manage/offline-course/components/OfflineCourseFilter.jsx
View file @
39be164c
...
...
@@ -136,10 +136,10 @@ class OfflineCourseFilter extends React.Component {
<
Row
type=
'flex'
justify=
'space-between'
align=
'top'
>
<
div
className=
'search-condition'
>
<
div
className=
'search-condition__item'
>
<
span
className=
'search-name'
>
线下
课
名称:
</
span
>
<
span
className=
'search-name'
>
线下
活动
名称:
</
span
>
<
Search
value=
{
courseName
}
placeholder=
'搜索线下
课
名称'
placeholder=
'搜索线下
活动
名称'
onChange=
{
(
e
)
=>
{
this
.
handleChangeQuery
(
'courseName'
,
e
.
target
.
value
)
}
}
...
...
src/modules/course-manage/offline-course/components/OfflineCourseFilter.less
View file @
39be164c
.video-course-filter {
position: relative;
.video-list-table{
.video-list-table
{
// tr:nth-child(even){
// background: transparent !important;
// }
// tr:nth-child(odd){
// td{
...
...
@@ -24,13 +23,14 @@
margin-bottom: 12px;
align-items: center;
display: flex;
.search-name{
.search-name {
width: 114px;
vertical-align: middle;
}
.shelf-status{
width:84px;
display:inline-block;
text-align:right;
.shelf-status
{
width:
84px;
display:
inline-block;
text-align:
right;
}
}
}
...
...
@@ -49,7 +49,7 @@
line-height: 20px;
.fold-icon {
font-size: 12px;
margin-left:4px;
margin-left:
4px;
}
}
}
...
...
src/modules/course-manage/offline-course/components/OfflineCourseList.jsx
View file @
39be164c
...
...
@@ -6,77 +6,77 @@
* @Description: 线上课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
Service
from
'@/common/js/service'
;
import
User
from
'@/common/js/user'
;
import
college
from
'@/common/lottie/college'
;
import
{
PageControl
,
XMTable
}
from
'@/components'
;
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
;
import
CourseService
from
'@/domains/course-domain/CourseService'
;
import
ShareLiveModal
from
'@/modules/course-manage/modal/ShareLiveModal'
;
import
OfflineCourseData
from
'@/modules/course-manage/offline-course/OfflineCourseData'
;
import
{
Dropdown
,
message
,
Modal
,
Switch
,
Tooltip
}
from
'antd'
;
import
moment
from
'moment'
;
import
React
from
'react'
;
import
{
find
,
reduce
,
last
}
from
'underscore'
;
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
ENUM
from
'../../../knowledge-base/ENUM.js'
;
import
PreviewOfflineModal
from
'../modal/PreviewOfflineModal'
;
import
QRCodeModal
from
'../modal/QRCodeModal'
;
import
'./OfflineCourseList.less'
;
import
Service
from
'@/common/js/service'
import
User
from
'@/common/js/user'
import
college
from
'@/common/lottie/college'
import
{
PageControl
,
XMTable
}
from
'@/components'
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
import
CourseService
from
'@/domains/course-domain/CourseService'
import
ShareLiveModal
from
'@/modules/course-manage/modal/ShareLiveModal'
import
OfflineCourseData
from
'@/modules/course-manage/offline-course/OfflineCourseData'
import
{
Dropdown
,
message
,
Modal
,
Switch
,
Tooltip
}
from
'antd'
import
moment
from
'moment'
import
React
from
'react'
import
{
find
,
reduce
,
last
}
from
'underscore'
import
{
Route
,
withRouter
}
from
'react-router-dom'
import
ENUM
from
'../../../knowledge-base/ENUM.js'
import
PreviewOfflineModal
from
'../modal/PreviewOfflineModal'
import
QRCodeModal
from
'../modal/QRCodeModal'
import
'./OfflineCourseList.less'
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
class
OfflineCourseList
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
id
:
''
,
// 线上课ID
studentIds
:
[],
}
;
}
}
componentDidMount
()
{
const
videoCourseItem
=
localStorage
.
getItem
(
'videoCourseItem'
)
;
const
videoCourseItem
=
localStorage
.
getItem
(
'videoCourseItem'
)
if
(
videoCourseItem
)
{
const
_videoCourseItem
=
JSON
.
parse
(
videoCourseItem
)
;
this
.
handleShowShareModal
(
_videoCourseItem
,
true
)
;
const
_videoCourseItem
=
JSON
.
parse
(
videoCourseItem
)
this
.
handleShowShareModal
(
_videoCourseItem
,
true
)
}
}
handlePlanName
=
(
planArray
)
=>
{
let
planStr
=
''
;
let
planStr
=
''
planArray
.
forEach
((
item
,
index
)
=>
{
if
(
index
<
planArray
.
length
-
1
)
{
planStr
=
planStr
+
item
.
planName
+
'、'
;
planStr
=
planStr
+
item
.
planName
+
'、'
}
else
{
planStr
=
planStr
+
item
.
planName
;
planStr
=
planStr
+
item
.
planName
}
})
;
return
planStr
;
}
;
})
return
planStr
}
// 请求表头
parseColumns
=
()
=>
{
const
columns
=
[
{
title
:
'线下
课
'
,
title
:
'线下
活动
'
,
key
:
'scheduleName'
,
dataIndex
:
'scheduleName'
,
width
:
321
,
fixed
:
'left'
,
render
:
(
val
,
record
)
=>
{
const
{
courseMediaVOS
,
courseName
,
offlinePlace
,
calendarTime
,
startTime
,
endTime
}
=
record
;
const
coverUrl
=
(
find
(
courseMediaVOS
,
(
data
)
=>
data
.
contentType
===
'COVER'
)
||
{}).
mediaUrl
;
let
isContinue
=
calendarTime
.
length
>
1
;
const
{
courseMediaVOS
,
courseName
,
offlinePlace
,
calendarTime
,
startTime
,
endTime
}
=
record
const
coverUrl
=
(
find
(
courseMediaVOS
,
(
data
)
=>
data
.
contentType
===
'COVER'
)
||
{}).
mediaUrl
let
isContinue
=
calendarTime
.
length
>
1
reduce
(
calendarTime
,
(
a
,
b
)
=>
{
isContinue
=
isContinue
&&
b
-
a
===
86400000
;
return
b
;
})
;
const
lastTime
=
last
(
calendarTime
)
;
isContinue
=
isContinue
&&
b
-
a
===
86400000
return
b
})
const
lastTime
=
last
(
calendarTime
)
const
time
=
`
${
!
isContinue
?
calendarTime
.
map
((
item
)
=>
moment
(
item
).
format
(
'MM-DD'
)).
join
(
'、'
)
:
`
${
moment
(
calendarTime
[
0
]).
format
(
'MM-DD'
)}
~
${
moment
(
lastTime
).
format
(
'MM-DD'
)}
`
}
${
moment
(
startTime
).
format
(
'HH:mm'
)}
~
${
moment
(
endTime
).
format
(
'HH:mm'
)}
`
;
}
${
moment
(
startTime
).
format
(
'HH:mm'
)}
~
${
moment
(
endTime
).
format
(
'HH:mm'
)}
`
return
(
<
div
className=
'record__item'
>
<
img
className=
'course-cover'
src=
{
coverUrl
||
defaultCoverUrl
}
alt=
''
/>
...
...
@@ -92,7 +92,7 @@ class OfflineCourseList extends React.Component {
</
Tooltip
>
</
div
>
</
div
>
)
;
)
},
},
{
...
...
@@ -106,7 +106,7 @@ class OfflineCourseList extends React.Component {
<
div
style=
{
{
width
:
6
,
height
:
6
,
borderRadius
:
'50%'
,
background
:
ENUM
.
offlineStateShow
[
val
].
color
,
marginRight
:
8
}
}
></
div
>
{
ENUM
.
offlineStateShow
[
val
].
title
}
</
div
>
)
;
)
},
},
{
...
...
@@ -115,7 +115,7 @@ class OfflineCourseList extends React.Component {
dataIndex
:
'categoryName'
,
width
:
120
,
render
:
(
val
,
record
)
=>
{
return
<
div
className=
'record__item'
>
{
record
.
categorySonName
}
</
div
>
;
return
<
div
className=
'record__item'
>
{
record
.
categorySonName
}
</
div
>
},
},
{
...
...
@@ -141,7 +141,7 @@ class OfflineCourseList extends React.Component {
render
:
(
val
,
item
,
index
)
=>
{
return
(
<
Switch
size=
'small'
disabled=
{
item
.
courseState
===
'EXPIRED'
}
checked=
{
item
.
shelfState
===
'YES'
}
onChange=
{
()
=>
this
.
changeShelfState
(
item
)
}
/>
)
;
)
},
},
{
...
...
@@ -150,7 +150,7 @@ class OfflineCourseList extends React.Component {
key
:
'teacher'
,
dataIndex
:
'teacher'
,
render
:
(
val
,
item
)
=>
{
return
<
div
>
{
item
.
teacherName
}
</
div
>
;
return
<
div
>
{
item
.
teacherName
}
</
div
>
},
},
{
...
...
@@ -178,7 +178,7 @@ class OfflineCourseList extends React.Component {
</
span
>
)
}
</
div
>
)
;
)
},
},
{
...
...
@@ -188,7 +188,7 @@ class OfflineCourseList extends React.Component {
dataIndex
:
'created'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
<
span
style=
{
{
whiteSpace
:
'nowrap'
}
}
>
{
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
;
return
<
span
style=
{
{
whiteSpace
:
'nowrap'
}
}
>
{
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
}
</
span
>
},
},
{
...
...
@@ -219,12 +219,12 @@ class OfflineCourseList extends React.Component {
</
span
>
</
Dropdown
>
</
div
>
)
;
)
},
},
]
;
return
columns
;
}
;
]
return
columns
}
// 显示预览弹窗
handleShowPreviewModal
=
(
courseId
)
=>
{
...
...
@@ -234,12 +234,12 @@ class OfflineCourseList extends React.Component {
close=
{
()
=>
{
this
.
setState
({
previewOfflineModal
:
null
,
})
;
})
}
}
/>
)
;
this
.
setState
({
previewOfflineModal
})
;
}
;
)
this
.
setState
({
previewOfflineModal
})
}
renderMoreOperate
=
(
item
)
=>
{
return
(
...
...
@@ -249,7 +249,7 @@ class OfflineCourseList extends React.Component {
className=
'operate__item'
key=
'qrcode'
onClick=
{
()
=>
{
this
.
setState
({
openQRCodeModal
:
true
,
qrcodeData
:
item
})
;
this
.
setState
({
openQRCodeModal
:
true
,
qrcodeData
:
item
})
}
}
>
考勤二维码
</
div
>
...
...
@@ -258,7 +258,7 @@ class OfflineCourseList extends React.Component {
className=
'operate__item'
key=
'preview'
onClick=
{
()
=>
{
this
.
handleShowPreviewModal
(
item
.
courseId
)
;
this
.
handleShowPreviewModal
(
item
.
courseId
)
}
}
>
预览
</
div
>
...
...
@@ -268,7 +268,7 @@ class OfflineCourseList extends React.Component {
className=
'operate__item'
key=
'cancel'
onClick=
{
()
=>
{
this
.
handleDeleteOfflineCourse
(
item
.
courseId
)
;
this
.
handleDeleteOfflineCourse
(
item
.
courseId
)
}
}
>
取消课程
</
div
>
...
...
@@ -278,7 +278,7 @@ class OfflineCourseList extends React.Component {
className=
'operate__item'
key=
'edit'
onClick=
{
()
=>
{
RCHistory
.
push
(
`/create-offline-course?type=edit&id=${item.courseId}`
)
;
RCHistory
.
push
(
`/create-offline-course?type=edit&id=${item.courseId}`
)
}
}
>
编辑
</
div
>
...
...
@@ -289,37 +289,37 @@ class OfflineCourseList extends React.Component {
</
div
>
)
}
</
div
>
)
;
}
;
)
}
//改变上架状态
changeShelfState
=
(
item
)
=>
{
if
(
!
window
.
ctx
.
xmState
.
storeUserPermissionList
.
includes
(
'EditOfflineClass'
))
{
message
.
warning
(
'无【编辑线下
课】权限,请联系管理员'
);
return
;
message
.
warning
(
'无【编辑线下
活动】权限,请联系管理员'
)
return
}
let
_shelfState
=
item
.
shelfState
;
let
_shelfState
=
item
.
shelfState
if
(
_shelfState
===
'NO'
)
{
_shelfState
=
'YES'
;
item
.
shelfState
=
'YES'
;
_shelfState
=
'YES'
item
.
shelfState
=
'YES'
}
else
{
_shelfState
=
'NO'
;
item
.
shelfState
=
'NO'
;
_shelfState
=
'NO'
item
.
shelfState
=
'NO'
}
const
params
=
{
courseId
:
item
.
courseId
,
shelfState
:
_shelfState
,
}
;
}
CourseService
.
changeVideoShelfState
(
params
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
if
(
_shelfState
===
'YES'
)
{
message
.
success
(
'已开启展示'
)
;
message
.
success
(
'已开启展示'
)
}
else
{
message
.
success
(
'已取消展示'
)
;
message
.
success
(
'已取消展示'
)
}
this
.
props
.
onChange
()
;
this
.
props
.
onChange
()
}
})
;
}
;
})
}
// 删除视频课
handleDeleteOfflineCourse
=
(
courseId
,
isDelete
)
=>
{
if
(
isDelete
)
{
...
...
@@ -333,13 +333,13 @@ class OfflineCourseList extends React.Component {
onOk
:
()
=>
{
const
param
=
{
courseId
:
courseId
,
}
;
}
Service
.
Hades
(
'public/hades/delOfflineCourse'
,
param
).
then
(()
=>
{
message
.
success
(
'删除成功'
)
;
this
.
props
.
onChange
()
;
})
;
message
.
success
(
'删除成功'
)
this
.
props
.
onChange
()
})
},
})
;
})
}
else
{
Modal
.
confirm
({
title
:
'取消课程'
,
...
...
@@ -350,82 +350,82 @@ class OfflineCourseList extends React.Component {
onOk
:
()
=>
{
const
param
=
{
courseId
:
courseId
,
}
;
}
Service
.
Hades
(
'public/hades/cancelOfflineCourse'
,
param
).
then
(()
=>
{
message
.
success
(
'取消成功'
)
;
this
.
props
.
onChange
()
;
})
;
message
.
success
(
'取消成功'
)
this
.
props
.
onChange
()
})
},
})
;
})
}
}
;
}
// 显示分享弹窗
handleShowShareModal
=
(
record
,
needStr
=
false
)
=>
{
const
{
courseId
}
=
record
;
const
htmlUrl
=
`
${
LIVE_SHARE
}
offline_detail/
${
courseId
}
?id=
${
User
.
getStoreId
()}
`
;
const
longUrl
=
htmlUrl
;
const
{
courseName
,
courseMediaVOS
}
=
record
;
const
coverUrl
=
(
_
.
find
(
courseMediaVOS
,
(
data
)
=>
data
.
contentType
===
'COVER'
)
||
{}).
mediaUrl
;
const
{
courseId
}
=
record
const
htmlUrl
=
`
${
LIVE_SHARE
}
offline_detail/
${
courseId
}
?id=
${
User
.
getStoreId
()}
`
const
longUrl
=
htmlUrl
const
{
courseName
,
courseMediaVOS
}
=
record
const
coverUrl
=
(
_
.
find
(
courseMediaVOS
,
(
data
)
=>
data
.
contentType
===
'COVER'
)
||
{}).
mediaUrl
const
shareData
=
{
longUrl
,
coverUrl
,
courseName
,
}
;
}
const
shareLiveModal
=
(
<
ShareLiveModal
needStr=
{
needStr
}
data=
{
shareData
}
type=
'offlineClass'
title=
'线下
课
'
title=
'线下
活动
'
close=
{
()
=>
{
this
.
setState
({
shareLiveModal
:
null
,
})
;
localStorage
.
setItem
(
'videoCourseItem'
,
''
)
;
})
localStorage
.
setItem
(
'videoCourseItem'
,
''
)
}
}
/>
)
;
)
this
.
setState
({
shareLiveModal
})
;
}
;
this
.
setState
({
shareLiveModal
})
}
handleChangeTable
=
(
pagination
,
filters
,
sorter
)
=>
{
const
{
columnKey
,
order
}
=
sorter
;
const
{
query
}
=
this
.
props
;
let
_columnKey
;
let
_order
;
const
{
columnKey
,
order
}
=
sorter
const
{
query
}
=
this
.
props
let
_columnKey
let
_order
// 按创建时间升序排序
if
(
columnKey
===
'apply'
&&
order
===
'ascend'
)
{
_columnKey
=
'START_APPLY_DESC'
;
_order
=
'SORT_ASC'
;
_columnKey
=
'START_APPLY_DESC'
_order
=
'SORT_ASC'
}
if
(
columnKey
===
'created'
&&
order
===
'ascend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_ASC'
;
_columnKey
=
'CREATED'
_order
=
'SORT_ASC'
}
// 按创建时间降序排序
if
(
columnKey
===
'apply'
&&
order
===
'descend'
)
{
_columnKey
=
'START_APPLY_DESC'
;
_order
=
'SORT_DESC'
;
_columnKey
=
'START_APPLY_DESC'
_order
=
'SORT_DESC'
}
if
(
columnKey
===
'created'
&&
order
===
'descend'
)
{
_columnKey
=
'CREATED'
;
_order
=
'SORT_DESC'
;
_columnKey
=
'CREATED'
_order
=
'SORT_DESC'
}
const
_query
=
{
...
query
,
sortMap
:
{},
}
;
_query
.
sortMap
[
_columnKey
]
=
_order
;
this
.
props
.
onChange
(
_query
)
;
}
;
}
_query
.
sortMap
[
_columnKey
]
=
_order
this
.
props
.
onChange
(
_query
)
}
render
()
{
const
{
openQRCodeModal
,
qrcodeData
}
=
this
.
state
;
const
{
dataSource
=
[],
totalCount
,
query
,
match
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
const
{
openQRCodeModal
,
qrcodeData
}
=
this
.
state
const
{
dataSource
=
[],
totalCount
,
query
,
match
}
=
this
.
props
const
{
current
,
size
}
=
query
return
(
<
div
className=
'offline-course-list'
>
<
XMTable
...
...
@@ -449,8 +449,8 @@ class OfflineCourseList 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
)
}
}
/>
</
div
>
...
...
@@ -460,13 +460,13 @@ class OfflineCourseList extends React.Component {
visible=
{
openQRCodeModal
}
data=
{
qrcodeData
}
onCancel=
{
()
=>
{
this
.
setState
({
openQRCodeModal
:
false
})
;
this
.
setState
({
openQRCodeModal
:
false
})
}
}
/>
<
Route
path=
{
`${match.url}/data`
}
component=
{
OfflineCourseData
}
/>
</
div
>
)
;
)
}
}
export
default
withRouter
(
OfflineCourseList
)
;
export
default
withRouter
(
OfflineCourseList
)
src/modules/course-manage/offline-course/components/OfflineCourseOpt.jsx
View file @
39be164c
...
...
@@ -6,23 +6,23 @@
* @Description: 线上课-操作模块
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
;
import
{
Button
}
from
'antd'
;
import
'./OfflineCourseOpt.less'
;
import
React
from
'react'
import
{
Button
}
from
'antd'
export
default
function
OfflineCourseOpt
()
{
import
'./OfflineCourseOpt.less'
export
default
function
OfflineCourseOpt
()
{
return
(
<
div
className=
"video-course-opt"
>
<
div
className=
'video-course-opt'
>
<
Button
type=
"primary"
type=
'primary'
onClick=
{
()
=>
{
RCHistory
.
push
(
'/create-offline-course?type=add'
)
;
RCHistory
.
push
(
'/create-offline-course?type=add'
)
}
}
className=
"mr12"
>
新建线下课
</
Button
>
className=
'mr12'
>
新建线下活动
</
Button
>
</
div
>
)
;
)
}
src/modules/course-manage/offline-course/index.jsx
View file @
39be164c
import
React
from
'react'
;
import
React
from
'react'
import
OfflineCourseFilter
from
'./components/OfflineCourseFilter'
;
import
OfflineCourseOpt
from
'./components/OfflineCourseOpt'
;
import
OfflineCourseList
from
'./components/OfflineCourseList'
;
import
Service
from
'@/common/js/service'
;
import
OfflineCourseFilter
from
'./components/OfflineCourseFilter'
import
OfflineCourseOpt
from
'./components/OfflineCourseOpt'
import
OfflineCourseList
from
'./components/OfflineCourseList'
import
Service
from
'@/common/js/service'
import
User
from
'@/common/js/user'
class
OfflineCoursePage
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
query
:
{
size
:
10
,
current
:
1
,
storeId
:
User
.
getStoreId
()
storeId
:
User
.
getStoreId
(),
},
dataSource
:
[],
// 线下课列表
totalCount
:
0
,
// 线下课数据总条数
dataSource
:
[],
// 线下课列表
totalCount
:
0
,
// 线下课数据总条数
}
}
componentWillMount
()
{
// 获取线下课列表
this
.
handleFetchScheduleList
()
;
this
.
handleFetchScheduleList
()
}
// 获取线下课列表
handleFetchScheduleList
=
(
_query
=
{})
=>
{
const
query
=
{
...
this
.
state
.
query
,
...
_query
}
;
...
_query
,
}
// 更新请求参数
this
.
setState
({
query
})
;
this
.
setState
({
query
})
Service
.
Hades
(
'public/hades/getOfflineCoursePage'
,
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
)
})
;
totalCount
:
Number
(
total
)
,
})
})
}
render
()
{
const
{
dataSource
,
totalCount
,
query
}
=
this
.
state
;
const
{
dataSource
,
totalCount
,
query
}
=
this
.
state
return
(
<
div
className=
"page video-course-page"
>
<
div
className=
"content-header"
>
线下课
</
div
>
<
div
className=
'page video-course-page'
>
<
div
className=
'content-header'
>
线下活动
</
div
>
<
div
className=
"box"
>
<
div
className=
'box'
>
{
/* 搜索模块 */
}
<
OfflineCourseFilter
onChange=
{
this
.
handleFetchScheduleList
}
/>
<
OfflineCourseFilter
onChange=
{
this
.
handleFetchScheduleList
}
/>
{
/* 操作模块 */
}
{
window
.
ctx
.
xmState
.
storeUserPermissionList
.
includes
(
'AddOfflineClass'
)
&&
<
OfflineCourseOpt
/>
}
{
/* 线下课列表模块 */
}
<
OfflineCourseList
query=
{
query
}
dataSource=
{
dataSource
}
totalCount=
{
totalCount
}
onChange=
{
this
.
handleFetchScheduleList
}
/>
<
OfflineCourseList
query=
{
query
}
dataSource=
{
dataSource
}
totalCount=
{
totalCount
}
onChange=
{
this
.
handleFetchScheduleList
}
/>
</
div
>
</
div
>
)
}
}
export
default
OfflineCoursePage
;
export
default
OfflineCoursePage
src/modules/course-manage/offline-course/modal/PreviewOfflineModal.jsx
View file @
39be164c
import
React
from
'react'
;
import
{
Modal
}
from
'antd'
;
import
moment
from
'moment'
;
import
$
from
'jquery'
;
import
Service
from
"@/common/js/service"
;
import
'./PreviewOfflineModal.less'
;
import
ENUM
from
'@/modules/knowledge-base/ENUM'
;
import
React
from
'react'
import
{
Modal
}
from
'antd'
import
moment
from
'moment'
import
$
from
'jquery'
import
Service
from
'@/common/js/service'
import
'./PreviewOfflineModal.less'
import
ENUM
from
'@/modules/knowledge-base/ENUM'
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
;
const
defaultCoverUrl
=
'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'
class
PreviewOfflineModal
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
}
super
(
props
)
this
.
state
=
{}
}
componentDidMount
()
{
const
{
data
}
=
this
.
props
;
_
.
isEmpty
(
data
)
?
this
.
getCourseDetail
()
:
this
.
setState
({
...
data
})
;
const
{
data
}
=
this
.
props
_
.
isEmpty
(
data
)
?
this
.
getCourseDetail
()
:
this
.
setState
({
...
data
})
}
getCourseDetail
=
()
=>
{
...
...
@@ -26,20 +24,20 @@ class PreviewOfflineModal extends React.Component {
courseId
:
this
.
props
.
courseId
,
}).
then
((
res
)
=>
{
if
(
res
.
success
)
{
const
{
result
}
=
res
;
let
coverUrl
=
''
;
const
{
result
}
=
res
let
coverUrl
=
''
result
.
courseMediaVOS
.
map
((
item
)
=>
{
switch
(
item
.
contentType
){
case
"COVER"
:
coverUrl
=
item
.
mediaUrl
;
break
;
case
"INTRO"
:
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
;
break
;
switch
(
item
.
contentType
)
{
case
'COVER'
:
coverUrl
=
item
.
mediaUrl
break
case
'INTRO'
:
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
)
break
default
:
break
;
break
}
return
item
;
return
item
})
this
.
setState
({
...
result
,
...
...
@@ -54,10 +52,10 @@ class PreviewOfflineModal extends React.Component {
data
:
{},
type
:
'GET'
,
url
,
contentType
:
'application/x-www-form-urlencoded; charset=UTF-8'
,
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
})
}
,
})
}
...
...
@@ -85,79 +83,82 @@ class PreviewOfflineModal extends React.Component {
signOutStartTimeUnit
,
signOutEndTimeNum
,
signOutEndTimeUnit
,
}
=
this
.
state
;
const
unit
=
(
signInTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
;
const
time
=
(
signInType
===
'START_AGO'
?
startTime
:
endTime
)
&&
moment
(
signInType
===
'START_AGO'
?
startTime
:
endTime
).
subtract
(
signInTimeNum
,
unit
)
;
const
signInTime
=
(
time
&&
signInTimeNum
)
&&
`
${
moment
(
time
).
format
(
'HH:mm'
)}
~
${
moment
(
signInType
===
'START_AGO'
?
startTime
:
endTime
).
format
(
'HH:mm'
)}
`
;
const
endUnit
=
(
signOutEndTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
;
const
end
=
(
endTime
&&
signOutEndTimeNum
)
&&
moment
(
endTime
).
add
(
signOutEndTimeNum
,
endUnit
);
let
startUnit
=
''
;
let
start
=
''
;
}
=
this
.
state
const
unit
=
(
signInTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
const
time
=
(
signInType
===
'START_AGO'
?
startTime
:
endTime
)
&&
moment
(
signInType
===
'START_AGO'
?
startTime
:
endTime
).
subtract
(
signInTimeNum
,
unit
)
const
signInTime
=
time
&&
signInTimeNum
&&
`
${
moment
(
time
).
format
(
'HH:mm'
)}
~
${
moment
(
signInType
===
'START_AGO'
?
startTime
:
endTime
).
format
(
'HH:mm'
)}
`
const
endUnit
=
(
signOutEndTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
const
end
=
endTime
&&
signOutEndTimeNum
&&
moment
(
endTime
).
add
(
signOutEndTimeNum
,
endUnit
)
let
startUnit
=
''
let
start
=
''
if
(
signOutType
===
'START_LATER'
)
{
startUnit
=
(
signOutStartTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
;
start
=
(
startTime
&&
signOutStartTimeNum
)
&&
moment
(
startTime
).
add
(
signOutStartTimeNum
,
startUnit
);
startUnit
=
(
signOutStartTimeUnit
||
''
).
toLocaleLowerCase
()
+
's'
start
=
startTime
&&
signOutStartTimeNum
&&
moment
(
startTime
).
add
(
signOutStartTimeNum
,
startUnit
)
}
console
.
log
(
start
,
end
,
startTime
,
endTime
,
666666
)
const
signOutTime
=
(
start
||
end
)
&&
(
signOutType
===
'START_LATER'
?
`
${
moment
(
start
).
format
(
'HH:mm'
)}
~
${
moment
(
end
).
format
(
'HH:mm'
)}
`
:
`
${
moment
(
endTime
).
format
(
'HH:mm'
)}
~
${
moment
(
end
).
format
(
'HH:mm'
)}
`
);
const
signOutTime
=
(
start
||
end
)
&&
(
signOutType
===
'START_LATER'
?
`
${
moment
(
start
).
format
(
'HH:mm'
)}
~
${
moment
(
end
).
format
(
'HH:mm'
)}
`
:
`
${
moment
(
endTime
).
format
(
'HH:mm'
)}
~
${
moment
(
end
).
format
(
'HH:mm'
)}
`
)
return
(
<
Modal
title=
"预览"
title=
'预览'
visible=
{
true
}
width=
{
680
}
onCancel=
{
this
.
props
.
close
}
footer=
{
null
}
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
"icon iconfont modal-close-icon"
>

</
span
>
}
className=
"preview-offline-modal"
>
<
div
className=
"container__wrap"
>
<
div
className=
"container"
>
<
div
className=
"container__header"
>
<
div
className=
"cover"
></
div
>
<
img
src=
{
coverUrl
||
defaultCoverUrl
}
className=
"course-cover"
/>
<
span
className=
"cover-teacher"
>
主讲人:
{
teacherName
}
</
span
>
<
span
className=
"cover-state"
style=
{
{
background
:
(
ENUM
.
offlineStateShow
[
courseState
]
||
{}).
color
}
}
>
{
(
ENUM
.
offlineStateShow
[
courseState
]
||
{}).
title
}
</
span
>
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
className=
'preview-offline-modal'
>
<
div
className=
'container__wrap'
>
<
div
className=
'container'
>
<
div
className=
'container__header'
>
<
div
className=
'cover'
></
div
>
<
img
src=
{
coverUrl
||
defaultCoverUrl
}
className=
'course-cover'
/>
<
span
className=
'cover-teacher'
>
主讲人:
{
teacherName
}
</
span
>
<
span
className=
'cover-state'
style=
{
{
background
:
(
ENUM
.
offlineStateShow
[
courseState
]
||
{}).
color
}
}
>
{
(
ENUM
.
offlineStateShow
[
courseState
]
||
{}).
title
}
</
span
>
</
div
>
<
div
className=
"container__body"
>
<
div
className=
"title__name"
>
{
courseName
}
</
div
>
<
div
className=
"title__categery"
>
<
img
className=
"item-icon"
src=
"https://image.xiaomaiketang.com/xm/cDMwz3jzaX.png"
/>
<
div
className=
'container__body'
>
<
div
className=
'title__name'
>
{
courseName
}
</
div
>
<
div
className=
'title__categery'
>
<
img
className=
'item-icon'
src=
'https://image.xiaomaiketang.com/xm/cDMwz3jzaX.png'
/>
课程分类:
{
categoryName
}
</
div
>
<
div
className=
"title__categery"
>
<
img
className=
"item-icon"
src=
"https://image.xiaomaiketang.com/xm/BfTBK3dGda.png"
/>
<
div
className=
'title__categery'
>
<
img
className=
'item-icon'
src=
'https://image.xiaomaiketang.com/xm/BfTBK3dGda.png'
/>
上课时间:
{
startTime
?
moment
(
startTime
).
format
(
'HH:mm'
)
:
''
}
~
{
endTime
?
moment
(
endTime
).
format
(
'HH:mm'
)
:
''
}
</
div
>
<
div
className=
"title__categery"
>
<
img
className=
"item-icon"
src=
"https://image.xiaomaiketang.com/xm/KhFNBTtAKR.png"
/>
<
div
className=
'title__categery'
>
<
img
className=
'item-icon'
src=
'https://image.xiaomaiketang.com/xm/KhFNBTtAKR.png'
/>
上课地点:
{
offlinePlace
}
</
div
>
</
div
>
<
div
className=
"container__introduction"
>
<
div
className=
"title"
>
线下课简介
</
div
>
<
div
className=
"container__introduction__list editor-box"
>
{
whetherSetApply
===
'YES'
&&
<
div
className=
"course-time"
>
<
div
className=
"time-title"
>
报名时间
</
div
>
<
div
className=
"time-text"
>
{
startTimeApply
&&
moment
(
startTimeApply
).
format
(
'MM-DD HH:mm'
)
}
~
{
endTimeApply
&&
moment
(
endTimeApply
).
format
(
'MM-DD HH:mm'
)
}
</
div
>
</
div
>
}
{
(
whetherSetSignIn
===
'YES'
||
whetherSetSignOut
===
'YES'
)
&&
<
div
className=
"course-time"
>
<
div
className=
"time-title"
>
考勤时间
</
div
>
{
whetherSetSignIn
===
'YES'
&&
<
div
className=
"time-text"
>
签到:
{
signInTime
}
</
div
>
}
{
whetherSetSignOut
===
'YES'
&&
<
div
className=
"time-text"
>
签退:
{
signOutTime
}
</
div
>
<
div
className=
'container__introduction'
>
<
div
className=
'title'
>
线下活动简介
</
div
>
<
div
className=
'container__introduction__list editor-box'
>
{
whetherSetApply
===
'YES'
&&
(
<
div
className=
'course-time'
>
<
div
className=
'time-title'
>
报名时间
</
div
>
<
div
className=
'time-text'
>
{
startTimeApply
&&
moment
(
startTimeApply
).
format
(
'MM-DD HH:mm'
)
}
~
{
endTimeApply
&&
moment
(
endTimeApply
).
format
(
'MM-DD HH:mm'
)
}
</
div
>
}
</
div
>
}
</
div
>
)
}
{
(
whetherSetSignIn
===
'YES'
||
whetherSetSignOut
===
'YES'
)
&&
(
<
div
className=
'course-time'
>
<
div
className=
'time-title'
>
考勤时间
</
div
>
{
whetherSetSignIn
===
'YES'
&&
<
div
className=
'time-text'
>
签到:
{
signInTime
}
</
div
>
}
{
whetherSetSignOut
===
'YES'
&&
<
div
className=
'time-text'
>
签退:
{
signOutTime
}
</
div
>
}
</
div
>
)
}
<
div
className=
"intro-item text"
className=
'intro-item text'
dangerouslySetInnerHTML=
{
{
__html
:
introduce
__html
:
introduce
,
}
}
/>
</
div
>
...
...
@@ -169,4 +170,4 @@ class PreviewOfflineModal extends React.Component {
}
}
export
default
PreviewOfflineModal
;
export
default
PreviewOfflineModal
src/modules/course-manage/video-course/AddVideoCourse.jsx
View file @
39be164c
...
...
@@ -7,31 +7,30 @@
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
import
{
Button
,
Input
,
message
,
Modal
,
Cascader
,
Tooltip
,
Form
,
Popconfirm
,
Menu
,
Dropdown
}
from
'antd'
import
{
FileTypeIcon
,
FileVerifyMap
}
from
'@/common/constants/academic/lessonEnum'
import
ShowTips
from
'@/components/ShowTips'
import
Breadcrumbs
from
'@/components/Breadcrumbs'
import
moment
from
'moment'
import
AddVideoIntro
from
'./components/AddVideoIntro'
import
SelectStudent
from
'../modal/select-student'
import
Select
PrepareFileModal
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
ImgClipModal
from
'@/components/ImgClipModal'
import
$
from
'jquery'
import
'./AddVideoCourse.less'
import
Bus
from
'@/core/bus'
import
React
from
'react'
;
import
{
Button
,
Input
,
message
,
Modal
,
Tooltip
,
Form
,
Popconfirm
,
Menu
,
Dropdown
}
from
'antd'
;
import
{
FileTypeIcon
}
from
'@/common/constants/academic/lessonEnum'
;
import
{
CourseCatalogSelect
}
from
'@/modules/common'
;
import
ShowTips
from
'@/components/ShowTips'
;
import
Breadcrumbs
from
'@/components/Breadcrumbs'
;
import
moment
from
'moment'
;
import
AddVideoIntro
from
'./components/AddVideoIntro'
;
import
Select
Student
from
'../modal/select-student'
;
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
;
import
PreviewCourseModal
from
'../modal/PreviewCourseModal'
;
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
ImgClipModal
from
'@/components/ImgClipModal'
;
import
$
from
'jquery'
;
import
'./AddVideoCourse.less'
;
import
Bus
from
'@/core/bus'
;
const
{
TextArea
}
=
Input
;
const
EDIT_BOX_KEY
=
Math
.
random
()
const
fieldNames
=
{
label
:
'categoryName'
,
value
:
'id'
,
children
:
'sonCategoryList'
}
const
EDIT_BOX_KEY
=
Math
.
random
();
//添加课程时课程默认的一些值
const
defaultShelfState
=
'YES'
;
...
...
@@ -47,11 +46,11 @@ const whetherVisitorsJoin = 'NO';
let
cutFlag
=
false
;
const
SUPPORT_WORD_PDF
=
[
"application/msword"
,
"application/wps-writer"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
,
"application/pdf"
,
"application/wps-office.pdf"
'application/msword'
,
'application/wps-writer'
,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
,
'application/pdf'
,
'application/wps-office.pdf'
,
];
class
AddVideoCourse
extends
React
.
Component
{
constructor
(
props
)
{
...
...
@@ -84,24 +83,21 @@ class AddVideoCourse extends React.Component {
showSelectFileModal
:
false
,
studentModal
:
false
,
categoryName
:
null
,
//分类名称
courseCatalogList
:
[],
//分类列表
categoryId
:
null
,
//分类的Id值
whetherVisitorsJoin
:
'NO'
,
// 是否允许游客加入
showSelectCoverModal
:
false
,
cutImageBlob
:
null
,
introduce
:
''
,
courseChapterList
:[
],
// 课节列表
courseChapterList
:
[],
// 课节列表
// videoType: "MP4",
mediaNameAlias
:
''
,
// 任一视频重命名的名称(气泡框)
selectTypeList
:[
'MP4'
],
accept
:
'video/mp4'
}
selectTypeList
:
[
'MP4'
],
accept
:
'video/mp4'
,
}
;
}
componentWillMount
()
{
const
{
id
,
pageType
}
=
this
.
state
;
this
.
getCourseCatalogList
();
if
(
pageType
===
'edit'
)
{
this
.
handleFetchScheudleDetail
(
id
);
}
...
...
@@ -112,51 +108,29 @@ class AddVideoCourse extends React.Component {
});
}
//获取分类列表
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
this
.
setState
({
courseCatalogList
:
res
.
result
.
records
,
});
});
handleChangeCatalogList
=
(
value
,
label
)
=>
{
this
.
setState
({
categoryId
:
value
,
categoryName
:
label
[
0
]
});
};
catalogChange
=
(
value
,
_categoryName
)
=>
{
const
categoryName
=
_
.
pluck
(
_categoryName
,
'categoryName'
).
join
(
'-'
)
const
changeValueLength
=
value
.
length
switch
(
changeValueLength
)
{
case
1
:
this
.
setState
({
categoryId
:
value
[
0
],
categoryName
})
break
case
2
:
this
.
setState
({
categoryId
:
value
[
1
],
categoryName
})
break
default
:
this
.
setState
({
categoryId
:
null
});
break
;
}
}
// 获取线上课详情
handleFetchScheudleDetail
=
(
courseId
)
=>
{
CourseService
.
videoScheduleDetail
({
courseId
,
}).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
||
{}
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
categoryOneName
,
categoryTwoName
,
categoryId
,
courseChapterVOList
=
[]
}
=
result
let
coverId
let
coverUrl
// let videoDuration
// let videoName
let
scheduleMedia
=
[]
let
scheduleVideoUrl
let
hasIntro
const
{
result
=
{}
}
=
res
||
{};
const
{
courseName
,
shelfState
,
whetherVisitorsJoin
,
courseMediaVOS
,
categoryId
,
courseChapterVOList
=
[]
}
=
result
;
let
coverId
;
let
coverUrl
;
let
scheduleMedia
=
[];
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
'INTRO'
:
hasIntro
=
true
;
this
.
getTextDetail
(
'introduce'
,
item
.
mediaUrl
);
...
...
@@ -167,36 +141,26 @@ class AddVideoCourse extends React.Component {
return
item
;
});
let
categoryName
;
if
(
categoryTwoName
)
{
categoryName
=
`
${
categoryOneName
}
-
${
categoryTwoName
}
`
;
}
else
{
categoryName
=
`
${
categoryOneName
}
`
;
}
const
_courseChapterVOList
=
courseChapterVOList
.
map
(
item
=>
{
const
_courseChapterVOList
=
courseChapterVOList
.
map
((
item
)
=>
{
item
.
mediaName
=
item
.
name
;
item
.
resourceId
=
item
.
id
;
return
item
})
return
item
;
})
;
this
.
setState
({
loadintroduce
:
!
hasIntro
,
coverId
,
coverUrl
,
// videoName,
// videoDuration,
scheduleMedia
,
courseName
,
scheduleVideoUrl
,
shelfState
,
whetherVisitorsJoin
,
categoryName
,
categoryId
,
courseChapterList
:
_courseChapterVOList
})
})
}
courseChapterList
:
_courseChapterVOList
,
})
;
})
;
}
;
getTextDetail
=
(
key
,
url
)
=>
{
$
.
ajax
({
...
...
@@ -211,7 +175,7 @@ class AddVideoCourse extends React.Component {
};
handleGoBack
=
()
=>
{
const
{
coverId
,
courseName
,
scheduleMedia
,
courseChapterList
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
const
{
coverId
,
courseName
,
scheduleMedia
,
courseChapterList
,
categoryId
,
shelfState
,
whetherVisitorsJoin
}
=
this
.
state
;
if
(
!
courseChapterList
.
length
||
!
_
.
isEqual
(
scheduleMedia
,
defaultScheduleMedia
)
||
...
...
@@ -281,17 +245,17 @@ class AddVideoCourse extends React.Component {
// 显示预览弹窗
handleShowPreviewModal
=
()
=>
{
const
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
scheduleMedia
,
introduce
,
courseChapterList
,
categoryName
}
=
this
.
state
const
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
scheduleMedia
,
introduce
,
courseChapterList
,
categoryName
}
=
this
.
state
;
const
courseBasinInfo
=
{
coverUrl
,
scheduleVideoUrl
,
courseName
,
}
}
;
const
courseIntroInfo
=
{
liveCourseMediaRequests
:
scheduleMedia
,
introduce
,
categoryName
}
categoryName
,
}
;
const
previewCourseModal
=
(
<
PreviewCourseModal
...
...
@@ -311,42 +275,41 @@ class AddVideoCourse extends React.Component {
};
// 选择视频
handleSelectVideo
=
(
addFolderIds
,
selectedFileList
)
=>
{
handleSelectVideo
=
(
addFolderIds
,
selectedFileList
)
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
showSelectFileModal
:
false
,
})
;
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
[...
courseChapterList
];
if
(
selectedFileList
.
length
+
courseChapterList
.
length
>
20
)
{
if
(
selectedFileList
.
length
+
courseChapterList
.
length
>
20
)
{
message
.
warning
(
`最多只能上传20个文件`
);
return
;
}
selectedFileList
.
map
((
file
,
index
)
=>
{
selectedFileList
.
map
((
file
,
index
)
=>
{
const
{
ossUrl
,
resourceId
,
folderName
,
folderFormat
,
folderSize
}
=
file
;
const
_mediaName
=
folderName
.
replace
(
`.
${
_
.
last
(
folderName
.
split
(
'.'
)).
toLowerCase
()}
`
,
''
)
console
.
log
(
'folderFormat'
,
folderFormat
);
if
(
folderFormat
===
'MP4'
||
folderFormat
===
'video/mp4'
)
{
const
videoDom
=
document
.
createElement
(
'video'
)
videoDom
.
src
=
ossUrl
const
_mediaName
=
folderName
.
replace
(
`.
${
_
.
last
(
folderName
.
split
(
'.'
)).
toLowerCase
()}
`
,
''
);
console
.
log
(
'folderFormat'
,
folderFormat
);
if
(
folderFormat
===
'MP4'
||
folderFormat
===
'video/mp4'
)
{
const
videoDom
=
document
.
createElement
(
'video'
)
;
videoDom
.
src
=
ossUrl
;
videoDom
.
onloadedmetadata
=
()
=>
{
_courseChapterList
.
push
({
mediaContent
:
resourceId
,
contentType
:
'SCHEDULE'
,
mediaType
:
"VIDEO"
,
mediaType
:
'VIDEO'
,
mediaName
:
_mediaName
,
videoDuration
:
videoDom
.
duration
,
resourceId
,
mediaUrl
:
ossUrl
,
sort
:
_courseChapterList
.
length
})
sort
:
_courseChapterList
.
length
,
})
;
this
.
setState
({
courseChapterList
:
_courseChapterList
})
}
}
else
if
(
folderFormat
===
"WORD"
||
folderFormat
===
"PDF"
||
SUPPORT_WORD_PDF
.
indexOf
(
folderFormat
)
>-
1
)
{
courseChapterList
:
_courseChapterList
,
})
;
}
;
}
else
if
(
folderFormat
===
'WORD'
||
folderFormat
===
'PDF'
||
SUPPORT_WORD_PDF
.
indexOf
(
folderFormat
)
>
-
1
)
{
const
suffix
=
_
.
last
(
folderName
.
split
(
'.'
)).
toUpperCase
();
_courseChapterList
.
push
({
mediaContent
:
resourceId
,
...
...
@@ -355,61 +318,60 @@ class AddVideoCourse extends React.Component {
mediaName
:
_mediaName
,
resourceId
,
mediaUrl
:
ossUrl
,
sort
:
_courseChapterList
.
length
})
sort
:
_courseChapterList
.
length
,
})
;
this
.
setState
({
courseChapterList
:
_courseChapterList
})
courseChapterList
:
_courseChapterList
,
})
;
}
})
}
});
};
// 校验课节名称
handleValidateChapterName
=
(
chapterName
)
=>
{
let
hasError
=
false
;
return
new
Promise
((
resolve
)
=>
{
if
(
!
chapterName
)
{
this
.
setState
({
chapterNameValidateStatus
:
"error"
,
chapterNameHelpMsg
:
'请输入课节名称'
})
hasError
=
true
;
resolve
(
false
)
return
false
}
if
(
chapterName
.
length
>
40
)
{
this
.
setState
({
chapterNameValidateStatus
:
"error"
,
chapterNameHelpMsg
:
'不要超过40字'
})
hasError
=
true
;
resolve
(
false
)
return
false
}
if
(
!
hasError
)
{
resolve
(
true
)
this
.
setState
({
chapterNameValidateStatus
:
""
,
chapterNameHelpMsg
:
""
})
}
})
}
// 校验课节名称
handleValidateChapterName
=
(
chapterName
)
=>
{
let
hasError
=
false
;
return
new
Promise
((
resolve
)
=>
{
if
(
!
chapterName
)
{
this
.
setState
({
chapterNameValidateStatus
:
'error'
,
chapterNameHelpMsg
:
'请输入课节名称'
,
});
hasError
=
true
;
resolve
(
false
);
return
false
;
}
if
(
chapterName
.
length
>
40
)
{
this
.
setState
({
chapterNameValidateStatus
:
'error'
,
chapterNameHelpMsg
:
'不要超过40字'
,
});
hasError
=
true
;
resolve
(
false
);
return
false
;
}
if
(
!
hasError
)
{
resolve
(
true
);
this
.
setState
({
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
});
}
});
};
// 保存
handleSubmit
=
()
=>
{
//过期判断
if
(
User
.
getExpirationTime
()
&&
moment
().
valueOf
()
>
Number
(
User
.
getExpirationTime
()))
{
Modal
.
warning
({
title
:
"服务已到期"
,
content
:
"当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买"
,
okText
:
"我知道了"
})
return
}
//过期判断
if
(
User
.
getExpirationTime
()
&&
moment
().
valueOf
()
>
Number
(
User
.
getExpirationTime
()))
{
Modal
.
warning
({
title
:
'服务已到期'
,
content
:
'当前企业购买的小麦企学院服务已到期,如需继续使用学院功能,请尽快续费购买'
,
okText
:
'我知道了'
,
});
return
;
}
const
{
id
,
...
...
@@ -425,11 +387,11 @@ class AddVideoCourse extends React.Component {
introduce
,
courseChapterList
,
editorTextLength
,
}
=
this
.
state
}
=
this
.
state
;
const
commonParams
=
{
// videoName,
videoDuration
:
0
,
//后端的必要参数,不能传空
videoDuration
:
0
,
//后端的必要参数,不能传空
scheduleMedia
:
scheduleMedia
.
filter
((
item
)
=>
!!
item
.
mediaContent
),
categoryId
,
courseName
,
...
...
@@ -439,11 +401,11 @@ class AddVideoCourse extends React.Component {
shelfState
,
whetherVisitorsJoin
,
courseType
:
'VOICE'
,
courseChapterList
}
courseChapterList
,
}
;
// 校验必填字段:课程名称, 课程视频
this
.
handleValidate
(
courseName
,
courseChapterList
,
categoryId
,
scheduleMedia
,
editorTextLength
).
then
((
res
)
=>
{
if
(
!
res
)
return
if
(
!
res
)
return
;
Upload
.
uploadTextToOSS
(
introduce
,
`
${
randomString
()}
.txt`
,
(
introduceId
)
=>
{
this
.
submitRemote
({
id
,
pageType
,
commonParams
:
{
...
commonParams
,
introduceId
}
});
});
...
...
@@ -453,8 +415,8 @@ class AddVideoCourse extends React.Component {
submitRemote
=
({
id
,
pageType
,
commonParams
})
=>
{
if
(
pageType
===
'add'
)
{
Service
.
Hades
(
'public/hades/createVideoSchedule'
,
commonParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
message
.
success
(
'新建成功'
)
if
(
!
res
)
return
;
message
.
success
(
'新建成功'
)
;
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
,
});
...
...
@@ -462,11 +424,11 @@ class AddVideoCourse extends React.Component {
}
else
{
const
editParams
=
{
courseId
:
id
,
...
commonParams
}
...
commonParams
,
}
;
Service
.
Hades
(
'public/hades/editVideoSchedule'
,
editParams
).
then
((
res
)
=>
{
if
(
!
res
)
return
message
.
success
(
'保存成功'
)
if
(
!
res
)
return
;
message
.
success
(
'保存成功'
)
;
window
.
RCHistory
.
push
({
pathname
:
`/video-course`
,
});
...
...
@@ -482,9 +444,9 @@ class AddVideoCourse extends React.Component {
return
false
;
}
if
(
!
courseChapterList
.
length
)
{
message
.
warning
(
'请上传课节'
)
resolve
(
false
)
return
false
message
.
warning
(
'请上传课节'
)
;
resolve
(
false
)
;
return
false
;
}
if
(
!
categoryId
)
{
message
.
warning
(
'请选择课程分类'
);
...
...
@@ -500,8 +462,8 @@ class AddVideoCourse extends React.Component {
});
};
handleSelectCover
=
(
file
)
=>
{
if
(
!
file
)
{
message
.
info
(
"请选择文件!"
);
if
(
!
file
)
{
message
.
info
(
'请选择文件!'
);
return
;
}
this
.
setState
({
...
...
@@ -527,168 +489,180 @@ class AddVideoCourse extends React.Component {
this
.
setState
({
showSelectCoverModal
:
false
,
coverUrl
:
coverClicpPath
,
coverId
:
coverId
})
}
coverId
:
coverId
,
})
;
}
;
handleRenameCourseChapter
=
(
chapterId
,
chapterIndex
)
=>
{
const
{
mediaNameAlias
}
=
this
.
state
;
this
.
handleValidateChapterName
(
mediaNameAlias
).
then
(
res
=>
{
this
.
handleValidateChapterName
(
mediaNameAlias
).
then
(
(
res
)
=>
{
// 校验不通过不能点确定保存修改课节名称
if
(
!
res
)
{
return
message
.
warning
(
'重命名失败'
);
}
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
[];
_courseChapterList
=
courseChapterList
.
map
((
item
,
index
)
=>
{
if
(
item
.
resourceId
===
chapterId
&&
chapterIndex
===
index
)
{
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
[];
_courseChapterList
=
courseChapterList
.
map
((
item
,
index
)
=>
{
if
(
item
.
resourceId
===
chapterId
&&
chapterIndex
===
index
)
{
item
.
mediaName
=
mediaNameAlias
;
item
.
visible
=
false
;
}
return
item
})
return
item
;
})
;
this
.
setState
({
courseChapterList
:
_courseChapterList
,
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
mediaNameAlias
:
''
,
})
})
;
});
};
}
handleChangePopConfirmVisible
=
(
chapterId
,
chapterNameIndex
,
visible
)
=>
{
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
[];
_courseChapterList
=
courseChapterList
.
map
((
item
,
index
)
=>
{
if
(
item
.
resourceId
===
chapterId
&&
chapterNameIndex
===
index
){
item
.
visible
=
visible
handleChangePopConfirmVisible
=
(
chapterId
,
chapterNameIndex
,
visible
)
=>
{
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
[];
_courseChapterList
=
courseChapterList
.
map
((
item
,
index
)
=>
{
if
(
item
.
resourceId
===
chapterId
&&
chapterNameIndex
===
index
)
{
item
.
visible
=
visible
;
}
else
{
item
.
visible
=
false
item
.
visible
=
false
;
}
return
item
})
return
item
;
})
;
this
.
setState
({
courseChapterList
:
_courseChapterList
,
})
}
})
;
}
;
handleDeleteCourseChapter
=
(
chapterId
,
chapterIndex
)
=>
{
console
.
log
(
'chapterId---'
,
chapterId
,
chapterIndex
);
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
courseChapterList
.
filter
((
item
,
index
)
=>
{
return
item
.
resourceId
!==
chapterId
||
item
.
resourceId
===
chapterId
&&
chapterIndex
!==
index
})
console
.
log
(
'chapterId---'
,
chapterId
,
chapterIndex
);
let
{
courseChapterList
}
=
this
.
state
;
let
_courseChapterList
=
courseChapterList
.
filter
((
item
,
index
)
=>
{
return
item
.
resourceId
!==
chapterId
||
(
item
.
resourceId
===
chapterId
&&
chapterIndex
!==
index
);
})
;
_courseChapterList
.
map
((
item
,
index
)
=>
{
item
.
sort
=
index
})
item
.
sort
=
index
;
})
;
this
.
setState
({
courseChapterList
:
_courseChapterList
})
}
courseChapterList
:
_courseChapterList
,
})
;
}
;
renderChapterTitle
=
(
item
)
=>
{
const
{
chapterNameValidateStatus
,
chapterNameHelpMsg
}
=
this
.
state
;
const
{
chapterNameValidateStatus
,
chapterNameHelpMsg
}
=
this
.
state
;
return
<
div
className=
"course-chapter-title-popover"
>
<
div
className=
"tag-title"
>
课节名称
</
div
>
return
(
<
div
className=
'course-chapter-title-popover'
>
<
div
className=
'tag-title'
>
课节名称
</
div
>
<
Form
>
<
Form
.
Item
validateStatus=
{
chapterNameValidateStatus
}
help=
{
chapterNameHelpMsg
}
>
<
TextArea
defaultValue=
{
item
.
mediaName
}
placeholder=
"请输入课节名称"
maxLength=
{
40
}
autoSize
style=
{
{
width
:
'318px'
}
}
onChange=
{
(
e
)
=>
{
this
.
setState
({
mediaNameAlias
:
e
.
target
.
value
.
trim
()
},
()
=>
{
this
.
handleValidateChapterName
(
this
.
state
.
mediaNameAlias
)
})
}
}
/>
<
Form
.
Item
validateStatus=
{
chapterNameValidateStatus
}
help=
{
chapterNameHelpMsg
}
>
<
TextArea
defaultValue=
{
item
.
mediaName
}
placeholder=
'请输入课节名称'
maxLength=
{
40
}
autoSize
style=
{
{
width
:
'318px'
}
}
onChange=
{
(
e
)
=>
{
this
.
setState
(
{
mediaNameAlias
:
e
.
target
.
value
.
trim
(),
},
()
=>
{
this
.
handleValidateChapterName
(
this
.
state
.
mediaNameAlias
);
}
);
}
}
/>
</
Form
.
Item
>
</
Form
>
</
Form
>
</
div
>
}
);
};
// 上下移动
handleChangeIndex
=
(
isUp
,
sortIndex
)
=>
{
const
{
courseChapterList
}
=
this
.
state
;
// 第一个上移和最后一个下移不能使用
if
((
isUp
&&
sortIndex
===
0
)
||
(
!
isUp
&&
sortIndex
===
(
courseChapterList
.
length
-
1
))){
return
;
}
let
_courseChapterList
=
[...
courseChapterList
];
const
temp
=
courseChapterList
[
sortIndex
];
// 若上移
if
(
isUp
){
_courseChapterList
[
sortIndex
-
1
]
=
temp
;
_courseChapterList
[
sortIndex
-
1
].
sort
=
sortIndex
-
1
;
_courseChapterList
[
sortIndex
]
=
courseChapterList
[
sortIndex
-
1
];
_courseChapterList
[
sortIndex
].
sort
=
sortIndex
;
}
else
{
// 若下移
_courseChapterList
[
sortIndex
+
1
]
=
temp
;
_courseChapterList
[
sortIndex
+
1
].
sort
=
sortIndex
+
1
;
_courseChapterList
[
sortIndex
]
=
courseChapterList
[
sortIndex
+
1
];
_courseChapterList
[
sortIndex
].
sort
=
sortIndex
;
}
this
.
setState
({
courseChapterList
:
_courseChapterList
})
// 上下移动
handleChangeIndex
=
(
isUp
,
sortIndex
)
=>
{
const
{
courseChapterList
}
=
this
.
state
;
// 第一个上移和最后一个下移不能使用
if
((
isUp
&&
sortIndex
===
0
)
||
(
!
isUp
&&
sortIndex
===
courseChapterList
.
length
-
1
))
{
return
;
}
renderTypemenu
=
()
=>
{
return
<
Menu
>
<
Menu
.
Item
>
<
span
onClick=
{
()
=>
{
this
.
selectFileType
(
"VIDEO"
)}
}
>
视频文件
</
span
>
</
Menu
.
Item
>
<
Menu
.
Item
>
<
span
onClick=
{
()
=>
{
this
.
selectFileType
(
"WORD_PDF"
)}
}
>
资料文件
</
span
>
</
Menu
.
Item
>
</
Menu
>
let
_courseChapterList
=
[...
courseChapterList
];
const
temp
=
courseChapterList
[
sortIndex
];
// 若上移
if
(
isUp
)
{
_courseChapterList
[
sortIndex
-
1
]
=
temp
;
_courseChapterList
[
sortIndex
-
1
].
sort
=
sortIndex
-
1
;
_courseChapterList
[
sortIndex
]
=
courseChapterList
[
sortIndex
-
1
];
_courseChapterList
[
sortIndex
].
sort
=
sortIndex
;
}
else
{
// 若下移
_courseChapterList
[
sortIndex
+
1
]
=
temp
;
_courseChapterList
[
sortIndex
+
1
].
sort
=
sortIndex
+
1
;
_courseChapterList
[
sortIndex
]
=
courseChapterList
[
sortIndex
+
1
];
_courseChapterList
[
sortIndex
].
sort
=
sortIndex
;
}
selectFileType
=
(
type
)
=>
{
const
{
courseChapterList
}
=
this
.
state
;
if
(
courseChapterList
.
length
>=
20
)
{
message
.
warning
(
`最多只能上传20个文件`
);
return
;
}
if
(
type
===
"VIDEO"
){
this
.
setState
({
showSelectFileModal
:
true
,
selectTypeList
:[
'MP4'
],
accept
:
'video/mp4'
})
}
else
{
this
.
setState
({
showSelectFileModal
:
true
,
selectTypeList
:[
'DOC'
,
'DOCX'
,
'PDF'
],
accept
:
'.doc,.docx,.pdf'
})
}
this
.
setState
({
courseChapterList
:
_courseChapterList
,
});
};
renderTypemenu
=
()
=>
{
return
(
<
Menu
>
<
Menu
.
Item
>
<
span
onClick=
{
()
=>
{
this
.
selectFileType
(
'VIDEO'
);
}
}
>
视频文件
</
span
>
</
Menu
.
Item
>
<
Menu
.
Item
>
<
span
onClick=
{
()
=>
{
this
.
selectFileType
(
'WORD_PDF'
);
}
}
>
资料文件
</
span
>
</
Menu
.
Item
>
</
Menu
>
);
};
selectFileType
=
(
type
)
=>
{
const
{
courseChapterList
}
=
this
.
state
;
if
(
courseChapterList
.
length
>=
20
)
{
message
.
warning
(
`最多只能上传20个文件`
);
return
;
}
if
(
type
===
'VIDEO'
)
{
this
.
setState
({
showSelectFileModal
:
true
,
selectTypeList
:
[
'MP4'
],
accept
:
'video/mp4'
,
});
}
else
{
this
.
setState
({
showSelectFileModal
:
true
,
selectTypeList
:
[
'DOC'
,
'DOCX'
,
'PDF'
],
accept
:
'.doc,.docx,.pdf'
,
});
}
};
renderToolTipTitle
=
()
=>
{
return
(<
div
>
renderToolTipTitle
=
()
=>
{
return
(
<
div
>
<
p
>
视频支持mp4格式,大小不超过2G;
</
p
>
<
p
>
文件支持PDF、docx、doc格式,大小不超过100M
</
p
>
</
div
>)
}
</
div
>
);
};
render
()
{
const
{
pageType
,
...
...
@@ -699,21 +673,19 @@ class AddVideoCourse extends React.Component {
diskList
,
// videoType,
shelfState
,
categoryName
,
courseCatalogList
,
categoryId
,
whetherVisitorsJoin
,
visible
,
showSelectCoverModal
,
hasImgReady
,
cutImageBlob
,
introduce
,
loadintroduce
,
id
,
courseChapterList
,
imageFile
,
selectTypeList
,
accept
}
=
this
.
state
accept
,
}
=
this
.
state
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png'
;
const
isDefaultCover
=
coverUrl
===
defaultCover
||
coverUrl
==
null
;
...
...
@@ -745,91 +717,120 @@ class AddVideoCourse extends React.Component {
<
span
className=
'label required upload-chapter'
>
上传课节:
</
span
>
</
div
>
<
div
className=
'sub-content'
>
<
div
className=
"btn-wrap"
>
<
div
className=
'btn-wrap'
>
{
/* <Button
onClick={() => {
if(courseChapterList.length >= 20) {
message.warning(`最多只能上传20个文件`);
return;
}
this.setState({
showSelectFileModal: true
})
}}>添加视频</Button> */
}
<
div
className=
'select-file'
>
<
Dropdown
overlay=
{
this
.
renderTypemenu
()
}
>
<
Button
>
选择文件
</
Button
>
</
Dropdown
>
</
div
>
<
div
className=
'course-ware--empty'
>
从
资料云盘
中选择视频
</
div
>
<
div
className=
'course-ware--empty'
>
从
素材库
中选择视频
</
div
>
</
div
>
<
div
className=
'tips'
>
课节数量限制20个,文件规格说明
<
Tooltip
title=
{
this
.
renderToolTipTitle
()
}
overlayClassName=
"my-chapter-tooltip"
>
<
i
className=
'icon iconfont'
style=
{
{
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
}
}
>

</
i
>
</
Tooltip
>
课节数量限制20个,文件规格说明
<
Tooltip
title=
{
this
.
renderToolTipTitle
()
}
overlayClassName=
'my-chapter-tooltip'
>
<
i
className=
'icon iconfont'
style=
{
{
cursor
:
'pointer'
,
color
:
'#bfbfbf'
,
fontSize
:
'14px'
}
}
>
{
' '
}

</
i
>
</
Tooltip
>
</
div
>
</
div
>
</
div
>
<
If
condition=
{
courseChapterList
.
length
>
0
}
>
<
div
className=
"course-chapter-list-wrap"
>
<
div
className=
"course-chapter-total"
>
{
`共${courseChapterList.length}个课节`
}
</
div
>
<
div
className=
'course-chapter-list'
id=
"course-chapter-list"
>
{
_
.
map
(
courseChapterList
,(
item
,
index
)
=>
{
return
<
div
className=
'course-ware'
key=
{
index
}
>
<
div
className=
"course-ware__index"
>
{
index
<
9
?
`0${index + 1 } `
:
`${index + 1 } `
}
</
div
>
<
img
className=
'course-ware__img'
src=
{
FileTypeIcon
[
item
.
mediaType
]
}
alt=
''
/>
<
div
className=
'course-ware__name'
>
{
item
.
mediaName
&&
item
.
mediaName
.
length
>
24
?
<
Tooltip
title=
{
item
.
mediaName
}
>
{
item
.
mediaName
}
</
Tooltip
>:
item
.
mediaName
}
</
div
>
<
div
className=
"course-chapter__opt"
id=
{
item
.
resourceId
}
>
<
div
className=
{
`up ${Number(index) === 0 ? 'disabled':''}`
}
onClick=
{
()
=>
this
.
handleChangeIndex
(
true
,
item
.
sort
,
item
.
resourceId
)
}
>
上移
</
div
>
<
div
className=
"line"
>
|
</
div
>
<
div
className=
{
`down ${Number(index) === (courseChapterList.length - 1) ? 'disabled':''}`
}
onClick=
{
()
=>
this
.
handleChangeIndex
(
false
,
item
.
sort
,
item
.
resourceId
)
}
>
下移
</
div
>
<
div
className=
"line"
>
|
</
div
>
<
Popconfirm
placement=
"topLeft"
className=
"course-chapter-tooltip"
title=
{
this
.
renderChapterTitle
(
item
)
}
color=
'#fff'
trigger=
"click"
overlayClassName=
"chapter-popover"
getPopupContainer=
{
()
=>
document
.
getElementById
(
'course-chapter-list'
)
}
destroyTooltipOnHide=
{
true
}
visible=
{
item
.
visible
}
onConfirm=
{
()
=>
this
.
handleRenameCourseChapter
(
item
.
resourceId
,
index
)
}
icon=
{
null
}
onVisibleChange=
{
(
visible
)
=>
{
!
visible
&&
this
.
setState
({
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
mediaNameAlias
:
''
,
})
}
}
onCancel=
{
()
=>
this
.
handleChangePopConfirmVisible
(
item
.
resourceId
,
index
,
false
)
}
>
<
div
className=
"rename"
onClick=
{
()
=>
{
this
.
setState
({
mediaNameAlias
:
item
.
mediaName
},
()
=>
{
this
.
handleChangePopConfirmVisible
(
item
.
resourceId
,
index
,
true
)})
}
}
>
重命名
</
div
>
</
Popconfirm
>
<
div
className=
"line"
>
|
</
div
>
<
div
className=
"delete"
onClick=
{
()
=>
this
.
handleDeleteCourseChapter
(
item
.
resourceId
,
index
)
}
>
移除
</
div
>
</
div
>
<
div
className=
'course-chapter-list-wrap'
>
<
div
className=
'course-chapter-total'
>
{
`共${courseChapterList.length}个课节`
}
</
div
>
<
div
className=
'course-chapter-list'
id=
'course-chapter-list'
>
{
_
.
map
(
courseChapterList
,
(
item
,
index
)
=>
{
return
(
<
div
className=
'course-ware'
key=
{
index
}
>
<
div
className=
'course-ware__index'
>
{
index
<
9
?
`0${index + 1} `
:
`${index + 1} `
}
</
div
>
<
img
className=
'course-ware__img'
src=
{
FileTypeIcon
[
item
.
mediaType
]
}
alt=
''
/>
<
div
className=
'course-ware__name'
>
{
item
.
mediaName
&&
item
.
mediaName
.
length
>
24
?
<
Tooltip
title=
{
item
.
mediaName
}
>
{
item
.
mediaName
}
</
Tooltip
>
:
item
.
mediaName
}
</
div
>
})
}
</
div
>
</
div
>
</
If
>
<
div
className=
'course-chapter__opt'
id=
{
item
.
resourceId
}
>
<
div
className=
{
`up ${Number(index) === 0 ? 'disabled' : ''}`
}
onClick=
{
()
=>
this
.
handleChangeIndex
(
true
,
item
.
sort
,
item
.
resourceId
)
}
>
上移
</
div
>
<
div
className=
'line'
>
|
</
div
>
<
div
className=
{
`down ${Number(index) === courseChapterList.length - 1 ? 'disabled' : ''}`
}
onClick=
{
()
=>
this
.
handleChangeIndex
(
false
,
item
.
sort
,
item
.
resourceId
)
}
>
下移
</
div
>
<
div
className=
'line'
>
|
</
div
>
<
Popconfirm
placement=
'topLeft'
className=
'course-chapter-tooltip'
title=
{
this
.
renderChapterTitle
(
item
)
}
color=
'#fff'
trigger=
'click'
overlayClassName=
'chapter-popover'
getPopupContainer=
{
()
=>
document
.
getElementById
(
'course-chapter-list'
)
}
destroyTooltipOnHide=
{
true
}
visible=
{
item
.
visible
}
onConfirm=
{
()
=>
this
.
handleRenameCourseChapter
(
item
.
resourceId
,
index
)
}
icon=
{
null
}
onVisibleChange=
{
(
visible
)
=>
{
!
visible
&&
this
.
setState
({
chapterNameValidateStatus
:
''
,
chapterNameHelpMsg
:
''
,
mediaNameAlias
:
''
,
});
}
}
onCancel=
{
()
=>
this
.
handleChangePopConfirmVisible
(
item
.
resourceId
,
index
,
false
)
}
>
<
div
className=
'rename'
onClick=
{
()
=>
{
this
.
setState
({
mediaNameAlias
:
item
.
mediaName
},
()
=>
{
this
.
handleChangePopConfirmVisible
(
item
.
resourceId
,
index
,
true
);
});
}
}
>
重命名
</
div
>
</
Popconfirm
>
<
div
className=
'line'
>
|
</
div
>
<
div
className=
'delete'
onClick=
{
()
=>
this
.
handleDeleteCourseChapter
(
item
.
resourceId
,
index
)
}
>
移除
</
div
>
</
div
>
</
div
>
);
})
}
</
div
>
</
div
>
</
If
>
<
div
className=
'cover-url flex mt16'
>
<
div
className=
'label cover'
>
封面图:
</
div
>
<
div
className=
'label cover'
>
封面图:
</
div
>
<
div
className=
'cover-url__wrap'
>
<
div
className=
'opt-btns'
>
<
div
>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showSelectCoverModal
:
true
})
this
.
setState
({
showSelectCoverModal
:
true
})
;
}
}
>
{
`${pageType === 'add' && !coverUrl ? '上传' : '修改'}封面`
}
</
Button
>
<
span
className=
{
`span ${coverUrl ? 'defalut-span' : ''}`
}
onClick=
{
()
=>
{
this
.
setState
({
coverUrl
:
''
,
coverId
:
''
})
coverId
:
''
,
})
;
}
}
>
使用默认图
</
span
>
...
...
@@ -838,9 +839,7 @@ class AddVideoCourse extends React.Component {
</
div
>
<
div
className=
'img-content'
>
{
isDefaultCover
&&
<
span
className=
"tag"
>
默认图
</
span
>
}
{
isDefaultCover
&&
<
span
className=
'tag'
>
默认图
</
span
>
}
{
/* 如果视频和封面都没有上传的话, 那么就显示缺省, 如果上传了视频, 那么封面图就默认显示视频的第一帧, 如果上传了封面图, 那么就显示上传的封面图 */
}
<
img
src=
{
coverUrl
||
`https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png`
}
alt=
''
/>
</
div
>
...
...
@@ -848,38 +847,12 @@ class AddVideoCourse extends React.Component {
</
div
>
<
div
className=
'course-catalog required'
>
<
span
className=
'label'
>
课程分类:
</
span
>
{
pageType
===
'add'
&&
(
<
Cascader
defaultValue=
{
[]
}
options=
{
courseCatalogList
}
displayRender=
{
(
label
)
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
'请选择课程分类'
suffixIcon=
{
<
span
className=
'icon iconfont'
style=
{
{
fontSize
:
'12px'
,
color
:
'#BFBFBF'
}
}
>

</
span
>
}
/>
)
}
{
pageType
===
'edit'
&&
categoryName
&&
(
<
Cascader
defaultValue=
{
[
categoryName
]
}
options=
{
courseCatalogList
}
displayRender=
{
(
label
)
=>
label
.
join
(
'-'
)
}
fieldNames=
{
fieldNames
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
'请选择课程分类'
suffixIcon=
{
<
span
className=
'icon iconfont'
style=
{
{
fontSize
:
'12px'
,
color
:
'#BFBFBF'
}
}
>

</
span
>
}
/>
)
}
<
CourseCatalogSelect
value=
{
categoryId
}
onChange=
{
(
value
,
label
)
=>
{
this
.
handleChangeCatalogList
(
value
,
label
);
}
}
/>
</
div
>
<
div
className=
'intro-info mt16'
>
<
AddVideoIntro
...
...
@@ -915,7 +888,7 @@ class AddVideoCourse extends React.Component {
queryTypeEnum=
{
'ONLINE'
}
confirm=
{
{
title
:
'文件过大,无法上传'
,
content
:
'上传的视频大小不能超过2G,文件大小不能超过100M'
content
:
'上传的视频大小不能超过2G,文件大小不能超过100M'
,
}
}
tooltip=
{
''
}
isOpen=
{
showSelectFileModal
}
...
...
src/modules/course-manage/video-course/components/VideoCourseList.jsx
View file @
39be164c
import
React
from
"react"
import
{
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
"antd"
import
_
from
"underscore"
import
{
PageControl
}
from
"@/components"
import
{
LIVE_SHARE
}
from
"@/domains/course-domain/constants"
import
{
Route
,
withRouter
}
from
'react-router-dom'
;
import
ShareLiveModal
from
"@/modules/course-manage/modal/ShareLiveModal"
import
CourseService
from
"@/domains/course-domain/CourseService"
import
RelatedPlanModal
from
"../../modal/RelatedPlanModal"
import
User
from
"@/common/js/user"
import
VideoCourseDetail
from
'../VideoCourseDetail'
;
import
WatchData
from
"./WatchData"
;
import
{
XMTable
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
"./VideoCourseList.less"
import
React
from
'react'
import
{
Modal
,
message
,
Tooltip
,
Switch
,
Dropdown
}
from
'antd'
import
_
from
'underscore'
import
{
PageControl
}
from
'@/components'
import
{
LIVE_SHARE
}
from
'@/domains/course-domain/constants'
import
{
Route
,
withRouter
}
from
'react-router-dom'
import
ShareLiveModal
from
'@/modules/course-manage/modal/ShareLiveModal'
import
CourseService
from
'@/domains/course-domain/CourseService'
import
RelatedPlanModal
from
'../../modal/RelatedPlanModal'
import
User
from
'@/common/js/user'
import
VideoCourseDetail
from
'../VideoCourseDetail'
import
WatchData
from
'./WatchData'
import
{
XMTable
}
from
'@/components'
import
college
from
'@/common/lottie/college'
import
'./VideoCourseList.less'
class
VideoCourseList
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
id
:
''
,
// 视频课ID
studentIds
:
[],
...
...
@@ -24,54 +24,48 @@ class VideoCourseList extends React.Component {
selectPlanList
:
{},
ShelfLoading
:
false
,
// dataSource: [],
}
;
}
}
componentDidMount
()
{
const
videoCourseItem
=
localStorage
.
getItem
(
'videoCourseItem'
)
;
const
videoCourseItem
=
localStorage
.
getItem
(
'videoCourseItem'
)
if
(
videoCourseItem
)
{
const
_videoCourseItem
=
JSON
.
parse
(
videoCourseItem
)
;
this
.
handleShowShareModal
(
_videoCourseItem
,
true
)
;
const
_videoCourseItem
=
JSON
.
parse
(
videoCourseItem
)
this
.
handleShowShareModal
(
_videoCourseItem
,
true
)
}
}
// 跳转课程详情页
handleLinkToCourseDetail
=
(
courseId
)
=>
{
const
{
match
}
=
this
.
props
;
window
.
RCHistory
.
push
(
`
${
match
.
url
}
/video-course-detail?courseId=
${
courseId
}
`
)
}
// 跳转课程详情页
handleLinkToCourseDetail
=
(
courseId
)
=>
{
const
{
match
}
=
this
.
props
window
.
RCHistory
.
push
(
`
${
match
.
url
}
/video-course-detail?courseId=
${
courseId
}
`
)
}
// 观看数据弹窗
handleShowWatchDataModal
=
(
item
)
=>
{
const
{
match
}
=
this
.
props
;
const
{
match
}
=
this
.
props
window
.
RCHistory
.
push
({
pathname
:
`
${
match
.
url
}
/course-data?courseName=
${
item
.
courseName
}
&courseId=
${
item
.
id
}
`
pathname
:
`
${
match
.
url
}
/course-data?courseName=
${
item
.
courseName
}
&courseId=
${
item
.
id
}
`
,
})
}
// 请求表头
parseColumns
=
()
=>
{
const
{
type
}
=
this
.
props
;
const
{
ShelfLoading
}
=
this
.
state
;
const
{
type
}
=
this
.
props
const
{
ShelfLoading
}
=
this
.
state
const
columns
=
[
{
title
:
"线上课"
,
key
:
"scheduleName"
,
dataIndex
:
"scheduleName"
,
title
:
'线上课'
,
key
:
'scheduleName'
,
dataIndex
:
'scheduleName'
,
width
:
321
,
fixed
:
'left'
,
render
:
(
val
,
record
)
=>
{
const
{
coverUrl
}
=
record
;
const
{
coverUrl
}
=
record
return
(
<
div
className=
'record__item'
>
<
img
className=
'course-cover'
src=
{
coverUrl
||
'https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png'
}
alt=
'封面图'
/>
<
img
className=
'course-cover'
src=
{
coverUrl
||
'https://image.xiaomaiketang.com/xm/TwtGPQGE4K.png'
}
alt=
'封面图'
/>
<
Choose
>
<
When
condition=
{
record
.
courseName
.
length
>
25
}
>
<
Tooltip
title=
{
record
.
courseName
}
>
...
...
@@ -83,7 +77,7 @@ class VideoCourseList extends React.Component {
</
Otherwise
>
</
Choose
>
</
div
>
)
;
)
},
},
{
...
...
@@ -99,35 +93,23 @@ class VideoCourseList extends React.Component {
</
If
>
</
span
>
),
key
:
"categoryName"
,
dataIndex
:
"categoryName"
,
key
:
'categoryName'
,
dataIndex
:
'categoryName'
,
width
:
150
,
render
:
(
val
,
record
)
=>
{
return
(
<
Choose
>
<
When
condition=
{
type
===
'internal'
}
>
<
div
className=
'record__item'
>
{
record
.
categoryOneName
}
{
record
.
categoryTwoName
?
`-${record.categoryTwoName}`
:
''
}
</
div
>
</
When
>
<
Otherwise
>
<
div
className=
'record__item'
>
{
record
.
categorySonName
}
</
div
>
</
Otherwise
>
</
Choose
>
);
return
<
div
className=
'record__item'
>
{
record
.
categorySonName
}
</
div
>
},
},
{
title
:
'课节数'
,
key
:
'chapterNum'
,
dataIndex
:
'chapterNum'
,
className
:
"chapterNum"
,
className
:
'chapterNum'
,
width
:
100
,
align
:
'right'
,
render
:
(
val
,
item
)
=>
{
return
<
div
onClick=
{
()
=>
this
.
handleLinkToCourseDetail
(
item
.
id
)
}
>
{
val
||
1
}
</
div
>
}
render
:
(
val
,
item
)
=>
{
return
<
div
onClick=
{
()
=>
this
.
handleLinkToCourseDetail
(
item
.
id
)
}
>
{
val
||
1
}
</
div
>
}
,
},
{
title
:
(
...
...
@@ -158,26 +140,30 @@ class VideoCourseList extends React.Component {
checked=
{
item
.
shelfState
===
'YES'
}
defaultChecked=
{
item
.
shelfState
}
onClick=
{
(
checked
)
=>
{
this
.
changeShelfState
(
checked
,
item
,
index
)
;
this
.
changeShelfState
(
checked
,
item
,
index
)
}
}
/>
)
;
)
},
},
{
title
:
"观看学员数"
,
title
:
'观看学员数'
,
width
:
150
,
key
:
"watchUserCount"
,
dataIndex
:
"watchUserCount"
,
key
:
'watchUserCount'
,
dataIndex
:
'watchUserCount'
,
align
:
'right'
,
render
:
(
val
,
item
)
=>
{
return
<
div
className=
'watchUserCount'
onClick=
{
()
=>
this
.
handleShowWatchDataModal
(
item
)
}
>
{
val
||
0
}
</
div
>
}
return
(
<
div
className=
'watchUserCount'
onClick=
{
()
=>
this
.
handleShowWatchDataModal
(
item
)
}
>
{
val
||
0
}
</
div
>
)
},
},
{
title
:
"创建人"
,
key
:
"createName"
,
dataIndex
:
"createName"
,
title
:
'创建人'
,
key
:
'createName'
,
dataIndex
:
'createName'
,
width
:
100
,
render
:
(
val
)
=>
{
return
(
...
...
@@ -189,7 +175,7 @@ class VideoCourseList extends React.Component {
)
}
</
div
>
)
}
}
,
},
{
title
:
'创建时间'
,
...
...
@@ -198,7 +184,7 @@ class VideoCourseList extends React.Component {
dataIndex
:
'created'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
;
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
},
},
{
...
...
@@ -208,7 +194,7 @@ class VideoCourseList extends React.Component {
dataIndex
:
'updated'
,
sorter
:
true
,
render
:
(
val
)
=>
{
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
;
return
window
.
formatDate
(
'YYYY-MM-DD H:i'
,
val
)
},
},
{
...
...
@@ -227,7 +213,7 @@ class VideoCourseList extends React.Component {
<
span
key=
{
item
.
planId
}
>
{
item
.
planName
}
{
index
<
record
.
relatedPlanList
.
length
-
1
&&
<
span
>
、
</
span
>
}
</
span
>
)
;
)
})
}
</
Tooltip
>
</
When
>
...
...
@@ -236,7 +222,7 @@ class VideoCourseList extends React.Component {
</
Otherwise
>
</
Choose
>
</
div
>
)
;
)
},
},
{
...
...
@@ -248,7 +234,7 @@ class VideoCourseList extends React.Component {
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
'operate'
>
<
If
condition=
{
type
===
"internal"
}
>
<
If
condition=
{
type
===
'internal'
}
>
<
div
className=
'operate__item'
onClick=
{
()
=>
this
.
handleShowShareModal
(
record
)
}
>
分享
</
div
>
...
...
@@ -263,17 +249,17 @@ class VideoCourseList extends React.Component {
</
span
>
</
Dropdown
>
</
div
>
)
;
)
},
},
]
;
]
type
!==
'internal'
&&
columns
.
splice
(
5
,
1
)
;
return
columns
;
}
;
type
!==
'internal'
&&
columns
.
splice
(
5
,
1
)
return
columns
}
renderMoreOperate
=
(
item
)
=>
{
const
{
type
}
=
this
.
props
;
const
{
type
}
=
this
.
props
return
(
<
div
className=
'live-course-more-menu'
>
<
If
condition=
{
type
!==
'internal'
}
>
...
...
@@ -290,7 +276,7 @@ class VideoCourseList extends React.Component {
<
div
className=
'operate__item'
onClick=
{
()
=>
{
window
.
RCHistory
.
push
(
`/create-video-course?type=edit&id=${item.id}`
)
;
window
.
RCHistory
.
push
(
`/create-video-course?type=edit&id=${item.id}`
)
}
}
>
编辑
</
div
>
...
...
@@ -299,41 +285,41 @@ class VideoCourseList extends React.Component {
</
div
>
</
If
>
</
div
>
)
;
}
;
)
}
handlePlanName
=
(
planArray
)
=>
{
let
planStr
=
''
;
let
planStr
=
''
planArray
.
forEach
((
item
,
index
)
=>
{
if
(
index
<
planArray
.
length
-
1
)
{
planStr
=
planStr
+
item
.
planName
+
'、'
;
planStr
=
planStr
+
item
.
planName
+
'、'
}
else
{
planStr
=
planStr
+
item
.
planName
;
planStr
=
planStr
+
item
.
planName
}
})
;
return
planStr
;
}
;
})
return
planStr
}
//改变上架状态
changeShelfState
=
(
checked
,
item
,
index
)
=>
{
let
_shelfState
=
checked
?
'YES'
:
'NO'
;
let
_shelfState
=
checked
?
'YES'
:
'NO'
if
(
checked
)
{
_shelfState
=
'YES'
;
_shelfState
=
'YES'
}
else
{
_shelfState
=
'NO'
;
_shelfState
=
'NO'
}
const
params
=
{
courseId
:
item
.
id
,
shelfState
:
_shelfState
,
}
;
}
CourseService
.
changeVideoShelfState
(
params
).
then
(()
=>
{
if
(
_shelfState
===
'YES'
)
{
message
.
success
(
'已开启展示'
)
;
message
.
success
(
'已开启展示'
)
}
else
{
message
.
success
(
'已取消展示'
)
;
message
.
success
(
'已取消展示'
)
}
this
.
props
.
changeShelfState
(
index
,
_shelfState
)
;
})
;
}
;
this
.
props
.
changeShelfState
(
index
,
_shelfState
)
})
}
// 删除线上课
handleDeleteVideoCourse
=
(
scheduleId
)
=>
{
...
...
@@ -348,28 +334,28 @@ class VideoCourseList extends React.Component {
const
param
=
{
courseId
:
scheduleId
,
storeId
:
User
.
getStoreId
(),
}
;
}
CourseService
.
delVideoSchedule
(
param
).
then
(()
=>
{
message
.
success
(
'删除成功'
)
;
this
.
props
.
onChange
()
;
})
;
message
.
success
(
'删除成功'
)
this
.
props
.
onChange
()
})
},
})
;
}
;
})
}
// 显示分享弹窗
handleShowShareModal
=
(
record
,
needStr
=
false
)
=>
{
const
{
type
}
=
this
.
props
;
const
{
id
,
scheduleVideoUrl
}
=
record
;
const
htmlUrl
=
`
${
LIVE_SHARE
}
video_detail/
${
id
}
?id=
${
User
.
getStoreId
()}
`
;
const
longUrl
=
htmlUrl
;
const
{
coverUrl
,
courseName
}
=
record
;
const
{
type
}
=
this
.
props
const
{
id
,
scheduleVideoUrl
}
=
record
const
htmlUrl
=
`
${
LIVE_SHARE
}
video_detail/
${
id
}
?id=
${
User
.
getStoreId
()}
`
const
longUrl
=
htmlUrl
const
{
coverUrl
,
courseName
}
=
record
const
shareData
=
{
longUrl
,
coverUrl
,
scheduleVideoUrl
,
courseName
,
}
;
}
const
shareLiveModal
=
(
<
ShareLiveModal
...
...
@@ -381,82 +367,82 @@ class VideoCourseList extends React.Component {
close=
{
()
=>
{
this
.
setState
({
shareLiveModal
:
null
,
})
;
localStorage
.
setItem
(
'videoCourseItem'
,
''
)
;
})
localStorage
.
setItem
(
'videoCourseItem'
,
''
)
}
}
/>
)
;
)
this
.
setState
({
shareLiveModal
})
;
}
;
this
.
setState
({
shareLiveModal
})
}
handleChangeTable
=
(
pagination
,
filters
,
sorter
)
=>
{
const
{
columnKey
,
order
}
=
sorter
;
const
{
query
}
=
this
.
props
;
let
{
order
:
_order
}
=
query
;
const
{
columnKey
,
order
}
=
sorter
const
{
query
}
=
this
.
props
let
{
order
:
_order
}
=
query
// 按创建时间升序排序
if
(
columnKey
===
'created'
&&
order
===
'ascend'
)
{
_order
=
'CREATED_ASC'
;
_order
=
'CREATED_ASC'
}
// 按创建时间降序排序
if
(
columnKey
===
'created'
&&
order
===
'descend'
)
{
_order
=
'CREATED_DESC'
;
_order
=
'CREATED_DESC'
}
// 按更新时间升序排序
if
(
columnKey
===
'updated'
&&
order
===
'ascend'
)
{
_order
=
'UPDATED_ASC'
;
_order
=
'UPDATED_ASC'
}
// 按更新时间降序排序
if
(
columnKey
===
'updated'
&&
order
===
'descend'
)
{
_order
=
'UPDATED_DESC'
;
_order
=
'UPDATED_DESC'
}
const
_query
=
{
...
query
,
orderEnum
:
_order
,
}
;
this
.
props
.
onChange
(
_query
)
;
}
;
}
this
.
props
.
onChange
(
_query
)
}
handleRelatedModalShow
=
(
item
)
=>
{
const
selectPlanList
=
{}
;
const
selectPlanList
=
{}
if
(
item
.
relatedPlanList
)
{
item
.
relatedPlanList
.
map
((
item
,
index
)
=>
{
selectPlanList
[
item
.
planId
]
=
{}
;
selectPlanList
[
item
.
planId
].
planId
=
item
.
planId
;
selectPlanList
[
item
.
planId
].
taskBaseVOList
=
[{
taskId
:
item
.
taskId
}]
;
return
item
;
})
;
selectPlanList
[
item
.
planId
]
=
{}
selectPlanList
[
item
.
planId
].
planId
=
item
.
planId
selectPlanList
[
item
.
planId
].
taskBaseVOList
=
[{
taskId
:
item
.
taskId
}]
return
item
})
}
this
.
setState
({
RelatedPlanModalVisible
:
true
,
selectCourseId
:
item
.
id
,
selectPlanList
:
selectPlanList
,
})
;
}
;
})
}
closeRelatedPlanModalVisible
=
()
=>
{
this
.
setState
({
RelatedPlanModalVisible
:
false
,
})
;
}
;
})
}
onChangeSelectPlanList
=
(
selectPlanList
)
=>
{
this
.
setState
({
selectPlanList
:
selectPlanList
,
})
;
}
;
})
}
onConfirmSelectPlanList
=
()
=>
{
this
.
setState
(
{
RelatedPlanModalVisible
:
false
,
},
()
=>
{
this
.
props
.
onChange
()
;
this
.
props
.
onChange
()
}
)
;
}
;
)
}
render
()
{
const
{
dataSource
=
[],
totalCount
,
query
,
type
,
match
}
=
this
.
props
;
const
{
current
,
size
}
=
query
;
const
{
RelatedPlanModalVisible
,
selectPlanList
,
selectCourseId
}
=
this
.
state
;
const
{
dataSource
=
[],
totalCount
,
query
,
type
,
match
}
=
this
.
props
const
{
current
,
size
}
=
query
const
{
RelatedPlanModalVisible
,
selectPlanList
,
selectCourseId
}
=
this
.
state
return
(
<
div
className=
{
`video-course-list ${type !== 'internal' ? 'video-course-list-mt' : ''}`
}
>
<
XMTable
...
...
@@ -480,8 +466,8 @@ class VideoCourseList 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
)
}
}
/>
</
div
>
...
...
@@ -500,8 +486,8 @@ class VideoCourseList extends React.Component {
<
Route
path=
{
`${match.url}/video-course-detail`
}
component=
{
VideoCourseDetail
}
/>
<
Route
path=
{
`${match.url}/course-data`
}
component=
{
WatchData
}
/>
</
div
>
)
;
)
}
}
export
default
withRouter
(
VideoCourseList
)
;
export
default
withRouter
(
VideoCourseList
)
src/modules/home/Home.jsx
View file @
39be164c
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Select
,
Tooltip
,
Carousel
,
Popover
}
from
'antd'
;
import
DataSet
from
"@antv/data-set"
;
import
{
Chart
as
G2Chart
}
from
'@antv/g2'
;
import
{
G2
,
Chart
,
Geom
,
Axis
,
Tooltip
as
G2Tooltip
,
Coord
,
Label
,
Legend
,
View
,
Guide
,
Shape
,
Facet
,
Util
}
from
"bizcharts"
;
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
Select
,
Tooltip
,
Carousel
,
Popover
}
from
'antd'
import
DataSet
from
'@antv/data-set'
import
{
Chart
as
G2Chart
}
from
'@antv/g2'
import
{
G2
,
Chart
,
Geom
,
Axis
,
Tooltip
as
G2Tooltip
,
Coord
,
Label
,
Legend
,
View
,
Guide
,
Shape
,
Facet
,
Util
}
from
'bizcharts'
import
moment
from
'moment'
import
Service
from
"@/common/js/service"
;
import
User
from
'@/common/js/user'
;
import
Service
from
'@/common/js/service'
import
User
from
'@/common/js/user'
import
HomeTip
from
'./HomeTip'
;
import
'./Home.less'
;
import
HomeTip
from
'./HomeTip'
import
'./Home.less'
const
Option
=
Select
.
Option
;
const
Option
=
Select
.
Option
class
Home
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
scheduleType
:
'LIVE'
,
list
:
[],
...
...
@@ -48,54 +34,54 @@ class Home extends React.Component {
incWeekVisitCustomerNum
:
0
,
courseNum
:
0
,
//课程总数
inCourseNum
:
0
,
//本月新增课程总数
}
;
this
.
_chart
=
null
;
}
this
.
_chart
=
null
}
componentDidMount
()
{
this
.
getPanelInfo
()
;
this
.
getStudyInfo
()
;
this
.
getHotCourse
()
;
this
.
getTrainingInfo
()
;
this
.
getPanelInfo
()
this
.
getStudyInfo
()
this
.
getHotCourse
()
this
.
getTrainingInfo
()
}
getTrainingInfo
()
{
Service
.
Hades
(
'public/hades/planOverview'
,
{
storeId
:
User
.
getStoreId
()
}).
then
((
res
)
=>
{
if
(
res
.
success
)
{
this
.
setState
(
res
.
result
)
;
this
.
setState
(
res
.
result
)
}
})
;
})
}
getHotCourse
()
{
const
{
timeRange
,
scheduleType
}
=
this
.
state
;
const
{
timeRange
,
scheduleType
}
=
this
.
state
const
data
=
{
hotNum
:
5
,
scheduleType
,
storeId
:
User
.
getStoreId
(),
timeRange
,
}
;
}
Service
.
Hades
(
'public/courseCloud/hotCourse'
,
data
).
then
((
res
)
=>
{
if
(
res
.
success
)
{
this
.
setState
({
list
:
res
.
result
,
})
;
})
}
})
;
})
}
getStudyInfo
()
{
const
{
studyTimeRange
}
=
this
.
state
;
const
{
studyTimeRange
}
=
this
.
state
Service
.
Hades
(
'public/hades/studyInfo'
,
{
storeId
:
User
.
getStoreId
(),
timeRange
:
studyTimeRange
}).
then
((
res
)
=>
{
if
(
res
.
success
)
{
const
dataList
=
res
.
result
.
map
((
item
)
=>
({
time
:
moment
(
item
.
dateline
).
format
(
'MM-DD'
),
studyNum
:
item
.
studyNum
,
studyTime
:
Math
.
round
(
item
.
studyTime
/
6
)
/
10
,
}))
;
this
.
createChart
(
dataList
)
;
}))
this
.
createChart
(
dataList
)
}
})
;
})
}
getPanelInfo
()
{
...
...
@@ -120,22 +106,22 @@ class Home extends React.Component {
incWeekVisitCustomerNum
:
res
.
result
.
incWeekVisitCustomerNum
,
courseNum
:
res
.
result
.
videoCourseNum
+
res
.
result
.
liveCourseNum
+
res
.
result
.
pictureCourseNum
+
res
.
result
.
offlineCourseNum
,
inCourseNum
:
res
.
result
.
incLiveCourseNum
+
res
.
result
.
incVideoCourseNum
+
res
.
result
.
incPictureCourseNum
+
res
.
result
.
incOfflineCourseNum
,
})
;
})
}
})
;
})
}
showNumber
(
index
)
{
switch
(
index
)
{
case
0
:
return
'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
;
return
'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
case
1
:
return
'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png'
;
return
'https://image.xiaomaiketang.com/xm/Qfib4mnGJT.png'
case
2
:
return
'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png'
;
return
'https://image.xiaomaiketang.com/xm/8jKXHyrDaG.png'
default
:
return
'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
;
return
'https://image.xiaomaiketang.com/xm/D64QhNn74S.png'
}
}
...
...
@@ -146,28 +132,28 @@ class Home extends React.Component {
forceFit
:
true
,
height
:
290
,
padding
:
[
48
,
64
],
})
;
})
}
this
.
_chart
.
clear
()
;
this
.
_chart
.
clear
()
this
.
_chart
.
source
(
data
,
{
studyTime
:
{
formatter
:
(
val
)
=>
{
return
val
;
return
val
},
tickCount
:
5
,
},
time
:
{
formatter
:
(
val
)
=>
{
return
`
${
val
}
`
;
return
`
${
val
}
`
},
},
studyNum
:
{
formatter
:
(
val
)
=>
{
return
val
;
return
val
},
tickCount
:
5
,
},
})
;
})
this
.
_chart
.
axis
(
'time'
,
{
label
:
{
offset
:
20
,
...
...
@@ -182,7 +168,7 @@ class Home extends React.Component {
tickLine
:
{
stroke
:
'#E8E8E8'
,
},
})
;
})
this
.
_chart
.
axis
(
'submitCount'
,
{
label
:
{
textStyle
:
{
...
...
@@ -190,7 +176,7 @@ class Home extends React.Component {
fontSize
:
14
,
},
},
})
;
})
this
.
_chart
.
axis
(
'studyTime'
,
{
label
:
{
textStyle
:
{
...
...
@@ -198,7 +184,7 @@ class Home extends React.Component {
fontSize
:
14
,
},
},
})
;
})
this
.
_chart
.
line
()
.
position
(
'time*studyNum'
)
...
...
@@ -207,8 +193,8 @@ class Home extends React.Component {
return
{
name
:
'学习人数'
,
value
:
studyNum
+
'人'
,
}
;
})
;
}
})
this
.
_chart
.
line
()
.
position
(
'time*studyTime'
)
...
...
@@ -217,10 +203,10 @@ class Home extends React.Component {
return
{
name
:
'人均学习时长'
,
value
:
studyTime
+
'分钟'
,
}
;
})
;
}
})
this
.
_chart
.
legend
(
false
)
;
this
.
_chart
.
legend
(
false
)
this
.
_chart
.
tooltip
({
containerTpl
:
'<div class="g2-tooltip" style="background: #fff !important;">'
+
...
...
@@ -228,9 +214,9 @@ class Home extends React.Component {
'<ul class="g2-tooltip-list"></ul></div>'
,
// tooltip 容器模板
itemTpl
:
'<li data-index={index}><span style="background-color:{color};width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;"></span>{name}<span style="display: inline-block; float: right; margin-left: 30px;">{value}</span></li>'
,
// tooltip 每项记录的默认模板
})
;
this
.
_chart
.
render
()
;
}
;
})
this
.
_chart
.
render
()
}
render
()
{
const
{
...
...
@@ -259,7 +245,7 @@ class Home extends React.Component {
offlineCourseNum
,
weekVisitCustomerNum
,
incWeekVisitCustomerNum
,
}
=
this
.
state
;
}
=
this
.
state
const
data
=
[
{
item
:
'已完成培训'
,
...
...
@@ -269,26 +255,26 @@ class Home extends React.Component {
item
:
'未完成培训'
,
count
:
unfinishedNum
,
},
]
;
const
{
DataView
}
=
DataSet
;
const
{
Html
}
=
Guide
;
const
sum
=
data
[
0
].
count
+
data
[
1
].
count
;
const
dv
=
new
DataView
()
;
]
const
{
DataView
}
=
DataSet
const
{
Html
}
=
Guide
const
sum
=
data
[
0
].
count
+
data
[
1
].
count
const
dv
=
new
DataView
()
sum
&&
dv
.
source
(
data
).
transform
({
type
:
'percent'
,
field
:
'count'
,
dimension
:
'item'
,
as
:
'percent'
,
})
;
})
const
cols
=
{
percent
:
{
formatter
:
(
val
)
=>
{
val
=
val
*
100
+
'%'
;
return
val
;
val
=
val
*
100
+
'%'
return
val
},
},
}
;
}
return
(
<
div
className=
'home-page'
>
<
HomeTip
/>
...
...
@@ -359,7 +345,7 @@ class Home extends React.Component {
</
div
>
</
div
>
<
div
className=
'course-item'
>
<
div
className=
'course-title'
>
线下
课
</
div
>
<
div
className=
'course-title'
>
线下
活动
</
div
>
<
div
className=
'data'
>
<
span
className=
'course-number'
>
{
offlineCourseNum
}
</
span
>
{
incOfflineCourseNum
>
0
&&
<
span
className=
'icon iconfont'
>

</
span
>
}
...
...
@@ -409,9 +395,10 @@ class Home extends React.Component {
</
span
>
<
span
className=
{
`tab${scheduleType === 'VOICE' ? ' selected' : ''}`
}
onClick=
{
()
=>
this
.
setState
({
scheduleType
:
'VOICE'
},
()
=>
this
.
getHotCourse
())
}
>
线上课
</
span
>
<
span
onClick=
{
()
=>
this
.
setState
({
scheduleType
:
'VOICE'
},
()
=>
this
.
getHotCourse
())
}
>
线上课
</
span
>
<
span
className=
{
`tab${scheduleType === 'PICTURE' ? ' selected' : ''}`
}
onClick=
{
()
=>
this
.
setState
({
scheduleType
:
'PICTURE'
},
()
=>
this
.
getHotCourse
())
}
>
图文课
...
...
@@ -429,7 +416,7 @@ class Home extends React.Component {
style=
{
{
width
:
88
}
}
value=
{
timeRange
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
timeRange
:
value
},
()
=>
this
.
getHotCourse
())
;
this
.
setState
({
timeRange
:
value
},
()
=>
this
.
getHotCourse
())
}
}
>
<
Option
value=
'7'
>
近7天
</
Option
>
<
Option
value=
'15'
>
近15天
</
Option
>
...
...
@@ -509,11 +496,11 @@ class Home extends React.Component {
tooltip=
{
[
'item*percent'
,
(
item
,
percent
)
=>
{
percent
=
Math
.
round
(
percent
*
100
)
+
'%'
;
percent
=
Math
.
round
(
percent
*
100
)
+
'%'
return
{
name
:
item
,
value
:
percent
,
}
;
}
},
]
}
style=
{
{
...
...
@@ -567,7 +554,7 @@ class Home extends React.Component {
style=
{
{
width
:
88
}
}
value=
{
studyTimeRange
}
onChange=
{
(
value
)
=>
{
this
.
setState
({
studyTimeRange
:
value
},
()
=>
this
.
getStudyInfo
())
;
this
.
setState
({
studyTimeRange
:
value
},
()
=>
this
.
getStudyInfo
())
}
}
>
<
Option
value=
'7'
>
近7天
</
Option
>
<
Option
value=
'15'
>
近15天
</
Option
>
...
...
@@ -595,8 +582,8 @@ class Home extends React.Component {
</
div
>
</
div
>
</
div
>
)
;
)
}
}
export
default
Home
;
export
default
Home
src/modules/prepare-lesson/components/DiskList.jsx
View file @
39be164c
/*
* @Author: 吴文洁
* @Date: 2020-06-09 09:47:21
* @Author: 吴文洁
* @Date: 2020-06-09 09:47:21
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-06-23 14:54:14
* @Description: 网络磁盘(我的文件、公共文件、员工文件)
*/
import
React
from
'react'
;
import
React
from
'react'
import
{
DISK_MAP
}
from
"@/common/constants/academic/lessonEnum"
;
import
{
DISK_MAP
}
from
'@/common/constants/academic/lessonEnum'
function
DiskList
(
props
)
{
const
{
diskList
,
currentRootDisk
}
=
props
;
const
{
diskList
,
currentRootDisk
}
=
props
return
(
<
div
className=
"disk-list__wrap"
>
<
div
className=
"disk-list"
>
{
diskList
.
map
((
item
)
=>
{
<
div
className=
'disk-list__wrap'
>
<
div
className=
'disk-list'
>
{
diskList
.
map
((
item
)
=>
{
const
isActive
=
item
.
disk
===
currentRootDisk
.
disk
const
isActive
=
item
.
disk
===
currentRootDisk
.
disk
;
return
(
<
div
key=
{
item
.
disk
}
className=
{
`item ${isActive ? 'active' : ''}`
}
onClick=
{
()
=>
{
props
.
onChange
(
item
)}
}
>
{
item
.
disk
===
'MYSELF'
&&
<
span
className=
"icon iconfont"
>

</
span
>
}
{
item
.
disk
===
'COMMON'
&&
<
span
className=
"icon iconfont"
>

</
span
>
}
{
item
.
disk
===
'EMPLOYEE'
&&
<
span
className=
"icon iconfont"
>

</
span
>
}
<
span
className=
"disk-name"
>
{
item
.
folderName
}
</
span
>
</
div
>
)
})
}
return
(
<
div
key=
{
item
.
disk
}
className=
{
`item ${isActive ? 'active' : ''}`
}
onClick=
{
()
=>
{
props
.
onChange
(
item
)
}
}
>
{
item
.
disk
===
'MYSELF'
&&
<
span
className=
'icon iconfont'
>

</
span
>
}
{
item
.
disk
===
'COMMON'
&&
<
span
className=
'icon iconfont'
>

</
span
>
}
{
item
.
disk
===
'EMPLOYEE'
&&
<
span
className=
'icon iconfont'
>

</
span
>
}
<
span
className=
'disk-name'
>
{
item
.
folderName
}
</
span
>
</
div
>
)
})
}
</
div
>
<
a
className=
"guide-href"
<
a
className=
'guide-href'
href=
{
window
.
NewVersion
?
'https://mp.weixin.qq.com/s/s0XN0Gk4Xul192SmTd6znw'
:
'https://mp.weixin.qq.com/s/2EMWaaa3LQwkJd59bmy8pA'
}
target=
"_blank"
>
进一步了解资料云盘
target=
'_blank'
>
进一步了解素材库
</
a
>
</
div
>
)
}
;
}
export
default
DiskList
;
\ No newline at end of file
export
default
DiskList
src/modules/prepare-lesson/index.jsx
View file @
39be164c
import
React
from
'react'
;
import
{
withRouter
}
from
'react-router-dom'
;
import
{
Modal
,
Button
}
from
'antd'
;
import
React
from
'react'
import
{
withRouter
}
from
'react-router-dom'
import
{
Modal
,
Button
}
from
'antd'
import
User
from
'@/common/js/user'
;
import
User
from
'@/common/js/user'
import
FolderManage
from
'./components/FolderManage'
;
import
DiskList
from
'./components/DiskList'
;
import
{
DISK_MAP
}
from
"@/common/constants/academic/lessonEnum"
;
import
FolderManage
from
'./components/FolderManage'
import
DiskList
from
'./components/DiskList'
import
{
DISK_MAP
}
from
'@/common/constants/academic/lessonEnum'
import
'./index.less'
;
import
'./index.less'
const
{
teacherId
,
gmtCreate
}
=
window
.
currentUserInstInfo
;
const
{
teacherId
,
gmtCreate
}
=
window
.
currentUserInstInfo
// 判断是否是5.0或4.0T端
const
isTeacher
=
!!
teacherId
;
const
isTeacher
=
!!
teacherId
// 判断是新用户还是老用户(gmtCreate小于上线日期的话就是老用户)
const
onlineDate
=
+
new
Date
(
'2020-07-17 00:00:00'
)
;
const
isOldUser
=
gmtCreate
<=
onlineDate
;
const
onlineDate
=
+
new
Date
(
'2020-07-17 00:00:00'
)
const
isOldUser
=
gmtCreate
<=
onlineDate
const
defaultRootDisk
=
{
folderName
:
'我的文件'
,
disk
:
'MYSELF'
,
uploadPower
:
false
uploadPower
:
false
,
}
class
PrepareLessonPage
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
const
prepareLessonTips
=
localStorage
.
getItem
(
'prepare_lesson_tips'
)
;
super
(
props
)
const
prepareLessonTips
=
localStorage
.
getItem
(
'prepare_lesson_tips'
)
this
.
state
=
{
prepareLessonTips
,
diskList
:
[],
// 可见磁盘目录
currentRootDisk
:
defaultRootDisk
diskList
:
[],
// 可见磁盘目录
currentRootDisk
:
defaultRootDisk
,
}
}
componentWillMount
()
{
this
.
handleFetchDiskList
()
;
this
.
handleFetchDiskList
()
}
handleFetchDiskList
=
async
()
=>
{
const
res
=
await
axios
.
Apollo
(
'public/apollo/getUserDisk'
,
{})
;
const
{
result
=
[]
}
=
res
;
const
res
=
await
axios
.
Apollo
(
'public/apollo/getUserDisk'
,
{})
const
{
result
=
[]
}
=
res
const
diskList
=
result
.
map
((
item
)
=>
{
return
{
...
item
,
folderName
:
DISK_MAP
[
item
.
disk
]
folderName
:
DISK_MAP
[
item
.
disk
]
,
}
})
;
})
this
.
setState
({
diskList
,
currentRootDisk
:
diskList
[
0
]
||
defaultRootDisk
})
;
currentRootDisk
:
diskList
[
0
]
||
defaultRootDisk
,
})
}
handleChangeDisk
=
(
disk
)
=>
{
this
.
setState
({
currentRootDisk
:
disk
})
;
currentRootDisk
:
disk
,
})
}
render
()
{
const
{
currentRootDisk
,
prepareLessonTips
,
diskList
}
=
this
.
state
;
const
{
currentRootDisk
,
prepareLessonTips
,
diskList
}
=
this
.
state
return
(
<
div
className=
"prepare-lesson-page page"
>
<
div
className=
"content-header"
>
资料云盘
</
div
>
<
div
className=
"box content-body"
>
<
DiskList
diskList=
{
diskList
}
currentRootDisk=
{
currentRootDisk
}
onChange=
{
this
.
handleChangeDisk
}
/>
<
FolderManage
currentRootDisk=
{
currentRootDisk
}
/>
<
div
className=
'prepare-lesson-page page'
>
<
div
className=
'content-header'
>
素材库
</
div
>
<
div
className=
'box content-body'
>
<
DiskList
diskList=
{
diskList
}
currentRootDisk=
{
currentRootDisk
}
onChange=
{
this
.
handleChangeDisk
}
/>
<
FolderManage
currentRootDisk=
{
currentRootDisk
}
/>
</
div
>
{
/* 老用户显示弹窗提示 */
}
<
Modal
title=
"备课本改版"
title=
'备课本改版'
visible=
{
!
prepareLessonTips
&&
isOldUser
}
footer=
{
null
}
width=
{
680
}
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
"icon iconfont modal-close-icon"
>

</
span
>
}
className=
"prepare-lesson-upgrade-modal"
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
className=
'prepare-lesson-upgrade-modal'
onCancel=
{
()
=>
{
this
.
setState
({
prepareLessonTips
:
true
prepareLessonTips
:
true
,
})
}
}
>
<
div
className=
"title"
>
“备课本” 升级为 “资料云盘” 了!
</
div
>
<
div
className=
"upgrade-list"
>
<
div
className=
"upgrade-list__item"
>
<
img
src=
"https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780611301.png"
alt=
""
/>
<
div
className=
"item-title"
>
存储更便捷
</
div
>
<
div
className=
"item-sub-title"
>
讲次关联模式升级文件夹模式,存储不再受讲次限制
</
div
>
}
}
>
<
div
className=
'title'
>
“备课本” 升级为 “素材库” 了!
</
div
>
<
div
className=
'upgrade-list'
>
<
div
className=
'upgrade-list__item'
>
<
img
src=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780611301.png'
alt=
''
/>
<
div
className=
'item-title'
>
存储更便捷
</
div
>
<
div
className=
'item-sub-title'
>
讲次关联模式升级文件夹模式,存储不再受讲次限制
</
div
>
</
div
>
<
div
className=
"upgrade-list__item"
>
<
img
src=
"https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780629259.png"
alt=
""
/>
<
div
className=
"item-title"
>
结构更清晰
</
div
>
<
div
className=
"item-sub-title"
>
新增“我的文件”“公共文件”“员工文件”,满足机构存储需求
</
div
>
<
div
className=
'upgrade-list__item'
>
<
img
src=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780629259.png'
alt=
''
/>
<
div
className=
'item-title'
>
结构更清晰
</
div
>
<
div
className=
'item-sub-title'
>
新增“我的文件”“公共文件”“员工文件”,满足机构存储需求
</
div
>
</
div
>
<
div
className=
"upgrade-list__item"
>
<
img
src=
"https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780641665.png"
alt=
""
/>
<
div
className=
"item-title"
>
同步更方便
</
div
>
<
div
className=
"item-sub-title"
>
支持主管直接查看员工文件,优质资料一目了然
</
div
>
<
div
className=
'upgrade-list__item'
>
<
img
src=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594780641665.png'
alt=
''
/>
<
div
className=
'item-title'
>
同步更方便
</
div
>
<
div
className=
'item-sub-title'
>
支持主管直接查看员工文件,优质资料一目了然
</
div
>
</
div
>
</
div
>
<
div
className=
"footer"
className=
'footer'
onClick=
{
()
=>
{
this
.
setState
({
prepareLessonTips
:
true
});
localStorage
.
setItem
(
'prepare_lesson_tips'
,
true
);
}
}
>
我知道了
</
div
>
this
.
setState
({
prepareLessonTips
:
true
})
localStorage
.
setItem
(
'prepare_lesson_tips'
,
true
)
}
}
>
我知道了
</
div
>
</
Modal
>
</
div
>
)
}
}
export
default
PrepareLessonPage
;
\ No newline at end of file
export
default
PrepareLessonPage
src/modules/resource-disk/components/FolderList.jsx
View file @
39be164c
/*
* @Author: 吴文洁
* @Date: 2020-06-09 10:47:51
* @Author: 吴文洁
* @Date: 2020-06-09 10:47:51
* @Last Modified by: chenshu
* @Last Modified time: 2021-06-08 18:10:25
* @Description: 文件夹列表
*/
import
React
from
'react'
;
import
{
Table
,
Menu
,
Dropdown
,
Modal
,
message
,
Tooltip
}
from
'antd'
;
import
_
from
'underscore'
;
import
{
PageControl
}
from
'xiaomai-b-components'
;
import
{
XMTable
}
from
'@/components'
;
import
Service
from
'@/common/js/service'
;
import
{
formatDate
}
from
'@/domains/basic-domain/utils'
;
import
{
FILE_TYPE_ICON_MAP
,
SUPPORT_FILE_TYPE_MAP
,
DEFAULT_SIZE_UNIT
}
from
'@/domains/resource-disk/constants'
;
import
{
getFileTypeByName
}
from
'@/domains/resource-disk/utils'
;
import
addData
from
'../../lottie/addData/data.json'
;
import
search
from
'../../lottie/search/data.json'
;
import
UploadProgressModal
from
'@/bu-components/UploadProgressModal'
;
import
SelectPrepareFileModal
from
'@/bu-components/SelectPrepareFileModal'
;
import
CopyFileModal
from
'@/bu-components/CopyFileModal'
;
import
ManagingMembersModal
from
'@/bu-components/ManagingMembersModal'
;
import
PreviewFileModal
from
'@/bu-components/PreviewFileModal'
;
import
{
YZ_APPId
,
YZ_PREVIEW_URL
,
OFFICE_PREVIEW_URL
}
from
'@/domains/basic-domain/constants'
;
import
BaseService
from
"@/domains/basic-domain/baseService"
;
import
ScanFileModal
from
'../modal/ScanFileModal'
;
import
CreateFolderModal
from
'../modal/CreateFolderModal'
;
import
User
from
'@/common/js/user'
;
import
axios
from
'axios'
;
const
appId
=
"yozoqvpO2Hvz8346"
;
import
React
from
'react'
import
{
Table
,
Menu
,
Dropdown
,
Modal
,
message
,
Tooltip
}
from
'antd'
import
_
from
'underscore'
import
{
PageControl
}
from
'xiaomai-b-components'
import
{
XMTable
}
from
'@/components'
import
Service
from
'@/common/js/service'
import
{
formatDate
}
from
'@/domains/basic-domain/utils'
import
{
FILE_TYPE_ICON_MAP
,
SUPPORT_FILE_TYPE_MAP
,
DEFAULT_SIZE_UNIT
}
from
'@/domains/resource-disk/constants'
import
{
getFileTypeByName
}
from
'@/domains/resource-disk/utils'
import
addData
from
'../../lottie/addData/data.json'
import
search
from
'../../lottie/search/data.json'
import
UploadProgressModal
from
'@/bu-components/UploadProgressModal'
import
SelectPrepareFileModal
from
'@/bu-components/SelectPrepareFileModal'
import
CopyFileModal
from
'@/bu-components/CopyFileModal'
import
ManagingMembersModal
from
'@/bu-components/ManagingMembersModal'
import
PreviewFileModal
from
'@/bu-components/PreviewFileModal'
import
{
YZ_APPId
,
YZ_PREVIEW_URL
,
OFFICE_PREVIEW_URL
}
from
'@/domains/basic-domain/constants'
import
BaseService
from
'@/domains/basic-domain/baseService'
import
ScanFileModal
from
'../modal/ScanFileModal'
import
CreateFolderModal
from
'../modal/CreateFolderModal'
import
User
from
'@/common/js/user'
import
axios
from
'axios'
const
appId
=
'yozoqvpO2Hvz8346'
const
DEL_FOLDER_URL_MAP
=
{
'MYSELF'
:
'public/hadesStore/delFolder'
,
'COMMON'
:
'public/hadesStore/delFolder'
MYSELF
:
'public/hadesStore/delFolder'
,
COMMON
:
'public/hadesStore/delFolder'
,
}
// 支持本地上传的文件类型
const
loaclFileType
=
SUPPORT_FILE_TYPE_MAP
.
join
(
','
)
;
const
loaclFileType
=
SUPPORT_FILE_TYPE_MAP
.
join
(
','
)
let
count
=
0
;
let
count
=
0
class
FolderList
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
localFileList
:
[],
// 本地文件列表(待上传)
currentFolder
:
{},
// 当前文件/文件夹(操作列表中的文件/文件夹的时候需要用到)
uploadFolderPath
:
{},
// 上传文件的目录,防止中途切换文件夹
renameModalData
:
{},
// 重命名弹窗
scanFileModal
:
null
,
// 预览文件弹窗
showUploadModal
:
false
,
// 上传进度弹窗
showCopyFileModal
:
false
,
// 复制文件弹窗
showManagingModal
:
false
,
// 管理文件查看编辑权限
nonCompliantFileList
:
[],
// 不符合上限的文件列表
parentRights
:
''
,
// 继承父级文件夹权限
showPreviewModal
:
false
,
//是否显示loading
previewing
:
false
,
//是否正在预览
previewStatus
:
'UPLOAD'
//预览文件的生成状态
localFileList
:
[],
// 本地文件列表(待上传)
currentFolder
:
{},
// 当前文件/文件夹(操作列表中的文件/文件夹的时候需要用到)
uploadFolderPath
:
{},
// 上传文件的目录,防止中途切换文件夹
renameModalData
:
{},
// 重命名弹窗
scanFileModal
:
null
,
// 预览文件弹窗
showUploadModal
:
false
,
// 上传进度弹窗
showCopyFileModal
:
false
,
// 复制文件弹窗
showManagingModal
:
false
,
// 管理文件查看编辑权限
nonCompliantFileList
:
[],
// 不符合上限的文件列表
parentRights
:
''
,
// 继承父级文件夹权限
showPreviewModal
:
false
,
//是否显示loading
previewing
:
false
,
//是否正在预览
previewStatus
:
'UPLOAD'
,
//预览文件的生成状态
}
}
componentWillReceiveProps
(
nextProps
)
{
const
{
folderPathList
}
=
nextProps
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
]
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
]
this
.
setState
({
currentFolder
currentFolder
,
})
}
//预览文件
handleSelect
=
(
folder
)
=>
{
// 只有文件才有预览功能
if
(
folder
.
folderType
===
'FOLDER'
)
{
this
.
handleSelectFolder
(
folder
)
;
this
.
handleSelectFolder
(
folder
)
}
else
{
this
.
handleScanFile
(
folder
)
;
this
.
handleScanFile
(
folder
)
}
}
// 埋点
// 埋点
handleDataDot
=
(
folderFormat
)
=>
{
switch
(
folderFormat
)
{
case
'PDF'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_pdf'
,
'资料云盘_点击预览_pdf'
);
break
;
case
'WORD'
:
case
'DOCX'
:
case
'DOC'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_word'
,
'资料云盘_点击预览_word'
);
break
;
case
'EXCEL'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_excel'
,
'资料云盘_点击预览_excel'
);
break
;
case
'PPT'
:
case
'PPTX'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_ppt'
,
'资料云盘_点击预览_ppt'
);
break
;
default
:
break
;
switch
(
folderFormat
)
{
case
'PDF'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_pdf'
,
'资料云盘_点击预览_pdf'
)
break
case
'WORD'
:
case
'DOCX'
:
case
'DOC'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_word'
,
'资料云盘_点击预览_word'
)
break
case
'EXCEL'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_excel'
,
'资料云盘_点击预览_excel'
)
break
case
'PPT'
:
case
'PPTX'
:
window
.
WEBTRACING
(
'resource_disk_file_preview_ppt'
,
'资料云盘_点击预览_ppt'
)
break
default
:
break
}
}
handleYZPreviewDataDot
=
(
folderFormat
)
=>
{
switch
(
folderFormat
)
{
case
'PDF'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_pdf'
,
'资料云盘_点击永中预览_pdf'
);
break
;
case
'WORD'
:
case
'DOCX'
:
case
'DOC'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_word'
,
'资料云盘_点击永中预览_word'
);
break
;
case
'EXCEL'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_excel'
,
'资料云盘_点击永中预览_excel'
);
break
;
case
'PPT'
:
case
'PPTX'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_ppt'
,
'资料云盘_点击永中预览_ppt'
);
break
;
default
:
break
;
handleYZPreviewDataDot
=
(
folderFormat
)
=>
{
switch
(
folderFormat
)
{
case
'PDF'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_pdf'
,
'资料云盘_点击永中预览_pdf'
)
break
case
'WORD'
:
case
'DOCX'
:
case
'DOC'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_word'
,
'资料云盘_点击永中预览_word'
)
break
case
'EXCEL'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_excel'
,
'资料云盘_点击永中预览_excel'
)
break
case
'PPT'
:
case
'PPTX'
:
window
.
WEBTRACING
(
'resource_disk_yz_file_preview_ppt'
,
'资料云盘_点击永中预览_ppt'
)
break
default
:
break
}
}
// 预览文件
handleScanFile
=
async
(
folder
)
=>
{
const
{
folderFormat
,
folderSize
,
ossUrl
,
rights
,
fileVersionId
,
id
,
folderName
}
=
folder
;
const
{
currentRootDisk
}
=
this
.
props
;
const
{
folderFormat
,
folderSize
,
ossUrl
,
rights
,
fileVersionId
,
id
,
folderName
}
=
folder
const
{
currentRootDisk
}
=
this
.
props
//如果是公共文件且只有查看的权限的用户的预览对接的三方是永中
const
that
=
this
;
if
(
currentRootDisk
.
disk
===
"COMMON"
&&
rights
===
"LOOK"
)
{
const
that
=
this
if
(
currentRootDisk
.
disk
===
'COMMON'
&&
rights
===
'LOOK'
)
{
switch
(
folderFormat
)
{
case
'PDF'
:
case
'WORD'
:
...
...
@@ -136,155 +135,160 @@ class FolderList extends React.Component {
case
'EXCEL'
:
case
'PPT'
:
case
'PPTX'
:
that
.
handleYZPreviewDataDot
(
folderFormat
);
if
(
!
fileVersionId
){
this
.
setState
({
previewing
:
true
,
showPreviewModal
:
true
,
previewStatus
:
'UPLOAD'
},
async
()
=>
{
const
uploadParams
=
{
fileUrl
:
ossUrl
,
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'UPLOAD'
that
.
handleYZPreviewDataDot
(
folderFormat
)
if
(
!
fileVersionId
)
{
this
.
setState
(
{
previewing
:
true
,
showPreviewModal
:
true
,
previewStatus
:
'UPLOAD'
,
},
async
()
=>
{
const
uploadParams
=
{
fileUrl
:
ossUrl
,
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'UPLOAD'
,
}
const
uploadSign
=
await
BaseService
.
getYoZoSign
(
uploadParams
)
;
BaseService
.
yoZoUpload
(
ossUrl
,
YZ_APPId
,
uploadSign
).
then
(
async
function
(
response
)
{
const
saveParams
=
{
fileVersionId
:
response
.
data
.
data
.
fileVersionId
,
folderId
:
id
,
instId
:
User
.
getStoreId
(),
const
uploadSign
=
await
BaseService
.
getYoZoSign
(
uploadParams
)
BaseService
.
yoZoUpload
(
ossUrl
,
YZ_APPId
,
uploadSign
).
then
(
async
function
(
response
)
{
const
saveParams
=
{
fileVersionId
:
response
.
data
.
data
.
fileVersionId
,
folderId
:
id
,
instId
:
User
.
getStoreId
(),
}
BaseService
.
saveYoZoFileVersionId
(
saveParams
)
;
const
{
previewing
}
=
that
.
state
;
if
(
previewing
)
{
const
previewParams
=
{
fileVersionId
:
response
.
data
.
data
.
fileVersionId
,
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'VIEW'
,
htmlTitle
:
folderName
BaseService
.
saveYoZoFileVersionId
(
saveParams
)
const
{
previewing
}
=
that
.
state
if
(
previewing
)
{
const
previewParams
=
{
fileVersionId
:
response
.
data
.
data
.
fileVersionId
,
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'VIEW'
,
htmlTitle
:
folderName
,
}
const
previewSign
=
await
BaseService
.
getYoZoSign
(
previewParams
)
;
const
previewSign
=
await
BaseService
.
getYoZoSign
(
previewParams
)
const
url
=
`
${
YZ_PREVIEW_URL
}
?fileVersionId=
${
response
.
data
.
data
.
fileVersionId
}
&appId=
${
YZ_APPId
}
&sign=
${
previewSign
}
&htmlTitle=
${
folderName
}
`
that
.
setState
({
previewStatus
:
'UPLOAD_SUCCESS'
,
url
previewStatus
:
'UPLOAD_SUCCESS'
,
url
,
})
}
})
}
)
}
else
{
const
previewParams
=
{
}
)
}
else
{
const
previewParams
=
{
fileVersionId
,
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'VIEW'
,
htmlTitle
:
folderName
instId
:
User
.
getStoreId
(),
yoZoTypeEnum
:
'VIEW'
,
htmlTitle
:
folderName
,
}
const
previewSign
=
await
BaseService
.
getYoZoSign
(
previewParams
)
;
const
previewSign
=
await
BaseService
.
getYoZoSign
(
previewParams
)
const
url
=
`
${
YZ_PREVIEW_URL
}
?fileVersionId=
${
fileVersionId
}
&appId=
${
YZ_APPId
}
&sign=
${
previewSign
}
&htmlTitle=
${
folderName
}
`
const
a
=
document
.
createElement
(
'a'
)
;
document
.
body
.
appendChild
(
a
)
;
a
.
setAttribute
(
'href'
,
url
)
;
a
.
setAttribute
(
'target'
,
'_blank'
)
;
a
.
click
()
;
const
a
=
document
.
createElement
(
'a'
)
document
.
body
.
appendChild
(
a
)
a
.
setAttribute
(
'href'
,
url
)
a
.
setAttribute
(
'target'
,
'_blank'
)
a
.
click
()
document
.
body
.
removeChild
(
a
)
}
break
;
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
}
}
else
{
}
else
{
switch
(
folderFormat
)
{
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'
)
&&
folderSize
>
10
*
DEFAULT_SIZE_UNIT
)
{
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'
)
&&
folderSize
>
10
*
DEFAULT_SIZE_UNIT
)
{
Modal
.
confirm
({
title
:
'抱歉,不能在线预览'
,
content
:
'由于文件较大,不支持在线预览,请下载后再查看'
,
okText
:
"下载"
,
okText
:
'下载'
,
onOk
:
()
=>
{
const
a
=
document
.
createElement
(
'a'
)
;
a
.
href
=
ossUrl
;
a
.
click
()
;
}
})
;
break
;
const
a
=
document
.
createElement
(
'a'
)
a
.
href
=
ossUrl
a
.
click
()
}
,
})
break
}
const
prefixUrl
=
`
${
OFFICE_PREVIEW_URL
}
?src=`
;
const
prefixUrl
=
`
${
OFFICE_PREVIEW_URL
}
?src=`
const
scanUrl
=
`
${
prefixUrl
}${
encodeURIComponent
(
ossUrl
)}
`
window
.
open
(
scanUrl
,
"_blank"
);
break
;
window
.
open
(
scanUrl
,
'_blank'
)
break
default
:
const
scanFileModal
=
<
ScanFileModal
fileType=
{
folderFormat
}
item=
{
folder
}
close=
{
()
=>
{
this
.
setState
({
scanFileModal
:
null
})
}
}
/>
this
.
setState
({
scanFileModal
});
break
;
const
scanFileModal
=
(
<
ScanFileModal
fileType=
{
folderFormat
}
item=
{
folder
}
close=
{
()
=>
{
this
.
setState
({
scanFileModal
:
null
})
}
}
/>
)
this
.
setState
({
scanFileModal
})
break
}
}
// 预览文件埋点
this
.
handleDataDot
(
folderFormat
)
;
this
.
handleDataDot
(
folderFormat
)
}
cancelPreview
=
()
=>
{
cancelPreview
=
()
=>
{
this
.
setState
({
previewing
:
false
,
showPreviewModal
:
false
,
previewStatus
:
'UPLOAD'
previewing
:
false
,
showPreviewModal
:
false
,
previewStatus
:
'UPLOAD'
,
})
}
// 选择文件夹
handleSelectFolder
=
(
folder
)
=>
{
const
{
folderPathList
,
showResultPage
,
currentRootDisk
}
=
this
.
props
;
const
{
folderPathList
,
showResultPage
,
currentRootDisk
}
=
this
.
props
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
1
;
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
1
if
(
showResultPage
)
{
folderPathList
.
pop
()
;
folderPathList
.
pop
()
}
folderPathList
.
push
({
id
:
folder
.
id
,
folderName
:
folder
.
folderName
})
;
folderName
:
folder
.
folderName
,
})
this
.
setState
({
parentRights
:
folder
.
rights
,
})
this
.
props
.
onChangeFolderPath
(
folderPathList
)
;
this
.
props
.
onChangeFolderPath
(
folderPathList
)
this
.
props
.
onRefresh
({
parentId
:
folder
.
id
,
parentRights
:
folder
.
rights
,
folderIdType
:
employeeDisk
?
'USER'
:
'FOLDER'
})
;
folderIdType
:
employeeDisk
?
'USER'
:
'FOLDER'
,
})
}
// 修改文件路径
handleChangeFolderPath
=
(
folder
)
=>
{
const
{
instId
}
=
window
.
currentUserInstInfo
;
const
{
id
}
=
folder
;
const
{
currentRootDisk
}
=
this
.
props
;
const
{
instId
}
=
window
.
currentUserInstInfo
const
{
id
}
=
folder
const
{
currentRootDisk
}
=
this
.
props
const
params
=
{
id
,
instId
,
...
...
@@ -292,16 +296,16 @@ class FolderList extends React.Component {
}
Service
.
Hades
(
'public/hadesStore/folderPath'
,
params
).
then
((
res
)
=>
{
const
{
result
=
[]
}
=
res
;
this
.
props
.
onChangeFolderPath
(
result
,
false
)
;
const
{
result
=
[]
}
=
res
this
.
props
.
onChangeFolderPath
(
result
,
false
)
})
}
parseColumns
=
()
=>
{
const
{
currentRootDisk
,
showResultPage
,
folderPathList
}
=
this
.
props
;
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
;
const
{
currentRootDisk
,
showResultPage
,
folderPathList
}
=
this
.
props
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
1
;
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
1
const
columns
=
[
{
...
...
@@ -309,81 +313,66 @@ class FolderList extends React.Component {
key
:
'folderName'
,
dataIndex
:
'folderName'
,
width
:
'28%'
,
sorter
:
(
employeeDisk
||
!
hasManagementAuthority
)
?
false
:
true
,
sorter
:
employeeDisk
||
!
hasManagementAuthority
?
false
:
true
,
render
:
(
value
,
record
)
=>
{
const
{
folderType
,
folderFormat
}
=
record
;
const
isFolder
=
folderType
===
'FOLDER'
;
let
imgSrc
=
!
isFolder
?
FILE_TYPE_ICON_MAP
[
folderFormat
]
:
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png'
;
const
{
folderType
,
folderFormat
}
=
record
const
isFolder
=
folderType
===
'FOLDER'
let
imgSrc
=
!
isFolder
?
FILE_TYPE_ICON_MAP
[
folderFormat
]
:
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png'
if
(
employeeDisk
)
{
imgSrc
=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871440736.png'
}
return
(
<
div
className=
"file-name"
onClick=
{
()
=>
this
.
handleSelect
(
record
)
}
>
{
<
img
alt=
"img-src"
className=
"file-name__icon"
src=
{
imgSrc
}
/>
}
<
span
className=
{
`file-name__text ${!isFolder ? 'highlight' : ''}`
}
>
{
value
}
</
span
>
<
div
className=
'file-name'
onClick=
{
()
=>
this
.
handleSelect
(
record
)
}
>
{
<
img
alt=
'img-src'
className=
'file-name__icon'
src=
{
imgSrc
}
/>
}
<
span
className=
{
`file-name__text ${!isFolder ? 'highlight' : ''}`
}
>
{
value
}
</
span
>
</
div
>
)
}
}
,
},
{
title
:
'更新时间'
,
key
:
'updated'
,
dataIndex
:
'updated'
,
sorter
:
(
employeeDisk
||
!
hasManagementAuthority
)
?
false
:
true
,
sorter
:
employeeDisk
||
!
hasManagementAuthority
?
false
:
true
,
render
:
(
value
)
=>
{
return
<
span
>
{
formatDate
(
'YYYY-MM-DD H:i'
,
value
)
}
</
span
>
}
}
,
},
{
title
:
'大小'
,
key
:
'folderSize'
,
dataIndex
:
'folderSize'
,
width
:
'10%'
,
sorter
:
(
employeeDisk
||
!
hasManagementAuthority
)
?
false
:
true
,
sorter
:
employeeDisk
||
!
hasManagementAuthority
?
false
:
true
,
render
:
(
value
,
record
)
=>
{
const
{
folderType
}
=
record
;
const
_fileSize
=
Number
(
value
)
;
let
_size
=
`
${(
_fileSize
/
DEFAULT_SIZE_UNIT
).
toFixed
(
1
)}
M`
;
const
{
folderType
}
=
record
const
_fileSize
=
Number
(
value
)
let
_size
=
`
${(
_fileSize
/
DEFAULT_SIZE_UNIT
).
toFixed
(
1
)}
M`
if
(
_fileSize
<
0.1
*
DEFAULT_SIZE_UNIT
)
{
_size
=
`
${(
_fileSize
/
1024
).
toFixed
(
1
)}
kb`
;
_size
=
`
${(
_fileSize
/
1024
).
toFixed
(
1
)}
kb`
}
return
(
<
span
>
{
folderType
===
'FILE'
?
_size
:
'-'
}
</
span
>
)
}
return
<
span
>
{
folderType
===
'FILE'
?
_size
:
'-'
}
</
span
>
},
},
{
title
:
'操作'
,
key
:
'operate'
,
render
:
(
value
,
record
)
=>
{
if
((
!
(
currentRootDisk
.
disk
===
'COMMON'
&&
(
folderPathList
.
length
===
1
||
record
.
folderType
===
'FOLDER'
))
||
hasManagementAuthority
)
&&
!
(
record
.
rights
===
"LOOK"
)
){
if
(
(
!
(
currentRootDisk
.
disk
===
'COMMON'
&&
(
folderPathList
.
length
===
1
||
record
.
folderType
===
'FOLDER'
))
||
hasManagementAuthority
)
&&
!
(
record
.
rights
===
'LOOK'
)
)
{
return
(
<
Dropdown
overlay=
{
this
.
renderMenu
(
record
)
}
trigger=
{
[
'hover'
]
}
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
'icon iconfont'
>

</
span
>
</
Dropdown
>
)
}
return
<
span
>
-
</
span
>
}
}
}
,
}
,
]
// 公共文件需要显示创建者
...
...
@@ -391,8 +380,8 @@ class FolderList extends React.Component {
columns
.
splice
(
1
,
0
,
{
title
:
'创建者'
,
key
:
'createName'
,
dataIndex
:
'createName'
})
;
dataIndex
:
'createName'
,
})
}
// 搜索结果需要显示所在目录
...
...
@@ -402,38 +391,39 @@ class FolderList extends React.Component {
key
:
'parentName'
,
dataIndex
:
'parentName'
,
render
:
(
value
,
record
)
=>
{
return
<
span
className=
"file-path"
onClick=
{
()
=>
this
.
handleChangeFolderPath
(
record
)
}
>
{
value
||
currentRootDisk
.
folderName
}
</
span
>
}
return
(
<
span
className=
'file-path'
onClick=
{
()
=>
this
.
handleChangeFolderPath
(
record
)
}
>
{
value
||
currentRootDisk
.
folderName
}
</
span
>
)
},
})
}
return
columns
;
return
columns
}
// 删除文件
handleDeleteFolder
=
(
folder
)
=>
{
const
{
currentRootDisk
:
{
disk
}
}
=
this
.
props
;
const
{
currentRootDisk
:
{
disk
},
}
=
this
.
props
Modal
.
confirm
({
title
:
'确认删除所选的文件吗?'
,
content
:
'删除后,数据将无法恢复。'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
okType
:
'danger'
,
onOk
:
()
=>
{
const
{
currentFolder
}
=
this
.
state
;
const
{
currentFolder
}
=
this
.
state
Service
.
Hades
(
DEL_FOLDER_URL_MAP
[
disk
],
{
operatorId
:
User
.
getUserId
(),
storeId
:
User
.
getStoreId
(),
ids
:
[
folder
.
id
],
}).
then
(()
=>
{
message
.
success
(
'删除成功'
)
;
this
.
props
.
onRefresh
({
parentId
:
currentFolder
.
id
||
null
})
;
message
.
success
(
'删除成功'
)
this
.
props
.
onRefresh
({
parentId
:
currentFolder
.
id
||
null
})
})
}
})
;
}
,
})
}
// 重命名
...
...
@@ -443,90 +433,90 @@ class FolderList extends React.Component {
visible
:
true
,
id
:
folder
.
id
,
folderName
:
folder
.
folderName
,
}
})
;
}
,
})
}
// 重命名完成或者取消重命名之后隐藏重命名弹窗
handleRenameDone
=
(
folderName
)
=>
{
return
new
Promise
((
resolve
)
=>
{
const
{
renameModalData
,
currentFolder
}
=
this
.
state
;
const
{
folderPathList
}
=
this
.
props
;
const
{
renameModalData
,
currentFolder
}
=
this
.
state
const
{
folderPathList
}
=
this
.
props
// 名称未修改不发送请求
if
(
folderName
===
renameModalData
.
folderName
)
{
this
.
setState
({
renameModalData
:
{}
})
;
return
;
this
.
setState
({
renameModalData
:
{}
})
return
}
// 判断是否有同名文件
this
.
handleGetSameNameFiles
(
folderName
).
then
((
res
)
=>
{
if
(
(
!!
res
)
||
(
res
&&
Object
.
keys
(
res
).
length
))
{
if
(
!!
res
||
(
res
&&
Object
.
keys
(
res
).
length
))
{
if
(
!
res
.
isLook
&&
folderPathList
.
length
===
1
)
{
message
.
warning
(
'此目录下已存在同名文件,有疑问请联系机构校长'
)
;
message
.
warning
(
'此目录下已存在同名文件,有疑问请联系机构校长'
)
}
else
{
message
.
warning
(
'此目录下已存在同名文件'
)
;
message
.
warning
(
'此目录下已存在同名文件'
)
}
return
;
return
}
Service
.
Hades
(
'public/hadesStore/renameFolder'
,
{
id
:
renameModalData
.
id
,
name
:
folderName
}).
then
(
res2
=>
{
name
:
folderName
,
}).
then
(
(
res2
)
=>
{
if
(
!
res2
.
success
)
{
const
errorMessage
=
'此目录下已存在同名文件'
;
message
.
warning
(
errorMessage
)
;
return
;
const
errorMessage
=
'此目录下已存在同名文件'
message
.
warning
(
errorMessage
)
return
}
else
{
message
.
success
(
'重命名成功'
)
;
this
.
setState
({
renameModalData
:
{}
})
;
this
.
props
.
onRefresh
({
parentId
:
currentFolder
.
id
||
null
})
;
message
.
success
(
'重命名成功'
)
this
.
setState
({
renameModalData
:
{}
})
this
.
props
.
onRefresh
({
parentId
:
currentFolder
.
id
||
null
})
}
})
;
})
;
})
})
})
}
// 获取同名文件
handleGetSameNameFiles
=
async
(
folderName
)
=>
{
const
{
currentRootDisk
,
folderPathList
}
=
this
.
props
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
]
;
const
{
instId
}
=
window
.
currentUserInstInfo
;
const
{
currentRootDisk
,
folderPathList
}
=
this
.
props
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
]
const
{
instId
}
=
window
.
currentUserInstInfo
const
params
=
{
createId
:
User
.
getUserId
(),
createId
:
User
.
getUserId
(),
name
:
folderName
,
disk
:
currentRootDisk
.
disk
,
parentId
:
currentFolder
.
id
,
folderType
:
'FOLDER'
,
}
const
res
=
await
Service
.
Hades
(
'public/hadesStore/sameNameFile'
,
params
)
;
const
{
result
}
=
res
;
return
result
;
const
res
=
await
Service
.
Hades
(
'public/hadesStore/sameNameFile'
,
params
)
const
{
result
}
=
res
return
result
}
// 显示移动文件弹窗
handleShowSelectFileModal
=
(
file
)
=>
{
this
.
setState
({
currentFile
:
file
,
showSelectFileModal
:
true
})
;
showSelectFileModal
:
true
,
})
}
// 显示复制文件弹窗
handleShowCopyFileModal
=
(
file
)
=>
{
this
.
setState
({
currentFile
:
file
,
showCopyFileModal
:
true
})
;
showCopyFileModal
:
true
,
})
}
// 显示管理成员弹窗
handleShowManagingModal
=
(
file
)
=>
{
this
.
setState
({
currentFile
:
file
,
showManagingModal
:
true
})
;
showManagingModal
:
true
,
})
}
getBlob
=
(
url
)
=>
{
...
...
@@ -584,40 +574,40 @@ class FolderList extends React.Component {
// return;
// }
const
dom
=
document
.
querySelector
(
'#detailFileInput'
)
;
dom
.
click
()
;
const
dom
=
document
.
querySelector
(
'#detailFileInput'
)
dom
.
click
()
}
// 准备上传
handleUpload
=
(
event
)
=>
{
const
fileList
=
event
.
target
.
files
;
const
fileList
=
event
.
target
.
files
// 判断文件的大小是否超出了限制
const
nonCompliantFileList
=
[]
;
const
_fileList
=
[...
fileList
]
;
const
nonCompliantFileList
=
[]
const
_fileList
=
[...
fileList
]
_fileList
.
map
((
file
,
index
)
=>
{
let
{
size
,
type
,
name
}
=
file
;
let
{
size
,
type
,
name
}
=
file
if
(
!
type
)
{
type
=
getFileTypeByName
(
name
)
;
type
=
getFileTypeByName
(
name
)
}
if
(
type
.
indexOf
(
'image'
)
>
-
1
&&
size
>
50
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
)
;
_fileList
.
splice
(
index
,
1
)
;
nonCompliantFileList
.
push
(
file
)
_fileList
.
splice
(
index
,
1
)
}
if
(
type
.
indexOf
(
'audio'
)
>
-
1
&&
size
>
50
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
)
;
_fileList
.
splice
(
index
,
1
)
;
nonCompliantFileList
.
push
(
file
)
_fileList
.
splice
(
index
,
1
)
}
if
(
type
.
indexOf
(
'video'
)
>
-
1
&&
size
>
2000
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
)
;
_fileList
.
splice
(
index
,
1
)
;
nonCompliantFileList
.
push
(
file
)
_fileList
.
splice
(
index
,
1
)
}
if
(
loaclFileType
.
indexOf
(
type
)
>
-
1
&&
size
>
100
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
)
;
_fileList
.
splice
(
index
,
1
)
;
nonCompliantFileList
.
push
(
file
)
_fileList
.
splice
(
index
,
1
)
}
file
.
key
=
count
++
;
return
file
;
})
;
file
.
key
=
count
++
return
file
})
// 不符合规则的文件列表
if
(
nonCompliantFileList
.
length
>
0
)
{
this
.
setState
({
...
...
@@ -625,38 +615,38 @@ class FolderList extends React.Component {
showNonCompliantFileModal
:
true
,
})
}
else
{
this
.
handleShowUploadModal
(
_fileList
)
;
this
.
handleShowUploadModal
(
_fileList
)
}
// 清空文件,防止第二次无法上传同一个文件
const
dom
=
document
.
querySelector
(
'#detailFileInput'
)
;
dom
.
value
=
''
;
const
dom
=
document
.
querySelector
(
'#detailFileInput'
)
dom
.
value
=
''
}
// 显示上传进度弹窗
handleShowUploadModal
=
(
fileList
)
=>
{
// 保存当前路径
const
{
folderPathList
}
=
this
.
props
;
const
{
folderPathList
}
=
this
.
props
if
(
fileList
.
length
)
{
this
.
setState
({
showUploadModal
:
true
,
localFileList
:
fileList
,
uploadFolderPath
:
folderPathList
[
folderPathList
.
length
-
1
]
})
;
uploadFolderPath
:
folderPathList
[
folderPathList
.
length
-
1
]
,
})
}
}
// 上传成功
handleUploadDone
=
(
file
,
resourceId
)
=>
{
this
.
props
.
onCreate
(
file
,
resourceId
)
;
this
.
props
.
onCreate
(
file
,
resourceId
)
}
// 取消上传
handleHiddenUploadModal
=
()
=>
{
this
.
setState
({
showUploadModal
:
false
,
localFileList
:
[]
})
;
localFileList
:
[]
,
})
}
// 余额欠费提示弹窗
...
...
@@ -664,111 +654,123 @@ class FolderList extends React.Component {
Modal
.
info
({
title
:
'无法继续操作'
,
content
:
'直播系统已升级,请联系运营老师。'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
})
}
// 排序
handleChangeTable
=
(
pagination
,
filters
,
sorter
)
=>
{
const
{
columnKey
,
order
}
=
sorter
;
let
sort
=
null
;
if
(
columnKey
===
'folderName'
&&
order
===
'ascend'
)
{
sort
=
'NAME_ASC'
;
}
if
(
columnKey
===
'folderName'
&&
order
===
'descend'
)
{
sort
=
'NAME_DESC'
;
}
if
(
columnKey
===
'folderSize'
&&
order
===
'ascend'
)
{
sort
=
'SIZE_ASC'
;
}
if
(
columnKey
===
'folderSize'
&&
order
===
'descend'
)
{
sort
=
'SIZE_DESC'
;
}
if
(
columnKey
===
'updated'
&&
order
===
'ascend'
)
{
sort
=
'UPDATE_ASC'
;
}
if
(
columnKey
===
'updated'
&&
order
===
'descend'
)
{
sort
=
'UPDATE_DESC'
;
}
const
{
columnKey
,
order
}
=
sorter
let
sort
=
null
if
(
columnKey
===
'folderName'
&&
order
===
'ascend'
)
{
sort
=
'NAME_ASC'
}
if
(
columnKey
===
'folderName'
&&
order
===
'descend'
)
{
sort
=
'NAME_DESC'
}
if
(
columnKey
===
'folderSize'
&&
order
===
'ascend'
)
{
sort
=
'SIZE_ASC'
}
if
(
columnKey
===
'folderSize'
&&
order
===
'descend'
)
{
sort
=
'SIZE_DESC'
}
if
(
columnKey
===
'updated'
&&
order
===
'ascend'
)
{
sort
=
'UPDATE_ASC'
}
if
(
columnKey
===
'updated'
&&
order
===
'descend'
)
{
sort
=
'UPDATE_DESC'
}
const
{
currentFolder
}
=
this
.
state
;
const
{
currentFolder
}
=
this
.
state
this
.
props
.
onRefresh
({
sort
,
parentId
:
currentFolder
.
id
||
null
})
;
parentId
:
currentFolder
.
id
||
null
,
})
}
// 操作选项
renderMenu
=
(
record
)
=>
{
const
{
currentRootDisk
}
=
this
.
props
;
const
{
currentRootDisk
}
=
this
.
props
// 是否有编辑权限
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
;
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
// 公共文件权限和复制权限
const
{
folderType
,
rights
}
=
record
;
const
{
folderType
,
rights
}
=
record
const
menu
=
(
<
Menu
>
{
rights
===
"EDIT"
&&
!
record
.
parentId
&&
[
<
Menu
.
Item
key=
"administration"
>
<
span
onClick=
{
()
=>
this
.
handleShowManagingModal
(
record
)
}
>
权限管理
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Divider
key=
"administration-bottom"
/>
]
}
{
(
folderType
===
'FILE'
&&
(
rights
===
"LOOK_DOWNLOAD"
||
rights
===
'EDIT'
)
)
&&
<
Menu
.
Item
key=
"download"
>
<
span
onClick=
{
()
=>
{
this
.
handleDownload
(
record
)
}
}
>
下载
</
span
>
</
Menu
.
Item
>
}
{
(
rights
===
"LOOK_DOWNLOAD"
||
rights
===
'EDIT'
)
&&
<
Menu
.
Item
key=
"copy"
>
<
span
onClick=
{
()
=>
this
.
handleShowCopyFileModal
(
record
)
}
>
复制到
</
span
>
</
Menu
.
Item
>
}
{
hasManagementAuthority
&&
rights
===
"EDIT"
&&
[
<
Menu
.
Item
key=
"move"
>
<
span
onClick=
{
()
=>
this
.
handleShowSelectFileModal
(
record
)
}
>
移动到
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Item
key=
"rename"
>
<
span
onClick=
{
()
=>
this
.
handleRename
(
record
)
}
>
重命名
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Divider
key=
"administration-top"
/>,
<
Menu
.
Item
key=
"delete"
>
<
span
onClick=
{
()
=>
this
.
handleDeleteFolder
(
record
)
}
>
删除
</
span
>
</
Menu
.
Item
>
]
}
</
Menu
>
);
return
menu
;
<
Menu
>
{
rights
===
'EDIT'
&&
!
record
.
parentId
&&
[
<
Menu
.
Item
key=
'administration'
>
<
span
onClick=
{
()
=>
this
.
handleShowManagingModal
(
record
)
}
>
权限管理
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Divider
key=
'administration-bottom'
/>,
]
}
{
folderType
===
'FILE'
&&
(
rights
===
'LOOK_DOWNLOAD'
||
rights
===
'EDIT'
)
&&
(
<
Menu
.
Item
key=
'download'
>
<
span
onClick=
{
()
=>
{
this
.
handleDownload
(
record
)
}
}
>
下载
</
span
>
</
Menu
.
Item
>
)
}
{
(
rights
===
'LOOK_DOWNLOAD'
||
rights
===
'EDIT'
)
&&
(
<
Menu
.
Item
key=
'copy'
>
<
span
onClick=
{
()
=>
this
.
handleShowCopyFileModal
(
record
)
}
>
复制到
</
span
>
</
Menu
.
Item
>
)
}
{
hasManagementAuthority
&&
rights
===
'EDIT'
&&
[
<
Menu
.
Item
key=
'move'
>
<
span
onClick=
{
()
=>
this
.
handleShowSelectFileModal
(
record
)
}
>
移动到
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Item
key=
'rename'
>
<
span
onClick=
{
()
=>
this
.
handleRename
(
record
)
}
>
重命名
</
span
>
</
Menu
.
Item
>,
<
Menu
.
Divider
key=
'administration-top'
/>,
<
Menu
.
Item
key=
'delete'
>
<
span
onClick=
{
()
=>
this
.
handleDeleteFolder
(
record
)
}
>
删除
</
span
>
</
Menu
.
Item
>,
]
}
</
Menu
>
)
return
menu
}
render
()
{
const
{
currentFolder
,
currentFile
,
renameModalData
,
showSelectFileModal
,
showUploadModal
,
localFileList
,
showCopyFileModal
,
showManagingModal
,
showPreviewModal
,
previewStatus
,
url
}
=
this
.
state
;
const
{
selectedFileIds
,
folderList
,
showResultPage
,
currentRootDisk
,
query
,
totalCount
,
folderPathList
}
=
this
.
props
;
const
_disk
=
folderPathList
[
0
].
disk
;
currentFolder
,
currentFile
,
renameModalData
,
showSelectFileModal
,
showUploadModal
,
localFileList
,
showCopyFileModal
,
showManagingModal
,
showPreviewModal
,
previewStatus
,
url
,
}
=
this
.
state
const
{
selectedFileIds
,
folderList
,
showResultPage
,
currentRootDisk
,
query
,
totalCount
,
folderPathList
}
=
this
.
props
const
_disk
=
folderPathList
[
0
].
disk
// 是否有编辑权限
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
;
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
return
(
<
div
className=
"file-list"
>
<
div
className=
'file-list'
>
<
Choose
>
<
When
condition=
{
!
_
.
isEmpty
(
folderList
)
}
>
<
Table
key=
"table"
key=
'table'
rowKey=
{
(
record
)
=>
record
.
id
}
columns=
{
this
.
parseColumns
()
}
showSorterTooltip=
{
false
}
dataSource=
{
folderList
}
rowSelection=
{
{
selectedRowKeys
:
selectedFileIds
,
onChange
:
this
.
props
.
onChangeRow
}
}
rowSelection=
{
{
selectedRowKeys
:
selectedFileIds
,
onChange
:
this
.
props
.
onChangeRow
,
}
}
pagination=
{
false
}
onChange=
{
this
.
handleChangeTable
}
/>
...
...
@@ -778,73 +780,74 @@ class FolderList extends React.Component {
total=
{
totalCount
}
showSizeChanger=
{
true
}
toPage=
{
(
page
)
=>
{
this
.
props
.
onChangePage
(
'current'
,
page
+
1
)
;
this
.
props
.
onChangePage
(
'current'
,
page
+
1
)
}
}
onShowSizeChange=
{
(
current
,
size
)
=>
{
const
that
=
this
;
setTimeout
(()
=>
{
const
that
=
this
setTimeout
(()
=>
{
this
.
props
.
onChangePage
(
'size'
,
size
)
},
1000
)
},
1000
)
}
}
/>
</
When
>
<
Otherwise
>
<
XMTable
className=
"add-empty"
className=
'add-empty'
renderEmpty=
{
{
image
:
!
showResultPage
?
addData
:
search
,
description
:
<
Choose
>
<
When
condition=
{
!
showResultPage
}
>
<
input
multiple
type=
"file"
style=
{
{
display
:
'none'
}
}
id=
"detailFileInput"
accept=
".ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls"
onChange=
{
(
e
)
=>
this
.
handleUpload
(
e
)
}
/>
{
<
Choose
>
<
When
condition=
{
hasManagementAuthority
}
>
<
div
className=
"lottie-icon-title"
>
你还没有上传文件,点击
<
Tooltip
title=
"支持文件类型:ppt、word、excel、pdf、jpg、mp3、mp4,上传后默认私密,可邀请其他成员协作,支持批量上传文件"
>
<
span
className=
"upload-btn"
onClick=
{
this
.
handleChooseFile
}
>
上传文件
</
span
>
</
Tooltip
>
按钮
</
div
>
</
When
>
<
Otherwise
>
<
span
>
这个文件夹是空的
</
span
>
</
Otherwise
>
</
Choose
>
}
</
When
>
<
Otherwise
>
<
div
className=
"desc"
>
搜索无结果
</
div
>
</
Otherwise
>
</
Choose
>
description
:
(
<
Choose
>
<
When
condition=
{
!
showResultPage
}
>
<
input
multiple
type=
'file'
style=
{
{
display
:
'none'
}
}
id=
'detailFileInput'
accept=
'.ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls'
onChange=
{
(
e
)
=>
this
.
handleUpload
(
e
)
}
/>
{
<
Choose
>
<
When
condition=
{
hasManagementAuthority
}
>
<
div
className=
'lottie-icon-title'
>
你还没有上传文件,点击
<
Tooltip
title=
'支持文件类型:ppt、word、excel、pdf、jpg、mp3、mp4,上传后默认私密,可邀请其他成员协作,支持批量上传文件'
>
<
span
className=
'upload-btn'
onClick=
{
this
.
handleChooseFile
}
>
上传文件
</
span
>
</
Tooltip
>
按钮
</
div
>
</
When
>
<
Otherwise
>
<
span
>
这个文件夹是空的
</
span
>
</
Otherwise
>
</
Choose
>
}
</
When
>
<
Otherwise
>
<
div
className=
'desc'
>
搜索无结果
</
div
>
</
Otherwise
>
</
Choose
>
),
}
}
/>
</
Otherwise
>
</
Choose
>
<
CreateFolderModal
title=
'重命名'
folderName=
{
renameModalData
.
folderName
}
folderPathList=
{
folderPathList
}
isOpen=
{
renameModalData
.
visible
}
onClose=
{
()
=>
{
this
.
setState
({
renameModalData
:
{}
})
;
this
.
setState
({
renameModalData
:
{}
})
}
}
onOk=
{
this
.
handleRenameDone
}
/>
<
UploadProgressModal
isOpen=
{
showUploadModal
}
currentFolder=
{
currentFolder
}
...
...
@@ -857,43 +860,39 @@ class FolderList extends React.Component {
isOpen=
{
showSelectFileModal
}
currentRootDisk=
{
currentRootDisk
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
;
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onMove=
{
(
query
)
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
;
this
.
props
.
onMove
(
query
,
[
currentFile
.
id
],
[
currentFile
.
folderType
]);
this
.
setState
({
showSelectFileModal
:
false
})
this
.
props
.
onMove
(
query
,
[
currentFile
.
id
],
[
currentFile
.
folderType
])
}
}
/>
{
showCopyFileModal
&&
<
CopyFileModal
{
showCopyFileModal
&&
(
<
CopyFileModal
isOpen=
{
showCopyFileModal
}
dataInfo=
{
currentFile
}
currentRootDisk=
{
currentRootDisk
}
onClose=
{
()
=>
{
this
.
setState
({
showCopyFileModal
:
false
})
;
this
.
setState
({
showCopyFileModal
:
false
})
}
}
/>
}
{
showManagingModal
&&
<
ManagingMembersModal
)
}
{
showManagingModal
&&
(
<
ManagingMembersModal
isOpen=
{
showManagingModal
}
dataInfo=
{
currentFile
}
disk=
{
_disk
}
onClose=
{
()
=>
{
this
.
setState
({
showManagingModal
:
false
})
;
this
.
setState
({
showManagingModal
:
false
})
}
}
/>
}
{
showPreviewModal
&&
<
PreviewFileModal
onCancel=
{
()
=>
this
.
cancelPreview
()
}
previewStatus=
{
previewStatus
}
url=
{
url
}
/>
}
{
this
.
state
.
scanFileModal
}
{
this
.
state
.
chargeModal
}
)
}
{
showPreviewModal
&&
<
PreviewFileModal
onCancel=
{
()
=>
this
.
cancelPreview
()
}
previewStatus=
{
previewStatus
}
url=
{
url
}
/>
}
{
this
.
state
.
scanFileModal
}
{
this
.
state
.
chargeModal
}
</
div
>
)
}
}
export
default
FolderList
;
\ No newline at end of file
export
default
FolderList
src/modules/resource-disk/index.jsx
View file @
39be164c
import
React
from
'react'
;
import
Service
from
'@/common/js/service'
;
import
{
DISK_MAP
}
from
'@/domains/resource-disk/constants'
;
import
FolderManage
from
'./components/FolderManage'
;
import
DiskList
from
'./components/DiskList'
;
import
'./index.less'
;
import
React
from
'react'
import
Service
from
'@/common/js/service'
import
{
DISK_MAP
}
from
'@/domains/resource-disk/constants'
import
FolderManage
from
'./components/FolderManage'
import
DiskList
from
'./components/DiskList'
import
'./index.less'
const
defaultRootDisk
=
{
folderName
:
'公共文件'
,
disk
:
'COMMON'
,
uploadPower
:
true
uploadPower
:
true
,
}
class
PrepareLessonPage
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
// 目前只有公共文件,先由前端定义
diskList
:
[
{
folderName
:
'公共文件'
,
disk
:
'COMMON'
,
uploadPower
:
true
}
],
// 可见磁盘目录
currentRootDisk
:
defaultRootDisk
uploadPower
:
true
,
}
,
],
// 可见磁盘目录
currentRootDisk
:
defaultRootDisk
,
}
}
handleChangeDisk
=
(
disk
)
=>
{
this
.
setState
({
currentRootDisk
:
disk
})
;
currentRootDisk
:
disk
,
})
}
render
()
{
const
{
currentRootDisk
,
diskList
}
=
this
.
state
;
console
.
log
(
'currentRootDisk'
,
currentRootDisk
);
const
{
currentRootDisk
,
diskList
}
=
this
.
state
console
.
log
(
'currentRootDisk'
,
currentRootDisk
)
return
(
<
div
className=
"prepare-lesson-page page"
>
<
div
className=
"content-header"
>
资料云盘
</
div
>
<
div
className=
"box content-body"
>
<
DiskList
diskList=
{
diskList
}
currentRootDisk=
{
currentRootDisk
}
onChange=
{
this
.
handleChangeDisk
}
/>
<
FolderManage
currentRootDisk=
{
currentRootDisk
}
/>
<
div
className=
'prepare-lesson-page page'
>
<
div
className=
'content-header'
>
素材库
</
div
>
<
div
className=
'box content-body'
>
<
DiskList
diskList=
{
diskList
}
currentRootDisk=
{
currentRootDisk
}
onChange=
{
this
.
handleChangeDisk
}
/>
<
FolderManage
currentRootDisk=
{
currentRootDisk
}
/>
</
div
>
</
div
>
)
}
}
export
default
PrepareLessonPage
;
\ No newline at end of file
export
default
PrepareLessonPage
src/modules/store-manage/StoreDecorationPage.less
View file @
39be164c
.store-decoration-page {
.box {
padding-top:
11px
!important;
padding-top:
11px
!important;
}
thead {
display: none;
...
...
@@ -27,11 +27,11 @@
}
.banner-thumbnail {
width: 230px;
height:
79
px;
height:
96
px;
}
.web-banner-thumbnail {
width: 389px;
height:
67
px;
height:
162
px;
}
.index-num {
...
...
@@ -51,18 +51,17 @@
.operation {
.edit {
color: #2966
FF
;
color: #2966
ff
;
cursor: pointer;
}
.divider-line {
color:
#BFBFBF
color:
#bfbfbf;
}
.delete {
color: #2966
FF
;
color: #2966
ff
;
cursor: pointer;
}
}
}
.clip-box {
display: flex;
...
...
@@ -86,7 +85,7 @@
.preview-url {
width: 500px;
height: 73px;
background: #
E6E6E6;
background: #
e6e6e6;
}
#preview-url-box {
...
...
@@ -112,11 +111,11 @@
}
.banner-thumbnail {
width: 230px;
height:
79
px;
height:
96
px;
}
.web-banner-thumbnail {
width: 389px;
height:
67
px;
height:
162
px;
}
.index-num {
height: 33px;
...
...
src/modules/store-manage/StoreH5DecorationTab.jsx
View file @
39be164c
...
...
@@ -7,185 +7,164 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
"react"
;
import
{
withRouter
}
from
"react-router-dom"
;
import
_
from
"underscore"
;
import
{
Modal
,
message
,
Button
}
from
"antd"
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
{
sortableContainer
,
sortableElement
,
sortableHandle
,
}
from
"react-sortable-hoc"
;
import
{
MenuOutlined
}
from
"@ant-design/icons"
;
import
arrayMove
from
"array-move"
;
import
User
from
"@/common/js/user"
;
import
SelectPrepareFileModal
from
"@/modules/prepare-lesson/modal/SelectPrepareFileModal"
;
import
"./StoreDecorationPage.less"
;
import
Upload
from
"@/core/upload"
;
import
{
XMTable
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
React
from
'react'
import
{
withRouter
}
from
'react-router-dom'
import
_
from
'underscore'
import
{
Modal
,
message
,
Button
}
from
'antd'
import
StoreService
from
'@/domains/store-domain/storeService'
import
{
sortableContainer
,
sortableElement
,
sortableHandle
}
from
'react-sortable-hoc'
import
{
MenuOutlined
}
from
'@ant-design/icons'
import
arrayMove
from
'array-move'
import
User
from
'@/common/js/user'
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
import
'./StoreDecorationPage.less'
import
Upload
from
'@/core/upload'
import
{
XMTable
}
from
'@/components'
import
college
from
'@/common/lottie/college'
import
ImgClipModal
from
'@/components/ImgClipModal'
const
{
confirm
}
=
Modal
;
const
DragHandle
=
sortableHandle
(()
=>
(
<
MenuOutlined
style=
{
{
cursor
:
"pointer"
,
color
:
"#999"
}
}
className=
"drag-icon"
/>
));
const
SortableItem
=
sortableElement
((
props
)
=>
<
tr
{
...
props
}
/>);
const
SortableContainer
=
sortableContainer
((
props
)
=>
<
tbody
{
...
props
}
/>);
let
cutFlag
=
false
;
const
{
confirm
}
=
Modal
const
DragHandle
=
sortableHandle
(()
=>
<
MenuOutlined
style=
{
{
cursor
:
'pointer'
,
color
:
'#999'
}
}
className=
'drag-icon'
/>)
const
SortableItem
=
sortableElement
((
props
)
=>
<
tr
{
...
props
}
/>)
const
SortableContainer
=
sortableContainer
((
props
)
=>
<
tbody
{
...
props
}
/>)
let
cutFlag
=
false
class
StoreH5Decoration
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
storeDecorationlist
:
[],
query
:
{
storeId
:
User
.
getStoreId
(),
termType
:
"H5_ADMIN"
,
termType
:
'H5_ADMIN'
,
},
showSelectFileModal
:
false
,
diskList
:
[],
photoclip
:
null
,
preview
:
""
,
preview
:
''
,
cutImageBlob
:
null
,
hasImgReady
:
false
,
// 图片是否上传成功
imageFile
:
null
// 需要被截取的图片
}
;
imageFile
:
null
,
// 需要被截取的图片
}
}
timer
=
null
componentDidMount
()
{
this
.
getStoreDecorationList
()
;
this
.
getStoreDecorationList
()
}
getStoreDecorationList
=
()
=>
{
StoreService
.
getStoreDecorationList
(
this
.
state
.
query
).
then
((
res
)
=>
{
const
data
=
_
.
map
(
res
.
result
,
(
item
,
index
)
=>
{
item
.
index
=
index
;
item
.
key
=
index
;
return
item
;
})
;
item
.
index
=
index
item
.
key
=
index
return
item
})
this
.
setState
({
storeDecorationlist
:
data
,
})
;
})
;
}
;
})
})
}
parseColumn
=
()
=>
{
return
[
{
title
:
"Sort"
,
dataIndex
:
"sort"
,
title
:
'Sort'
,
dataIndex
:
'sort'
,
width
:
30
,
className
:
"drag-visible"
,
className
:
'drag-visible'
,
render
:
()
=>
<
DragHandle
/>,
},
{
title
:
"sequence"
,
dataIndex
:
"sequence"
,
key
:
"sequence"
,
className
:
"drag-visible"
,
title
:
'sequence'
,
dataIndex
:
'sequence'
,
key
:
'sequence'
,
className
:
'drag-visible'
,
width
:
20
,
render
:
(
val
,
record
,
index
)
=>
{
return
<
div
className=
"index-num"
>
{
index
+
1
}
</
div
>;
return
<
div
className=
'index-num'
>
{
index
+
1
}
</
div
>
},
},
{
title
:
"banner"
,
dataIndex
:
"bannerPath"
,
key
:
"bannerPath"
,
className
:
"drag-visible"
,
title
:
'banner'
,
dataIndex
:
'bannerPath'
,
key
:
'bannerPath'
,
className
:
'drag-visible'
,
render
:
(
val
)
=>
{
return
<
img
src=
{
val
}
alt=
"banner"
className=
"banner-thumbnail"
/>;
return
<
img
src=
{
val
}
alt=
'banner'
className=
'banner-thumbnail'
/>
},
},
{
title
:
"操作"
,
dataIndex
:
"operation"
,
width
:
"20%"
,
title
:
'操作'
,
dataIndex
:
'operation'
,
width
:
'20%'
,
render
:
(
val
,
record
,
index
)
=>
{
return
(
<
div
className=
"operation"
>
<
span
className=
"edit"
onClick=
{
()
=>
this
.
handleReplaceDecoration
(
record
,
index
)
}
>
<
div
className=
'operation'
>
<
span
className=
'edit'
onClick=
{
()
=>
this
.
handleReplaceDecoration
(
record
,
index
)
}
>
替换
</
span
>
<
span
className=
"divider-line"
>
{
" | "
}
</
span
>
<
span
className=
"delete"
onClick=
{
()
=>
this
.
handleDeleteDecorationConfirm
(
record
)
}
>
<
span
className=
'divider-line'
>
{
' | '
}
</
span
>
<
span
className=
'delete'
onClick=
{
()
=>
this
.
handleDeleteDecorationConfirm
(
record
)
}
>
删除
</
span
>
</
div
>
)
;
)
},
},
]
;
}
;
]
}
handleToAddStoreDecoration
=
()
=>
{
const
{
choosedBannerId
}
=
this
.
state
;
const
{
choosedBannerId
}
=
this
.
state
if
(
this
.
state
.
storeDecorationlist
.
length
>=
5
&&
!
choosedBannerId
)
{
message
.
info
(
"最多可添加5条"
);
return
;
message
.
info
(
'最多可添加5条'
)
return
}
this
.
setState
({
showSelectFileModal
:
true
,
choosedBannerId
:
""
})
;
}
;
choosedBannerId
:
''
,
})
}
handleReplaceDecoration
=
(
record
,
index
)
=>
{
this
.
setState
({
showSelectFileModal
:
true
,
choosedBannerId
:
record
.
id
,
choosedBannerItem
:
record
})
;
}
;
choosedBannerItem
:
record
,
})
}
handleDeleteDecoration
=
(
record
)
=>
{
StoreService
.
deleteStoreDecorationList
({
storeBannerId
:
record
.
id
,
termType
:
"H5_ADMIN"
,
termType
:
'H5_ADMIN'
,
}).
then
((
res
)
=>
{
message
.
success
(
"已删除"
);
this
.
getStoreDecorationList
()
;
})
;
}
;
message
.
success
(
'已删除'
)
this
.
getStoreDecorationList
()
})
}
handleDeleteDecorationConfirm
=
(
record
)
=>
{
return
confirm
({
title
:
"你确定要删除这个banner吗?"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
title
:
'你确定要删除这个banner吗?'
,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
okText
:
'删除'
,
okType
:
'danger'
,
cancelText
:
"取消"
,
cancelText
:
'取消'
,
onOk
:
()
=>
{
this
.
handleDeleteDecoration
(
record
)
;
this
.
handleDeleteDecoration
(
record
)
},
})
;
}
;
})
}
onSortEnd
=
({
oldIndex
,
newIndex
})
=>
{
const
{
storeDecorationlist
}
=
this
.
state
;
const
{
storeDecorationlist
}
=
this
.
state
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMove
(
[].
concat
(
storeDecorationlist
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
);
const
newData
=
arrayMove
([].
concat
(
storeDecorationlist
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
this
.
setState
(
{
storeDecorationlist
:
newData
,
...
...
@@ -193,132 +172,108 @@ class StoreH5Decoration extends React.Component {
storeBannerId
:
storeDecorationlist
[
oldIndex
].
id
,
},
()
=>
{
this
.
moveBannerSequence
()
;
this
.
moveBannerSequence
()
}
)
;
)
}
}
;
}
DraggableBodyRow
=
({
className
,
style
,
...
restProps
})
=>
{
const
{
storeDecorationlist
}
=
this
.
state
;
const
{
storeDecorationlist
}
=
this
.
state
// function findIndex base on Table rowKey props and should always be a right array index
const
index
=
storeDecorationlist
.
findIndex
(
(
x
)
=>
x
.
index
===
restProps
[
"data-row-key"
]
);
return
<
SortableItem
index=
{
index
}
{
...
restProps
}
/>;
};
const
index
=
storeDecorationlist
.
findIndex
((
x
)
=>
x
.
index
===
restProps
[
'data-row-key'
])
return
<
SortableItem
index=
{
index
}
{
...
restProps
}
/>
}
// 选择云盘资源
handleSelectImg
=
(
file
)
=>
{
if
(
file
)
{
if
(
file
)
{
this
.
setState
({
visible
:
true
,
imageFile
:
file
})
;
imageFile
:
file
,
})
}
};
}
//获取resourceId
getSignature
=
(
blob
)
=>
{
Upload
.
uploadBlobToOSS
(
blob
,
"avatar"
+
new
Date
().
valueOf
()).
then
(
(
addBannerPath
)
=>
{
this
.
setState
(
{
Upload
.
uploadBlobToOSS
(
blob
,
'avatar'
+
new
Date
().
valueOf
()).
then
((
addBannerPath
)
=>
{
this
.
setState
(
{
addBannerPath
,
visible
:
false
},
()
=>
{
this
.
state
.
choosedBannerId
?
this
.
editStoreBanner
()
:
this
.
addStoreBanner
();
});
}
);
};
visible
:
false
,
},
()
=>
{
this
.
state
.
choosedBannerId
?
this
.
editStoreBanner
()
:
this
.
addStoreBanner
()
}
)
})
}
editStoreBanner
=
()
=>
{
const
{
addBannerPath
,
choosedBannerId
}
=
this
.
state
;
const
{
addBannerPath
,
choosedBannerId
}
=
this
.
state
const
params
=
{
bannerPath
:
addBannerPath
,
storeBannerId
:
choosedBannerId
,
termType
:
"H5_ADMIN"
,
}
;
termType
:
'H5_ADMIN'
,
}
StoreService
.
editStoreBanner
(
params
).
then
((
res
)
=>
{
message
.
success
(
"设置成功"
);
this
.
getStoreDecorationList
()
;
})
;
}
;
message
.
success
(
'设置成功'
)
this
.
getStoreDecorationList
()
})
}
moveBannerSequence
=
()
=>
{
const
{
newSequence
,
storeBannerId
}
=
this
.
state
;
const
{
newSequence
,
storeBannerId
}
=
this
.
state
const
params
=
{
sequence
:
newSequence
,
storeBannerId
:
storeBannerId
,
termType
:
"H5_ADMIN"
,
}
;
termType
:
'H5_ADMIN'
,
}
StoreService
.
moveBannerSequence
(
params
).
then
((
res
)
=>
{
this
.
getStoreDecorationList
()
;
})
;
}
;
this
.
getStoreDecorationList
()
})
}
addStoreBanner
=
()
=>
{
const
{
addBannerPath
}
=
this
.
state
;
const
{
addBannerPath
}
=
this
.
state
const
params
=
{
bannerPath
:
addBannerPath
,
storeId
:
User
.
getStoreId
(),
termType
:
"H5_ADMIN"
,
}
;
termType
:
'H5_ADMIN'
,
}
StoreService
.
addStoreBanner
(
params
).
then
((
res
)
=>
{
message
.
success
(
"设置成功"
);
this
.
getStoreDecorationList
();
});
};
message
.
success
(
'设置成功'
)
this
.
getStoreDecorationList
()
})
}
render
()
{
const
{
storeDecorationlist
,
showSelectFileModal
,
diskList
,
visible
,
cutImageBlob
,
hasImgReady
,
imageFile
,
}
=
this
.
state
;
const
DraggableContainer
=
(
props
)
=>
(
<
SortableContainer
useDragHandle
helperClass=
"row-dragging"
onSortEnd=
{
this
.
onSortEnd
}
{
...
props
}
/>
);
const
{
storeDecorationlist
,
showSelectFileModal
,
diskList
,
visible
,
cutImageBlob
,
hasImgReady
,
imageFile
}
=
this
.
state
const
DraggableContainer
=
(
props
)
=>
<
SortableContainer
useDragHandle
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onSortEnd
}
{
...
props
}
/>
return
(
<
div
className=
"store-decoration-h5-page"
>
<
div
className=
"box-header"
>
<
div
className=
"banner-setting"
>
<
div
className=
"title"
>
banner设置
</
div
>
<
div
className=
"tip"
>
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸750*252px。
</
div
>
<
div
className=
'store-decoration-h5-page'
>
<
div
className=
'box-header'
>
<
div
className=
'banner-setting'
>
<
div
className=
'title'
>
banner设置
</
div
>
<
div
className=
'tip'
>
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸750*252px。
</
div
>
</
div
>
<
Button
onClick=
{
()
=>
{
this
.
handleToAddStoreDecoration
()
;
this
.
handleToAddStoreDecoration
()
}
}
type=
"primary"
className=
"add-show-btn"
>
type=
'primary'
className=
'add-show-btn'
>
添加Banner
</
Button
>
</
div
>
<
div
className=
"box-body"
>
<
XMTable
<
div
className=
'box-body'
>
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
description
:
'暂无数据'
,
}
}
size=
{
"middle"
}
size=
{
'middle'
}
pagination=
{
false
}
dataSource=
{
storeDecorationlist
}
columns=
{
this
.
parseColumn
()
}
...
...
@@ -333,23 +288,32 @@ class StoreH5Decoration extends React.Component {
/>
</
div
>
<
SelectPrepareFileModal
operateType=
"select"
accept=
"image/jpeg,image/png,image/jpg"
selectTypeList=
{
[
"JPG"
,
"JPEG"
,
"PNG"
]
}
tooltip=
"支持文件类型:jpg、jpeg、png"
operateType=
'select'
accept=
'image/jpeg,image/png,image/jpg'
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectFileModal
}
diskList=
{
diskList
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
;
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectImg
}
/>
{
visible
&&
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
aspectRatio=
'500/172'
cropBoxHeight=
'172'
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
});}
}
/>
}
{
visible
&&
(
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
aspectRatio=
'500/169'
cropBoxHeight=
'169'
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
</
div
>
)
;
)
}
}
export
default
withRouter
(
StoreH5Decoration
)
;
export
default
withRouter
(
StoreH5Decoration
)
src/modules/store-manage/StoreWebDecorationTab.jsx
View file @
39be164c
...
...
@@ -7,184 +7,163 @@
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
React
from
"react"
;
import
{
withRouter
}
from
"react-router-dom"
;
import
_
from
"underscore"
;
import
{
Modal
,
message
,
Button
}
from
"antd"
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
{
sortableContainer
,
sortableElement
,
sortableHandle
,
}
from
"react-sortable-hoc"
;
import
{
MenuOutlined
}
from
"@ant-design/icons"
;
import
arrayMove
from
"array-move"
;
import
User
from
"@/common/js/user"
;
import
SelectPrepareFileModal
from
"@/modules/prepare-lesson/modal/SelectPrepareFileModal"
;
import
"./StoreDecorationPage.less"
;
import
Upload
from
"@/core/upload"
;
import
{
XMTable
}
from
'@/components'
;
import
college
from
'@/common/lottie/college'
;
import
React
from
'react'
import
{
withRouter
}
from
'react-router-dom'
import
_
from
'underscore'
import
{
Modal
,
message
,
Button
}
from
'antd'
import
StoreService
from
'@/domains/store-domain/storeService'
import
{
sortableContainer
,
sortableElement
,
sortableHandle
}
from
'react-sortable-hoc'
import
{
MenuOutlined
}
from
'@ant-design/icons'
import
arrayMove
from
'array-move'
import
User
from
'@/common/js/user'
import
SelectPrepareFileModal
from
'@/modules/prepare-lesson/modal/SelectPrepareFileModal'
import
'./StoreDecorationPage.less'
import
Upload
from
'@/core/upload'
import
{
XMTable
}
from
'@/components'
import
college
from
'@/common/lottie/college'
import
ImgClipModal
from
'@/components/ImgClipModal'
const
{
confirm
}
=
Modal
;
const
DragHandle
=
sortableHandle
(()
=>
(
<
MenuOutlined
style=
{
{
cursor
:
"pointer"
,
color
:
"#999"
}
}
className=
"drag-icon"
/>
));
const
SortableItem
=
sortableElement
((
props
)
=>
<
tr
{
...
props
}
/>);
const
SortableContainer
=
sortableContainer
((
props
)
=>
<
tbody
{
...
props
}
/>);
let
cutFlag
=
false
;
const
{
confirm
}
=
Modal
const
DragHandle
=
sortableHandle
(()
=>
<
MenuOutlined
style=
{
{
cursor
:
'pointer'
,
color
:
'#999'
}
}
className=
'drag-icon'
/>)
const
SortableItem
=
sortableElement
((
props
)
=>
<
tr
{
...
props
}
/>)
const
SortableContainer
=
sortableContainer
((
props
)
=>
<
tbody
{
...
props
}
/>)
let
cutFlag
=
false
class
StoreWebDecoration
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
)
;
super
(
props
)
this
.
state
=
{
storeDecorationlist
:
[],
query
:
{
storeId
:
User
.
getStoreId
(),
termType
:
"WEB_ADMIN"
,
termType
:
'WEB_ADMIN'
,
},
showSelectFileModal
:
false
,
diskList
:
[],
photoclip
:
null
,
preview
:
""
,
preview
:
''
,
cutImageBlob
:
null
,
hasImgReady
:
false
,
// 图片是否上传成功
imageFile
:
null
// 需要被截取的图片
}
;
hasImgReady
:
false
,
// 图片是否上传成功
imageFile
:
null
,
// 需要被截取的图片
}
}
timer
=
null
componentDidMount
()
{
this
.
getStoreDecorationList
()
;
this
.
getStoreDecorationList
()
}
getStoreDecorationList
=
()
=>
{
StoreService
.
getStoreDecorationList
(
this
.
state
.
query
).
then
((
res
)
=>
{
const
data
=
_
.
map
(
res
.
result
,
(
item
,
index
)
=>
{
item
.
index
=
index
;
item
.
key
=
index
;
return
item
;
})
;
item
.
index
=
index
item
.
key
=
index
return
item
})
this
.
setState
({
storeDecorationlist
:
data
,
})
;
})
;
}
;
})
})
}
parseColumn
=
()
=>
{
return
[
{
title
:
"Sort"
,
dataIndex
:
"sort"
,
title
:
'Sort'
,
dataIndex
:
'sort'
,
width
:
30
,
className
:
"drag-visible"
,
className
:
'drag-visible'
,
render
:
()
=>
<
DragHandle
/>,
},
{
title
:
"sequence"
,
dataIndex
:
"sequence"
,
key
:
"sequence"
,
className
:
"drag-visible"
,
title
:
'sequence'
,
dataIndex
:
'sequence'
,
key
:
'sequence'
,
className
:
'drag-visible'
,
width
:
20
,
render
:
(
val
,
record
,
index
)
=>
{
return
<
div
className=
"index-num"
>
{
index
+
1
}
</
div
>;
return
<
div
className=
'index-num'
>
{
index
+
1
}
</
div
>
},
},
{
title
:
"banner"
,
dataIndex
:
"bannerPath"
,
key
:
"bannerPath"
,
className
:
"drag-visible"
,
title
:
'banner'
,
dataIndex
:
'bannerPath'
,
key
:
'bannerPath'
,
className
:
'drag-visible'
,
render
:
(
val
)
=>
{
return
<
img
src=
{
val
}
alt=
"banner"
className=
"web-banner-thumbnail"
/>;
return
<
img
src=
{
val
}
alt=
'banner'
className=
'web-banner-thumbnail'
/>
},
},
{
title
:
"操作"
,
dataIndex
:
"operation"
,
width
:
"20%"
,
title
:
'操作'
,
dataIndex
:
'operation'
,
width
:
'20%'
,
render
:
(
val
,
record
)
=>
{
return
(
<
div
className=
"operation"
>
<
span
className=
"edit"
onClick=
{
()
=>
this
.
handleReplaceDecoration
(
record
)
}
>
<
div
className=
'operation'
>
<
span
className=
'edit'
onClick=
{
()
=>
this
.
handleReplaceDecoration
(
record
)
}
>
替换
</
span
>
<
span
className=
"divider-line"
>
{
" | "
}
</
span
>
<
span
className=
"delete"
onClick=
{
()
=>
this
.
handleDeleteDecorationConfirm
(
record
)
}
>
<
span
className=
'divider-line'
>
{
' | '
}
</
span
>
<
span
className=
'delete'
onClick=
{
()
=>
this
.
handleDeleteDecorationConfirm
(
record
)
}
>
删除
</
span
>
</
div
>
)
;
)
},
},
]
;
}
;
]
}
handleToAddStoreDecoration
=
()
=>
{
const
{
choosedBannerId
}
=
this
.
state
;
const
{
choosedBannerId
}
=
this
.
state
if
(
this
.
state
.
storeDecorationlist
.
length
>=
5
&&
!
choosedBannerId
)
{
message
.
info
(
"最多可添加5条"
);
return
;
message
.
info
(
'最多可添加5条'
)
return
}
this
.
setState
({
showSelectFileModal
:
true
,
choosedBannerId
:
""
})
;
}
;
choosedBannerId
:
''
,
})
}
handleReplaceDecoration
=
(
record
)
=>
{
this
.
setState
({
showSelectFileModal
:
true
,
choosedBannerId
:
record
.
id
,
choosedBannerItem
:
record
})
;
}
;
choosedBannerItem
:
record
,
})
}
handleDeleteDecoration
=
(
record
)
=>
{
StoreService
.
deleteStoreDecorationList
({
storeBannerId
:
record
.
id
,
termType
:
"WEB_ADMIN"
,
termType
:
'WEB_ADMIN'
,
}).
then
((
res
)
=>
{
message
.
success
(
"已删除"
);
this
.
getStoreDecorationList
()
;
})
;
}
;
message
.
success
(
'已删除'
)
this
.
getStoreDecorationList
()
})
}
handleDeleteDecorationConfirm
=
(
record
)
=>
{
return
confirm
({
title
:
"你确定要删除这个banner吗?"
,
icon
:
(
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
),
okText
:
"删除"
,
title
:
'你确定要删除这个banner吗?'
,
icon
:
<
span
className=
'icon iconfont default-confirm-icon'
>

</
span
>,
okText
:
'删除'
,
okType
:
'danger'
,
cancelText
:
"取消"
,
cancelText
:
'取消'
,
onOk
:
()
=>
{
this
.
handleDeleteDecoration
(
record
)
;
this
.
handleDeleteDecoration
(
record
)
},
})
;
}
;
})
}
onSortEnd
=
({
oldIndex
,
newIndex
})
=>
{
const
{
storeDecorationlist
}
=
this
.
state
;
const
{
storeDecorationlist
}
=
this
.
state
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMove
(
[].
concat
(
storeDecorationlist
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
);
const
newData
=
arrayMove
([].
concat
(
storeDecorationlist
),
oldIndex
,
newIndex
).
filter
((
el
)
=>
!!
el
)
this
.
setState
(
{
storeDecorationlist
:
newData
,
...
...
@@ -192,131 +171,107 @@ class StoreWebDecoration extends React.Component {
storeBannerId
:
storeDecorationlist
[
oldIndex
].
id
,
},
()
=>
{
this
.
moveBannerSequence
()
;
this
.
moveBannerSequence
()
}
)
;
)
}
}
;
}
DraggableBodyRow
=
({
className
,
style
,
...
restProps
})
=>
{
const
{
storeDecorationlist
}
=
this
.
state
;
const
{
storeDecorationlist
}
=
this
.
state
// function findIndex base on Table rowKey props and should always be a right array index
const
index
=
storeDecorationlist
.
findIndex
(
(
x
)
=>
x
.
index
===
restProps
[
"data-row-key"
]
);
return
<
SortableItem
index=
{
index
}
{
...
restProps
}
/>;
};
const
index
=
storeDecorationlist
.
findIndex
((
x
)
=>
x
.
index
===
restProps
[
'data-row-key'
])
return
<
SortableItem
index=
{
index
}
{
...
restProps
}
/>
}
// 选择云盘资源
handleSelectImg
=
(
file
)
=>
{
if
(
file
)
{
if
(
file
)
{
this
.
setState
({
visible
:
true
,
imageFile
:
file
})
;
imageFile
:
file
,
})
}
};
}
//获取resourceId
getSignature
=
(
blob
)
=>
{
Upload
.
uploadBlobToOSS
(
blob
,
"avatar"
+
new
Date
().
valueOf
()).
then
(
(
addBannerPath
)
=>
{
this
.
setState
(
{
Upload
.
uploadBlobToOSS
(
blob
,
'avatar'
+
new
Date
().
valueOf
()).
then
((
addBannerPath
)
=>
{
this
.
setState
(
{
addBannerPath
,
visible
:
false
},
()
=>
{
this
.
state
.
choosedBannerId
?
this
.
editStoreBanner
()
:
this
.
addStoreBanner
();
});
}
);
};
visible
:
false
,
},
()
=>
{
this
.
state
.
choosedBannerId
?
this
.
editStoreBanner
()
:
this
.
addStoreBanner
()
}
)
})
}
editStoreBanner
=
()
=>
{
const
{
addBannerPath
,
choosedBannerId
}
=
this
.
state
;
const
{
addBannerPath
,
choosedBannerId
}
=
this
.
state
const
params
=
{
bannerPath
:
addBannerPath
,
storeBannerId
:
choosedBannerId
,
termType
:
"WEB_ADMIN"
,
}
;
termType
:
'WEB_ADMIN'
,
}
StoreService
.
editStoreBanner
(
params
).
then
((
res
)
=>
{
message
.
success
(
"设置成功"
);
this
.
getStoreDecorationList
()
;
})
;
}
;
message
.
success
(
'设置成功'
)
this
.
getStoreDecorationList
()
})
}
moveBannerSequence
=
()
=>
{
const
{
newSequence
,
storeBannerId
}
=
this
.
state
;
const
{
newSequence
,
storeBannerId
}
=
this
.
state
const
params
=
{
sequence
:
newSequence
,
storeBannerId
:
storeBannerId
,
termType
:
"WEB_ADMIN"
,
}
;
termType
:
'WEB_ADMIN'
,
}
StoreService
.
moveBannerSequence
(
params
).
then
((
res
)
=>
{
this
.
getStoreDecorationList
()
;
})
;
}
;
this
.
getStoreDecorationList
()
})
}
addStoreBanner
=
()
=>
{
const
{
addBannerPath
}
=
this
.
state
;
const
{
addBannerPath
}
=
this
.
state
const
params
=
{
bannerPath
:
addBannerPath
,
storeId
:
User
.
getStoreId
(),
termType
:
"WEB_ADMIN"
,
}
;
termType
:
'WEB_ADMIN'
,
}
StoreService
.
addStoreBanner
(
params
).
then
((
res
)
=>
{
message
.
success
(
"设置成功"
);
this
.
getStoreDecorationList
();
});
};
message
.
success
(
'设置成功'
)
this
.
getStoreDecorationList
()
})
}
render
()
{
const
{
storeDecorationlist
,
showSelectFileModal
,
diskList
,
visible
,
cutImageBlob
,
hasImgReady
,
imageFile
}
=
this
.
state
;
const
DraggableContainer
=
(
props
)
=>
(
<
SortableContainer
useDragHandle
helperClass=
"row-dragging"
onSortEnd=
{
this
.
onSortEnd
}
{
...
props
}
/>
);
const
{
storeDecorationlist
,
showSelectFileModal
,
diskList
,
visible
,
cutImageBlob
,
hasImgReady
,
imageFile
}
=
this
.
state
const
DraggableContainer
=
(
props
)
=>
<
SortableContainer
useDragHandle
helperClass=
'row-dragging'
onSortEnd=
{
this
.
onSortEnd
}
{
...
props
}
/>
return
(
<
div
className=
"store-decoration-web-page"
>
<
div
className=
"box-header"
>
<
div
className=
"banner-setting"
>
<
div
className=
"title"
>
banner设置
</
div
>
<
div
className=
"tip"
>
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸1232*212px。
</
div
>
<
div
className=
'store-decoration-web-page'
>
<
div
className=
'box-header'
>
<
div
className=
'banner-setting'
>
<
div
className=
'title'
>
banner设置
</
div
>
<
div
className=
'tip'
>
图片支持bmp、jpeg、jpg、png、gif格式,最大5M,最多可添加5张,拖动可排序。建议尺寸1232*212px。
</
div
>
</
div
>
<
Button
onClick=
{
()
=>
{
this
.
handleToAddStoreDecoration
()
;
this
.
handleToAddStoreDecoration
()
}
}
type=
"primary"
className=
"add-show-btn"
>
type=
'primary'
className=
'add-show-btn'
>
添加Banner
</
Button
>
</
div
>
<
div
className=
"box-body"
>
<
XMTable
<
div
className=
'box-body'
>
<
XMTable
renderEmpty=
{
{
image
:
college
,
description
:
'暂无数据'
description
:
'暂无数据'
,
}
}
size=
{
"middle"
}
size=
{
'middle'
}
pagination=
{
false
}
dataSource=
{
storeDecorationlist
}
columns=
{
this
.
parseColumn
()
}
...
...
@@ -331,23 +286,32 @@ class StoreWebDecoration extends React.Component {
/>
</
div
>
<
SelectPrepareFileModal
operateType=
"select"
accept=
"image/jpeg,image/png,image/jpg"
selectTypeList=
{
[
"JPG"
,
"JPEG"
,
"PNG"
]
}
tooltip=
"支持文件类型:jpg、jpeg、png"
operateType=
'select'
accept=
'image/jpeg,image/png,image/jpg'
selectTypeList=
{
[
'JPG'
,
'JPEG'
,
'PNG'
]
}
tooltip=
'支持文件类型:jpg、jpeg、png'
isOpen=
{
showSelectFileModal
}
diskList=
{
diskList
}
onClose=
{
()
=>
{
this
.
setState
({
showSelectFileModal
:
false
})
;
this
.
setState
({
showSelectFileModal
:
false
})
}
}
onSelect=
{
this
.
handleSelectImg
}
/>
{
visible
&&
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
aspectRatio=
'500/73'
cropBoxHeight=
'73'
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
});}
}
/>
}
{
visible
&&
(
<
ImgClipModal
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
aspectRatio=
'500/134'
cropBoxHeight=
'134'
onConfirm=
{
this
.
getSignature
}
onClose=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
</
div
>
)
;
)
}
}
export
default
withRouter
(
StoreWebDecoration
)
;
export
default
withRouter
(
StoreWebDecoration
)
src/routes/config/mainRoutes.tsx
View file @
39be164c
...
...
@@ -5,37 +5,37 @@
* @LastEditTime: 2021-05-19 19:44:08
* @Description: 内容线路由配置
*/
import
Home
from
'@/modules/home/Home'
;
import
EmployeesManagePage
from
'@/modules/store-manage/EmployeesManagePage'
;
import
EmployeeManage
from
'@/modules/college-manage/EmployeeManage'
;
import
personalInfoPage
from
'@/modules/personalInfo'
;
import
UserManagePage
from
'@/modules/store-manage/UserManagePage'
;
import
UserManage
from
'@/modules/college-manage/UserManagePage'
;
import
StoreDecorationPage
from
'@/modules/store-manage/StoreDecorationPage'
;
import
CourseCatalogPage
from
'@/modules/store-manage/CourseCatalogPage'
;
import
LiveCoursePage
from
'@/modules/course-manage/LiveCoursePage'
;
import
AddLivePage
from
'@/modules/course-manage/AddLive'
;
import
VideoCoursePage
from
'@/modules/course-manage/video-course'
;
import
GraphicsCoursePage
from
'@/modules/course-manage/graphics-course'
;
import
OfflineCoursePage
from
'@/modules/course-manage/offline-course'
;
import
AddVideoCoursePage
from
'@/modules/course-manage/video-course/AddVideoCourse'
;
import
AddGraphicsCoursePage
from
'@/modules/course-manage/graphics-course/AddGraphicsCourse'
;
import
AddOfflineCoursePage
from
'@/modules/course-manage/offline-course/AddOfflineCourse'
;
import
Home
from
'@/modules/home/Home'
import
EmployeesManagePage
from
'@/modules/store-manage/EmployeesManagePage'
import
EmployeeManage
from
'@/modules/college-manage/EmployeeManage'
import
personalInfoPage
from
'@/modules/personalInfo'
import
UserManagePage
from
'@/modules/store-manage/UserManagePage'
import
UserManage
from
'@/modules/college-manage/UserManagePage'
import
StoreDecorationPage
from
'@/modules/store-manage/StoreDecorationPage'
import
CourseCatalogPage
from
'@/modules/store-manage/CourseCatalogPage'
import
LiveCoursePage
from
'@/modules/course-manage/LiveCoursePage'
import
AddLivePage
from
'@/modules/course-manage/AddLive'
import
VideoCoursePage
from
'@/modules/course-manage/video-course'
import
GraphicsCoursePage
from
'@/modules/course-manage/graphics-course'
import
OfflineCoursePage
from
'@/modules/course-manage/offline-course'
import
AddVideoCoursePage
from
'@/modules/course-manage/video-course/AddVideoCourse'
import
AddGraphicsCoursePage
from
'@/modules/course-manage/graphics-course/AddGraphicsCourse'
import
AddOfflineCoursePage
from
'@/modules/course-manage/offline-course/AddOfflineCourse'
// import DataList from '@/modules/course-manage/DataList/DataList';
// import ClassBook from '@/modules/resource-disk';
import
ResourceDisk
from
'@/modules/resource-disk'
;
import
SwitchRoute
from
'@/modules/root/SwitchRoute'
;
import
PlanPage
from
'@/modules/plan-manage/PlanPage'
;
import
AddPlanPage
from
'@/modules/plan-manage/AddPlan'
;
import
LearningDataPage
from
'@/modules/plan-manage/LearningData'
;
import
StoreInfoPage
from
'@/modules/store-manage/StoreInfo'
;
import
CourseCategoryManage
from
'@/modules/teach-tool/components/CourseCategoryManage'
;
import
QuestionManageIndex
from
'@/modules/teach-tool/question-manage/Index'
;
import
PaperManageIndex
from
'@/modules/teach-tool/paper-manage/Index'
;
import
ExaminationManagerIndex
from
'@/modules/teach-tool/examination-manager/Index'
;
import
ExaminationManagerTestDetail
from
'@/modules/teach-tool/examination-manager/TestDetailPage'
;
import
KnowledgeBase
from
'@/modules/knowledge-base/index'
;
import
CollegeInfoPage
from
'@/modules/college-manage/CollegeInfoPage'
;
import
ResourceDisk
from
'@/modules/resource-disk'
import
SwitchRoute
from
'@/modules/root/SwitchRoute'
import
PlanPage
from
'@/modules/plan-manage/PlanPage'
import
AddPlanPage
from
'@/modules/plan-manage/AddPlan'
import
LearningDataPage
from
'@/modules/plan-manage/LearningData'
import
StoreInfoPage
from
'@/modules/store-manage/StoreInfo'
import
CourseCategoryManage
from
'@/modules/teach-tool/components/CourseCategoryManage'
import
QuestionManageIndex
from
'@/modules/teach-tool/question-manage/Index'
import
PaperManageIndex
from
'@/modules/teach-tool/paper-manage/Index'
import
ExaminationManagerIndex
from
'@/modules/teach-tool/examination-manager/Index'
import
ExaminationManagerTestDetail
from
'@/modules/teach-tool/examination-manager/TestDetailPage'
import
KnowledgeBase
from
'@/modules/knowledge-base/index'
import
CollegeInfoPage
from
'@/modules/college-manage/CollegeInfoPage'
const
mainRoutes
=
[
{
...
...
@@ -91,7 +91,7 @@ const mainRoutes = [
{
path
:
'/offline-course'
,
component
:
OfflineCoursePage
,
name
:
'线下
课
'
,
name
:
'线下
活动
'
,
},
{
path
:
'/create-live-course'
,
...
...
@@ -117,12 +117,12 @@ const mainRoutes = [
{
path
:
'/create-offline-course'
,
component
:
AddOfflineCoursePage
,
name
:
'创建线下
课
'
,
name
:
'创建线下
活动
'
,
},
{
path
:
'/resource-disk'
,
component
:
ResourceDisk
,
name
:
'
资料云盘
'
,
name
:
'
素材库
'
,
},
{
path
:
'/question-manage-index'
,
...
...
@@ -180,6 +180,6 @@ const mainRoutes = [
component
:
LearningDataPage
,
name
:
'学习数据'
,
},
]
;
]
export
default
mainRoutes
;
export
default
mainRoutes
src/routes/config/menuList.tsx
View file @
39be164c
...
...
@@ -28,8 +28,8 @@ export const menuList: any = [
link
:
'/live-course'
,
},
{
groupName
:
"线上课"
,
groupCode
:
"CourseVideoClass"
,
groupName
:
'线上课'
,
groupCode
:
'CourseVideoClass'
,
link
:
'/video-course'
,
},
{
...
...
@@ -38,7 +38,7 @@ export const menuList: any = [
link
:
'/graphics-course'
,
},
{
groupName
:
'线下
课
'
,
groupName
:
'线下
活动
'
,
groupCode
:
'OfflineClass'
,
link
:
'/offline-course'
,
},
...
...
@@ -91,7 +91,7 @@ export const menuList: any = [
selectImg
:
'https://image.xiaomaiketang.com/xm/hJKCfibC22.png'
,
},
{
groupName
:
'
资料云盘
'
,
groupName
:
'
素材库
'
,
groupCode
:
'CloudDisk'
,
icon
:
''
,
link
:
'/resource-disk'
,
...
...
@@ -151,4 +151,4 @@ export const menuList: any = [
},
],
},
]
;
]
src/routes/config/redirectRoutes.tsx
View file @
39be164c
import
LiveCoursePage
from
"@/modules/course-manage/LiveCoursePage"
;
import
ResourceDisk
from
"@/modules/resource-disk"
;
import
LiveCoursePage
from
'@/modules/course-manage/LiveCoursePage'
import
ResourceDisk
from
'@/modules/resource-disk'
const
redirectRoutes
=
[
{
path
:
"/redirect-to-live-course"
,
path
:
'/redirect-to-live-course'
,
component
:
LiveCoursePage
,
name
:
"课程管理"
,
name
:
'课程管理'
,
},
{
path
:
"/redirect-to-resource-disk"
,
path
:
'/redirect-to-resource-disk'
,
component
:
ResourceDisk
,
name
:
"资料云盘"
,
name
:
'素材库'
,
},
]
;
]
export
default
redirectRoutes
;
export
default
redirectRoutes
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