diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index d49e28d80..18e8a160d 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -924,16 +924,23 @@ class CoursesController < ApplicationController course_message = CourseMessage.new(course_id: course.id, user_id: course.tea_id, status: 0, course_message_id: current_user.id, course_message_type: "JoinCourseRequest", viewed: false) - course_message.content = 2 if params[:professor].present? && params[:professor].to_i == 1 - course_message.content = 3 if params[:assistant_professor].present? && params[:assistant_professor].to_i == 1 + if params[:professor].present? && params[:professor].to_i == 1 + course_message.content = 2 + role = 9 + message = "教师申请已提交,请等待审核" + else + course_message.content = 3 + role = 7 + message = "助教申请已提交,请等待审核" + end course_message.save! - role = course_message.content == 2 ? '9' : '7' # 7:助教 9:教师 + # role = course_message.content == 2 ? '9' : '7' # 7:助教 9:教师 ApplyTeacherRoleJoinCourseNotifyJob.perform_later(current_user.id, course.id, role) - message = "#{course_message.content == 2 ? '教师' : '助教'}申请已提交,请等待审核" + # message = "#{course_message.content == 2 ? '教师' : '助教'}申请已提交,请等待审核" else - message = "#{existing_course_message.content == 2 ? '教师' : '助教'}申请已提交,请等待审核" + message = "#{existing_course_message.content == '2' ? '教师' : '助教'}申请已提交,请等待审核" end else message = "您已是课堂成员" diff --git a/app/models/course_message.rb b/app/models/course_message.rb index 77c86e3e5..42cbe00c8 100644 --- a/app/models/course_message.rb +++ b/app/models/course_message.rb @@ -11,7 +11,7 @@ class CourseMessage < ApplicationRecord def pass! update!(status: :PASSED) - send_deal_tiding + send_deal_tiding(1) end def application_user @@ -20,16 +20,16 @@ class CourseMessage < ApplicationRecord def reject! update!(status: :REJECTED) - send_deal_tiding + send_deal_tiding(2) end private - def send_deal_tiding + def send_deal_tiding deal_status # 发送申请处理结果消息 Tiding.create!( user_id: course_message_id, trigger_user: User.current, container_id: course_id, container_type: 'DealCourse', - belong_container: course, extra: content.to_i == 2 ? '7' : '9', tiding_type: 'System', status: status == :PASSED ? 1 : 2 + belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status ) # 将申请消息置为已处理 Tiding.where(trigger_user_id: user_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1) diff --git a/public/react/src/modules/courses/boards/BoardsNew.js b/public/react/src/modules/courses/boards/BoardsNew.js index 56dddff7c..cea4f47aa 100644 --- a/public/react/src/modules/courses/boards/BoardsNew.js +++ b/public/react/src/modules/courses/boards/BoardsNew.js @@ -1,449 +1,449 @@ -import React,{ Component } from "react"; - -import { - Form, Input, InputNumber, Switch, Radio, - Slider, Button, Upload, Icon, Rate, Checkbox, message, - Row, Col, Select, Modal, Divider -} from 'antd'; -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; -import axios from 'axios' -import './board.css' -import "../common/formCommon.css" -import AddDirModal from './AddDirModal' -import { RouteHOC } from './common.js' -import CBreadcrumb from '../common/CBreadcrumb' -import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder'; - -const confirm = Modal.confirm; -const $ = window.$ -const { Option } = Select; -// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652 -class BoardsNew extends Component{ - constructor(props){ - super(props); - - this.mdRef = React.createRef(); - - this.state = { - fileList: [], - boards: [], - title_num: 60 - } - } - addSuccess = () => { - this.fetchBoards() - } - fetchBoards = () => { - const isEdit = this.isEdit - const boardId = this.props.match.params.boardId - - const boardsUrl = `/courses/board_list.json?board_id=${boardId}` - axios.get(boardsUrl, { }) - .then((response) => { - if (response.data.status == 0) { - this.setState({ - boards: response.data.data.boards || [], - course_id: response.data.data.course_id - }) - if (!isEdit) { - response.data.data.boards.forEach( board => { - if (board.id == boardId) { - this.setState({ board_name: board.name }) - } - }) - // board_name - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - componentDidMount = () => { - - const topicId = this.props.match.params.topicId - const isEdit = !!topicId - this.isEdit = isEdit - - const boardId = this.props.match.params.boardId - - this.fetchBoards() - - if (isEdit) { - const url = `/messages/${topicId}.json` - axios.get(url, { - }) - .then((response) => { - if (response.data.status == 0) { - const { id, data } = response.data; - if (data) { - this.editTopic = data; - this.props.form.setFieldsValue({ - sticky: !!data.sticky, - content: data.content, - subject: data.subject, - select_board_id: data.board_id // TODO 没返回给前端 - }); - this.mdRef.current.setValue(data.content) - const _fileList = data.attachments.map(item => { - return { - id: item.id, - uid: item.id, - name: appendFileSizeToUploadFile(item), - url: item.url, - status: 'done' - } - }) - - this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) }) - } - } - }) - .catch(function (error) { - console.log(error); - }); - } else { - const boardId = this.props.match.params.boardId - - this.props.form.setFieldsValue({ - select_board_id: parseInt(boardId) - }); - } - } - handleSubmit = (e) => { - e.preventDefault(); - const cid = this.state.course_id - const boardId = this.props.match.params.boardId - - this.props.form.validateFieldsAndScroll((err, values) => { - if (!err) { - console.log('Received values of form: ', values); - if (this.isEdit == true) { - const editTopic = this.editTopic - const editUrl = `/messages/${editTopic.id}.json` - - let attachment_ids = undefined - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - axios.put(editUrl, { - subject: values.subject, - select_board_id: values.select_board_id, - content: values.content, - sticky: values.sticky, - attachment_ids, - }) - .then((response) => { - if (response.data.status == 0) { - const { id } = response.data; - console.log('--- success') - - this.props.toDetailPage(cid, values.select_board_id, editTopic.id) - } - }) - .catch(function (error) { - console.log(error); - }); - } else { - const url = `/boards/${boardId}/messages.json` - let attachment_ids = undefined - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response.id - }) - } - - axios.post(url, { - ...values, - course_id: cid, - attachment_ids, - }) - .then((response) => { - if (response.data.data && response.data.status == 0) { - const { id } = response.data.data; - if (id) { - console.log('--- success') - this.props.toDetailPage(cid, values.select_board_id, id) - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - } else { - $("html").animate({ scrollTop: $('html').scrollTop() - 100 }) - } - }); - } - // 附件相关 START - handleChange = (info) => { - let fileList = info.fileList; - this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) - }); - } - onAttachmentRemove = (file) => { - confirm({ - // title: '确定要删除这个附件吗?', - title: '是否确认删除?', - - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - - - return false; - } - deleteAttachment = (file) => { - // 初次上传不能直接取uid - const url = `/attachments/${file.response ? file.response.id : file.uid}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - console.log('--- success') - - this.setState((state) => { - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - // 附件相关 ------------ END - changeTitle=(e)=>{ - console.log(e.target.value.length); - this.setState({ - title_num: 60 - parseInt(e.target.value.length) - }) - } - render() { - let { addGroup, fileList, course_id, title_num } = this.state; - const { getFieldDecorator } = this.props.form; - const { current_user } = this.props - - const formItemLayout = { - labelCol: { - xs: { span: 24 }, - // sm: { span: 8 }, - sm: { span: 24 }, - }, - wrapperCol: { - xs: { span: 24 }, - // sm: { span: 16 }, - sm: { span: 24 }, - }, - }; - - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file) => { - console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 150; - if (!isLt150M) { - message.error('文件大小必须小于150MB!'); - } - return isLt150M; - }, - }; - const isAdmin = this.props.isAdmin() - const courseId=this.props.match.params.coursesId; - const boardId = this.props.match.params.boardId - - return( -
- - -
- - -

- {this.isEdit ? "编辑" : "新建"}帖子 - this.props.history.goBack()}> - 返回 - -

- {/* notRequired */} -
-
- { isAdmin && - - {getFieldDecorator('sticky', { - valuePropName: 'checked', - })( - isAdmin && 置顶 - )} - {/* checkbox 有个边距样式 .ant-checkbox-wrapper + span, */} - - - } - - - {getFieldDecorator('subject', { - rules: [{ - required: true, message: '请输入标题', - }, { - max: 60, message: '最大限制为60个字符', - }], - })( - - )} - - - - {getFieldDecorator('select_board_id', { - // initialValue: '3779', - })( - - )} - - - {/* { isAdmin && - {getFieldDecorator('sticky', { - })( - 置顶 - )} - } */} -
- - - -
- - - {getFieldDecorator('content', { - rules: [{ - required: true, message: '请输入帖子内容', - }, { - max: 10000, message: '最大限制为10000个字符', - }], - })( - - )} - - - - - (单个文件150M以内) - -
- - -
- - this.isEdit ? - this.props.toDetailPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) : - this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) }>取消 -
-
- -
-
- ) - } -} - -const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew); +import React,{ Component } from "react"; + +import { + Form, Input, InputNumber, Switch, Radio, + Slider, Button, Upload, Icon, Rate, Checkbox, message, + Row, Col, Select, Modal, Divider +} from 'antd'; +import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; +import axios from 'axios' +import './board.css' +import "../common/formCommon.css" +import AddDirModal from './AddDirModal' +import { RouteHOC } from './common.js' +import CBreadcrumb from '../common/CBreadcrumb' +import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder'; + +const confirm = Modal.confirm; +const $ = window.$ +const { Option } = Select; +// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652 +class BoardsNew extends Component{ + constructor(props){ + super(props); + + this.mdRef = React.createRef(); + + this.state = { + fileList: [], + boards: [], + title_num: 60 + } + } + addSuccess = () => { + this.fetchBoards() + } + fetchBoards = () => { + const isEdit = this.isEdit + const boardId = this.props.match.params.boardId + + const boardsUrl = `/courses/board_list.json?board_id=${boardId}` + axios.get(boardsUrl, { }) + .then((response) => { + if (response.data.status == 0) { + this.setState({ + boards: response.data.data.boards || [], + course_id: response.data.data.course_id + }) + if (!isEdit) { + response.data.data.boards.forEach( board => { + if (board.id == boardId) { + this.setState({ board_name: board.name }) + } + }) + // board_name + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + componentDidMount = () => { + + const topicId = this.props.match.params.topicId + const isEdit = !!topicId + this.isEdit = isEdit + + const boardId = this.props.match.params.boardId + + this.fetchBoards() + + if (isEdit) { + const url = `/messages/${topicId}.json` + axios.get(url, { + }) + .then((response) => { + if (response.data.status == 0) { + const { id, data } = response.data; + if (data) { + this.editTopic = data; + this.props.form.setFieldsValue({ + sticky: !!data.sticky, + content: data.content, + subject: data.subject, + select_board_id: data.board_id // TODO 没返回给前端 + }); + this.mdRef.current.setValue(data.content) + const _fileList = data.attachments.map(item => { + return { + id: item.id, + uid: item.id, + name: appendFileSizeToUploadFile(item), + url: item.url, + status: 'done' + } + }) + + this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) }) + } + } + }) + .catch(function (error) { + console.log(error); + }); + } else { + const boardId = this.props.match.params.boardId + + this.props.form.setFieldsValue({ + select_board_id: parseInt(boardId) + }); + } + } + handleSubmit = (e) => { + e.preventDefault(); + const cid = this.state.course_id + const boardId = this.props.match.params.boardId + + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + console.log('Received values of form: ', values); + if (this.isEdit == true) { + const editTopic = this.editTopic + const editUrl = `/messages/${editTopic.id}.json` + + let attachment_ids = undefined + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + } + axios.put(editUrl, { + subject: values.subject, + select_board_id: values.select_board_id, + content: values.content, + sticky: values.sticky, + attachment_ids, + }) + .then((response) => { + if (response.data.status == 0) { + const { id } = response.data; + console.log('--- success') + + this.props.toDetailPage(cid, values.select_board_id, editTopic.id) + } + }) + .catch(function (error) { + console.log(error); + }); + } else { + const url = `/boards/${boardId}/messages.json` + let attachment_ids = undefined + if (this.state.fileList) { + attachment_ids = this.state.fileList.map(item => { + return item.response.id + }) + } + + axios.post(url, { + ...values, + course_id: cid, + attachment_ids, + }) + .then((response) => { + if (response.data.data && response.data.status == 0) { + const { id } = response.data.data; + if (id) { + console.log('--- success') + this.props.toDetailPage(cid, values.select_board_id, id) + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + } else { + $("html").animate({ scrollTop: $('html').scrollTop() - 100 }) + } + }); + } + // 附件相关 START + handleChange = (info) => { + let fileList = info.fileList; + this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) + }); + } + onAttachmentRemove = (file) => { + confirm({ + // title: '确定要删除这个附件吗?', + title: '是否确认删除?', + + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + + + return false; + } + deleteAttachment = (file) => { + // 初次上传不能直接取uid + const url = `/attachments/${file.response ? file.response.id : file.uid}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + console.log('--- success') + + this.setState((state) => { + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + }; + }); + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + // 附件相关 ------------ END + changeTitle=(e)=>{ + console.log(e.target.value.length); + this.setState({ + title_num: 60 - parseInt(e.target.value.length) + }) + } + render() { + let { addGroup, fileList, course_id, title_num } = this.state; + const { getFieldDecorator } = this.props.form; + const { current_user } = this.props + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + // sm: { span: 8 }, + sm: { span: 24 }, + }, + wrapperCol: { + xs: { span: 24 }, + // sm: { span: 16 }, + sm: { span: 24 }, + }, + }; + + const uploadProps = { + width: 600, + fileList, + multiple: true, + // https://github.com/ant-design/ant-design/issues/15505 + // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // showUploadList: false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file) => { + console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 150; + if (!isLt150M) { + message.error('文件大小必须小于150MB!'); + } + return isLt150M; + }, + }; + const isAdmin = this.props.isAdmin() + const courseId=this.props.match.params.coursesId; + const boardId = this.props.match.params.boardId + + return( +
+ + +
+ + +

+ {this.isEdit ? "编辑" : "新建"}帖子 + this.props.history.goBack()}> + 返回 + +

+ {/* notRequired */} +
+
+ { isAdmin && + + {getFieldDecorator('sticky', { + valuePropName: 'checked', + })( + isAdmin && 置顶 + )} + {/* checkbox 有个边距样式 .ant-checkbox-wrapper + span, */} + + + } + + + {getFieldDecorator('subject', { + rules: [{ + required: true, message: '请输入标题', + }, { + max: 60, message: '最大限制为60个字符', + }], + })( + + )} + + + + {getFieldDecorator('select_board_id', { + // initialValue: '3779', + })( + + )} + + + {/* { isAdmin && + {getFieldDecorator('sticky', { + })( + 置顶 + )} + } */} +
+ + + +
+ + + {getFieldDecorator('content', { + rules: [{ + required: true, message: '请输入帖子内容', + }, { + max: 10000, message: '最大限制为10000个字符', + }], + })( + + )} + + + + + (单个文件150M以内) + +
+ + +
+ + this.isEdit ? + this.props.toDetailPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) : + this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) }>取消 +
+
+ +
+
+ ) + } +} + +const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew); export default RouteHOC()(WrappedBoardsNew); \ No newline at end of file diff --git a/public/react/src/modules/courses/boards/TopicDetail.js b/public/react/src/modules/courses/boards/TopicDetail.js index 7aaecdd16..970cf798a 100644 --- a/public/react/src/modules/courses/boards/TopicDetail.js +++ b/public/react/src/modules/courses/boards/TopicDetail.js @@ -1,726 +1,726 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames' - -import axios from 'axios' - -import moment from 'moment' - -import Comments from '../../comment/Comments' - -import update from 'immutability-helper' -import RewardDialog from '../../common/RewardDialog'; -import {ImageLayerOfCommentHOC} from '../../page/layers/ImageLayerOfCommentHOC' - -import MemoDetailMDEditor from '../../forums/MemoDetailMDEditor' -import { RouteHOC } from './common.js' -import '../../forums/Post.css' -import '../../forums/RightSection.css' -import './TopicDetail.css' -import '../common/courseMessage.css' -import { Pagination, Tooltip } from 'antd' -import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder' -import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal' -import CBreadcrumb from '../common/CBreadcrumb' -import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment - , addSecondLevelComment, NEED_TO_WRITE_CONTENT, handleContentBeforeCreateSecondLevelComment - , handleDeleteComment, handleCommentPraise, handleHiddenComment } from '../common/CommentsHelper' - -const $ = window.$ -const REPLY_PAGE_COUNT = 10 -function urlStringify(params) { - let noParams = true; - let paramsUrl = ''; - for (let key in params) { - noParams = false; - paramsUrl += `${key}=${params[key]}&` - } - if (noParams) { - return ''; - } - paramsUrl = paramsUrl.substring(0, paramsUrl.length - 1); - return paramsUrl; -} -class TopicDetail extends Component { - constructor(props) { - super(props) - - this.state = { - memo: {}, - memoLoading: true, - hasMoreComments: false, - pageCount: 1, - comments: [], - goldRewardDialogOpen: false, - } - } - componentDidMount() { - window.$("html,body").animate({"scrollTop":0}) - - const topicId = this.props.match.params.topicId - const bid = this.props.match.params.boardId - - const memoUrl = `/messages/${topicId}.json`; - this.setState({ - memoLoading: true - }) - axios.get(memoUrl,{ - }) - .then((response) => { - - if (response.data.status === -1) { - setTimeout(() => { - this.props.showNotification('帖子不存在!') - }, 300) - // this.props.toListPage(response.data.data.course_id, bid) - return; - } else { - - this.setState({ - memo: Object.assign({}, { - ...response.data.data, - replies_count: response.data.data.total_replies_count - }, {...this.state.memo}) - }, () => { - }) - - // const { memo_replies, memo } = response.data; - // let hasMoreComments = false; - // if (memo_replies && memo_replies.length === 10 && memo.total_replies_count > 10) { - // // 遍历一遍,计算下是否还有评论未加载 - // let totalCount = 10; - // memo_replies.forEach(item=>{ - // totalCount += item.children.length - // }) - // if (totalCount < memo.total_replies_count) { - // hasMoreComments = true; - // } - // } - // this.setState({ - // hasMoreComments, - // pageCount: 1, - // comments: memo_replies - // }) - // delete response.data.memo_replies; - // this.setState(response.data) - // const user = response.data.current_user; - // user.tidding_count = response.data.tidding_count; - // this.props.initCommonState(user) - } - this.setState({ - memoLoading: false - }) - - }).catch((error) => { - console.log(error) - }) - - this.fetchReplies() - - $('body>#root').on('onMemoDelete', (event) => { - // const val = $('body>#root').data('onMemoDelete') - const val = window.onMemoDelete ; - this.onMemoDelete( JSON.parse(decodeURIComponent(val)) ) - }) - - - } - - onPaginationChange = (pageCount) => { - this.setState({ pageCount }, () => { - this.fetchReplies() - }) - } - - componentWillUnmount() { - $('body>#root').off('onMemoDelete') - } - onMemoDelete(memo) { - const deleteUrl = `/commons/delete.json`; - // 获取memo list - axios.delete(deleteUrl, { data: { - object_id: memo.id, - object_type: 'message' - } - }) - .then((response) => { - const status = response.data.status - if (status === 0) { - - this.props.showNotification('删除成功'); - const props = Object.assign({}, this.props, {}) - this.props.toListPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id} ) ) - - } else if (status === -1) { - this.props.showNotification('帖子已被删除'); - this.props.history.push(`/forums`) - } - }).catch((error) => { - console.log(error) - }) - } - - componentDidUpdate(prevProps, prevState, snapshot) { - // if (this.state.memo && this.state.memo.content - // && (!prevProps.memo || prevProps.memo.content != this.state.memo.content) ) { - if (this.state.memo && this.state.memo.content && prevState.memoLoading === true && this.state.memoLoading === false) { - // md渲染content,等xhr执行完(即memoLoading变化),memo.content更新后初始化md - - setTimeout(()=>{ - // var shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", { - // htmlDecode: "style,script,iframe", // you can filter tags decode - // taskList: true, - // tex: true, // 默认不解析 - // flowChart: true, // 默认不解析 - // sequenceDiagram: true // 默认不解析 - // }); - }, 200) - } - - } - - clickPraise(){ - const { memo } = this.state; - // const url = `/api/v1/discusses/${memo.id}/plus`; - const url = memo.user_praise ? '/praise_tread/unlike.json' : `/praise_tread/like.json`; - const _method = memo.user_praise ? axios.delete : axios.post - let _data = { - object_id: memo.id, - object_type: 'message', //Discuss - } - if (memo.user_praise) { - _data = { - data: _data - } - } - _method(url, { - ..._data - }, - { - - } - ).then((response) => { - - const newMemo = Object.assign({}, this.state.memo) - newMemo.praises_count = newMemo.user_praise ? newMemo.praises_count - 1 : newMemo.praises_count + 1 - newMemo.total_praises_count = newMemo.user_praise ? newMemo.total_praises_count - 1 : newMemo.total_praises_count + 1 - newMemo.user_praise = !newMemo.user_praise - this.setState({memo : newMemo }) - }).catch((error) => { - console.log(error) - }) - } - renderAttachment() { - const { memo } = this.state; - const attachments = [] - memo.attachments.forEach((item, index) => { - const ar = item.url.split('/') - const fileName = item.title || ar[ar.length - 1] - let filesize = 0 - if (item.filesize) { - filesize = item.filesize - // filesize = bytesToSize(item.filesize) - } - attachments.push( - //

- // - // - // {fileName && 30 }> - // {fileName} - // } - // {filesize? ` ${filesize.replace(' ', '')}` : ''} - // - //

- -
- - - - {/* {fileName && 30 }> } */} - 30 ? fileName : ''} - className="mr12 color9B9B overflowHidden1" length="58" style={{maxWidth: '480px'}}> - {fileName} - - - - {item.filesize} - -
- ) - }) - return attachments; - } - // ------------------------------------------------------------------------------------------- comments START - // ------------------------------------------------------------------------------------------- comments START - transformReply = (reply, children = []) => { - const isAdmin = this.props.isAdmin() - const isSuperAdmin = this.props.isSuperAdmin() - return { - isSuperAdmin: isSuperAdmin, - admin: isAdmin, // - permission: true, // - children: children, - child_message_count: reply.total_count, - hidden: reply.is_hidden, - id: reply.id, - image_url: reply.author.image_url, - reward: null, // - time: moment(reply.created_on).fromNow(), - user_id: reply.author.id, - user_login: reply.author.login, - user_praise: reply.liked, - username: reply.author.name, - content: reply.content, - praise_count: reply.praises_count - } - } - - fetchReplies = () => { - const topicId = this.props.match.params.topicId - const url = `/messages/${topicId}/reply_list.json?page=${this.state.pageCount}&page_size=${REPLY_PAGE_COUNT}` - axios.get(url,{ - }) - .then((response) => { - const { replies, liked, total_replies_count, total_count } = response.data.data - - const memo = Object.assign({}, this.state.memo) - memo.user_praise = liked - memo.total_replies_count = total_replies_count; - this.setState({ - memo, - comments: generateComments(replies, this.transformReply, 'replies'), - // : this.state.comments.concat(comments), - total_count: total_count - }) - }).catch((error) => { - console.log(error) - }) - } - - _getUser() { - const { current_user } = this.props; - current_user.user_url = `/users/${current_user.login}`; - return current_user; - } - _findById = _findById - replyComment = (commentContent, id, editor) => { - const { showNotification } = this.props; - // if (!commentContent || commentContent.length === 0) { - // showNotification(NEED_TO_WRITE_CONTENT) - // return; - // } - - if (this.state.memo.id === id ) { // 回复帖子 - this.createNewComment(commentContent, id, editor); - return; - } - const url = `/messages/${id}/reply.json`; - - const { comments } = this.state; - const user = this._getUser(); - /* - 移除末尾的空行 - .replace(/(\n

\n\t
\n<\/p>)*$/g,''); - - */ - - commentContent = handleContentBeforeCreateSecondLevelComment(commentContent) - if (!commentContent) { - this.props.showNotification('不能为空') - return; - } - axios.post(url, { - content: commentContent - }, - { - } - ).then((response) => { - if (response.data.data.id) { - let newId = response.data.data.id; - const commentIndex = this._findById(id, comments); - const parentComment = comments[commentIndex] - - this.setState({ - // runTesting: false, - comments: addSecondLevelComment(comments, parentComment, commentIndex, newId, commentContent, user, editor) - }, ()=>{ - // keditor代码美化 - editor.html && window.prettyPrint() - }) - - const newMemo2 = Object.assign({}, this.state.memo); - newMemo2.total_replies_count = newMemo2.total_replies_count + 1; - this.setState({ - memo: newMemo2 - }) - } - - }).catch((error) => { - console.log(error) - }) - } - // 公共接口 --- 删除回复 - deleteComment = (parrentComment, childCommentId) => { - handleDeleteComment(this, parrentComment, childCommentId, 'message') - - } - // 公共接口 --- 回复点赞 - commentPraise = (discussId) => { - handleCommentPraise(this, discussId, 'message', (old_user_praise) => { - const newMemo2 = Object.assign({}, this.state.memo); - - newMemo2.total_praises_count = old_user_praise - ? newMemo2.total_praises_count - 1 : newMemo2.total_praises_count + 1; - this.setState({ - memo: newMemo2 - }) - }) - } - // 公共接口 --- 隐藏回复 - hiddenComment = (item, childCommentId) => { - handleHiddenComment(this, item, childCommentId, 'message') - } - createNewComment = (commentContent, id, editor) => { - let content = handleContentBeforeCreateNew(commentContent); - const { memo } = this.props; - - const url = `/messages/${id}/reply.json`; - - // const url = `/api/v1/memos/${memo.id}/reply`; - let { comments } = this.state; - axios.post(url, { - content: content - }, - { - } - ).then((response) => { - if (response.data.status === -1) { - console.error('服务端异常') - return; - } - // this.props.showNotification('帖子发表成功') - - if (response.data) { - const _id = response.data.data.id; - // ke - editor.html && editor.html(''); - editor.afterBlur && editor.afterBlur() - // md - editor.setValue && editor.setValue('') - - - const user = this._getUser(); - this.setState({ - comments: addNewComment(comments, _id, content, user, this.props.isSuperAdmin(), this) - }) - const newMemo2 = Object.assign({}, this.state.memo); - newMemo2.total_replies_count = newMemo2.total_replies_count + 1; - this.setState({ - memo: newMemo2 - }) - this.refs.editor.showEditor(); - this.refs.editor.close(); - - - } - }).catch((error) => { - console.log(error) - }) - } - - /** - * parent.isAllChildrenLoaded 为 true的时候,表示已经没有更多子回复了 - */ - loadMoreChildComments = (parent) => { - const url = `/messages/${parent.id}/reply_list.json?page=1&page_size=500` - axios.get(url,{ - }) - .then((response) => { - const { replies, liked, total_replies_count } = response.data.data - - // const memo = Object.assign({}, this.state.memo) - // memo.total_replies_count = total_replies_count; - this.setState({ - // memo, - comments: generateChildComments(replies, this.state.comments, parent, this.transformReply) - }) - }).catch((error) => { - console.log(error) - }) - } - // ------------------------------------------------------------------------------------------- comments END - // ------------------------------------------------------------------------------------------- comments END - // 置顶 - setTop(memo) { - // const params = { - // sticky: memo.sticky ? 0 : 1, - // } - // if (this.state.p_s_order) { - // params.order = this.state.p_s_order; - // } - // if (this.state.p_forum_id) { - // params.forum_id = this.state.p_forum_id; - // } - // let paramsUrl = urlStringify(params) - const set_top_or_down_Url = `/messages/${memo.id}/sticky_top.json`; - // 获取memo list - axios.put(set_top_or_down_Url, { - - }) - .then((response) => { - const status = response.data.status - if (status === 0) { - this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功'); - memo.sticky = memo.sticky ? false : true - this.setState({ - memo: Object.assign({}, memo) - }) - } - }).catch((error) => { - console.log(error) - }) - } - - setRewardDialogVisible = (visible) => { - this.setState({ - goldRewardDialogOpen: visible - }) - } - showRewardDialog = () => { - this.setState({ - goldRewardDialogOpen: true - }) - } - // --------------------------------------------------------------------------------------------帖子獎勵 END - showCommentInput = () => { - if (window.__useKindEditor === true) { - this.refs.editor.showEditor(); - } else { - this.refs.editor.showEditor(); - } - } - initReply = (parent) => { - if (!parent.isAllChildrenLoaded) { - this.loadMoreChildComments(parent) - } - } - - - render() { - const { match, history } = this.props - const { recommend_shixun, current_user,author_info } = this.props; - const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state; - const messageId = match.params.topicId - if (this.state.memoLoading || !current_user) { - return

- } - current_user.user_url = `/users/${current_user.login}`; - const isCurrentUserTheAuthor = current_user.login == memo.author.login - const isAdmin = this.props.isAdmin() - // TODO 图片上传地址 - const courseId=this.props.match.params.coursesId; - const boardId = this.props.match.params.boardId - return ( -
{/* fl with100 */} - - - - -
-
-
-
- {memo.subject} - { !!memo.sticky && 置顶} - { !!memo.reward && - {memo.reward} - } - {/* || current_user.user_id === author_info.user_id */} - { current_user && (isAdmin || isCurrentUserTheAuthor) && - - } - -
-
- {moment(memo.created_on).fromNow()} 发布 -
- -
-
- -
- - {/* { current_user.admin && - - - - } */} - - - - {memo.visits || '1'} - - - { !!memo.total_replies_count && - - - - { memo.total_replies_count } - - - } - {!!memo.total_praises_count && - - - - { memo.total_praises_count } - - - } - - -
-
- - -
- {memo.is_md == true ? : -
- } -
-
-
- {/* ${memo.user_praise ? '' : ''} */} - -

{this.clickPraise()}} > -
- {memo.praises_count} -

-
-
- - { memo.attachments && !!memo.attachments.length && -
- {this.renderAttachment()} -
- } -
- - - - {/* onClick={ this.createNewComment } - enableReplyTo={true} - */} -
-
- 全部回复 - ({memo.total_replies_count}) -
- - - - - {/* { true ? : -
-
写评论
-
} */} -
- - -
- { total_count > REPLY_PAGE_COUNT && - - } -
写评论
-
- -
-
-
- - ); - } -} - -export default ImageLayerOfCommentHOC() ( RouteHOC()(TopicDetail) ); +import React, { Component } from 'react'; +import { Redirect } from 'react-router'; + +import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; + +import PropTypes from 'prop-types'; + +import classNames from 'classnames' + +import axios from 'axios' + +import moment from 'moment' + +import Comments from '../../comment/Comments' + +import update from 'immutability-helper' +import RewardDialog from '../../common/RewardDialog'; +import {ImageLayerOfCommentHOC} from '../../page/layers/ImageLayerOfCommentHOC' + +import MemoDetailMDEditor from '../../forums/MemoDetailMDEditor' +import { RouteHOC } from './common.js' +import '../../forums/Post.css' +import '../../forums/RightSection.css' +import './TopicDetail.css' +import '../common/courseMessage.css' +import { Pagination, Tooltip } from 'antd' +import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder' +import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal' +import CBreadcrumb from '../common/CBreadcrumb' +import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment + , addSecondLevelComment, NEED_TO_WRITE_CONTENT, handleContentBeforeCreateSecondLevelComment + , handleDeleteComment, handleCommentPraise, handleHiddenComment } from '../common/CommentsHelper' + +const $ = window.$ +const REPLY_PAGE_COUNT = 10 +function urlStringify(params) { + let noParams = true; + let paramsUrl = ''; + for (let key in params) { + noParams = false; + paramsUrl += `${key}=${params[key]}&` + } + if (noParams) { + return ''; + } + paramsUrl = paramsUrl.substring(0, paramsUrl.length - 1); + return paramsUrl; +} +class TopicDetail extends Component { + constructor(props) { + super(props) + + this.state = { + memo: {}, + memoLoading: true, + hasMoreComments: false, + pageCount: 1, + comments: [], + goldRewardDialogOpen: false, + } + } + componentDidMount() { + window.$("html,body").animate({"scrollTop":0}) + + const topicId = this.props.match.params.topicId + const bid = this.props.match.params.boardId + + const memoUrl = `/messages/${topicId}.json`; + this.setState({ + memoLoading: true + }) + axios.get(memoUrl,{ + }) + .then((response) => { + + if (response.data.status === -1) { + setTimeout(() => { + this.props.showNotification('帖子不存在!') + }, 300) + // this.props.toListPage(response.data.data.course_id, bid) + return; + } else { + + this.setState({ + memo: Object.assign({}, { + ...response.data.data, + replies_count: response.data.data.total_replies_count + }, {...this.state.memo}) + }, () => { + }) + + // const { memo_replies, memo } = response.data; + // let hasMoreComments = false; + // if (memo_replies && memo_replies.length === 10 && memo.total_replies_count > 10) { + // // 遍历一遍,计算下是否还有评论未加载 + // let totalCount = 10; + // memo_replies.forEach(item=>{ + // totalCount += item.children.length + // }) + // if (totalCount < memo.total_replies_count) { + // hasMoreComments = true; + // } + // } + // this.setState({ + // hasMoreComments, + // pageCount: 1, + // comments: memo_replies + // }) + // delete response.data.memo_replies; + // this.setState(response.data) + // const user = response.data.current_user; + // user.tidding_count = response.data.tidding_count; + // this.props.initCommonState(user) + } + this.setState({ + memoLoading: false + }) + + }).catch((error) => { + console.log(error) + }) + + this.fetchReplies() + + $('body>#root').on('onMemoDelete', (event) => { + // const val = $('body>#root').data('onMemoDelete') + const val = window.onMemoDelete ; + this.onMemoDelete( JSON.parse(decodeURIComponent(val)) ) + }) + + + } + + onPaginationChange = (pageCount) => { + this.setState({ pageCount }, () => { + this.fetchReplies() + }) + } + + componentWillUnmount() { + $('body>#root').off('onMemoDelete') + } + onMemoDelete(memo) { + const deleteUrl = `/commons/delete.json`; + // 获取memo list + axios.delete(deleteUrl, { data: { + object_id: memo.id, + object_type: 'message' + } + }) + .then((response) => { + const status = response.data.status + if (status === 0) { + + this.props.showNotification('删除成功'); + const props = Object.assign({}, this.props, {}) + this.props.toListPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id} ) ) + + } else if (status === -1) { + this.props.showNotification('帖子已被删除'); + this.props.history.push(`/forums`) + } + }).catch((error) => { + console.log(error) + }) + } + + componentDidUpdate(prevProps, prevState, snapshot) { + // if (this.state.memo && this.state.memo.content + // && (!prevProps.memo || prevProps.memo.content != this.state.memo.content) ) { + if (this.state.memo && this.state.memo.content && prevState.memoLoading === true && this.state.memoLoading === false) { + // md渲染content,等xhr执行完(即memoLoading变化),memo.content更新后初始化md + + setTimeout(()=>{ + // var shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", { + // htmlDecode: "style,script,iframe", // you can filter tags decode + // taskList: true, + // tex: true, // 默认不解析 + // flowChart: true, // 默认不解析 + // sequenceDiagram: true // 默认不解析 + // }); + }, 200) + } + + } + + clickPraise(){ + const { memo } = this.state; + // const url = `/api/v1/discusses/${memo.id}/plus`; + const url = memo.user_praise ? '/praise_tread/unlike.json' : `/praise_tread/like.json`; + const _method = memo.user_praise ? axios.delete : axios.post + let _data = { + object_id: memo.id, + object_type: 'message', //Discuss + } + if (memo.user_praise) { + _data = { + data: _data + } + } + _method(url, { + ..._data + }, + { + + } + ).then((response) => { + + const newMemo = Object.assign({}, this.state.memo) + newMemo.praises_count = newMemo.user_praise ? newMemo.praises_count - 1 : newMemo.praises_count + 1 + newMemo.total_praises_count = newMemo.user_praise ? newMemo.total_praises_count - 1 : newMemo.total_praises_count + 1 + newMemo.user_praise = !newMemo.user_praise + this.setState({memo : newMemo }) + }).catch((error) => { + console.log(error) + }) + } + renderAttachment() { + const { memo } = this.state; + const attachments = [] + memo.attachments.forEach((item, index) => { + const ar = item.url.split('/') + const fileName = item.title || ar[ar.length - 1] + let filesize = 0 + if (item.filesize) { + filesize = item.filesize + // filesize = bytesToSize(item.filesize) + } + attachments.push( + //

+ // + // + // {fileName && 30 }> + // {fileName} + // } + // {filesize? ` ${filesize.replace(' ', '')}` : ''} + // + //

+ +
+ + + + {/* {fileName && 30 }> } */} + 30 ? fileName : ''} + className="mr12 color9B9B overflowHidden1" length="58" style={{maxWidth: '480px'}}> + {fileName} + + + + {item.filesize} + +
+ ) + }) + return attachments; + } + // ------------------------------------------------------------------------------------------- comments START + // ------------------------------------------------------------------------------------------- comments START + transformReply = (reply, children = []) => { + const isAdmin = this.props.isAdmin() + const isSuperAdmin = this.props.isSuperAdmin() + return { + isSuperAdmin: isSuperAdmin, + admin: isAdmin, // + permission: true, // + children: children, + child_message_count: reply.total_count, + hidden: reply.is_hidden, + id: reply.id, + image_url: reply.author.image_url, + reward: null, // + time: moment(reply.created_on).fromNow(), + user_id: reply.author.id, + user_login: reply.author.login, + user_praise: reply.liked, + username: reply.author.name, + content: reply.content, + praise_count: reply.praises_count + } + } + + fetchReplies = () => { + const topicId = this.props.match.params.topicId + const url = `/messages/${topicId}/reply_list.json?page=${this.state.pageCount}&page_size=${REPLY_PAGE_COUNT}` + axios.get(url,{ + }) + .then((response) => { + const { replies, liked, total_replies_count, total_count } = response.data.data + + const memo = Object.assign({}, this.state.memo) + memo.user_praise = liked + memo.total_replies_count = total_replies_count; + this.setState({ + memo, + comments: generateComments(replies, this.transformReply, 'replies'), + // : this.state.comments.concat(comments), + total_count: total_count + }) + }).catch((error) => { + console.log(error) + }) + } + + _getUser() { + const { current_user } = this.props; + current_user.user_url = `/users/${current_user.login}`; + return current_user; + } + _findById = _findById + replyComment = (commentContent, id, editor) => { + const { showNotification } = this.props; + // if (!commentContent || commentContent.length === 0) { + // showNotification(NEED_TO_WRITE_CONTENT) + // return; + // } + + if (this.state.memo.id === id ) { // 回复帖子 + this.createNewComment(commentContent, id, editor); + return; + } + const url = `/messages/${id}/reply.json`; + + const { comments } = this.state; + const user = this._getUser(); + /* + 移除末尾的空行 + .replace(/(\n

\n\t
\n<\/p>)*$/g,''); + + */ + + commentContent = handleContentBeforeCreateSecondLevelComment(commentContent) + if (!commentContent) { + this.props.showNotification('不能为空') + return; + } + axios.post(url, { + content: commentContent + }, + { + } + ).then((response) => { + if (response.data.data.id) { + let newId = response.data.data.id; + const commentIndex = this._findById(id, comments); + const parentComment = comments[commentIndex] + + this.setState({ + // runTesting: false, + comments: addSecondLevelComment(comments, parentComment, commentIndex, newId, commentContent, user, editor) + }, ()=>{ + // keditor代码美化 + editor.html && window.prettyPrint() + }) + + const newMemo2 = Object.assign({}, this.state.memo); + newMemo2.total_replies_count = newMemo2.total_replies_count + 1; + this.setState({ + memo: newMemo2 + }) + } + + }).catch((error) => { + console.log(error) + }) + } + // 公共接口 --- 删除回复 + deleteComment = (parrentComment, childCommentId) => { + handleDeleteComment(this, parrentComment, childCommentId, 'message') + + } + // 公共接口 --- 回复点赞 + commentPraise = (discussId) => { + handleCommentPraise(this, discussId, 'message', (old_user_praise) => { + const newMemo2 = Object.assign({}, this.state.memo); + + newMemo2.total_praises_count = old_user_praise + ? newMemo2.total_praises_count - 1 : newMemo2.total_praises_count + 1; + this.setState({ + memo: newMemo2 + }) + }) + } + // 公共接口 --- 隐藏回复 + hiddenComment = (item, childCommentId) => { + handleHiddenComment(this, item, childCommentId, 'message') + } + createNewComment = (commentContent, id, editor) => { + let content = handleContentBeforeCreateNew(commentContent); + const { memo } = this.props; + + const url = `/messages/${id}/reply.json`; + + // const url = `/api/v1/memos/${memo.id}/reply`; + let { comments } = this.state; + axios.post(url, { + content: content + }, + { + } + ).then((response) => { + if (response.data.status === -1) { + console.error('服务端异常') + return; + } + // this.props.showNotification('帖子发表成功') + + if (response.data) { + const _id = response.data.data.id; + // ke + editor.html && editor.html(''); + editor.afterBlur && editor.afterBlur() + // md + editor.setValue && editor.setValue('') + + + const user = this._getUser(); + this.setState({ + comments: addNewComment(comments, _id, content, user, this.props.isSuperAdmin(), this) + }) + const newMemo2 = Object.assign({}, this.state.memo); + newMemo2.total_replies_count = newMemo2.total_replies_count + 1; + this.setState({ + memo: newMemo2 + }) + this.refs.editor.showEditor(); + this.refs.editor.close(); + + + } + }).catch((error) => { + console.log(error) + }) + } + + /** + * parent.isAllChildrenLoaded 为 true的时候,表示已经没有更多子回复了 + */ + loadMoreChildComments = (parent) => { + const url = `/messages/${parent.id}/reply_list.json?page=1&page_size=500` + axios.get(url,{ + }) + .then((response) => { + const { replies, liked, total_replies_count } = response.data.data + + // const memo = Object.assign({}, this.state.memo) + // memo.total_replies_count = total_replies_count; + this.setState({ + // memo, + comments: generateChildComments(replies, this.state.comments, parent, this.transformReply) + }) + }).catch((error) => { + console.log(error) + }) + } + // ------------------------------------------------------------------------------------------- comments END + // ------------------------------------------------------------------------------------------- comments END + // 置顶 + setTop(memo) { + // const params = { + // sticky: memo.sticky ? 0 : 1, + // } + // if (this.state.p_s_order) { + // params.order = this.state.p_s_order; + // } + // if (this.state.p_forum_id) { + // params.forum_id = this.state.p_forum_id; + // } + // let paramsUrl = urlStringify(params) + const set_top_or_down_Url = `/messages/${memo.id}/sticky_top.json`; + // 获取memo list + axios.put(set_top_or_down_Url, { + + }) + .then((response) => { + const status = response.data.status + if (status === 0) { + this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功'); + memo.sticky = memo.sticky ? false : true + this.setState({ + memo: Object.assign({}, memo) + }) + } + }).catch((error) => { + console.log(error) + }) + } + + setRewardDialogVisible = (visible) => { + this.setState({ + goldRewardDialogOpen: visible + }) + } + showRewardDialog = () => { + this.setState({ + goldRewardDialogOpen: true + }) + } + // --------------------------------------------------------------------------------------------帖子獎勵 END + showCommentInput = () => { + if (window.__useKindEditor === true) { + this.refs.editor.showEditor(); + } else { + this.refs.editor.showEditor(); + } + } + initReply = (parent) => { + if (!parent.isAllChildrenLoaded) { + this.loadMoreChildComments(parent) + } + } + + + render() { + const { match, history } = this.props + const { recommend_shixun, current_user,author_info } = this.props; + const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state; + const messageId = match.params.topicId + if (this.state.memoLoading || !current_user) { + return

+ } + current_user.user_url = `/users/${current_user.login}`; + const isCurrentUserTheAuthor = current_user.login == memo.author.login + const isAdmin = this.props.isAdmin() + // TODO 图片上传地址 + const courseId=this.props.match.params.coursesId; + const boardId = this.props.match.params.boardId + return ( +
{/* fl with100 */} + + + + +
+
+
+
+ {memo.subject} + { !!memo.sticky && 置顶} + { !!memo.reward && + {memo.reward} + } + {/* || current_user.user_id === author_info.user_id */} + { current_user && (isAdmin || isCurrentUserTheAuthor) && + + } + +
+
+ {moment(memo.created_on).fromNow()} 发布 +
+ +
+
+ +
+ + {/* { current_user.admin && + + + + } */} + + + + {memo.visits || '1'} + + + { !!memo.total_replies_count && + + + + { memo.total_replies_count } + + + } + {!!memo.total_praises_count && + + + + { memo.total_praises_count } + + + } + + +
+
+ + +
+ {memo.is_md == true ? : +
+ } +
+
+
+ {/* ${memo.user_praise ? '' : ''} */} + +

{this.clickPraise()}} > +
+ {memo.praises_count} +

+
+
+ + { memo.attachments && !!memo.attachments.length && +
+ {this.renderAttachment()} +
+ } +
+ + + + {/* onClick={ this.createNewComment } + enableReplyTo={true} + */} +
+
+ 全部回复 + ({memo.total_replies_count}) +
+ + + + + {/* { true ? : +
+
写评论
+
} */} +
+ + +
+ { total_count > REPLY_PAGE_COUNT && + + } +
写评论
+
+ +
+
+
+ + ); + } +} + +export default ImageLayerOfCommentHOC() ( RouteHOC()(TopicDetail) ); diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js index eb53fa373..4d82f4182 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js @@ -223,7 +223,7 @@ class CommonWorkDetailIndex extends Component{ } `} {current_user && { - const Id = this.props.match.params.Id - this.isEdit = !!Id - if (Id) { - const url = `/exercises/${Id}/edit.json` - axios.get(url) - .then((response) => { - if (response.data.status == 0) { - const { exercise, ...others } = response.data - this.setState({ - ...exercise, - ...others, - editMode: false - }) - } - }) - .catch(function (error) { - console.log(error); - }); - } else { - const courseId=this.props.match.params.coursesId; - - const newUrl = `/courses/${courseId}/exercises/new.json` - axios.get(newUrl) - .then((response) => { - if (response.data.status == 0) { - this.setState({ - ...response.data - }) - } - }) - .catch(function (error) { - console.log(error); - }); - } - } - componentDidMount = () => { - this.fetchExercise() - } - handleSubmit = (e) => { - - } - onSaveExercise = () => { - const { exercise_name, exercise_description } = this.state; - const exercise_id = this.props.match.params.Id - const courseId = this.props.match.params.coursesId - if (this.isEdit) { - const editUrl = `/exercises/${exercise_id}.json` - axios.put(editUrl, { - exercise_name, - exercise_description - }) - .then((response) => { - if (response.data.status == 0) { - this.setState({editMode: false}) - this.props.showNotification('试卷编辑成功') - } - }) - .catch(function (error) { - console.log(error); - }); - } else { - const url = `/courses/${courseId}/exercises.json` - axios.post(url, { - exercise_name, - exercise_description - }) - .then((response) => { - if (response.data.status == 0) { - this.setState({editMode: false}) - - this.props.showNotification('试卷新建成功') - const exercise_id = response.data.data.exercise_id; - this.isEdit = true; - - this.props.history.replace(`/courses/${courseId}/exercises/${exercise_id}/edit`); - - } - }) - .catch(function (error) { - console.log(error); - }); - } - } - exercise_name_change = (e) => { - this.setState({exercise_name: e.target.value}) - } - exercise_description_change = (e) => { - this.setState({exercise_description: e.target.value}) - } - // #问题的类型,0为单选题,1为多选题,2为判断题,3为填空题,4为主观题,5为实训题 - _checkIsEditing = () => { - if (this.editingId && $(this.editingId).length ) { - this.props.showNotification('请先保存或取消当前正在编辑的问题。') - $("html").animate({ scrollTop: $(this.editingId).offset().top - 100}) - return true - } - return false - } - onEditorCancel = () => { - this.editingId = null; - // 找到编辑或新建的item,新建就删掉item,编辑就isNew改为false - const { exercise_questions } = this.state - let index = -1; - for(let i = 0; i < exercise_questions.length; i++) { - if (exercise_questions[i].isNew == true) { - index = i; - break; - } - } - if (exercise_questions[index].question_id) { // 编辑 - this.setState( - (prevState) => ({ - exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: false}}}) - // update(prevState.exercise_questions, {$splice: [[index, 1]]}) - }) - ) - } else { // 新建 - this.setState( - (prevState) => ({ - exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]}) - }) - ) - } - } - addQuestion = (question_id_to_insert_after, type) => { - if (!this.isEdit) { - this.props.showNotification('请先输入试卷标题,并保存试卷') - return; - } - if (this._checkIsEditing()) { - return; - } - if (type == Q_TYPE_SHIXUN) { - this.addShixun(question_id_to_insert_after) - } else { - this.addEditingQuestion(type, question_id_to_insert_after) - } - } - chooseShixun = (array) => { - this.addEditingQuestion(Q_TYPE_SHIXUN, this.question_id_to_insert_after, { - shixun_id: array[0] - }) - } - chooseShixunSuccess = () => { - this.refs.shixunChooseModal.setVisible(false) - } - addShixun = (question_id_to_insert_after) => { - if (!this.isEdit) { - this.props.showNotification('请先输入试卷标题,并保存试卷') - return; - } - // TODO 弹框选择实训 - if (this._checkIsEditing()) { - return; - } - this.refs.shixunChooseModal.setVisible(true) - this.question_id_to_insert_after = question_id_to_insert_after; - return; - // 拉取实训items - this.addEditingQuestion(Q_TYPE_SHIXUN, question_id_to_insert_after, { - shixun_id: 50 - }) - } - editQestion = (index) => { - if (this._checkIsEditing()) { - return; - } - this.editingId = `#question_${index}` - - this.setState( - (prevState) => ({ - exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: true}}}) - }) - ) - } - onSort = (index, question_id, isUp) => { - if (this._checkIsEditing()) { - return; - } - const url = `/exercise_questions/${question_id}/up_down.json` - axios.post(url, { opr: isUp ? 'up' : 'down'}) - .then((response) => { - if (response.data.status == 0) { - // this.props.showNotification('移动成功') - this.fetchExercise() - } - }) - .catch(function (error) { - console.log(error); - }); - } - onSortDown = (index, question_id) => { - this.onSort(index, question_id, false) - } - onSortUp = (index, question_id) => { - this.onSort(index, question_id, true) - } - getInitScore = (question_type, question_id_to_insert_after) => { - /** - 1.每个题型的首个题目默认值规则如下: - 选择题:5分 01 - 判断题:2分 2 - 填空题:2分 3 - 简答题:10分 4 - 实训题:每个关卡5分 5 - */ - let init_question_score = 0; - if (question_type == 0 || question_type == 1) { - init_question_score = 5 - } else if (question_type == 2) { - init_question_score = 2 - } else if (question_type == 3) { - init_question_score = 2 - } else if (question_type == 4) { - init_question_score = 10 - } else if (question_type == 5) { - init_question_score = 5 - } - const _indexBefore = question_id_to_insert_after ? this.findIndexById(question_id_to_insert_after) : this.state.exercise_questions.length - 1 - for (let i = _indexBefore; i >= 0; i--) { - if(this.state.exercise_questions[i].question_type == question_type) { - init_question_score = this.state.exercise_questions[i].question_score - break; - } - } - return init_question_score; - } - addEditingQuestion = (question_type, question_id_to_insert_after, otherAttributes) => { - - let init_question_score = this.getInitScore(question_type, question_id_to_insert_after) - - let questionObj = { - question_type: question_type, // 需要这个通过类型判断 - init_question_score: init_question_score, - isNew: true, // 新建或编辑,用是否有id区分是新建还是编辑 - question_id_to_insert_after, - ...otherAttributes - } - const { exercise_questions } = this.state; - let new_exercise_questions = exercise_questions.slice(0) - let newIndex = new_exercise_questions.length; - - if (question_id_to_insert_after) { - const _indexBefore = this.findIndexById(question_id_to_insert_after) - new_exercise_questions.splice(_indexBefore + 1, 0, questionObj) - newIndex = _indexBefore + 1 - } else { - new_exercise_questions.push(questionObj) - } - this.editingId = `#question_${newIndex}` - this.setState({ exercise_questions: new_exercise_questions }, () => { - setTimeout(() => { - $(this.editingId).length && $("html").animate({ scrollTop: $(this.editingId).offset().top - 100}) - }, 500) - }) - } - findIndexById = (id) => { - const { exercise_questions } = this.state - for(let i = 0; i < exercise_questions.length; i++) { - if (exercise_questions[i].question_id == id) { - return i; - } - } - } - onQestionDelete = (question_id) => { - this.props.confirm({ - content: `确认要删除这个问题吗?`, - onOk: () => { - const url = `/exercise_questions/${question_id}.json` - axios.delete(url) - .then((response) => { - if (response.data.status == 0) { - this.props.showNotification('删除成功') - const { exercise_questions } = this.state - const index = this.findIndexById(question_id) - - this.setState( - (prevState) => ({ - exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]}) - }) - ) - } - }) - .catch(function (error) { - console.log(error); - }); - } - }) - } - addSuccess = () => { - this.editingId = null; - this.fetchExercise() - } - goToPreview = () => { - const exercise_id = this.props.match.params.Id - const courseId = this.props.match.params.coursesId - this.props.history.push(`/courses/${courseId}/exercises/${exercise_id}/student_exercise_list?tab=2`) - } - render() { - let { exercise_name, exercise_description, course_id, exercise_types, - exercise_questions, left_banner_id } = this.state; - // if (this.isEdit && !exercise_types) { - // return '' - // } - // const { getFieldDecorator } = this.props.form; - const { q_counts, q_scores, q_doubles, q_doubles_scores, q_judges, q_judges_scores, - q_mains, q_mains_scores, q_nulls, q_nulls_scores, q_shixuns, q_shixuns_scores, q_singles, q_singles_scores} = exercise_types; - const formItemLayout = { - labelCol: { - xs: { span: 24 }, - // sm: { span: 8 }, - sm: { span: 24 }, - }, - wrapperCol: { - xs: { span: 24 }, - // sm: { span: 16 }, - sm: { span: 24 }, - }, - }; - - const { current_user } = this.props - const isAdmin = this.props.isAdmin() - const courseId=this.props.match.params.coursesId; - const exercise_id = this.props.match.params.Id - - const isEdit = this.isEdit - const commonHandler = { - onQestionDelete: this.onQestionDelete, - addSuccess: this.addSuccess, - addQuestion: this.addQuestion, - onEditorCancel: this.onEditorCancel, - editQestion: this.editQestion, - onSortDown: this.onSortDown, - onSortUp: this.onSortUp, - displayCount: exercise_questions.length, - exercise_status: this.state.exercise_status, - exerciseIsPublish: this.state.exercise_status >= 2 - } - return( -
- - -
- { current_user && } - -

- {this.isEdit ? "编辑" : "新建"}试卷 - this.props.history.length == 1 ? this.props.history.push(`/courses/${courseId}/exercises/${left_banner_id}`): this.props.history.goBack()}> - 返回 - -

- - {!this.state.editMode &&
- -
- -
} - {this.state.editMode &&
-
- - {/* {getFieldDecorator('subject', { - rules: [{ - required: true, message: '请输入标题', - }, { - max: 20, message: '最大限制为20个字符', - }], - })( */} - - {/* )} */} - - - - {/* {getFieldDecorator('select_board_id', { - // initialValue: '3779', - })( */} -