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

482 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 from 'react'
import axios from 'axios'
import { notification } from 'antd'
import update from 'immutability-helper'
import ImageLayer from '../page/layers/ImageLayer'
const $ = window.$
/* 需要的props:
shixun
id
myshixun
id
challenge
id
user
"image_url": user.image_url,
"username": user.username,
showSnackbar
*/
/*
这里提供props给WrappedComponent用于封装特定的state和功能评论列表
不要直接使用this.xxx调用WrappedComponent内的方法尽量避免互相依赖封装好后供不同场景使用tpi、tpm
*/
export function commentHOC(WrappedComponent) {
// 这里如果extends WrappedComponent 会出现 WrappedComponent mount twice的问题
return class II extends React.Component {
constructor(props) {
super(props)
// ------------------------------------
this.createNewComment = this.createNewComment.bind(this)
this.fetchCommentIfNotFetched = this.fetchCommentIfNotFetched.bind(this)
this.replyComment = this.replyComment.bind(this)
this.deleteComment = this.deleteComment.bind(this)
this.commentPraise = this.commentPraise.bind(this)
this.hiddenComment = this.hiddenComment.bind(this)
this.rewardCode = this.rewardCode.bind(this)
this.showNewReply = this.showNewReply.bind(this)
// ------------------------------------
this.onPaginationChange = this.onPaginationChange.bind(this)
this.state = {
// 评论
comments: [],
comment_count_without_reply: 0,
// 默认pageSize为10
currentPage: 1,
loadingComments: true,
// 图片最大化
showImage: false,
imageSrc: '',
}
}
// ----------------------------------------------------------------------------------------------评论 Start
// ----------------------------------------------------------------------------------------------评论 Start
onPaginationChange(page) {
this.fetchComment(page)
this.setState({
currentPage: page,
});
}
/*
email: "1843820944@qq.com"
grade: 2138
image_url: "avatar/User/36497"
login: "p24891375"
name: "杨俊男"
user_url: "/users/p24891375"
*/
handleComments(comments, responseData) {
comments.forEach(element => {
if (element.children) {
this.handleComments(element.children, responseData)
}
element.admin = responseData.all
element.manager = element.manage
element.username = element.author.name
element.user_login = element.author.login
element.image_url = element.author.image_url
element.user_id = element.author.user_id
});
}
responseDataParse(response) {
const comments = response.data.comments
this.handleComments(comments, response.data)
}
fetchComment(page = 1) {
const { challenge, shixun, match } = this.props;
// const url = `/api/v1/shixuns/${shixun.id}/shixun_discusses?page=${page-1}&container_type=Shixun`
const url =
`/discusses.json?page=${page - 1}&container_identifier=${shixun && shixun.identifier ?
shixun.identifier : match.params.shixunId}&container_type=Shixun`
this.setState({
loadingComments: true,
});
axios.get(url,
{}
).then((response) => {
// test
if (response.data) {
this.responseDataParse(response)
this.setState({
comments: response.data.comments,
comment_count_without_reply: response.data.disscuss_count,
currentPage: page,
loadingComments: false,
}, () => {
// keditor代码美化
window.prettyPrint()
})
}
// console.log(response)
}).catch((error) => {
console.log(error)
})
}
// 切换关卡时清空state
clearCommentsInState = () => {
this.setState({ comments: [] })
}
fetchCommentIfNotFetched() {
if (this.state.comments && this.state.comments.length) {
return;
}
// http://localhost:3000/api/v1/shixuns/cz7yw3en/shixun_discusses?page=0
this.fetchComment();
}
// 新增父级评论
createNewComment(content) {
const { challenge, shixun, showSnackbar } = this.props;
if (!content || content.length === 0) {
showSnackbar('必须填写内容!')
return;
}
const url = `/discusses.json`
if (content != undefined) {
var beforeImage = content.split("<img");
var afterImage = content.split("/>");
if (beforeImage[0] == "" && afterImage[1] == "") {
window.notice_box('不支持纯图片评论<br/>请在评论中增加文字信息');
return;
}
}
let res = axios.post(url, {
container_type: "Shixun",
container_id: shixun.id,
challenge_id: challenge.id,
content,
position: challenge.position
}
).then((response) => {
if (response.data.discuss) {
this.fetchComment()
}
}).catch((error) => {
console.log(error)
})
return res;
}
_findCommentById(id, arg_comments) {
let comments;
if (!arg_comments) {
comments = this.state.comments;
} else {
comments = arg_comments;
}
for (let i = 0; i < comments.length; i++) {
if (id === comments[i].id) {
return i;
}
}
}
replyComment(commentContent, id) {
const { challenge, shixun, user, showSnackbar, match } = this.props;
if (!commentContent || commentContent.length === 0) {
showSnackbar('必须填写内容!')
return;
}
const url = `/discusses/${id}/reply.json`
if (commentContent) {
commentContent = commentContent.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g, '');
}
if (!user.login && user.user_url) {
const loginAr = user.user_url.split('/')
user.login = loginAr[loginAr.length - 1]
}
let res = axios.post(url, { content: commentContent, "container_id": match.params.shixunId, "container_type": "Shixun", }).then((response) => {
if (response.data.discuss) {
let newDiscuss = response.data.discuss;
let { comments } = this.state;
var commentIndex = this._findCommentById(id);
let comment = comments[commentIndex]
comment = Object.assign({}, comment)
if (!comment.children) {
comment.children = []
} else {
comment.children = comment.children.slice(0);
}
comment.children.push({
"can_delete": true,
"content": commentContent,
"image_url": user.image_url,
"username": user.username,
"user_login": user.login,
"id": newDiscuss.id,
"position": newDiscuss.position,
"time": "1分钟前",
"praise_count": newDiscuss.praise_count,
"user_id": newDiscuss.user_id,
})
comments = comments.slice(0)
comments[commentIndex] = comment
this.setState({
comments: comments
})
}
}).catch((error) => {
console.log(error)
})
return res
}
hiddenComment(item, childCommentId) {
const id = item.id
const { challenge, shixun, user, showSnackbar, match } = this.props;
const url = `/discusses/${id}/hidden.json`
const commentIndex = this._findCommentById(id);
const { comments } = this.state;
const comment = Object.assign({}, comments[commentIndex]);
axios.post(url, {
hidden: !comment.hidden ? "1" : "0",
container_identifier: match.params.shixunId || shixun.identifier
}).then((response) => {
if (response.data.status === -1) {
showSnackbar(response.data.message)
return;
}
if (response.data.status === 1) {
if (!childCommentId) {
comment.hidden = !comment.hidden;
const commentsCopy = this.state.comments.slice(0)
commentsCopy[commentIndex] = comment
this.setState({
comments: commentsCopy
})
} else { // TODO 目前子回复没hidden字段
let childCommentIndex = this._findCommentById(childCommentId, comments[commentIndex].children);
const childComment = comments[commentIndex].children[childCommentIndex]
childComment.hidden = !childComment.hidden;
this.setState({ comments })
}
}
}).catch((error) => {
console.log(error)
})
}
deleteComment(parrentComment, childCommentId) {
const { challenge, shixun } = this.props;
let deleteCommentId = parrentComment.id
if (childCommentId) {
deleteCommentId = childCommentId;
}
const url = `/discusses/${deleteCommentId}.json`
axios.delete(url).then((response) => {
if (response.data && response.data.status === 1) {
const commentIndex = this._findCommentById(parrentComment.id);
// https://stackoverflow.com/questions/29527385/removing-element-from-array-in-component-state
if (!childCommentId) {
this.setState((prevState) => ({
comments: update(prevState.comments, { $splice: [[commentIndex, 1]] })
}))
if (this.state.comments.length <= 5) {
this.fetchComment()
}
} else {
let comments = this.state.comments;
let newComments = Object.assign({}, comments)
let childCommentIndex = this._findCommentById(childCommentId, newComments[commentIndex].children);
newComments[commentIndex].children = update(newComments[commentIndex].children, { $splice: [[childCommentIndex, 1]] })
this.setState({ newComments })
}
}
}).catch((error) => {
console.log(error)
})
}
rewardCode(parrentComment, childComment, amount) {
const { showSnackbar } = this.props;
let handleComment = parrentComment
if (childComment) {
handleComment = childComment;
}
let handleCommentId = handleComment.id;
const url = `/discusses/${handleCommentId}/reward_code.json`
axios.post(url, {
container_type: 'Discusses',
score: amount,
user_id: handleComment.user_id
}).then((response) => {
if (response.data && response.data.code) {
const commentIndex = this._findCommentById(parrentComment.id);
let { comments } = this.state;
const newComments = comments.slice(0)
if (childComment) {
const childCommentIndex = this._findCommentById(handleComment.id, parrentComment.children);
const newChildComment = Object.assign({}, childComment);
newChildComment.reward = response.data.code
parrentComment = Object.assign({}, parrentComment)
parrentComment.children = parrentComment.children.slice(0)
parrentComment.children[childCommentIndex] = newChildComment
newComments[commentIndex] = parrentComment;
} else {
const newComment = Object.assign({}, newComments[commentIndex]);
newComment.reward = response.data.code;
newComments[commentIndex] = newComment;
}
this.setState({
comments: newComments
})
}
}).catch((error) => {
console.log(error)
showSnackbar('奖励失败,请联系系统管理员!')
})
}
// 评论点赞
commentPraise(discussId) {
const commentIndex = this._findCommentById(discussId);
const { comments } = this.state;
const { challenge } = this.props;
const url = `/discusses/${discussId}/plus.json`
axios.post(url, {
container_type: 'Discuss', //Discuss
type: comments[commentIndex].user_praise === true ? 0 : 1, // "踩0赞1"
}).then((response) => {
if (response.data.praise_count === 0 || response.data.praise_count) {
const newComments = comments.slice(0)
const comment = Object.assign({}, newComments[commentIndex])
comment.user_praise = !comment.user_praise;
comment.praise_count = response.data.praise_count;
newComments[commentIndex] = comment;
this.setState({
comments: newComments
})
}
}).catch((error) => {
console.log(error)
})
}
showNewReply() {
const { shixun, myshixun } = this.props;
const commentId = 929 // TODO
const url = `/api/v1/shixuns/${shixun.id}/anchor?container_type=Shixun&myshixun_id=${myshixun.id}&discuss_id=${commentId}`
this.setState({
loadingComments: true,
gotNewReply: false,
});
axios.get(url,
{
// withCredentials: true
}
).then((response) => {
const data = response.data;
const new_message = data.new_message;
this.setState({
comments: data.children_list,
comment_count_without_reply: data.disscuss_count,
currentPage: data.page,
loadingComments: false,
}, () => {
if (response.data.find_status) { // 没找到评论的话,默认会返回第一页的评论
const comment_J = window.$(`#reply_content_${commentId}`);
if (comment_J.length) {
comment_J[0].scrollIntoView()
comment_J.parents('.comment_item_cont').css('border', '1px solid #4CACFF')
}
}
})
}).catch((error) => {
console.log(error)
})
}
componentDidMount() {
$(".commentsDelegateParent")
.delegate(".J_Comment_Reply .comment_content img, .J_Comment_Reply .childrenCommentsView img", "click", (event) => {
const imageSrc = event.target.src
// 非回复里的头像图片; 非emoticons
if (imageSrc.indexOf('/images/avatars/User') === -1 &&
imageSrc.indexOf('kindeditor/plugins/emoticons') === -1) {
this.setState({
showImage: true,
imageSrc,
})
}
});
}
onImageLayerClose = () => {
this.setState({
showImage: false,
imageSrc: '',
})
}
showNotification = (description, message = "提示", icon) => {
const data = {
message,
description
}
if (icon) {
data.icon = icon;
}
notification.open(data);
}
render() {
return (
<React.Fragment>
<ImageLayer {...this.state} onImageLayerClose={this.onImageLayerClose}></ImageLayer>
<WrappedComponent {...this.props} {...this.state}
createNewComment={this.createNewComment}
fetchCommentIfNotFetched={this.fetchCommentIfNotFetched}
clearCommentsInState={this.clearCommentsInState}
replyComment={this.replyComment}
deleteComment={this.deleteComment}
commentPraise={this.commentPraise}
hiddenComment={this.hiddenComment}
rewardCode={this.rewardCode}
onPaginationChange={this.onPaginationChange}
showNotification={this.showNotification}
newMessage={this.newMessage}
showNewReply={this.showNewReply}
></WrappedComponent>
</React.Fragment>
)
}
}
}