+
+ {
+ total && total > limit ?
+ :""
+ }
+
+
+
+
+ )
+ }
+}
+export default AddModeratorModal;
\ No newline at end of file
diff --git a/src/exchange/Manage/CheckPublic.js b/src/exchange/Manage/CheckPublic.js
new file mode 100644
index 000000000..a10b008e0
--- /dev/null
+++ b/src/exchange/Manage/CheckPublic.js
@@ -0,0 +1,54 @@
+import React, { Component } from 'react';
+
+
+import MenuWraps from '../MenuComponent/Menu';
+import SendItem from './SubSendItem';
+import CheckItem from './SubCheckItem'
+import CheckReplyItem from './SubCheckReplyItem'
+
+const menu_nav = [
+ {
+ name:"待审查帖子",
+ key:`checkPost`,
+ content:CheckItem
+ },
+ {
+ name:"待审查回复",
+ key:`checkReply`,
+ content:CheckReplyItem
+ },
+ {
+ name:"已发布的帖子",
+ key:`sendPost`,
+ content:SendItem
+ }
+]
+class CheckPublic extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ activeKey:undefined
+ }
+ }
+ changeTab=(activeKey)=>{
+ this.setState({
+ activeKey
+ })
+ }
+
+ render(){
+ return(
+
+
+
+ )
+ }
+}
+
+export default CheckPublic;
\ No newline at end of file
diff --git a/src/exchange/Manage/ItemLeft.js b/src/exchange/Manage/ItemLeft.js
new file mode 100644
index 000000000..dd693e133
--- /dev/null
+++ b/src/exchange/Manage/ItemLeft.js
@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import {Link} from 'react-router-dom';
+import { getImageUrl } from 'educoder';
+import RenderHtml from "../../components/render-html";
+
+import Customers from '../CustomComponent/Index'
+import "./manage.css"
+
+class ItemLeft extends Component {
+
+ render(){
+ // user_url,username , time , image_url :用户链接,用户名,时间,头像,
+ // memo_title , forum_title(待审查帖子以及已发布帖子:帖子名称,发表的论坛名)
+ // source_title , reply_content(待审查回复:帖子来源,回复内容)
+ //memo_id,forum_id,source_id( 待审查帖子id,发表在版块id,来源版块id)
+ const {user_url,id, memo_id,username , time , image_url , memo_title , forum_title ,source_title , reply_content,forum_id,source_id} = this.props;
+ const title_Url= id || memo_id;
+ return(
+
+
+
+
+ {time}
+ { forum_title && 发表在 {forum_title} }
+ { source_title && 来源 {source_title} }
+
+ { memo_title &&
{memo_title}
}
+ {
+ reply_content &&
+
+
+
+ }
+
+
+ )
+ }
+}
+
+export default ItemLeft;
\ No newline at end of file
diff --git a/src/exchange/Manage/ModeratorNav.js b/src/exchange/Manage/ModeratorNav.js
new file mode 100644
index 000000000..07dc9f3f9
--- /dev/null
+++ b/src/exchange/Manage/ModeratorNav.js
@@ -0,0 +1,87 @@
+import React, { Component } from 'react';
+import { Dropdown } from 'antd';
+import { Link } from 'react-router-dom';
+import Nav from '../NavComponent/Index';
+
+
+class ModeratorNav extends Component {
+
+ render(){
+ const { current_user , bread_crumb }=this.props;
+
+ const forum_tag = bread_crumb && bread_crumb.forum_tag;
+ const forum = bread_crumb && bread_crumb.forum;
+ // {
+ // name:current_user && current_user.username,
+ // url:`/users/${current_user && current_user.login}`
+ // },
+ const routerMap = [
+ {
+ name: forum && forum.title,
+ url:"/forums"
+ },
+ {
+ url:`/forums/theme/${forum_tag && forum_tag.id}`,
+ name:forum_tag && forum_tag.title
+ },
+ {
+ url:`/forums/theme/${forum_tag && forum_tag.children_bread_crumb && forum_tag.children_bread_crumb.id}`,
+ name:forum_tag && forum_tag.children_bread_crumb && forum_tag.children_bread_crumb.title
+ },{
+ name:"版主管理"
+ }
+ ];
+
+ // 板块导航dropdown显示内容
+ const menu =(item)=> {
+ // console.log("item",item);
+
+ if(item){
+ return(
+
+
+
+ {
+ item.map((i,key)=>{
+ return(- {i.title}
)
+ })
+ }
+
+
+
+ )
+ }
+ }
+
+ const titleFlag = () => {
+ if (forum_tag ) {
+ console.log(forum_tag.children_bread_crumb);
+ if (bread_crumb && bread_crumb.is_children) {
+ return ({forum_tag.children_bread_crumb && forum_tag.children_bread_crumb.title}
)
+ } else {
+
+ return (
+
+ { forum_tag.children_bread_crumb ?
+
+ {forum_tag.title}
+
+ :
+
{forum_tag.title}
+ }
+
+ )
+ }
+ }
+
+ }
+ return(
+
+
+ {titleFlag()}
+
+ )
+ }
+}
+
+export default ModeratorNav;
\ No newline at end of file
diff --git a/src/exchange/Manage/PassItem.js b/src/exchange/Manage/PassItem.js
new file mode 100644
index 000000000..91496e0d7
--- /dev/null
+++ b/src/exchange/Manage/PassItem.js
@@ -0,0 +1,35 @@
+import React, { Component } from 'react';
+
+
+
+import '../exchange.css';
+import './manage.css';
+import axios from 'axios'
+
+
+class PassItem extends Component {
+
+ passEvent=(checked)=>{
+ const { id , refresh ,page } = this.props;
+ const url = `/memos/${id}/memo_hidden`;
+ axios.post(url,{
+ checked
+ }).then((result)=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ refresh(page);
+ }
+ })
+ }
+
+ render(){
+ return(
+
+ this.passEvent(true)}>通过
+ this.passEvent(false)}>不通过
+
+ )
+ }
+}
+
+export default PassItem;
\ No newline at end of file
diff --git a/src/exchange/Manage/PreApplyPlate.js b/src/exchange/Manage/PreApplyPlate.js
new file mode 100644
index 000000000..6c67f1661
--- /dev/null
+++ b/src/exchange/Manage/PreApplyPlate.js
@@ -0,0 +1,122 @@
+import React, { Component } from 'react';
+import { getImageUrl } from 'educoder';
+
+import axios from 'axios';
+import './manage.css'
+import { Link } from 'react-router-dom';
+
+class PreApplyPlate extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ applylist:undefined
+ }
+ }
+
+ componentDidMount=()=>{
+ const { plateId } = this.props.match.params;
+ this.getApplyInfo(plateId);
+ }
+
+ getApplyInfo=(id)=>{
+ const url=`/forum_sections/${id}/applied_forums`;
+ axios.get(url).then((result)=>{
+ if(result){
+ this.setState({
+ applylist:result.data.applied_moderators
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ // 通过,拒绝
+ passApplyEvent=(flag,applyId)=>{
+ this.props.confirm({
+ content: `确认${flag?"通过":"拒绝"}版主申请?`,
+
+ onOk: () => {
+ const { plateId } = this.props.match.params;
+
+ const url = `/forum_sections/${plateId}/deal_applies/${applyId}`
+ axios.post(url,{
+ deal_type:flag?1:2
+ }).then((result)=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.getApplyInfo(plateId);
+ }
+ }).catch((error)=>{
+
+ })
+ },
+ onCancel() {
+ console.log('Cancel');
+ }
+ })
+ }
+
+ render(){
+ const { applylist } = this.state;
+ // const applylist = [
+ // {
+ // apply_id: 5,
+ // username: "OpenGCC",
+ // login: "innov",
+ // image_url: "avatars/User/girl.jpg",
+ // user_url: "/users/innov",
+ // user_ip: null,
+ // user_ip_address: "--",
+ // time: "14小时前",
+ // forum_title: "MAC安全",
+ // forum_id: 9,
+ // forum_url: "/memos/forum_memos/9",
+ // parent_forum: {
+ // forum_title: "网络安全网络安全333",
+ // forum_id: 6,
+ // forum_url: "/memos/forum_memos/6"
+ // }
+ // }
+ // ]
+ const listItem= () => {
+ if(applylist && applylist.length > 0){
+ return(
+
+
版主申请
+
+ { applylist.map((item,key)=>{
+ return(
+
+
})
+
+
+ {item.username}
+ { item.user_ip && IP:{item.user_ip}({item.user_ip_address}) }
+
+
申请成为”{item.forum_title}“的版主
+
+
+
{item.time}
+
+ this.passApplyEvent(true,item.apply_id)}>通过
+ this.passApplyEvent(false,item.apply_id)}>拒绝
+
+
+
+ )
+ })
+ }
+
+
+ )
+ }
+ }
+ return(
+
+ {listItem()}
+
+ )
+ }
+}
+export default PreApplyPlate;
\ No newline at end of file
diff --git a/src/exchange/Manage/PreCreate.js b/src/exchange/Manage/PreCreate.js
new file mode 100644
index 000000000..ec133f974
--- /dev/null
+++ b/src/exchange/Manage/PreCreate.js
@@ -0,0 +1,87 @@
+import React, { Component } from 'react';
+
+import { Modal , Form , Input } from 'antd';
+import '../exchange.css';
+import axios from 'axios';
+
+class PreCreate extends Component {
+
+ componentDidUpdate=(preState)=>{
+ const { subId , subName } = this.props;
+ if(preState.subId !== subId){
+ if(subId){
+ this.props.form.setFieldsValue({
+ title:subName
+ })
+ }
+ }
+ }
+
+ // 确定
+ modalSave=()=>{
+ this.props.form.validateFieldsAndScroll((err, values) => {
+ if(!err){
+ // subId存在就是编辑否则就是新增
+ const { refresh , subId } = this.props;
+ const { plateId } = this.props.match.params;
+ const url = `/forum_sections/${plateId}${subId ? "/rename":""}.json`;
+ axios.post(url,{
+ title:values.title,
+ children_section_id:subId
+ }).then((result)=>{
+ if(result){
+ refresh();
+ this.props.showNotification(result.data.message);
+ }
+ }).catch((error)=>{
+
+ })
+ }
+ })
+ }
+ modalCancel=()=>{
+ this.props.close();
+ }
+
+ render(){
+ const { getFieldDecorator } = this.props.form;
+
+ const { title , visible } = this.props
+ return(
+
+
+
+ {getFieldDecorator('title', {
+ rules: [{
+ required: true, message: '请输入板块名称',
+ },{
+ max: 5000 , message:'最大限制20个字符'
+ }],
+ })(
+
+ )}
+
+
+
+
+
+ )
+ }
+}
+const WrappedPreCreate = Form.create({ name: 'PreCreate' })(PreCreate);
+export default WrappedPreCreate;
\ No newline at end of file
diff --git a/src/exchange/Manage/PreModerator.js b/src/exchange/Manage/PreModerator.js
new file mode 100644
index 000000000..f72c4ac32
--- /dev/null
+++ b/src/exchange/Manage/PreModerator.js
@@ -0,0 +1,77 @@
+import React, { Component } from 'react';
+
+import CheckPublic from './CheckPublic'
+import ModeratorNav from './ModeratorNav';
+
+import ApplyPlate from './PreApplyPlate';
+import PrePlateManage from './PrePlateManage'
+import axios from 'axios';
+
+class PreModerator extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ activeKey:undefined,
+ bread_crumb:undefined,
+ is_children:false,
+ }
+ }
+ changeTab=(activeKey)=>{
+ this.setState({
+ activeKey
+ })
+ }
+ componentDidMount=()=>{
+ const { plateId } = this.props.match.params;
+ this.getPlateInfo(plateId);
+ }
+ componentDidUpdate=(prevState)=>{
+ let prePlateId = prevState.match.params.plateId;
+ const { plateId } = this.props.match.params;
+ if(prePlateId !== prePlateId){
+ this.getPlateInfo(plateId);
+ }
+ }
+ getPlateInfo=(plateId)=>{
+ const url = `/forum_sections/${plateId}/forum_section_header`;
+ axios.get(url).then((result)=>{
+ if(result){
+ this.setState({
+ bread_crumb:result.data.bread_crumb,
+ is_children:result.data.bread_crumb && result.data.bread_crumb.is_children
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ render(){
+ const { bread_crumb , is_children } = this.state;
+ const parentManage =()=> {
+ if(!is_children){
+ return(
+
+
+
+ {/* 板块申请 */}
+
+
+ )
+ }
+ }
+ return(
+
+
+
+
+ {parentManage()}
+
+ {/* 审批(二级版主只有这一块) */}
+
+
+ )
+ }
+}
+
+export default PreModerator;
\ No newline at end of file
diff --git a/src/exchange/Manage/PrePlateManage.js b/src/exchange/Manage/PrePlateManage.js
new file mode 100644
index 000000000..0bfbe443a
--- /dev/null
+++ b/src/exchange/Manage/PrePlateManage.js
@@ -0,0 +1,285 @@
+import React, { Component } from 'react';
+import { getImageUrl} from 'educoder';
+import PreCreate from './PreCreate';
+import './manage.css'
+import '../exchange.css'
+import {Link} from 'react-router-dom'
+import axios from 'axios';
+import update from 'immutability-helper'
+
+import AddModeratorModal from './AddModeratorModal'
+
+
+
+class PrePlateManage extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ visible:false,
+ children_tags:undefined,
+ subId:undefined,
+ subName:undefined,
+ // 新增版主有关
+ addVisible:undefined,
+ operationPlateId:undefined
+ }
+ }
+ componentDidMount=()=>{
+ this.getSubModerator();
+ }
+ // 获取所有二级板块
+ getSubModerator=()=>{
+ const { plateId } = this.props.match.params;
+ const url = `/forum_sections/${plateId}/managements`;
+ axios.get(url).then((result)=>{
+ if(result){
+ this.setState({
+ children_tags:result.data.forum_tag && result.data.forum_tag.children_tags
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+ // 新建板块和重命名板块后的刷新方法
+ reSetInfo=()=>{
+ this.setState({
+ visible:false,
+ subId:undefined,
+ subName:undefined
+ })
+ this.getSubModerator();
+ const { plateId } = this.props.match.params;
+ const { getPlateInfo } = this.props;
+ getPlateInfo(plateId);
+ }
+
+ // 展开
+ expandEvent=(index,flag)=>{
+ this.setState(
+ (prevState) => ({
+ children_tags : update(prevState.children_tags, {[index]: { expand: {$set: flag} }}),
+ })
+ )
+ }
+
+ // 显示删除版主的按钮
+ deleteManageEvent=(index,flag)=>{
+ console.log(index)
+ this.setState(
+ (prevState) => ({
+ children_tags : update(prevState.children_tags, {[index]: { isDeleting: {$set: flag} }}),
+ })
+ )
+ }
+
+ // 新建二级板块
+ createSubPlateEvent=()=>{
+ this.setState({
+ visible:true,
+ subId:undefined,
+ subName:undefined
+ })
+ }
+ // 二级板块重命名
+ RenamneSubPlateEvent=(id,name)=>{
+ this.setState({
+ visible:true,
+ subId:id,
+ subName:name
+ })
+ }
+
+ // 删除二级板块
+ DeleteSubPlateEvent=(id)=>{
+ this.props.confirm({
+ content: '确认删除二级板块?',
+ onOk: () => {
+ const { plateId } = this.props.match.params;
+ const url=`/forum_sections/${plateId}/destroy.json`
+ axios.post(url,{
+ children_section_id:id
+ }).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.getSubModerator();
+ const { getPlateInfo } = this.props;
+ getPlateInfo(plateId);
+ }
+ }).catch((error)=>{
+
+ })
+ },
+ onCancel() {
+ console.log('Cancel');
+ }
+ })
+
+ }
+
+ // 关闭新建弹框
+ colseModalEvent=()=>{
+ this.setState({
+ visible:false
+ })
+ }
+
+ // 删除版主
+ deletePlateEvent=(id,name,index,key)=>{
+ console.log(index,'dddd',key);
+ this.props.confirm({
+ content: `是否确认解除“${name}”的二级版主权限?`,
+ onOk: () => {
+ const { plateId } = this.props.match.params;
+ const url=`/forum_sections/${plateId}/destroy_moderator/${id}`
+ axios.post(url).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ const { children_tags } = this.state;
+ // 去掉当前选中的版主
+ let tempObj = children_tags[index].forum_moderators;
+ tempObj = tempObj.filter((_, i) => i !== key) ;
+ children_tags[index].forum_moderators = tempObj;
+ this.setState({ children_tags })
+ }
+ }).catch((error)=>{
+
+ })
+ },
+ onCancel() {
+ console.log('Cancel');
+ }
+ })
+ }
+
+ // 新增版主弹框
+ showAddBox=(flag,plateId)=>{
+ this.setState({
+ addVisible:true,
+ operationPlateId:plateId
+ })
+ }
+ hideAddBox=()=>{
+ this.setState({
+ addVisible:false,
+ operationPlateId:undefined
+ })
+ }
+
+
+ render(){
+ const { visible ,children_tags , subId , subName , addVisible , operationPlateId } = this.state;
+ // console.log("child",children_tags);
+ const forumTagList = ()=>{
+ if(children_tags && children_tags.length>0){
+ return(
+
+ {
+ children_tags.map((item,key)=>{
+ return(
+
+
+
+ {item.title}
+
+ this.RenamneSubPlateEvent(item.id,item.title)}>重命名
+ this.DeleteSubPlateEvent(item.id)}>删除板块
+
+
+
二级版主
+
+ { renderSubList(item.forum_moderators,key,item.isDeleting) }
+
+ {/* 展开 */}
+ {
+ item.forum_moderators && item.forum_moderators.length > 5 && !item.expand &&
+ this.expandEvent(key,true)}>
+ }
+ {/* 收起 */}
+ {
+ item.forum_moderators && item.forum_moderators.length > 5 && item.expand &&
+ this.expandEvent(key,false)}>
+ }
+ {/* 新增版主 */}
+ this.showAddBox(true,item.id)}>
+ {/* 删除版主 */}
+ {
+ item.forum_moderators && item.forum_moderators.length > 0 && !item.isDeleting &&
+ this.deleteManageEvent(key,true)}>
+ }
+ {
+ item.isDeleting && this.deleteManageEvent(key,false)}>完成
+ }
+
+
+
+
+
+ )
+ })
+ }
+
+ )
+ }
+ }
+
+ const renderSubList = (item,index,deletingFlag) =>{
+ if(item){
+ return(
+
+ {
+ item.map((i,key)=>{
+ return(
+
+ {
+ !i.isDelete &&
+ -
+
+ {
+ deletingFlag &&
+ this.deletePlateEvent(`${i.moderator_id}`,`${i.username}`,index,key)}>
+ }
+ {i.username}
+
+ }
+
+
+ )
+ })
+ }
+
+ )
+ }
+ }
+ return(
+
+ )
+ }
+}
+
+export default PrePlateManage;
\ No newline at end of file
diff --git a/src/exchange/Manage/SubCheckItem.js b/src/exchange/Manage/SubCheckItem.js
new file mode 100644
index 000000000..976547829
--- /dev/null
+++ b/src/exchange/Manage/SubCheckItem.js
@@ -0,0 +1,146 @@
+import React, { Component } from 'react';
+import { Spin , Pagination } from 'antd';
+import '../exchange.css';
+import './manage.css';
+import Empty from '../Empty'
+import ItemLeft from './ItemLeft';
+import PassItem from './PassItem';
+import axios from 'axios'
+
+class SubCheckItem extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ page:1,
+ data:undefined,
+ isSpin:true,
+ limit:10
+ }
+ }
+
+ componentDidMount=()=>{
+ this.getList(1);
+ }
+
+ getList = (page) =>{
+ this.setState({
+ isSpin:true
+ })
+ const { plateId } = this.props.match.params;
+ const url = `/forum_sections/${plateId}/unchecked_memos.json`;
+ axios.get(url,{params:{
+ page
+ }}).then((result)=>{
+ if(result){
+ this.setState({
+ data:result.data,
+ isSpin:false
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 禁言
+ stopEvent=(id,banned,user_id)=>{
+ const { current_user } = this.props;
+ const url =`/memos/${id}/banned_user.json`
+ axios.post((url),{
+ user_id:user_id,
+ banned
+ }).then((result)=>{
+ if(result){
+ const { page } = this.state;
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch((error)=>{
+
+ })
+ console.log("banned",banned);
+ }
+
+ // 分页
+ changePageEvent=(page)=>{
+ this.setState({
+ page
+ })
+ this.getList(page);
+ }
+
+ render(){
+ const { data , page , isSpin , limit } = this.state;
+ const { current_user } = this.props;
+
+ const pageCom = (
+ data && data.memos_count > limit &&
+
+ )
+
+ const dataList = (
+
+ data && data.memos_lists && data.memos_lists.length > 0 ?
+
+ {
+ data.memos_lists.map((item,key)=>{
+ const userInfo = {
+ forum_id:item.forum_id,
+ memo_id:item.memo_id,
+ user_url:item.user_url,
+ username:item.username,
+ time:item.time,
+ image_url:item.image_url,
+ memo_title:item.memo_title,
+ forum_title:item.forum_title,
+ user_id:item.user_id
+ }
+ const passItem = {
+ refresh:this.getList,
+ page,
+ id:item.memo_id
+ }
+
+
+ return(
+
+
+
+
+ {
+ current_user && current_user.admin &&
+ ( item.is_banned ?
+
this.stopEvent(item.memo_id,0,item.user_id)}>已禁言
+ :
+
this.stopEvent(item.memo_id,1,item.user_id)}>禁言
+ )
+ }
+
+
+
+
+
+
+
+ )
+ })
+ }
+ { pageCom }
+
+ :
+
+
+
+ )
+
+ return(
+
+ { dataList }
+
+ )
+ }
+}
+
+export default SubCheckItem;
\ No newline at end of file
diff --git a/src/exchange/Manage/SubCheckReplyItem.js b/src/exchange/Manage/SubCheckReplyItem.js
new file mode 100644
index 000000000..7c92542ff
--- /dev/null
+++ b/src/exchange/Manage/SubCheckReplyItem.js
@@ -0,0 +1,148 @@
+import React, { Component } from 'react';
+import { Spin , Pagination } from 'antd';
+import '../exchange.css';
+import './manage.css';
+import Empty from '../Empty'
+import ItemLeft from './ItemLeft';
+import PassItem from './PassItem';
+import axios from 'axios'
+
+class SubCheckReplyItem extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ page:1,
+ data:undefined,
+ isSpin:true,
+ limit:10
+ }
+ }
+
+ componentDidMount=()=>{
+ this.getList(1);
+ }
+
+ getList = (page) =>{
+ this.setState({
+ isSpin:true
+ })
+ const { plateId } = this.props.match.params;
+ const url = `/forum_sections/${plateId}/unchecked_replies.json`;
+ axios.get(url,{params:{
+ page
+ }}).then((result)=>{
+ if(result){
+ this.setState({
+ data:result.data,
+ isSpin:false
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 禁言
+ stopEvent=(id,banned,user_id)=>{
+ const { current_user } = this.props;
+ const url =`/memos/${id}/banned_user.json`
+ axios.post((url),{
+ user_id:user_id,
+ banned
+ }).then((result)=>{
+ if(result){
+ const { page } = this.state;
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 分页
+ changePageEvent=(page)=>{
+ this.setState({
+ page
+ })
+ this.getList(page);
+ }
+
+ render(){
+ const { data , page , isSpin , limit } = this.state;
+ const { current_user } = this.props;
+
+ const pageCom = (
+ data && data.memos_count > limit &&
+
+ )
+
+ const dataList = (
+ data && data.replies_lists && data.replies_lists.length > 0 ?
+
+ {
+ data.replies_lists.map((item,key)=>{
+ const userInfo = {
+ source_id:item.source_id,
+ user_url:item.user_url,
+ username:item.username,
+ time:item.time,
+ image_url:item.image_url,
+ reply_content:item.reply_content,
+ source_title:item.source_title,
+ user_id:item.user_id,
+ id:item.reply_id
+ }
+ const passItem = {
+ refresh:this.getList,
+ page,
+ id:item.reply_id
+ }
+
+
+ return(
+
+
+
+
+
+ {
+ current_user && current_user.admin &&
+ ( item.is_banned ?
+
this.stopEvent(item.reply_id,0,item.user_id)}>已禁言
+ :
+
this.stopEvent(item.reply_id,1,item.user_id)}>禁言
+ )
+ }
+
+
+
+
+
+
+
+
+ )
+ })
+ }
+
+ { pageCom }
+
+ :
+
+
+
+ )
+
+ return(
+
+ { dataList }
+
+ )
+ }
+}
+
+
+export default SubCheckReplyItem;
\ No newline at end of file
diff --git a/src/exchange/Manage/SubSendItem.js b/src/exchange/Manage/SubSendItem.js
new file mode 100644
index 000000000..2a0e49d4b
--- /dev/null
+++ b/src/exchange/Manage/SubSendItem.js
@@ -0,0 +1,174 @@
+import React, { Component } from 'react';
+import { Spin , Pagination } from 'antd';
+import Tags from '../TagComponent/Index';
+import '../exchange.css';
+import './manage.css';
+import Empty from '../Empty'
+import ItemLeft from './ItemLeft';
+import PassItem from './PassItem';
+import axios from 'axios'
+
+class SubSendItem extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ page:1,
+ data:undefined,
+ isSpin:true,
+ limit:10
+ }
+ }
+
+ componentDidMount=()=>{
+ this.getList(1);
+ }
+
+ getList = (page) =>{
+ this.setState({
+ isSpin:true
+ })
+ const { plateId } = this.props.match.params;
+ const url = `/forum_sections/${plateId}/checked_memos.json`;
+ axios.get(url,{params:{
+ page
+ }}).then((result)=>{
+ if(result){
+ this.setState({
+ data:result.data,
+ isSpin:false
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 删除-已发布的帖子
+ deleteEvent=(id)=>{
+ const { page } = this.state;
+ const url = `/memos/${id}/destroy.json`;
+ axios.post(url).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch(error=>{
+
+ })
+ }
+ // 取消推荐/推荐-已发布的帖子
+ isFineEvent=(id,flag)=>{
+ const { page } = this.state;
+ const url = `/memos/${id}/is_fine`;
+ axios.post(url,{
+ is_fine:flag ? 0 : 1
+ }).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch(error=>{
+
+ })
+ }
+ // 取消置顶/置顶-已发布的帖子
+ stickyEvent=(id,flag)=>{
+ const { page } = this.state;
+ const url = `/memos/${id}/set-top-or-down`;
+ axios.get(url,{params:{
+ sticky:flag ? 0 : 1
+ }}).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ // 禁言
+ stopEvent=(id,banned)=>{
+ const { current_user } = this.props;
+ const url =`/memos/${id}/banned_user.json`
+ axios.post((url),{
+ user_id:current_user && current_user.user_id,
+ banned
+ }).then((result)=>{
+ if(result){
+ const { page } = this.state;
+ this.props.showNotification(result.data.message);
+ this.getList(page);
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 分页
+ changePageEvent=(page)=>{
+ this.setState({
+ page
+ })
+ this.getList(page);
+ }
+
+ render(){
+ const { data , page , isSpin , limit } = this.state;
+
+ const pageCom = (
+ data && data.memos_count > limit &&
+
+ )
+ const dataList = (
+ data && data.memos_lists && data.memos_lists.length > 0 ?
+
+ {
+ data.memos_lists.map((item,key)=>{
+ const userInfo = {
+ forum_id:item.forum_id,
+ memo_id:item.memo_id,
+ user_url:item.user_url,
+ username:item.username,
+ time:item.time,
+ image_url:item.image_url,
+ memo_title:item.memo_title,
+ forum_title:item.forum_title
+ }
+ return(
+
+
+
+
+
+
+
+
+ this.stickyEvent(item.memo_id,item.sticky)}>{item.sticky?"取消置顶":"置顶"}
+ this.isFineEvent(item.memo_id,item.is_fine)}>{item.is_fine?"取消推荐":"推荐"}
+ this.deleteEvent(item.memo_id)}>删除
+
+
+
+
+ )
+ })
+ }
+ { pageCom }
+
+ :
+
+
+
+ )
+
+ return(
+
+ { dataList }
+
+ )
+ }
+}
+export default SubSendItem;
\ No newline at end of file
diff --git a/src/exchange/Manage/manage.css b/src/exchange/Manage/manage.css
new file mode 100644
index 000000000..d698800a1
--- /dev/null
+++ b/src/exchange/Manage/manage.css
@@ -0,0 +1,134 @@
+
+.moderatorMenu .ant-tabs-ink-bar{
+ display: none!important;
+}
+.moderatorItems{
+ padding:20px 0px;
+ border-bottom: 1px solid #eaeaea;
+}
+.moderatorItems:last-child{
+ border-bottom: none;
+}
+.ItemsHeadPhoto .custom-img{
+ width:36px;
+ height: 36px;
+ margin-right: 15px;
+}
+.reply_manage_content img{
+ width: 30px
+}
+
+/* 一级板块管理-版主申请 */
+.applyList{
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between
+}
+.applyList > div{
+ background: #fff;
+ width: 585px;
+ display: flex;
+ padding:20px 30px;
+ box-sizing: border-box;
+ margin-bottom: 20px;
+}
+
+/* 表单form---标题和内容在统一行 */
+.formInline .ant-row.ant-form-item{
+ display: flex
+}
+.formInline .ant-col.ant-form-item-control-wrapper{
+ flex: 1;
+}
+/* 二级板块管理 */
+.subPlateList{
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content:space-between;
+}
+.subPlateList > div{
+ width:585px;
+ height: 180px;
+ background: #fff;
+ position: relative;
+ margin-bottom: 20px;
+}
+.subPlateList > div .subPlateItem{
+ position: absolute;
+ width: 100%;
+ left: 0px;
+ top:0px;
+ padding-left:30px;
+ box-sizing: border-box;
+ background: #fff;
+}
+.subPlateList > div .subPlateItem.active{
+ box-shadow: 0px 5px 26px rgba(0,0,0,0.1);
+ z-index: 1;
+}
+.subPlateItem_head{
+ display: flex;
+ justify-content: space-between;
+ height: 50px;
+ line-height: 50px;
+ border-bottom: 1px solid #f4f4f4;
+ margin-right: 30px;
+}
+.subPlateItem.active .plateManager > ul{
+ width: auto;
+ height: auto;
+ display: inline
+}
+.plateManager > ul{
+ display: inline-block;
+ width: 345px;
+ height: 60px;
+ overflow: hidden;
+}
+.font-36{font-size: 36px!important;}
+.plateManager > ul > li{
+ display: flex;
+ flex-direction: column;
+ font-size: 12px;
+ align-items: center;
+ float: left;
+ margin-right: 30px;
+ text-align: center;
+ margin-bottom: 20px;
+ position: relative;
+}
+.deletePlateIcon{
+ position: absolute;
+ top: -11px;
+ right: -8px;
+ font-size: 18px;
+ color: #FF5555;
+ cursor: pointer;
+}
+.completeIcon{
+ background: #5091FF;
+ width: 36px;
+ height: 36px;
+ line-height: 36px;
+ font-size: 12px;
+ color: #fff;
+ text-align: center;
+ float: right;
+ border-radius: 50%;
+ margin-top: 18px;
+}
+
+/* 添加版主弹框 */
+.addPlateModal .ant-modal-body{
+ padding:30px 0px!important;
+}
+/* .addPlateModal .ant-table-tbody > tr > td{
+ padding:10px 5px;
+} */
+/*禁言两端对齐*/
+.between_{
+ flex-direction: column;
+ justify-content: space-between;
+}
\ No newline at end of file
diff --git a/src/exchange/MenuComponent/Menu.css b/src/exchange/MenuComponent/Menu.css
new file mode 100644
index 000000000..303e3150e
--- /dev/null
+++ b/src/exchange/MenuComponent/Menu.css
@@ -0,0 +1,18 @@
+
+.plate-left-Menu .ant-tabs-tab{
+ height: 80px;
+ line-height: 80px;
+ font-size: 16px;
+ margin-left: 30px;
+ margin-right: 0px;
+ padding:0px;
+}
+.plate-left-Menu .ant-tabs-bar{
+ margin-bottom: 0px;
+ border-bottom: 1px solid #f4f4f4;
+ background: #fff;
+}
+.plate-left-Menu .ant-tabs-extra-content{
+ margin-top: 18px;
+ margin-right: 30px;
+}
\ No newline at end of file
diff --git a/src/exchange/MenuComponent/Menu.js b/src/exchange/MenuComponent/Menu.js
new file mode 100644
index 000000000..2dd8c0e8d
--- /dev/null
+++ b/src/exchange/MenuComponent/Menu.js
@@ -0,0 +1,51 @@
+import React, { Component } from 'react';
+import { Tabs } from 'antd';
+import './Menu.css';
+
+
+const { TabPane } = Tabs;
+
+class MenuCom extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ activeKey: ''
+ }
+ }
+
+ componentDidMount () {
+ const { defaultUrlKey } = this.props;
+ this.setState({
+ activeKey: defaultUrlKey
+ })
+ }
+ changeTabs=(activeKey)=>{
+ this.setState({
+ activeKey:activeKey
+ })
+ const { changeTab } = this.props;
+ changeTab(activeKey);
+ }
+
+ render(){
+ const { menu_nav , btn , ...props } = this.props;
+
+ const tabs = menu_nav.map((tab)=>{
+ const Content = tab.content;
+ return(
+
+
+
+ )
+ })
+
+ let { activeKey } = this.state;
+
+ return(
+
+ { tabs }
+
+ )
+ }
+}
+export default MenuCom;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/Index.js b/src/exchange/MyExchange/Index.js
new file mode 100644
index 000000000..19b914c9b
--- /dev/null
+++ b/src/exchange/MyExchange/Index.js
@@ -0,0 +1,115 @@
+import React, { Component } from 'react';
+
+import ExchangeRight from '../ExchangeRight'
+
+import '../exchange.css';
+import './myExchange.css';
+
+import Nav from '../NavComponent/Index'
+
+import MyTopic from './MyTopic';
+import MyInteresting from './MyInteresting';
+import MyEnshrine from './MyEnshrine';
+import MenuWraps from '../MenuComponent/Menu'
+
+import axios from 'axios';
+
+const menu_nav = [
+ {
+ name:"我的话题",
+ key:`MyTopic`,
+ content:MyTopic
+ },
+ {
+ name:"我的收藏",
+ key:`MyEnshrine`,
+ content:MyEnshrine
+ },
+ {
+ name:"我感兴趣的论坛",
+ key:`MyInteresting`,
+ content:MyInteresting
+ }
+]
+class Index extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ activeKey:"MyTopic",
+ data:undefined
+ }
+ }
+
+ componentDidMount=()=>{
+ this.getMain();
+ }
+
+ getMain=()=>{
+ const url =`/my_memos/recommend_memos`;
+ axios.get(url).then(result=>{
+ if(result){
+ this.setState({
+ data:result.data
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ // 切换第一个nav
+ changeTab=(activeKey)=>{
+ // console.log('1--',activeKey);
+ this.setState({
+ activeKey
+ })
+ }
+ render(){
+ let pathname = this.props.location.pathname;
+ let urllength = pathname.split("/").length;
+ let urlLast = pathname.split("/")[urllength-1];
+
+ const { current_user } = this.props;
+ const { activeKey , data } = this.state;
+
+ const NavMap=[
+ {
+ url:current_user && current_user.user_url,
+ name:current_user && current_user.username
+ },
+ {
+ url:"/forums",
+ name:"论坛交流"
+ },
+ {
+ name:activeKey === "MyTopic" ? "我的话题" :activeKey === "MyEnshrine" ? "我的收藏" : "我感兴趣的论坛"
+ }
+ ]
+
+ return(
+
+
+ )
+ }
+}
+export default Index;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/MyEnshrine.js b/src/exchange/MyExchange/MyEnshrine.js
new file mode 100644
index 000000000..ec4b1a934
--- /dev/null
+++ b/src/exchange/MyExchange/MyEnshrine.js
@@ -0,0 +1,17 @@
+import React, { Component } from 'react';
+
+import MyTopicItem from './MyTopicItem';
+
+
+class MyEnshrine extends Component {
+
+ render(){
+ return(
+
+
+
+ )
+ }
+}
+
+export default MyEnshrine;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/MyInteresting.js b/src/exchange/MyExchange/MyInteresting.js
new file mode 100644
index 000000000..73bcd7856
--- /dev/null
+++ b/src/exchange/MyExchange/MyInteresting.js
@@ -0,0 +1,101 @@
+import React, { Component } from 'react';
+import { Spin } from 'antd';
+import { Link } from 'react-router-dom'
+
+import Empty from '../Empty';
+import './myExchange.css';
+
+import box1 from '../images/box1.png';
+import box2 from '../images/box2.png';
+import box3 from '../images/box3.png';
+import box4 from '../images/box4.png';
+import box5 from '../images/box5.png';
+import box6 from '../images/box6.png';
+
+import axios from 'axios';
+
+const backImgArray = [box1,box2,box3,box4,box5,box6];
+class MyInteresting extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ forum_details:undefined,
+ isSpin:true
+ }
+ }
+
+ componentDidMount = () =>{
+ this.getInfo();
+ }
+
+ getInfo = () =>{
+ this.setState({
+ isSpin:true
+ })
+ const url = `/my_memos/my_interested`;
+ axios.get(url).then((result)=>{
+ if(result){
+ this.setState({
+ forum_details:result.data.forum_details,
+ isSpin:false
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ // 取消收藏
+ cancelEnshrineEvent=(id)=>{
+ const url = `/memos/forum_memos/${id}/is_watch.json`;
+ axios.post((url),{
+ is_watch:0
+ }).then(result=>{
+ if(result){
+ this.getInfo();
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ render(){
+ const { forum_details , isSpin } = this.state;
+
+ const divList = ( forum_details && forum_details.length > 0 ?
+
+ {
+ forum_details.map((item,key) => {
+ const index = Number(Number((key)%6)+1)-1;
+ // console.log(index);
+ return(
+
+
+
+
{item.title}
+
{item.memos_count} 个话题
+
+
+
+ this.cancelEnshrineEvent(`${item.id}`)}>取消收藏
+ 查看
+
+
+ )
+ })
+ }
+
+ :
+
+ )
+ return(
+
+
+ { divList }
+
+
+ )
+ }
+}
+
+export default MyInteresting;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/MyTopic.js b/src/exchange/MyExchange/MyTopic.js
new file mode 100644
index 000000000..541cd2aa0
--- /dev/null
+++ b/src/exchange/MyExchange/MyTopic.js
@@ -0,0 +1,59 @@
+import React, { Component } from 'react';
+
+import MenuWraps from '../MenuComponent/Menu';
+import MyTopicItem from './MyTopicItem';
+
+import './myExchange.css';
+
+
+const menu_nav = [
+ {
+ name:"发表的话题",
+ key:`published`,
+ content:MyTopicItem
+ },
+ {
+ name:"回复的话题",
+ key:`replied`,
+ content:MyTopicItem
+ },
+ {
+ name:"看过的话题",
+ key:`watched`,
+ content:MyTopicItem
+ }
+]
+class MyTopic extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ activeKey:"published"
+ }
+ }
+
+ // 切换第2个nav:发表的话题、回复的话题、看过的话题
+ changeTab=(activeKey)=>{
+ this.setState({
+ activeKey
+ })
+ }
+ render(){
+ let { activeKey } = this.state;
+ return(
+
+
+
+ )
+ }
+}
+
+export default MyTopic;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/MyTopicItem.js b/src/exchange/MyExchange/MyTopicItem.js
new file mode 100644
index 000000000..f3728d708
--- /dev/null
+++ b/src/exchange/MyExchange/MyTopicItem.js
@@ -0,0 +1,239 @@
+import React, { Component } from 'react';
+import { Dropdown , Menu , Icon , DatePicker , Pagination , Spin } from 'antd';
+import { Link } from 'react-router-dom'
+
+import moment from 'moment'
+import Empty from '../Empty'
+
+import ExchangeItems from '../ExchangeItem';
+import './myExchange.css'
+import '../exchange.css'
+
+import axios from 'axios';
+const { SubMenu } = Menu;
+
+const dateFormat = 'YYYY-MM-DD';
+
+class MyTopicItem extends Component {
+ constructor(props){
+ super(props);
+ this.state={
+ // 筛选条件
+ memo_type:undefined,
+ forum_section_id:undefined,
+ is_hidden:undefined,
+ is_hidden_name:undefined,
+ start_time:undefined,
+ end_time:undefined,
+ page:1,
+ plateName:undefined,
+ // 分页
+ pageSize:15,
+ // 数据
+ data:undefined,
+ isSpin:true
+ }
+ }
+
+ // 搜索
+ searchEvent=()=>{}
+
+ // 清除
+ clearEvent=()=>{}
+
+ componentDidMount=()=>{
+ this.refresh();
+ }
+
+ // 我的话题和我的收藏公用当前组件,但接口不同,根据url判断调用哪个接口
+ getMytopicInfo = (forum_section_id,is_hidden,start_time,end_time,page) =>{
+ this.setState({
+ isSpin:true
+ })
+ const { subActiveKey , urlName } = this.props;
+
+ const url = `/${urlName}`;
+ axios.get(url,{params:{
+ memo_type:subActiveKey,
+ forum_section_id,
+ is_hidden,
+ start_time,
+ end_time,
+ page
+ }}).then(result=>{
+ if(result){
+ this.setState({
+ data:result.data,
+ isSpin:false
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ // 刷新时需要用到
+ refresh=()=>{
+ const {forum_section_id,is_hidden,start_time,end_time } = this.state;
+ this.getMytopicInfo(forum_section_id,is_hidden,start_time,end_time,1);
+ }
+
+ // 切换分页
+ changePageEvent = (page) =>{
+ this.setState({
+ page
+ })
+ const {forum_section_id,is_hidden,start_time,end_time } = this.state;
+ this.getMytopicInfo(forum_section_id,is_hidden,start_time,end_time,page);
+ }
+
+ // 选择板块
+ changeForumId=(plateId,name)=>{
+ this.setState({
+ forum_section_id:plateId,
+ plateName:name
+ })
+ const {is_hidden,start_time,end_time , page } = this.state;
+ this.getMytopicInfo(plateId,is_hidden,start_time,end_time,page);
+ }
+
+ // 选择帖子状态
+ forumType=(type)=>{
+ this.setState({
+ is_hidden:type,
+ is_hidden_name:type === "show" ? "已发布的话题":"待审查的话题"
+ })
+ const {forum_section_id,start_time,end_time , page } = this.state;
+ this.getMytopicInfo(forum_section_id,type,start_time,end_time,page);
+ }
+
+ // 清除搜索条件
+ clearEvent=()=>{
+ this.setState({
+ forum_section_id:undefined,
+ plateName:undefined,
+ is_hidden:undefined,
+ is_hidden_name:undefined,
+ start_time:undefined,
+ end_time:undefined
+ })
+ this.getMytopicInfo(undefined,undefined,undefined,undefined,1);
+ }
+
+ // 选择开始时间
+ changeBeginEvent=(e,dateString)=>{
+ this.setState({
+ start_time:dateString
+ })
+ }
+
+ // 选择结束时间
+ changeEndEvent=(e,dateString)=>{
+ this.setState({
+ end_time:dateString
+ })
+ }
+
+ // 搜索
+ searchEvent=()=>{
+ this.setState({
+ page:1
+ })
+ const {forum_section_id,is_hidden,start_time,end_time } = this.state;
+ this.getMytopicInfo(forum_section_id , is_hidden , start_time , end_time , 1);
+ }
+
+ render(){
+ const { data , pageSize , page , plateName , is_hidden_name , start_time , end_time , isSpin } = this.state;
+
+ // 选择板块
+ const menuList =(
+
+ {
+ data && data.forum_sections && data.forum_sections.map(item => {
+ return(
+
+ )
+ })
+ }
+
+ )
+
+ // 全部帖子
+ const forumList = (
+
+ )
+
+
+ const pagination = (
+ data && data.memos && data.memos_count > pageSize &&
+
+ )
+
+ const dataList = (
+
+
+ {
+ data && data.memos && data.memos.length>0 ?
+
+
+ { pagination }
+
+ :
+
+
+
+ }
+
+ )
+ return( dataList )
+ }
+}
+
+export default MyTopicItem;
\ No newline at end of file
diff --git a/src/exchange/MyExchange/myExchange.css b/src/exchange/MyExchange/myExchange.css
new file mode 100644
index 000000000..291a69aa4
--- /dev/null
+++ b/src/exchange/MyExchange/myExchange.css
@@ -0,0 +1,56 @@
+.MyTopicSearch{
+ display: flex;
+ border-bottom: 1px solid #f4f4f4;
+ padding:20px 30px;
+ align-items: center;
+ justify-content: space-between;
+ background: #fff;
+}
+
+/* 我感兴趣的论坛 */
+.ForumList{
+ display: flex;
+ flex-flow: row;
+ flex-wrap:wrap;
+ justify-content: space-between;
+}
+.interestItem{
+ width: 280px;
+ margin:20px 0px;
+ background: #FFFFFF;
+}
+.interestItem .interestingUpper{
+ height: 150px;
+ background-repeat:no-repeat;
+ background-size:100% 100%;
+ background-color:#fff ;
+ display: flex;
+ flex-flow: row;
+ align-items: center;
+ justify-content: center;
+}
+.interestingOperate{
+ display: flex;
+ height: 50px;
+ line-height: 50px;
+}
+.interestingOperate .operateBtn{
+ width: 50%;
+ display: block;
+ text-align: center;
+ position: relative;
+ color: #666666;
+}
+.interestingOperate .operateBtn:first-child::after{
+ height: 24px;
+ width:1px;
+ top:13px;
+ position: absolute;
+ right: 0px;
+ content: '';
+ background: #eee;
+}
+
+.mainNav-style > .ant-tabs-bar .ant-tabs-ink-bar{
+ display: none!important;
+}
\ No newline at end of file
diff --git a/src/exchange/NavComponent/Index.js b/src/exchange/NavComponent/Index.js
new file mode 100644
index 000000000..915158cb6
--- /dev/null
+++ b/src/exchange/NavComponent/Index.js
@@ -0,0 +1,28 @@
+import React , { PureComponent } from "react";
+import { Link } from 'react-router-dom';
+
+import './nav.css'
+
+class Index extends PureComponent{
+ render(){
+ const { NavMap , ...props } = this.props;
+ let navRouter = NavMap && NavMap.map((item) => {
+ return(
+
+ {
+ item.name ? (item.url ?
+ { item.name }
+ :
+ { item.name })
+ :""
+ }
+
+ )
+ })
+ return(
+ { navRouter }
+ )
+ }
+
+}
+export default Index;
\ No newline at end of file
diff --git a/src/exchange/NavComponent/nav.css b/src/exchange/NavComponent/nav.css
new file mode 100644
index 000000000..b453349bf
--- /dev/null
+++ b/src/exchange/NavComponent/nav.css
@@ -0,0 +1,13 @@
+.nav_Link{
+ position: relative;
+ margin-right: 20px;
+}
+.nav_Link::after{
+ position: absolute;
+ right: -15px;
+ content: '>';
+ top:0px;
+ color: #999;
+ height: 20px;
+ line-height: 18px;
+}
\ No newline at end of file
diff --git a/src/exchange/Plate/All.js b/src/exchange/Plate/All.js
new file mode 100644
index 000000000..07e403a56
--- /dev/null
+++ b/src/exchange/Plate/All.js
@@ -0,0 +1,36 @@
+import React, { PureComponent } from 'react';
+import ExchangeItem from '../ExchangeItem'
+import Empty from '../Empty'
+
+import '../exchange.css'
+import './plate.css'
+class All extends PureComponent{
+ state = {
+ condition:"all"
+ }
+
+ componentDidMount = () =>{
+ const { condition } = this.props;
+ this.setState({
+ condition
+ })
+ }
+
+ render(){
+
+ const { memos } = this.props;
+
+ const memosList = (
+ memos && memos.length > 0 ?
+
+ :
+
+
+
+ )
+ return(
+ memosList
+ )
+ }
+}
+export default All;
\ No newline at end of file
diff --git a/src/exchange/Plate/Index.js b/src/exchange/Plate/Index.js
new file mode 100644
index 000000000..e931978fd
--- /dev/null
+++ b/src/exchange/Plate/Index.js
@@ -0,0 +1,264 @@
+import React, { Component } from 'react';
+import { Pagination , Spin } from 'antd'
+import {Link} from 'react-router-dom'
+import '../exchange.css';
+import './plate.css'
+
+import Nav from '../NavComponent/Index';
+import MenuWraps from '../MenuComponent/Menu';
+
+
+
+import PlateRight from './PlateRight'
+
+import axios from 'axios';
+import All from './All'
+
+const menu_nav = [
+ {
+ name:"全部",
+ key:`all`,
+ content:All
+ },
+ {
+ name:"推荐精华",
+ key:`is_fine`,
+ content:All
+ },
+ {
+ name:"我的话题",
+ key:`my_memos`,
+ content:All
+ },
+ {
+ name:"我参与的话题",
+ key:`my_topics`,
+ content:All
+ }
+]
+class Index extends Component {
+ constructor(props){
+ super(props);
+ this.state = {
+ collectFlag:false,
+
+ // 列表搜索相关
+ page:1,
+ search:undefined,
+ pageSize:10,
+ select_type:"all",
+
+ memos:undefined,
+ memos_count:0,
+ // 接口返回的所有数据
+ data:undefined,
+ forum_tag :undefined,
+ forum_moders:undefined,
+ forum_sections:undefined,
+ bread_crumb:undefined,
+ current_user:undefined,
+ isSpin:true
+ }
+ }
+
+ componentDidMount () {
+ this.InitData();
+ }
+
+ InitData=()=>{
+ this.setState({
+ isSpin:true
+ })
+ const { plateid } = this.props.match.params;
+ const { page , search , select_type} = this.state;
+ this.getInfos(plateid , page , search , select_type);
+ }
+
+ getInfos = (plateid , page , search , select_type) =>{
+ const url= `/memos/forum_memos/${plateid}.json`;
+ axios.get(url,{params:{
+ page,
+ search,
+ select_type
+ }}).then(result=>{
+ if(result){
+ this.setState({
+ data:result.data,
+ memos:result.data.memos,
+ memos_count:result.data.memos_count,
+ collectFlag:result.data.watched,
+ forum_tag :result.data.bread_crumb && result.data.bread_crumb.forum_tag,
+ forum_moders:result.data.forum_moders,
+ forum_sections:result.data.forum_sections,
+ bread_crumb:result.data.bread_crumb,
+ current_user:result.data.current_user,
+ isSpin:false
+ })
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+
+ // 点击收藏
+ colectPlate = () =>{
+ const { collectFlag } = this.state;
+ const { plateid } = this.props.match.params;
+ const url = `/memos/forum_memos/${plateid}/is_watch.json`;
+ // is_watch:1为添加关注
+ axios.post(url,{
+ is_watch: collectFlag ? 0 : 1
+ }).then((result)=>{
+ if(result){
+ if(result.data.status === 0){
+ this.setState({
+ collectFlag:!collectFlag
+ })
+ this.props.showNotification(result.data.message);
+ }
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 搜索
+ searchEvent=(e)=>{
+ this.setState({
+ search:e
+ })
+ const { plateid } = this.props.match.params;
+ const { select_type } = this.state;
+ this.getInfos(plateid , 1 , e , select_type);
+ }
+
+ // 切换菜单项
+ changeTabEvent = (key) =>{
+ this.setState({
+ select_type:key,
+ isSpin:true
+ })
+ const { plateid } = this.props.match.params;
+
+ const { search} = this.state;
+ this.getInfos(plateid , 1 , search , key);
+ }
+
+ // 切换分页
+ changePageEvent=(pageNum)=>{
+ this.setState({
+ page:pageNum
+ })
+ const { plateid } = this.props.match.params;
+
+ const { search , select_type} = this.state;
+ this.getInfos(plateid , pageNum , search , select_type);
+ }
+
+ render(){
+ let {
+ title,
+ collectFlag ,
+ memos ,
+ forum_tag ,
+ select_type,
+ forum_moders ,
+ forum_sections ,
+ page,
+ data,
+ pageSize,
+ bread_crumb ,
+ current_user,
+ isSpin } = this.state;
+
+ const { plateid } = this.props.match.params;
+ let pathname = this.props.location.pathname;
+ let urlLastLength = pathname.split("/").length;
+ let urlLast = pathname.split("/")[urlLastLength-1];
+
+ const children_bread_crumb = forum_tag && forum_tag.children_bread_crumb;
+ //获取当前版块标题
+ const title_post=forum_tag && ((children_bread_crumb && children_bread_crumb.title) || forum_tag.title);
+
+ console.log("c",children_bread_crumb)
+ // 顶部导航栏
+ const routerMap = [
+ {
+ name:current_user && current_user.username,
+ url:current_user && current_user.user_url
+ },
+ {
+ name:bread_crumb && bread_crumb.forum && bread_crumb.forum.title,
+ url:"/forums"
+ },
+ {
+ name:forum_tag && ((children_bread_crumb && children_bread_crumb.title) || forum_tag.title)
+ }
+ ];
+
+ let collectMap = current_user? this.colectPlate()}>{collectFlag ?'取消收藏':'收藏'}: 收藏 ;
+
+ // 菜单行右侧按钮
+ //只有登录管理员可见
+
+ const btn = (current_user && current_user.admin_permission) ?版块管理 : undefined;
+ console.log(btn);
+
+
+ // 操作列表item需要刷新页面以及切换菜单项需要重新调用参数
+ const commonEvent = {
+ refresh:this.InitData,
+ changeTab:this.changeTabEvent
+ }
+
+ // 列表分页
+ const pageination = (
+ data && data.memos_count > pageSize &&
+
+ )
+
+
+ return(
+
+
+
+
+
+ {title_post}
+ { collectMap }
+
+
+
+
+
+
+
+
+
+ { pageination }
+
+
+
+
+
+ )
+ }
+}
+export default Index;
\ No newline at end of file
diff --git a/src/exchange/Plate/PlateRight.js b/src/exchange/Plate/PlateRight.js
new file mode 100644
index 000000000..20a96c3fc
--- /dev/null
+++ b/src/exchange/Plate/PlateRight.js
@@ -0,0 +1,93 @@
+import React, { PureComponent } from 'react';
+import { getImageUrl } from 'educoder';
+import { Link } from 'react-router-dom';
+import '../exchange.css';
+import './plate.css'
+
+import ExchangeRightSearch from '../ExchangeRightSearch'
+import Custom from '../CustomComponent/Index';
+
+import axios from 'axios';
+class PlateRight extends PureComponent {
+
+ // 申请版主
+ applyModerator = () =>{
+ this.props.confirm({
+ content: '是否确认申请版主?',
+
+ onOk: () => {
+ const { plateid } = this.props.match.params;
+ const url = `/forum_sections/${plateid}/user_apply`;
+ axios.post(url).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ }
+ }).catch(error=>{
+
+ })
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ }
+
+ render(){
+
+ const { forum_sections , forum_moders , searchEvent , current_user }= this.props;
+
+ // admin_permission:是否是版主
+ const moderatorInfo = ( forum_moders && forum_moders.length > 0 &&
+
+
+
+ 版主
+ {
+ current_user && current_user.admin_permission === false && 申请版主
+ }
+
+
+ { forum_moders.map((item,key)=>{
+ return(
+
+ )
+ }) }
+
+
+ )
+
+
+ const choiceInfo = ( forum_sections && forum_sections.length > 0 &&
+
+
+
+ 精选版块
+
+
+
+ )
+
+
+ return(
+
+
+
+ { moderatorInfo }
+
+ { choiceInfo }
+
+ )
+ }
+}
+export default PlateRight;
\ No newline at end of file
diff --git a/src/exchange/Plate/plate.css b/src/exchange/Plate/plate.css
new file mode 100644
index 000000000..f1bb1cad3
--- /dev/null
+++ b/src/exchange/Plate/plate.css
@@ -0,0 +1,45 @@
+
+/* plate */
+.collecting{
+ height: 22px;
+ padding:0px 11px;
+ border: 1px solid #5091FF;
+ color: #5091FF;
+ border-radius: 4px;
+ line-height: 22px;
+ font-size: 12px;
+ float: left;
+ cursor: pointer;
+}
+.collected{
+ color: #999999;
+ border:1px solid #999999;
+}
+
+.applyBtn{
+ border:1px solid #5091FF;
+ color: #5091FF;
+ height: 26px;
+ line-height: 26px;
+ padding:0px 8px;
+ border-radius: 4px;
+}
+
+/* 版主 */
+.moderatorPanel{
+ display: flex;
+ flex-wrap:wrap;
+ padding: 10px 15px 0px;
+}
+
+/* 精选版块 */
+.choicePlate{
+ padding:10px 20px 0px 20px;
+}
+.choicePlate > li{
+ padding: 10px 0px;
+}
+
+.searchForHide .ant-tabs-bar.ant-tabs-top-bar{
+ display: none;
+}
\ No newline at end of file
diff --git a/src/exchange/Post/CommentsIndex.js b/src/exchange/Post/CommentsIndex.js
new file mode 100644
index 000000000..ed878d8d1
--- /dev/null
+++ b/src/exchange/Post/CommentsIndex.js
@@ -0,0 +1,155 @@
+import React, { PureComponent } from 'react';
+import './post.css'
+import Item from '../Comments/CommentsItem'
+import ItemImg from '../Comments/CommentsItemImg'
+import axios from 'axios';
+
+import CommentsSend from '../Comments/CommentsSend';
+
+
+
+class CommentsIndex extends PureComponent{
+
+ // 调用父组件的刷新方法
+ refreshReply=()=>{
+ let { refresh , page} = this.props;
+ refresh(page);
+ }
+
+ // 删除评论
+ deleteReplyEvent=(id)=>{
+ const url = `/memos/${id}/destroy.json`
+ axios.post(url).then((result)=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.refreshReply();
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ commentReplyEvent=(index,flag)=>{
+ console.log("1",flag);
+ this.props.showCommentEvent(index,true);
+ }
+
+
+
+ // 点赞评论
+ praiseEvent=(id)=>{
+ const url = `/discusses/${id}/plus.json`;
+ axios.post(url,{
+ container_type:'Memo',
+ type:1
+ }).then(result=>{
+ if(result){
+ this.refreshReply();
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ parseCommentContent = (oldContent) => {
+ if (oldContent && oldContent.startsWith('<') && oldContent.endsWith('>')) {
+ } else if (window.$('#md_div').length) { // 有这个临时处理md内容的dom
+ window.$('#md_div').html('')
+ // markdown to html
+ try {
+ var markdwonParser = window.editormd.markdownToHTML("md_div", {
+ markdown: oldContent,
+ emoji: true,
+ htmlDecode: "style,script,iframe", // you can filter tags decode
+ taskList: true,
+ tex: true, // 默认不解析
+ flowChart: true, // 默认不解析
+ sequenceDiagram: true // 默认不解析
+ });
+ oldContent = window.$('#md_div').html()
+ } catch (e) {
+ // TODO 可能公式parse时报错了
+ console.error(e)
+ }
+ }
+ return oldContent;
+ }
+
+ render(){
+ // 评论列表,当前用户信息
+ const { repliesData , current_user , page } = this.props;
+ const renderNum = (arrs,flag) =>{
+ return(展开其余1条评论
)
+ }
+
+ //二级评论
+ const renderChild = (arrs) => {
+ return(
+
+ {
+ arrs.map((child)=>{
+ return(
+
+ )
+ })
+ }
+
+ )
+ }
+
+ const replyInfoWrap = (i,index)=> (
+
+
+ this.praiseEvent(i.id)}>
+
+ {i.praise_count}
+
+ {
+ current_user && (current_user.is_banned === false || current_user.admin) &&
+ this.commentReplyEvent(index,i.commentsFlag)}>
+ {i.replies_count}
+
+ }
+
+ {
+ i.commentsFlag &&
+
+ }
+
+ )
+
+ // 判断是否是管理员或者版主
+ const manage = current_user && (current_user.admin || current_user.banned_permission);
+ const itemMap = repliesData && repliesData.map((i,index)=>{
+ let _content = this.parseCommentContent(i.content);
+ return(
+
+
+
+
+
+ {
+ i.children && i.children.length > 0 &&
+
+ {renderChild(i.children)}
+ {/* { i.children.length > 1 && renderNum(i.children)} */}
+
+ }
+
+ {replyInfoWrap(i,index)}
+
+
+
+ )
+ })
+
+ return( itemMap )
+ }
+}
+
+export default CommentsIndex;
\ No newline at end of file
diff --git a/src/exchange/Post/ImageUpload.js b/src/exchange/Post/ImageUpload.js
new file mode 100644
index 000000000..dc15691ac
--- /dev/null
+++ b/src/exchange/Post/ImageUpload.js
@@ -0,0 +1,128 @@
+import React, { Component } from 'react';
+
+import moment from 'moment'
+import Select, {Option, OptGroup} from 'rc-select';
+import 'rc-select/assets/index.css';
+
+import { Upload, Icon, Modal, message } from 'antd';
+
+
+import 'antd/lib/upload/style/index.css'
+import 'antd/lib/modal/style/index.css'
+import 'antd/lib/style/index.css'
+import 'antd/lib/message/style/index.css'
+import './MemoNew.css'
+// -------------------------------------------
+
+
+let uploadValidateFailed = false;
+function beforeUpload(file) {
+ const isJPG = file.type === 'image/jpeg';
+ const isPNG = file.type === 'image/png';
+ const isGIF = file.type === 'image/gif';
+ if (!isJPG && !isPNG && !isGIF) {
+ message.error('只能上传图片文件!(jpg、png或gif)');
+ uploadValidateFailed = true;
+ return false;
+ }
+ const isLt2M = (file.size / 1024 / 1024) < 2;
+ if (!isLt2M) {
+ uploadValidateFailed = true;
+ message.error('图片大小必须小于 2MB!');
+ return false;
+ }
+ uploadValidateFailed = false;
+ return true;
+}
+
+class ImageUpload extends Component {
+ state = {
+ previewVisible: false,
+ previewImage: '',
+ fileList: [
+ // {
+ // uid: -1,
+ // name: 'xxx.png',
+ // status: 'done',
+ // url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
+ // }
+ ],
+ };
+
+ handleCancel = () => {
+
+ this.setState({ previewVisible: false })
+ }
+
+ handlePreview = (file) => {
+ this.setState({
+ previewImage: file.url || file.thumbUrl,
+ previewVisible: true,
+ });
+ }
+
+ handleRemove = () => {
+ const { onImageUploadRemove } = this.props;
+ onImageUploadRemove()
+ }
+
+ componentWillReceiveProps(newProps, oldProps) {
+ // 初始化值
+ if (newProps.fileList && this.props.fileList.length != newProps.fileList.length) {
+ this.setState({
+ fileList: newProps.fileList
+ })
+ }
+ }
+
+ handleChange = ({ fileList }) => {
+
+ const { onImageUploadDone } = this.props;
+ if (fileList.length && fileList[0].status === 'done') {
+ onImageUploadDone(fileList[0])
+ }
+ if (!uploadValidateFailed) {
+ this.setState({ fileList })
+ }
+ }
+
+
+
+ render() {
+ const { previewVisible, previewImage, fileList } = this.state;
+ const { currentMemoId } = this.props;
+ const uploadButton = (
+
+
+
点击上传封面
+
只支持JPG、PNG、JPEG大小不超过2M
+
建议尺寸4:3
+
+ );
+
+ return (
+
+
+ {fileList.length >= 1 ? null : uploadButton}
+
+
+
+
+
+ );
+ }
+}
+
+export default ImageUpload;
diff --git a/src/exchange/Post/Index.js b/src/exchange/Post/Index.js
new file mode 100644
index 000000000..90beaa1d6
--- /dev/null
+++ b/src/exchange/Post/Index.js
@@ -0,0 +1,248 @@
+
+import React, { Component } from 'react';
+import { Pagination , Spin } from 'antd';
+
+import '../exchange.css'
+import './post.css'
+
+import Nav from '../NavComponent/Index'
+import Parse from './Parse';
+import ExchangeItem from '../ExchangeItem'
+
+import CommentsIndex from './CommentsIndex';
+import CommentsSend from '../Comments/CommentsSend';
+import RenderHtml from "../../components/render-html";
+
+import FileList from '../../common/FileList';
+
+import update from 'immutability-helper'
+
+import axios from 'axios';
+
+class Index extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ // 当前用户是否点赞
+ judge:true,
+ parseNum:0,
+ // 帖子用户信息
+ author_info:undefined,
+ // 当前用户信息
+ current_user:undefined,
+ // 面包屑
+ bread_crumb:undefined,
+ // 当前帖子详情
+ memos:undefined,
+ // 帖子评论
+ repliesData:undefined,
+ // 帖子评论分页相关
+ replyPage:1,
+ replyPageSize:10,
+ replyCount:0,
+ is_Spin:true
+ }
+ }
+
+ componentDidMount = () =>{
+ this.getInfo();
+ }
+
+ getInfo=()=>{
+ this.InitDetailInfo();
+ this.getReply(1);
+ }
+
+ InitDetailInfo = ()=>{
+ let postid = this.props.match.params.postid;
+ const url = `/memos/${postid}.json`;
+ axios.get(url).then((result)=>{
+ if(result.data && result.data.status === -1){
+ this.props.history.push("/forums");
+ }
+ if(result){
+ this.setState({
+ judge:result.data.memo.user_praise,
+ parseNum:result.data.memo && result.data.memo.praises_count,
+ author_info:result.data.author_info,
+ current_user:result.data.current_user,
+ bread_crumb:result.data.bread_crumb,
+ memos:result.data.memo,
+ is_Spin:false
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ getReply = (replyPage) =>{
+ let postid = this.props.match.params.postid;
+ const url = `/memos/${postid}/more_reply.json`;
+ axios.get(url,{params:{
+ page:replyPage
+ }}).then((result)=>{
+ if(result){
+ this.setState({
+ repliesData:result.data.memo_replies,
+ replyCount:result.data.memos_count,
+ is_Spin:false
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 点赞
+ thumbForum = () =>{
+ let postid = this.props.match.params.postid;
+ const url = `/discusses/${postid}/plus.json`
+ axios.post(url,{
+ container_type:'Memo',
+ type:1
+ }).then((result)=>{
+ if(result){
+ this.InitDetailInfo();
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ // 切换评论分页
+ changeReplyEvent=(pageNumber)=>{
+ this.setState({
+ replyPage:pageNumber
+ })
+ this.getReply(pageNumber);
+ }
+
+ // 点击显示评论输入框
+ commentReplyEvent=(index,flag)=>{
+ console.log("2",flag);
+
+ this.setState(
+ (prevState) => ({
+ repliesData : update(prevState.repliesData, {[index]: { commentsFlag: {$set: flag} }}),
+ })
+ )
+ }
+
+ // 删除评论
+ deleteReplyEvent=(id)=>{
+ const url = `/memos/${id}/destroy.json`
+ axios.post(url).then((result)=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ let{ replyPage } = this.state;
+ this.getReply(replyPage);
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ render(){
+ let {
+ judge , parseNum , author_info , current_user , bread_crumb , memos , repliesData ,
+ replyPage,
+ replyPageSize,
+ replyCount,
+ is_Spin
+ } = this.state;
+ let postid = this.props.match.params.postid;
+
+ const NavMap=[
+ {
+ url:`/users/${current_user && current_user.login}`,
+ name:current_user && current_user.username
+ },
+ {
+ url:"/forums",
+ name:bread_crumb && bread_crumb.forum && bread_crumb.forum.title
+ },
+ {
+ url:`/forums/theme/${bread_crumb && bread_crumb.forum_tag && bread_crumb.forum_tag.id}`,
+ name:bread_crumb && bread_crumb.forum_tag && bread_crumb.forum_tag.title
+ },
+ {
+ name:"帖子详情"
+ }
+ ]
+
+ //插入字段从author_info表内选取
+ const memos_list = [{
+ ...memos,
+ image_url:author_info && author_info.image_url,
+ username:author_info && author_info.username,
+ user_login:author_info && author_info.login
+ }];
+
+ // 评论列表
+ const memo_replies = repliesData;
+ const repliesList = (
+ memo_replies && memo_replies.length > 0 &&
+
+
+ 全部回复
+ {replyCount}
+
+
+
+ )
+
+ // 附件显示
+ const fileListCom = ( memos && memos.attachment_url && )
+
+ return(
+
+
+
+
+
+
+ {/* 调用和首页共用的列表item,传了enshine就代表底部右侧操作按钮只有收藏或者取消收藏,否则就是置顶、推荐等 */}
+
+
+
+ {/* 帖子详情 */}
+
+ {/* 文件列表 */}
+ { fileListCom }
+
+ {/* 点赞 */}
+
+
+ {/* 发送评论部分 */}
+ {
+ current_user && (current_user.is_banned === false || current_user.admin) &&
+
this.getReply(replyPage)}/>
+ }
+ {/* 评论列表 */}
+ { repliesList }
+
+
+ {
+ replyCount && replyCount > replyPageSize ?
+
:""
+ }
+
+
+
+ )
+ }
+}
+
+export default Index;
\ No newline at end of file
diff --git a/src/exchange/Post/MemoNew.css b/src/exchange/Post/MemoNew.css
new file mode 100644
index 000000000..7a7cc7589
--- /dev/null
+++ b/src/exchange/Post/MemoNew.css
@@ -0,0 +1,128 @@
+.compilegoback{
+ float:right;
+ color:#676767 !important;
+ cursor: pointer;
+}
+
+.compilegodell{
+ float:right;
+ margin-right:20px;
+ color:#dadada;
+ cursor: pointer;
+}
+
+.Releasethetitle{
+ height: 48px !important;
+ padding-left: 20px !important;
+ background:#f4f4f4 !important;
+}
+.Releasethetitle:focus{
+ background:#FFF !important;
+}
+.Releasethetitle::-webkit-input-placeholder{
+ color:#999999;
+}
+.Releasethetitle:-moz-placeholder{
+ color:#999999;
+}
+.Releasethetitle::-moz-placeholder{
+ color:#999999;
+}
+.Releasethetitle:-ms-input-placeholder{
+ color:#999999;
+}
+.ecSelectbox{
+ margin-top: 30px;
+}
+
+.ant-select-selection__placeholder{
+ color:#999999;
+}
+
+.antuploadName{
+ width: 280px;
+ height: 170px;
+}
+
+.antuploadName div:nth-child(2){
+ color:#999898;
+ font-size:16px;
+}
+.antuploadName div:nth-child(3){
+ margin-top: 10px;
+ color:#d2d2d2;
+}
+.antuploadName div:nth-child(4){
+ margin-top: 10px;
+ color:#d2d2d2;
+}
+.antIconName{
+ width: 30px;
+ height: 30px;
+ background: #21B351;
+ border: 1px solid #21B351;
+ border-radius: 50%;
+ color: #FFF;
+ text-align: center;
+ line-height: 25px;
+ margin: 40px auto 12px;
+ font-size: 20px;
+ position: relative;
+ }
+ .antIconName i{
+ position: absolute;
+ top: 4px;
+ left: 3.8px;
+ }
+ .ReleasTopic{
+ color:#333;
+ font-size:18px;
+ }
+
+.ant-calendar-picker-input::-webkit-input-placeholder{
+ color:#999999;
+}
+.ant-calendar-picker-input:-moz-placeholder{
+ color:#999999;
+}
+.ant-calendar-picker-input::-moz-placeholder{
+ color:#999999;
+}
+.ant-calendar-picker-input:-ms-input-placeholder{
+ color:#999999;
+}
+.ml57{
+ margin-left:57px;
+}
+.newdefalutSubmitbtn{
+ width: 120px !important;
+ height: 38px !important;
+ line-height: 38px !important;
+ margin-top: -5px;
+}
+.newdefalutCancelbtn{
+ width: 120px !important;
+ height: 38px !important;
+ line-height: 38px !important;
+ margin-top: -5px;
+ border: 1px solid #CDCDCD;
+
+}
+.ecSelect{
+ background: #f4f4f4 !important;
+ padding-left: 4px !important;
+ height: 48px;
+ overflow: hidden;
+ width: 526px;
+ position: relative;
+}
+.newLeftgrey{
+ margin-left: 18px;
+}
+.uploadBtnclick{
+ margin-left: 34px;
+}
+.ant-select-selection--multiple{
+ height:100%;
+ border: 1px solid transparent;
+}
diff --git a/src/exchange/Post/MemoNew.js b/src/exchange/Post/MemoNew.js
new file mode 100644
index 000000000..23a557175
--- /dev/null
+++ b/src/exchange/Post/MemoNew.js
@@ -0,0 +1,811 @@
+import React, { Component } from 'react';
+
+
+import axios from 'axios';
+
+
+
+import { Select } from 'antd';
+
+import 'antd/lib/select/style/index.css'
+
+import 'antd/lib/date-picker/style/index.css'
+
+import zhCN from 'antd/lib/date-picker/locale/zh_CN';
+
+import './MemoNew.css'
+import './post.css'
+import '../exchange.css'
+
+
+import ImageUpload from './ImageUpload'
+
+const Option = Select.Option;
+
+
+const $ = window.$;
+const isDevServer = window.location.port === "3007";
+let origin = window.location.origin;
+let path = "/editormd/lib/" // origin + '/react/build/js/editormd/lib/'
+if (isDevServer) {
+ origin = 'http://localhost:3000'
+ path = 'http://localhost:3000/editormd/lib/'
+}
+
+// load
+if (!window.postUpMsg) {
+ $.getScript(
+ `${origin}/javascripts/attachments.js`,
+ (data, textStatus, jqxhr) => {
+
+ });
+}
+
+// editorMD to create
+/**
+ *
+ * @param id 渲染DOM的id
+ * @param width 宽度
+ * @param high 高度
+ * @param placeholder
+ * @param imageUrl 上传图片的url
+ * @returns {*} 返回一个editorMD实例
+ */
+function create_editorMD(id, width, high, placeholder, imageUrl, callback){
+ var editorName = window.editormd(id, {
+ width : width,
+ height : high,
+ syncScrolling : "single",
+ //你的lib目录的路径,我这边用JSP做测试的
+ path : path , // "/editormd/lib/"
+ tex : true,
+ tocm : true,
+ emoji : true,
+ taskList : true,
+ codeFold : true,
+ searchReplace : true,
+ htmlDecode : "style,script,iframe",
+ sequenceDiagram : true,
+ autoFocus: false,
+ toolbarIcons : function() {
+ // Or return editormd.toolbarModes[name]; // full, simple, mini
+ // Using "||" set icons align right.
+ return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear" ]
+ },
+ toolbarCustomIcons : {
+ testIcon : "",
+ testIcon1 : ""
+ },
+ //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。
+ saveHTMLToTextarea : true,
+ // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标
+ dialogMaskOpacity : 0.6,
+ placeholder: placeholder,
+ imageUpload : true,
+ imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"],
+ imageUploadURL : imageUrl,//url
+ onload: function(){
+ // this.previewing();
+ $("#"+ id +" [type=\"latex\"]").bind("click", function(){
+ editorName.cm.replaceSelection("```latex");
+ editorName.cm.replaceSelection("\n");
+ editorName.cm.replaceSelection("\n");
+ editorName.cm.replaceSelection("```");
+ var __Cursor = editorName.cm.getDoc().getCursor();
+ editorName.cm.setCursor(__Cursor.line-1, 0);
+ });
+
+ $("#"+ id +" [type=\"inline\"]").bind("click", function(){
+ editorName.cm.replaceSelection("$$$$");
+ var __Cursor = editorName.cm.getDoc().getCursor();
+ editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2);
+ editorName.cm.focus();
+ });
+ $("[type=\"inline\"]").attr("title", "行内公式");
+ $("[type=\"latex\"]").attr("title", "多行公式");
+
+ callback && callback()
+ }
+ });
+ return editorName;
+}
+
+
+class MemoNew extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ memoSubject: '',
+ memoContent: '',
+ memoType: undefined,
+ memoTime: undefined,
+ memoRepertoire: '',
+ memoLanguage: [],
+ fileList: [],
+ memoSubjectLength:undefined,
+ repertoires: [],
+ currentSelectRepertoiresIndex: -1,
+ repertoiresTagMap: {},
+ // 主题板块
+ smallOption:undefined,
+ bigPlateId:undefined,
+ smallPlateId:undefined,
+ }
+ }
+ onCommit() {
+ const { memoSubject , memoLanguage, currentMemoId, attachmentData , bigPlateId , smallPlateId} = this.state;
+ const { showSnackbar } = this.props;
+
+ this.setState({
+ memoSubjectLength : memoSubject.length
+ })
+
+ if (!memoSubject) {
+ showSnackbar('请先输入标题')
+ return
+ }
+ let mdVal;
+ try {
+ mdVal = this.taskpass_editormd.getValue()
+
+ } catch (e) {
+ showSnackbar('编辑器还未加载完毕,请稍后')
+ return
+ }
+
+ if (!mdVal) {
+ showSnackbar('请输入话题内容')
+ return
+ }
+ if (!bigPlateId) {
+ showSnackbar('请选择一级板块');
+ return
+ }
+ /*
+
+
+
+ http://localhost:3000/attachments/download/185790/Git-2.17.1.2-32-bit.exe
+ https://www.educoder.net/attachments/205112.js?attachment_id=1
+ */
+ // collect attachments
+ const $ = window.$;
+ const attachmentsMap = {};
+ let lastIndex = 0;
+ $('#attachments_fields .attachment').each(( index, item ) => {
+ const filename = $(item).find('.upload_filename').val();
+ // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
+ const token = $(item).find('input:nth-child(6)').val()
+ const attachment_id = $(item).find('input:nth-child(7)').val()
+ attachmentsMap[index] = {
+ filename,
+ token,
+ attachment_id
+ }
+ lastIndex = index;
+ })
+
+ if (attachmentData) {
+ const { response } = attachmentData
+ lastIndex++;
+ attachmentsMap[lastIndex] = {
+ filename: attachmentData.name,
+ token: '',
+ attachment_id: response.attachment_id
+ }
+ }
+
+ if (currentMemoId) {
+ this.updateMemo(attachmentsMap)
+ } else {
+ this.newMemo(attachmentsMap)
+ }
+ }
+ onCancel() {
+ const { currentMemoId } = this.state;
+ if (currentMemoId) { // 编辑
+ this.props.history.push(`/forums/${currentMemoId}`)
+ } else { // 新建
+ this.props.history.push(`/forums`)
+ }
+ }
+ onOkTime(value, dateString){
+ this.setState({
+ memoTime:dateString
+ })
+ }
+ updateMemo(attachmentsMap) {
+ const { memoSubject , currentMemoId, content, attachmentData , smallPlateId , bigPlateId} = this.state;
+
+ const mdVal = this.taskpass_editormd.getValue()
+ console.log('isContentEdit: ', mdVal === content);
+ const newMemoUrl = `/memos/${currentMemoId}/update`
+ const params = {
+ content_changed: this.contentChanged,
+ memo: {
+ subject: memoSubject ,
+ content: mdVal,
+ },
+ forum_id:bigPlateId,
+ attachments: attachmentsMap,
+ children_forum_id:smallPlateId
+ }
+
+ if (attachmentData) {
+ const attachment_id = attachmentData.response.attachment_id
+ if (attachment_id) {
+ params.attachment_id = attachment_id;
+ }
+ }
+ axios.post(newMemoUrl, params)
+ .then((response) => {
+ const { status, message } = response.data;
+ if (status === 0) {
+ window.$("html,body").animate({"scrollTop":0})
+ this.props.history.push(`/forums/${currentMemoId}`)
+ } else {
+ if (message.indexOf("Couldn't find Attachment with") !== -1) {
+ this.props.showSnackbar('附件不存在或正在被删除中,请稍后再试。。。')
+ } else {
+ this.props.showSnackbar(message)
+ }
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ newMemo(attachmentsMap) {
+ const { memoSubject , attachmentData , smallPlateId , bigPlateId } = this.state;
+ const mdVal = this.taskpass_editormd.getValue()
+ const newMemoUrl = `/memos/create`
+ const params = {
+ memo: {
+ subject: memoSubject ,
+ content: mdVal
+ },
+ forum_id:bigPlateId,
+ attachments: attachmentsMap,
+ children_forum_id:smallPlateId,
+ }
+ if (attachmentData) {
+ const attachment_id = attachmentData.response.attachment_id
+ if (attachment_id) {
+ params.attachment_id = attachment_id;
+ // params.filename = attachmentData.name // 服务端处理 服务端使用默认的origin_filename
+ }
+ }
+ axios.post(newMemoUrl, params).then((response) => {
+ const { status, message, memo_id } = response.data;
+ if (status === 0) {
+ window.$("html,body").animate({"scrollTop":0})
+ this.props.history.push(`/forums/${memo_id}`)
+ } else {
+ if (message.indexOf("Couldn't find Attachment with") !== -1) {
+ this.props.showSnackbar('附件不存在或正在被删除中,请稍后再试。。。')
+ } else {
+ this.props.showNotification(message)
+ }
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ onMemoDelete(memo) {
+ const deleteUrl = `/memos/${memo.id}`;
+ // 获取memo list
+ axios.delete(deleteUrl, {
+ withCredentials: true,
+ })
+ .then((response) => {
+ const status = response.data.status
+ if (status === 0) {
+ this.props.showSnackbar('删除成功');
+ this.props.history.push(`/forums`)
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ componentWillUnmount() {
+ $('body>#root').off('onMemoDelete')
+ }
+ componentDidMount(){
+ $('body>#root').on('onMemoDelete', (event) => {
+ // const val = $('body>#root').data('onMemoDelete')
+ const val = window.onMemoDelete ;
+ this.onMemoDelete( JSON.parse(decodeURIComponent(val)) )
+ })
+ const newMemoUrl = `/memos/new`
+ axios.get(newMemoUrl,{
+ // withCredentials: true,
+ })
+ .then((response) => {
+ const data = response.data;
+
+ if ( data.current_user ) {
+ this.setState({
+ memo_tag: data.memo_type,
+ memoTime:""
+ })
+
+ const user = response.data.current_user;
+ user.tidding_count = response.data.tidding_count;
+ // this.props.initCommonState(user)
+
+ // 初始化 csrf meta
+ const $ = window.$
+ $('head').append( $('') )
+ $('head').append( $(``) )
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+
+ // 如果是编辑
+ const { match } = this.props
+ const memoId = match.params.memoId;
+ if (memoId) {
+ const memoUrl = `/memos/${match.params.memoId}/edit`;
+
+ axios.get(memoUrl).then((response) => {
+ const current_user = response.data.current_user;
+ if (current_user) {
+
+ const { content, forum_section, id, subject , attachments_url, memo_image_info,
+ memo_type, published_at , children_forum_section} = response.data;
+ let date;
+ let date_value;
+ this.initMD(content, memoId);
+ if(published_at){
+ date = new Date(published_at);
+ date_value=date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
+ }
+ const newState = {
+ currentMemoId: id,
+ attachments_url,
+ memoSubject: subject,
+ memo_tag: memo_type,
+ memoLanguage: forum_section.forum_id,
+ memoTime:date_value,
+ content,
+ bigPlateId: forum_section.forum_id,
+ smallPlateId: children_forum_section.children_forum_id
+ }
+ // 编辑,初始化小板块的下拉选项(如果大板块有值)
+ this.getChildPlate(memo_type,forum_section && forum_section.forum_id);
+
+ if (memo_image_info && memo_image_info.id) {
+ newState.fileList = [{
+ uid: memo_image_info.id,
+ name: memo_image_info.filename,
+ status: 'done',
+ url: memo_image_info.url,
+ }]
+
+ newState.attachmentData = { // 初始化
+ name: memo_image_info.filename,
+ response: {
+ attachment_id: memo_image_info.id,
+ }
+ }
+ }
+ this.setState({...newState})
+
+
+ // 加载完后滚动条滚动
+ window.$("html,body").animate({"scrollTop":0})
+
+ // this.props.initForumState({
+ // current_user,
+ // tag_list
+ // })
+ }
+
+ }).catch((error) => {
+ console.log(error)
+ })
+ } else {
+ this.initMD();
+ }
+ }
+ initMD(initValue, memoId) {
+ this.contentChanged = false;
+ const placeholder = "";
+ // amp;
+ // 编辑时要传memoId
+ const imageUrl = `/upload_with_markdown?container_id=${memoId?memoId:''}&container_type=Memo`;
+ // 创建editorMd
+
+ setTimeout(()=>{
+ const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => {
+ setTimeout(()=>{
+ taskpass_editormd.resize()
+ taskpass_editormd.cm && taskpass_editormd.cm.refresh()
+ }, 500)
+
+ if (initValue) {
+ taskpass_editormd.setValue(initValue)
+ }
+ taskpass_editormd.cm.on("change", (_cm, changeObj) =>{
+ console.log('....contentChanged')
+ this.contentChanged = true;
+ })
+ });
+ this.taskpass_editormd = taskpass_editormd;
+ window.taskpass_editormd = taskpass_editormd;
+ }, 300)
+
+
+ }
+
+ renderOptions(array) {
+ const elementArray = [];
+ array.forEach(( item, index ) => {
+ elementArray.push(
+
+ )
+ })
+ return elementArray
+ }
+ onRepertoiresChange(value) {
+
+ const index = this.state.repertoires.indexOf(value)
+
+ this.setState({
+ currentSelectRepertoiresIndex: index,
+ memoRepertoire: value,
+ memoLanguage: []
+ });
+ };
+ onTagChange(value) {
+ if (value && value.length > 3) {
+ this.props.showSnackbar(`最多选择3个技术标签`)
+
+ return;
+ }
+ this.setState({
+ memoLanguage: value
+ })
+ }
+ onTypeChange(value) {
+
+ this.setState({
+ memoType: value
+ })
+ }
+ onMemoNameChange(e) {
+ this.setState({
+ memoSubject: e.target.value
+ })
+ }
+ renderMemoType() {
+ const { memo_type } = this.state;
+ if (!memo_type || memo_type.length === 0) {
+ return ''
+ }
+ const result = []
+ // memo_type.map((item, index) => )
+ memo_type.forEach((item, index) => {
+ result.push()
+ })
+
+ return result;
+ }
+ renderTag() {
+ let { memo_tag } = this.state;
+ if (!memo_tag || memo_tag.length === 0) {
+ return ''
+ }
+ const result = []
+
+ memo_tag.forEach((item, index) => {
+ result.push()
+ })
+
+ return result;
+
+ }
+ renderAttachment() {
+ const { attachments_url } = this.state;
+ const attachments = []
+ attachments_url.forEach((item, index) => {
+ const ar = item.url.split('/')
+
+ attachments.push(
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ })
+ return attachments;
+ }
+ _findById(id, arg_items) {
+ if (!arg_items) {
+ return undefined
+ }
+ const items = arg_items;
+ for(let i = 0; i < items.length; i++) {
+ if (id === items[i].id) {
+ return i;
+ }
+ }
+ }
+ // 是否是技术动态吧
+ _isTechShare() {
+ const { memoType, memo_type } = this.state
+ const index = this._findById(memoType, memo_type)
+ return !!index && memo_type[index] && memo_type[index].name.indexOf('技术问答') !== -1
+ }
+ onImageUploadDone = (data) => {
+ this.setState({
+ attachmentData: data
+ })
+ }
+ onImageUploadRemove = () => {
+ const { attachment_id } = this.state.attachmentData.response;
+ const deleteUrl = `/attachments/${attachment_id}.js?attachment_id=1`;
+ // 获取memo list
+ axios.delete(deleteUrl, {
+ withCredentials: true,
+ })
+ .then((response) => {
+ const data = response.data
+ if (data) {
+ this.setState({
+ attachmentData: undefined
+ })
+ this.props.showSnackbar('删除成功');
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+
+ // 切换大板块
+ changeLargeOption=(value)=>{
+ const { memo_tag } = this.state;
+ this.getChildPlate(memo_tag,value);
+ }
+
+ getChildPlate =(memo_tag,value)=>{
+ let listFilter = memo_tag && memo_tag.length > 0 && memo_tag.filter((item=> item.id === value))[0];
+ let list = listFilter && listFilter.children_tags;
+ this.setState({
+ smallOption:list && list.map(item=>{
+ return(
+
+ )
+ }),
+ bigPlateId:value,
+ smallPlateId: list && list.length > 0 ? (list[0].id || undefined) : undefined
+ })
+ }
+
+ // 切换二级板块
+ changeSmallOption=(value)=>{
+ this.setState({
+ smallPlateId:value
+ })
+ }
+
+ render() {
+ const { match } = this.props
+ const {
+ memoSubject ,
+ attachments_url,
+ currentMemoId,
+ fileList,
+ memoSubjectLength ,
+ memo_tag,
+ smallOption,
+ bigPlateId,
+ smallPlateId
+ } = this.state;
+ const memoId = match.params.memoId;
+ console.log("bigPlateId",bigPlateId);
+ return (
+
+
{ memoId ? '编辑' : '新建'}
+
+
+
+
+
*标题:
+
+ this.onMemoNameChange(val)} placeholder="请输入发布标题,最大限制50字符">
+
+
+
+
+ 必填项
+
+
+
+
+
+ {/* 发布时间 */}
+ {/*
+
+
+ this.onOkTime(value, dateString)}
+ />
+
+
+
+ 必填项
+
+
+
*/}
+
+ {/*
内容
*/}
+
+
+
+
+ {/* 请求status 422 X-CSRF-Token: eVo38laEF880o3cwZ/0F9kH01q4jMkriuVRemIBq06Y= */}
+
+
+ {/* 选择了技术问答才显示树标签 */}
+ {/* this._isTechShare() &&
+
+
+
技术标签
+
+
*
+
+
+
+
+
+
+
+ 必填项
+
+
+
+
+
*/}
+
+
*主题板块:
+
+ {/* */}
+ {/* */}
+
+
+
+
+
+ 必填项
+
+
+
+
+ {/* */}
+
+
上传封面:
+
+
+
+
+
+ 必填项
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+const children = [];
+for (let i = 10; i < 36; i++) {
+ children.push();
+}
+
+export default MemoNew;
diff --git a/src/exchange/Post/New.js b/src/exchange/Post/New.js
new file mode 100644
index 000000000..889e36e3f
--- /dev/null
+++ b/src/exchange/Post/New.js
@@ -0,0 +1,277 @@
+import React, { PureComponent } from 'react';
+
+import {appendFileSizeToUploadFileAll ,appendFileSizeToUploadFile} from 'educoder';
+import { Form , Input , Upload ,Button , Select , Icon , message } from "antd";
+import './post.css'
+import '../exchange.css'
+
+import axios from 'axios';
+
+import MDEditor from '../../common/MDEditor';
+
+const Option = Select.Option;
+const uploadButton = (
+
+
+
点击上传封面
+
只支持JPG、PNG、JPEG大小不超过2M建议尺寸4:3
+
+)
+
+function getBase64(img, callback) {
+ debugger;
+ const reader = new FileReader();
+ reader.addEventListener('load', () => callback(reader.result));
+ reader.readAsDataURL(img);
+}
+
+
+class New extends PureComponent{
+ constructor(props){
+ super(props);
+ this.contentMdRef = React.createRef();
+ this.state={
+ // 封面图
+ imageUrl:undefined,
+ // 大板块下拉选项
+ memo_type:undefined,
+ // 小板块
+ smallOption:undefined,
+ // 附件列表
+ contentFileList:undefined,
+ }
+ }
+
+ componentDidMount = () =>{
+ this.getInfo();
+ }
+
+ // 获取信息
+ getInfo = () =>{
+ let url = '/memos/new';
+ axios.get((url)).then((result)=>{
+ if(result){
+ this.setState({
+ memo_type:result.data.memo_type
+ })
+ }
+ }).catch((error)=>{
+
+ })
+ }
+
+ changeUploadImage =(info)=>{
+ if (info.file.status === 'done') {
+ // Get this url from response in real world.
+ getBase64(info.file.originFileObj, imageUrl =>
+ this.setState({
+ imageUrl
+ }),
+ );
+ }
+ }
+
+ // 切换大板块
+ changeLargeOption=(value)=>{
+ // console.log(value);
+ const { memo_type } = this.state;
+ let list = memo_type.filter((item=> item.id === value))[0].children_tags;
+ // console.log(list);
+ this.setState({
+ smallOption:list && list.map(item=>{
+ return(
+
+ )
+ })
+ })
+ }
+
+ // 提交
+ handleSubmit=()=>{
+ this.props.form.validateFieldsAndScroll((err, values) => {
+ console.log(values);
+ if(!err){
+ let url=`/memos.json`;
+ axios.post((url),{
+ forum_id:values.bigPlate,
+ children_forum_id:values.smallPlate,
+ memo:{
+ subject:values.title,
+ content:values.description
+ }
+ }).then(result=>{
+ if(result){
+ this.props.showNotification(result.data.message);
+ this.props.history.push(`/forums/${result.data && result.data.memo_id}`);
+ }
+ }).catch(error=>{
+
+ })
+ }
+ })
+ }
+
+ // 上传附件
+ handleContentUploadChange = (info) => {
+ console.log("changeFIle==================>",info);
+ if (info.file.status === 'done' || info.file.status === 'uploading' || info.file.status === 'removed') {
+ let contentFileList = info.fileList;
+ this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList)});
+ let list = appendFileSizeToUploadFileAll(contentFileList);
+ let arr = list.map(item=>{
+ return ( item.response && item.response.id )
+ })
+ this.setState({
+ filesID:arr,
+ checkFile:arr.length > 0 ? false : true
+ })
+ }
+ }
+ // 上传附件-删除确认框
+ onAttachmentRemove = (file, stateName) => {
+ if(!file.percent || file.percent == 100){
+ this.props.confirm({
+ content: '是否确认删除?',
+ onOk: () => {
+ this.deleteAttachment(file, stateName)
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ return false;
+ }
+ }
+
+ deleteAttachment=(file,list)=>{
+ console.log("delete===============>",file)
+ }
+
+
+ render(){
+ const { getFieldDecorator } = this.props.form;
+
+ /** 上传封面图 */
+ let { imageUrl , memo_type , smallOption , contentFileList } = this.state;
+
+ const largeOption = memo_type && memo_type.length > 0 && memo_type.map(item=>{
+ return(
+
+ )
+ })
+
+ let uploadImg = ( imageUrl ?
: uploadButton )
+
+ // 上传封面图
+ const uploadCover = {
+ listType:"picture-card",
+ className:"avatar-uploader",
+ showUploadList:false,
+ action:`/uploads.js`,
+ data: { attachment_id: 1 },
+ onChange:this.changeUploadImage,
+ }
+
+ /**上传附件 */
+ const uploadProps = {
+ width: 600,
+ fileList: contentFileList,
+ multiple: true,
+ action: 'http://127.0.0.1:3000/uploads.js',
+ 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;
+ },
+ };
+ return(
+
+
新建
+
+
+ {getFieldDecorator('title', {
+ rules: [{
+ required: true, message: '请输入帖子标题',
+ },{
+ max: 5000 , message:'最大限制60个字符'
+ }],
+ })(
+
+ )}
+
+
+ {getFieldDecorator('description', {
+ rules: [{
+ required: true, message: '请输入帖子内容',
+ },{
+ max: 5000 , message:'最大限制5000个字符'
+ }],
+ })(
+
+ )}
+
+
+
+
+
+
+ {
+ getFieldDecorator('bigPlate',{
+ rules:[{
+ required:true,message:'请选择大板块'
+ }]
+ })(
+
+ )
+ }
+
+
+ {
+ getFieldDecorator('smallPlate',{
+ rules:[{
+ required:true,message:'请选择小板块'
+ }]
+ })(
+
+ )
+ }
+
+
+
+
+
+ {uploadImg}
+
+
+
+
+
+
+ 取消
+
+
+
+
+
+ )
+ }
+}
+
+const WrappedNewPostForm = Form.create({ name: 'New' })(New);
+export default WrappedNewPostForm;
\ No newline at end of file
diff --git a/src/exchange/Post/Parse.js b/src/exchange/Post/Parse.js
new file mode 100644
index 000000000..2cb38398a
--- /dev/null
+++ b/src/exchange/Post/Parse.js
@@ -0,0 +1,33 @@
+import React, { PureComponent } from 'react';
+
+class Parse extends PureComponent{
+
+ render(){
+ let { judge , num , clickEvent ,current_user} = this.props;
+
+ const info = (
+ current_user? (judge ?
+
+
+ {num}
+
+ :
+
+
+ {num}
+
+ ):
+
+
+ {num}
+
+ )
+ return(
+
+ { info }
+
+ )
+ }
+}
+
+export default Parse;
\ No newline at end of file
diff --git a/src/exchange/Post/post.css b/src/exchange/Post/post.css
new file mode 100644
index 000000000..f9062c427
--- /dev/null
+++ b/src/exchange/Post/post.css
@@ -0,0 +1,157 @@
+.postDetail{
+ padding:20px 0px;
+}
+.postContent{
+ margin:0px 30px;
+ border-top: 1px solid #f4f4f4;
+}
+
+.fileTeam{
+ padding-bottom: 40px;
+}
+.fileTeam > li {
+ height: 18px;
+ line-height: 18px;
+ margin-bottom: 10px;
+}
+
+/* parse.js */
+.forumParse{
+ width: 72px;
+ height: 72px;
+ display: inline-flex;
+ align-items: center;
+ flex-flow: column;
+ background: #5091FF;
+ color: #fff!important;
+ border-radius: 50%;
+ padding-top: 7px;
+}
+.forumParse.parsed{
+ background:#999999;
+}
+
+/* 评论 */
+.replyTitle{
+ line-height: 30px;
+ padding:20px;
+ border-bottom: 1px solid #f4f4f4;
+}
+.pre_stage{
+ border-bottom: 1px solid #f4f4f4;
+ padding : 10px 0px;
+}
+.pre_stage:last-child{
+ border-bottom: none;
+}
+.pre_stage .sub_stage{
+ padding: 10px 20px;
+ box-sizing: border-box;
+ background: #fafafa;
+ position: relative;
+ margin-top: 20px;
+ border-radius:4px;
+}
+.pre_stage .sub_stage::before{
+ position: absolute;
+ content: "";
+ top:-20px;
+ z-index: 1;
+ left: 20px;
+ width: 0;
+ height: 0;
+ border-width: 10px;
+ border-style: solid;
+ border-color: transparent transparent #fafafa transparent;
+}
+.commentsItem_infos{
+ display: flex;
+ padding:10px 0px 10px;
+}
+.commentsItem_infos .markdown-body{
+ padding:0px;
+}
+.commentsItem_infos .editormd-html-preview,.commentsItem_infos .editormd-preview-container{
+ background-color: unset;
+}
+
+/* 新建 */
+.postNewform.ant-form .ant-row{
+ display: flex;
+ align-items: top;
+}
+.postNewform.ant-form .ant-form-item-control-wrapper{
+ flex: 1;
+}
+.postNewform.ant-form .ant-form-item-label,.postNewform .new_label{
+ width: 90px;
+ text-align: right;
+ margin-right: 8px;
+ height: 40px;
+ line-height: 40px;
+ margin-top: 3px;
+ font-size: 16px
+}
+.postNewform.ant-form label{
+ font-size: 16px;
+ color: #333;
+}
+.editorFromItem {
+ align-items: flex-start!important;
+ margin-bottom: 0px!important;
+}
+.editorFromItem .editormd.editormd-vertical{
+ margin-bottom: 0px;
+}
+.editorFromItem .rememberTip{
+ height: 20px;
+ line-height: 20px;
+}
+.newPostUpload{
+ margin-left: 84px;
+}
+.newPostUpload .uploadBtn{
+ border:none;
+ box-shadow: none;
+ color:#5091FF;
+ line-height: 30px;
+}
+.newPostUpload .ant-upload-list{
+ padding-left: 100px;
+}
+.newPostUpload .ant-upload-list-item-info{
+ padding:0px;
+ font-size: 15px;
+ height: 24px;
+ line-height: 24px;
+ max-width: 500px;
+ position: relative;
+}
+.selectItem .ant-select-selection--single{
+ width: 200px;
+ margin-right: 20px;
+ height: 40px;
+}
+.selectItem .ant-select-selection__rendered{
+ line-height: 40px;
+}
+/* 上传封面 */
+.uploadImageBox .ant-upload-picture-card-wrapper{
+ width: 340px;
+ height: 248px;
+ border:none;
+ background: #fafafa;
+ display: flex;
+ flex-direction: column;
+ padding:0px 60px;
+ color: #999;
+}
+.uploadImageBox .ant-upload.ant-upload-select-picture-card{
+ width: 100%;
+ height: 100%;
+ border: none;
+}
+.uploadImageBox .ant-upload.ant-upload-select-picture-card i{
+ font-size: 44px!important;
+ color:#999;
+}
\ No newline at end of file
diff --git a/src/exchange/SearchInfoComponent/Index.js b/src/exchange/SearchInfoComponent/Index.js
new file mode 100644
index 000000000..0e527b237
--- /dev/null
+++ b/src/exchange/SearchInfoComponent/Index.js
@@ -0,0 +1,16 @@
+import React, { PureComponent } from 'react';
+
+class Index extends PureComponent {
+
+ render(){
+ const {count, returnEvent} = this.props;
+ return(
+
+ 共找到相关结果{count}个
+ 返回
+
+ )
+ }
+}
+
+export default Index;
diff --git a/src/exchange/TagComponent/Index.js b/src/exchange/TagComponent/Index.js
new file mode 100644
index 000000000..2b670f448
--- /dev/null
+++ b/src/exchange/TagComponent/Index.js
@@ -0,0 +1,18 @@
+import React, { PureComponent } from 'react';
+
+import { getImageUrl } from 'educoder';
+
+class Index extends PureComponent {
+
+ render(){
+ let { topClass , bestClass } = this.props;
+ return(
+
+ { topClass &&
}
+ { bestClass &&
}
+
+ )
+ }
+}
+
+export default Index;
\ No newline at end of file
diff --git a/src/exchange/exchange.css b/src/exchange/exchange.css
new file mode 100644
index 000000000..439cc4c4f
--- /dev/null
+++ b/src/exchange/exchange.css
@@ -0,0 +1,289 @@
+.newContainer{
+ padding:60px 0px 120px 0px;
+}
+ul,p{
+ margin: 0px;
+}
+.flex1{
+ flex: 1;
+ width: 0
+}
+.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-nav .ant-tabs-tab:hover{
+ color:#21B350!important;
+}
+/* shownotification的z-index */
+.ant-notification{
+ z-index: 100000;
+}
+/* 小按钮 */
+.small-default-btn{
+ height: 24px;
+ line-height: 24px;
+ padding: 0px 15px;
+ font-size: 12px;
+ background:rgba(244,244,244,1);
+ border-radius:2px;
+ color: #999;
+ display: inline-block;
+}
+.middle-default-btn{
+ height: 30px;
+ line-height: 30px;
+ padding: 0px 15px;
+ font-size: 12px;
+ background:rgba(244,244,244,1);
+ border-radius:2px;
+ color: #999;
+ display: inline-block;
+}
+.small-blue-btn{
+ background:rgba(80,145,255,1);
+ color:rgba(255,255,255,1);
+}
+.small-green-btn{
+ background:#21B350;
+ color:rgba(255,255,255,1)!important;
+}
+.educontent{
+ width: 1200px;
+ margin:0px auto;
+}
+.educontent-min{
+ width: 960px;
+ margin:0px auto;
+}
+.F_panel{
+ width: 1200px;
+ display: flex;
+ margin:30px auto;
+}
+.f_left_head{
+ display: flex;
+ justify-content:space-between;
+ border-bottom: 1px solid #eaeaea;
+ padding-left:30px;
+ background: #fff;
+}
+.f_left_head > ul{
+ display: flex;
+ align-items: center;
+ height:80px;
+ margin-bottom: 0px;
+}
+.f_left_head > ul >li{
+ margin-right: 30px;
+ color: #666666
+}
+.f_left_head > ul >li a{
+ color: #666666
+}
+.f_left_head > ul:first-child > li{
+ font-size: 16px;
+ position: relative;
+ color: #333;
+}
+.f_left_head > ul:first-child > li.active a{
+ color: #5091FF;
+}
+.f_left_head > ul:first-child > li.active a:after{
+ position: absolute;
+ width: 100%;
+ bottom: -25px;
+ height: 2px;
+ background: #5091FF;
+ content: '';
+ left: 0px;
+}
+.platePanel{
+ top: 24px;
+ background: #fff;
+ left: 0px;
+ box-shadow:0px 6px 16px 0px rgba(7,12,70,0.2);
+ border-radius:4px;
+ max-width: 770px;
+ max-height: 500px;
+ padding:10px 10px 0px 10px;
+ overflow: auto;
+ box-sizing: border-box;
+}
+.platePanel .plateItem{
+ display: flex;
+ padding-bottom:10px;
+ box-sizing: border-box;
+}
+.platePanel .plateItem .plateItem_h{
+ color: #333;
+ margin:5px 20px 0px 10px;
+}
+.plateUl{
+ flex: 1;
+}
+.plateUl li{
+ position: relative;
+ margin-right: 11px;
+ color: #666;
+ float: left;
+ padding:5px 0px;
+ box-sizing: border-box;
+ margin-left: 10px;
+}
+.plateUl li:after{
+ width: 1px;
+ position: absolute;
+ right: -12px;
+ height:10px;
+ background: #ccc;
+ top:11px;
+ content: ''
+}
+.plateUl li:last-child:after{
+ display:none;
+}
+.radius{
+ border-radius: 50%;
+}
+.flex1{
+ flex: 1;
+}
+.color-blue {
+ color: #5091FF!important;
+}
+.flex-align-center{
+ display: flex;
+ align-items: center;
+}
+.flex-align-top{
+ display: flex;
+ align-items: flex-start;
+}
+.flex-align-bottom{
+ display: flex;
+ align-items: flex-end;
+}
+/* 列表 */
+.plateTabulation{
+ padding: 0px 30px;
+ box-sizing: border-box;
+ background: #fff;
+}
+.plateTabulation > li{
+ border-bottom: 1px solid #f4f4f4;
+ padding:20px 0px;
+}
+.plateTabulation > li:last-child{
+ border-bottom: none;
+}
+.exchangeItem-subject{
+ font-size: 16px;
+ color: #333;
+ flex:1;
+ height: 20px;
+ line-height: 20px;
+ margin-right: 20px;
+}
+.flex_h{
+ display: flex;
+ align-items: center
+}
+.sendPoint{
+ font-size: 12px;
+ color: #999;
+ position: relative;
+ margin-left: 20px;
+ height: 18px;
+ line-height: 18px;
+}
+.sendPoint::before{
+ position: absolute;
+ left: -10px;
+ top:3px;
+ height:12px;
+ width:1px ;
+ content: '';
+ background: #ccc;
+}
+p{
+ margin:0px;padding:0px
+}
+.edu-txt-center .ant-dropdown-menu-item,.edu-txt-center .ant-dropdown-menu-submenu-title{
+ text-align: center;
+}
+.c_point{
+ cursor: pointer;
+}
+
+.top_Operate{
+ position: relative;
+ background: #fff;
+ padding:20px;
+ margin-bottom: 20px;
+}
+
+.top_Operate .send_btn{
+ width: 188px;
+ height: 40px;
+ background: #5091ff;
+ text-align: center;
+ color: #fff;
+ font-size: 16px;
+ line-height: 40px;
+ display: block;
+ border-radius: 4px;
+}
+.top_Operate .searchfrom{
+ position: absolute;
+ width: 40px;
+ right:20px;
+ top:20px;
+}
+.top_Operate .searchfrom.ant-input-affix-wrapper .ant-input-suffix{
+ right:-2px
+}
+.top_Operate .searchfrom .ant-input-search-icon svg{
+ width: 3em;
+ height: 1.3em;
+}
+.top_Operate .searchfrom.active{
+ width: 250px;
+ z-index: 10;
+}
+.r_part_title{
+ border-bottom: 1px solid #F4F4F4;
+ padding:20px;
+}
+.r_part_list{
+ padding:20px;
+}
+.r_part_list li{
+ margin-bottom: 20px;
+ color: #333;
+}
+.r_part_list li:last-child{
+ margin-bottom: 0px;
+}
+/* InfoComponent */
+.icon-wrap{
+ margin-left: 30px;
+ color: #ccc;
+ float: left;
+ line-height: 20px;
+}
+.icon-wrap > i{
+ margin-right: 5px;
+ float: left;
+}
+/*給下拉列表的……添加高宽*/
+.addheight{
+ background: url(./images/more.png) no-repeat right;
+ width: 30px;
+ height: 20px;
+
+}
+/*帖子列表标题点击变颜色*/
+.is_onclick:hover{
+ color: #5091FF;
+}
+/*帖子详情标题颜色不变*/
+.color_black{
+ color: black;
+}
\ No newline at end of file
diff --git a/src/exchange/images/box1.png b/src/exchange/images/box1.png
new file mode 100644
index 000000000..dacf54e34
Binary files /dev/null and b/src/exchange/images/box1.png differ
diff --git a/src/exchange/images/box2.png b/src/exchange/images/box2.png
new file mode 100644
index 000000000..e7d68225c
Binary files /dev/null and b/src/exchange/images/box2.png differ
diff --git a/src/exchange/images/box3.png b/src/exchange/images/box3.png
new file mode 100644
index 000000000..f1fb2e4fa
Binary files /dev/null and b/src/exchange/images/box3.png differ
diff --git a/src/exchange/images/box4.png b/src/exchange/images/box4.png
new file mode 100644
index 000000000..34054d3e6
Binary files /dev/null and b/src/exchange/images/box4.png differ
diff --git a/src/exchange/images/box5.png b/src/exchange/images/box5.png
new file mode 100644
index 000000000..072c174fa
Binary files /dev/null and b/src/exchange/images/box5.png differ
diff --git a/src/exchange/images/box6.png b/src/exchange/images/box6.png
new file mode 100644
index 000000000..0215a25d6
Binary files /dev/null and b/src/exchange/images/box6.png differ
diff --git a/src/exchange/images/more.png b/src/exchange/images/more.png
new file mode 100644
index 000000000..c665263f2
Binary files /dev/null and b/src/exchange/images/more.png differ
diff --git a/src/exchange/images/nodata.png b/src/exchange/images/nodata.png
new file mode 100644
index 000000000..7c01edf3b
Binary files /dev/null and b/src/exchange/images/nodata.png differ
diff --git a/src/exchange/index.js b/src/exchange/index.js
new file mode 100644
index 000000000..761e4f0b0
--- /dev/null
+++ b/src/exchange/index.js
@@ -0,0 +1,91 @@
+import React, { Component } from 'react';
+import { Route , Switch } from 'react-router-dom';
+
+import { TPMIndexHOC } from '../modules/tpm/TPMIndexHOC';
+import { SnackbarHOC , CNotificationHOC } from 'educoder';
+
+import ExchangeIndex from './ExchangeIndex';
+
+import Post from './Post/Index'
+import PostNew from './Post/MemoNew';
+import PlateIndex from './Plate/Index';
+import MyExchange from './MyExchange/Index'
+import PreManager from './Manage/PreModerator'
+import axios from 'axios';
+import './exchange.css';
+
+class Index extends Component{
+ constructor(props){
+ super(props);
+ this.state={
+ current_user:undefined
+ }
+ }
+
+ componentDidMount=()=>{
+ const url = `/users/get_user_info.json`;
+ axios.get(url).then(result=>{
+ if(result){
+ this.setState({
+ current_user:result.data.current_user
+ })
+ // 给NewHeader传值,当前用户的信息
+ if(result.data.current_user && result.data.current_user.login){
+ this.props.initCommonState(result.data.current_user);
+ }
+ }
+ }).catch(error=>{
+
+ })
+ }
+
+ render(){
+ return(
+
+ {/* 帖子列表 */}
+ ()
+ } >
+ {/* 编辑帖子 */}
+ {
+ return ()}
+ }>
+ {/* 新建帖子 */}
+ {
+ return ()}
+ }>
+ {/* 版主管理 */}
+ {
+ return ()}
+ }>
+
+ {/* 我的话题 */}
+ {
+ return ()}
+ }>
+ {
+ return ()}
+ }>
+ {
+ return ()}
+ }>
+ {/* 帖子详情 */}
+ {
+ return ()}
+ }>
+ {/* 论坛首页 */}
+ ()
+ }>
+
+ )
+ }
+}
+export default SnackbarHOC() (CNotificationHOC() (TPMIndexHOC ( Index ))) ;
\ No newline at end of file
diff --git a/src/forums/New.jsx b/src/forums/New.jsx
index ddb6efe90..b20d60274 100644
--- a/src/forums/New.jsx
+++ b/src/forums/New.jsx
@@ -8,7 +8,6 @@ import Attachments from '../forge/Upload/attachment';
import "./css/All.scss";
import axios from "axios";
-const TextArea = Input.TextArea;
const Option = Select.Option;
// forum_id: values.forum_id, //大主题版块的id, int类型 (必填)