通用评论

index.js 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import React, { Component } from "react";
  2. import PropTypes from "prop-types";
  3. import { Avatar, Icon, Tooltip } from "antd";
  4. import dayjs from "dayjs";
  5. import "dayjs/locale/zh-cn";
  6. import relativeTime from "dayjs/plugin/relativeTime";
  7. import Comment from "../../Comment";
  8. import CommentInput from "../CommentInput";
  9. import avatar from "../../avatar";
  10. import { renderContent } from "../../helper";
  11. import "./index.css";
  12. dayjs.locale("zh-cn");
  13. dayjs.extend(relativeTime);
  14. class CommentItem extends Component {
  15. constructor(props) {
  16. super(props);
  17. this.state = {
  18. showInput: false
  19. };
  20. this.handleToggleInput = this.handleToggleInput.bind(this);
  21. this.renderTextWithReply = this.renderTextWithReply.bind(this);
  22. }
  23. handleToggleInput() {
  24. this.setState({ showInput: !this.state.showInput });
  25. }
  26. renderTextWithReply(text, content) {
  27. let newText = text;
  28. const { reply } = content;
  29. if (reply) {
  30. newText = `${newText} //@<a href="/${reply.user_id}">${
  31. reply.user_name
  32. }</a> ${reply.content}`;
  33. if (reply.reply) {
  34. return this.renderTextWithReply(newText, reply);
  35. }
  36. }
  37. return newText;
  38. }
  39. render() {
  40. const {
  41. commentId,
  42. replyId,
  43. content,
  44. action,
  45. showReply,
  46. onShowReply,
  47. app
  48. } = this.props;
  49. const { showInput } = this.state;
  50. return (
  51. <div className="comment-item-box">
  52. <div className="comment-item-left">
  53. <Avatar src={content.user_avatar || avatar} size="large" />
  54. </div>
  55. <div className="comment-item-right">
  56. <div>
  57. <a href={`/${content.user_id}`}>
  58. {content.user_name || "暂无昵称"}
  59. </a>
  60. <span style={{ marginLeft: 10 }}>
  61. <Tooltip
  62. placement="top"
  63. title={dayjs(content.created * 1000).format(
  64. "YYYY-MM-DD HH:mm:ss"
  65. )}
  66. >
  67. {dayjs(content.created * 1000).fromNow()}
  68. </Tooltip>
  69. </span>
  70. </div>
  71. <div
  72. className="comment-item-content"
  73. dangerouslySetInnerHTML={{
  74. __html: renderContent(
  75. this.renderTextWithReply(content.content, content)
  76. )
  77. }}
  78. />
  79. <div className="comment-item-bottom">
  80. {content.reply_count ? (
  81. <div>
  82. <a className="comment-item-bottom-left" onClick={onShowReply}>
  83. {content.reply_count} 条回复
  84. {showReply ? <Icon type="up" /> : <Icon type="down" />}
  85. </a>
  86. </div>
  87. ) : null}
  88. <a
  89. onClick={this.handleToggleInput}
  90. className="comment-item-bottom-right"
  91. >
  92. &nbsp; 回复
  93. </a>
  94. <div
  95. className="comment-item-bottom-right"
  96. onClick={() => {
  97. if (replyId) {
  98. // 如果有 replyId,则说明是评论的回复
  99. app.sReplyFavor(content.id, commentId, content.favored);
  100. return;
  101. }
  102. app.sCommentFavor(content.id, content.favored);
  103. }}
  104. >
  105. <Icon
  106. type="like-o"
  107. className={content.favored ? "comment-favored" : ""}
  108. />
  109. &nbsp;{content.favor_count}
  110. </div>
  111. </div>
  112. </div>
  113. {showInput && (
  114. <CommentInput
  115. content={app.children}
  116. action={action}
  117. replyId={replyId}
  118. commentId={commentId}
  119. callback={this.handleToggleInput}
  120. />
  121. )}
  122. </div>
  123. );
  124. }
  125. }
  126. CommentItem.propTypes = {
  127. content: PropTypes.object.isRequired,
  128. // comment 评论
  129. // reply 评论的回复
  130. // replyToReply 回复的回复
  131. action: PropTypes.oneOf(["comment", "reply", "replyToReply"]),
  132. onShowReply: PropTypes.func
  133. };
  134. CommentItem.defaultProps = {
  135. action: "comment",
  136. onShowReply: () => {}
  137. };
  138. export default Comment(CommentItem);