@ -3,11 +3,11 @@ import { Input, InputNumber, Form, Button, Checkbox, Upload, Icon, message, Moda
import axios from 'axios'
import axios from 'axios'
import '../css/busyWork.css'
import '../css/busyWork.css'
import '../css/Courses.css'
import '../css/Courses.css'
import { WordsBtn , getUrl , ConditionToolTip } from 'educoder'
import { WordsBtn , getUrl , ConditionToolTip , appendFileSizeToUploadFile , appendFileSizeToUploadFileAll } from 'educoder'
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor' ;
import CBreadcrumb from '../common/CBreadcrumb'
import CBreadcrumb from '../common/CBreadcrumb'
import NewWorkForm from './NewWorkForm'
const confirm = Modal . confirm ;
const $ = window . $
const $ = window . $
const MAX _TITLE _LENGTH = 60 ;
const MAX _TITLE _LENGTH = 60 ;
class NewWork extends Component {
class NewWork extends Component {
@ -17,6 +17,15 @@ class NewWork extends Component{
this . answerMdRef = React . createRef ( ) ;
this . answerMdRef = React . createRef ( ) ;
this . state = {
this . state = {
title _value : "" ,
title _num : 0 ,
contentFileList : [ ] ,
answerFileList : [ ] ,
workLoaded : false ,
base _on _project : true ,
category : { } ,
min _num : 2 ,
max _num : 10 ,
}
}
}
}
componentDidMount ( ) {
componentDidMount ( ) {
@ -41,6 +50,7 @@ class NewWork extends Component{
course _id : data . course _id ,
course _id : data . course _id ,
course _name : data . course _name ,
course _name : data . course _name ,
category : data . category ,
category : data . category ,
} )
} )
}
}
} )
} )
@ -55,29 +65,129 @@ class NewWork extends Component{
. then ( ( response ) => {
. then ( ( response ) => {
if ( response . data . name ) {
if ( response . data . name ) {
const data = response . data ;
const data = response . data ;
data . isEdit = true ;
this . setState ( {
const contentFileList = data . attachments . map ( item => {
category : data . category ,
return {
course _id : data . course _id ,
id : item . id ,
course _name : data . course _name ,
uid : item . id ,
name : appendFileSizeToUploadFile ( item ) ,
url : item . url ,
filesize : item . filesize ,
status : 'done'
}
} )
const answerFileList = data . ref _attachments . map ( item => {
return {
id : item . id ,
uid : item . id ,
name : appendFileSizeToUploadFile ( item ) ,
url : item . url ,
filesize : item . filesize ,
status : 'done'
}
} )
this . setState ( {
... data ,
// course_id: data.course_id,
// course_name: data.course_name,
// category: data.category,
title _num : parseInt ( data . name . length ) ,
workLoaded : true ,
init _min _num : data . min _num ,
init _max _num : data . max _num ,
// description: data.description,
reference _answer : data . reference _answer ,
contentFileList ,
answerFileList ,
} , ( ) => {
setTimeout ( ( ) => {
this . contentMdRef . current . setValue ( data . description || '' )
this . answerMdRef . current . setValue ( data . reference _answer || '' )
} , 2000 )
this . props . form . setFieldsValue ( {
title : data . name ,
description : data . description || '' ,
reference _answer : data . reference _answer || '' ,
} ) ;
} )
} )
this . newWorkFormRef . initValue ( data ) ;
}
}
} )
} )
. catch ( function ( error ) {
. catch ( function ( error ) {
console . log ( error ) ;
console . log ( error ) ;
} ) ;
} ) ;
}
}
onCancel = ( ) => {
this . props . toListPage ( this . props . match . params , category . category _id )
// 输入title
changeTitle = ( e ) => {
console . log ( e . target . value . length ) ;
this . setState ( {
title _num : parseInt ( e . target . value . length )
} )
}
handleSubmit = ( ) => {
const courseId = this . state . course _id || this . props . match . params . coursesId ;
this . props . form . validateFieldsAndScroll ( ( err , values ) => {
console . log ( values )
const mdContnet = this . contentMdRef . current . getValue ( ) . trim ( ) ;
console . log ( mdContnet )
values . description = mdContnet ;
// return;
{ /* max={has_commit ? init_min_num : null } */ }
{ /* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */ }
// 已有提交作品,人数范围只能扩大
const { has _commit , max _num , init _max _num , min _num , init _min _num } = this . state ;
if ( has _commit ) {
if ( max _num < init _max _num || min _num > init _min _num ) {
this . props . showNotification ( ` 已有提交作品,人数范围只能扩大(原设置为: ${ init _min _num } - ${ init _max _num } ) ` )
return ;
}
}
// const errKeys = Object.keys(err); // || errKeys.length == 1 && errKeys[0] == 'content' && mdContnet
if ( ! err ) {
if ( this . isEdit ) {
this . doEdit ( courseId , values )
} else {
this . doNew ( courseId , values )
}
} else {
$ ( "html" ) . animate ( { scrollTop : $ ( 'html' ) . scrollTop ( ) - 100 } )
}
} )
}
}
doEdit = ( courseId , values ) => {
doEdit = ( params ) => {
const workId = this . props . match . params . workId
const workId = this . props . match . params . workId
const newUrl = ` /homework_commons/ ${ workId } .json `
const newUrl = ` /homework_commons/ ${ workId } .json `
let attachment _ids = this . state . contentFileList . map ( item => {
return item . response ? item . response . id : item . id
} )
let reference _attachment _ids = this . state . answerFileList . map ( item => {
return item . response ? item . response . id : item . id
} )
const { min _num , max _num , base _on _project , category } = this . state
const isGroup = this . props . isGroup ( )
const isGroup = this . props . isGroup ( )
axios . put ( newUrl , params )
axios . put ( newUrl , {
type : isGroup ? 3 : 1 ,
name : values . title ,
description : values . description ,
reference _answer : values . reference _answer ,
attachment _ids ,
reference _attachment _ids ,
min _num ,
max _num ,
base _on _project
} )
. then ( ( response ) => {
. then ( ( response ) => {
if ( response . data . status == 0 ) {
if ( response . data . status == 0 ) {
this . props . showNotification ( '保存成功' )
this . props . showNotification ( '保存成功' )
@ -88,11 +198,30 @@ class NewWork extends Component{
console . log ( error ) ;
console . log ( error ) ;
} ) ;
} ) ;
}
}
doNew = ( params ) => {
doNew = ( courseId , values ) => {
const courseId = this . props . match . params . coursesId ;
const newUrl = ` /courses/ ${ courseId } /homework_commons.json `
const newUrl = ` /courses/ ${ courseId } /homework_commons.json `
axios . post ( newUrl , params )
let attachment _ids = this . state . contentFileList . map ( item => {
return item . response ? item . response . id : item . id
} )
let reference _attachment _ids = this . state . answerFileList . map ( item => {
return item . response ? item . response . id : item . id
} )
const isGroup = this . props . isGroup ( )
const { min _num , max _num , base _on _project , category } = this . state
axios . post ( newUrl , {
type : isGroup ? 3 : 1 ,
name : values . title ,
description : values . description ,
reference _answer : values . reference _answer ,
attachment _ids ,
reference _attachment _ids ,
min _num ,
max _num ,
base _on _project
} )
. then ( ( response ) => {
. then ( ( response ) => {
if ( response . data . status == 0 ) {
if ( response . data . status == 0 ) {
this . props . showNotification ( '保存成功' )
this . props . showNotification ( '保存成功' )
@ -103,26 +232,147 @@ class NewWork extends Component{
console . log ( error ) ;
console . log ( error ) ;
} ) ;
} ) ;
}
}
handleContentUploadChange = ( info ) => {
let contentFileList = info . fileList ;
this . setState ( { contentFileList : appendFileSizeToUploadFileAll ( contentFileList ) } ) ;
}
handleAnswerUploadChange = ( info ) => {
let answerFileList = info . fileList ;
this . setState ( { answerFileList : appendFileSizeToUploadFileAll ( answerFileList ) } ) ;
}
onAttachmentRemove = ( file , stateName ) => {
if ( file . response != undefined ) {
this . props . confirm ( {
content : '是否确认删除?' ,
onOk : ( ) => {
this . deleteAttachment ( file , stateName )
} ,
onCancel ( ) {
console . log ( 'Cancel' ) ;
} ,
} ) ;
return false ;
}
}
deleteAttachment = ( file , stateName ) => {
// 初次上传不能直接取uid
const url = ` /attachments/ ${ file . response ? file . response . id : file . uid } .json `
axios . delete ( url , {
} )
. then ( ( response ) => {
if ( response . data ) {
const { status } = response . data ;
if ( status == 0 ) {
console . log ( '--- success' )
this . setState ( ( state ) => {
const index = state [ stateName ] . indexOf ( file ) ;
const newFileList = state [ stateName ] . slice ( ) ;
newFileList . splice ( index , 1 ) ;
return {
[ stateName ] : newFileList ,
} ;
} ) ;
}
}
} )
. catch ( function ( error ) {
console . log ( error ) ;
} ) ;
}
max _num _change = ( val ) => {
if ( val < 2 ) {
this . setState ( {
max _num : 2 ,
} )
return ;
}
const { min _num } = this . state ;
this . setState ( {
max _num : val ,
min _num : val <= min _num ? val - 1 : min _num
} )
}
min _num _change = ( val ) => {
this . setState ( { min _num : val } )
}
base _on _project _change = ( ) => {
this . setState ( { base _on _project : ! this . state . base _on _project } )
}
render ( ) {
render ( ) {
let { typeId , coursesId , pageType } = this . props . match . params ;
let { typeId , coursesId , pageType } = this . props . match . params ;
const { getFieldDecorator } = this . props . form ;
const isGroup = this . props . isGroup ( )
const isGroup = this . props . isGroup ( )
const moduleName = ! isGroup ? "普通作业" : "分组作业" ;
const moduleName = ! isGroup ? "普通作业" : "分组作业" ;
const moduleEngName = this . props . getModuleName ( )
const moduleEngName = this . props . getModuleName ( )
let {
let {
category
title _value , contentFileList , answerFileList , max _num , min _num , base _on _project ,
init _max _num , init _min _num ,
title _num , course _name , category , has _commit , has _project
} = this . state
} = this . state
const { current _user } = this . props
const { current _user } = this . props
const courseId = this . props . match . params . coursesId ;
const courseId = this . state. course _id || this . props. match . params . coursesId ;
const isEdit = this . isEdit ;
const isEdit = this . isEdit ;
if ( ( isEdit == undefined || isEdit ) && ! this . state . workLoaded ) {
return ''
}
const uploadProps = {
width : 600 ,
fileList : contentFileList ,
multiple : true ,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action : ` ${ getUrl ( ) } /api/attachments.json ` ,
onChange : this . handleContentUploadChange ,
onRemove : ( file ) => this . onAttachmentRemove ( file , 'contentFileList' ) ,
beforeUpload : ( file ) => {
console . log ( 'beforeUpload' , file . name ) ;
const isLt150M = file . size / 1024 / 1024 < 150 ;
if ( ! isLt150M ) {
this . props . showNotification ( '文件大小必须小于150MB!' ) ;
}
return isLt150M ;
} ,
} ;
const answerUploadProps = {
width : 600 ,
fileList : answerFileList ,
multiple : true ,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action : ` ${ getUrl ( ) } /api/attachments.json ` ,
onChange : this . handleAnswerUploadChange ,
onRemove : ( file ) => this . onAttachmentRemove ( file , 'answerFileList' ) ,
beforeUpload : ( file ) => {
console . log ( 'beforeUpload' , file . name ) ;
const isLt150M = file . size / 1024 / 1024 < 150 ;
if ( ! isLt150M ) {
this . props . showNotification ( '文件大小必须小于150MB!' ) ;
}
return isLt150M ;
} ,
} ;
return (
return (
< div className = "newMain" >
< div className = "newMain" >
< div className = "educontent mt20 mb50" >
< div className = "educontent mt20 mb50" >
{ / * < p c l a s s N a m e = " c l e a r f i x " >
< WordsBtn style = "grey" className = "fl" > { course _name } < / W o r d s B t n >
< span className = "color-grey-9 fl ml3 mr3" > & gt ; < / s p a n >
< WordsBtn style = "grey" className = "fl" > { typeId == 1 ? "普通作业" : "分组作业" } < / W o r d s B t n >
< span className = "color-grey-9 fl ml3 mr3" > & gt ; < / s p a n >
< span > { pageType === "new" ? "新建" : "编辑" } < / s p a n >
< /p> */ }
< CBreadcrumb items = { [
< CBreadcrumb items = { [
{ to : current _user && current _user . first _category _url , name : this . state . course _name } ,
{ to : current _user && current _user . first _category _url , name : this . state . course _name } ,
{ to : ` /courses/ ${ courseId } / ${ moduleEngName } / ${ category && category . category _id ? category . category _id : '' } `
{ to : ` /courses/ ${ courseId } / ${ moduleEngName } / ${ category && category . category _id ? category . category _id : '' } `
@ -141,16 +391,161 @@ class NewWork extends Component{
< / a >
< / a >
< / p >
< / p >
< div >
< div >
< NewWorkForm wrappedComponentRef = { ( ref ) => { this . newWorkFormRef = ref } }
{ /* onSubmit={this.handleSubmit} */ }
{ ... this . props }
< style >
onCancel = { this . onCancel }
{
doNew = { this . doNew }
`
doEdit = { this . doEdit }
. yslnewworkinputaddonAfter . ant - input {
> < / N e w W o r k F o r m >
border - right : none ! important ;
height : 40 px ! important ;
}
`
}
< / s t y l e >
< Form className = "courseForm" >
< Form . Item
label = "标题"
className = "AboutInputForm"
>
{ getFieldDecorator ( 'title' , {
rules : [ {
required : true , message : '请输入标题'
} ] ,
} ) (
< Input placeholder = "请输入作业标题, 最大限制60个字符" onInput = { this . changeTitle } className = "searchView yslnewworkinputaddonAfter searchViewAfter" style = { { "width" : "100%" } } maxLength = { MAX _TITLE _LENGTH } addonAfter = { ` ${ String ( title _num ) } / ${ MAX _TITLE _LENGTH } ` } / >
) }
< / F o r m . I t e m >
< style > { `
. uploadBtn . ant - btn {
border : none ;
color : # 4 CACFF ;
box - shadow : none ;
background : transparent ;
padding : 0 6 px ;
}
. ant - upload - list - item : hover . ant - upload - list - item - info {
background - color : # fff ;
}
. upload _1 . ant - upload - list {
width : 350 px ;
}
. ant - input - number {
height : 40 px ;
line - height : 40 px ;
}
. workContent . AboutInputForm . ant - form - item {
border - bottom : none ;
padding - bottom : 0 px ! important ;
}
. newWorkUpload {
padding : 0 px 30 px 30 px 30 px ! important ;
background : # fff ;
width : 100 % ;
display : inline - block ;
border - bottom : 1 px solid # EDEDED ;
}
` }</style>
{ < Form . Item
label = "内容"
className = "AboutInputForm workContent mdInForm"
>
{ getFieldDecorator ( 'description' , {
rules : [ {
required : true , message : '请输入作业内容和要求'
} ] ,
} ) (
< TPMMDEditor ref = { this . contentMdRef } placeholder = "请在此输入作业内容和要求,最大限制5000个字符" mdID = { 'courseContentMD' } refreshTimeout = { 1500 }
className = "courseMessageMD" initValue = { this . state . description } > < / T P M M D E d i t o r >
) }
< / F o r m . I t e m > }
< Upload { ... uploadProps } className = "upload_1 newWorkUpload" >
< Button className = "uploadBtn" >
< Icon type = "upload" / > 上传附件
< / B u t t o n >
( 单个文件150M以内 )
< / U p l o a d >
{ isGroup &&
< Form . Item
label = "分组设置"
className = "AboutInputForm"
>
{ getFieldDecorator ( 'personNum' , {
rules : [ {
required : false
// required: true, message: '请输入最小人数和最大人数'
} ] ,
} ) (
< div >
< p className = "clearfix" >
< ConditionToolTip condition = { has _commit } title = { '已有提交作品,人数范围只能扩大' } >
{ /* max={has_commit ? init_min_num : null } */ }
< InputNumber placeholder = "请填写每组最小人数" min = { 1 } className = "winput-240-40" value = { min _num }
onChange = { this . min _num _change } style = { { width : '180px' } } / >
< / C o n d i t i o n T o o l T i p >
< span className = "ml15 mr15" > ~ < / s p a n >
{ /* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */ }
< ConditionToolTip condition = { has _commit } title = { '已有提交作品,人数范围只能扩大' } >
< InputNumber className = "winput-240-40" placeholder = "请填写每组最大人数" value = { max _num } max = { 10 }
onChange = { this . max _num _change } style = { { width : '180px' } } / >
< / C o n d i t i o n T o o l T i p >
< label className = "color-grey-9 ml20 font-14" > ( 项目管理员角色的成员都可以提交作品 , 提交作品时需要关联同组成员 , 组内成员作品共享 ) < / l a b e l >
< / p >
< p className = "mt20" >
< ConditionToolTip condition = { has _commit || has _project } title = { '已有关联项目或作品,不能修改' } >
< Checkbox checked = { base _on _project } onChange = { this . base _on _project _change }
disabled = { has _project || has _commit }
> 基于项目实施 < / C h e c k b o x >
< / C o n d i t i o n T o o l T i p >
< label className = "color-grey-9 ml12 font-14" > ( 勾选后各小组必须在educoder平台创建项目 , 教师可随时观察平台对各小组最新进展的实时统计 ) < / l a b e l >
< / p >
< / d i v >
) }
< / F o r m . I t e m >
}
< Form . Item
label = "参考答案"
className = "AboutInputForm"
style = { { "borderBottom" : "none" } }
>
{ getFieldDecorator ( 'reference_answer' , {
rules : [ {
required : false
} ] ,
} ) (
< TPMMDEditor ref = { this . answerMdRef } placeholder = "请在此输入作业的参考答案,最大限制5000个字符" mdID = { 'workAnswerMD' }
className = "courseMessageMD" refreshTimeout = { 1500 } initValue = { this . state . reference _answer || '' } > < / T P M M D E d i t o r >
) }
< Upload { ... answerUploadProps } className = "upload_1" >
< Button className = "uploadBtn" >
< Icon type = "upload" / > 上传附件
< / B u t t o n >
( 单个文件150M以内 )
< / U p l o a d >
< / F o r m . I t e m >
< Form . Item >
< div className = "clearfix mt30 mb30" >
{ /* htmlType="submit" */ }
< Button type = "primary" onClick = { this . handleSubmit } className = "defalutSubmitbtn fl mr20" > 提交 < / B u t t o n >
< a className = "defalutCancelbtn fl" onClick = { ( ) => this . props . toListPage ( this . props . match . params , category . category _id ) } > 取消 < / a >
< / d i v >
< / F o r m . I t e m >
< / F o r m >
< / d i v >
< / d i v >
< / d i v >
< / d i v >
< / d i v >
< / d i v >
)
)
}
}
}
}
export default NewWork ;
const WrappedBoardsNew = Form . create ( { name : 'NewWork' } ) ( NewWork ) ;
export default WrappedBoardsNew ;