Explorar el Código

feat: 完成视频评论框大部分功能需求

node hace 5 años
padre
commit
0e1bc13c48

+ 2
- 0
src/App.css Ver fichero

2
   width: 100%;
2
   width: 100%;
3
   padding: 10px;
3
   padding: 10px;
4
   margin-bottom: 100px;
4
   margin-bottom: 100px;
5
+  background: rgba(0, 0, 0, 0.59);
6
+  color: white;
5
 }
7
 }
6
 
8
 
7
 .comment .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
9
 .comment .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {

+ 4
- 4
src/App.js Ver fichero

463
       this.state.initDone && (
463
       this.state.initDone && (
464
         <CommentContext.Provider value={value}>
464
         <CommentContext.Provider value={value}>
465
           <div className="comment">
465
           <div className="comment">
466
-            {this.props.showEditor && (
467
-              <CommentInput content={this.props.children} />
468
-            )}
469
             {this.props.showList && (
466
             {this.props.showList && (
470
-              <div style={{ marginTop: 20 }}>
467
+              <div>
471
                 <CommentList />
468
                 <CommentList />
472
               </div>
469
               </div>
473
             )}
470
             )}
471
+            {this.props.showEditor && (
472
+              <CommentInput content={this.props.children} />
473
+            )}
474
           </div>
474
           </div>
475
         </CommentContext.Provider>
475
         </CommentContext.Provider>
476
       )
476
       )

+ 112
- 24
src/components/CommentBox/index.js Ver fichero

4
 import intl from "react-intl-universal";
4
 import intl from "react-intl-universal";
5
 import Comment from "../../Comment";
5
 import Comment from "../../Comment";
6
 import ContentItem from "./../ContentItem";
6
 import ContentItem from "./../ContentItem";
7
+import ReplyItem from "./../ReplyItem";
7
 import "./index.css";
8
 import "./index.css";
8
 
9
 
9
 class CommentBox extends Component {
10
 class CommentBox extends Component {
11
     super(props);
12
     super(props);
12
     this.state = {
13
     this.state = {
13
       showReply: true,
14
       showReply: true,
14
-      page: 1
15
+      page: 1,
16
+      isShowOver3: false
15
     };
17
     };
16
 
18
 
17
     this.handleToggleReply = this.handleToggleReply.bind(this);
19
     this.handleToggleReply = this.handleToggleReply.bind(this);
18
     this.handleGetMoreReply = this.handleGetMoreReply.bind(this);
20
     this.handleGetMoreReply = this.handleGetMoreReply.bind(this);
19
     this.renderReplies = this.renderReplies.bind(this);
21
     this.renderReplies = this.renderReplies.bind(this);
22
+    this.handleClickCollapse = this.handleClickCollapse.bind(this);
20
   }
23
   }
21
 
24
 
22
   /**
25
   /**
26
     this.setState({ showReply: !this.state.showReply });
29
     this.setState({ showReply: !this.state.showReply });
27
   }
30
   }
28
 
31
 
32
+  /**
33
+   * 点击收起按钮的时候只展示最多三条留言
34
+   */
35
+  handleClickCollapse() {
36
+    this.setState({ isShowOver3: !this.state.isShowOver3 });
37
+    console.log("this.isMore", this.state.isShowOver3);
38
+  }
39
+
29
   /**
40
   /**
30
    * 获取更多评论
41
    * 获取更多评论
31
    * @param {string} commentId comment id
42
    * @param {string} commentId comment id
43
    * @param {number} replies 回复的数量
54
    * @param {number} replies 回复的数量
44
    * @param {boolean} isNoMoreReply 是否没有更多回复
55
    * @param {boolean} isNoMoreReply 是否没有更多回复
45
    */
56
    */
57
+  // renderReplies(replies, replyCount, isNoMoreReply) {
58
+  //   console.log('replies', replies);
59
+  //   console.log('replyCount', replyCount);
60
+  //   console.log('isNoMoreReply', isNoMoreReply);
61
+  //   const { commentId } = this.props;
62
+  //   const { showReply } = this.state;
63
+  //   if (showReply && replies && replies.length) {
64
+  //     const len = replies.length;
65
+  //     return (
66
+  //       <div style={{ marginLeft: 50 }}>
67
+  //         {replies.map((item, index) => {
68
+  //           if (index === len - 1) {
69
+  //             return [
70
+  //               <ContentItem
71
+  //                 commentId={commentId}
72
+  //                 replyId={item.id}
73
+  //                 key={item.id}
74
+  //                 content={item}
75
+  //                 action="replyToReply" // 回复的回复
76
+  //               />,
77
+  //               <div className="comment-more-box" key="show_more_button">
78
+  //                 {!isNoMoreReply && replyCount !== len && (
79
+  //                   <span
80
+  //                     className="comment-show-more"
81
+  //                     onClick={() => this.handleGetMoreReply(commentId)}
82
+  //                   >
83
+  //                     {intl.get("reply.moreReply")}
84
+  //                   </span>
85
+  //                 )}
86
+
87
+  //                 <a
88
+  //                   style={{ float: "right" }}
89
+  //                   onClick={this.handleToggleReply}
90
+  //                 >
91
+  //                   <Icon type="up" /> {intl.get("reply.collapse")}
92
+  //                 </a>
93
+  //               </div>
94
+  //             ];
95
+  //           }
96
+  //           return (
97
+  //             <ContentItem
98
+  //               commentId={commentId}
99
+  //               replyId={item.id}
100
+  //               key={item.id}
101
+  //               content={item}
102
+  //               action="replyToReply" // 评论的回复
103
+  //             />
104
+  //           );
105
+  //         })}
106
+  //       </div>
107
+  //     );
108
+  //   }
109
+  //   return null;
110
+  // }
111
+
112
+  /**
113
+   * 渲染回复 DOM
114
+   * @param {array} replies 回复列表
115
+   * @param {number} replyCount 回复的数量
116
+   * @param {boolean} isNoMoreReply 是否没有更多回复
117
+   */
46
   renderReplies(replies, replyCount, isNoMoreReply) {
118
   renderReplies(replies, replyCount, isNoMoreReply) {
119
+    console.log("this.isMore3", this.state.isShowOver3);
47
     const { commentId } = this.props;
120
     const { commentId } = this.props;
48
     const { showReply } = this.state;
121
     const { showReply } = this.state;
122
+    console.log("replies", replies);
123
+    console.log("replyCount", replyCount);
124
+    console.log("isNoMoreReply", isNoMoreReply);
49
     if (showReply && replies && replies.length) {
125
     if (showReply && replies && replies.length) {
126
+      console.log("showReply", showReply);
50
       const len = replies.length;
127
       const len = replies.length;
51
       return (
128
       return (
52
-        <div style={{ marginLeft: 50 }}>
129
+        <div
130
+          style={{
131
+            marginLeft: 50,
132
+            borderTop: "1px solid #e3e3e3",
133
+            paddingTop: 15,
134
+            marginTop: -5
135
+          }}
136
+        >
53
           {replies.map((item, index) => {
137
           {replies.map((item, index) => {
54
             if (index === len - 1) {
138
             if (index === len - 1) {
55
               return [
139
               return [
56
-                <ContentItem
57
-                  commentId={commentId}
58
-                  replyId={item.id}
59
-                  key={item.id}
60
-                  content={item}
61
-                  action="replyToReply" // 回复的回复
62
-                />,
63
-                <div className="comment-more-box" key="show_more_button">
140
+                <ReplyItem replyItem={item} key={item.id} />,
141
+                <div key="show_more_button">
64
                   {!isNoMoreReply && replyCount !== len && (
142
                   {!isNoMoreReply && replyCount !== len && (
65
                     <span
143
                     <span
66
-                      className="comment-show-more"
144
+                      // className="comment-show-more"
67
                       onClick={() => this.handleGetMoreReply(commentId)}
145
                       onClick={() => this.handleGetMoreReply(commentId)}
68
                     >
146
                     >
69
-                      {intl.get("reply.moreReply")}
147
+                      展开更多评论
148
+                      <Icon type="down" />
149
+                    </span>
150
+                  )}
151
+                  {replyCount === len && (
152
+                    <span
153
+                      // className="comment-show-more"
154
+                      onClick={() => this.handleClickCollapse()}
155
+                    >
156
+                      收起
157
+                      <Icon type="up" />
70
                     </span>
158
                     </span>
71
                   )}
159
                   )}
72
 
160
 
73
-                  <a
161
+                  {/* <a
74
                     style={{ float: "right" }}
162
                     style={{ float: "right" }}
75
                     onClick={this.handleToggleReply}
163
                     onClick={this.handleToggleReply}
76
                   >
164
                   >
77
                     <Icon type="up" /> {intl.get("reply.collapse")}
165
                     <Icon type="up" /> {intl.get("reply.collapse")}
78
-                  </a>
166
+                  </a> */}
79
                 </div>
167
                 </div>
80
               ];
168
               ];
81
             }
169
             }
82
-            return (
83
-              <ContentItem
84
-                commentId={commentId}
85
-                replyId={item.id}
86
-                key={item.id}
87
-                content={item}
88
-                action="replyToReply" // 评论的回复
89
-              />
90
-            );
170
+            if (this.state.isShowOver3) {
171
+              console.log("11111");
172
+              return <ReplyItem replyItem={item} key={item.id} />;
173
+            }
174
+            if (!this.state.isShowOver3 && index < 3) {
175
+              console.log("222222");
176
+              return <ReplyItem replyItem={item} key={item.id} />;
177
+            }
178
+            console.log("3333");
179
+            return null;
91
           })}
180
           })}
92
         </div>
181
         </div>
93
       );
182
       );
94
     }
183
     }
95
-    return null;
96
   }
184
   }
97
 
185
 
98
   render() {
186
   render() {

+ 1
- 1
src/components/CommentList/index.js Ver fichero

77
       <div>
77
       <div>
78
         <Spin spinning={spinning}>
78
         <Spin spinning={spinning}>
79
           {/* <div>共 {total} 条评论</div> */}
79
           {/* <div>共 {total} 条评论</div> */}
80
-          <div>{intl.get("comment.totalComment", { total })}</div>
80
+          {/* <div>{intl.get("comment.totalComment", { total })}</div> */}
81
           {list.map(item => (
81
           {list.map(item => (
82
             <CommentBox content={item} key={item.id} commentId={item.id} />
82
             <CommentBox content={item} key={item.id} commentId={item.id} />
83
           ))}
83
           ))}

+ 9
- 4
src/components/ContentItem/index.css Ver fichero

1
 .comment-item-box {
1
 .comment-item-box {
2
   margin: 10px 0 0 0;
2
   margin: 10px 0 0 0;
3
   padding: 15px 5px 0 5px;
3
   padding: 15px 5px 0 5px;
4
-  border-top: 1px solid #eee;
4
+  border-top: 1px solid #d5d5d5;
5
 }
5
 }
6
 
6
 
7
 .comment-item-left {
7
 .comment-item-left {
14
   display: inline-block;
14
   display: inline-block;
15
   width: 90%;
15
   width: 90%;
16
   margin-left: 10px;
16
   margin-left: 10px;
17
-  margin-bottom: 20px;
17
+  /* margin-bottom: 20px; */
18
 }
18
 }
19
 
19
 
20
 .comment-item-content {
20
 .comment-item-content {
21
-  margin: 10px 0;
21
+  margin: 10px 0 20px 0;
22
   word-break: break-all;
22
   word-break: break-all;
23
 }
23
 }
24
 
24
 
38
 }
38
 }
39
 
39
 
40
 .comment-favor {
40
 .comment-favor {
41
-  font-size: 20px;
41
+  /* font-size: 20px; */
42
 }
42
 }
43
 
43
 
44
 .comment-favored {
44
 .comment-favored {
81
   margin-right: 10px;
81
   margin-right: 10px;
82
 }
82
 }
83
 
83
 
84
+.comment-item-icon {
85
+  float: right;
86
+  margin-left: 10px;
87
+}
88
+
84
 @media screen and (max-width: 616px) and (min-width: 449px) {
89
 @media screen and (max-width: 616px) and (min-width: 449px) {
85
   .comment-item-right {
90
   .comment-item-right {
86
     display: inline-block;
91
     display: inline-block;

+ 49
- 7
src/components/ContentItem/index.js Ver fichero

14
 import "./index.css";
14
 import "./index.css";
15
 import ImagePreviewer from "../ImagePreviewer/ImagePreviewer";
15
 import ImagePreviewer from "../ImagePreviewer/ImagePreviewer";
16
 
16
 
17
-// dayjs.locale("zh-cn");
17
+dayjs.locale("zh-cn");
18
 dayjs.extend(relativeTime);
18
 dayjs.extend(relativeTime);
19
 
19
 
20
 const LOCALES = {
20
 const LOCALES = {
122
             {/* <a href={`/${content.user_id}`}>
122
             {/* <a href={`/${content.user_id}`}>
123
               {content.user_name || "暂无昵称"}
123
               {content.user_name || "暂无昵称"}
124
             </a> */}
124
             </a> */}
125
-            <strong>{content.user_name || intl.get("comment.tourist")}</strong>
126
-            <span style={{ marginLeft: 10 }}>
125
+            <strong style={{ color: "#75ACFF" }}>
126
+              {content.user_name || intl.get("comment.tourist")}
127
+            </strong>
128
+            {/* <span style={{ marginLeft: 10 }}>
127
               <Tooltip
129
               <Tooltip
128
                 placement="top"
130
                 placement="top"
129
                 title={dayjs(content.created * 1000).format(
131
                 title={dayjs(content.created * 1000).format(
136
                       .fromNow()
138
                       .fromNow()
137
                   : dayjs(content.created * 1000).fromNow()}
139
                   : dayjs(content.created * 1000).fromNow()}
138
               </Tooltip>
140
               </Tooltip>
141
+            </span> */}
142
+            <span
143
+              className="comment-item-icon"
144
+              onClick={this.handleToggleInput}
145
+            >
146
+              <Icon type="message" />
147
+              &nbsp; {content.reply_count}
148
+            </span>
149
+            <span className="comment-item-icon">
150
+              <Icon
151
+                type="heart"
152
+                onClick={() => {
153
+                  if (replyId) {
154
+                    // 如果有 replyId,则说明是评论的回复
155
+                    app.sReplyFavor(content.id, commentId, content.favored);
156
+                    return;
157
+                  }
158
+                  app.sCommentFavor(content.id, content.favored);
159
+                }}
160
+                className={
161
+                  content.favored
162
+                    ? "comment-favor comment-favored"
163
+                    : "comment-favor"
164
+                }
165
+              />
166
+              &nbsp; {content.favor_count}
139
             </span>
167
             </span>
140
           </div>
168
           </div>
169
+          <div style={{ color: "#D5D5D5" }}>
170
+            {dayjs(content.created * 1000).format("MM-DD HH:mm:ss")}
171
+          </div>
172
+        </div>
173
+        <div>
141
           <div
174
           <div
142
             className="comment-item-content"
175
             className="comment-item-content"
143
             dangerouslySetInnerHTML={{
176
             dangerouslySetInnerHTML={{
194
               <div className="clearfix" />
227
               <div className="clearfix" />
195
             </div>
228
             </div>
196
           )}
229
           )}
197
-          <div className="comment-item-bottom">
230
+          {/* <div className="comment-item-bottom">
231
+            {content.reply_count ? (
232
+              <div>
233
+                <a className="comment-item-bottom-left" onClick={onShowReply}>
234
+                  {content.reply_count} 条回复
235
+                  {showReply ? <Icon type="up" /> : <Icon type="down" />}
236
+                </a>
237
+              </div>
238
+            ) : null}
239
+          </div> */}
240
+          {/* <div className="comment-item-bottom">
198
             {content.reply_count ? (
241
             {content.reply_count ? (
199
               <div>
242
               <div>
200
                 <a className="comment-item-bottom-left" onClick={onShowReply}>
243
                 <a className="comment-item-bottom-left" onClick={onShowReply}>
201
-                  {/* {content.reply_count} 条回复 */}
202
-                  {intl.get("reply.totalReply", { total: content.reply_count })}
244
+                  {content.reply_count} 条回复
203
                   {showReply ? <Icon type="up" /> : <Icon type="down" />}
245
                   {showReply ? <Icon type="up" /> : <Icon type="down" />}
204
                 </a>
246
                 </a>
205
               </div>
247
               </div>
250
               />
292
               />
251
               &nbsp;{content.favor_count}
293
               &nbsp;{content.favor_count}
252
             </div>
294
             </div>
253
-          </div>
295
+          </div> */}
254
         </div>
296
         </div>
255
 
297
 
256
         {showInput && (
298
         {showInput && (

+ 8
- 0
src/components/Editor/index.css Ver fichero

100
 .clearfix {
100
 .clearfix {
101
   clear: both;
101
   clear: both;
102
 }
102
 }
103
+
104
+.submitBtn {
105
+  width: 88px;
106
+  height: 30px;
107
+  background: rgba(252, 71, 71, 1);
108
+  border-radius: 15px;
109
+  color: #fff;
110
+}

+ 12
- 12
src/components/Editor/index.js Ver fichero

120
     const { maxLength } = this.props;
120
     const { maxLength } = this.props;
121
     let { value, fileMap, fileList } = this.state;
121
     let { value, fileMap, fileList } = this.state;
122
     if (value.length > maxLength) {
122
     if (value.length > maxLength) {
123
-      // message.error(`字数不得超过${maxLength}字`);
124
-      message.error(intl.get("editor.maxLength", { maxLength }));
123
+      message.error(`字数不得超过${maxLength}字`);
124
+      // message.error(intl.get("editor.maxLength", { maxLength }));
125
       return;
125
       return;
126
     }
126
     }
127
     const files = [];
127
     const files = [];
183
       maxLength,
183
       maxLength,
184
       autoFocus
184
       autoFocus
185
     } = this.props;
185
     } = this.props;
186
-    let placeholder = this.props.placeholder || intl.get("editor.placeholder");
187
-    let btnSubmitText = this.props.placeholder || intl.get("editor.SubmitBtn");
186
+    let placeholder = this.props.placeholder || "快发表评论吧!";
187
+    let btnSubmitText = this.props.placeholder || "发表评论";
188
     const handleSubmit = this.handleSubmit;
188
     const handleSubmit = this.handleSubmit;
189
     const disabledSubmit =
189
     const disabledSubmit =
190
       btnDisabled ||
190
       btnDisabled ||
192
     const inputValue = value || this.state.value;
192
     const inputValue = value || this.state.value;
193
     return (
193
     return (
194
       <div className="comment-editor-container">
194
       <div className="comment-editor-container">
195
-        <div
195
+        {/* <div
196
           className={classnames({
196
           className={classnames({
197
             "comment-editor-toolbar": true,
197
             "comment-editor-toolbar": true,
198
             "comment-editor-toolbar-error": inputValue.length > maxLength
198
             "comment-editor-toolbar-error": inputValue.length > maxLength
199
           })}
199
           })}
200
         >
200
         >
201
-          {intl.get("editor.alreadyEntered", {
202
-            count: inputValue.length,
203
-            maxLength
204
-          })}
205
-          {/* 已输入 {inputValue.length} / {maxLength} 字 */}
206
-        </div>
201
+          已输入 {inputValue.length} / {maxLength} 字
202
+        </div> */}
207
         <div className="comment-editor">
203
         <div className="comment-editor">
208
           <TextArea
204
           <TextArea
209
             value={inputValue}
205
             value={inputValue}
316
             </div>
312
             </div>
317
 
313
 
318
             <div className="comment-toolbar-right">
314
             <div className="comment-toolbar-right">
315
+              <span style={{ marginRight: 10 }}>
316
+                {inputValue.length} / {maxLength}
317
+              </span>
319
               {button ? (
318
               {button ? (
320
                 React.cloneElement(button, {
319
                 React.cloneElement(button, {
321
                   onClick: button.props.onClick || handleSubmit
320
                   onClick: button.props.onClick || handleSubmit
323
               ) : (
322
               ) : (
324
                 <Button
323
                 <Button
325
                   onClick={() => this.handleSubmit()}
324
                   onClick={() => this.handleSubmit()}
326
-                  type="primary"
325
+                  // type="primary"
326
+                  className="submitBtn"
327
                   loading={btnLoading}
327
                   loading={btnLoading}
328
                   disabled={disabledSubmit}
328
                   disabled={disabledSubmit}
329
                 >
329
                 >

+ 13
- 0
src/components/ReplyItem/index.css Ver fichero

1
+.reply-item {
2
+  margin-bottom: 20px;
3
+  /* margin-top: 5px; */
4
+  color: #d5d5d5;
5
+}
6
+
7
+.reply-item-content {
8
+  margin-bottom: 10px;
9
+}
10
+
11
+.reply-item-span {
12
+  margin-right: 25px;
13
+}

+ 73
- 0
src/components/ReplyItem/index.js Ver fichero

1
+import React, { Component } from "react";
2
+// import PropTypes from 'prop-type';
3
+import { Icon } from "antd";
4
+import Comment from "../../Comment";
5
+import CommentInput from "../CommentInput";
6
+import "./index.css";
7
+
8
+class ReplyItem extends Component {
9
+  constructor(props) {
10
+    super(props);
11
+    this.state = {
12
+      showInput: false
13
+    };
14
+    this.handleToggleInput = this.handleToggleInput.bind(this);
15
+  }
16
+
17
+  handleToggleInput() {
18
+    this.setState({ showInput: !this.state.showInput });
19
+  }
20
+
21
+  render() {
22
+    const { commentId, replyItem, replyId, action, app } = this.props;
23
+
24
+    const { showInput } = this.state;
25
+
26
+    return (
27
+      <div className="reply-item">
28
+        <div className="reply-item-content">
29
+          @<strong>{replyItem.user_name}</strong>
30
+          {replyItem.reply ? ` 回复 @${replyItem.reply.user_name}` : null}:
31
+          &nbsp;
32
+          {replyItem.content}
33
+        </div>
34
+        <div className="reply-item-icon">
35
+          <span className="reply-item-span">
36
+            <Icon
37
+              type="heart"
38
+              onClick={() => {
39
+                if (replyId) {
40
+                  // 如果有 replyId,则说明是评论的回复
41
+                  app.sReplyFavor(replyItem.id, commentId, replyItem.favored);
42
+                  return;
43
+                }
44
+                app.sCommentFavor(replyItem.id, replyItem.favored);
45
+              }}
46
+              className={
47
+                replyItem.favored
48
+                  ? "comment-favor comment-favored"
49
+                  : "comment-favor"
50
+              }
51
+            />
52
+            &nbsp; {replyItem.favor_count}
53
+          </span>
54
+          <span className="reply-item-span">
55
+            <Icon type="message" onClick={this.handleToggleInput} /> &nbsp;{" "}
56
+            {replyItem.reply_count || 0}
57
+          </span>
58
+        </div>
59
+        {showInput && (
60
+          <CommentInput
61
+            content={app.children}
62
+            action={action}
63
+            replyId={replyId}
64
+            commentId={commentId}
65
+            callback={this.handleToggleInput}
66
+          />
67
+        )}
68
+      </div>
69
+    );
70
+  }
71
+}
72
+
73
+export default Comment(ReplyItem);