Browse Source

feature: 评论移动端初适配

cloudzqy 5 years ago
parent
commit
b81225284a

+ 3
- 0
src/App.js View File

411
       sDeleteReply: this.sDeleteReply
411
       sDeleteReply: this.sDeleteReply
412
     };
412
     };
413
 
413
 
414
+    console.log(this.props.isMobile);
415
+
414
     return (
416
     return (
415
       <CommentContext.Provider value={value}>
417
       <CommentContext.Provider value={value}>
416
         <div className="comment">
418
         <div className="comment">
445
   limit: PropTypes.number, // 一次加载评论数量
447
   limit: PropTypes.number, // 一次加载评论数量
446
   onPageChange: PropTypes.func, // 页码变化回调
448
   onPageChange: PropTypes.func, // 页码变化回调
447
   onGetMoreBtnClick: PropTypes.func, // 点击查看更多按钮回调
449
   onGetMoreBtnClick: PropTypes.func, // 点击查看更多按钮回调
450
+  isMobile: PropTypes.bool,
448
   onDelete: PropTypes.func
451
   onDelete: PropTypes.func
449
 };
452
 };
450
 
453
 

+ 14
- 11
src/components/CommentBox/index.js View File

43
    * @param {boolean} isNoMoreReply 是否没有更多回复
43
    * @param {boolean} isNoMoreReply 是否没有更多回复
44
    */
44
    */
45
   renderReplies(replies, replyCount, isNoMoreReply) {
45
   renderReplies(replies, replyCount, isNoMoreReply) {
46
-    const { commentId } = this.props;
46
+    const { commentId, isMobile } = this.props;
47
     const { showReply } = this.state;
47
     const { showReply } = this.state;
48
     if (showReply && replies && replies.length) {
48
     if (showReply && replies && replies.length) {
49
       const len = replies.length;
49
       const len = replies.length;
54
               return [
54
               return [
55
                 <ContentItem
55
                 <ContentItem
56
                   commentId={commentId}
56
                   commentId={commentId}
57
+                  isMobile={isMobile}
57
                   replyId={item.id}
58
                   replyId={item.id}
58
                   key={item.id}
59
                   key={item.id}
59
                   content={item}
60
                   content={item}
60
                   action="replyToReply" // 回复的回复
61
                   action="replyToReply" // 回复的回复
61
                 />,
62
                 />,
62
                 <div className="comment-more-box" key="show_more_button">
63
                 <div className="comment-more-box" key="show_more_button">
63
-                  {!isNoMoreReply &&
64
-                    replyCount !== len && (
65
-                      <span
66
-                        className="comment-show-more"
67
-                        onClick={() => this.handleGetMoreReply(commentId)}
68
-                      >
69
-                        查看更多回复
70
-                      </span>
71
-                    )}
64
+                  {!isNoMoreReply && replyCount !== len && (
65
+                    <span
66
+                      className="comment-show-more"
67
+                      onClick={() => this.handleGetMoreReply(commentId)}
68
+                    >
69
+                      查看更多回复
70
+                    </span>
71
+                  )}
72
 
72
 
73
                   <a
73
                   <a
74
                     style={{ float: "right" }}
74
                     style={{ float: "right" }}
81
             }
81
             }
82
             return (
82
             return (
83
               <ContentItem
83
               <ContentItem
84
+                isMobile={isMobile}
84
                 commentId={commentId}
85
                 commentId={commentId}
85
                 replyId={item.id}
86
                 replyId={item.id}
86
                 key={item.id}
87
                 key={item.id}
96
   }
97
   }
97
 
98
 
98
   render() {
99
   render() {
99
-    const { content } = this.props;
100
+    const { content, isMobile } = this.props;
100
     const { showReply } = this.state;
101
     const { showReply } = this.state;
102
+
101
     return (
103
     return (
102
       <div>
104
       <div>
103
         <ContentItem
105
         <ContentItem
106
+          isMobile={isMobile}
104
           content={content}
107
           content={content}
105
           onShowReply={this.handleToggleReply}
108
           onShowReply={this.handleToggleReply}
106
           showReply={showReply}
109
           showReply={showReply}

+ 7
- 2
src/components/CommentList/index.js View File

67
   }
67
   }
68
 
68
 
69
   render() {
69
   render() {
70
-    const { list, total, loading } = this.props.app;
70
+    const { list, total, loading, isMobile } = this.props.app;
71
 
71
 
72
     const spinning = Boolean(
72
     const spinning = Boolean(
73
       loading.sGetComment || loading.sCommentFavor || loading.sReplyFavor
73
       loading.sGetComment || loading.sCommentFavor || loading.sReplyFavor
77
         <Spin spinning={spinning}>
77
         <Spin spinning={spinning}>
78
           <div>共 {total} 条评论</div>
78
           <div>共 {total} 条评论</div>
79
           {list.map(item => (
79
           {list.map(item => (
80
-            <CommentBox content={item} key={item.id} commentId={item.id} />
80
+            <CommentBox
81
+              isMobile={isMobile}
82
+              content={item}
83
+              key={item.id}
84
+              commentId={item.id}
85
+            />
81
           ))}
86
           ))}
82
           {this.renderPagination()}
87
           {this.renderPagination()}
83
         </Spin>
88
         </Spin>

+ 21
- 7
src/components/ContentItem/index.css View File

10
   width: 40px;
10
   width: 40px;
11
 }
11
 }
12
 
12
 
13
-.comment-item-right {
13
+.comment-item-middle {
14
   display: inline-block;
14
   display: inline-block;
15
-  width: 90%;
15
+  width: 80%;
16
   margin-left: 10px;
16
   margin-left: 10px;
17
   margin-bottom: 20px;
17
   margin-bottom: 20px;
18
 }
18
 }
19
 
19
 
20
+.comment-item-right {
21
+  display: inline-block;
22
+  vertical-align: top;
23
+  width: 10%;
24
+}
25
+
20
 .comment-item-content {
26
 .comment-item-content {
21
   margin: 10px 0;
27
   margin: 10px 0;
22
   word-break: break-all;
28
   word-break: break-all;
23
 }
29
 }
24
 
30
 
31
+.comment-item-top-right {
32
+  margin: 20px auto;
33
+}
34
+
25
 .comment-item-bottom {
35
 .comment-item-bottom {
26
   margin: 20px auto;
36
   margin: 20px auto;
27
 }
37
 }
81
   margin-right: 10px;
91
   margin-right: 10px;
82
 }
92
 }
83
 
93
 
94
+.text-center {
95
+  text-align: center;
96
+}
97
+
84
 @media screen and (max-width: 616px) and (min-width: 449px) {
98
 @media screen and (max-width: 616px) and (min-width: 449px) {
85
-  .comment-item-right {
99
+  .comment-item-middle {
86
     display: inline-block;
100
     display: inline-block;
87
     width: 85%;
101
     width: 85%;
88
     margin-left: 10px;
102
     margin-left: 10px;
90
 }
104
 }
91
 
105
 
92
 @media screen and (max-width: 449px) and (min-width: 365px) {
106
 @media screen and (max-width: 449px) and (min-width: 365px) {
93
-  .comment-item-right {
107
+  .comment-item-middle {
94
     display: inline-block;
108
     display: inline-block;
95
-    width: 80%;
109
+    width: 70%;
96
     margin-left: 10px;
110
     margin-left: 10px;
97
   }
111
   }
98
 }
112
 }
99
 
113
 
100
 @media screen and (max-width: 365px) {
114
 @media screen and (max-width: 365px) {
101
-  .comment-item-right {
115
+  .comment-item-middle {
102
     display: inline-block;
116
     display: inline-block;
103
-    width: 75%;
117
+    width: 65%;
104
     margin-left: 10px;
118
     margin-left: 10px;
105
   }
119
   }
106
 }
120
 }

+ 174
- 32
src/components/ContentItem/index.js View File

75
       action,
75
       action,
76
       showReply,
76
       showReply,
77
       onShowReply,
77
       onShowReply,
78
+      isMobile,
78
       app
79
       app
79
     } = this.props;
80
     } = this.props;
80
 
81
 
105
       }
106
       }
106
     }
107
     }
107
 
108
 
108
-    return (
109
-      <div className="comment-item-box">
110
-        <div className="comment-item-left">
111
-          <Avatar src={content.user_avatar || avatar} size="large" />
112
-        </div>
113
-        <div className="comment-item-right">
114
-          <div>
115
-            {/* <a href={`/${content.user_id}`}>
116
-              {content.user_name || "暂无昵称"}
117
-            </a> */}
118
-            <strong>{content.user_name || "游客"}</strong>
119
-            <span style={{ marginLeft: 10 }}>
120
-              <Tooltip
121
-                placement="top"
122
-                title={dayjs(content.created * 1000).format(
123
-                  "YYYY-MM-DD HH:mm:ss"
124
-                )}
125
-              >
126
-                {dayjs(content.created * 1000).fromNow()}
127
-              </Tooltip>
128
-            </span>
109
+    if (isMobile) {
110
+      return (
111
+        <div className="comment-item-box">
112
+          <div className="comment-item-left">
113
+            <Avatar src={content.user_avatar || avatar} size="large" />
129
           </div>
114
           </div>
130
-          <div
131
-            className="comment-item-content"
132
-            dangerouslySetInnerHTML={{
133
-              __html: renderContent(
134
-                this.renderTextWithReply(newContent, content)
135
-              )
136
-            }}
137
-          />
138
-          {// image为空时不渲染comment-item-image
139
-          imageList.length > 0 &&
140
-            imageList[0] !== "" && (
115
+          <div className="comment-item-middle">
116
+            <div>
117
+              <strong>{content.user_name || "游客"}</strong>
118
+            </div>
119
+            <div
120
+              className="comment-item-content"
121
+              dangerouslySetInnerHTML={{
122
+                __html: renderContent(
123
+                  this.renderTextWithReply(newContent, content)
124
+                )
125
+              }}
126
+            />
127
+            {// image为空时不渲染comment-item-image
128
+            imageList.length > 0 && imageList[0] !== "" && (
141
               <div className="comment-item-image">
129
               <div className="comment-item-image">
142
                 {!this.state.showPreviewer &&
130
                 {!this.state.showPreviewer &&
143
                   imgs.map((item, index) => {
131
                   imgs.map((item, index) => {
184
                 <div className="clearfix" />
172
                 <div className="clearfix" />
185
               </div>
173
               </div>
186
             )}
174
             )}
175
+            <div>
176
+              <Tooltip
177
+                placement="top"
178
+                title={dayjs(content.created * 1000).format(
179
+                  "YYYY-MM-DD HH:mm:ss"
180
+                )}
181
+              >
182
+                {dayjs(content.created * 1000).fromNow()}
183
+              </Tooltip>
184
+            </div>
185
+            <div className="comment-item-bottom">
186
+              {content.reply_count ? (
187
+                <div>
188
+                  <a className="comment-item-bottom-left" onClick={onShowReply}>
189
+                    {content.reply_count} 条回复
190
+                    {showReply ? <Icon type="up" /> : <Icon type="down" />}
191
+                  </a>
192
+                </div>
193
+              ) : null}
194
+              {app.userId === content.user_id && (
195
+                <Popconfirm
196
+                  title="确定要删除吗?"
197
+                  onConfirm={() => {
198
+                    if (replyId) {
199
+                      app.sDeleteReply(content.id, commentId);
200
+                      return;
201
+                    }
202
+                    app.sDeleteComment(content.id);
203
+                  }}
204
+                  okText="确定"
205
+                  cancelText="取消"
206
+                >
207
+                  <a className="comment-item-bottom-right">&nbsp; 删除</a>
208
+                </Popconfirm>
209
+              )}
210
+            </div>
211
+          </div>
212
+
213
+          <div className="comment-item-right">
214
+            <div
215
+              className="comment-item-top-right"
216
+              onClick={() => {
217
+                if (replyId) {
218
+                  // 如果有 replyId,则说明是评论的回复
219
+                  app.sReplyFavor(content.id, commentId, content.favored);
220
+                  return;
221
+                }
222
+                app.sCommentFavor(content.id, content.favored);
223
+              }}
224
+            >
225
+              <div className="text-center">
226
+                <Icon
227
+                  type="heart"
228
+                  className={
229
+                    content.favored
230
+                      ? "comment-favor comment-favored"
231
+                      : "comment-favor"
232
+                  }
233
+                />
234
+              </div>
235
+              <div className="text-center">{content.favor_count}</div>
236
+            </div>
237
+          </div>
238
+          {showInput && (
239
+            <CommentInput
240
+              content={app.children}
241
+              action={action}
242
+              replyId={replyId}
243
+              commentId={commentId}
244
+              callback={this.handleToggleInput}
245
+            />
246
+          )}
247
+        </div>
248
+      );
249
+    }
250
+
251
+    return (
252
+      <div className="comment-item-box">
253
+        <div className="comment-item-left">
254
+          <Avatar src={content.user_avatar || avatar} size="large" />
255
+        </div>
256
+        <div className="comment-item-right">
257
+          <div>
258
+            {/* <a href={`/${content.user_id}`}>
259
+              {content.user_name || "暂无昵称"}
260
+            </a> */}
261
+            <strong>{content.user_name || "游客"}</strong>
262
+            <span style={{ marginLeft: 10 }}>
263
+              <Tooltip
264
+                placement="top"
265
+                title={dayjs(content.created * 1000).format(
266
+                  "YYYY-MM-DD HH:mm:ss"
267
+                )}
268
+              >
269
+                {dayjs(content.created * 1000).fromNow()}
270
+              </Tooltip>
271
+            </span>
272
+          </div>
273
+          <div
274
+            className="comment-item-content"
275
+            dangerouslySetInnerHTML={{
276
+              __html: renderContent(
277
+                this.renderTextWithReply(newContent, content)
278
+              )
279
+            }}
280
+          />
281
+          {// image为空时不渲染comment-item-image
282
+          imageList.length > 0 && imageList[0] !== "" && (
283
+            <div className="comment-item-image">
284
+              {!this.state.showPreviewer &&
285
+                imgs.map((item, index) => {
286
+                  if (item.type === "divider") {
287
+                    return (
288
+                      <div className="comment-item-image-wrapper" key={index}>
289
+                        <div className="comment-img-divider" />
290
+                        {/* <img src={item} alt={item} className="comment-img" /> */}
291
+                      </div>
292
+                    );
293
+                  }
294
+                  return (
295
+                    <div
296
+                      className="comment-item-image-wrapper"
297
+                      key={index}
298
+                      onClick={() => {
299
+                        let i = index;
300
+                        if (needClear) {
301
+                          if (index > 3) {
302
+                            i -= 1;
303
+                          }
304
+                          if (index > 7) {
305
+                            i -= 1;
306
+                          }
307
+                        }
308
+                        this.showPreviewer(i);
309
+                      }}
310
+                    >
311
+                      <div
312
+                        style={{ backgroundImage: `url(${item})` }}
313
+                        className="comment-img-thumbnail"
314
+                      />
315
+                      {/* <img src={item} alt={item} className="comment-img" /> */}
316
+                    </div>
317
+                  );
318
+                })}
319
+              {this.state.showPreviewer && (
320
+                <ImagePreviewer
321
+                  list={imageList}
322
+                  index={this.state.previewerIndex}
323
+                  onFold={this.hidePreviewer}
324
+                />
325
+              )}
326
+              <div className="clearfix" />
327
+            </div>
328
+          )}
187
           <div className="comment-item-bottom">
329
           <div className="comment-item-bottom">
188
             {content.reply_count ? (
330
             {content.reply_count ? (
189
               <div>
331
               <div>

+ 8
- 1
src/index.js View File

4
 // import registerServiceWorker from "./registerServiceWorker";
4
 // import registerServiceWorker from "./registerServiceWorker";
5
 
5
 
6
 const Index = props => (
6
 const Index = props => (
7
-  <App showAlertComment showAlertReply showAlertFavor showError {...props}>
7
+  <App
8
+    isMobile
9
+    showAlertComment
10
+    showAlertReply
11
+    showAlertFavor
12
+    showError
13
+    {...props}
14
+  >
8
     <Editor maxUpload={9} autoFocus />
15
     <Editor maxUpload={9} autoFocus />
9
   </App>
16
   </App>
10
 );
17
 );