|
|
|
@ -1,449 +1,449 @@
|
|
|
|
|
import React,{ Component } from "react";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
Form, Input, InputNumber, Switch, Radio,
|
|
|
|
|
Slider, Button, Upload, Icon, Rate, Checkbox, message,
|
|
|
|
|
Row, Col, Select, Modal, Divider
|
|
|
|
|
} from 'antd';
|
|
|
|
|
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
|
|
|
|
import axios from 'axios'
|
|
|
|
|
import './board.css'
|
|
|
|
|
import "../common/formCommon.css"
|
|
|
|
|
import AddDirModal from './AddDirModal'
|
|
|
|
|
import { RouteHOC } from './common.js'
|
|
|
|
|
import CBreadcrumb from '../common/CBreadcrumb'
|
|
|
|
|
import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder';
|
|
|
|
|
|
|
|
|
|
const confirm = Modal.confirm;
|
|
|
|
|
const $ = window.$
|
|
|
|
|
const { Option } = Select;
|
|
|
|
|
// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
|
|
|
|
|
class BoardsNew extends Component{
|
|
|
|
|
constructor(props){
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
this.mdRef = React.createRef();
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
fileList: [],
|
|
|
|
|
boards: [],
|
|
|
|
|
title_num: 60
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
addSuccess = () => {
|
|
|
|
|
this.fetchBoards()
|
|
|
|
|
}
|
|
|
|
|
fetchBoards = () => {
|
|
|
|
|
const isEdit = this.isEdit
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
|
|
|
|
|
axios.get(boardsUrl, { })
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
this.setState({
|
|
|
|
|
boards: response.data.data.boards || [],
|
|
|
|
|
course_id: response.data.data.course_id
|
|
|
|
|
})
|
|
|
|
|
if (!isEdit) {
|
|
|
|
|
response.data.data.boards.forEach( board => {
|
|
|
|
|
if (board.id == boardId) {
|
|
|
|
|
this.setState({ board_name: board.name })
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
// board_name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
componentDidMount = () => {
|
|
|
|
|
|
|
|
|
|
const topicId = this.props.match.params.topicId
|
|
|
|
|
const isEdit = !!topicId
|
|
|
|
|
this.isEdit = isEdit
|
|
|
|
|
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.fetchBoards()
|
|
|
|
|
|
|
|
|
|
if (isEdit) {
|
|
|
|
|
const url = `/messages/${topicId}.json`
|
|
|
|
|
axios.get(url, {
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
const { id, data } = response.data;
|
|
|
|
|
if (data) {
|
|
|
|
|
this.editTopic = data;
|
|
|
|
|
this.props.form.setFieldsValue({
|
|
|
|
|
sticky: !!data.sticky,
|
|
|
|
|
content: data.content,
|
|
|
|
|
subject: data.subject,
|
|
|
|
|
select_board_id: data.board_id // TODO 没返回给前端
|
|
|
|
|
});
|
|
|
|
|
this.mdRef.current.setValue(data.content)
|
|
|
|
|
const _fileList = data.attachments.map(item => {
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
uid: item.id,
|
|
|
|
|
name: appendFileSizeToUploadFile(item),
|
|
|
|
|
url: item.url,
|
|
|
|
|
status: 'done'
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.props.form.setFieldsValue({
|
|
|
|
|
select_board_id: parseInt(boardId)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
handleSubmit = (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
const cid = this.state.course_id
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
console.log('Received values of form: ', values);
|
|
|
|
|
if (this.isEdit == true) {
|
|
|
|
|
const editTopic = this.editTopic
|
|
|
|
|
const editUrl = `/messages/${editTopic.id}.json`
|
|
|
|
|
|
|
|
|
|
let attachment_ids = undefined
|
|
|
|
|
if (this.state.fileList) {
|
|
|
|
|
attachment_ids = this.state.fileList.map(item => {
|
|
|
|
|
return item.response ? item.response.id : item.id
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
axios.put(editUrl, {
|
|
|
|
|
subject: values.subject,
|
|
|
|
|
select_board_id: values.select_board_id,
|
|
|
|
|
content: values.content,
|
|
|
|
|
sticky: values.sticky,
|
|
|
|
|
attachment_ids,
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
const { id } = response.data;
|
|
|
|
|
console.log('--- success')
|
|
|
|
|
|
|
|
|
|
this.props.toDetailPage(cid, values.select_board_id, editTopic.id)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
const url = `/boards/${boardId}/messages.json`
|
|
|
|
|
let attachment_ids = undefined
|
|
|
|
|
if (this.state.fileList) {
|
|
|
|
|
attachment_ids = this.state.fileList.map(item => {
|
|
|
|
|
return item.response.id
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
axios.post(url, {
|
|
|
|
|
...values,
|
|
|
|
|
course_id: cid,
|
|
|
|
|
attachment_ids,
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.data && response.data.status == 0) {
|
|
|
|
|
const { id } = response.data.data;
|
|
|
|
|
if (id) {
|
|
|
|
|
console.log('--- success')
|
|
|
|
|
this.props.toDetailPage(cid, values.select_board_id, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 附件相关 START
|
|
|
|
|
handleChange = (info) => {
|
|
|
|
|
let fileList = info.fileList;
|
|
|
|
|
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
onAttachmentRemove = (file) => {
|
|
|
|
|
confirm({
|
|
|
|
|
// title: '确定要删除这个附件吗?',
|
|
|
|
|
title: '是否确认删除?',
|
|
|
|
|
|
|
|
|
|
okText: '确定',
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
// content: 'Some descriptions',
|
|
|
|
|
onOk: () => {
|
|
|
|
|
this.deleteAttachment(file)
|
|
|
|
|
},
|
|
|
|
|
onCancel() {
|
|
|
|
|
console.log('Cancel');
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
deleteAttachment = (file) => {
|
|
|
|
|
// 初次上传不能直接取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.fileList.indexOf(file);
|
|
|
|
|
const newFileList = state.fileList.slice();
|
|
|
|
|
newFileList.splice(index, 1);
|
|
|
|
|
return {
|
|
|
|
|
fileList: newFileList,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 附件相关 ------------ END
|
|
|
|
|
changeTitle=(e)=>{
|
|
|
|
|
console.log(e.target.value.length);
|
|
|
|
|
this.setState({
|
|
|
|
|
title_num: 60 - parseInt(e.target.value.length)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
render() {
|
|
|
|
|
let { addGroup, fileList, course_id, title_num } = this.state;
|
|
|
|
|
const { getFieldDecorator } = this.props.form;
|
|
|
|
|
const { current_user } = this.props
|
|
|
|
|
|
|
|
|
|
const formItemLayout = {
|
|
|
|
|
labelCol: {
|
|
|
|
|
xs: { span: 24 },
|
|
|
|
|
// sm: { span: 8 },
|
|
|
|
|
sm: { span: 24 },
|
|
|
|
|
},
|
|
|
|
|
wrapperCol: {
|
|
|
|
|
xs: { span: 24 },
|
|
|
|
|
// sm: { span: 16 },
|
|
|
|
|
sm: { span: 24 },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const uploadProps = {
|
|
|
|
|
width: 600,
|
|
|
|
|
fileList,
|
|
|
|
|
multiple: true,
|
|
|
|
|
// https://github.com/ant-design/ant-design/issues/15505
|
|
|
|
|
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
|
|
|
|
// showUploadList: false,
|
|
|
|
|
action: `${getUploadActionUrl()}`,
|
|
|
|
|
onChange: this.handleChange,
|
|
|
|
|
onRemove: this.onAttachmentRemove,
|
|
|
|
|
beforeUpload: (file) => {
|
|
|
|
|
console.log('beforeUpload', file.name);
|
|
|
|
|
const isLt150M = file.size / 1024 / 1024 < 150;
|
|
|
|
|
if (!isLt150M) {
|
|
|
|
|
message.error('文件大小必须小于150MB!');
|
|
|
|
|
}
|
|
|
|
|
return isLt150M;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const isAdmin = this.props.isAdmin()
|
|
|
|
|
const courseId=this.props.match.params.coursesId;
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
return(
|
|
|
|
|
<div className="newMain ">
|
|
|
|
|
<AddDirModal {...this.props}
|
|
|
|
|
title="添加目录"
|
|
|
|
|
label="目录名称"
|
|
|
|
|
ref="addDirModal"
|
|
|
|
|
addSuccess={this.addSuccess}
|
|
|
|
|
></AddDirModal>
|
|
|
|
|
<style>{`
|
|
|
|
|
.courseForm .ant-form {
|
|
|
|
|
}
|
|
|
|
|
.courseForm .formBlock {
|
|
|
|
|
padding: 20px 30px 30px 30px;
|
|
|
|
|
border-bottom: 1px solid #EDEDED;
|
|
|
|
|
margin-bottom: 0px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
}
|
|
|
|
|
.courseForm .noBorder {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
`}</style>
|
|
|
|
|
<div className="edu-class-container edu-position courseForm">
|
|
|
|
|
<CBreadcrumb items={[
|
|
|
|
|
{ to: current_user.first_category_url, name: this.props.coursedata ? this.props.coursedata.name : ''},
|
|
|
|
|
{ to: `/courses/${courseId}/boards/${boardId}`, name: this.state.board_name },
|
|
|
|
|
{ name: this.isEdit ? '帖子编辑' : '帖子新建'}
|
|
|
|
|
]}></CBreadcrumb>
|
|
|
|
|
|
|
|
|
|
<p className="clearfix mt20 mb20">
|
|
|
|
|
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}帖子</span>
|
|
|
|
|
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
|
|
|
|
|
onClick={() => this.props.history.goBack()}>
|
|
|
|
|
返回
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
|
|
|
|
{/* notRequired */}
|
|
|
|
|
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
|
|
|
|
|
<div className="formBlock" style={{paddingBottom: '0px', position: 'relative'}}>
|
|
|
|
|
{ isAdmin &&
|
|
|
|
|
<React.Fragment>
|
|
|
|
|
{getFieldDecorator('sticky', {
|
|
|
|
|
valuePropName: 'checked',
|
|
|
|
|
})(
|
|
|
|
|
isAdmin && <Checkbox style={{ right: '22px',
|
|
|
|
|
top: '28px',
|
|
|
|
|
position: 'absolute'
|
|
|
|
|
}}>置顶</Checkbox>
|
|
|
|
|
)}
|
|
|
|
|
{/* checkbox 有个边距样式 .ant-checkbox-wrapper + span, */}
|
|
|
|
|
<span style={{ "padding-left": 0, "padding-right": 0 }}></span>
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
}
|
|
|
|
|
<Form.Item
|
|
|
|
|
label="标题"
|
|
|
|
|
className="topicTitle "
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
{getFieldDecorator('subject', {
|
|
|
|
|
rules: [{
|
|
|
|
|
required: true, message: '请输入标题',
|
|
|
|
|
}, {
|
|
|
|
|
max: 60, message: '最大限制为60个字符',
|
|
|
|
|
}],
|
|
|
|
|
})(
|
|
|
|
|
<Input placeholder="请输入帖子标题,最大限制60个字符" className="searchViewAfter" maxLength="60"
|
|
|
|
|
onInput={this.changeTitle} addonAfter={String(title_num)} />
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
label=""
|
|
|
|
|
style={{ display: 'inline-block' }}
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('select_board_id', {
|
|
|
|
|
// initialValue: '3779',
|
|
|
|
|
})(
|
|
|
|
|
<Select style={{ width: 230 }}
|
|
|
|
|
dropdownRender={menu => (
|
|
|
|
|
<div>
|
|
|
|
|
{menu}
|
|
|
|
|
<Divider style={{ margin: '4px 0' }} />
|
|
|
|
|
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
|
|
|
|
|
<Icon type="plus" /> 添加目录
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
{this.state.boards.map(item => {
|
|
|
|
|
return (
|
|
|
|
|
<Option value={item.id}>{item.name}</Option>
|
|
|
|
|
)
|
|
|
|
|
})}
|
|
|
|
|
</Select>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
{/* { isAdmin && <Form.Item
|
|
|
|
|
label=""
|
|
|
|
|
style={{ display: 'inline-block', marginLeft: "14px" }}
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('sticky', {
|
|
|
|
|
})(
|
|
|
|
|
<Checkbox>置顶</Checkbox>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item> } */}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<style>{`
|
|
|
|
|
.courseMessageMD {
|
|
|
|
|
width: 1140px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.uploadBtn.ant-btn {
|
|
|
|
|
border: none;
|
|
|
|
|
color: #4CACFF;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
padding: 0 6px;
|
|
|
|
|
}
|
|
|
|
|
.upload_1 .ant-upload-list {
|
|
|
|
|
width: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
`}</style>
|
|
|
|
|
|
|
|
|
|
<div className="formBlock noBorder">
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
label="内容"
|
|
|
|
|
className="mdInForm"
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('content', {
|
|
|
|
|
rules: [{
|
|
|
|
|
required: true, message: '请输入帖子内容',
|
|
|
|
|
}, {
|
|
|
|
|
max: 10000, message: '最大限制为10000个字符',
|
|
|
|
|
}],
|
|
|
|
|
})(
|
|
|
|
|
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入帖子详情,最大限制为10000个字符'}
|
|
|
|
|
mdID={'courseMessageMD'} initValue={this.editTopic ? this.editTopic.content : ''} className="courseMessageMD"></TPMMDEditor>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Upload {...uploadProps} className="upload_1">
|
|
|
|
|
<Button className="uploadBtn">
|
|
|
|
|
<Icon type="upload" /> 上传附件
|
|
|
|
|
</Button>
|
|
|
|
|
(单个文件150M以内)
|
|
|
|
|
</Upload>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<div className="clearfix mt30 mb30">
|
|
|
|
|
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">提交</Button>
|
|
|
|
|
<a className="defalutCancelbtn fl"
|
|
|
|
|
onClick={() => this.isEdit ?
|
|
|
|
|
this.props.toDetailPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) :
|
|
|
|
|
this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) }>取消</ a>
|
|
|
|
|
</div>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
|
|
|
|
|
import React,{ Component } from "react";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
Form, Input, InputNumber, Switch, Radio,
|
|
|
|
|
Slider, Button, Upload, Icon, Rate, Checkbox, message,
|
|
|
|
|
Row, Col, Select, Modal, Divider
|
|
|
|
|
} from 'antd';
|
|
|
|
|
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
|
|
|
|
import axios from 'axios'
|
|
|
|
|
import './board.css'
|
|
|
|
|
import "../common/formCommon.css"
|
|
|
|
|
import AddDirModal from './AddDirModal'
|
|
|
|
|
import { RouteHOC } from './common.js'
|
|
|
|
|
import CBreadcrumb from '../common/CBreadcrumb'
|
|
|
|
|
import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder';
|
|
|
|
|
|
|
|
|
|
const confirm = Modal.confirm;
|
|
|
|
|
const $ = window.$
|
|
|
|
|
const { Option } = Select;
|
|
|
|
|
// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
|
|
|
|
|
class BoardsNew extends Component{
|
|
|
|
|
constructor(props){
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
this.mdRef = React.createRef();
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
fileList: [],
|
|
|
|
|
boards: [],
|
|
|
|
|
title_num: 60
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
addSuccess = () => {
|
|
|
|
|
this.fetchBoards()
|
|
|
|
|
}
|
|
|
|
|
fetchBoards = () => {
|
|
|
|
|
const isEdit = this.isEdit
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
|
|
|
|
|
axios.get(boardsUrl, { })
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
this.setState({
|
|
|
|
|
boards: response.data.data.boards || [],
|
|
|
|
|
course_id: response.data.data.course_id
|
|
|
|
|
})
|
|
|
|
|
if (!isEdit) {
|
|
|
|
|
response.data.data.boards.forEach( board => {
|
|
|
|
|
if (board.id == boardId) {
|
|
|
|
|
this.setState({ board_name: board.name })
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
// board_name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
componentDidMount = () => {
|
|
|
|
|
|
|
|
|
|
const topicId = this.props.match.params.topicId
|
|
|
|
|
const isEdit = !!topicId
|
|
|
|
|
this.isEdit = isEdit
|
|
|
|
|
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.fetchBoards()
|
|
|
|
|
|
|
|
|
|
if (isEdit) {
|
|
|
|
|
const url = `/messages/${topicId}.json`
|
|
|
|
|
axios.get(url, {
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
const { id, data } = response.data;
|
|
|
|
|
if (data) {
|
|
|
|
|
this.editTopic = data;
|
|
|
|
|
this.props.form.setFieldsValue({
|
|
|
|
|
sticky: !!data.sticky,
|
|
|
|
|
content: data.content,
|
|
|
|
|
subject: data.subject,
|
|
|
|
|
select_board_id: data.board_id // TODO 没返回给前端
|
|
|
|
|
});
|
|
|
|
|
this.mdRef.current.setValue(data.content)
|
|
|
|
|
const _fileList = data.attachments.map(item => {
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
uid: item.id,
|
|
|
|
|
name: appendFileSizeToUploadFile(item),
|
|
|
|
|
url: item.url,
|
|
|
|
|
status: 'done'
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.props.form.setFieldsValue({
|
|
|
|
|
select_board_id: parseInt(boardId)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
handleSubmit = (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
const cid = this.state.course_id
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
console.log('Received values of form: ', values);
|
|
|
|
|
if (this.isEdit == true) {
|
|
|
|
|
const editTopic = this.editTopic
|
|
|
|
|
const editUrl = `/messages/${editTopic.id}.json`
|
|
|
|
|
|
|
|
|
|
let attachment_ids = undefined
|
|
|
|
|
if (this.state.fileList) {
|
|
|
|
|
attachment_ids = this.state.fileList.map(item => {
|
|
|
|
|
return item.response ? item.response.id : item.id
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
axios.put(editUrl, {
|
|
|
|
|
subject: values.subject,
|
|
|
|
|
select_board_id: values.select_board_id,
|
|
|
|
|
content: values.content,
|
|
|
|
|
sticky: values.sticky,
|
|
|
|
|
attachment_ids,
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.status == 0) {
|
|
|
|
|
const { id } = response.data;
|
|
|
|
|
console.log('--- success')
|
|
|
|
|
|
|
|
|
|
this.props.toDetailPage(cid, values.select_board_id, editTopic.id)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
const url = `/boards/${boardId}/messages.json`
|
|
|
|
|
let attachment_ids = undefined
|
|
|
|
|
if (this.state.fileList) {
|
|
|
|
|
attachment_ids = this.state.fileList.map(item => {
|
|
|
|
|
return item.response.id
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
axios.post(url, {
|
|
|
|
|
...values,
|
|
|
|
|
course_id: cid,
|
|
|
|
|
attachment_ids,
|
|
|
|
|
})
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response.data.data && response.data.status == 0) {
|
|
|
|
|
const { id } = response.data.data;
|
|
|
|
|
if (id) {
|
|
|
|
|
console.log('--- success')
|
|
|
|
|
this.props.toDetailPage(cid, values.select_board_id, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 附件相关 START
|
|
|
|
|
handleChange = (info) => {
|
|
|
|
|
let fileList = info.fileList;
|
|
|
|
|
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
onAttachmentRemove = (file) => {
|
|
|
|
|
confirm({
|
|
|
|
|
// title: '确定要删除这个附件吗?',
|
|
|
|
|
title: '是否确认删除?',
|
|
|
|
|
|
|
|
|
|
okText: '确定',
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
// content: 'Some descriptions',
|
|
|
|
|
onOk: () => {
|
|
|
|
|
this.deleteAttachment(file)
|
|
|
|
|
},
|
|
|
|
|
onCancel() {
|
|
|
|
|
console.log('Cancel');
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
deleteAttachment = (file) => {
|
|
|
|
|
// 初次上传不能直接取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.fileList.indexOf(file);
|
|
|
|
|
const newFileList = state.fileList.slice();
|
|
|
|
|
newFileList.splice(index, 1);
|
|
|
|
|
return {
|
|
|
|
|
fileList: newFileList,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(function (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 附件相关 ------------ END
|
|
|
|
|
changeTitle=(e)=>{
|
|
|
|
|
console.log(e.target.value.length);
|
|
|
|
|
this.setState({
|
|
|
|
|
title_num: 60 - parseInt(e.target.value.length)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
render() {
|
|
|
|
|
let { addGroup, fileList, course_id, title_num } = this.state;
|
|
|
|
|
const { getFieldDecorator } = this.props.form;
|
|
|
|
|
const { current_user } = this.props
|
|
|
|
|
|
|
|
|
|
const formItemLayout = {
|
|
|
|
|
labelCol: {
|
|
|
|
|
xs: { span: 24 },
|
|
|
|
|
// sm: { span: 8 },
|
|
|
|
|
sm: { span: 24 },
|
|
|
|
|
},
|
|
|
|
|
wrapperCol: {
|
|
|
|
|
xs: { span: 24 },
|
|
|
|
|
// sm: { span: 16 },
|
|
|
|
|
sm: { span: 24 },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const uploadProps = {
|
|
|
|
|
width: 600,
|
|
|
|
|
fileList,
|
|
|
|
|
multiple: true,
|
|
|
|
|
// https://github.com/ant-design/ant-design/issues/15505
|
|
|
|
|
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
|
|
|
|
// showUploadList: false,
|
|
|
|
|
action: `${getUploadActionUrl()}`,
|
|
|
|
|
onChange: this.handleChange,
|
|
|
|
|
onRemove: this.onAttachmentRemove,
|
|
|
|
|
beforeUpload: (file) => {
|
|
|
|
|
console.log('beforeUpload', file.name);
|
|
|
|
|
const isLt150M = file.size / 1024 / 1024 < 150;
|
|
|
|
|
if (!isLt150M) {
|
|
|
|
|
message.error('文件大小必须小于150MB!');
|
|
|
|
|
}
|
|
|
|
|
return isLt150M;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const isAdmin = this.props.isAdmin()
|
|
|
|
|
const courseId=this.props.match.params.coursesId;
|
|
|
|
|
const boardId = this.props.match.params.boardId
|
|
|
|
|
|
|
|
|
|
return(
|
|
|
|
|
<div className="newMain ">
|
|
|
|
|
<AddDirModal {...this.props}
|
|
|
|
|
title="添加目录"
|
|
|
|
|
label="目录名称"
|
|
|
|
|
ref="addDirModal"
|
|
|
|
|
addSuccess={this.addSuccess}
|
|
|
|
|
></AddDirModal>
|
|
|
|
|
<style>{`
|
|
|
|
|
.courseForm .ant-form {
|
|
|
|
|
}
|
|
|
|
|
.courseForm .formBlock {
|
|
|
|
|
padding: 20px 30px 30px 30px;
|
|
|
|
|
border-bottom: 1px solid #EDEDED;
|
|
|
|
|
margin-bottom: 0px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
}
|
|
|
|
|
.courseForm .noBorder {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
`}</style>
|
|
|
|
|
<div className="edu-class-container edu-position courseForm">
|
|
|
|
|
<CBreadcrumb items={[
|
|
|
|
|
{ to: current_user&¤t_user.first_category_url, name: this.props.coursedata ? this.props.coursedata.name : ''},
|
|
|
|
|
{ to: `/courses/${courseId}/boards/${boardId}`, name: this.state.board_name },
|
|
|
|
|
{ name: this.isEdit ? '帖子编辑' : '帖子新建'}
|
|
|
|
|
]}></CBreadcrumb>
|
|
|
|
|
|
|
|
|
|
<p className="clearfix mt20 mb20">
|
|
|
|
|
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}帖子</span>
|
|
|
|
|
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
|
|
|
|
|
onClick={() => this.props.history.goBack()}>
|
|
|
|
|
返回
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
|
|
|
|
{/* notRequired */}
|
|
|
|
|
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
|
|
|
|
|
<div className="formBlock" style={{paddingBottom: '0px', position: 'relative'}}>
|
|
|
|
|
{ isAdmin &&
|
|
|
|
|
<React.Fragment>
|
|
|
|
|
{getFieldDecorator('sticky', {
|
|
|
|
|
valuePropName: 'checked',
|
|
|
|
|
})(
|
|
|
|
|
isAdmin && <Checkbox style={{ right: '22px',
|
|
|
|
|
top: '28px',
|
|
|
|
|
position: 'absolute'
|
|
|
|
|
}}>置顶</Checkbox>
|
|
|
|
|
)}
|
|
|
|
|
{/* checkbox 有个边距样式 .ant-checkbox-wrapper + span, */}
|
|
|
|
|
<span style={{ "padding-left": 0, "padding-right": 0 }}></span>
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
}
|
|
|
|
|
<Form.Item
|
|
|
|
|
label="标题"
|
|
|
|
|
className="topicTitle "
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
{getFieldDecorator('subject', {
|
|
|
|
|
rules: [{
|
|
|
|
|
required: true, message: '请输入标题',
|
|
|
|
|
}, {
|
|
|
|
|
max: 60, message: '最大限制为60个字符',
|
|
|
|
|
}],
|
|
|
|
|
})(
|
|
|
|
|
<Input placeholder="请输入帖子标题,最大限制60个字符" className="searchViewAfter" maxLength="60"
|
|
|
|
|
onInput={this.changeTitle} addonAfter={String(title_num)} />
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
label=""
|
|
|
|
|
style={{ display: 'inline-block' }}
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('select_board_id', {
|
|
|
|
|
// initialValue: '3779',
|
|
|
|
|
})(
|
|
|
|
|
<Select style={{ width: 230 }}
|
|
|
|
|
dropdownRender={menu => (
|
|
|
|
|
<div>
|
|
|
|
|
{menu}
|
|
|
|
|
<Divider style={{ margin: '4px 0' }} />
|
|
|
|
|
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
|
|
|
|
|
<Icon type="plus" /> 添加目录
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
{this.state.boards.map(item => {
|
|
|
|
|
return (
|
|
|
|
|
<Option value={item.id}>{item.name}</Option>
|
|
|
|
|
)
|
|
|
|
|
})}
|
|
|
|
|
</Select>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
{/* { isAdmin && <Form.Item
|
|
|
|
|
label=""
|
|
|
|
|
style={{ display: 'inline-block', marginLeft: "14px" }}
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('sticky', {
|
|
|
|
|
})(
|
|
|
|
|
<Checkbox>置顶</Checkbox>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item> } */}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<style>{`
|
|
|
|
|
.courseMessageMD {
|
|
|
|
|
width: 1140px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.uploadBtn.ant-btn {
|
|
|
|
|
border: none;
|
|
|
|
|
color: #4CACFF;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
padding: 0 6px;
|
|
|
|
|
}
|
|
|
|
|
.upload_1 .ant-upload-list {
|
|
|
|
|
width: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
`}</style>
|
|
|
|
|
|
|
|
|
|
<div className="formBlock noBorder">
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
label="内容"
|
|
|
|
|
className="mdInForm"
|
|
|
|
|
>
|
|
|
|
|
{getFieldDecorator('content', {
|
|
|
|
|
rules: [{
|
|
|
|
|
required: true, message: '请输入帖子内容',
|
|
|
|
|
}, {
|
|
|
|
|
max: 10000, message: '最大限制为10000个字符',
|
|
|
|
|
}],
|
|
|
|
|
})(
|
|
|
|
|
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入帖子详情,最大限制为10000个字符'}
|
|
|
|
|
mdID={'courseMessageMD'} initValue={this.editTopic ? this.editTopic.content : ''} className="courseMessageMD"></TPMMDEditor>
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Upload {...uploadProps} className="upload_1">
|
|
|
|
|
<Button className="uploadBtn">
|
|
|
|
|
<Icon type="upload" /> 上传附件
|
|
|
|
|
</Button>
|
|
|
|
|
(单个文件150M以内)
|
|
|
|
|
</Upload>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<div className="clearfix mt30 mb30">
|
|
|
|
|
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">提交</Button>
|
|
|
|
|
<a className="defalutCancelbtn fl"
|
|
|
|
|
onClick={() => this.isEdit ?
|
|
|
|
|
this.props.toDetailPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) :
|
|
|
|
|
this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) }>取消</ a>
|
|
|
|
|
</div>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
|
|
|
|
|
export default RouteHOC()(WrappedBoardsNew);
|