通用评论

index.js 3.4KB

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