forgeplus-react/src/modules/comment/Comments.js

379 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component } from 'react';
import { getImageUrl } from 'educoder';
import CommentItemMDEditor from './comment-item-editor';
import './Comment.css'
import Modals from '../modals/Modals'
import { InputNumber, Pagination, Tooltip, Modal } from 'antd'
import RenderHtml from '../../components/render-html';
const _origin = window.location.origin;
/*
tpi讨论、交流问答帖子详情讨论、课堂讨论的公用模块:
https://www.educoder.net/tasks/n2ejvaowk6l9
https://www.educoder.net/forums/2629
注意不同模块使用时的参数的不同 usingAntdModal onlySuperAdminCouldHide isChildCommentPagination等等
用到的props:
user user_url image_url
loadingComments--
comment_count_without_reply
currentPage
comments
buttonText 发送按钮 显示文本
showRewardButton 是否显示奖励按钮
showHiddenButton 是否显示隐藏按钮
onlySuperAdminCouldHide 只有超级管理员才显示隐藏、取消隐藏
isChildCommentPagination 是否子回复分页
loadMoreChildComments function 加载所有子回复
usingAntdModal 是否使用antd的弹框
接口
deleteComment 删除
onPaginationChange 翻页变化
commentPraise 点赞
hiddenComment 隐藏
rewardCode 奖励
*/
class Comments extends Component {
constructor(props) {
super(props)
this.handleDialogClose = this.handleDialogClose.bind(this)
this.handleGoldRewardDialogClose = this.handleGoldRewardDialogClose.bind(this)
this.state = {
dialogOpen: false,
goldRewardDialogOpen: false,
goldRewardInput: '',
showReplyEditorFlag: false,
currentReplyComment: null
}
}
initReply(comment) {
this.props.initReply && this.props.initReply(comment)
this.setState({
currentReplyComment: comment,
showReplyEditorFlag: !this.state.showReplyEditorFlag
})
}
renderChildenComments(comment) {
if (!comment.children || comment.children.length === 0) {
return ''
}
const { user } = this.props;
let childCommentsElement = comment.children.map((item, index) => {
return (
<div key={index} className="childComment" >
<div className="J_Comment_Info clearfix mt3">
<div className="t_info fl">
<a href={`${_origin}/users/${item.user_login}`} className="content-username hide fl">
{item.username}
</a>
<span className="t_area fl">{item.time}</span>
{
item.reward ?
<Tooltip title={`已奖励金币${item.reward}`} disableFocusListener={true}>
<a style={{ marginLeft: '20px', cursor: 'default' }}
className={`rewarded color-grey-8 font-12 fl ${item.admin === true ? '' : 'normalUser'}`}
>
<i className="iconfont icon-gift mr5 color-orange fl" style={{ display: 'inline' }}></i><span className="fl">{item.reward}</span>
</a>
</Tooltip> : ''
}
</div>
<p className="fr orig_reply lineh-20">
<span id="hidden_discuss_btn_952">
</span>
{this.props.showRewardButton != false && comment.admin === true ?
<a className="color-grey-8" onClick={() => this.showGoldRewardDialog(comment, item)}>
<Tooltip title={"给TA奖励金币"} disableFocusListener={true}>
<i className="iconfont icon-jiangli fl"></i>
</Tooltip>
</a>
: ""}
{/*子回复还没hidden字段*/}
{false && comment.admin === true ?
<Tooltip title={item.hidden ? "取消隐藏" : "隐藏评论"}>
<a className="color-grey-8" onClick={() => this.onCommentBtnClick(comment, item, item.hidden ? 'hiddenCancel' : 'hidden')}>
<i className={`fa ${item.hidden ? 'fa-eye' : 'fa-eye-slash'} mr5`}></i>
</a>
</Tooltip>
: ""}
{/* 新版user_id不准获取方式不对 */}
{comment.admin === true || item.can_delete || item.user_id === user.user_id || item.user_login == user.login ?
<a className="color-grey-8" id="delete_reply_118_952" onClick={() => this.onCommentBtnClick(comment, item, 'delete')}>
<Tooltip title={"删除"} disableFocusListener={true}>
<i className="iconfont icon-shanchu mr5"></i>
</Tooltip>
</a>
: null}
</p>
</div>
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
<div className="color-grey-3" id={`reply_content_${item.id}`}>
<RenderHtml className="break_word_comments" value={item.content} />
</div>
</div>
</div>
)
})
return childCommentsElement
}
renderComments() {
let { comments, commentPraise, tabIndexChange, user, replyComment } = this.props;
const { showReplyEditorFlag, currentReplyComment } = this.state;
if (!comments || comments.length === 0) {
return;
}
// "https://www.educoder.net/users/m02945638"
let commentsElement = comments.map((item, index) => {
return (
<div className="comment_item_cont df clearfix" key={index}>
<div className="J_Comment_Face fl">
<a href={`${_origin}/users/${item.user_login}`} target="_blank">
<img alt="用户头像" height="50" src={getImageUrl(`images/${item.image_url}`)} width="50" />
</a>
</div>
<div className="t_content fl">
<div className="J_Comment_Reply">
<div className="comment_orig_content" style={{ margin: "0px" }}>
<div className="J_Comment_Info clearfix mt3">
<div className="t_info fl">
<a href={`${_origin}/users/${item.user_login}`} className="content-username hide fl">
{item.username}
</a>
<span className="t_area fl">{item.time}</span>
{item.position && <span className="fl color-light-green font-14 ml15">[{item.position}]</span>}
{item.game_url ?
<Tooltip title={`点击查看TA的代码页面`} disableFocusListener={true}>
<a href={item.game_url} target="_blank" className="fl font-14 ml15"
style={{ color: "#4CACFF", cursor: "pointer" }}
>查看</a>
</Tooltip> : ""}
{
item.reward ?
<Tooltip title={`已奖励金币${item.reward}`} disableFocusListener={true}>
<a style={{ marginLeft: '20px', cursor: 'default' }}
className={`rewarded color-grey-8 font-12 fl ${item.admin === true ? '' : 'normalUser'}`}
>
<i className="iconfont icon-gift mr5 color-orange fl"></i><span className="fl">{item.reward}</span>
</a>
</Tooltip> : ''
}
</div>
</div>
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
<div className="color-grey-3" id={`reply_content_${item.id}`}>
<RenderHtml className="break_word_comments" value={item.content} />
</div>
</div>
<div className="childrenCommentsView">
{(item && item.children && item.children.length) ? <div className="trangle"></div> : ''}
{this.renderChildenComments(item)}
{item.isAllChildrenLoaded != true && item.children && this.props.isChildCommentPagination == true && item.child_message_count > 5 ?
<Tooltip title={"点击查看更多回复"} disableFocusListener={true}>
<div className="loadMoreChildComments" onClick={() => { this.props.loadMoreChildComments && this.props.loadMoreChildComments(item) }}>
<i className="iconfont icon-xiajiantou"></i>
</div>
</Tooltip>
: ''}
</div>
{/*mr10 */}
<p className="fr orig_reply">
<span id="hidden_discuss_btn_952">
</span>
{(this.props.power) ?
<a href="javascript:void(0);" className="color-grey-8" onClick={() => { this.putTop(item.id, !item.sticky) }}>
<Tooltip title={item.sticky ? "取消置顶" : "置顶"} disableFocusListener={true}>
<i className="iconfont icon-zhiding mr5" style={item.sticky ? { transform: "rotate(180deg)", display: "inline-block" } : undefined}></i>
</Tooltip>
</a> : null}
{/* && !item.reward */}
{this.props.showRewardButton != false && item.admin === true ?
<a className="color-grey-8 fl mt2" onClick={() => this.showGoldRewardDialog(item)}>
<Tooltip title={"给TA奖励金币"} disableFocusListener={true}>
<i className="iconfont icon-jiangli mr5 fl"></i>
</Tooltip>
</a>
: ""}
{this.props.showHiddenButton == true
&& (this.props.onlySuperAdminCouldHide && item.isSuperAdmin || !this.props.onlySuperAdminCouldHide && item.admin === true) ?
<Tooltip title={item.hidden ? "取消隐藏" : "隐藏评论"} disableFocusListener={true}>
<a className="color-grey-8 fl mt1" onClick={() => this.onCommentBtnClick(item, '', item.hidden ? 'hiddenCancel' : 'hidden')}>
<i className={` ${item.hidden ? 'iconfont icon-yincangbiyan' : 'fa fa-eye'} mr5`}></i>
</a>
</Tooltip>
: ""}
{item.admin && (!item.children || item.children.length === 0) ?
<a className="color-grey-8" onClick={() => this.onCommentBtnClick(item, '', 'delete')}>
<Tooltip title={"删除"} disableFocusListener={true}>
<i className="iconfont icon-shanchu mr5"></i>
</Tooltip>
</a> : ''}
{(this.props.showReply == undefined || this.props.showReply == true) && <a className="color-grey-8"
onClick={() => this.initReply(item)} >
<Tooltip title={"回复"}>
<i className="iconfont icon-huifu1 mr5"></i>
</Tooltip>
</a>}
<span className="reply_praise_count_952">
<Tooltip title={item.user_praise ? "取消点赞" : "点赞"}>
<a className={`fr mr5 ${item.user_praise ? 'color-orange03' : 'color-grey-8'}`} onClick={() => commentPraise(item.id)}>
<i className={item.user_praise ? "iconfont icon-dianzan mr3" : "iconfont icon-dianzan-xian mr3"}></i>
<span className="fr font-14" style={{ marginTop: '1px' }}>{item.praise_count ? item.praise_count : ''}</span>
</a>
</Tooltip>
</span>
</p>
<CommentItemMDEditor showReplyEditorFlag={showReplyEditorFlag}
currentReplyComment={currentReplyComment}
item={item}
user={user}
replyComment={replyComment}
tabIndexChange={tabIndexChange}
buttonText={this.props.buttonText}
/>
</div>
</div>
</div>
</div>
)
})
return commentsElement;
}
onCommentBtnClick(comment, childComment, dialogType) {
this.comment = comment;
this.childComment = childComment;
this.setState({ dialogOpen: true, dialogType: dialogType })
}
handleDialogClose() {
this.setState({
dialogOpen: false
})
}
onDialogOkBtnClick = () => {
const { deleteComment, hiddenComment } = this.props;
const { dialogType } = this.state;
if (dialogType === 'delete') {
deleteComment(this.comment, this.childComment ? this.childComment.id : '')
} else if (dialogType === 'hidden' || dialogType === 'hiddenCancel') {
hiddenComment(this.comment, this.childComment ? this.childComment.id : '')
}
this.setState({ dialogOpen: false })
}
showGoldRewardDialog(comment, childComment) {
if (comment.admin === true) {
this.comment = comment;
this.childComment = childComment;
this.setState({ goldRewardDialogOpen: true })
}
}
handleGoldRewardDialogClose() {
this.setState({
goldRewardDialogOpen: false
})
}
onGoldRewardDialogOkBtnClick() {
const { goldRewardInput } = this.state;
if (!goldRewardInput || goldRewardInput === '0') {
this.setState({ goldRewardInputError: true })
return;
} else {
this.setState({ goldRewardDialogOpen: false })
this.props.rewardCode(this.comment, this.childComment, goldRewardInput)
}
}
onGoldRewardInputChange(value) {
// e.target.value
const number = parseInt(value || 0, 10);
if (Number.isNaN(number)) {
return;
}
this.setState({ goldRewardInput: number, goldRewardInputError: false });
}
render() {
const { deleteComment, onPaginationChange, comment_count_without_reply, currentPage, comments, usingAntdModal } = this.props;
const { dialogOpen, goldRewardDialogOpen, dialogType, goldRewardInputError } = this.state;
return (
<div className="fit -scroll" style={{ 'overflowX': 'hidden' }}>
<Modals
modalsType={dialogOpen}
modalsTopval={
dialogType === 'delete' ? '确定要删除该条回复吗?'
: dialogType === 'hidden' ? '确定要隐藏该条回复吗?'
: dialogType === 'hiddenCancel' ? '确定要取消隐藏该条回复吗?' : ''
}
modalsBottomval={""}
modalCancel={this.handleDialogClose}
modalSave={this.onDialogOkBtnClick}
>
</Modals>
<Modal
width={400}
title="奖励设置"
bodyStyle={{ textAlign: 'center' }}
visible={goldRewardDialogOpen}
onCancel={this.handleGoldRewardDialogClose}
onOk={() => this.onGoldRewardDialogOkBtnClick()}
>
<InputNumber placeholder="请输入奖励的金币数量" id="goldReward" type="number" value={this.state.goldRewardInput}
onChange={(e) => this.onGoldRewardInputChange(e)} width={228} style={{ width: '228px' }} />
</Modal>
<div className="-layout-v -fit">
<div className="panel-comment_item" >
{this.renderComments()}
</div>
{(comment_count_without_reply > 10) ?
<div className="pagination-contaner">
<Pagination showQuickJumper onChange={onPaginationChange} current={currentPage} total={comment_count_without_reply} />
</div>
: ''}
{(comment_count_without_reply == 0) ? <div>
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")} />
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p>
</div>
</div>
: ''}
</div>
</div>
)
}
}
export default Comments;