通用评论

index.js 3.8KB

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