Ver código fonte

feat: 支持跟读

Tzhx 4 anos atrás
pai
commit
7da2eb9b93

+ 118
- 116
lib/App.js Ver arquivo

@@ -1,11 +1,11 @@
1
-"use strict";
1
+'use strict';
2 2
 
3 3
 Object.defineProperty(exports, "__esModule", {
4 4
   value: true
5 5
 });
6 6
 exports.RenderText = exports.Editor = undefined;
7 7
 
8
-var _message2 = require("antd/es/message");
8
+var _message2 = require('antd/es/message');
9 9
 
10 10
 var _message3 = _interopRequireDefault(_message2);
11 11
 
@@ -13,57 +13,57 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
13 13
 
14 14
 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; }; }();
15 15
 
16
-require("antd/es/message/style");
16
+require('antd/es/message/style');
17 17
 
18
-var _react = require("react");
18
+var _react = require('react');
19 19
 
20 20
 var _react2 = _interopRequireDefault(_react);
21 21
 
22
-var _propTypes = require("prop-types");
22
+var _propTypes = require('prop-types');
23 23
 
24 24
 var _propTypes2 = _interopRequireDefault(_propTypes);
25 25
 
26
-var _axios = require("axios");
26
+var _axios = require('axios');
27 27
 
28 28
 var _axios2 = _interopRequireDefault(_axios);
29 29
 
30
-var _jsCookie = require("js-cookie");
30
+var _jsCookie = require('js-cookie');
31 31
 
32 32
 var _jsCookie2 = _interopRequireDefault(_jsCookie);
33 33
 
34
-var _reactIntlUniversal = require("react-intl-universal");
34
+var _reactIntlUniversal = require('react-intl-universal');
35 35
 
36 36
 var _reactIntlUniversal2 = _interopRequireDefault(_reactIntlUniversal);
37 37
 
38
-var _constant = require("./constant");
38
+var _constant = require('./constant');
39 39
 
40
-var _Comment = require("./Comment");
40
+var _Comment = require('./Comment');
41 41
 
42
-var _helper = require("./helper");
42
+var _helper = require('./helper');
43 43
 
44
-var _CommentInput = require("./components/CommentInput");
44
+var _CommentInput = require('./components/CommentInput');
45 45
 
46 46
 var _CommentInput2 = _interopRequireDefault(_CommentInput);
47 47
 
48
-var _CommentList = require("./components/CommentList");
48
+var _CommentList = require('./components/CommentList');
49 49
 
50 50
 var _CommentList2 = _interopRequireDefault(_CommentList);
51 51
 
52
-var _Editor = require("./components/Editor");
52
+var _Editor = require('./components/Editor');
53 53
 
54 54
 var _Editor2 = _interopRequireDefault(_Editor);
55 55
 
56
-var _RenderText = require("./components/RenderText");
56
+var _RenderText = require('./components/RenderText');
57 57
 
58 58
 var _RenderText2 = _interopRequireDefault(_RenderText);
59 59
 
60
-var _EditComment = require("./components/EditComment/EditComment");
60
+var _EditComment = require('./components/EditComment/EditComment');
61 61
 
62 62
 var _EditComment2 = _interopRequireDefault(_EditComment);
63 63
 
64
-var _lang = require("./lang");
64
+var _lang = require('./lang');
65 65
 
66
-require("./App.css");
66
+require('./App.css');
67 67
 
68 68
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
69 69
 
@@ -94,13 +94,13 @@ var App = function (_Component) {
94 94
       // 是否没有更多评论了
95 95
       isNoMoreComment: false,
96 96
       initDone: false,
97
-      locale: "zh-CN",
97
+      locale: 'zh-CN',
98 98
       editModalVisible: false,
99
-      action: "",
100
-      replyId: "",
101
-      commentId: "",
102
-      userId: "",
103
-      content: "",
99
+      action: '',
100
+      replyId: '',
101
+      commentId: '',
102
+      userId: '',
103
+      content: '',
104 104
       replyPage: 1,
105 105
       emojiList: []
106 106
     };
@@ -123,16 +123,16 @@ var App = function (_Component) {
123 123
   }
124 124
 
125 125
   _createClass(App, [{
126
-    key: "componentWillMount",
126
+    key: 'componentWillMount',
127 127
     value: function componentWillMount() {
128 128
       this.axios = _axios2.default;
129 129
       this.axios.defaults.withCredentials = true;
130 130
       if (this.props.token) {
131
-        this.axios.defaults.headers.common["Authorization"] = "Bearer " + this.props.token;
131
+        this.axios.defaults.headers.common['Authorization'] = 'Bearer ' + this.props.token;
132 132
       }
133 133
     }
134 134
   }, {
135
-    key: "componentDidMount",
135
+    key: 'componentDidMount',
136 136
     value: function componentDidMount() {
137 137
       this.loadLocales();
138 138
       this.loadEmoji();
@@ -145,27 +145,27 @@ var App = function (_Component) {
145 145
      */
146 146
 
147 147
   }, {
148
-    key: "loadLocales",
148
+    key: 'loadLocales',
149 149
     value: function loadLocales() {
150 150
       var _this2 = this;
151 151
 
152 152
       var currentLocale = this.props.locales;
153 153
 
154
-      var cookieLang = _jsCookie2.default.get("lnk_lang");
154
+      var cookieLang = _jsCookie2.default.get('lnk_lang');
155 155
       if (!currentLocale) {
156 156
         currentLocale = cookieLang || _reactIntlUniversal2.default.determineLocale({
157
-          urlLocaleKey: "lang"
157
+          urlLocaleKey: 'lang'
158 158
         });
159 159
       }
160 160
       currentLocale = _lang.SUPPORT_LOCALES.find(function (item) {
161 161
         return item.value === currentLocale;
162
-      }) ? currentLocale : "zh-CN";
163
-      var version = require("./version.json").hash;
162
+      }) ? currentLocale : 'zh-CN';
163
+      var version = require('./version.json').hash;
164 164
       // 使用绝对路径
165
-      var languageURL = _constant.LANGUAGE_LINK + "/" + currentLocale + ".json?v=" + version;
165
+      var languageURL = _constant.LANGUAGE_LINK + '/' + currentLocale + '.json?v=' + version;
166 166
       return fetch(languageURL).then(function (response) {
167 167
         if (response.status >= 400) {
168
-          throw new Error("Bad response from server");
168
+          throw new Error('Bad response from server');
169 169
         }
170 170
         return response.json();
171 171
       }).then(function (data) {
@@ -184,21 +184,21 @@ var App = function (_Component) {
184 184
      */
185 185
 
186 186
   }, {
187
-    key: "loadEmoji",
187
+    key: 'loadEmoji',
188 188
     value: function loadEmoji() {
189 189
       var _this3 = this;
190 190
 
191
-      this.axios.get(this.props.emojiAPI + "/emoticons").then(function (response) {
191
+      this.axios.get(this.props.emojiAPI + '/emoticons').then(function (response) {
192 192
         var emojiMap = {};
193 193
         response.data.list.forEach(function (item) {
194 194
           emojiMap[item.name] = item.url;
195 195
         });
196
-        window.sessionStorage.setItem("emojiMap", JSON.stringify(emojiMap));
196
+        window.sessionStorage.setItem('emojiMap', JSON.stringify(emojiMap));
197 197
         _this3.setState({ emojiList: response.data.list });
198 198
       }).catch(this.errorHandler);
199 199
     }
200 200
   }, {
201
-    key: "handleEdit",
201
+    key: 'handleEdit',
202 202
     value: function handleEdit(_ref) {
203 203
       var replyId = _ref.replyId,
204 204
           commentId = _ref.commentId,
@@ -208,7 +208,7 @@ var App = function (_Component) {
208 208
 
209 209
       this.setState({
210 210
         editModalVisible: true,
211
-        action: content.replies ? "comment" : content.reply ? "replyToReply" : "reply",
211
+        action: content.replies ? 'comment' : content.reply ? 'replyToReply' : 'reply',
212 212
         replyId: replyId,
213 213
         commentId: commentId,
214 214
         userId: userId,
@@ -217,14 +217,14 @@ var App = function (_Component) {
217 217
       });
218 218
     }
219 219
   }, {
220
-    key: "handleClose",
220
+    key: 'handleClose',
221 221
     value: function handleClose() {
222 222
       this.setState({
223 223
         editModalVisible: false
224 224
       });
225 225
     }
226 226
   }, {
227
-    key: "error",
227
+    key: 'error',
228 228
     value: function error(msg) {
229 229
       var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
230 230
 
@@ -236,7 +236,7 @@ var App = function (_Component) {
236 236
       }
237 237
     }
238 238
   }, {
239
-    key: "errorHandler",
239
+    key: 'errorHandler',
240 240
     value: function errorHandler(error) {
241 241
       var locale = this.state.locale;
242 242
 
@@ -259,7 +259,7 @@ var App = function (_Component) {
259 259
      */
260 260
 
261 261
   }, {
262
-    key: "handleChangeLoading",
262
+    key: 'handleChangeLoading',
263 263
     value: function handleChangeLoading(key, value) {
264 264
       var loading = this.state.loading;
265 265
 
@@ -272,24 +272,26 @@ var App = function (_Component) {
272 272
      */
273 273
 
274 274
   }, {
275
-    key: "sGetComment",
275
+    key: 'sGetComment',
276 276
     value: function sGetComment() {
277 277
       var _this4 = this;
278 278
 
279 279
       var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
280 280
           _ref2$page = _ref2.page,
281
-          page = _ref2$page === undefined ? 1 : _ref2$page;
281
+          page = _ref2$page === undefined ? 1 : _ref2$page,
282
+          _ref2$filterSpeak = _ref2.filterSpeak,
283
+          filterSpeak = _ref2$filterSpeak === undefined ? 0 : _ref2$filterSpeak;
282 284
 
283 285
       var pageType = this.props.pageType;
284 286
 
285
-      this.handleChangeLoading("sGetComment", true);
287
+      this.handleChangeLoading('sGetComment', true);
286 288
       var _props = this.props,
287 289
           API = _props.API,
288 290
           type = _props.type,
289 291
           businessId = _props.businessId,
290 292
           limit = _props.limit;
291 293
 
292
-      this.axios.get(API + "/comments?type=" + type + "&business_id=" + businessId + "&page=" + page + "&limit=" + limit).then(function (response) {
294
+      this.axios.get(API + '/comments?type=' + type + '&business_id=' + businessId + '&is_speak=' + filterSpeak + '&page=' + page + '&limit=' + limit).then(function (response) {
293 295
         var _response$data = response.data,
294 296
             list = _response$data.list,
295 297
             page = _response$data.page,
@@ -299,7 +301,7 @@ var App = function (_Component) {
299 301
           var newList = list;
300 302
           var oldList = _this4.state.list;
301 303
 
302
-          if (pageType === "more") {
304
+          if (pageType === 'more') {
303 305
             if (page > 1) {
304 306
               // 删除临时数据
305 307
               oldList = oldList.filter(function (o) {
@@ -307,7 +309,7 @@ var App = function (_Component) {
307 309
               });
308 310
               newList = oldList.concat(newList);
309 311
             }
310
-          } else if (pageType === "pagination") {
312
+          } else if (pageType === 'pagination') {
311 313
             // TODO 滚动到顶部
312 314
             window.scrollTo(0, 0);
313 315
           }
@@ -319,13 +321,13 @@ var App = function (_Component) {
319 321
           });
320 322
           _this4.props.onCountChange(total);
321 323
         } else {
322
-          _message3.default.info(_reactIntlUniversal2.default.get("message.noMoreComment"));
324
+          _message3.default.info(_reactIntlUniversal2.default.get('message.noMoreComment'));
323 325
           _this4.setState({
324 326
             isNoMoreComment: true
325 327
           });
326 328
         }
327 329
       }).catch(this.errorHandler).finally(function () {
328
-        _this4.handleChangeLoading("sGetComment", false);
330
+        _this4.handleChangeLoading('sGetComment', false);
329 331
       });
330 332
     }
331 333
 
@@ -334,7 +336,7 @@ var App = function (_Component) {
334 336
      */
335 337
 
336 338
   }, {
337
-    key: "sGetReply",
339
+    key: 'sGetReply',
338 340
     value: function sGetReply() {
339 341
       var _this5 = this;
340 342
 
@@ -343,14 +345,14 @@ var App = function (_Component) {
343 345
           _ref3$page = _ref3.page,
344 346
           page = _ref3$page === undefined ? 1 : _ref3$page;
345 347
 
346
-      this.handleChangeLoading("sGetReply", true);
348
+      this.handleChangeLoading('sGetReply', true);
347 349
       var _props2 = this.props,
348 350
           API = _props2.API,
349 351
           limit = _props2.limit;
350 352
 
351
-      this.axios.get(API + "/replies?comment_id=" + commentId + "&page=" + page + "&limit=" + limit).then(function (response) {
353
+      this.axios.get(API + '/replies?comment_id=' + commentId + '&page=' + page + '&limit=' + limit).then(function (response) {
352 354
         if (!response.data.list) {
353
-          _message3.default.info(_reactIntlUniversal2.default.get("message.noMoreData"));
355
+          _message3.default.info(_reactIntlUniversal2.default.get('message.noMoreData'));
354 356
         }
355 357
         var list = _this5.state.list.map(function (item) {
356 358
           if (item.id === commentId) {
@@ -376,7 +378,7 @@ var App = function (_Component) {
376 378
         });
377 379
         _this5.setState({ list: list });
378 380
       }).catch(this.errorHandler).finally(function () {
379
-        _this5.handleChangeLoading("sGetReply", false);
381
+        _this5.handleChangeLoading('sGetReply', false);
380 382
       });
381 383
     }
382 384
 
@@ -386,7 +388,7 @@ var App = function (_Component) {
386 388
      */
387 389
 
388 390
   }, {
389
-    key: "sCreateComment",
391
+    key: 'sCreateComment',
390 392
     value: function sCreateComment() {
391 393
       var _this6 = this;
392 394
 
@@ -395,16 +397,16 @@ var App = function (_Component) {
395 397
 
396 398
       var cb = arguments[1];
397 399
 
398
-      if (!content) return this.error(_reactIntlUniversal2.default.get("message.notNull"));
399
-      this.handleChangeLoading("sCreateComment", true);
400
+      if (!content) return this.error(_reactIntlUniversal2.default.get('message.notNull'));
401
+      this.handleChangeLoading('sCreateComment', true);
400 402
       var _props3 = this.props,
401 403
           API = _props3.API,
402 404
           type = _props3.type,
403 405
           businessId = _props3.businessId,
404 406
           businessUserId = _props3.businessUserId;
405 407
 
406
-      this.axios(API + "/comments", {
407
-        method: "post",
408
+      this.axios(API + '/comments', {
409
+        method: 'post',
408 410
         data: {
409 411
           type: type,
410 412
           business_id: businessId,
@@ -414,7 +416,7 @@ var App = function (_Component) {
414 416
         withCredentials: true
415 417
       }).then(function (response) {
416 418
         if (_this6.props.showAlertComment) {
417
-          _message3.default.success(_reactIntlUniversal2.default.get("message.success"));
419
+          _message3.default.success(_reactIntlUniversal2.default.get('message.success'));
418 420
         }
419 421
         if ((0, _helper.isFunction)(cb)) cb(response.data);
420 422
         // 将数据写入到 list 中
@@ -434,7 +436,7 @@ var App = function (_Component) {
434 436
         _this6.props.onCommentFail(error.response.status);
435 437
         _this6.errorHandler(error);
436 438
       }).finally(function () {
437
-        _this6.handleChangeLoading("sCreateComment", false);
439
+        _this6.handleChangeLoading('sCreateComment', false);
438 440
       });
439 441
     }
440 442
 
@@ -443,15 +445,15 @@ var App = function (_Component) {
443 445
      */
444 446
 
445 447
   }, {
446
-    key: "sDeleteComment",
448
+    key: 'sDeleteComment',
447 449
     value: function sDeleteComment(commentId) {
448 450
       var _this7 = this;
449 451
 
450
-      this.handleChangeLoading("sDeleteComment", true);
452
+      this.handleChangeLoading('sDeleteComment', true);
451 453
       var API = this.props.API;
452 454
 
453
-      this.axios(API + "/comments/" + commentId, {
454
-        method: "delete",
455
+      this.axios(API + '/comments/' + commentId, {
456
+        method: 'delete',
455 457
         withCredentials: true
456 458
       }).then(function () {
457 459
         var _state2 = _this7.state,
@@ -468,7 +470,7 @@ var App = function (_Component) {
468 470
         _this7.props.onDelete(_constant.COMMENT_TYPE.COMMENT, deletedItem);
469 471
         _this7.props.onCountChange(total - 1);
470 472
       }).catch(this.errorHandler).finally(function () {
471
-        _this7.handleChangeLoading("sDeleteComment", false);
473
+        _this7.handleChangeLoading('sDeleteComment', false);
472 474
       });
473 475
     }
474 476
     /**
@@ -477,18 +479,18 @@ var App = function (_Component) {
477 479
      */
478 480
 
479 481
   }, {
480
-    key: "sUpdateComment",
482
+    key: 'sUpdateComment',
481 483
     value: function sUpdateComment(_ref5) {
482 484
       var _this8 = this;
483 485
 
484 486
       var commentId = _ref5.commentId,
485 487
           content = _ref5.content;
486 488
 
487
-      this.handleChangeLoading("sUpdateComment", true);
489
+      this.handleChangeLoading('sUpdateComment', true);
488 490
       var API = this.props.API;
489 491
 
490
-      this.axios(API + "/comments/" + commentId, {
491
-        method: "post",
492
+      this.axios(API + '/comments/' + commentId, {
493
+        method: 'post',
492 494
         data: {
493 495
           content: content
494 496
         },
@@ -504,10 +506,10 @@ var App = function (_Component) {
504 506
           }
505 507
           return it;
506 508
         });
507
-        _this8.props.onUpdateComment("comment");
509
+        _this8.props.onUpdateComment('comment');
508 510
         _this8.setState({ list: list });
509 511
       }).catch(this.errorHandler).finally(function () {
510
-        _this8.handleChangeLoading("sUpdateComment", false);
512
+        _this8.handleChangeLoading('sUpdateComment', false);
511 513
       });
512 514
     }
513 515
     /**
@@ -517,21 +519,21 @@ var App = function (_Component) {
517 519
      */
518 520
 
519 521
   }, {
520
-    key: "sCreateReply",
522
+    key: 'sCreateReply',
521 523
     value: function sCreateReply(data, cb) {
522 524
       var _this9 = this;
523 525
 
524
-      if (!data.content) return this.error(_reactIntlUniversal2.default.get("message.replyNoNull"));
525
-      this.handleChangeLoading("sCreateReply", true);
526
+      if (!data.content) return this.error(_reactIntlUniversal2.default.get('message.replyNoNull'));
527
+      this.handleChangeLoading('sCreateReply', true);
526 528
       var API = this.props.API;
527 529
 
528
-      this.axios(API + "/replies", {
529
-        method: "post",
530
+      this.axios(API + '/replies', {
531
+        method: 'post',
530 532
         data: data,
531 533
         withCredentials: true
532 534
       }).then(function (response) {
533 535
         if (_this9.props.showAlertReply) {
534
-          _message3.default.success(_reactIntlUniversal2.default.get("message.replySuccess"));
536
+          _message3.default.success(_reactIntlUniversal2.default.get('message.replySuccess'));
535 537
         }
536 538
         if ((0, _helper.isFunction)(cb)) cb(response.data);
537 539
         // 将数据写入到 list 中
@@ -552,7 +554,7 @@ var App = function (_Component) {
552 554
         _this9.props.onCommentFail(error.response.status);
553 555
         _this9.errorHandler(error);
554 556
       }).finally(function () {
555
-        _this9.handleChangeLoading("sCreateReply", false);
557
+        _this9.handleChangeLoading('sCreateReply', false);
556 558
       });
557 559
     }
558 560
 
@@ -563,15 +565,15 @@ var App = function (_Component) {
563 565
      */
564 566
 
565 567
   }, {
566
-    key: "sDeleteReply",
568
+    key: 'sDeleteReply',
567 569
     value: function sDeleteReply(replyId, commentId) {
568 570
       var _this10 = this;
569 571
 
570
-      this.handleChangeLoading("sDeleteReply", true);
572
+      this.handleChangeLoading('sDeleteReply', true);
571 573
       var API = this.props.API;
572 574
 
573
-      this.axios(API + "/replies/" + replyId + "?CommentID=" + commentId, {
574
-        method: "delete",
575
+      this.axios(API + '/replies/' + replyId + '?CommentID=' + commentId, {
576
+        method: 'delete',
575 577
         withCredentials: true
576 578
       }).then(function () {
577 579
         var deletedItem = null;
@@ -591,7 +593,7 @@ var App = function (_Component) {
591 593
         _this10.setState({ list: list });
592 594
         _this10.props.onDelete(_constant.COMMENT_TYPE.REPLY, deletedItem);
593 595
       }).catch(this.errorHandler).finally(function () {
594
-        _this10.handleChangeLoading("sDeleteReply", false);
596
+        _this10.handleChangeLoading('sDeleteReply', false);
595 597
       });
596 598
     }
597 599
     /**
@@ -601,7 +603,7 @@ var App = function (_Component) {
601 603
      */
602 604
 
603 605
   }, {
604
-    key: "sUpdateReply",
606
+    key: 'sUpdateReply',
605 607
     value: function sUpdateReply(_ref6) {
606 608
       var _this11 = this;
607 609
 
@@ -610,11 +612,11 @@ var App = function (_Component) {
610 612
           replyId = _ref6.replyId,
611 613
           replyPage = _ref6.replyPage;
612 614
 
613
-      this.handleChangeLoading("sUpdateReply", true);
615
+      this.handleChangeLoading('sUpdateReply', true);
614 616
       var API = this.props.API;
615 617
 
616
-      this.axios(API + "/replies/" + replyId, {
617
-        method: "post",
618
+      this.axios(API + '/replies/' + replyId, {
619
+        method: 'post',
618 620
         data: {
619 621
           comment_id: commentId,
620 622
           content: content
@@ -624,9 +626,9 @@ var App = function (_Component) {
624 626
         for (var i = 1; i <= replyPage; i++) {
625 627
           _this11.sGetReply({ commentId: commentId, page: i });
626 628
         }
627
-        _this11.props.onUpdateComment("reply");
629
+        _this11.props.onUpdateComment('reply');
628 630
       }).catch(this.errorHandler).finally(function () {
629
-        _this11.handleChangeLoading("sUpdateReply", false);
631
+        _this11.handleChangeLoading('sUpdateReply', false);
630 632
       });
631 633
     }
632 634
     /**
@@ -636,19 +638,19 @@ var App = function (_Component) {
636 638
      */
637 639
 
638 640
   }, {
639
-    key: "sCommentFavor",
641
+    key: 'sCommentFavor',
640 642
     value: function sCommentFavor(commentId, favored) {
641 643
       var _this12 = this;
642 644
 
643
-      this.handleChangeLoading("sCommentFavor", true);
645
+      this.handleChangeLoading('sCommentFavor', true);
644 646
       var API = this.props.API;
645 647
 
646
-      this.axios(API + "/comments/" + commentId + "/favor", {
647
-        method: favored ? "delete" : "put",
648
+      this.axios(API + '/comments/' + commentId + '/favor', {
649
+        method: favored ? 'delete' : 'put',
648 650
         withCredentials: true
649 651
       }).then(function (response) {
650 652
         if (_this12.props.showAlertFavor) {
651
-          _message3.default.success(favored ? _reactIntlUniversal2.default.get("message.cancelLickSuccess") : _reactIntlUniversal2.default.get("message.likeSuccess"));
653
+          _message3.default.success(favored ? _reactIntlUniversal2.default.get('message.cancelLickSuccess') : _reactIntlUniversal2.default.get('message.likeSuccess'));
652 654
         }
653 655
         // 更新 list 中的该项数据的 favored
654 656
         var list = _this12.state.list.map(function (item) {
@@ -660,7 +662,7 @@ var App = function (_Component) {
660 662
         });
661 663
         _this12.setState({ list: list });
662 664
       }).catch(this.errorHandler).finally(function () {
663
-        _this12.handleChangeLoading("sCommentFavor", false);
665
+        _this12.handleChangeLoading('sCommentFavor', false);
664 666
       });
665 667
     }
666 668
 
@@ -672,21 +674,21 @@ var App = function (_Component) {
672 674
      */
673 675
 
674 676
   }, {
675
-    key: "sReplyFavor",
677
+    key: 'sReplyFavor',
676 678
     value: function sReplyFavor(replyId, commentId, favored) {
677 679
       var _this13 = this;
678 680
 
679
-      this.handleChangeLoading("sReplyFavor", true);
681
+      this.handleChangeLoading('sReplyFavor', true);
680 682
       var API = this.props.API;
681 683
 
682
-      this.axios(API + "/replies/" + replyId + "/favor", {
683
-        method: favored ? "delete" : "put",
684
+      this.axios(API + '/replies/' + replyId + '/favor', {
685
+        method: favored ? 'delete' : 'put',
684 686
         data: {
685 687
           comment_id: commentId
686 688
         },
687 689
         withCredentials: true
688 690
       }).then(function (response) {
689
-        _message3.default.success(favored ? _reactIntlUniversal2.default.get("message.cancelLickSuccess") : _reactIntlUniversal2.default.get("message.likeSuccess"));
691
+        _message3.default.success(favored ? _reactIntlUniversal2.default.get('message.cancelLickSuccess') : _reactIntlUniversal2.default.get('message.likeSuccess'));
690 692
         // 更新 list 中的该项数据的 favored
691 693
         var list = _this13.state.list.map(function (item) {
692 694
           if (item.id === commentId) {
@@ -705,7 +707,7 @@ var App = function (_Component) {
705 707
         });
706 708
         _this13.setState({ list: list });
707 709
       }).catch(this.errorHandler).finally(function () {
708
-        _this13.handleChangeLoading("sReplyFavor", false);
710
+        _this13.handleChangeLoading('sReplyFavor', false);
709 711
       });
710 712
     }
711 713
 
@@ -714,21 +716,21 @@ var App = function (_Component) {
714 716
      */
715 717
 
716 718
   }, {
717
-    key: "sOssSts",
719
+    key: 'sOssSts',
718 720
     value: function sOssSts() {
719 721
       var _this14 = this;
720 722
 
721
-      this.handleChangeLoading("sOssSts", true);
723
+      this.handleChangeLoading('sOssSts', true);
722 724
       var API = this.props.API;
723 725
 
724
-      this.axios.get(API + "/oss/sts").then(function (response) {
726
+      this.axios.get(API + '/oss/sts').then(function (response) {
725 727
         _this14.setState({ oss: _extends({}, response.data) });
726 728
       }).catch(this.errorHandler).finally(function () {
727
-        _this14.handleChangeLoading("sOssSts", false);
729
+        _this14.handleChangeLoading('sOssSts', false);
728 730
       });
729 731
     }
730 732
   }, {
731
-    key: "render",
733
+    key: 'render',
732 734
     value: function render() {
733 735
       // 添加到 Context 的数据
734 736
       var value = _extends({}, this.state, this.props, {
@@ -750,11 +752,11 @@ var App = function (_Component) {
750 752
         _Comment.CommentContext.Provider,
751 753
         { value: value },
752 754
         _react2.default.createElement(
753
-          "div",
754
-          { className: "comment" },
755
+          'div',
756
+          { className: 'comment' },
755 757
           this.props.showEditor && _react2.default.createElement(_CommentInput2.default, { content: this.props.children }),
756 758
           this.props.showList && _react2.default.createElement(
757
-            "div",
759
+            'div',
758 760
             { style: { marginTop: 20 } },
759 761
             _react2.default.createElement(_CommentList2.default, null)
760 762
           )
@@ -805,9 +807,9 @@ App.propTypes = {
805 807
 
806 808
 App.defaultProps = {
807 809
   businessUserId: 0,
808
-  API: "//api.links123.net/comment/v1",
809
-  emojiAPI: "//api.links123.net/link/v1",
810
-  LOGINLINK: process.env.RUN_MOD === "production" ? "https://passport.links123.com/login" : "http://test.links123.net:5050/login",
810
+  API: '//api.links123.net/comment/v1',
811
+  emojiAPI: '//api.links123.net/link/v1',
812
+  LOGINLINK: process.env.RUN_MOD === 'production' ? 'https://passport.links123.com/login' : 'http://test.links123.net:5050/login',
811 813
   showList: true,
812 814
   showEditor: true,
813 815
   showAlertComment: false,
@@ -815,7 +817,7 @@ App.defaultProps = {
815 817
   showAlertFavor: false,
816 818
   showError: true,
817 819
   showEdit: false,
818
-  pageType: "more",
820
+  pageType: 'more',
819 821
   limit: _constant.LIMIT,
820 822
   onGetMoreBtnClick: function onGetMoreBtnClick() {},
821 823
   onPageChange: function onPageChange(page) {},

+ 1
- 1
lib/App.js.map
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 172
- 0
lib/components/AudioPlayer/index.js Ver arquivo

@@ -0,0 +1,172 @@
1
+'use strict';
2
+
3
+Object.defineProperty(exports, "__esModule", {
4
+  value: true
5
+});
6
+
7
+var _slider = require('antd/es/slider');
8
+
9
+var _slider2 = _interopRequireDefault(_slider);
10
+
11
+var _icon = require('antd/es/icon');
12
+
13
+var _icon2 = _interopRequireDefault(_icon);
14
+
15
+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; }; }();
16
+
17
+require('antd/es/slider/style');
18
+
19
+require('antd/es/icon/style');
20
+
21
+var _react = require('react');
22
+
23
+var _react2 = _interopRequireDefault(_react);
24
+
25
+var _dayjs = require('dayjs');
26
+
27
+var _dayjs2 = _interopRequireDefault(_dayjs);
28
+
29
+var _duration = require('dayjs/plugin/duration');
30
+
31
+var _duration2 = _interopRequireDefault(_duration);
32
+
33
+var _utc = require('dayjs/plugin/utc');
34
+
35
+var _utc2 = _interopRequireDefault(_utc);
36
+
37
+require('./index.less');
38
+
39
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40
+
41
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42
+
43
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
44
+
45
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
46
+
47
+_dayjs2.default.extend(_duration2.default);
48
+_dayjs2.default.extend(_utc2.default);
49
+
50
+var AudioPlayer = function (_React$Component) {
51
+  _inherits(AudioPlayer, _React$Component);
52
+
53
+  function AudioPlayer(props) {
54
+    _classCallCheck(this, AudioPlayer);
55
+
56
+    var _this = _possibleConstructorReturn(this, (AudioPlayer.__proto__ || Object.getPrototypeOf(AudioPlayer)).call(this, props));
57
+
58
+    _this.state = {
59
+      duration: 0,
60
+      currentDuration: 0,
61
+      isPlaying: false
62
+    };
63
+    return _this;
64
+  }
65
+
66
+  _createClass(AudioPlayer, [{
67
+    key: 'componentDidMount',
68
+    value: function componentDidMount() {
69
+      var _this2 = this;
70
+
71
+      if (this.player) {
72
+        var src = this.props.src;
73
+
74
+        this.player.oncanplay = function (event) {
75
+          return _this2.setState({ duration: event.target.duration });
76
+        };
77
+        this.player.onended = function () {
78
+          return _this2.setState({ isPlaying: false, currentDuration: 0 });
79
+        };
80
+        this.player.onpause = function () {
81
+          return _this2.setState({ isPlaying: false });
82
+        };
83
+        this.player.onplay = function () {
84
+          return _this2.setState({ isPlaying: true });
85
+        };
86
+        this.player.ontimeupdate = function (event) {
87
+          return _this2.setState({ currentDuration: event.target.currentTime });
88
+        };
89
+        this.player.src = src;
90
+      }
91
+    }
92
+  }, {
93
+    key: 'componentDidUpdate',
94
+    value: function componentDidUpdate(prevProps) {
95
+      var _this3 = this;
96
+
97
+      if (this.props.src !== prevProps.src) {
98
+        this.player.oncanplay = function (event) {
99
+          return _this3.setState({ duration: event.target.duration });
100
+        };
101
+        this.player.onended = function () {
102
+          return _this3.setState({ isPlaying: false, currentDuration: 0 });
103
+        };
104
+        this.player.onpause = function () {
105
+          return _this3.setState({ isPlaying: false });
106
+        };
107
+        this.player.onplay = function () {
108
+          return _this3.setState({ isPlaying: true });
109
+        };
110
+        this.player.ontimeupdate = function (event) {
111
+          return _this3.setState({ currentDuration: event.target.currentTime });
112
+        };
113
+        this.player.src = this.props.src;
114
+      }
115
+    }
116
+  }, {
117
+    key: 'render',
118
+    value: function render() {
119
+      var _this4 = this;
120
+
121
+      var _state = this.state,
122
+          currentDuration = _state.currentDuration,
123
+          isPlaying = _state.isPlaying,
124
+          duration = _state.duration;
125
+
126
+      return _react2.default.createElement(
127
+        'div',
128
+        { className: 'comment-item-speak-audio-container' },
129
+        _react2.default.createElement('audio', {
130
+          ref: function ref(_ref) {
131
+            _this4.player = _ref;
132
+          },
133
+          style: { display: 'none' }
134
+        }),
135
+        _react2.default.createElement(
136
+          'span',
137
+          {
138
+            className: 'icon',
139
+            onClick: function onClick() {
140
+              return _this4.player && (isPlaying ? _this4.player.pause() : _this4.player.play());
141
+            }
142
+          },
143
+          isPlaying ? _react2.default.createElement(_icon2.default, { className: 'pause', type: 'pause' }) : _react2.default.createElement('i', { className: 'schedule schedule-icon_image_audio' })
144
+        ),
145
+        _react2.default.createElement(_slider2.default, {
146
+          step: 0.001,
147
+          className: 'slider',
148
+          tooltipVisible: false,
149
+          value: currentDuration,
150
+          max: duration,
151
+          onChange: function onChange(value) {
152
+            if (_this4.player) {
153
+              _this4.player.currentTime = value;
154
+            }
155
+          }
156
+        }),
157
+        _react2.default.createElement(
158
+          'span',
159
+          { className: 'time' },
160
+          _dayjs2.default.utc(_dayjs2.default.duration(currentDuration, 'seconds').asMilliseconds()).format('mm:ss'),
161
+          '/',
162
+          _dayjs2.default.utc(_dayjs2.default.duration(duration, 'seconds').asMilliseconds()).format('mm:ss')
163
+        )
164
+      );
165
+    }
166
+  }]);
167
+
168
+  return AudioPlayer;
169
+}(_react2.default.Component);
170
+
171
+exports.default = AudioPlayer;
172
+//# sourceMappingURL=index.js.map

+ 1
- 0
lib/components/AudioPlayer/index.js.map
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 60
- 0
lib/components/AudioPlayer/index.less Ver arquivo

@@ -0,0 +1,60 @@
1
+.comment-item-speak-audio-container {
2
+  background-color: #f5f5f5;
3
+  border: 1px solid rgba(210, 210, 210, 1);
4
+  border-radius: 4px;
5
+  display: flex;
6
+  align-items: center;
7
+  height: 100%;
8
+
9
+  .icon {
10
+    cursor: pointer;
11
+    width: 28px;
12
+    height: 28px;
13
+    line-height: 28px;
14
+    text-align: center;
15
+    border-radius: 14px;
16
+    background-color: #fff;
17
+    color: #71c135;
18
+    margin-left: 12px;
19
+    font-size: 14px;
20
+  }
21
+
22
+  .slider {
23
+    margin: 0 0 0 16px;
24
+    width: 195px;
25
+
26
+    :global {
27
+      .ant-slider-rail {
28
+        background-color: #dfdfdf;
29
+      }
30
+    }
31
+  }
32
+
33
+  .time {
34
+    margin-left: 14px;
35
+    color: #848484;
36
+    font-size: 12px;
37
+  }
38
+}
39
+
40
+@media screen and (max-width: 616px) and (min-width: 449px) {
41
+  .comment-item-speak-audio-container {
42
+    .slider {
43
+      width: 195px;
44
+    }
45
+  }
46
+}
47
+@media screen and (max-width: 449px) and (min-width: 365px) {
48
+  .comment-item-speak-audio-container {
49
+    .slider {
50
+      width: 114px;
51
+    }
52
+  }
53
+}
54
+@media screen and (max-width: 365px) {
55
+  .comment-item-speak-audio-container {
56
+    .slider {
57
+      width: 60px;
58
+    }
59
+  }
60
+}

+ 12
- 0
lib/components/CommentList/index.css Ver arquivo

@@ -17,3 +17,15 @@
17 17
 .comment-list-pagination {
18 18
   text-align: center;
19 19
 }
20
+
21
+.comment-list-filter-speak {
22
+  margin-left: 20px;
23
+  font-size: 14px;
24
+  color: rgba(93, 93, 93, 0.65);
25
+}
26
+
27
+@media screen and (max-width: 365px) {
28
+  .comment-list-filter-speak {
29
+    float: right;
30
+  }
31
+}

+ 36
- 5
lib/components/CommentList/index.js Ver arquivo

@@ -8,6 +8,10 @@ var _spin = require("antd/es/spin");
8 8
 
9 9
 var _spin2 = _interopRequireDefault(_spin);
10 10
 
11
+var _checkbox = require("antd/es/checkbox");
12
+
13
+var _checkbox2 = _interopRequireDefault(_checkbox);
14
+
11 15
 var _pagination = require("antd/es/pagination");
12 16
 
13 17
 var _pagination2 = _interopRequireDefault(_pagination);
@@ -16,6 +20,8 @@ var _createClass = function () { function defineProperties(target, props) { for
16 20
 
17 21
 require("antd/es/spin/style");
18 22
 
23
+require("antd/es/checkbox/style");
24
+
19 25
 require("antd/es/pagination/style");
20 26
 
21 27
 var _react = require("react");
@@ -52,7 +58,9 @@ var CommentList = function (_Component) {
52 58
 
53 59
     var _this = _possibleConstructorReturn(this, (CommentList.__proto__ || Object.getPrototypeOf(CommentList)).call(this, props));
54 60
 
55
-    _this.state = {};
61
+    _this.state = {
62
+      filterSpeak: 0
63
+    };
56 64
     return _this;
57 65
   }
58 66
 
@@ -74,6 +82,7 @@ var CommentList = function (_Component) {
74 82
           sGetComment = _props$app.sGetComment,
75 83
           onPageChange = _props$app.onPageChange,
76 84
           onGetMoreBtnClick = _props$app.onGetMoreBtnClick;
85
+      var filterSpeak = this.state.filterSpeak;
77 86
 
78 87
       if (pageType === "slice") {
79 88
         // 截断多余评论,通过点击查看更多跳转
@@ -93,7 +102,7 @@ var CommentList = function (_Component) {
93 102
             {
94 103
               className: "comment-list-show-more",
95 104
               onClick: function onClick() {
96
-                sGetComment({ page: page + 1 });
105
+                sGetComment({ page: page + 1, filterSpeak: filterSpeak });
97 106
                 onPageChange(page + 1);
98 107
               }
99 108
             },
@@ -115,7 +124,7 @@ var CommentList = function (_Component) {
115 124
             current: page,
116 125
             total: total,
117 126
             onChange: function onChange(p) {
118
-              sGetComment({ page: p });
127
+              sGetComment({ page: p, filterSpeak: filterSpeak });
119 128
               onPageChange(p);
120 129
             }
121 130
           })
@@ -125,10 +134,15 @@ var CommentList = function (_Component) {
125 134
   }, {
126 135
     key: "render",
127 136
     value: function render() {
137
+      var _this2 = this;
138
+
128 139
       var _props$app2 = this.props.app,
129 140
           list = _props$app2.list,
130 141
           total = _props$app2.total,
131
-          loading = _props$app2.loading;
142
+          loading = _props$app2.loading,
143
+          isSpeak = _props$app2.isSpeak,
144
+          sGetComment = _props$app2.sGetComment,
145
+          onPageChange = _props$app2.onPageChange;
132 146
 
133 147
 
134 148
       var spinning = Boolean(loading.sGetComment || loading.sCommentFavor || loading.sReplyFavor);
@@ -141,7 +155,24 @@ var CommentList = function (_Component) {
141 155
           _react2.default.createElement(
142 156
             "div",
143 157
             null,
144
-            _reactIntlUniversal2.default.get("comment.totalComment", { total: total })
158
+            _reactIntlUniversal2.default.get("comment.totalComment", { total: total }),
159
+            isSpeak && _react2.default.createElement(
160
+              _checkbox2.default,
161
+              {
162
+                className: "comment-list-filter-speak",
163
+                onChange: function onChange(e) {
164
+                  _this2.setState({
165
+                    filterSpeak: e.target.checked ? 1 : 0
166
+                  });
167
+                  sGetComment({
168
+                    page: 1,
169
+                    filterSpeak: e.target.checked ? 1 : 0
170
+                  });
171
+                  onPageChange(1);
172
+                }
173
+              },
174
+              _reactIntlUniversal2.default.get("comment.filterSpeak")
175
+            )
145 176
           ),
146 177
           list.map(function (item) {
147 178
             return _react2.default.createElement(_CommentBox2.default, {

+ 1
- 1
lib/components/CommentList/index.js.map
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 28
- 1
lib/components/ContentItem/index.css Ver arquivo

@@ -33,6 +33,21 @@
33 33
   word-break: break-all;
34 34
 }
35 35
 
36
+.comment-item-speak {
37
+  margin-top: 4px;
38
+}
39
+
40
+.comment-item-speak-message {
41
+  font-size: 14px;
42
+  color: #71c135;
43
+}
44
+
45
+.comment-item-speak-audio-wrapper {
46
+  margin-top: 8px;
47
+  width: 350px;
48
+  height: 44px;
49
+}
50
+
36 51
 .comment-item-bottom {
37 52
   display: flex;
38 53
   justify-content: flex-end;
@@ -124,7 +139,7 @@
124 139
   height: 0;
125 140
   padding-bottom: 100%;
126 141
   border-radius: 5px;
127
-  cursor: url("//links-comment.oss-cn-beijing.aliyuncs.com/comment/20180928/QPI84fxmD.undefined"),
142
+  cursor: url('//links-comment.oss-cn-beijing.aliyuncs.com/comment/20180928/QPI84fxmD.undefined'),
128 143
     auto;
129 144
 }
130 145
 
@@ -156,6 +171,10 @@
156 171
     width: 85%;
157 172
     margin-left: 10px;
158 173
   }
174
+
175
+  .comment-item-speak-audio-wrapper {
176
+    width: 350px;
177
+  }
159 178
 }
160 179
 
161 180
 @media screen and (max-width: 449px) and (min-width: 365px) {
@@ -164,6 +183,10 @@
164 183
     width: 80%;
165 184
     margin-left: 10px;
166 185
   }
186
+
187
+  .comment-item-speak-audio-wrapper {
188
+    width: 266px;
189
+  }
167 190
 }
168 191
 
169 192
 @media screen and (max-width: 365px) {
@@ -172,6 +195,10 @@
172 195
     width: 75%;
173 196
     margin-left: 10px;
174 197
   }
198
+
199
+  .comment-item-speak-audio-wrapper {
200
+    width: 218px;
201
+  }
175 202
 }
176 203
 
177 204
 @media (max-width: 575px) {

+ 21
- 1
lib/components/ContentItem/index.js Ver arquivo

@@ -80,6 +80,10 @@ var _ImagePreviewer = require("../ImagePreviewer/ImagePreviewer");
80 80
 
81 81
 var _ImagePreviewer2 = _interopRequireDefault(_ImagePreviewer);
82 82
 
83
+var _AudioPlayer = require("../AudioPlayer");
84
+
85
+var _AudioPlayer2 = _interopRequireDefault(_AudioPlayer);
86
+
83 87
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
84 88
 
85 89
 function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
@@ -197,6 +201,8 @@ var CommentItem = function (_Component) {
197 201
           app = _props.app,
198 202
           user_id = _props.user_id,
199 203
           page = _props.page;
204
+      var medias = content.medias,
205
+          isSpeak = content.is_speak;
200 206
       var _props$app = this.props.app,
201 207
           locale = _props$app.locale,
202 208
           showHoverCard = _props$app.showHoverCard,
@@ -295,6 +301,20 @@ var CommentItem = function (_Component) {
295 301
               __html: (0, _helper.renderContent)(this.renderTextWithReply(newContent, content))
296 302
             }
297 303
           }),
304
+          isSpeak && _react2.default.createElement(
305
+            "div",
306
+            { className: "comment-item-speak" },
307
+            _react2.default.createElement(
308
+              "span",
309
+              { className: "comment-item-speak-message" },
310
+              "[\u8DDF\u8BFB\u6D88\u606F]"
311
+            ),
312
+            _react2.default.createElement(
313
+              "div",
314
+              { className: "comment-item-speak-audio-wrapper" },
315
+              _react2.default.createElement(_AudioPlayer2.default, { src: medias && medias[0] && medias[0].url })
316
+            )
317
+          ),
298 318
           // image为空时不渲染comment-item-image
299 319
           imageList.length > 0 && imageList[0] !== "" && _react2.default.createElement(
300 320
             "div",
@@ -351,7 +371,7 @@ var CommentItem = function (_Component) {
351 371
                 showReply ? _react2.default.createElement(_icon2.default, { type: "up" }) : _react2.default.createElement(_icon2.default, { type: "down" })
352 372
               )
353 373
             ) : null,
354
-            showEdit && app.userId === content.user_id && _react2.default.createElement("i", {
374
+            showEdit && !isSpeak && app.userId === content.user_id && _react2.default.createElement("i", {
355 375
               className: "comment-item-edit",
356 376
               onClick: function onClick() {
357 377
                 return _this2.props.app.handleEdit({

+ 1
- 1
lib/components/ContentItem/index.js.map
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 1
- 0
lib/lang/en-US.js Ver arquivo

@@ -16,6 +16,7 @@ var USdata = {
16 16
   "comment.totalComment": "Total {total, plural, =1 {one comment} other {# comments}}",
17 17
   "comment.reply": "Reply",
18 18
   "comment.moreComment": "More comments",
19
+  "comment.filterSpeak": "Show imitations only",
19 20
 
20 21
   "reply.totalReply": "Total {total, plural, =1 {one reply} other {# replies}}",
21 22
   "reply.moreReply": "More replies",

+ 1
- 1
lib/lang/en-US.js.map Ver arquivo

@@ -1 +1 @@
1
-{"version":3,"sources":["../../src/lang/en-US.js"],"names":["USdata"],"mappings":";;;;;AAAA,IAAMA,SAAS;AACb,2BAAyB,uBADZ;AAEb,wBAAsB,eAFT;AAGb,sBAAoB,2BAHP;AAIb,sBAAoB,MAJP;AAKb,sBAAoB,iBALP;AAMb,wBAAsB,iCANT;AAOb,sBAAoB,QAPP;;AASb,qBAAmB,SATN;AAUb,0BACE,4DAXW;AAYb,mBAAiB,OAZJ;AAab,yBAAuB,eAbV;;AAeb,sBAAoB,yDAfP;AAgBb,qBAAmB,cAhBN;AAiBb,oBAAkB,cAjBL;;AAmBb,sBAAoB,MAnBP;AAoBb,0BAAwB,kBApBX;;AAsBb,sBAAoB,SAtBP;AAuBb,mBAAiB,SAvBJ;AAwBb,uBAAqB,QAxBR;AAyBb,uBAAqB,QAzBR;;AA2Bb,2BAAyB,kBA3BZ;AA4Bb,wBAAsB,cA5BT;AA6Bb,qBAAmB,kBA7BN;AA8Bb,qBAAmB,eA9BN;AA+Bb,yBAAuB,kBA/BV;AAgCb,0BAAwB,YAhCX;AAiCb,+BAA6B,SAjChB;AAkCb,yBAAuB;AAlCV,CAAf;;kBAqCeA,M","file":"en-US.js","sourcesContent":["const USdata = {\n  \"editor.alreadyEntered\": \"{count} words entered\",\n  \"editor.placeholder\": \"Say something\",\n  \"editor.maxLength\": \"Maximum {maxLength} words\",\n  \"editor.SubmitBtn\": \"Send\",\n  \"editor.uploadTip\": \"Upload pictures\",\n  \"editor.uploadCount\": \"(You could upload {count} more)\",\n  \"editor.uploadBtn\": \"Upload\",\n\n  \"comment.tourist\": \"Visitor\",\n  \"comment.totalComment\":\n    \"Total {total, plural, =1 {one comment} other {# comments}}\",\n  \"comment.reply\": \"Reply\",\n  \"comment.moreComment\": \"More comments\",\n\n  \"reply.totalReply\": \"Total {total, plural, =1 {one reply} other {# replies}}\",\n  \"reply.moreReply\": \"More replies\",\n  \"reply.collapse\": \"Fold replies\",\n\n  \"picture.collapse\": \"Fold\",\n  \"picture.viewOriginal\": \"See the original\",\n\n  \"popConfirm.title\": \"Delete?\",\n  \"popConfirm.ok\": \"Confirm\",\n  \"popConfirm.cancel\": \"Cancel\",\n  \"popConfirm.delete\": \"Delete\",\n\n  \"message.noMoreComment\": \"No more comments\",\n  \"message.noMoreData\": \"No more data\",\n  \"message.notNull\": \"It's still empty\",\n  \"message.success\": \"Comments sent\",\n  \"message.replyNoNull\": \"It's still empty\",\n  \"message.replySuccess\": \"Reply sent\",\n  \"message.cancelLickSuccess\": \"Unliked\",\n  \"message.likeSuccess\": \"Liked\"\n};\n\nexport default USdata;\n"]}
1
+{"version":3,"sources":["../../src/lang/en-US.js"],"names":["USdata"],"mappings":";;;;;AAAA,IAAMA,SAAS;AACb,2BAAyB,uBADZ;AAEb,wBAAsB,eAFT;AAGb,sBAAoB,2BAHP;AAIb,sBAAoB,MAJP;AAKb,sBAAoB,iBALP;AAMb,wBAAsB,iCANT;AAOb,sBAAoB,QAPP;;AASb,qBAAmB,SATN;AAUb,0BACE,4DAXW;AAYb,mBAAiB,OAZJ;AAab,yBAAuB,eAbV;AAcb,yBAAuB,sBAdV;;AAgBb,sBAAoB,yDAhBP;AAiBb,qBAAmB,cAjBN;AAkBb,oBAAkB,cAlBL;;AAoBb,sBAAoB,MApBP;AAqBb,0BAAwB,kBArBX;;AAuBb,sBAAoB,SAvBP;AAwBb,mBAAiB,SAxBJ;AAyBb,uBAAqB,QAzBR;AA0Bb,uBAAqB,QA1BR;;AA4Bb,2BAAyB,kBA5BZ;AA6Bb,wBAAsB,cA7BT;AA8Bb,qBAAmB,kBA9BN;AA+Bb,qBAAmB,eA/BN;AAgCb,yBAAuB,kBAhCV;AAiCb,0BAAwB,YAjCX;AAkCb,+BAA6B,SAlChB;AAmCb,yBAAuB;AAnCV,CAAf;;kBAsCeA,M","file":"en-US.js","sourcesContent":["const USdata = {\n  \"editor.alreadyEntered\": \"{count} words entered\",\n  \"editor.placeholder\": \"Say something\",\n  \"editor.maxLength\": \"Maximum {maxLength} words\",\n  \"editor.SubmitBtn\": \"Send\",\n  \"editor.uploadTip\": \"Upload pictures\",\n  \"editor.uploadCount\": \"(You could upload {count} more)\",\n  \"editor.uploadBtn\": \"Upload\",\n\n  \"comment.tourist\": \"Visitor\",\n  \"comment.totalComment\":\n    \"Total {total, plural, =1 {one comment} other {# comments}}\",\n  \"comment.reply\": \"Reply\",\n  \"comment.moreComment\": \"More comments\",\n  \"comment.filterSpeak\": \"Show imitations only\",\n\n  \"reply.totalReply\": \"Total {total, plural, =1 {one reply} other {# replies}}\",\n  \"reply.moreReply\": \"More replies\",\n  \"reply.collapse\": \"Fold replies\",\n\n  \"picture.collapse\": \"Fold\",\n  \"picture.viewOriginal\": \"See the original\",\n\n  \"popConfirm.title\": \"Delete?\",\n  \"popConfirm.ok\": \"Confirm\",\n  \"popConfirm.cancel\": \"Cancel\",\n  \"popConfirm.delete\": \"Delete\",\n\n  \"message.noMoreComment\": \"No more comments\",\n  \"message.noMoreData\": \"No more data\",\n  \"message.notNull\": \"It's still empty\",\n  \"message.success\": \"Comments sent\",\n  \"message.replyNoNull\": \"It's still empty\",\n  \"message.replySuccess\": \"Reply sent\",\n  \"message.cancelLickSuccess\": \"Unliked\",\n  \"message.likeSuccess\": \"Liked\"\n};\n\nexport default USdata;\n"]}

+ 1
- 0
lib/lang/zh-CN.js Ver arquivo

@@ -16,6 +16,7 @@ var CNdata = {
16 16
   "comment.totalComment": "共{total}条评论",
17 17
   "comment.reply": "回复",
18 18
   "comment.moreComment": "更多评论",
19
+  "comment.filterSpeak": "只显示跟读",
19 20
 
20 21
   "reply.totalReply": "共{total}条回复",
21 22
   "reply.moreReply": "更多回复",

+ 1
- 1
lib/lang/zh-CN.js.map Ver arquivo

@@ -1 +1 @@
1
-{"version":3,"sources":["../../src/lang/zh-CN.js"],"names":["CNdata"],"mappings":";;;;;AAAA,IAAMA,SAAS;AACb,2BAAyB,yBADZ;AAEb,wBAAsB,UAFT;AAGb,sBAAoB,iBAHP;AAIb,sBAAoB,IAJP;AAKb,sBAAoB,MALP;AAMb,wBAAsB,mBANT;AAOb,sBAAoB,IAPP;;AASb,qBAAmB,IATN;AAUb,0BAAwB,aAVX;AAWb,mBAAiB,IAXJ;AAYb,yBAAuB,MAZV;;AAcb,sBAAoB,aAdP;AAeb,qBAAmB,MAfN;AAgBb,oBAAkB,MAhBL;;AAkBb,sBAAoB,IAlBP;AAmBb,0BAAwB,MAnBX;;AAqBb,sBAAoB,QArBP;AAsBb,mBAAiB,IAtBJ;AAuBb,uBAAqB,IAvBR;AAwBb,uBAAqB,IAxBR;;AA0Bb,2BAAyB,SA1BZ;AA2Bb,wBAAsB,UA3BT;AA4Bb,qBAAmB,OA5BN;AA6Bb,qBAAmB,QA7BN;AA8Bb,yBAAuB,OA9BV;AA+Bb,0BAAwB,QA/BX;AAgCb,+BAA6B,QAhChB;AAiCb,yBAAuB;AAjCV,CAAf;;kBAoCeA,M","file":"zh-CN.js","sourcesContent":["const CNdata = {\n  \"editor.alreadyEntered\": \"已输入{count}/{maxLength}字\",\n  \"editor.placeholder\": \"说点什么吧...\",\n  \"editor.maxLength\": \"字数上限{maxLength}\",\n  \"editor.SubmitBtn\": \"发送\",\n  \"editor.uploadTip\": \"上传图片\",\n  \"editor.uploadCount\": \"(您还能上传{count}张图片)\",\n  \"editor.uploadBtn\": \"上传\",\n\n  \"comment.tourist\": \"游客\",\n  \"comment.totalComment\": \"共{total}条评论\",\n  \"comment.reply\": \"回复\",\n  \"comment.moreComment\": \"更多评论\",\n\n  \"reply.totalReply\": \"共{total}条回复\",\n  \"reply.moreReply\": \"更多回复\",\n  \"reply.collapse\": \"收起回复\",\n\n  \"picture.collapse\": \"收起\",\n  \"picture.viewOriginal\": \"查看原图\",\n\n  \"popConfirm.title\": \"确定要删除吗\",\n  \"popConfirm.ok\": \"确定\",\n  \"popConfirm.cancel\": \"取消\",\n  \"popConfirm.delete\": \"删除\",\n\n  \"message.noMoreComment\": \"没有更多评论了\",\n  \"message.noMoreData\": \"没有更多数据了!\",\n  \"message.notNull\": \"没写内容呢\",\n  \"message.success\": \"评论已发送!\",\n  \"message.replyNoNull\": \"没写内容呢\",\n  \"message.replySuccess\": \"回复已发送!\",\n  \"message.cancelLickSuccess\": \"已取消点赞!\",\n  \"message.likeSuccess\": \"已赞!\"\n};\n\nexport default CNdata;\n"]}
1
+{"version":3,"sources":["../../src/lang/zh-CN.js"],"names":["CNdata"],"mappings":";;;;;AAAA,IAAMA,SAAS;AACb,2BAAyB,yBADZ;AAEb,wBAAsB,UAFT;AAGb,sBAAoB,iBAHP;AAIb,sBAAoB,IAJP;AAKb,sBAAoB,MALP;AAMb,wBAAsB,mBANT;AAOb,sBAAoB,IAPP;;AASb,qBAAmB,IATN;AAUb,0BAAwB,aAVX;AAWb,mBAAiB,IAXJ;AAYb,yBAAuB,MAZV;AAab,yBAAuB,OAbV;;AAeb,sBAAoB,aAfP;AAgBb,qBAAmB,MAhBN;AAiBb,oBAAkB,MAjBL;;AAmBb,sBAAoB,IAnBP;AAoBb,0BAAwB,MApBX;;AAsBb,sBAAoB,QAtBP;AAuBb,mBAAiB,IAvBJ;AAwBb,uBAAqB,IAxBR;AAyBb,uBAAqB,IAzBR;;AA2Bb,2BAAyB,SA3BZ;AA4Bb,wBAAsB,UA5BT;AA6Bb,qBAAmB,OA7BN;AA8Bb,qBAAmB,QA9BN;AA+Bb,yBAAuB,OA/BV;AAgCb,0BAAwB,QAhCX;AAiCb,+BAA6B,QAjChB;AAkCb,yBAAuB;AAlCV,CAAf;;kBAqCeA,M","file":"zh-CN.js","sourcesContent":["const CNdata = {\n  \"editor.alreadyEntered\": \"已输入{count}/{maxLength}字\",\n  \"editor.placeholder\": \"说点什么吧...\",\n  \"editor.maxLength\": \"字数上限{maxLength}\",\n  \"editor.SubmitBtn\": \"发送\",\n  \"editor.uploadTip\": \"上传图片\",\n  \"editor.uploadCount\": \"(您还能上传{count}张图片)\",\n  \"editor.uploadBtn\": \"上传\",\n\n  \"comment.tourist\": \"游客\",\n  \"comment.totalComment\": \"共{total}条评论\",\n  \"comment.reply\": \"回复\",\n  \"comment.moreComment\": \"更多评论\",\n  \"comment.filterSpeak\": \"只显示跟读\",\n\n  \"reply.totalReply\": \"共{total}条回复\",\n  \"reply.moreReply\": \"更多回复\",\n  \"reply.collapse\": \"收起回复\",\n\n  \"picture.collapse\": \"收起\",\n  \"picture.viewOriginal\": \"查看原图\",\n\n  \"popConfirm.title\": \"确定要删除吗\",\n  \"popConfirm.ok\": \"确定\",\n  \"popConfirm.cancel\": \"取消\",\n  \"popConfirm.delete\": \"删除\",\n\n  \"message.noMoreComment\": \"没有更多评论了\",\n  \"message.noMoreData\": \"没有更多数据了!\",\n  \"message.notNull\": \"没写内容呢\",\n  \"message.success\": \"评论已发送!\",\n  \"message.replyNoNull\": \"没写内容呢\",\n  \"message.replySuccess\": \"回复已发送!\",\n  \"message.cancelLickSuccess\": \"已取消点赞!\",\n  \"message.likeSuccess\": \"已赞!\"\n};\n\nexport default CNdata;\n"]}

+ 4
- 4
lib/version.json Ver arquivo

@@ -1,8 +1,8 @@
1 1
 {
2 2
     "name":       "comment",
3
-    "buildDate":  1582467062540,
3
+    "buildDate":  1585374331505,
4 4
     "version":    "1.0.4",
5
-    "numCommits": 204,
6
-    "hash":       "016964f",
7
-    "dirty":      true
5
+    "numCommits": 209,
6
+    "hash":       "daff054",
7
+    "dirty":      false
8 8
 }

+ 2
- 2
src/App.js Ver arquivo

@@ -190,13 +190,13 @@ class App extends Component {
190 190
   /**
191 191
    * 获取评论列表
192 192
    */
193
-  sGetComment({ page = 1 } = {}) {
193
+  sGetComment({ page = 1, filterSpeak = 0 } = {}) {
194 194
     const { pageType } = this.props;
195 195
     this.handleChangeLoading("sGetComment", true);
196 196
     const { API, type, businessId, limit } = this.props;
197 197
     this.axios
198 198
       .get(
199
-        `${API}/comments?type=${type}&business_id=${businessId}&page=${page}&limit=${limit}`
199
+        `${API}/comments?type=${type}&business_id=${businessId}&is_speak=${filterSpeak}&page=${page}&limit=${limit}`
200 200
       )
201 201
       .then(response => {
202 202
         const { list, page, total } = response.data;

+ 100
- 0
src/components/AudioPlayer/index.js Ver arquivo

@@ -0,0 +1,100 @@
1
+import React from "react";
2
+import { Slider, Icon } from "antd";
3
+import dayjs from "dayjs";
4
+import durationPlugin from "dayjs/plugin/duration";
5
+import utcPlugin from "dayjs/plugin/utc";
6
+import "./index.less";
7
+
8
+dayjs.extend(durationPlugin);
9
+dayjs.extend(utcPlugin);
10
+
11
+class AudioPlayer extends React.Component {
12
+  constructor(props) {
13
+    super(props);
14
+    this.state = {
15
+      duration: 0,
16
+      currentDuration: 0,
17
+      isPlaying: false
18
+    };
19
+  }
20
+
21
+  componentDidMount() {
22
+    if (this.player) {
23
+      const { src } = this.props;
24
+      this.player.oncanplay = event =>
25
+        this.setState({ duration: event.target.duration });
26
+      this.player.onended = () =>
27
+        this.setState({ isPlaying: false, currentDuration: 0 });
28
+      this.player.onpause = () => this.setState({ isPlaying: false });
29
+      this.player.onplay = () => this.setState({ isPlaying: true });
30
+      this.player.ontimeupdate = event =>
31
+        this.setState({ currentDuration: event.target.currentTime });
32
+      this.player.src = src;
33
+    }
34
+  }
35
+
36
+  componentDidUpdate(prevProps) {
37
+    if (this.props.src !== prevProps.src) {
38
+      this.player.oncanplay = event =>
39
+        this.setState({ duration: event.target.duration });
40
+      this.player.onended = () =>
41
+        this.setState({ isPlaying: false, currentDuration: 0 });
42
+      this.player.onpause = () => this.setState({ isPlaying: false });
43
+      this.player.onplay = () => this.setState({ isPlaying: true });
44
+      this.player.ontimeupdate = event =>
45
+        this.setState({ currentDuration: event.target.currentTime });
46
+      this.player.src = this.props.src;
47
+    }
48
+  }
49
+
50
+  render() {
51
+    const { currentDuration, isPlaying, duration } = this.state;
52
+    return (
53
+      <div className="comment-item-speak-audio-container">
54
+        {/* eslint-disable-next-line jsx-a11y/media-has-caption */}
55
+        <audio
56
+          ref={ref => {
57
+            this.player = ref;
58
+          }}
59
+          style={{ display: "none" }}
60
+        />
61
+        <span
62
+          className="icon"
63
+          onClick={() =>
64
+            this.player &&
65
+            (isPlaying ? this.player.pause() : this.player.play())
66
+          }
67
+        >
68
+          {isPlaying ? (
69
+            <Icon className="pause" type="pause" />
70
+          ) : (
71
+            <i className="schedule schedule-icon_image_audio" />
72
+          )}
73
+        </span>
74
+        <Slider
75
+          step={0.001}
76
+          className="slider"
77
+          tooltipVisible={false}
78
+          value={currentDuration}
79
+          max={duration}
80
+          onChange={value => {
81
+            if (this.player) {
82
+              this.player.currentTime = value;
83
+            }
84
+          }}
85
+        />
86
+        <span className="time">
87
+          {dayjs
88
+            .utc(dayjs.duration(currentDuration, "seconds").asMilliseconds())
89
+            .format("mm:ss")}
90
+          /
91
+          {dayjs
92
+            .utc(dayjs.duration(duration, "seconds").asMilliseconds())
93
+            .format("mm:ss")}
94
+        </span>
95
+      </div>
96
+    );
97
+  }
98
+}
99
+
100
+export default AudioPlayer;

+ 60
- 0
src/components/AudioPlayer/index.less Ver arquivo

@@ -0,0 +1,60 @@
1
+.comment-item-speak-audio-container {
2
+  background-color: #f5f5f5;
3
+  border: 1px solid rgba(210, 210, 210, 1);
4
+  border-radius: 4px;
5
+  display: flex;
6
+  align-items: center;
7
+  height: 100%;
8
+
9
+  .icon {
10
+    cursor: pointer;
11
+    width: 28px;
12
+    height: 28px;
13
+    line-height: 28px;
14
+    text-align: center;
15
+    border-radius: 14px;
16
+    background-color: #fff;
17
+    color: #71c135;
18
+    margin-left: 12px;
19
+    font-size: 14px;
20
+  }
21
+
22
+  .slider {
23
+    margin: 0 0 0 16px;
24
+    width: 195px;
25
+
26
+    :global {
27
+      .ant-slider-rail {
28
+        background-color: #dfdfdf;
29
+      }
30
+    }
31
+  }
32
+
33
+  .time {
34
+    margin-left: 14px;
35
+    color: #848484;
36
+    font-size: 12px;
37
+  }
38
+}
39
+
40
+@media screen and (max-width: 616px) and (min-width: 449px) {
41
+  .comment-item-speak-audio-container {
42
+    .slider {
43
+      width: 195px;
44
+    }
45
+  }
46
+}
47
+@media screen and (max-width: 449px) and (min-width: 365px) {
48
+  .comment-item-speak-audio-container {
49
+    .slider {
50
+      width: 114px;
51
+    }
52
+  }
53
+}
54
+@media screen and (max-width: 365px) {
55
+  .comment-item-speak-audio-container {
56
+    .slider {
57
+      width: 60px;
58
+    }
59
+  }
60
+}

+ 12
- 0
src/components/CommentList/index.css Ver arquivo

@@ -17,3 +17,15 @@
17 17
 .comment-list-pagination {
18 18
   text-align: center;
19 19
 }
20
+
21
+.comment-list-filter-speak {
22
+  margin-left: 20px;
23
+  font-size: 14px;
24
+  color: rgba(93, 93, 93, 0.65);
25
+}
26
+
27
+@media screen and (max-width: 365px) {
28
+  .comment-list-filter-speak {
29
+    float: right;
30
+  }
31
+}

+ 35
- 6
src/components/CommentList/index.js Ver arquivo

@@ -1,5 +1,5 @@
1 1
 import React, { Component } from "react";
2
-import { Spin, Pagination } from "antd";
2
+import { Spin, Pagination, Checkbox } from "antd";
3 3
 import intl from "react-intl-universal";
4 4
 import Comment from "../../Comment";
5 5
 import CommentBox from "../CommentBox";
@@ -8,7 +8,9 @@ import "./index.css";
8 8
 class CommentList extends Component {
9 9
   constructor(props) {
10 10
     super(props);
11
-    this.state = {};
11
+    this.state = {
12
+      filterSpeak: 0
13
+    };
12 14
   }
13 15
 
14 16
   componentWillMount() {
@@ -27,6 +29,7 @@ class CommentList extends Component {
27 29
       onPageChange,
28 30
       onGetMoreBtnClick
29 31
     } = this.props.app;
32
+    const { filterSpeak } = this.state;
30 33
     if (pageType === "slice") {
31 34
       // 截断多余评论,通过点击查看更多跳转
32 35
       return (
@@ -40,7 +43,7 @@ class CommentList extends Component {
40 43
           <div
41 44
             className="comment-list-show-more"
42 45
             onClick={() => {
43
-              sGetComment({ page: page + 1 });
46
+              sGetComment({ page: page + 1, filterSpeak });
44 47
               onPageChange(page + 1);
45 48
             }}
46 49
           >
@@ -58,7 +61,7 @@ class CommentList extends Component {
58 61
             current={page}
59 62
             total={total}
60 63
             onChange={p => {
61
-              sGetComment({ page: p });
64
+              sGetComment({ page: p, filterSpeak });
62 65
               onPageChange(p);
63 66
             }}
64 67
           />
@@ -68,7 +71,14 @@ class CommentList extends Component {
68 71
   }
69 72
 
70 73
   render() {
71
-    const { list, total, loading } = this.props.app;
74
+    const {
75
+      list,
76
+      total,
77
+      loading,
78
+      isSpeak,
79
+      sGetComment,
80
+      onPageChange
81
+    } = this.props.app;
72 82
 
73 83
     const spinning = Boolean(
74 84
       loading.sGetComment || loading.sCommentFavor || loading.sReplyFavor
@@ -77,7 +87,26 @@ class CommentList extends Component {
77 87
       <div>
78 88
         <Spin spinning={spinning}>
79 89
           {/* <div>共 {total} 条评论</div> */}
80
-          <div>{intl.get("comment.totalComment", { total })}</div>
90
+          <div>
91
+            {intl.get("comment.totalComment", { total })}
92
+            {isSpeak && (
93
+              <Checkbox
94
+                className="comment-list-filter-speak"
95
+                onChange={e => {
96
+                  this.setState({
97
+                    filterSpeak: e.target.checked ? 1 : 0
98
+                  });
99
+                  sGetComment({
100
+                    page: 1,
101
+                    filterSpeak: e.target.checked ? 1 : 0
102
+                  });
103
+                  onPageChange(1);
104
+                }}
105
+              >
106
+                {intl.get("comment.filterSpeak")}
107
+              </Checkbox>
108
+            )}
109
+          </div>
81 110
           {list.map(item => (
82 111
             <CommentBox
83 112
               content={item}

+ 27
- 0
src/components/ContentItem/index.css Ver arquivo

@@ -33,6 +33,21 @@
33 33
   word-break: break-all;
34 34
 }
35 35
 
36
+.comment-item-speak {
37
+  margin-top: 4px;
38
+}
39
+
40
+.comment-item-speak-message {
41
+  font-size: 14px;
42
+  color: #71c135;
43
+}
44
+
45
+.comment-item-speak-audio-wrapper {
46
+  margin-top: 8px;
47
+  width: 350px;
48
+  height: 44px;
49
+}
50
+
36 51
 .comment-item-bottom {
37 52
   display: flex;
38 53
   justify-content: flex-end;
@@ -156,6 +171,10 @@
156 171
     width: 85%;
157 172
     margin-left: 10px;
158 173
   }
174
+
175
+  .comment-item-speak-audio-wrapper {
176
+    width: 350px;
177
+  }
159 178
 }
160 179
 
161 180
 @media screen and (max-width: 449px) and (min-width: 365px) {
@@ -164,6 +183,10 @@
164 183
     width: 80%;
165 184
     margin-left: 10px;
166 185
   }
186
+
187
+  .comment-item-speak-audio-wrapper {
188
+    width: 266px;
189
+  }
167 190
 }
168 191
 
169 192
 @media screen and (max-width: 365px) {
@@ -172,6 +195,10 @@
172 195
     width: 75%;
173 196
     margin-left: 10px;
174 197
   }
198
+
199
+  .comment-item-speak-audio-wrapper {
200
+    width: 218px;
201
+  }
175 202
 }
176 203
 
177 204
 @media (max-width: 575px) {

+ 12
- 1
src/components/ContentItem/index.js Ver arquivo

@@ -14,6 +14,7 @@ import { renderContent } from "../../helper";
14 14
 import { IMAGE_SPLIT } from "../../constant";
15 15
 import "./index.css";
16 16
 import ImagePreviewer from "../ImagePreviewer/ImagePreviewer";
17
+import AudioPlayer from "../AudioPlayer";
17 18
 
18 19
 // dayjs.locale("zh-cn");
19 20
 dayjs.extend(relativeTime);
@@ -103,6 +104,7 @@ class CommentItem extends Component {
103 104
       user_id,
104 105
       page
105 106
     } = this.props;
107
+    const { medias, is_speak: isSpeak } = content;
106 108
     const { locale, showHoverCard, showEdit } = this.props.app;
107 109
     const { showInput } = this.state;
108 110
     let newContent = content.content;
@@ -206,6 +208,15 @@ class CommentItem extends Component {
206 208
               )
207 209
             }}
208 210
           />
211
+
212
+          {isSpeak && (
213
+            <div className="comment-item-speak">
214
+              <span className="comment-item-speak-message">[跟读消息]</span>
215
+              <div className="comment-item-speak-audio-wrapper">
216
+                <AudioPlayer src={medias && medias[0] && medias[0].url} />
217
+              </div>
218
+            </div>
219
+          )}
209 220
           {// image为空时不渲染comment-item-image
210 221
           imageList.length > 0 && imageList[0] !== "" && (
211 222
             <div className="comment-item-image">
@@ -264,7 +275,7 @@ class CommentItem extends Component {
264 275
                 </a>
265 276
               </div>
266 277
             ) : null}
267
-            {showEdit && app.userId === content.user_id && (
278
+            {showEdit && !isSpeak && app.userId === content.user_id && (
268 279
               <i
269 280
                 className="comment-item-edit"
270 281
                 onClick={() =>

+ 1
- 0
src/lang/en-US.js Ver arquivo

@@ -12,6 +12,7 @@ const USdata = {
12 12
     "Total {total, plural, =1 {one comment} other {# comments}}",
13 13
   "comment.reply": "Reply",
14 14
   "comment.moreComment": "More comments",
15
+  "comment.filterSpeak": "Show imitations only",
15 16
 
16 17
   "reply.totalReply": "Total {total, plural, =1 {one reply} other {# replies}}",
17 18
   "reply.moreReply": "More replies",

+ 1
- 0
src/lang/zh-CN.js Ver arquivo

@@ -11,6 +11,7 @@ const CNdata = {
11 11
   "comment.totalComment": "共{total}条评论",
12 12
   "comment.reply": "回复",
13 13
   "comment.moreComment": "更多评论",
14
+  "comment.filterSpeak": "只显示跟读",
14 15
 
15 16
   "reply.totalReply": "共{total}条回复",
16 17
   "reply.moreReply": "更多回复",