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
2c634bc6
Commit
2c634bc6
authored
Mar 09, 2021
by
zhangleyuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:处理任务排序
parent
b3ffb2aa
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
319 additions
and
109 deletions
+319
-109
src/data-source/plan/request-apis.ts
+5
-1
src/data-source/store/request-apis.ts
+4
-3
src/domains/plan-domain/planService.ts
+6
-2
src/modules/plan-manage/AddPlan.jsx
+16
-5
src/modules/plan-manage/components/ExpiredCourseList.jsx
+30
-20
src/modules/plan-manage/components/TrainingTask.jsx
+150
-78
src/modules/plan-manage/components/TrainingTask.less
+106
-0
src/modules/plan-manage/modal/relatedCourseModal.jsx
+2
-0
No files found.
src/data-source/plan/request-apis.ts
View file @
2c634bc6
...
...
@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-21 16:08:38
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-0
5 14:04:52
* @LastEditTime: 2021-03-0
9 12:54:31
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -43,4 +43,7 @@ export function removePlanCustomer(params: object) {
}
export
function
getStorePlanAll
(
params
:
object
)
{
return
Service
.
Hades
(
"public/hades/getStorePlanAll"
,
params
);
}
export
function
getTrainingCourseAutoCancel
(
params
:
object
)
{
return
Service
.
Hades
(
"public/hades/getTrainingCourseAutoCancel"
,
params
);
}
\ No newline at end of file
src/data-source/store/request-apis.ts
View file @
2c634bc6
...
...
@@ -2,7 +2,7 @@
* @Author: wufan
* @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-0
8 11:47:58
* @LastEditTime: 2021-03-0
9 10:28:03
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -73,4 +73,6 @@ export function updateStoreMessage(params: object) {
}
export
function
getStoreDetail
(
params
:
object
)
{
return
Service
.
Hades
(
"public/hades/getStoreDetail"
,
params
);
}
\ No newline at end of file
}
src/domains/plan-domain/planService.ts
View file @
2c634bc6
...
...
@@ -2,11 +2,11 @@
* @Author: zhangleyuan
* @Date: 2021-02-21 16:15:38
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-0
5 14:04:25
* @LastEditTime: 2021-03-0
9 12:54:46
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import
{
getTrainingPlanPage
,
createTrainingPlan
,
updateStateTrainingPlan
,
getTrainingPlanDetail
,
updateTrainingPlan
,
deleteTrainingPlan
,
getPlanUserRecordPage
,
getPlanCustomerRecordPage
,
getPlanCustomerDetail
,
getPlanCustomerAboutUser
,
removePlanCustomer
,
getStorePlanAll
}
from
'@/data-source/plan/request-apis'
;
import
{
getTrainingPlanPage
,
createTrainingPlan
,
updateStateTrainingPlan
,
getTrainingPlanDetail
,
updateTrainingPlan
,
deleteTrainingPlan
,
getPlanUserRecordPage
,
getPlanCustomerRecordPage
,
getPlanCustomerDetail
,
getPlanCustomerAboutUser
,
removePlanCustomer
,
getStorePlanAll
,
getTrainingCourseAutoCancel
}
from
'@/data-source/plan/request-apis'
;
export
default
class
PlanService
{
// 获取员工列表
static
getTrainingPlanPage
(
params
:
any
)
{
...
...
@@ -45,4 +45,7 @@ export default class PlanService {
static
getStorePlanAll
(
params
:
any
)
{
return
getStorePlanAll
(
params
);
}
static
getTrainingCourseAutoCancel
(
params
:
any
)
{
return
getTrainingCourseAutoCancel
(
params
);
}
}
\ No newline at end of file
src/modules/plan-manage/AddPlan.jsx
View file @
2c634bc6
...
...
@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:13:39
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-0
8 18:19:14
* @LastEditTime: 2021-03-0
9 12:54:53
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -27,7 +27,8 @@ const defaultBasicData = {
instro
:
''
,
operateType
:
'All_Operate'
,
percentCompleteLive
:
80
,
percentCompleteVideo
:
80
percentCompleteVideo
:
80
,
}
const
defaultTaskList
=
[];
...
...
@@ -36,12 +37,22 @@ function AddPlan() {
const
type
=
getParameterByName
(
"type"
);
const
[
basicData
,
setBasicData
]
=
useState
(
defaultBasicData
);
const
[
taskList
,
setTaskList
]
=
useState
(
defaultTaskList
);
const
[
expiredCourseList
,
setExpiredCourseList
]
=
useState
([]);
useEffect
(()
=>
{
if
(
type
===
'edit'
){
getPlanDetail
();
getPlanCustomerState
();
}
},
id
)
function
getPlanDetail
(){
function
getPlanCustomerState
(){
PlanService
.
getTrainingCourseAutoCancel
({
planId
:
id
}).
then
((
res
)
=>
{
const
expiredCourseList
=
res
.
result
;
setExpiredCourseList
(
expiredCourseList
)
})
}
function
getPlanDetail
(){
PlanService
.
getTrainingPlanDetail
({
planId
:
id
}).
then
((
res
)
=>
{
...
...
@@ -220,10 +231,10 @@ function AddPlan() {
<
TrainingTask
data=
{
taskList
}
onChange=
{
handleChangeTaskInfo
}
/>
}
</
div
>
{
type
===
'edit'
&&
{
(
type
===
'edit'
&&
expiredCourseList
.
length
>
0
)
&&
<
div
className=
"expired-info__wrap"
>
<
div
className=
"title"
>
失效课程
</
div
>
<
ExpiredCourseList
/>
<
ExpiredCourseList
expiredCourseList=
{
expiredCourseList
}
/>
</
div
>
}
</
div
>
...
...
src/modules/plan-manage/components/ExpiredCourseList.jsx
View file @
2c634bc6
...
...
@@ -4,33 +4,43 @@ import { withRouter } from 'react-router-dom';
import
User
from
'@/common/js/user'
;
import
'./ExpiredCourseList.less'
;
function
ExpiredCourseList
()
{
function
ExpiredCourseList
(
props
)
{
return
(
<
div
className=
"expired-course-list"
>
<
div
className=
"course-item"
>
<
div
className=
"course-left"
>
<
div
className=
"course-status"
>
未成功开课
</
div
>
<
div
className=
"course-info"
>
<
div
className=
"course-type"
>
<
span
>
直播课
</
span
>
</
div
>
<
div
className=
"course-instro"
>
<
div
className=
"course-name"
>
课程名称最多四十个字课程名称最多四十个字课程名称最多四十个字课程名称最多四十个字
{
props
.
expiredCourseList
.
map
((
item
,
index
)
=>
{
return
<
div
className=
"course-item"
>
<
div
className=
"course-left"
>
<
div
className=
"course-status"
>
未成功开课
</
div
>
<
div
className=
"task-name"
>
培训名称最多二十个字培训名称最多二十个字
<
div
className=
"course-info"
>
<
div
className=
"course-type"
>
{
item
.
courseType
===
"LIVE"
&&
<
span
>
直播课
</
span
>
}
{
item
.
courseType
===
"VOICE "
&&
<
span
>
视频课
</
span
>
}
</
div
>
<
div
className=
"course-instro"
>
<
div
className=
"course-name"
>
{
item
.
courseName
}
</
div
>
<
div
className=
"task-name"
>
{
item
.
taskName
}
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"course-time"
>
上课时间:
{
formatDate
(
'YYYY-MM-DD H:i'
,
item
.
startTime
)
}
</
div
>
</
div
>
</
div
>
<
div
className=
"course-time"
>
上课时间:47238095327
</
div
>
</
div
>
})
}
</
div
>
);
}
...
...
src/modules/plan-manage/components/TrainingTask.jsx
View file @
2c634bc6
...
...
@@ -2,7 +2,7 @@
* @Author: zhangleyuan
* @Date: 2021-02-20 16:45:51
* @LastEditors: zhangleyuan
* @LastEditTime: 2021-03-09 1
0:04:40
* @LastEditTime: 2021-03-09 1
3:42:05
* @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
...
...
@@ -15,39 +15,42 @@ import RelatedCourseModal from '../modal/relatedCourseModal'
import
{
withRouter
}
from
'react-router-dom'
;
import
'./TrainingTask.less'
;
const
{
Panel
}
=
Collapse
const
CourseType
=
{
LIVE
:
{
text
:
"直播课"
},
VOICE
:
{
text
:
"视频课"
},
RECORD
:
{
text
:
'录播课'
}
};
const
courseStateShow
=
{
UN_START
:
{
title
:
"待开课"
,
},
STARTING
:
{
title
:
"上课中"
,
},
FINISH
:
{
title
:
"已完成"
,
},
EXPIRED
:
{
title
:
"未成功开课"
,
},
};
const
DragHandle
=
sortableHandle
(()
=>
(
<
span
style=
{
{
cursor
:
'pointer'
,
color
:
'#999'
}
}
>
<
span
className=
"operate__item"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
>
移动
</
span
>
<
span
className=
"text"
>
移动
</
span
>
</
span
>
));
const
SortableItem
=
sortableElement
(
props
=>
<
tr
{
...
props
}
/>);
const
SortableContainer
=
sortableContainer
(
props
=>
<
tbody
{
...
props
}
/>);
const
taskData
=
[
{
key
:
'1'
,
name
:
'John Brown'
,
age
:
32
,
address
:
'New York No. 1 Lake Park'
,
index
:
0
,
},
{
key
:
'2'
,
name
:
'Jim Green'
,
age
:
42
,
address
:
'London No. 1 Lake Park'
,
index
:
1
,
},
{
key
:
'3'
,
name
:
'Joe Black'
,
age
:
32
,
address
:
'Sidney No. 1 Lake Park'
,
index
:
2
,
},
];
const
SortableTaskItem
=
sortableElement
(
props
=>
<
div
{
...
props
}
>
{
props
.
taskItem
}
</
div
>)
const
SortableTaskContainer
=
sortableContainer
(
props
=>
<
div
{
...
props
}
></
div
>);
...
...
@@ -209,8 +212,9 @@ class TrainingTask extends React.Component {
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMove
([].
concat
(
dataSource
),
oldIndex
,
newIndex
).
filter
(
el
=>
!!
el
);
console
.
log
(
"newData"
,
newData
)
this
.
setState
({
dataSource
:
newData
});
this
.
setState
({
dataSource
:
newData
,
},()
=>
{
this
.
props
.
onChange
(
newData
);})
}
};
onCourseSortEnd
=
({
oldIndex
,
newIndex
},
parentIndex
)
=>
{
...
...
@@ -223,7 +227,9 @@ class TrainingTask extends React.Component {
const
_dataSource
=
[...
dataSource
];
if
(
oldIndex
!==
newIndex
)
{
_dataSource
[
parentIndex
].
courseList
=
arrayMove
([].
concat
(
dataSource
[
parentIndex
].
courseList
),
oldIndex
,
newIndex
).
filter
(
el
=>
!!
el
);
this
.
setState
({
dataSource
:
_dataSource
});
this
.
setState
({
dataSource
:
_dataSource
,
},()
=>
{
this
.
props
.
onChange
(
_dataSource
);})
}
};
...
...
@@ -344,51 +350,116 @@ class TrainingTask extends React.Component {
this
.
props
.
onChange
(
newData
);
})
}
renderTaskItem
=
(
record
,
index
)
=>
{
return
<
div
>
<
span
>
<
span
></
span
>
</
span
>
{
record
.
type
===
'input'
?
<
Form
>
<
Form
.
Item
validateTrigger=
{
[
'onChange'
,
'onBlur'
]
}
name=
{
[
'taskName'
]
}
rules=
{
[
{
required
:
true
,
message
:
"请输入任务名称"
,
},
]
}
>
<
Input
defaultValue=
{
record
.
taskName
}
style=
{
{
width
:
300
}
}
placeholder=
"请输入任务名称(20字以内)"
maxLength=
{
20
}
onChange=
{
(
e
)
=>
{
this
.
handleRenameTaskName
(
e
,
record
)}
}
onBlur=
{
(
e
)
=>
{
this
.
handleTaskNameBlur
(
e
,
record
)}
}
/>
</
Form
.
Item
>
</
Form
>
:
<
span
>
{
record
.
taskName
}
</
span
>
}
<
DragHandle
/>
<
div
>
<
SortableCourseContainer
useDragHandle
disableAutoscroll
helperClass=
"row-dragging"
onSortEnd=
{
(
record
)
=>
this
.
onCourseSortEnd
(
record
,
index
)
}
>
{
record
.
courseList
.
map
((
courseItem
,
courseIndex
)
=>
<
SortableCourseItem
courseItem=
{
this
.
renderCourseItem
(
courseItem
,
courseIndex
)
}
index=
{
courseIndex
}
>
</
SortableCourseItem
>
)
}
</
SortableCourseContainer
>
<
div
><
Button
onClick=
{
()
=>
{
this
.
showRelatedCourseModal
(
index
)}
}
><
span
>
+
</
span
><
span
>
关联课程
</
span
></
Button
></
div
>
</
div
>
</
div
>
openOrCloseTask
=
(
index
)
=>
{
const
{
dataSource
}
=
this
.
state
;
const
newData
=
[...
dataSource
];
newData
[
index
].
open
=
!
newData
[
index
].
open
;
this
.
setState
({
dataSource
:
newData
,
},()
=>
{
this
.
props
.
onChange
(
newData
);})
}
renderCourseItem
=
(
record
,
index
)
=>
{
return
<
div
>
{
record
.
courseName
}
<
DragHandle
/>
renderTaskItem
=
(
record
,
index
)
=>
{
return
<
div
className=
"task-item"
>
<
div
className=
"task-con"
>
<
div
className=
"task-instro"
>
<
span
onClick=
{
()
=>
this
.
openOrCloseTask
(
index
)
}
>
{
record
.
open
?
<
span
className=
"icon iconfont open-icon"
>

</
span
>:
<
span
className=
"icon iconfont open-icon"
>

</
span
>
}
</
span
>
{
record
.
type
===
'input'
?
<
div
className=
"task-name-con"
>
<
span
className=
"number"
>
{
index
+
1
}
.
</
span
>
<
Form
>
<
Form
.
Item
validateTrigger=
{
[
'onChange'
,
'onBlur'
]
}
name=
{
[
'taskName'
]
}
rules=
{
[
{
required
:
true
,
message
:
"请输入任务名称"
,
},
]
}
>
<
Input
className=
"task-name-input"
defaultValue=
{
record
.
taskName
}
style=
{
{
width
:
300
}
}
placeholder=
"请输入任务名称(20字以内)"
maxLength=
{
20
}
onChange=
{
(
e
)
=>
{
this
.
handleRenameTaskName
(
e
,
record
)}
}
onBlur=
{
(
e
)
=>
{
this
.
handleTaskNameBlur
(
e
,
record
)}
}
/>
</
Form
.
Item
>
</
Form
>
</
div
>
:
<
div
className=
"task-name-con"
>
<
span
className=
"number"
>
{
index
+
1
}
.
</
span
>
<
span
className=
"task-name"
>
{
record
.
taskName
}
</
span
>
</
div
>
}
</
div
>
<
div
className=
"operate"
>
<
DragHandle
/>
<
span
className=
"operate__item"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
onClick=
{
()
=>
{
const
{
dataSource
}
=
this
.
state
;
record
.
type
=
"input"
;
this
.
setState
({
dataSource
})}
}
>
重命名
</
span
>
</
span
>
<
span
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleDeleteTask
(
index
)}
}
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
>
删除
</
span
>
</
span
>
</
div
>
</
div
>
{
record
.
open
&&
<
div
className=
"course-box"
>
<
SortableCourseContainer
useDragHandle
disableAutoscroll
helperClass=
"row-dragging"
onSortEnd=
{
(
record
)
=>
this
.
onCourseSortEnd
(
record
,
index
)
}
>
{
record
.
courseList
.
map
((
courseItem
,
courseIndex
)
=>
<
SortableCourseItem
courseItem=
{
this
.
renderCourseItem
(
courseItem
,
courseIndex
,
index
)
}
index=
{
courseIndex
}
>
</
SortableCourseItem
>
)
}
</
SortableCourseContainer
>
<
div
className=
"add-course-con"
><
span
className=
"add-course-item"
onClick=
{
()
=>
{
this
.
showRelatedCourseModal
(
index
)}
}
><
span
>
+
</
span
><
span
>
关联课程
</
span
></
span
></
div
>
</
div
>
}
</
div
>
}
renderCourseItem
=
(
record
,
index
,
parentIndex
)
=>
{
return
<
div
className=
"course-item"
>
<
div
className=
"course-info"
>
<
span
className=
"course-type"
>
{
CourseType
[
record
.
courseType
].
text
}
</
span
>
{
record
.
type
===
'input'
?
<
Form
>
<
Form
.
Item
validateTrigger=
{
[
'onChange'
,
'onBlur'
]
}
name=
{
[
'courseName'
]
}
rules=
{
[
{
required
:
true
,
message
:
"请输入课程名称"
,
},
]
}
>
<
Input
className=
"course-name-input"
defaultValue=
{
record
.
courseName
}
style=
{
{
width
:
300
}
}
placeholder=
"请输入任务名称(40字以内)"
maxLength=
{
40
}
onChange=
{
(
e
)
=>
{
this
.
handleRenameCourseName
(
e
,
record
)}
}
onBlur=
{
(
e
)
=>
{
this
.
handleCourseNameBlur
(
e
,
record
)}
}
/></
Form
.
Item
>
</
Form
>
:
<
span
className=
"course-name"
>
{
parentIndex
+
1
}
.
{
index
+
1
}{
record
.
courseName
}
</
span
>
}
{
record
.
courseState
===
"EXPIRED"
&&
<
span
className=
"icon iconfont tip"
>

</
span
>
}
{
record
.
courseState
&&
<
span
className=
"course-state"
>
{
courseStateShow
[
record
.
courseState
].
title
}
</
span
>
}
</
div
>
<
div
className=
"operate"
>
<
DragHandle
/>
<
span
className=
"operate__item"
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
onClick=
{
(
e
)
=>
{
const
{
dataSource
}
=
this
.
state
;
record
.
type
=
"input"
;
this
.
setState
({
dataSource
})}
}
>
重命名
</
span
>
</
span
>
<
span
className=
"operate__item"
onClick=
{
()
=>
{
this
.
handleDeleteCourse
(
parentIndex
,
index
)}
}
>
<
span
className=
"icon iconfont"
>

</
span
>
<
span
className=
"text"
>
删除
</
span
>
</
span
>
</
div
>
</
div
>
}
render
()
{
...
...
@@ -397,7 +468,7 @@ class TrainingTask extends React.Component {
const
{
data
}
=
this
.
props
;
return
(
<
div
className=
"training-task"
>
<
Table
{
/*
<Table
pagination={false}
dataSource={dataSource}
columns={this.parseTaskColumns()}
...
...
@@ -429,8 +500,9 @@ class TrainingTask extends React.Component {
row: this.DraggableBodyRow,
},
}}
/>
{
/* <SortableTaskContainer
/> */
}
<
SortableTaskContainer
useDragHandle
disableAutoscroll
helperClass=
"row-dragging"
...
...
@@ -440,9 +512,9 @@ class TrainingTask extends React.Component {
<
SortableTaskItem
taskItem=
{
this
.
renderTaskItem
(
item
,
index
)
}
index=
{
index
}
>
</
SortableTaskItem
>
)
}
</SortableTaskContainer>
*/
}
</
SortableTaskContainer
>
<
div
><
Button
onClick=
{
()
=>
this
.
addTask
()
}
><
span
>
+
</
span
><
span
>
添加任务
</
span
></
Butto
n
></
div
>
<
div
className=
"add-task-con"
><
span
className=
"add-task-btn"
onClick=
{
()
=>
this
.
addTask
()
}
><
span
>
+
</
span
><
span
>
添加任务
</
span
></
spa
n
></
div
>
{
relatedCourseModalVisible
&&
<
RelatedCourseModal
selectedTaskIndex=
{
selectedTaskIndex
}
...
...
src/modules/plan-manage/components/TrainingTask.less
View file @
2c634bc6
...
...
@@ -2,4 +2,110 @@
thead{
display:none;
}
.ant-form-item{
margin-bottom:0 !important;
}
.task-item{
.task-con{
display:flex;
padding:16px;
background: #F7F8F9;
border-radius: 2px;
justify-content: space-between;
align-items: center;
.task-instro{
display:flex;
align-items: center;
.open-icon{
color:#999999;
font-size:10px;
}
.task-name-con{
display:flex;
align-items: center;
color:#333333;
font-size:14px;
.number{
margin-right:10px;
margin-left:10px;
}
.task-name-input{
width: 300px;
height: 32px;
background: #FFFFFF;
border-radius: 4px;
}
}
}
}
.operate{
.operate__item{
cursor:pointer;
margin-left:16px;
color:#666666;
font-size:14px;
.icon{
color:#999;
}
.text{
margin-left:8px;
}
}
}
.course-box{
.course-item{
display:flex;
padding:16px 16px 16px 51px;
justify-content: space-between;
align-items: center;
.course-info{
.ant-form{
display:inline-block;
}
.course-name-input{
margin-right:8px;
}
.course-type{
font-size:11px;
color:#666666;
padding:1px 8px;
border: 1px solid #999999;
margin-right:4px;
border-radius: 2px;
}
.course-name{
color:#666666;
font-size:14px;
margin-right:8px;
}
.tip{
font-size:14px;
color:#FF4F4F;
margin-right:2px;
}
.course-state{
color:#999;
font-size:14px;
}
}
}
.add-course-con{
padding:16px 51px;
color: #5289FA;
font-size:14px;
}
}
}
.add-task-con{
height: 52px;
background: #F7F8F9;
border-radius: 2px;
padding:16px;
margin-top:16px;
.add-task-btn{
color: #5289FA;
font-size:14px;
}
}
}
src/modules/plan-manage/modal/relatedCourseModal.jsx
View file @
2c634bc6
...
...
@@ -295,6 +295,7 @@ class SelectOperatorModal extends React.Component {
_item
.
courseId
=
item
.
id
;
_item
.
courseType
=
"VOICE"
;
_item
.
courseName
=
item
.
courseName
;
return
_item
;
})
}
...
...
@@ -304,6 +305,7 @@ class SelectOperatorModal extends React.Component {
_item
.
courseId
=
item
.
liveCourseId
;
_item
.
courseType
=
"LIVE"
;
_item
.
courseName
=
item
.
courseName
;
_item
.
courseState
=
item
.
courseState
;
return
_item
;
})
}
...
...
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