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
df1c6376
Commit
df1c6376
authored
Jul 23, 2021
by
guomingpang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:线下课新建分类
parent
6a729fcf
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
169 additions
and
48 deletions
+169
-48
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
+169
-48
No files found.
src/modules/course-manage/offline-course/AddOfflineCourse.jsx
View file @
df1c6376
...
...
@@ -2,17 +2,19 @@
* @Author: 吴文洁
* @Date: 2020-08-05 10:07:47
* @LastEditors: yuananting
* @LastEditTime: 2021-07-
22 18:33:14
* @LastEditTime: 2021-07-
15 12:04:00
* @Description: 线下课新增/编辑页
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import
React
from
'react'
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
Select
,
Switch
,
TimePicker
,
InputNumber
,
Tooltip
}
from
'antd'
import
{
Button
,
Input
,
Radio
,
message
,
Modal
,
TreeSelect
,
Select
,
Switch
,
TimePicker
,
InputNumber
,
Tooltip
}
from
'antd'
import
$
from
'jquery'
import
{
CourseCatalogSelect
,
RangePicker
}
from
'@/modules/common/'
import
RangePicker
from
'@/modules/common/DateRangePicker'
import
ShowTips
from
'@/components/ShowTips'
import
Breadcrumbs
from
'@/components/Breadcrumbs'
import
SelectStudent
from
'../modal/select-student'
import
SelectPrepareFileModal
from
'../../prepare-lesson/modal/SelectPrepareFileModal'
import
PreviewOfflineModal
from
'./modal/PreviewOfflineModal'
import
StoreService
from
'@/domains/store-domain/storeService'
...
...
@@ -24,12 +26,12 @@ 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'
let
cutFlag
=
false
const
unitList
=
[
{
key
:
'HOUR'
,
value
:
'小时'
},
{
key
:
'MINUTE'
,
value
:
'分钟'
},
...
...
@@ -39,8 +41,8 @@ class AddOfflineCourse extends React.Component {
constructor
(
props
)
{
super
(
props
)
const
courseId
=
window
.
getParameterByName
(
'id'
)
const
pageType
=
window
.
getParameterByName
(
'type'
)
const
courseId
=
getParameterByName
(
'id'
)
const
pageType
=
getParameterByName
(
'type'
)
this
.
state
=
{
courseId
,
// 线下课ID,编辑的时候从URL上带过来
...
...
@@ -156,6 +158,7 @@ class AddOfflineCourse extends React.Component {
const
{
result
=
{}
}
=
res
||
{}
const
{
courseName
,
courseState
,
categoryId
,
offlinePlace
,
whetherVisitorsJoin
,
...
...
@@ -338,10 +341,79 @@ class AddOfflineCourse extends React.Component {
}
handleSelectCover
=
(
file
)
=>
{
this
.
setState
({
this
.
uploadCoverImage
(
file
)
}
//上传图片
uploadCoverImage
=
(
imageFile
)
=>
{
const
{
folderName
}
=
imageFile
const
fileName
=
window
.
random_string
(
16
)
+
folderName
.
slice
(
folderName
.
lastIndexOf
(
'.'
))
const
self
=
this
this
.
setState
(
{
visible
:
true
,
imageFile
:
file
,
},
()
=>
{
setTimeout
(()
=>
{
const
okBtnDom
=
document
.
querySelector
(
'#headPicModal'
)
const
options
=
{
size
:
[
500
,
282
],
ok
:
okBtnDom
,
maxZoom
:
3
,
style
:
{
jpgFillColor
:
'transparent'
,
},
done
:
function
(
dataUrl
)
{
clearTimeout
(
self
.
timer
)
self
.
timer
=
setTimeout
(()
=>
{
if
(
self
.
state
.
rotate
!=
this
.
rotate
()
||
self
.
state
.
scale
!=
this
.
scale
())
{
const
_dataUrl
=
this
.
clip
()
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
_dataUrl
)
self
.
setState
({
cutImageBlob
,
dataUrl
:
_dataUrl
,
rotate
:
this
.
rotate
(),
scale
:
this
.
scale
(),
})
}
},
500
)
const
cutImageBlob
=
self
.
convertBase64UrlToBlob
(
dataUrl
)
self
.
setState
({
cutImageBlob
,
dataUrl
,
})
setTimeout
(()
=>
{
cutFlag
=
false
},
2000
)
},
fail
:
(
failInfo
)
=>
{
message
.
error
(
'图片上传失败了,请重新上传'
)
},
loadComplete
:
function
(
img
)
{
setTimeout
(()
=>
{
const
_dataUrl
=
this
.
clip
()
self
.
setState
({
dataUrl
:
_dataUrl
,
hasImgReady
:
true
,
})
},
100
)
},
}
const
imgUrl
=
`
${
imageFile
.
ossUrl
}
?
${
new
Date
().
getTime
()}
`
if
(
!
this
.
state
.
photoclip
)
{
const
_photoclip
=
new
PhotoClip
(
'#headPicModal'
,
options
)
_photoclip
.
load
(
imgUrl
)
this
.
setState
({
photoclip
:
_photoclip
,
})
}
else
{
this
.
state
.
photoclip
.
clear
()
this
.
state
.
photoclip
.
load
(
imgUrl
)
}
},
200
)
}
)
}
//获取resourceId
...
...
@@ -367,6 +439,17 @@ class AddOfflineCourse extends React.Component {
})
}
// base64转换成blob
convertBase64UrlToBlob
=
(
urlData
)
=>
{
const
bytes
=
window
.
atob
(
urlData
.
split
(
','
)[
1
])
const
ab
=
new
ArrayBuffer
(
bytes
.
length
)
const
ia
=
new
Uint8Array
(
ab
)
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
ia
[
i
]
=
bytes
.
charCodeAt
(
i
)
}
return
new
Blob
([
ab
],
{
type
:
'image/png'
})
}
preSubmit
=
()
=>
{
//过期判断
if
(
User
.
getExpirationTime
()
&&
moment
().
valueOf
()
>
Number
(
User
.
getExpirationTime
()))
{
...
...
@@ -615,7 +698,7 @@ class AddOfflineCourse extends React.Component {
}
StoreService
.
getStoreUserBasicPage
(
_query
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
const
{
records
=
[],
hasNext
}
=
result
const
{
records
=
[],
total
=
0
,
hasNext
}
=
result
const
list
=
current
>
1
?
teacherList
.
concat
(
records
)
:
records
this
.
setState
({
hasNext
,
...
...
@@ -625,7 +708,11 @@ class AddOfflineCourse extends React.Component {
})
}
changeIntro
=
(
value
)
=>
{
changeIntro
=
(
value
,
textLength
)
=>
{
// const isMore = textLength > 1000;
// if (isMore) {
// message.warning('内容过长,不能超过1000字');
// }
this
.
setState
({
introduce
:
value
})
}
...
...
@@ -649,11 +736,6 @@ class AddOfflineCourse extends React.Component {
}
whetherVisitorsJoinChange
=
()
=>
{
const
{
whetherSetApply
,
whetherVisitorsJoin
}
=
this
.
state
if
(
whetherSetApply
==
'NO'
)
{
message
.
warning
(
'关闭报名无法获取手机号!'
)
return
}
if
(
this
.
state
.
whetherVisitorsJoin
===
'NO'
)
{
this
.
setState
({
whetherVisitorsJoin
:
'YES'
})
}
else
{
...
...
@@ -673,11 +755,14 @@ class AddOfflineCourse extends React.Component {
coverUrl
,
introduce
,
categoryId
,
categoryList
,
courseCatalogList
,
whetherVisitorsJoin
,
loadintroduce
,
showSelectCoverModal
,
visible
,
hasImgReady
,
cutImageBlob
,
teacherId
,
teacherList
,
calendarTime
,
...
...
@@ -701,7 +786,6 @@ class AddOfflineCourse extends React.Component {
quota
,
offlinePlace
,
isEditDisablie
,
imageFile
,
}
=
this
.
state
const
isDefaultCover
=
coverUrl
===
defaultCoverUrl
return
(
...
...
@@ -758,12 +842,7 @@ class AddOfflineCourse extends React.Component {
<
span
className=
'label special'
>
<
span
className=
'require'
>
*
</
span
>
课程分类:
</
span
>
<
CourseCatalogSelect
courseCatalogList=
{
courseCatalogList
}
value=
{
categoryId
}
onChange=
{
(
value
,
label
)
=>
this
.
handleChangeCatalogList
(
value
,
label
)
}
/>
{
/* <TreeSelect
<
TreeSelect
showSearch
treeNodeFilterProp=
'title'
style=
{
{
width
:
240
}
}
...
...
@@ -774,9 +853,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'
>
...
...
@@ -844,7 +923,7 @@ class AddOfflineCourse extends React.Component {
)
}
}
getPopupContainer=
{
()
=>
document
.
getElementById
(
'teacher'
)
}
>
{
_
.
map
(
teacherList
,
(
item
)
=>
{
{
_
.
map
(
teacherList
,
(
item
,
index
)
=>
{
return
(
<
Option
value=
{
item
.
id
}
key=
{
item
.
id
}
>
{
item
.
nickName
}
...
...
@@ -853,6 +932,13 @@ class AddOfflineCourse extends React.Component {
})
}
</
Select
>
</
div
>
<
div
className=
'allow-tourist-join'
>
<
span
className=
'label'
>
观看设置:
</
span
>
<
div
className=
'content'
>
<
Switch
checked=
{
whetherVisitorsJoin
===
'NO'
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
<
div
className=
'desc'
>
{
whetherVisitorsJoin
===
'NO'
?
'已开启,学员需绑定手机号才可观看'
:
'已关闭,学员无需绑定手机号即可观看'
}
</
div
>
</
div
>
</
div
>
<
div
className=
'introduce'
>
<
span
className=
'label'
>
课程简介:
</
span
>
<
div
className=
'content'
>
...
...
@@ -885,7 +971,7 @@ class AddOfflineCourse extends React.Component {
</
span
>
<
div
>
<
div
className=
'select-day'
>
已选
<
span
className=
'mark-day'
>
{
window
.
isLongArr
(
calendarTime
)
?
calendarTime
.
length
:
0
}
</
span
>
天
已选
<
span
className=
'mark-day'
>
{
isLongArr
(
calendarTime
)
?
calendarTime
.
length
:
0
}
</
span
>
天
</
div
>
<
MultipleDatePicker
disabled=
{
isEditDisablie
}
selectDateList=
{
calendarTime
}
onSelect=
{
this
.
selectMultiDate
}
canSelectTodayBefore=
{
false
}
/>
</
div
>
...
...
@@ -956,8 +1042,7 @@ class AddOfflineCourse extends React.Component {
startTimeApply
:
undefined
,
endTimeApply
:
undefined
,
quota
:
null
,
whetherVisitorsJoin
:
value
?
whetherVisitorsJoin
:
'YES'
});
})
}
}
/>
<
span
className=
'switch-tip'
>
开启后可设置课程报名时间,获取报名数据
</
span
>
...
...
@@ -974,8 +1059,8 @@ class AddOfflineCourse extends React.Component {
onChange=
{
(
dates
)
=>
{
this
.
handleChangeDates
(
dates
)
}
}
renderExtraFooter=
{
()
=>
(
<
If
condition=
{
calendarTime
[
0
]
}
>
renderExtraFooter=
{
()
=>
calendarTime
[
0
]
?
(
<
div
style=
{
{
position
:
'absolute'
,
bottom
:
8
,
cursor
:
'pointer'
}
}
>
<
span
onClick=
{
()
=>
...
...
@@ -1035,8 +1120,8 @@ class AddOfflineCourse extends React.Component {
上课前3天
</
span
>
</
div
>
</
If
>
)
}
)
:
null
}
/>
</
div
>
)
}
...
...
@@ -1068,15 +1153,6 @@ class AddOfflineCourse extends React.Component {
)
}
</
div
>
</
div
>
<
div
className=
'allow-tourist-join'
>
<
span
className=
'label'
>
观看设置:
</
span
>
<
div
className=
'content'
>
<
Switch
checked=
{
whetherVisitorsJoin
===
'NO'
?
true
:
false
}
onChange=
{
this
.
whetherVisitorsJoinChange
}
/>
<
div
className=
'desc'
>
{
whetherVisitorsJoin
===
'NO'
?
'已开启,仅限绑定了手机号的学员报名线下课'
:
'已关闭,允许未绑定手机号的学员报名线下课'
}
</
div
>
</
div
>
</
div
>
<
div
className=
'course-catalog'
>
<
span
className=
'label'
>
考勤签到:
</
span
>
<
div
className=
'switch-box'
>
...
...
@@ -1277,16 +1353,61 @@ class AddOfflineCourse extends React.Component {
onSelect=
{
this
.
handleSelectCover
}
/>
)
}
{
visible
&&
(
<
ImgClipModal
<
Modal
title=
'设置图片'
width=
{
1080
}
visible=
{
visible
}
imgUrl=
{
imageFile
.
ossUrl
}
onConfirm=
{
this
.
getSignature
}
onClose
=
{
()
=>
{
maskClosable=
{
false
}
closeIcon=
{
<
span
className=
'icon iconfont modal-close-icon'
>

</
span
>
}
onCancel
=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
/>
)
}
zIndex=
{
10001
}
footer=
{
[
<
Button
key=
'back'
onClick=
{
()
=>
{
this
.
setState
({
visible
:
false
})
}
}
>
重新上传
</
Button
>,
<
Button
key=
'submit'
type=
'primary'
disabled=
{
!
hasImgReady
}
onClick=
{
()
=>
{
if
(
!
cutFlag
)
{
cutFlag
=
true
this
.
refs
.
hiddenBtn
.
click
()
}
this
.
getSignature
(
cutImageBlob
)
}
}
>
确定
</
Button
>,
]
}
>
<
div
className=
'clip-box'
>
<
div
id=
'headPicModal'
ref=
'headPicModal'
style=
{
{
width
:
'500px'
,
height
:
'430px'
,
marginBottom
:
0
,
}
}
></
div
>
<
div
id=
'clipBtn'
style=
{
{
display
:
'none'
}
}
ref=
'hiddenBtn'
></
div
>
<
div
className=
'preview-img'
>
<
div
className=
'title'
>
效果预览
</
div
>
<
div
id=
'preview-url-box'
style=
{
{
width
:
500
,
height
:
282
}
}
>
<
img
src=
{
this
.
state
.
dataUrl
}
style=
{
{
width
:
'100%'
}
}
alt=
''
/>
</
div
>
<
div
className=
'tip-box'
>
<
div
className=
'tip'
>
温馨提示
</
div
>
<
div
className=
'tip'
>
①预览效果图时可能存在延迟,单击左侧图片刷新即可
</
div
>
<
div
className=
'tip'
>
②设置图片时双击可旋转图片,滚动可放大或缩小图片
</
div
>
</
div
>
</
div
>
</
div
>
</
Modal
>
{
this
.
state
.
previewOfflineModal
}
</
div
>
)
...
...
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