narro 5 лет назад
Родитель
Сommit
88ed1ddca6

+ 5
- 0
CHANGELOG.md Просмотреть файл

1
 # CHANGELOG
1
 # CHANGELOG
2
 
2
 
3
+## 0.5.5
4
+
5
+- [x] 增加删除评论、回复功能
6
+- [x] 错误回调onError增加info:{ response } 参数
7
+
3
 ## 0.5.4
8
 ## 0.5.4
4
 
9
 
5
 - [x] 暂无昵称 -> 游客
10
 - [x] 暂无昵称 -> 游客

+ 17
- 17
README.md Просмотреть файл

2
 
2
 
3
 通用评论系统及编辑器
3
 通用评论系统及编辑器
4
 
4
 
5
-**`version 0.5.4`**
5
+**`version 0.5.5`**
6
 
6
 
7
 ```js
7
 ```js
8
 import Comment, { Editor, RenderText } from 'comment';
8
 import Comment, { Editor, RenderText } from 'comment';
13
 ## Comment
13
 ## Comment
14
 
14
 
15
 
15
 
16
-| props            | type          | default                            | required | description                                                  |
17
-| ---------------- | ------------- | ---------------------------------- | -------- | ------------------------------------------------------------ |
18
-| type             | number        |                                    | true     | 评论的 type                                                  |
19
-| businessId       | string        |                                    | true     | 评论的 business id                                           |
20
-| API              | string        | http://api.links123.net/comment/v1 | false    | API 前缀                                                     |
21
-| showList         | boolean       | true                               | false    | 是否显示评论列表                                             |
22
-| showEditor       | boolean       | true                               | false    | 是否显示评论输入框                                           |
23
-| showAlertComment | boolean       | false                              | false    | 评论成功之后,是否通过 Antd 的 Message 组件进行提示          |
24
-| showAlertReply   | boolean       | false                              | false    | 回复成功之后,是否通过 Antd 的 Message 组件进行提示          |
25
-| showAlertFavor   | boolean       | false                              | false    | 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示 |
26
-| showError        | boolean       | true                               | false    | 是否使用Antd的Message组件提示错误信息                        |
27
-| onError          | function(msg) |                                    | false    | 错误回调, 出错了会被调用                                     |
28
-| token            | string        |                                    | false    | [deprecated] token,用于身份认证,非必须。默认使用 cookie    |
29
-
16
+| props            | type          | default                            | required | description                                                                       |
17
+| ---------------- | ------------- | ---------------------------------- | -------- | --------------------------------------------------------------------------------- |
18
+| type             | number        |                                    | true     | 评论的 type                                                                       |
19
+| businessId       | string        |                                    | true     | 评论的 business id                                                                |
20
+| API              | string        | http://api.links123.net/comment/v1 | false    | API 前缀                                                                          |
21
+| showList         | boolean       | true                               | false    | 是否显示评论列表                                                                  |
22
+| showEditor       | boolean       | true                               | false    | 是否显示评论输入框                                                                |
23
+| showAlertComment | boolean       | false                              | false    | 评论成功之后,是否通过 Antd 的 Message 组件进行提示                               |
24
+| showAlertReply   | boolean       | false                              | false    | 回复成功之后,是否通过 Antd 的 Message 组件进行提示                               |
25
+| showAlertFavor   | boolean       | false                              | false    | 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示                      |
26
+| showError        | boolean       | true                               | false    | 是否使用Antd的Message组件提示错误信息                                             |
27
+| onError          | function(msg) |                                    | false    | 错误回调, 出错了会被调用                                                          |
28
+| userId           | number        |                                    | false    | 用户id, comment内部不维护用户id, 调用组件时传递过来, 目前用于判断是否显示删除按钮 |
29
+| token            | string        |                                    | false    | [deprecated] token,用于身份认证,非必须。默认使用 cookie                         |
30
 
30
 
31
 
31
 
32
 ## Editor
32
 ## Editor
52
 | onRef               | function                        |               | false    | 传递子组件的引用                                                                                  |
52
 | onRef               | function                        |               | false    | 传递子组件的引用                                                                                  |
53
 | closeUploadWhenBlur | boolean                         |               | false    | 当 upload 失去焦点(鼠标点击非 Upload 的区域)的时候,是否自动关闭 Popover                        |
53
 | closeUploadWhenBlur | boolean                         |               | false    | 当 upload 失去焦点(鼠标点击非 Upload 的区域)的时候,是否自动关闭 Popover                        |
54
 | showError           | boolean                         | true          | false    | 是否使用Antd的Message组件提示错误信息, 主要是上传图片出错的情况                                   |
54
 | showError           | boolean                         | true          | false    | 是否使用Antd的Message组件提示错误信息, 主要是上传图片出错的情况                                   |
55
-| onError             | function(msg)                   |               | false    | 错误回调, 出错了会被调用, 主要是上传图片出错的情况                                                |
55
+| onError             | function(msg,{response})        |               | false    | 错误回调, 出错了会被调用, 主要是上传图片出错的情况                                                |
56
 
56
 
57
 
57
 
58
 
58
 
265
 - [x] oss/sts 接口报错
265
 - [x] oss/sts 接口报错
266
 - [ ] 头像 404 `https://links123-images.oss-cn-hangzhou.aliyuncs.com/avatar/`
266
 - [ ] 头像 404 `https://links123-images.oss-cn-hangzhou.aliyuncs.com/avatar/`
267
 - [ ] 上传图片的时候偶尔会出现InvalidPart
267
 - [ ] 上传图片的时候偶尔会出现InvalidPart
268
-
268
+- [ ] 上传图片失败时, 提示并且不显示缩略图

+ 110
- 72
lib/App.js Просмотреть файл

85
       isNoMoreComment: false
85
       isNoMoreComment: false
86
     };
86
     };
87
     _this.handleChangeLoading = _this.handleChangeLoading.bind(_this);
87
     _this.handleChangeLoading = _this.handleChangeLoading.bind(_this);
88
-    _this.sGetComment = _this.sGetComment.bind(_this);
89
-    _this.sGetReply = _this.sGetReply.bind(_this);
90
     _this.sCreateComment = _this.sCreateComment.bind(_this);
88
     _this.sCreateComment = _this.sCreateComment.bind(_this);
91
-    _this.sCreateReply = _this.sCreateReply.bind(_this);
89
+    _this.sDeleteComment = _this.sDeleteComment.bind(_this);
92
     _this.sCommentFavor = _this.sCommentFavor.bind(_this);
90
     _this.sCommentFavor = _this.sCommentFavor.bind(_this);
91
+    _this.sCreateReply = _this.sCreateReply.bind(_this);
92
+    _this.sDeleteReply = _this.sDeleteReply.bind(_this);
93
+    _this.errorHandler = _this.errorHandler.bind(_this);
94
+    _this.sGetComment = _this.sGetComment.bind(_this);
93
     _this.sReplyFavor = _this.sReplyFavor.bind(_this);
95
     _this.sReplyFavor = _this.sReplyFavor.bind(_this);
96
+    _this.sGetReply = _this.sGetReply.bind(_this);
94
     _this.sOssSts = _this.sOssSts.bind(_this);
97
     _this.sOssSts = _this.sOssSts.bind(_this);
95
     return _this;
98
     return _this;
96
   }
99
   }
110
   }, {
113
   }, {
111
     key: "error",
114
     key: "error",
112
     value: function error(msg) {
115
     value: function error(msg) {
116
+      var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
117
+
113
       if (this.props.showError) {
118
       if (this.props.showError) {
114
         _message3.default.error(msg);
119
         _message3.default.error(msg);
115
       }
120
       }
116
       if (this.props.onError) {
121
       if (this.props.onError) {
117
-        this.props.onError(msg);
122
+        this.props.onError(msg, info);
123
+      }
124
+    }
125
+  }, {
126
+    key: "errorHandler",
127
+    value: function errorHandler(error) {
128
+      if (error.response && error.response.data && error.response.data.msg) {
129
+        this.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT, { response: error.response });
130
+        return;
118
       }
131
       }
132
+      this.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT, { response: error.response });
119
     }
133
     }
120
 
134
 
121
     /**
135
     /**
180
             isNoMoreComment: true
194
             isNoMoreComment: true
181
           });
195
           });
182
         }
196
         }
183
-      }).catch(function (error) {
184
-        if (error.response && error.response.data && error.response.data.msg) {
185
-          _this2.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
186
-          return;
187
-        }
188
-        _this2.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
189
-      }).finally(function () {
197
+      }).catch(this.errorHandler).finally(function () {
190
         _this2.handleChangeLoading("sGetComment", false);
198
         _this2.handleChangeLoading("sGetComment", false);
191
       });
199
       });
192
     }
200
     }
235
           return item;
243
           return item;
236
         });
244
         });
237
         _this3.setState({ list: list });
245
         _this3.setState({ list: list });
238
-      }).catch(function (error) {
239
-        if (error.response && error.response.data && error.response.data.msg) {
240
-          _this3.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
241
-          return;
242
-        }
243
-        _this3.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
244
-      }).finally(function () {
246
+      }).catch(this.errorHandler).finally(function () {
245
         _this3.handleChangeLoading("sGetReply", false);
247
         _this3.handleChangeLoading("sGetReply", false);
246
       });
248
       });
247
     }
249
     }
292
           isTemporary: true // 临时的数据
294
           isTemporary: true // 临时的数据
293
         }));
295
         }));
294
         _this4.setState({ list: list, total: total + 1 });
296
         _this4.setState({ list: list, total: total + 1 });
295
-      }).catch(function (error) {
296
-        if (error.response && error.response.data && error.response.data.msg) {
297
-          _this4.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
298
-          return;
299
-        }
300
-        _this4.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
301
-      }).finally(function () {
297
+      }).catch(this.errorHandler).finally(function () {
302
         _this4.handleChangeLoading("sCreateComment", false);
298
         _this4.handleChangeLoading("sCreateComment", false);
303
       });
299
       });
304
     }
300
     }
305
 
301
 
302
+    /**
303
+     * 删除评论
304
+     */
305
+
306
+  }, {
307
+    key: "sDeleteComment",
308
+    value: function sDeleteComment(commentId) {
309
+      var _this5 = this;
310
+
311
+      this.handleChangeLoading("sDeleteComment", true);
312
+      var API = this.props.API;
313
+
314
+      this.axios(API + "/comments/" + commentId, {
315
+        method: "delete",
316
+        withCredentials: true
317
+      }).then(function () {
318
+        var _state2 = _this5.state,
319
+            list = _state2.list,
320
+            total = _state2.total;
321
+
322
+        var res = list.filter(function (item) {
323
+          return item.id !== commentId;
324
+        });
325
+        _this5.setState({ list: res, total: total - 1 });
326
+      }).catch(this.errorHandler).finally(function () {
327
+        _this5.handleChangeLoading("sDeleteComment", false);
328
+      });
329
+    }
330
+
306
     /**
331
     /**
307
      * 添加回复
332
      * 添加回复
308
      * 回复评论/回复回复
333
      * 回复评论/回复回复
312
   }, {
337
   }, {
313
     key: "sCreateReply",
338
     key: "sCreateReply",
314
     value: function sCreateReply(data, cb) {
339
     value: function sCreateReply(data, cb) {
315
-      var _this5 = this;
340
+      var _this6 = this;
316
 
341
 
317
       if (!data.content) return this.error("回复内容不能为空 ");
342
       if (!data.content) return this.error("回复内容不能为空 ");
318
       this.handleChangeLoading("sCreateReply", true);
343
       this.handleChangeLoading("sCreateReply", true);
323
         data: data,
348
         data: data,
324
         withCredentials: true
349
         withCredentials: true
325
       }).then(function (response) {
350
       }).then(function (response) {
326
-        if (_this5.props.showAlertReply) {
351
+        if (_this6.props.showAlertReply) {
327
           _message3.default.success("回复成功!");
352
           _message3.default.success("回复成功!");
328
         }
353
         }
329
         if ((0, _helper.isFunction)(cb)) cb();
354
         if ((0, _helper.isFunction)(cb)) cb();
330
         // 将数据写入到 list 中
355
         // 将数据写入到 list 中
331
         // 临时插入
356
         // 临时插入
332
         // 等到获取数据之后,删除临时数据
357
         // 等到获取数据之后,删除临时数据
333
-        var list = _this5.state.list.map(function (item) {
358
+        var list = _this6.state.list.map(function (item) {
334
           if (item.id === data.comment_id) {
359
           if (item.id === data.comment_id) {
335
             if (!item.replies) item.replies = [];
360
             if (!item.replies) item.replies = [];
336
             item.replies.push(_extends({}, response.data, {
361
             item.replies.push(_extends({}, response.data, {
340
           }
365
           }
341
           return item;
366
           return item;
342
         });
367
         });
343
-        _this5.setState({ list: list });
344
-      }).catch(function (error) {
345
-        if (error.response && error.response.data && error.response.data.msg) {
346
-          _this5.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
347
-          return;
348
-        }
349
-        _this5.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
350
-      }).finally(function () {
351
-        _this5.handleChangeLoading("sCreateReply", false);
368
+        _this6.setState({ list: list });
369
+      }).catch(this.errorHandler).finally(function () {
370
+        _this6.handleChangeLoading("sCreateReply", false);
371
+      });
372
+    }
373
+
374
+    /**
375
+     * 删除回复
376
+     * @param {*} replyId 
377
+     * @param {*} commentId 
378
+     */
379
+
380
+  }, {
381
+    key: "sDeleteReply",
382
+    value: function sDeleteReply(replyId, commentId) {
383
+      var _this7 = this;
384
+
385
+      this.handleChangeLoading("sDeleteReply", true);
386
+      var API = this.props.API;
387
+
388
+      this.axios(API + "/replies/" + replyId + "?CommentID=" + commentId, {
389
+        method: "delete",
390
+        withCredentials: true
391
+      }).then(function () {
392
+        var list = _this7.state.list.map(function (item) {
393
+          if (item.id === commentId) {
394
+            var replies = item.replies.filter(function (item) {
395
+              return item.id !== replyId;
396
+            });
397
+            item.replies = replies;
398
+            item.reply_count -= 1;
399
+          }
400
+          return item;
401
+        });
402
+        _this7.setState({ list: list });
403
+      }).catch(this.errorHandler).finally(function () {
404
+        _this7.handleChangeLoading("sDeleteReply", false);
352
       });
405
       });
353
     }
406
     }
354
 
407
 
361
   }, {
414
   }, {
362
     key: "sCommentFavor",
415
     key: "sCommentFavor",
363
     value: function sCommentFavor(commentId, favored) {
416
     value: function sCommentFavor(commentId, favored) {
364
-      var _this6 = this;
417
+      var _this8 = this;
365
 
418
 
366
       this.handleChangeLoading("sCommentFavor", true);
419
       this.handleChangeLoading("sCommentFavor", true);
367
       var API = this.props.API;
420
       var API = this.props.API;
370
         method: favored ? "delete" : "put",
423
         method: favored ? "delete" : "put",
371
         withCredentials: true
424
         withCredentials: true
372
       }).then(function (response) {
425
       }).then(function (response) {
373
-        if (_this6.props.showAlertFavor) {
426
+        if (_this8.props.showAlertFavor) {
374
           _message3.default.success(favored ? "取消点赞成功!" : "点赞成功!");
427
           _message3.default.success(favored ? "取消点赞成功!" : "点赞成功!");
375
         }
428
         }
376
         // 更新 list 中的该项数据的 favored
429
         // 更新 list 中的该项数据的 favored
377
-        var list = _this6.state.list.map(function (item) {
430
+        var list = _this8.state.list.map(function (item) {
378
           if (item.id === commentId) {
431
           if (item.id === commentId) {
379
             item.favored = !favored;
432
             item.favored = !favored;
380
             item.favor_count += favored ? -1 : 1;
433
             item.favor_count += favored ? -1 : 1;
381
           }
434
           }
382
           return item;
435
           return item;
383
         });
436
         });
384
-        _this6.setState({ list: list });
385
-      }).catch(function (error) {
386
-        if (error.response && error.response.data && error.response.data.msg) {
387
-          _this6.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
388
-          return;
389
-        }
390
-        _this6.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
391
-      }).finally(function () {
392
-        _this6.handleChangeLoading("sCommentFavor", false);
437
+        _this8.setState({ list: list });
438
+      }).catch(this.errorHandler).finally(function () {
439
+        _this8.handleChangeLoading("sCommentFavor", false);
393
       });
440
       });
394
     }
441
     }
395
 
442
 
403
   }, {
450
   }, {
404
     key: "sReplyFavor",
451
     key: "sReplyFavor",
405
     value: function sReplyFavor(replyId, commentId, favored) {
452
     value: function sReplyFavor(replyId, commentId, favored) {
406
-      var _this7 = this;
453
+      var _this9 = this;
407
 
454
 
408
       this.handleChangeLoading("sReplyFavor", true);
455
       this.handleChangeLoading("sReplyFavor", true);
409
       var API = this.props.API;
456
       var API = this.props.API;
417
       }).then(function (response) {
464
       }).then(function (response) {
418
         _message3.default.success(favored ? "取消点赞成功!" : "点赞成功!");
465
         _message3.default.success(favored ? "取消点赞成功!" : "点赞成功!");
419
         // 更新 list 中的该项数据的 favored
466
         // 更新 list 中的该项数据的 favored
420
-        var list = _this7.state.list.map(function (item) {
467
+        var list = _this9.state.list.map(function (item) {
421
           if (item.id === commentId) {
468
           if (item.id === commentId) {
422
             item.replies = item.replies.map(function (r) {
469
             item.replies = item.replies.map(function (r) {
423
               if (r.id === replyId) {
470
               if (r.id === replyId) {
432
           }
479
           }
433
           return item;
480
           return item;
434
         });
481
         });
435
-        _this7.setState({ list: list });
436
-      }).catch(function (error) {
437
-        if (error.response && error.response.data && error.response.data.msg) {
438
-          _this7.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
439
-          return;
440
-        }
441
-        _this7.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
442
-      }).finally(function () {
443
-        _this7.handleChangeLoading("sReplyFavor", false);
482
+        _this9.setState({ list: list });
483
+      }).catch(this.errorHandler).finally(function () {
484
+        _this9.handleChangeLoading("sReplyFavor", false);
444
       });
485
       });
445
     }
486
     }
446
 
487
 
451
   }, {
492
   }, {
452
     key: "sOssSts",
493
     key: "sOssSts",
453
     value: function sOssSts() {
494
     value: function sOssSts() {
454
-      var _this8 = this;
495
+      var _this10 = this;
455
 
496
 
456
       this.handleChangeLoading("sOssSts", true);
497
       this.handleChangeLoading("sOssSts", true);
457
       var API = this.props.API;
498
       var API = this.props.API;
458
 
499
 
459
       this.axios.get(API + "/oss/sts").then(function (response) {
500
       this.axios.get(API + "/oss/sts").then(function (response) {
460
-        _this8.setState({ oss: _extends({}, response.data) });
461
-      }).catch(function (error) {
462
-        if (error.response && error.response.data && error.response.data.msg) {
463
-          _this8.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
464
-          return;
465
-        }
466
-        _this8.error(_lang2.default[error.message] || _constant.ERROR_DEFAULT);
467
-      }).finally(function () {
468
-        _this8.handleChangeLoading("sOssSts", false);
501
+        _this10.setState({ oss: _extends({}, response.data) });
502
+      }).catch(this.errorHandler).finally(function () {
503
+        _this10.handleChangeLoading("sOssSts", false);
469
       });
504
       });
470
     }
505
     }
471
   }, {
506
   }, {
479
         sReplyFavor: this.sReplyFavor,
514
         sReplyFavor: this.sReplyFavor,
480
         sCreateReply: this.sCreateReply,
515
         sCreateReply: this.sCreateReply,
481
         sGetReply: this.sGetReply,
516
         sGetReply: this.sGetReply,
482
-        sOssSts: this.sOssSts
517
+        sOssSts: this.sOssSts,
518
+        sDeleteComment: this.sDeleteComment,
519
+        sDeleteReply: this.sDeleteReply
483
       });
520
       });
484
 
521
 
485
       return _react2.default.createElement(
522
       return _react2.default.createElement(
512
   showAlertReply: _propTypes2.default.bool, // 回复成功之后,是否通过 Antd 的 Message 组件进行提示
549
   showAlertReply: _propTypes2.default.bool, // 回复成功之后,是否通过 Antd 的 Message 组件进行提示
513
   showAlertFavor: _propTypes2.default.bool, // 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示
550
   showAlertFavor: _propTypes2.default.bool, // 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示
514
   showError: _propTypes2.default.bool, // 是否使用Antd的Message组件提示错误信息
551
   showError: _propTypes2.default.bool, // 是否使用Antd的Message组件提示错误信息
515
-  onError: _propTypes2.default.func // 错误回调, 出错了会被调用
552
+  onError: _propTypes2.default.func, // 错误回调, 出错了会被调用
553
+  userId: _propTypes2.default.number // 用户id, comment内部不维护用户id, 调用组件时传递过来, 目前用于判断是否显示删除按钮
516
 };
554
 };
517
 
555
 
518
 App.defaultProps = {
556
 App.defaultProps = {

+ 1
- 1
lib/App.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 23
- 0
lib/components/ContentItem/index.js Просмотреть файл

4
   value: true
4
   value: true
5
 });
5
 });
6
 
6
 
7
+var _popconfirm = require("antd/es/popconfirm");
8
+
9
+var _popconfirm2 = _interopRequireDefault(_popconfirm);
10
+
7
 var _icon = require("antd/es/icon");
11
 var _icon = require("antd/es/icon");
8
 
12
 
9
 var _icon2 = _interopRequireDefault(_icon);
13
 var _icon2 = _interopRequireDefault(_icon);
18
 
22
 
19
 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
23
 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
20
 
24
 
25
+require("antd/es/popconfirm/style/css");
26
+
21
 require("antd/es/icon/style/css");
27
 require("antd/es/icon/style/css");
22
 
28
 
23
 require("antd/es/tooltip/style/css");
29
 require("antd/es/tooltip/style/css");
201
                 showReply ? _react2.default.createElement(_icon2.default, { type: "up" }) : _react2.default.createElement(_icon2.default, { type: "down" })
207
                 showReply ? _react2.default.createElement(_icon2.default, { type: "up" }) : _react2.default.createElement(_icon2.default, { type: "down" })
202
               )
208
               )
203
             ) : null,
209
             ) : null,
210
+            app.userId === content.user_id && _react2.default.createElement(
211
+              _popconfirm2.default,
212
+              { title: "\u786E\u5B9A\u8981\u5220\u9664\u5417?", onConfirm: function onConfirm() {
213
+                  if (replyId) {
214
+                    app.sDeleteReply(content.id, commentId);
215
+                    return;
216
+                  }
217
+                  app.sDeleteComment(content.id);
218
+                }, okText: "\u786E\u5B9A", cancelText: "\u53D6\u6D88" },
219
+              _react2.default.createElement(
220
+                "a",
221
+                {
222
+                  className: "comment-item-bottom-right"
223
+                },
224
+                "\xA0 \u5220\u9664"
225
+              )
226
+            ),
204
             _react2.default.createElement(
227
             _react2.default.createElement(
205
               "a",
228
               "a",
206
               {
229
               {

+ 1
- 1
lib/components/ContentItem/index.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 1
- 1
lib/components/Editor/Upload.js Просмотреть файл

150
             _message3.default.error(msg);
150
             _message3.default.error(msg);
151
           }
151
           }
152
           if (_this2.props.onError) {
152
           if (_this2.props.onError) {
153
-            _this2.props.onError(msg);
153
+            _this2.props.onError(msg, { response: e.response });
154
           }
154
           }
155
           info.onError(e);
155
           info.onError(e);
156
         });
156
         });

+ 1
- 1
lib/components/Editor/Upload.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 1
- 1
lib/components/Editor/index.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 13
- 2
lib/index.js Просмотреть файл

81
           showAlertReply: true,
81
           showAlertReply: true,
82
           showAlertFavor: true,
82
           showAlertFavor: true,
83
           showError: false,
83
           showError: false,
84
-          onError: function onError(msg) {
84
+          userId: 71299,
85
+          onError: function onError(msg, _ref2) {
86
+            var response = _ref2.response;
87
+
88
+            if (response.status === 401) {
89
+              console.log("unlogined");
90
+            }
85
             console.log("-----------" + msg);
91
             console.log("-----------" + msg);
86
           }
92
           }
87
         },
93
         },
96
             console.log("succ");
102
             console.log("succ");
97
           },
103
           },
98
           showError: false,
104
           showError: false,
99
-          onError: function onError(msg) {
105
+          onError: function onError(msg, _ref3) {
106
+            var response = _ref3.response;
107
+
108
+            if (response.status === 401) {
109
+              console.log("unlogined");
110
+            }
100
             console.log("-----------" + msg);
111
             console.log("-----------" + msg);
101
           }
112
           }
102
         })
113
         })

+ 1
- 1
lib/index.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 1
- 1
package.json Просмотреть файл

1
 {
1
 {
2
   "name": "comment",
2
   "name": "comment",
3
-  "version": "0.5.4",
3
+  "version": "0.5.5",
4
   "main": "lib/App.js",
4
   "main": "lib/App.js",
5
   "description": "通用评论",
5
   "description": "通用评论",
6
   "keywords": [
6
   "keywords": [

+ 82
- 56
src/App.js Просмотреть файл

29
       isNoMoreComment: false
29
       isNoMoreComment: false
30
     };
30
     };
31
     this.handleChangeLoading = this.handleChangeLoading.bind(this);
31
     this.handleChangeLoading = this.handleChangeLoading.bind(this);
32
-    this.sGetComment = this.sGetComment.bind(this);
33
-    this.sGetReply = this.sGetReply.bind(this);
34
     this.sCreateComment = this.sCreateComment.bind(this);
32
     this.sCreateComment = this.sCreateComment.bind(this);
35
-    this.sCreateReply = this.sCreateReply.bind(this);
33
+    this.sDeleteComment = this.sDeleteComment.bind(this);
36
     this.sCommentFavor = this.sCommentFavor.bind(this);
34
     this.sCommentFavor = this.sCommentFavor.bind(this);
35
+    this.sCreateReply = this.sCreateReply.bind(this);
36
+    this.sDeleteReply = this.sDeleteReply.bind(this);
37
+    this.errorHandler = this.errorHandler.bind(this);
38
+    this.sGetComment = this.sGetComment.bind(this);
37
     this.sReplyFavor = this.sReplyFavor.bind(this);
39
     this.sReplyFavor = this.sReplyFavor.bind(this);
40
+    this.sGetReply = this.sGetReply.bind(this);
38
     this.sOssSts = this.sOssSts.bind(this);
41
     this.sOssSts = this.sOssSts.bind(this);
39
   }
42
   }
40
 
43
 
50
 
53
 
51
   componentDidMount() {}
54
   componentDidMount() {}
52
 
55
 
53
-  error(msg) {
56
+  error(msg, info = {}) {
54
     if (this.props.showError) {
57
     if (this.props.showError) {
55
       message.error(msg);
58
       message.error(msg);
56
     }
59
     }
57
     if (this.props.onError) {
60
     if (this.props.onError) {
58
-      this.props.onError(msg);
61
+      this.props.onError(msg, info);
59
     }
62
     }
60
   }
63
   }
61
 
64
 
65
+  errorHandler(error) {
66
+    if (error.response && error.response.data && error.response.data.msg) {
67
+      this.error(lang[error.response.data.msg] || ERROR_DEFAULT, {
68
+        response: error.response
69
+      });
70
+      return;
71
+    }
72
+    this.error(lang[error.message] || ERROR_DEFAULT, {
73
+      response: error.response
74
+    });
75
+  }
76
+
62
   /**
77
   /**
63
    * 改变 loading 状态
78
    * 改变 loading 状态
64
    * @param {string} key key
79
    * @param {string} key key
102
           });
117
           });
103
         }
118
         }
104
       })
119
       })
105
-      .catch(error => {
106
-        if (error.response && error.response.data && error.response.data.msg) {
107
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
108
-          return;
109
-        }
110
-        this.error(lang[error.message] || ERROR_DEFAULT);
111
-      })
120
+      .catch(this.errorHandler)
112
       .finally(() => {
121
       .finally(() => {
113
         this.handleChangeLoading("sGetComment", false);
122
         this.handleChangeLoading("sGetComment", false);
114
       });
123
       });
150
         });
159
         });
151
         this.setState({ list });
160
         this.setState({ list });
152
       })
161
       })
153
-      .catch(error => {
154
-        if (error.response && error.response.data && error.response.data.msg) {
155
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
156
-          return;
157
-        }
158
-        this.error(lang[error.message] || ERROR_DEFAULT);
159
-      })
162
+      .catch(this.errorHandler)
160
       .finally(() => {
163
       .finally(() => {
161
         this.handleChangeLoading("sGetReply", false);
164
         this.handleChangeLoading("sGetReply", false);
162
       });
165
       });
194
         });
197
         });
195
         this.setState({ list, total: total + 1 });
198
         this.setState({ list, total: total + 1 });
196
       })
199
       })
197
-      .catch(error => {
198
-        if (error.response && error.response.data && error.response.data.msg) {
199
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
200
-          return;
201
-        }
202
-        this.error(lang[error.message] || ERROR_DEFAULT);
203
-      })
200
+      .catch(this.errorHandler)
204
       .finally(() => {
201
       .finally(() => {
205
         this.handleChangeLoading("sCreateComment", false);
202
         this.handleChangeLoading("sCreateComment", false);
206
       });
203
       });
207
   }
204
   }
208
 
205
 
206
+  /**
207
+   * 删除评论
208
+   */
209
+  sDeleteComment(commentId) {
210
+    this.handleChangeLoading("sDeleteComment", true);
211
+    const { API } = this.props;
212
+    this.axios(`${API}/comments/${commentId}`, {
213
+      method: "delete",
214
+      withCredentials: true
215
+    })
216
+      .then(() => {
217
+        const { list, total } = this.state;
218
+        const res = list.filter(item => item.id !== commentId);
219
+        this.setState({ list: res, total: total - 1 });
220
+      })
221
+      .catch(this.errorHandler)
222
+      .finally(() => {
223
+        this.handleChangeLoading("sDeleteComment", false);
224
+      });
225
+  }
226
+
209
   /**
227
   /**
210
    * 添加回复
228
    * 添加回复
211
    * 回复评论/回复回复
229
    * 回复评论/回复回复
241
         });
259
         });
242
         this.setState({ list });
260
         this.setState({ list });
243
       })
261
       })
244
-      .catch(error => {
245
-        if (error.response && error.response.data && error.response.data.msg) {
246
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
247
-          return;
248
-        }
249
-        this.error(lang[error.message] || ERROR_DEFAULT);
250
-      })
262
+      .catch(this.errorHandler)
251
       .finally(() => {
263
       .finally(() => {
252
         this.handleChangeLoading("sCreateReply", false);
264
         this.handleChangeLoading("sCreateReply", false);
253
       });
265
       });
254
   }
266
   }
255
 
267
 
268
+  /**
269
+   * 删除回复
270
+   * @param {*} replyId
271
+   * @param {*} commentId
272
+   */
273
+  sDeleteReply(replyId, commentId) {
274
+    this.handleChangeLoading("sDeleteReply", true);
275
+    const { API } = this.props;
276
+    this.axios(`${API}/replies/${replyId}?CommentID=${commentId}`, {
277
+      method: "delete",
278
+      withCredentials: true
279
+    })
280
+      .then(() => {
281
+        const list = this.state.list.map(item => {
282
+          if (item.id === commentId) {
283
+            const replies = item.replies.filter(item => item.id !== replyId);
284
+            item.replies = replies;
285
+            item.reply_count -= 1;
286
+          }
287
+          return item;
288
+        });
289
+        this.setState({ list });
290
+      })
291
+      .catch(this.errorHandler)
292
+      .finally(() => {
293
+        this.handleChangeLoading("sDeleteReply", false);
294
+      });
295
+  }
296
+
256
   /**
297
   /**
257
    * 评论 点赞/取消点赞
298
    * 评论 点赞/取消点赞
258
    * @param {string} commentId { commentId }
299
    * @param {string} commentId { commentId }
279
         });
320
         });
280
         this.setState({ list });
321
         this.setState({ list });
281
       })
322
       })
282
-      .catch(error => {
283
-        if (error.response && error.response.data && error.response.data.msg) {
284
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
285
-          return;
286
-        }
287
-        this.error(lang[error.message] || ERROR_DEFAULT);
288
-      })
323
+      .catch(this.errorHandler)
289
       .finally(() => {
324
       .finally(() => {
290
         this.handleChangeLoading("sCommentFavor", false);
325
         this.handleChangeLoading("sCommentFavor", false);
291
       });
326
       });
327
         });
362
         });
328
         this.setState({ list });
363
         this.setState({ list });
329
       })
364
       })
330
-      .catch(error => {
331
-        if (error.response && error.response.data && error.response.data.msg) {
332
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
333
-          return;
334
-        }
335
-        this.error(lang[error.message] || ERROR_DEFAULT);
336
-      })
365
+      .catch(this.errorHandler)
337
       .finally(() => {
366
       .finally(() => {
338
         this.handleChangeLoading("sReplyFavor", false);
367
         this.handleChangeLoading("sReplyFavor", false);
339
       });
368
       });
350
       .then(response => {
379
       .then(response => {
351
         this.setState({ oss: { ...response.data } });
380
         this.setState({ oss: { ...response.data } });
352
       })
381
       })
353
-      .catch(error => {
354
-        if (error.response && error.response.data && error.response.data.msg) {
355
-          this.error(lang[error.response.data.msg] || ERROR_DEFAULT);
356
-          return;
357
-        }
358
-        this.error(lang[error.message] || ERROR_DEFAULT);
359
-      })
382
+      .catch(this.errorHandler)
360
       .finally(() => {
383
       .finally(() => {
361
         this.handleChangeLoading("sOssSts", false);
384
         this.handleChangeLoading("sOssSts", false);
362
       });
385
       });
373
       sReplyFavor: this.sReplyFavor,
396
       sReplyFavor: this.sReplyFavor,
374
       sCreateReply: this.sCreateReply,
397
       sCreateReply: this.sCreateReply,
375
       sGetReply: this.sGetReply,
398
       sGetReply: this.sGetReply,
376
-      sOssSts: this.sOssSts
399
+      sOssSts: this.sOssSts,
400
+      sDeleteComment: this.sDeleteComment,
401
+      sDeleteReply: this.sDeleteReply
377
     };
402
     };
378
 
403
 
379
     return (
404
     return (
403
   showAlertReply: PropTypes.bool, // 回复成功之后,是否通过 Antd 的 Message 组件进行提示
428
   showAlertReply: PropTypes.bool, // 回复成功之后,是否通过 Antd 的 Message 组件进行提示
404
   showAlertFavor: PropTypes.bool, // 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示
429
   showAlertFavor: PropTypes.bool, // 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示
405
   showError: PropTypes.bool, // 是否使用Antd的Message组件提示错误信息
430
   showError: PropTypes.bool, // 是否使用Antd的Message组件提示错误信息
406
-  onError: PropTypes.func // 错误回调, 出错了会被调用
431
+  onError: PropTypes.func, // 错误回调, 出错了会被调用
432
+  userId: PropTypes.number // 用户id, comment内部不维护用户id, 调用组件时传递过来, 目前用于判断是否显示删除按钮
407
 };
433
 };
408
 
434
 
409
 App.defaultProps = {
435
 App.defaultProps = {

+ 17
- 2
src/components/ContentItem/index.js Просмотреть файл

1
 import React, { Component } from "react";
1
 import React, { Component } from "react";
2
 import PropTypes from "prop-types";
2
 import PropTypes from "prop-types";
3
-import { Avatar, Icon, Tooltip } from "antd";
3
+import { Avatar, Icon, Tooltip, Popconfirm } from "antd";
4
 import dayjs from "dayjs";
4
 import dayjs from "dayjs";
5
 import "dayjs/locale/zh-cn";
5
 import "dayjs/locale/zh-cn";
6
 import relativeTime from "dayjs/plugin/relativeTime";
6
 import relativeTime from "dayjs/plugin/relativeTime";
121
                 </a>
121
                 </a>
122
               </div>
122
               </div>
123
             ) : null}
123
             ) : null}
124
-
124
+            {app.userId === content.user_id && (
125
+              <Popconfirm
126
+                title="确定要删除吗?"
127
+                onConfirm={() => {
128
+                  if (replyId) {
129
+                    app.sDeleteReply(content.id, commentId);
130
+                    return;
131
+                  }
132
+                  app.sDeleteComment(content.id);
133
+                }}
134
+                okText="确定"
135
+                cancelText="取消"
136
+              >
137
+                <a className="comment-item-bottom-right">&nbsp; 删除</a>
138
+              </Popconfirm>
139
+            )}
125
             <a
140
             <a
126
               onClick={this.handleToggleInput}
141
               onClick={this.handleToggleInput}
127
               className="comment-item-bottom-right"
142
               className="comment-item-bottom-right"

+ 1
- 1
src/components/Editor/Upload.js Просмотреть файл

93
             message.error(msg);
93
             message.error(msg);
94
           }
94
           }
95
           if (this.props.onError) {
95
           if (this.props.onError) {
96
-            this.props.onError(msg);
96
+            this.props.onError(msg, { response: e.response });
97
           }
97
           }
98
           info.onError(e);
98
           info.onError(e);
99
         });
99
         });

+ 9
- 2
src/index.js Просмотреть файл

41
         showAlertReply
41
         showAlertReply
42
         showAlertFavor
42
         showAlertFavor
43
         showError={false}
43
         showError={false}
44
-        onError={msg => {
44
+        userId={71299}
45
+        onError={(msg, { response }) => {
46
+          if (response.status === 401) {
47
+            console.log("unlogined");
48
+          }
45
           console.log(`-----------${msg}`);
49
           console.log(`-----------${msg}`);
46
         }}
50
         }}
47
       >
51
       >
56
             console.log("succ");
60
             console.log("succ");
57
           }}
61
           }}
58
           showError={false}
62
           showError={false}
59
-          onError={msg => {
63
+          onError={(msg, { response }) => {
64
+            if (response.status === 401) {
65
+              console.log("unlogined");
66
+            }
60
             console.log(`-----------${msg}`);
67
             console.log(`-----------${msg}`);
61
           }}
68
           }}
62
         />
69
         />