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
3bcbb935
Commit
3bcbb935
authored
Dec 14, 2020
by
zhangleyuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:调整创建直播课页面
parent
bbd20dcd
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
930 additions
and
97 deletions
+930
-97
src/components/ImgCutModalNew.jsx
+1
-1
src/modules/course-manage/AddLive.jsx
+75
-89
src/modules/course-manage/components/AddLiveBasic.jsx
+21
-5
src/modules/course-manage/components/AddLiveBasic.less
+1
-1
src/modules/course-manage/components/AddLiveIntro.jsx
+1
-1
src/modules/course-manage/modal/SelectPrepareFileModal.jsx
+720
-0
src/modules/course-manage/modal/SelectPrepareFileModal.less
+111
-0
No files found.
src/components/ImgCutModalNew.jsx
View file @
3bcbb935
...
...
@@ -184,7 +184,7 @@ ImgCutModalNew.propTypes = {
width
:
PropTypes
.
number
,
cutWidth
:
PropTypes
.
number
,
cutHeight
:
PropTypes
.
number
,
// imageFile: PropTypes.File
imageFile
:
PropTypes
.
object
};
ImgCutModalNew
.
defaultProps
=
{
width
:
550
,
...
...
src/modules/course-manage/AddLive.jsx
View file @
3bcbb935
...
...
@@ -10,7 +10,6 @@ import React from 'react';
import
{
withRouter
}
from
"react-router-dom"
;
import
{
Button
,
message
,
Modal
}
from
'antd'
;
import
Bus
from
'@/core/bus'
;
import
ShowTips
from
"@/components/ShowTips"
;
import
Breadcrumbs
from
"@/components/Breadcrumbs"
;
...
...
@@ -19,16 +18,20 @@ import AddLiveClass from './components/AddLiveClass';
import
AddLiveIntro
from
'./components/AddLiveIntro'
;
import
PreviewCourseModal
from
'./modal/PreviewCourseModal'
;
import
LackConsumeStudentModal
from
'./modal/LackConsumeStudentModal'
;
import
StoreService
from
"@/domains/store-domain/storeService"
;
import
moment
from
'moment'
;
import
'./AddLive.less'
;
const
defaultCover
=
'https://image.xiaomaiketang.com/xm/YNfi45JwFA.png'
;
// const editBoxKey = window.random_string(16);
const
defaultBasicInfo
=
{
courseName
:
null
,
// 课程名称
coverId
:
null
,
coverUrl
:
defaultCover
coverUrl
:
defaultCover
,
parentCatalogId
:
''
,
parentCatalogName
:
''
,
sonCatalogId
:
''
,
sonCatalogName
:
''
};
const
defaultClassInfo
=
{
...
...
@@ -80,23 +83,25 @@ class AddLive extends React.Component {
courseName
:
null
,
// 课程名称
coverId
:
null
,
coverUrl
:
defaultCover
,
parentCatalogId
:
''
,
sonCatalogId
:
''
,
courseCatalogOption
:[
{
value
:
'
zhejiang
'
,
value
:
'
1
'
,
label
:
'Zhejiang'
,
children
:
[
{
value
:
'
hangzhou
'
,
value
:
'
2
'
,
label
:
'Hangzhou'
,
},
],
},
{
value
:
'
jiangsu
'
,
value
:
'
3
'
,
label
:
'Jiangsu'
,
children
:
[
{
value
:
'
nanjing
'
,
value
:
'
4
'
,
label
:
'Nanjing'
,
}
],
...
...
@@ -144,7 +149,7 @@ class AddLive extends React.Component {
if
(
type
===
'edit'
)
{
this
.
getCourseDetail
();
}
else
{
this
.
getLivePermission
();
}
}
...
...
@@ -248,25 +253,39 @@ class AddLive extends React.Component {
// });
// })
}
getLivePermission
=
()
=>
{
// axios.Apollo("public/businessLive/queryLiveAccount").then((res) => {
// const { addParam } = this.state;
// let list = res.result || [];
// const isXiaomai = _.some(list, (item) => item.channel === "XIAOMAI");
// this.setState({ isXiaomai });
// });
getCourseCatalogList
=
()
=>
{
StoreService
.
getCourseCatalogList
({
current
:
1
,
size
:
1000
}).
then
((
res
)
=>
{
// let resultData = this.handleCatalogListData(res.result.records)
// setCourseCatalogList(resultData);
// setTotal(res.result.total);
});
}
handleCatalogListData
=
(
listData
)
=>
{
// listData.map((item:any,index:any) => {
// item.type = "parent"
// item.key = item.id;
// if(item.sonCategoryList){
// item.sonCategoryList.map((_item:any,_index:any) =>{
// _item.type = "child";
// _item.key=_item.id
// return _item
// });
// }
// return item
// })
// return listData
}
// 修改基本信息
handleChangeBasicInfo
=
(
field
,
value
,
_coverUrl
)
=>
{
const
{
coverUrl
}
=
this
.
state
.
addLiveBasicInfo
;
console
.
log
(
field
,
value
);
this
.
setState
({
addLiveBasicInfo
:
{
...
this
.
state
.
addLiveBasicInfo
,
[
field
]:
value
,
coverUrl
:
_coverUrl
?
_coverUrl
:
coverUrl
,
}
})
}
,()
=>
{
console
.
log
(
this
.
state
.
addLiveBasicInfo
)}
)
}
// 修改上课信息
...
...
@@ -484,90 +503,57 @@ class AddLive extends React.Component {
return
new
Promise
((
resolve
)
=>
{
const
{
type
}
=
this
.
state
;
// 校验基本信息(直播课名称)
const
{
courseName
}
=
addLiveBasicInfo
;
console
.
log
(
"addLiveBasicInfo"
,
addLiveBasicInfo
);
const
{
courseName
,
parentCatalogId
}
=
addLiveBasicInfo
;
const
{
liveDate
,
timeHorizonStart
,
timeHorizonEnd
,
studentList
,
teacherId
,
calendarTime
,
consumeStudentList
,
consumeHourNum
,
consumeClassTime
,
applyMode
liveDate
,
timeHorizonStart
,
timeHorizonEnd
,
teacherId
,
calendarTime
,
consumeStudentList
,
consumeHourNum
,
consumeClassTime
,
applyMode
}
=
addLiveClassInfo
;
const
{
liveCourseMediaRequests
}
=
addLiveIntroInfo
;
const
currentTime
=
+
new
Date
();
if
(
!
courseName
)
{
message
.
warning
(
'
直播名称不能为空
'
);
message
.
warning
(
'
请输入课程名称
'
);
resolve
(
false
);
return
;
}
if
(
window
.
NewVersion
&&
type
===
'add'
)
{
// 5.0新建 校验 批量排课
const
{
startTime
,
endTime
}
=
addLiveClassInfo
;
if
(
calendarTime
.
length
&&
calendarTime
.
length
===
0
)
{
message
.
warning
(
'请选择上课日期'
);
resolve
(
false
);
return
;
}
else
if
(
startTime
===
endTime
)
{
message
.
warning
(
'结束时间必须晚于开始时间'
);
resolve
(
false
);
return
;
}
// 若有今日排课 校验当前时间
const
currentDay
=
moment
(
currentTime
).
format
(
'YYYY-MM-DD'
);
const
itemToday
=
_
.
find
(
calendarTime
,
(
item
)
=>
{
const
itemDay
=
moment
(
item
).
format
(
'YYYY-MM-DD'
);
return
itemDay
===
currentDay
;
})
if
(
itemToday
)
{
const
itemDay
=
moment
(
itemToday
).
format
(
'YYYY-MM-DD'
);
const
itemHour
=
moment
(
startTime
).
format
(
'HH:mm'
);
if
(
itemDay
===
currentDay
)
{
if
(
moment
(
itemDay
+
' '
+
itemHour
).
format
(
'x'
)
<
currentTime
)
{
message
.
warning
(
'开始时间不能早于现在'
);
resolve
(
false
);
return
;
}
if
(
!
parentCatalogId
){
message
.
warning
(
'请选择课程分类'
);
resolve
(
false
);
return
;
}
const
{
startTime
,
endTime
}
=
addLiveClassInfo
;
if
(
calendarTime
.
length
===
0
)
{
message
.
warning
(
'请选择上课日期'
);
resolve
(
false
);
return
;
}
else
if
(
startTime
===
endTime
)
{
message
.
warning
(
'结束时间必须晚于开始时间'
);
resolve
(
false
);
return
;
}
// 若有今日排课 校验当前时间
const
currentDay
=
moment
(
currentTime
).
format
(
'YYYY-MM-DD'
);
const
itemToday
=
_
.
find
(
calendarTime
,
(
item
)
=>
{
const
itemDay
=
moment
(
item
).
format
(
'YYYY-MM-DD'
);
return
itemDay
===
currentDay
;
})
if
(
itemToday
)
{
const
itemDay
=
moment
(
itemToday
).
format
(
'YYYY-MM-DD'
);
const
itemHour
=
moment
(
startTime
).
format
(
'HH:mm'
);
if
(
itemDay
===
currentDay
)
{
if
(
moment
(
itemDay
+
' '
+
itemHour
).
format
(
'x'
)
<
currentTime
)
{
message
.
warning
(
'开始时间不能早于现在'
);
resolve
(
false
);
return
;
}
}
if
(
consumeClassTime
>
(
endTime
-
startTime
)
/
60000
)
{
message
.
warning
(
'到课规则时长不能超过排课时长'
);
resolve
(
false
);
return
;
}
}
else
{
const
_liveDate
=
moment
(
liveDate
).
format
(
"YYYY-MM-DD"
);
const
_timeHorizonStart
=
moment
(
timeHorizonStart
).
format
(
'HH:mm'
);
const
_timeHorizonEnd
=
moment
(
timeHorizonEnd
).
format
(
'HH:mm'
);
const
startTime
=
moment
(
_liveDate
+
' '
+
_timeHorizonStart
).
format
(
'x'
);
const
endTime
=
moment
(
_liveDate
+
' '
+
_timeHorizonEnd
).
format
(
'x'
);
if
(
!
startTime
||
!
endTime
)
{
message
.
warning
(
'日期不能为空'
);
resolve
(
false
);
return
;
}
else
if
(
!
timeHorizonStart
)
{
message
.
warning
(
'开始时间不能为空'
);
resolve
(
false
);
return
;
}
else
if
(
!
timeHorizonEnd
)
{
message
.
warning
(
'结束时间不能为空'
);
resolve
(
false
);
return
;
}
else
if
(
isEdit
&&
startTime
<
currentTime
)
{
message
.
warning
(
'开始时间不能早于当前时间'
);
resolve
(
false
);
return
;
}
else
if
(
isEdit
&&
endTime
<
currentTime
)
{
message
.
warning
(
'结束时间不能早于当前时间'
);
resolve
(
false
);
return
;
}
else
if
(
isEdit
&&
endTime
<=
startTime
)
{
message
.
warning
(
"结束时间不能早于开始时间"
);
resolve
(
false
);
return
;
}
else
if
(
isEdit
&&
consumeClassTime
>
(
endTime
-
startTime
)
/
60000
)
{
message
.
warning
(
"到课规则时长不能超过排课时长"
);
resolve
(
false
);
return
;
}
}
// if(consumeClassTime > (endTime - startTime) / 60000) {
// message.warning('到课规则时长不能超过排课时长');
// resolve(false);
// return;
// }
if
(
!
teacherId
)
{
message
.
warning
(
'上课老师不能为空'
);
resolve
(
false
);
...
...
src/modules/course-manage/components/AddLiveBasic.jsx
View file @
3bcbb935
...
...
@@ -26,6 +26,10 @@ class AddLiveBasic extends React.Component {
showCutModal
:
false
}
}
componentWillUnmount
()
{
const
{
xhr
}
=
this
.
state
;
xhr
&&
xhr
.
abort
();
}
// 上传封面图
handleShowImgCutModal
=
(
event
)
=>
{
...
...
@@ -47,11 +51,23 @@ class AddLiveBasic extends React.Component {
this
.
props
.
onChange
(
'coverId'
,
null
,
defaultCover
);
}
componentWillUnmount
()
{
const
{
xhr
}
=
this
.
state
;
xhr
&&
xhr
.
abort
();
catalogChange
=
(
value
)
=>
{
const
changeValueLength
=
value
.
length
;
switch
(
changeValueLength
){
case
1
:
this
.
props
.
onChange
(
'parentCatalogId'
,
value
[
0
]);
break
;
case
2
:
this
.
props
.
onChange
(
'parentCatalogId'
,
value
[
0
]);
setTimeout
(()
=>
{
this
.
props
.
onChange
(
'sonCatalogId'
,
value
[
1
]);
},
1000
)
break
;
default
:
break
;
}
}
render
()
{
const
{
showCutModal
,
imageFile
}
=
this
.
state
;
const
{
data
,
liveScene
}
=
this
.
props
;
...
...
@@ -110,7 +126,7 @@ class AddLiveBasic extends React.Component {
</
div
>
<
div
className=
"course-catalog"
>
<
span
className=
"label"
><
span
className=
"require"
>
*
</
span
>
课程分类:
</
span
>
<
Cascader
options=
{
courseCatalogOption
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
<
Cascader
options=
{
courseCatalogOption
}
displayRender=
{
label
=>
label
.
join
(
'-'
)
}
onChange=
{
this
.
catalogChange
}
style=
{
{
width
:
240
}
}
placeholder=
"请选择课程分类"
/>
</
div
>
<
ImgCutModalNew
title=
"裁剪"
...
...
src/modules/course-manage/components/AddLiveBasic.less
View file @
3bcbb935
...
...
@@ -50,7 +50,7 @@
.default-btn {
margin-left: 16px;
color: #FF
7519
;
color: #FF
B714
;
cursor: pointer;
&.disabled {
...
...
src/modules/course-manage/components/AddLiveIntro.jsx
View file @
3bcbb935
...
...
@@ -14,7 +14,7 @@ import UploadOss from "@/core/upload";
import
EditorBox
from
'../components/EditorBox'
;
import
'./AddLiveIntro.less'
;
// import SelectPrepareFileModal from '../
prepare-lesson/
modal/SelectPrepareFileModal';
// import SelectPrepareFileModal from '../modal/SelectPrepareFileModal';
import
{
DISK_MAP
}
from
'@/common/constants/academic/lessonEnum'
;
import
{
ImgCutModalNew
}
from
'@/components'
;
...
...
src/modules/course-manage/modal/SelectPrepareFileModal.jsx
0 → 100644
View file @
3bcbb935
/*
* @Author: 吴文洁
* @Date: 2020-06-10 13:54:01
* @Last Modified by: 吴文洁
* @Last Modified time: 2020-07-23 09:33:21
* @Description:选择备课文件弹窗
*/
import
React
from
'react'
;
import
{
Modal
,
Button
,
Radio
,
Checkbox
,
Spin
,
Upload
,
message
,
Tooltip
}
from
'antd'
;
import
InfiniteScroll
from
'react-infinite-scroller'
;
import
User
from
'@/core/user'
;
import
{
getEllipsText
}
from
"@/core/util"
;
import
DefaultIcon
from
'@/modules/common/DefaultIcon'
;
import
UploadProgressModal
from
'./UploadProgressModal'
;
import
NonCompliantFileModal
from
'./NonCompliantFileModal'
;
import
{
DEFAULT_SIZE_UNIT
,
FileTypeIcon
,
NonCompliantFileMap
,
DISK_LIST
,
SupportFileType
,
LocalFileType
}
from
"@/common/constants/academic/lessonEnum"
;
import
{
getFileTypeByName
}
from
'../components/FolderManage'
;
import
'./SelectPrepareFileModal.less'
;
const
defaultQuery
=
{
size
:
10
,
current
:
1
,
folderIdType
:
'FOLDER'
}
const
defaultRootDisk
=
{
folderName
:
'我的文件'
,
disk
:
'MYSELF'
,
uploadPower
:
false
}
const
FOLDERLIST_URL_MAP
=
{
'MYSELF'
:
'public/apollo/folderList'
,
'COMMON'
:
'public/apollo/commonFolderList'
,
'EMPLOYEE'
:
'public/apollo/employeeFolderList'
};
// 支持本地上传的文件类型
const
supportFileType
=
SupportFileType
.
join
(
','
);
const
localFileType
=
LocalFileType
.
join
(
','
);
// 合法的文件名后缀
const
FILE_SUFFIX_LIST
=
[
'docx'
,
'doc'
,
'ppt'
,
'pptx'
,
'pdf'
,
'xlsx'
,
'xls'
,
'jpg'
,
'jpeg'
,
'png'
,
'mp3'
,
'mp4'
];
// 禁止选择的文件类型
const
DISABLE_FILE_FORMAT
=
[
'text/csv'
,
'application/vnd.ms-excel'
,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
];
// 最多可以选择20个文件
const
MAX_SELECT_LENGTH
=
20
;
let
count
=
0
;
class
SelectPrepareFileModal
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
targetFolder
:
{},
// 当前选中的目录
currentRootDisk
:
{},
// 当前所在根目录
uploadFolderPath
:
{},
// 上传文件的目录,防止中途切换文件夹
currentFile
:
null
,
// 单选模式下, 当前选择的文件
currentFileIndex
:
0
,
// 单选模式下, 当前选择的文件的索引
folderList
:
[],
// 文件列表
folderPathList
:
[],
// 文件路径列表
selectedFileList
:
[],
// 已勾选的文件
nonCompliantFileList
:
[],
// 超出限制的文件列表
query
:
defaultQuery
,
// 初始请求参数
showUploadModal
:
false
,
// 上传进度弹窗
showNonCompliantFileModal
:
false
,
}
}
componentWillReceiveProps
(
nextProps
)
{
const
{
diskList
=
[],
currentRootDisk
}
=
nextProps
;
if
(
nextProps
.
isOpen
)
{
const
_currentRootDisk
=
diskList
[
0
]
||
currentRootDisk
||
defaultRootDisk
;
this
.
setState
({
query
:
defaultQuery
,
currentRootDisk
:
_currentRootDisk
,
folderPathList
:
[
_currentRootDisk
],
},
()
=>
{
this
.
handleFetchFolderList
();
});
}
}
// 获取文件列表
handleFetchFolderList
=
(
params
=
{},
loadMore
=
false
)
=>
{
// 根据当前根节点获取文件列表
const
{
selectTypeList
}
=
this
.
props
;
const
{
query
,
folderList
,
currentRootDisk
}
=
this
.
state
;
const
{
instId
}
=
window
.
currentUserInstInfo
;
const
_params
=
{
...
query
,
...
params
,
instId
:
instId
||
LS
.
get
(
'instId'
),
disk
:
params
.
disk
||
currentRootDisk
.
disk
,
sort
:
'NAME_ASC'
}
if
(
selectTypeList
)
{
_params
.
folderFileType
=
selectTypeList
}
axios
.
Apollo
(
FOLDERLIST_URL_MAP
[
currentRootDisk
.
disk
],
_params
).
then
((
res
)
=>
{
const
{
result
=
{}
}
=
res
;
const
{
records
=
[],
total
=
0
}
=
result
;
this
.
setState
({
folderList
:
loadMore
?
[...
folderList
,
...
records
]
:
records
,
totalCount
:
Number
(
total
)
});
});
}
// 修改目录
handleChangeFolder
=
(
folder
)
=>
{
this
.
setState
({
query
:
defaultQuery
,
folderPathList
:
[
folder
],
currentRootDisk
:
folder
,
selectedFileList
:
[],
// 切换目录不保存之前已勾选的记录
},
()
=>
{
this
.
handleFetchFolderList
({
disk
:
folder
.
disk
});
});
}
// 选择文件/文件夹
handleSelect
=
(
folder
,
index
)
=>
{
// 如果是文件,直接return, 否则进入下一级
const
{
operateType
=
'select'
,
scene
,
selectedFileList
=
[]
}
=
this
.
props
;
const
{
folderType
,
folderName
,
folderFormat
}
=
folder
;
if
(
folderType
===
'FOLDER'
)
{
this
.
handleSelectFolder
(
folder
);
}
const
suffix
=
_
.
last
(
folderName
.
split
(
'.'
)).
toLowerCase
();
{
/* TODO:麦麦打卡类目申请下来后解开视频入口 */
}
const
hiddenVideo
=
this
.
props
.
hiddenVideo
&&
[
'mp4'
,
'MP4'
].
includes
(
suffix
);
// 文件是否已经被关联了
const
hasRelation
=
_
.
find
(
selectedFileList
,
(
item
)
=>
item
.
resourceId
===
folder
.
resourceId
);
// 文件禁止点击的情况(移动、直播场景下文件为Excel、文件已经被关联了、文件后缀不合法)
const
disabled
=
hiddenVideo
||
operateType
===
'move'
||
(
scene
===
'liveCourse'
&&
folderFormat
===
'EXCEL'
)
||
!!
hasRelation
||
!
FILE_SUFFIX_LIST
.
includes
(
suffix
);
if
(
folderType
===
'FILE'
&&
!
disabled
)
{
this
.
handleSelectFile
(
folder
,
index
);
}
}
// 选择文件夹
handleSelectFolder
=
(
folder
)
=>
{
const
{
folderList
,
folderPathList
,
currentRootDisk
}
=
this
.
state
;
// 更新文件路径
folderPathList
.
push
({
id
:
folder
.
id
,
folderName
:
folder
.
folderName
});
this
.
setState
({
query
:
{
...
this
.
state
.
query
,
current
:
1
},
folderPathList
,
targetFolder
:
folder
},
()
=>
{
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
2
;
// 根据父级目录id获取文件夹列表
this
.
handleFetchFolderList
({
parentId
:
folder
.
id
,
folderIdType
:
employeeDisk
?
'USER'
:
'FOLDER'
});
});
}
// 选择文件
handleSelectFile
=
(
file
,
index
)
=>
{
const
{
multiple
}
=
this
.
props
;
if
(
multiple
)
{
const
{
selectedFileList
}
=
this
.
state
;
const
index
=
_
.
findIndex
(
selectedFileList
,
(
item
)
=>
item
.
resourceId
===
file
.
resourceId
);
// 如果文件没有被勾选,则勾选
if
(
index
<
0
)
{
selectedFileList
.
push
(
file
);
}
else
{
// 如果文件已经被勾选了,则取消勾选
selectedFileList
.
splice
(
index
,
1
);
}
this
.
setState
({
selectedFileList
});
}
else
{
this
.
setState
({
currentFile
:
file
,
currentFileIndex
:
index
});
}
}
handleSelectFileDone
=
()
=>
{
const
{
selectedFileList
,
currentFile
}
=
this
.
state
;
const
{
multiple
,
selectedFileList
:
prevSelectedFileList
=
[],
maxSelectLength
}
=
this
.
props
;
if
(
multiple
)
{
const
currSelectedFileList
=
[...(
prevSelectedFileList
||
[]),
...
selectedFileList
];
// 最多选择20个文件,判断是否超出了20个
if
(
currSelectedFileList
.
length
>
(
maxSelectLength
?
maxSelectLength
:
MAX_SELECT_LENGTH
))
{
// 最多还可选择的个数 = 总量(20) - 已经选择的个数(prevSelectedFileList)
message
.
warning
(
`最多可选择
${
maxSelectLength
?(
maxSelectLength
-
prevSelectedFileList
.
length
):(
MAX_SELECT_LENGTH
-
prevSelectedFileList
.
length
)}
个文件`
);
return
;
}
const
addFolderIds
=
_
.
pluck
(
selectedFileList
,
'id'
);
this
.
props
.
onSelect
(
addFolderIds
,
selectedFileList
);
// 上传完成之后将selectedFileList置为空,上传进度弹窗也一起消失
this
.
setState
({
selectedFileList
:
[],
showUploadModal
:
false
,
})
}
else
{
this
.
props
.
onSelect
(
currentFile
);
this
.
setState
({
currentFile
:
null
,
showUploadModal
:
false
,
});
}
}
// 前往特定的文件夹
handleChangeCurrentFolder
=
(
folder
,
index
)
=>
{
// 请求接口,获取当前folder下所有的文件
const
{
folderPathList
,
currentRootDisk
}
=
this
.
state
;
if
(
folderPathList
.
length
===
1
)
return
;
folderPathList
.
splice
(
index
+
1
,
folderPathList
.
length
);
const
targetFolder
=
folderPathList
[
folderPathList
.
length
-
1
];
const
{
id
=
null
}
=
targetFolder
;
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
2
;
this
.
setState
({
targetFolder
,
folderPathList
},
()
=>
{
this
.
handleFetchFolderList
({
parentId
:
id
,
disk
:
currentRootDisk
.
disk
,
folderIdType
:
employeeDisk
?
'USER'
:
'FOLDER'
})
});
}
// 移动到此目录
handleMoveToTargetFolder
=
()
=>
{
const
{
targetFolder
}
=
this
.
state
;
// 请求接口,完成之后刷新文件列表
this
.
props
.
onMove
(
targetFolder
);
}
// 滑动加载更多
handleScrollEvent
=
()
=>
{
const
{
folderList
,
totalCount
,
currentRootDisk
,
folderPathList
}
=
this
.
state
;
const
hasMore
=
folderList
.
length
<
totalCount
;
const
{
fileListRef
}
=
this
.
refs
;
const
hasReachBottom
=
fileListRef
.
scrollTop
+
fileListRef
.
clientHeight
===
fileListRef
.
scrollHeight
;
if
(
!
hasReachBottom
||
!
hasMore
)
return
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
];
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
2
;
const
query
=
_
.
clone
(
this
.
state
.
query
);
query
.
current
=
query
.
current
+
1
;
this
.
setState
({
query
},
()
=>
{
this
.
handleFetchFolderList
({
disk
:
currentRootDisk
.
disk
,
folderIdType
:
employeeDisk
?
'USER'
:
'FOLDER'
,
parentId
:
currentFolder
.
id
},
true
);
})
}
// 取消选择
handleClose
=
()
=>
{
this
.
setState
({
query
:
defaultQuery
,
selectedFileList
:
[]
},
()
=>
{
this
.
props
.
onClose
();
})
}
handleChooseFile
=
async
()
=>
{
// 校验是否已经欠费
const
{
instId
}
=
window
.
currentUserInstInfo
;
const
balanceRes
=
await
axios
.
Business
(
"public/liveAssets/query"
,
{
instId
});
// balance小于等于0表示已经欠费,旗舰版用户不需要校验余额
const
ultimateRes
=
await
axios
.
Business
(
'public/inst/checkInstProduct'
,
{
instId
,
productCodeList
:
[
'ULTIMATESELL'
,
'PIP_TO_ULTIMATE'
,
'HIGH_TO_ULTIMATE'
]
});
const
{
result
}
=
balanceRes
;
if
((
!
result
||
result
.
balance
<=
0
)
&&
!
ultimateRes
.
result
)
{
this
.
handleShowNoticeModal
(
balance
);
return
;
}
const
dom
=
document
.
querySelector
(
'#detailFileInput'
);
dom
.
click
();
}
// 上传文件
handleUpload
=
(
event
)
=>
{
const
{
selectType
}
=
this
.
props
;
const
fileList
=
event
.
target
.
files
;
// 判断文件的大小是否超出了限制
const
nonCompliantFileList
=
[];
const
_fileList
=
[...
fileList
];
_fileList
.
map
((
file
,
index
)
=>
{
let
{
size
,
type
,
name
}
=
file
;
if
(
!
type
)
{
type
=
getFileTypeByName
(
name
);
}
if
(
type
.
indexOf
(
'image'
)
>
-
1
&&
size
>
50
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
);
_fileList
.
splice
(
index
,
1
);
}
if
(
type
.
indexOf
(
'audio'
)
>
-
1
&&
size
>
50
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
);
_fileList
.
splice
(
index
,
1
);
}
if
(
type
.
indexOf
(
'video'
)
>
-
1
&&
size
>
500
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
);
_fileList
.
splice
(
index
,
1
);
}
if
(
localFileType
.
indexOf
(
type
)
>
-
1
&&
size
>
100
*
DEFAULT_SIZE_UNIT
)
{
nonCompliantFileList
.
push
(
file
);
_fileList
.
splice
(
index
,
1
);
}
file
.
key
=
count
++
;
});
// 不符合规则的文件列表
if
(
nonCompliantFileList
.
length
>
0
)
{
const
{
confirm
}
=
this
.
props
;
if
(
confirm
)
{
Modal
.
info
({
...
confirm
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
});
return
;
}
this
.
setState
({
fileList
:
_fileList
,
nonCompliantFileList
,
showNonCompliantFileModal
:
true
,
})
}
else
{
this
.
handleShowUploadModal
(
_fileList
);
}
// 清空文件,防止第二次无法上传同一个文件
const
dom
=
document
.
querySelector
(
'#detailFileInput'
);
dom
.
value
=
''
;
}
// 显示上传进度弹窗
handleShowUploadModal
=
async
(
fileList
)
=>
{
if
(
fileList
.
length
)
{
const
{
folderPathList
}
=
this
.
state
;
this
.
setState
({
showUploadModal
:
true
,
localFileList
:
fileList
,
uploadFolderPath
:
folderPathList
[
folderPathList
.
length
-
1
]
});
}
}
handleUploadDone
=
(
file
,
resourceId
)
=>
{
const
{
folderList
,
folderPathList
,
currentRootDisk
,
uploadFolderPath
}
=
this
.
state
;
const
{
scene
}
=
this
.
props
;
const
{
teacherId
,
instId
}
=
window
.
currentUserInstInfo
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
];
const
{
id
=
null
}
=
uploadFolderPath
||
currentFolder
;
let
{
size
,
type
,
name
}
=
file
;
if
(
!
type
)
{
type
=
getFileTypeByName
(
name
)
}
const
params
=
{
name
,
resourceId
,
folderSize
:
size
,
folderFormat
:
type
,
folderTypeEnum
:
resourceId
?
'FILE'
:
'FOLDER'
,
disk
:
currentRootDisk
.
disk
,
instId
:
instId
||
LS
.
get
(
'instId'
),
createUser
:
teacherId
?
"TEACHER"
:
"ADMIN"
,
parentId
:
id
}
axios
.
Apollo
(
'public/apollo/saveFolder'
,
params
).
then
((
res
)
=>
{
const
{
query
,
selectedFileList
,
currentRootDisk
}
=
this
.
state
;
const
_query
=
_
.
clone
(
query
);
{
/* TODO:麦麦打卡类目申请下来后解开视频入口 */
}
const
suffix
=
_
.
last
(
name
.
split
(
'.'
)).
toLowerCase
();
const
hiddenVideo
=
this
.
props
.
hiddenVideo
&&
[
'mp4'
,
'MP4'
].
includes
(
suffix
);
const
_selectedFileList
=
hiddenVideo
?
[...
selectedFileList
]
:
[...
selectedFileList
,
res
.
result
];
_query
.
current
=
1
;
this
.
setState
({
query
:
_query
,
selectedFileList
:
scene
===
'liveCourse'
?
_selectedFileList
.
filter
(
item
=>
{
return
!
DISABLE_FILE_FORMAT
.
includes
(
item
.
folderFormat
)})
:
_selectedFileList
,
},
()
=>
{
if
(
resourceId
&&
!
_
.
isEqual
(
uploadFolderPath
,
currentFolder
))
return
;
// 上传之后根目录不变
this
.
handleFetchFolderList
({
parentId
:
id
,
disk
:
currentRootDisk
.
disk
});
});
});
}
// 取消上传
handleHiddenUploadModal
=
()
=>
{
this
.
setState
({
showUploadModal
:
false
,
localFileList
:
[]
});
}
// 余额欠费提示弹窗
handleShowNoticeModal
=
(
balance
)
=>
{
Modal
.
info
({
title
:
'无法继续操作'
,
content
:
'直播服务已升级,请联系运营老师。'
,
icon
:
<
span
className=
"icon iconfont default-confirm-icon"
>

</
span
>
})
}
renderFooter
=
()
=>
{
const
{
selectedFileList
,
currentRootDisk
}
=
this
.
state
;
const
{
operateType
,
selectType
,
multiple
,
accept
=
".ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls"
,
tooltip
=
'支持文件类型:ppt、word、excel、pdf、jpg、jpeg、png、mp3、mp4'
}
=
this
.
props
;
const
selectedFileLength
=
selectedFileList
.
length
;
const
hasSelect
=
!!
selectedFileLength
;
// 是否有上传权限
const
hasManagementAuthority
=
currentRootDisk
.
uploadPower
;
return
[
<
input
multiple
type=
"file"
style=
{
{
display
:
'none'
}
}
id=
"detailFileInput"
accept=
{
accept
}
onChange=
{
(
e
)
=>
this
.
handleUpload
(
e
)
}
/>,
<
div
key=
"footerLeft"
className=
"footer__left"
className=
{
`prepare-lesson-upload ${operateType === 'select' && hasManagementAuthority ? 'visible' : 'hidden'}`
}
>
<
Tooltip
title=
{
tooltip
}
>
<
span
className=
"footer__left"
onClick=
{
this
.
handleChooseFile
}
>
上传文件
</
span
>
</
Tooltip
>
</
div
>,
<
div
className=
"footer__right"
key=
"footerRight"
>
<
Button
onClick=
{
()
=>
{
this
.
setState
({
showUploadModal
:
false
,
selectedFileList
:
[]
});
this
.
props
.
onClose
();
}
}
>
取消
</
Button
>
{
operateType
===
'select'
?
<
Button
key=
"cancel"
type=
"primary"
disabled=
{
!
hasSelect
&&
multiple
}
onClick=
{
this
.
handleSelectFileDone
}
>
{
`确定${hasSelect ? `
(
$
{
selectedFileLength
})
` : ''}`
}
</
Button
>
:
<
Button
type=
"primary"
onClick=
{
this
.
handleMoveToTargetFolder
}
>
移动到此目录
</
Button
>
}
</
div
>
]
}
render
()
{
const
{
folderPathList
,
folderList
,
selectedFileList
,
currentRootDisk
,
showUploadModal
,
localFileList
,
showNonCompliantFileModal
,
nonCompliantFileList
,
currentFile
,
currentFileIndex
}
=
this
.
state
;
const
{
scene
,
isOpen
,
multiple
=
false
,
diskList
=
[],
operateType
=
'move'
,
footer
=
this
.
renderFooter
(),
selectedFileList
:
prevSelectedFileList
=
[],
}
=
this
.
props
;
const
currentFolder
=
folderPathList
[
folderPathList
.
length
-
1
];
const
title
=
operateType
===
'move'
?
'移动到'
:
'选择文件'
;
const
currSelectedFileList
=
[...(
prevSelectedFileList
||
[]),
...
selectedFileList
];
// 判断是否是员工文件的根目录
const
employeeDisk
=
currentRootDisk
.
disk
===
'EMPLOYEE'
&&
folderPathList
.
length
===
1
;
return
(
<
Modal
visible=
{
isOpen
}
title=
{
title
}
footer=
{
footer
}
width=
{
560
}
onCancel=
{
this
.
handleClose
}
className=
"select-prepare-file-modal"
>
{
// 机构可见磁盘大于1且在选择文件的情况下才显示tabs
operateType
===
'select'
&&
diskList
.
length
>
1
&&
<
div
className=
"radio-buttons"
>
<
Radio
.
Group
defaultValue=
{
currentRootDisk
.
disk
}
value=
{
currentRootDisk
.
disk
}
>
{
diskList
.
map
((
item
,
index
)
=>
{
return
(
<
Radio
.
Button
value=
{
item
.
disk
}
key=
{
`folder-item${index}`
}
onClick=
{
()
=>
this
.
handleChangeFolder
(
item
)
}
>
{
item
.
folderName
}
</
Radio
.
Button
>
)
})
}
</
Radio
.
Group
>
</
div
>
}
<
div
className=
"bread-crumbs"
>
{
folderPathList
.
map
((
folderPath
,
index
)
=>
{
return
(
<
div
className=
"file-path"
key=
{
`file-path${index}`
}
onClick=
{
()
=>
this
.
handleChangeCurrentFolder
(
folderPath
,
index
)
}
>
{
folderPath
.
folderName
}
</
div
>
)
})
}
</
div
>
{
!
_
.
isEmpty
(
folderList
)
?
<
div
onScrollCapture=
{
()
=>
this
.
handleScrollEvent
()
}
style=
{
{
height
:
'320px'
,
overflowY
:
'scroll'
}
}
ref=
"fileListRef"
>
<
div
className=
"file-list"
>
{
folderList
.
map
((
folder
,
index
)
=>
{
const
{
folderType
,
folderSize
,
folderFormat
,
folderName
}
=
folder
;
const
isFolder
=
folderType
===
'FOLDER'
;
let
_size
=
`${(folderSize / DEFAULT_SIZE_UNIT).toFixed(1)}M`
;
if
(
folderSize
<
0.1
*
DEFAULT_SIZE_UNIT
)
{
_size
=
`${(folderSize / 1000).toFixed(1)}kb`
;
}
let
imgSrc
=
!
isFolder
?
FileTypeIcon
[
folderFormat
]
:
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png'
;
if
(
employeeDisk
)
{
imgSrc
=
'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871440736.png'
}
const
suffix
=
_
.
last
(
folderName
.
split
(
'.'
)).
toLowerCase
();
{
/* TODO:麦麦打卡类目申请下来后解开视频入口 */
}
const
hiddenVideo
=
this
.
props
.
hiddenVideo
&&
[
'mp4'
,
'MP4'
].
includes
(
suffix
);
// 判断文件是否被选中了
const
hasSelect
=
_
.
find
(
currSelectedFileList
,
(
item
)
=>
item
.
resourceId
===
folder
.
resourceId
);
// 判断文件是否已经被关联了
const
hasRelation
=
_
.
find
((
prevSelectedFileList
||
[]),
(
item
)
=>
item
.
resourceId
===
folder
.
resourceId
);
// 文件禁止点击的情况(移动、直播场景下文件为Excel、文件已经被关联了、文件不合法)
const
disabled
=
hiddenVideo
||
(
!
isFolder
&&
operateType
===
'move'
)
||
(
scene
===
'liveCourse'
&&
folder
.
folderFormat
===
'EXCEL'
)
||
!!
hasRelation
||
(
!
isFolder
&&
!
FILE_SUFFIX_LIST
.
includes
(
suffix
));
return
(
<
div
className=
{
`file-item ${!disabled ? 'enable' : 'disable'}`
}
key=
{
`file-item${index}`
}
onClick=
{
()
=>
{
this
.
handleSelect
(
folder
,
index
)
}
}
>
<
div
className=
"file-item__cover"
>
<
img
src=
{
imgSrc
}
alt=
"file-item__img"
width=
"24"
/>
<
span
>
{
getEllipsText
(
folderName
,
20
)
}
</
span
>
</
div
>
{
/* 文件夹不显示大小 */
}
{
!
isFolder
&&
<
div
className=
"file-item__size"
>
{
_size
}
</
div
>
}
{
/* 当选择文件的时候,显示复选框 */
}
{
!
isFolder
&&
operateType
===
'select'
&&
(
multiple
?
<
Checkbox
checked=
{
!!
hasSelect
}
disabled=
{
!!
hasRelation
}
/>
:
(
_
.
isEqual
(
currentFile
,
folder
)
?
<
span
className=
"icon iconfont correct"
>

</
span
>
:
<
span
className=
"icon iconfont error"
>

</
span
>
)
)
}
{
/* 文件不显示展开的图标 */
}
{
isFolder
&&
<
div
className=
"file-item__expend-icon"
>
<
span
className=
"icon iconfont"
>

</
span
>
</
div
>
}
</
div
>
)
})
}
</
div
>
</
div
>
:
<
DefaultIcon
type=
'student'
title=
{
<
span
className=
"desc"
>
这个文件夹是空的
</
span
>
}
/>
}
<
UploadProgressModal
isOpen=
{
showUploadModal
}
fileList=
{
localFileList
}
currentFolder=
{
currentFolder
}
onUpload=
{
this
.
handleUploadDone
}
onCancel=
{
this
.
handleHiddenUploadModal
}
/>
<
NonCompliantFileModal
isOpen=
{
showNonCompliantFileModal
}
fileList=
{
nonCompliantFileList
}
onClose=
{
()
=>
{
this
.
setState
({
showNonCompliantFileModal
:
false
});
}
}
onOk=
{
()
=>
{
this
.
setState
({
showNonCompliantFileModal
:
false
});
this
.
handleShowUploadModal
(
this
.
state
.
fileList
)
}
}
/>
{
this
.
state
.
chargeModal
}
</
Modal
>
)
}
}
export
default
SelectPrepareFileModal
;
\ No newline at end of file
src/modules/course-manage/modal/SelectPrepareFileModal.less
0 → 100644
View file @
3bcbb935
.select-prepare-file-modal {
.ant-upload-list {
display: none;
}
.DefaultIcon {
margin: 12px 0 0 0;
border: 1px solid #E8E8E8;
border-radius: 4px;
padding: 100px 0;
.desc {
color: #999;
.upload-btn {
color: #FF7519;
margin: 0 4px;
cursor: pointer;
}
}
}
.radio-buttons {
text-align: center;
margin-bottom: 16px;
}
.file-path {
display: inline-block;
color: #333;
position: relative;
margin-bottom: 12px;
margin-right: 12px;
&:last-child {
color: #999;
}
&:not(:last-child) {
cursor: pointer;
&:hover {
color: #FF8534;
}
&::before {
content: '/';
position: absolute;
color: #CCC;
right: -8px;
}
}
}
.file-list {
border: 1px solid #E8E8E8;
border-radius: 4px;
.file-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 48px;
padding: 12px 25px;
&:not(:last-child) {
border-bottom: 1px solid #E8E8E8;
}
&.enable {
cursor: pointer;
}
&.disable {
cursor: not-allowed;
opacity: 0.5;
}
&__cover {
min-width: 320px;
img {
margin-right: 8px;
}
}
&__size {
margin-left: 40px;
}
.iconfont {
color: #BFBFBF;
&.correct {
color: #FC9C6B;
}
}
}
}
.ant-modal-footer {
display: flex;
align-items: center;
justify-content: space-between;
.prepare-lesson-upload.hidden {
visibility: hidden;
}
.prepare-lesson-upload.visible {
visibility: visible;
}
.footer__left {
color: #FF7519;
cursor: pointer;
}
}
}
\ No newline at end of file
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