Browse Source

Merge branch 'feature/token' of node/npmcomment into master

node 5 years ago
parent
commit
0d0fb477b9

+ 5
- 0
CHANGELOG.md View File

@@ -1,5 +1,10 @@
1 1
 # CHANGELOG
2 2
 
3
+## 0.2.1
4
+
5
+- [x] feat: 添加 props token
6
+- [x] feat: 编辑器没有值的时候,默认处于 disabled 状态
7
+
3 8
 ## 0.2.0
4 9
 
5 10
 - [x] feat: 添加 showHeader 属性

+ 1
- 0
README.md View File

@@ -22,6 +22,7 @@ import Comment, { Editor } from 'comment';
22 22
 | showList | boolean |   true  | false     | 是否显示评论列表|
23 23
 | showEditor | boolean |   true  | false     | 是否显示评论输入框|
24 24
 | showHeader | boolean |   true  | false     | 是否显示评论顶部的提示|
25
+| token | string |     | false     | token,用于身份认证,非必须。默认使用 cookie|
25 26
 
26 27
 
27 28
 

+ 40
- 24
lib/App.js View File

@@ -29,7 +29,7 @@ var _propTypes = require("prop-types");
29 29
 
30 30
 var _propTypes2 = _interopRequireDefault(_propTypes);
31 31
 
32
-var _axios = require("./axios");
32
+var _axios = require("axios");
33 33
 
34 34
 var _axios2 = _interopRequireDefault(_axios);
35 35
 
@@ -98,6 +98,15 @@ var App = function (_Component) {
98 98
   }
99 99
 
100 100
   _createClass(App, [{
101
+    key: "componentWillMount",
102
+    value: function componentWillMount() {
103
+      this.axios = _axios2.default;
104
+      this.axios.defaults.withCredentials = true;
105
+      if (this.props.token) {
106
+        this.axios.defaults.headers.common["Authorization"] = "Bearer " + this.props.token;
107
+      }
108
+    }
109
+  }, {
101 110
     key: "componentDidMount",
102 111
     value: function componentDidMount() {}
103 112
 
@@ -135,7 +144,7 @@ var App = function (_Component) {
135 144
           type = _props.type,
136 145
           businessId = _props.businessId;
137 146
 
138
-      _axios2.default.get(API + "/comments?type=" + type + "&business_id=" + businessId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
147
+      this.axios.get(API + "/comments?type=" + type + "&business_id=" + businessId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
139 148
         var _response$data = response.data,
140 149
             list = _response$data.list,
141 150
             page = _response$data.page,
@@ -191,7 +200,7 @@ var App = function (_Component) {
191 200
       this.handleChangeLoading("sGetReply", true);
192 201
       var API = this.props.API;
193 202
 
194
-      _axios2.default.get(API + "/replies?comment_id=" + commentId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
203
+      this.axios.get(API + "/replies?comment_id=" + commentId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
195 204
         if (!response.data.list) {
196 205
           _message3.default.info("没有更多数据了!");
197 206
         }
@@ -242,6 +251,8 @@ var App = function (_Component) {
242 251
       var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
243 252
           content = _ref3.content;
244 253
 
254
+      var cb = arguments[1];
255
+
245 256
       if (!content) return _message3.default.error("评论内容不能为空 ");
246 257
       this.handleChangeLoading("sCreateComment", true);
247 258
       var _props2 = this.props,
@@ -249,7 +260,7 @@ var App = function (_Component) {
249 260
           type = _props2.type,
250 261
           businessId = _props2.businessId;
251 262
 
252
-      (0, _axios2.default)(API + "/comments", {
263
+      this.axios(API + "/comments", {
253 264
         method: "post",
254 265
         data: {
255 266
           type: type,
@@ -259,6 +270,7 @@ var App = function (_Component) {
259 270
         withCredentials: true
260 271
       }).then(function (response) {
261 272
         _message3.default.success("评论成功!");
273
+        if ((0, _helper.isFunction)(cb)) cb();
262 274
         // 将数据写入到 list 中
263 275
         // 临时插入
264 276
         // 等到获取数据之后,删除临时数据
@@ -292,13 +304,11 @@ var App = function (_Component) {
292 304
     value: function sCreateReply(data, cb) {
293 305
       var _this5 = this;
294 306
 
295
-      console.log("list: ", this.state.list);
296
-
297 307
       if (!data.content) return _message3.default.error("回复内容不能为空 ");
298 308
       this.handleChangeLoading("sCreateReply", true);
299 309
       var API = this.props.API;
300 310
 
301
-      (0, _axios2.default)(API + "/replies", {
311
+      this.axios(API + "/replies", {
302 312
         method: "post",
303 313
         data: data,
304 314
         withCredentials: true
@@ -344,7 +354,7 @@ var App = function (_Component) {
344 354
       this.handleChangeLoading("sCommentFavor", true);
345 355
       var API = this.props.API;
346 356
 
347
-      (0, _axios2.default)(API + "/comments/" + commentId + "/favor", {
357
+      this.axios(API + "/comments/" + commentId + "/favor", {
348 358
         method: favored ? "delete" : "put",
349 359
         withCredentials: true
350 360
       }).then(function (response) {
@@ -382,27 +392,33 @@ var App = function (_Component) {
382 392
       var _this7 = this;
383 393
 
384 394
       this.handleChangeLoading("sReplyFavor", true);
385
-      console.log("replyId, commentId ", replyId, commentId);
386
-
387 395
       var API = this.props.API;
388 396
 
389
-      (0, _axios2.default)(API + "/replies/" + replyId + "/favor", {
397
+      this.axios(API + "/replies/" + replyId + "/favor", {
390 398
         method: favored ? "delete" : "put",
399
+        data: {
400
+          comment_id: commentId
401
+        },
391 402
         withCredentials: true
392 403
       }).then(function (response) {
393
-        console.log("response: ", response);
394
-
395 404
         _message3.default.success(favored ? "取消点赞成功!" : "点赞成功!");
396
-        // TODO: (2018.07.20 node) 对评论的回复点赞,报错
397
-        // // 更新 list 中的该项数据的 favored
398
-        // const list = this.state.list.map(item => {
399
-        //   if (item.id === replyId) {
400
-        //     item.favored = !favored;
401
-        //     item.favor_count += favored ? -1 : 1;
402
-        //   }
403
-        //   return item;
404
-        // });
405
-        // this.setState({ list });
405
+        // 更新 list 中的该项数据的 favored
406
+        var list = _this7.state.list.map(function (item) {
407
+          if (item.id === commentId) {
408
+            item.replies = item.replies.map(function (r) {
409
+              if (r.id === replyId) {
410
+                r.favored = !favored;
411
+                // r.favor_count =  response.data.favor_count;
412
+                // 点赞数 +1,而不是使用后端返回的点赞数
413
+                // 不然如果返回的不是增加 1,用户可能以为程序错误
414
+                r.favor_count += favored ? -1 : 1;
415
+              }
416
+              return r;
417
+            });
418
+          }
419
+          return item;
420
+        });
421
+        _this7.setState({ list: list });
406 422
       }).catch(function (error) {
407 423
         if (error.response && error.response.data && error.response.data.msg) {
408 424
           _message3.default.error(_lang2.default[error.response.data.msg] || _constant.ERROR_DEFAULT);
@@ -426,7 +442,7 @@ var App = function (_Component) {
426 442
       this.handleChangeLoading("sOssSts", true);
427 443
       var API = this.props.API;
428 444
 
429
-      _axios2.default.get(API + "/oss/sts").then(function (response) {
445
+      this.axios.get(API + "/oss/sts").then(function (response) {
430 446
         _this8.setState({ oss: _extends({}, response.data) });
431 447
       }).catch(function (error) {
432 448
         if (error.response && error.response.data && error.response.data.msg) {

+ 1
- 1
lib/App.js.map
File diff suppressed because it is too large
View File


+ 1
- 0
lib/axios.js View File

@@ -11,6 +11,7 @@ var _axios2 = _interopRequireDefault(_axios);
11 11
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 12
 
13 13
 _axios2.default.defaults.withCredentials = true;
14
+_axios2.default.defaults.headers.common["Authorization"] = "Bearer ";
14 15
 
15 16
 exports.default = _axios2.default;
16 17
 //# sourceMappingURL=axios.js.map

+ 1
- 1
lib/axios.js.map View File

@@ -1 +1 @@
1
-{"version":3,"sources":["../src/axios.js"],"names":["axios","defaults","withCredentials"],"mappings":";;;;;;AAAA;;;;;;AAEAA,gBAAMC,QAAN,CAAeC,eAAf,GAAiC,IAAjC;;kBAEeF,e","file":"axios.js","sourcesContent":["import axios from \"axios\";\n\naxios.defaults.withCredentials = true;\n\nexport default axios;\n"]}
1
+{"version":3,"sources":["../src/axios.js"],"names":["axios","defaults","withCredentials","headers","common"],"mappings":";;;;;;AAAA;;;;;;AAEAA,gBAAMC,QAAN,CAAeC,eAAf,GAAiC,IAAjC;AACAF,gBAAMC,QAAN,CAAeE,OAAf,CAAuBC,MAAvB,CAA8B,eAA9B,IAAiD,SAAjD;;kBAEeJ,e","file":"axios.js","sourcesContent":["import axios from \"axios\";\n\naxios.defaults.withCredentials = true;\naxios.defaults.headers.common[\"Authorization\"] = \"Bearer \";\n\nexport default axios;\n"]}

+ 9
- 2
lib/components/CommentInput/index.js View File

@@ -41,9 +41,16 @@ var CommentInput = function (_Component) {
41 41
     return _this;
42 42
   }
43 43
 
44
+  /**
45
+   * 提交评论
46
+   * @param {string} value 需要提交的评论的值
47
+   * @param {function} cb 提交成功后的回掉
48
+   */
49
+
50
+
44 51
   _createClass(CommentInput, [{
45 52
     key: "handleSubmit",
46
-    value: function handleSubmit(value) {
53
+    value: function handleSubmit(value, cb) {
47 54
       var _props = this.props,
48 55
           action = _props.action,
49 56
           commentId = _props.commentId,
@@ -53,7 +60,7 @@ var CommentInput = function (_Component) {
53 60
       if (action === "comment") {
54 61
         this.props.app.sCreateComment({
55 62
           content: value
56
-        });
63
+        }, cb);
57 64
       } else if (action === "reply") {
58 65
         this.props.app.sCreateReply({
59 66
           comment_id: commentId,

+ 1
- 1
lib/components/CommentInput/index.js.map View File

@@ -1 +1 @@
1
-{"version":3,"sources":["../../../src/components/CommentInput/index.js"],"names":["CommentInput","props","state","handleSubmit","bind","value","action","commentId","replyId","callback","app","sCreateComment","content","sCreateReply","comment_id","reply_id","childrenWithProps","React","Children","map","cloneElement","child","onSubmit","rows","Component","propTypes","PropTypes","oneOf","defaultProps"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;;;;;;;;;;;IAEMA,Y;;;AACJ,wBAAYC,KAAZ,EAAmB;AAAA;;AAAA,4HACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa,EAAb;AACA,UAAKC,YAAL,GAAoB,MAAKA,YAAL,CAAkBC,IAAlB,OAApB;AAHiB;AAIlB;;;;iCAEYC,K,EAAO;AAAA,mBAC+B,KAAKJ,KADpC;AAAA,UACVK,MADU,UACVA,MADU;AAAA,UACFC,SADE,UACFA,SADE;AAAA,UACSC,OADT,UACSA,OADT;AAAA,UACkBC,QADlB,UACkBA,QADlB;;AAElB,UAAIH,WAAW,SAAf,EAA0B;AACxB,aAAKL,KAAL,CAAWS,GAAX,CAAeC,cAAf,CAA8B;AAC5BC,mBAASP;AADmB,SAA9B;AAGD,OAJD,MAIO,IAAIC,WAAW,OAAf,EAAwB;AAC7B,aAAKL,KAAL,CAAWS,GAAX,CAAeG,YAAf,CACE;AACEC,sBAAYP,SADd;AAEEK,mBAASP;AAFX,SADF,EAKE;AAAA,iBAAMI,YAAYA,UAAlB;AAAA,SALF;AAOD,OARM,MAQA,IAAIH,WAAW,cAAf,EAA+B;AACpC,aAAKL,KAAL,CAAWS,GAAX,CAAeG,YAAf,CACE;AACEC,sBAAYP,SADd;AAEEK,mBAASP,KAFX;AAGEU,oBAAUP;AAHZ,SADF,EAME;AAAA,iBAAMC,YAAYA,UAAlB;AAAA,SANF;AAQD;AACF;;;6BAEQ;AAAA;;AACP,UAAMO,oBAAoBC,gBAAMC,QAAN,CAAeC,GAAf,CAAmB,KAAKlB,KAAL,CAAWW,OAA9B,EAAuC,iBAAS;AACxE,eAAOK,gBAAMG,YAAN,CAAmBC,KAAnB;AACL;AACA;AACA;AACA;AACAC,oBAAU,OAAKnB;AALV,WAMFkB,MAAMpB,KANJ;AAOL;AACAsB,gBACE,OAAKtB,KAAL,CAAWK,MAAX,KAAsB,SAAtB,GACIe,MAAMpB,KAAN,CAAYsB,IADhB,GAEIF,MAAMpB,KAAN,CAAYsB,IAAZ,GAAmB;AAXpB,WAAP;AAaD,OAdyB,CAA1B;;AAgBA,aAAO;AAAA;AAAA;AAAMP;AAAN,OAAP;AACD;;;;EAnDwBQ,gB;;AAsD3BxB,aAAayB,SAAb,GAAyB;AACvB;AACA;AACA;AACAnB,UAAQoB,oBAAUC,KAAV,CAAgB,CAAC,SAAD,EAAY,OAAZ,EAAqB,cAArB,CAAhB;AAJe,CAAzB;;AAOA3B,aAAa4B,YAAb,GAA4B;AAC1BtB,UAAQ;AADkB,CAA5B;;kBAIe,uBAAQN,YAAR,C","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport PropTypes from \"prop-types\";\nimport Comment from \"../../Comment\";\n\nclass CommentInput extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {};\n    this.handleSubmit = this.handleSubmit.bind(this);\n  }\n\n  handleSubmit(value) {\n    const { action, commentId, replyId, callback } = this.props;\n    if (action === \"comment\") {\n      this.props.app.sCreateComment({\n        content: value\n      });\n    } else if (action === \"reply\") {\n      this.props.app.sCreateReply(\n        {\n          comment_id: commentId,\n          content: value\n        },\n        () => callback && callback()\n      );\n    } else if (action === \"replyToReply\") {\n      this.props.app.sCreateReply(\n        {\n          comment_id: commentId,\n          content: value,\n          reply_id: replyId\n        },\n        () => callback && callback()\n      );\n    }\n  }\n\n  render() {\n    const childrenWithProps = React.Children.map(this.props.content, child => {\n      return React.cloneElement(child, {\n        // 编辑器本身不提交值,但 CommentInput 会提交\n        // CommentInput 主要是负责评论的业务逻辑,提交评论和回复\n        // 默认使用 CommentInput 的 onSubmit 来提交评论\n        // 但也可以使用 Editor 的 props 来覆盖 onSubmit\n        onSubmit: this.handleSubmit,\n        ...child.props,\n        // 如果当前的编辑器不是“评论”,则编辑器高度减小一些\n        rows:\n          this.props.action === \"comment\"\n            ? child.props.rows\n            : child.props.rows - 1\n      });\n    });\n\n    return <div>{childrenWithProps}</div>;\n  }\n}\n\nCommentInput.propTypes = {\n  // comment 评论\n  // reply 评论的回复\n  // replyToReply 回复的回复\n  action: PropTypes.oneOf([\"comment\", \"reply\", \"replyToReply\"])\n};\n\nCommentInput.defaultProps = {\n  action: \"comment\"\n};\n\nexport default Comment(CommentInput);\n"]}
1
+{"version":3,"sources":["../../../src/components/CommentInput/index.js"],"names":["CommentInput","props","state","handleSubmit","bind","value","cb","action","commentId","replyId","callback","app","sCreateComment","content","sCreateReply","comment_id","reply_id","childrenWithProps","React","Children","map","cloneElement","child","onSubmit","rows","Component","propTypes","PropTypes","oneOf","defaultProps"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;;;;;;;;;;;IAEMA,Y;;;AACJ,wBAAYC,KAAZ,EAAmB;AAAA;;AAAA,4HACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa,EAAb;AACA,UAAKC,YAAL,GAAoB,MAAKA,YAAL,CAAkBC,IAAlB,OAApB;AAHiB;AAIlB;;AAED;;;;;;;;;iCAKaC,K,EAAOC,E,EAAI;AAAA,mBAC2B,KAAKL,KADhC;AAAA,UACdM,MADc,UACdA,MADc;AAAA,UACNC,SADM,UACNA,SADM;AAAA,UACKC,OADL,UACKA,OADL;AAAA,UACcC,QADd,UACcA,QADd;;AAEtB,UAAIH,WAAW,SAAf,EAA0B;AACxB,aAAKN,KAAL,CAAWU,GAAX,CAAeC,cAAf,CACE;AACEC,mBAASR;AADX,SADF,EAIEC,EAJF;AAMD,OAPD,MAOO,IAAIC,WAAW,OAAf,EAAwB;AAC7B,aAAKN,KAAL,CAAWU,GAAX,CAAeG,YAAf,CACE;AACEC,sBAAYP,SADd;AAEEK,mBAASR;AAFX,SADF,EAKE;AAAA,iBAAMK,YAAYA,UAAlB;AAAA,SALF;AAOD,OARM,MAQA,IAAIH,WAAW,cAAf,EAA+B;AACpC,aAAKN,KAAL,CAAWU,GAAX,CAAeG,YAAf,CACE;AACEC,sBAAYP,SADd;AAEEK,mBAASR,KAFX;AAGEW,oBAAUP;AAHZ,SADF,EAME;AAAA,iBAAMC,YAAYA,UAAlB;AAAA,SANF;AAQD;AACF;;;6BAEQ;AAAA;;AACP,UAAMO,oBAAoBC,gBAAMC,QAAN,CAAeC,GAAf,CAAmB,KAAKnB,KAAL,CAAWY,OAA9B,EAAuC,iBAAS;AACxE,eAAOK,gBAAMG,YAAN,CAAmBC,KAAnB;AACL;AACA;AACA;AACA;AACAC,oBAAU,OAAKpB;AALV,WAMFmB,MAAMrB,KANJ;AAOL;AACAuB,gBACE,OAAKvB,KAAL,CAAWM,MAAX,KAAsB,SAAtB,GACIe,MAAMrB,KAAN,CAAYuB,IADhB,GAEIF,MAAMrB,KAAN,CAAYuB,IAAZ,GAAmB;AAXpB,WAAP;AAaD,OAdyB,CAA1B;;AAgBA,aAAO;AAAA;AAAA;AAAMP;AAAN,OAAP;AACD;;;;EA3DwBQ,gB;;AA8D3BzB,aAAa0B,SAAb,GAAyB;AACvB;AACA;AACA;AACAnB,UAAQoB,oBAAUC,KAAV,CAAgB,CAAC,SAAD,EAAY,OAAZ,EAAqB,cAArB,CAAhB;AAJe,CAAzB;;AAOA5B,aAAa6B,YAAb,GAA4B;AAC1BtB,UAAQ;AADkB,CAA5B;;kBAIe,uBAAQP,YAAR,C","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport PropTypes from \"prop-types\";\nimport Comment from \"../../Comment\";\n\nclass CommentInput extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {};\n    this.handleSubmit = this.handleSubmit.bind(this);\n  }\n\n  /**\n   * 提交评论\n   * @param {string} value 需要提交的评论的值\n   * @param {function} cb 提交成功后的回掉\n   */\n  handleSubmit(value, cb) {\n    const { action, commentId, replyId, callback } = this.props;\n    if (action === \"comment\") {\n      this.props.app.sCreateComment(\n        {\n          content: value\n        },\n        cb\n      );\n    } else if (action === \"reply\") {\n      this.props.app.sCreateReply(\n        {\n          comment_id: commentId,\n          content: value\n        },\n        () => callback && callback()\n      );\n    } else if (action === \"replyToReply\") {\n      this.props.app.sCreateReply(\n        {\n          comment_id: commentId,\n          content: value,\n          reply_id: replyId\n        },\n        () => callback && callback()\n      );\n    }\n  }\n\n  render() {\n    const childrenWithProps = React.Children.map(this.props.content, child => {\n      return React.cloneElement(child, {\n        // 编辑器本身不提交值,但 CommentInput 会提交\n        // CommentInput 主要是负责评论的业务逻辑,提交评论和回复\n        // 默认使用 CommentInput 的 onSubmit 来提交评论\n        // 但也可以使用 Editor 的 props 来覆盖 onSubmit\n        onSubmit: this.handleSubmit,\n        ...child.props,\n        // 如果当前的编辑器不是“评论”,则编辑器高度减小一些\n        rows:\n          this.props.action === \"comment\"\n            ? child.props.rows\n            : child.props.rows - 1\n      });\n    });\n\n    return <div>{childrenWithProps}</div>;\n  }\n}\n\nCommentInput.propTypes = {\n  // comment 评论\n  // reply 评论的回复\n  // replyToReply 回复的回复\n  action: PropTypes.oneOf([\"comment\", \"reply\", \"replyToReply\"])\n};\n\nCommentInput.defaultProps = {\n  action: \"comment\"\n};\n\nexport default Comment(CommentInput);\n"]}

+ 3
- 0
lib/components/ContentItem/index.css View File

@@ -29,6 +29,9 @@
29 29
   margin-left: 5px;
30 30
   cursor: pointer;
31 31
 }
32
+.comment-favor {
33
+  font-size: 20px;
34
+}
32 35
 .comment-favored {
33 36
   color: #4a90e2;
34 37
 }

+ 1
- 1
lib/components/ContentItem/index.js View File

@@ -193,7 +193,7 @@ var CommentItem = function (_Component) {
193 193
               },
194 194
               _react2.default.createElement(_icon2.default, {
195 195
                 type: "like-o",
196
-                className: content.favored ? "comment-favored" : ""
196
+                className: content.favored ? "comment-favor comment-favored" : "comment-favor"
197 197
               }),
198 198
               "\xA0",
199 199
               content.favor_count

+ 1
- 1
lib/components/ContentItem/index.js.map
File diff suppressed because it is too large
View File


+ 19
- 10
lib/components/Editor/index.js View File

@@ -147,7 +147,7 @@ var Editor = function (_React$Component) {
147 147
     }
148 148
 
149 149
     /**
150
-     * 上传文件 TODO:
150
+     * 上传文件
151 151
      * @param {object} param 文件对象
152 152
      */
153 153
 
@@ -171,6 +171,8 @@ var Editor = function (_React$Component) {
171 171
   }, {
172 172
     key: "handleSubmit",
173 173
     value: function handleSubmit() {
174
+      var _this2 = this;
175
+
174 176
       var _state = this.state,
175 177
           value = _state.value,
176 178
           fileMap = _state.fileMap,
@@ -182,12 +184,19 @@ var Editor = function (_React$Component) {
182 184
           value += "[" + _constant.OSS_LINK + fileMap[item.uid] + "]";
183 185
         });
184 186
       }
185
-      this.props.onSubmit(value);
187
+      this.props.onSubmit(value, function () {
188
+        _this2.setState({
189
+          showUpload: false,
190
+          value: "",
191
+          fileList: [],
192
+          fileMap: {}
193
+        });
194
+      });
186 195
     }
187 196
   }, {
188 197
     key: "render",
189 198
     value: function render() {
190
-      var _this2 = this;
199
+      var _this3 = this;
191 200
 
192 201
       var _props = this.props,
193 202
           value = _props.value,
@@ -202,15 +211,15 @@ var Editor = function (_React$Component) {
202 211
           emojiToolIcon = _props.emojiToolIcon,
203 212
           imageToolIcon = _props.imageToolIcon;
204 213
 
205
-
206 214
       var handleSubmit = this.handleSubmit;
215
+      var disabledSubmit = btnDisabled || !this.props.value && !this.state.value && !this.state.fileList.length;
207 216
       return _react2.default.createElement(
208 217
         "div",
209 218
         { className: "comment-editor" },
210 219
         _react2.default.createElement(TextArea, {
211 220
           value: value || this.state.value,
212 221
           onChange: function onChange(e) {
213
-            return _this2.handleChange(e.target.value);
222
+            return _this3.handleChange(e.target.value);
214 223
           },
215 224
           rows: rows,
216 225
           placeholder: placeholder
@@ -271,7 +280,7 @@ var Editor = function (_React$Component) {
271 280
                   _react2.default.createElement(_icon2.default, {
272 281
                     type: "close",
273 282
                     onClick: function onClick() {
274
-                      return _this2.handleShowUpload(false);
283
+                      return _this3.handleShowUpload(false);
275 284
                     },
276 285
                     style: {
277 286
                       float: "right",
@@ -283,14 +292,14 @@ var Editor = function (_React$Component) {
283 292
               },
284 293
               imageToolIcon ? _react2.default.cloneElement(imageToolIcon, {
285 294
                 onClick: function onClick() {
286
-                  return _this2.handleShowUpload(true);
295
+                  return _this3.handleShowUpload(true);
287 296
                 }
288 297
               }) : _react2.default.createElement(_icon2.default, {
289 298
                 type: "picture",
290 299
                 className: "comment-toolbar-icon",
291 300
                 style: { marginLeft: 10 },
292 301
                 onClick: function onClick() {
293
-                  return _this2.handleShowUpload(true);
302
+                  return _this3.handleShowUpload(true);
294 303
                 }
295 304
               })
296 305
             )
@@ -304,11 +313,11 @@ var Editor = function (_React$Component) {
304 313
               _button2.default,
305 314
               {
306 315
                 onClick: function onClick() {
307
-                  return _this2.handleSubmit();
316
+                  return _this3.handleSubmit();
308 317
                 },
309 318
                 type: "primary",
310 319
                 loading: btnLoading,
311
-                disabled: btnDisabled
320
+                disabled: disabledSubmit
312 321
               },
313 322
               btnSubmitText
314 323
             )

+ 1
- 1
lib/components/Editor/index.js.map
File diff suppressed because it is too large
View File


+ 4
- 0
lib/index.js View File

@@ -25,6 +25,9 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
25 25
 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; }
26 26
 
27 27
 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; }
28
+// e.g.
29
+// import { Button, Icon } from "antd";
30
+
28 31
 
29 32
 var Index = function (_Component) {
30 33
   _inherits(Index, _Component);
@@ -70,6 +73,7 @@ var Index = function (_Component) {
70 73
         _react2.default.createElement(_App.Editor, null)
71 74
       );
72 75
 
76
+      // e.g.
73 77
       // 复杂的用户法
74 78
       // const props = {
75 79
       //   type: 1,

+ 1
- 1
lib/index.js.map View File

@@ -1 +1 @@
1
-{"version":3,"sources":["../src/index.js"],"names":["Index","props","state","value","handleChangeValue","bind","handleChangeSubmit","setState","console","log","loading","setTimeout","Component","ReactDOM","render","document","getElementById"],"mappings":";;;;AAAA;;;;AACA;;;;AAEA;;;;AACA;;;;;;;;;;;;IAEMA,K;;;AACJ,iBAAYC,KAAZ,EAAmB;AAAA;;AAAA,8GACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa;AACXC,aAAO;AADI,KAAb;AAGA,UAAKC,iBAAL,GAAyB,MAAKA,iBAAL,CAAuBC,IAAvB,OAAzB;AACA,UAAKC,kBAAL,GAA0B,MAAKA,kBAAL,CAAwBD,IAAxB,OAA1B;AANiB;AAOlB;;;;sCAEiBF,K,EAAO;AACvB,WAAKI,QAAL,CAAc,EAAEJ,YAAF,EAAd;AACAK,cAAQC,GAAR,CAAY,2BAAZ,EAAyCN,KAAzC;AACD;;;uCAEkBA,K,EAAO;AAAA;;AACxB,WAAKI,QAAL,CAAc,EAAEG,SAAS,IAAX,EAAd,EAAiC,YAAM;AACrCC,mBAAW,YAAM;AACf,iBAAKJ,QAAL,CAAc,EAAEG,SAAS,KAAX,EAAd;AACD,SAFD,EAEG,IAFH;AAGD,OAJD;AAKAF,cAAQC,GAAR,CAAY,gBAAZ,EAA8BN,KAA9B;AACD;;;6BAEQ;AACP;AACA,aACE;AAAC,qBAAD;AAAA,UAAK,MAAM,CAAX,EAAc,YAAW,MAAzB;AACE,sCAAC,WAAD;AADF,OADF;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACD;;;;EAtEiBS,gB;;AAyEpBC,mBAASC,MAAT,CAAgB,8BAAC,KAAD,OAAhB,EAA2BC,SAASC,cAAT,CAAwB,cAAxB,CAA3B;AACA","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { Button, Icon } from \"antd\";\nimport App, { Editor } from \"./App\";\nimport registerServiceWorker from \"./registerServiceWorker\";\n\nclass Index extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      value: \"\"\n    };\n    this.handleChangeValue = this.handleChangeValue.bind(this);\n    this.handleChangeSubmit = this.handleChangeSubmit.bind(this);\n  }\n\n  handleChangeValue(value) {\n    this.setState({ value });\n    console.log(\"handleChangeValue value: \", value);\n  }\n\n  handleChangeSubmit(value) {\n    this.setState({ loading: true }, () => {\n      setTimeout(() => {\n        this.setState({ loading: false });\n      }, 2000);\n    });\n    console.log(\"submit value: \", value);\n  }\n\n  render() {\n    // 最简单的用法\n    return (\n      <App type={1} businessId=\"test\">\n        <Editor />\n      </App>\n    );\n\n    // 复杂的用户法\n    // const props = {\n    //   type: 1,\n    //   businessId: \"1\",\n    //   API: \"http://api.links123.net/comment/v1\",\n    //   showList: true\n    // };\n\n    // const editorProps = {\n    //   showEmoji: true,\n    //   placeholder: \"说点什么吧\",\n    //   rows: 5,\n    //   btnLoading: this.state.loading,\n    //   btnDisable: this.state.loading,\n    //   btnSubmitText: \"提交\",\n    //   value: this.state.value,\n    //   onChange: v => this.handleChangeValue(v),\n    //   onSubmit: v => this.handleChangeSubmit(v),\n    //   button: (\n    //     <Button\n    //       type=\"primary\"\n    //       ghost\n    //       // onClick={() => console.log('click btn: ', this.state.value)}\n    //     >\n    //       自定义按钮\n    //     </Button>\n    //   ),\n    //   emojiToolIcon: <Icon type=\"smile\" style={{ fontSize: 23 }} />,\n    //   imageToolIcon: (\n    //     <Icon type=\"cloud-upload-o\" style={{ fontSize: 25, marginLeft: 10 }} />\n    //   )\n    // };\n\n    // return (\n    //   <App {...props}>\n    //     <Editor {...editorProps} />\n    //   </App>\n    // );\n  }\n}\n\nReactDOM.render(<Index />, document.getElementById(\"root-comment\"));\nregisterServiceWorker();\n"]}
1
+{"version":3,"sources":["../src/index.js"],"names":["Index","props","state","value","handleChangeValue","bind","handleChangeSubmit","setState","console","log","loading","setTimeout","Component","ReactDOM","render","document","getElementById"],"mappings":";;;;AAAA;;;;AACA;;;;AAGA;;;;AACA;;;;;;;;;;;AAHA;AACA;;;IAIMA,K;;;AACJ,iBAAYC,KAAZ,EAAmB;AAAA;;AAAA,8GACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa;AACXC,aAAO;AADI,KAAb;AAGA,UAAKC,iBAAL,GAAyB,MAAKA,iBAAL,CAAuBC,IAAvB,OAAzB;AACA,UAAKC,kBAAL,GAA0B,MAAKA,kBAAL,CAAwBD,IAAxB,OAA1B;AANiB;AAOlB;;;;sCAEiBF,K,EAAO;AACvB,WAAKI,QAAL,CAAc,EAAEJ,YAAF,EAAd;AACAK,cAAQC,GAAR,CAAY,2BAAZ,EAAyCN,KAAzC;AACD;;;uCAEkBA,K,EAAO;AAAA;;AACxB,WAAKI,QAAL,CAAc,EAAEG,SAAS,IAAX,EAAd,EAAiC,YAAM;AACrCC,mBAAW,YAAM;AACf,iBAAKJ,QAAL,CAAc,EAAEG,SAAS,KAAX,EAAd;AACD,SAFD,EAEG,IAFH;AAGD,OAJD;AAKAF,cAAQC,GAAR,CAAY,gBAAZ,EAA8BN,KAA9B;AACD;;;6BAEQ;AACP;AACA,aACE;AAAC,qBAAD;AAAA,UAAK,MAAM,CAAX,EAAc,YAAW,MAAzB;AACE,sCAAC,WAAD;AADF,OADF;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACD;;;;EAvEiBS,gB;;AA0EpBC,mBAASC,MAAT,CAAgB,8BAAC,KAAD,OAAhB,EAA2BC,SAASC,cAAT,CAAwB,cAAxB,CAA3B;AACA","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport ReactDOM from \"react-dom\";\n// e.g.\n// import { Button, Icon } from \"antd\";\nimport App, { Editor } from \"./App\";\nimport registerServiceWorker from \"./registerServiceWorker\";\n\nclass Index extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      value: \"\"\n    };\n    this.handleChangeValue = this.handleChangeValue.bind(this);\n    this.handleChangeSubmit = this.handleChangeSubmit.bind(this);\n  }\n\n  handleChangeValue(value) {\n    this.setState({ value });\n    console.log(\"handleChangeValue value: \", value);\n  }\n\n  handleChangeSubmit(value) {\n    this.setState({ loading: true }, () => {\n      setTimeout(() => {\n        this.setState({ loading: false });\n      }, 2000);\n    });\n    console.log(\"submit value: \", value);\n  }\n\n  render() {\n    // 最简单的用法\n    return (\n      <App type={1} businessId=\"test\">\n        <Editor />\n      </App>\n    );\n\n    // e.g.\n    // 复杂的用户法\n    // const props = {\n    //   type: 1,\n    //   businessId: \"1\",\n    //   API: \"http://api.links123.net/comment/v1\",\n    //   showList: true\n    // };\n\n    // const editorProps = {\n    //   showEmoji: true,\n    //   placeholder: \"说点什么吧\",\n    //   rows: 5,\n    //   btnLoading: this.state.loading,\n    //   btnDisable: this.state.loading,\n    //   btnSubmitText: \"提交\",\n    //   value: this.state.value,\n    //   onChange: v => this.handleChangeValue(v),\n    //   onSubmit: v => this.handleChangeSubmit(v),\n    //   button: (\n    //     <Button\n    //       type=\"primary\"\n    //       ghost\n    //       // onClick={() => console.log('click btn: ', this.state.value)}\n    //     >\n    //       自定义按钮\n    //     </Button>\n    //   ),\n    //   emojiToolIcon: <Icon type=\"smile\" style={{ fontSize: 23 }} />,\n    //   imageToolIcon: (\n    //     <Icon type=\"cloud-upload-o\" style={{ fontSize: 25, marginLeft: 10 }} />\n    //   )\n    // };\n\n    // return (\n    //   <App {...props}>\n    //     <Editor {...editorProps} />\n    //   </App>\n    // );\n  }\n}\n\nReactDOM.render(<Index />, document.getElementById(\"root-comment\"));\nregisterServiceWorker();\n"]}

+ 2
- 2
package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "comment",
3
-  "version": "0.2.0",
3
+  "version": "0.2.1",
4 4
   "main": "lib/App.js",
5 5
   "description": "通用评论",
6 6
   "keywords": [
@@ -31,7 +31,7 @@
31 31
   },
32 32
   "scripts": {
33 33
     "precommit": "lint-staged",
34
-    "prettier": "prettier --single-quote --trailing-comma --write 'src/**/*.{js,jsx,json,css,less}'",
34
+    "prettier": "prettier --single-quote --trailing-comma=es5 --write 'src/**/*.{js,jsx,json,css,less}'",
35 35
     "start": "react-app-rewired start",
36 36
     "build": "react-app-rewired build",
37 37
     "test": "react-app-rewired test --env=jsdom",

+ 40
- 25
src/App.js View File

@@ -1,7 +1,7 @@
1 1
 import React, { Component } from "react";
2 2
 import PropTypes from "prop-types";
3 3
 import { message, Tag } from "antd";
4
-import axios from "./axios";
4
+import axios from "axios";
5 5
 import { ERROR_DEFAULT, LIMIT } from "./constant";
6 6
 import { CommentContext } from "./Comment";
7 7
 import { isFunction } from "./helper";
@@ -37,6 +37,16 @@ class App extends Component {
37 37
     this.sOssSts = this.sOssSts.bind(this);
38 38
   }
39 39
 
40
+  componentWillMount() {
41
+    this.axios = axios;
42
+    this.axios.defaults.withCredentials = true;
43
+    if (this.props.token) {
44
+      this.axios.defaults.headers.common["Authorization"] = `Bearer ${
45
+        this.props.token
46
+      }`;
47
+    }
48
+  }
49
+
40 50
   componentDidMount() {}
41 51
 
42 52
   /**
@@ -56,7 +66,7 @@ class App extends Component {
56 66
   sGetComment({ page = 1 } = {}) {
57 67
     this.handleChangeLoading("sGetComment", true);
58 68
     const { API, type, businessId } = this.props;
59
-    axios
69
+    this.axios
60 70
       .get(
61 71
         `${API}/comments?type=${type}&business_id=${businessId}&page=${page}&limit=${LIMIT}`
62 72
       )
@@ -100,7 +110,7 @@ class App extends Component {
100 110
   sGetReply({ commentId, page = 1 } = {}) {
101 111
     this.handleChangeLoading("sGetReply", true);
102 112
     const { API } = this.props;
103
-    axios
113
+    this.axios
104 114
       .get(`${API}/replies?comment_id=${commentId}&page=${page}&limit=${LIMIT}`)
105 115
       .then(response => {
106 116
         if (!response.data.list) {
@@ -146,11 +156,11 @@ class App extends Component {
146 156
    * 添加评论
147 157
    * @param {object} {content} comment content
148 158
    */
149
-  sCreateComment({ content } = {}) {
159
+  sCreateComment({ content } = {}, cb) {
150 160
     if (!content) return message.error("评论内容不能为空 ");
151 161
     this.handleChangeLoading("sCreateComment", true);
152 162
     const { API, type, businessId } = this.props;
153
-    axios(`${API}/comments`, {
163
+    this.axios(`${API}/comments`, {
154 164
       method: "post",
155 165
       data: {
156 166
         type,
@@ -161,6 +171,7 @@ class App extends Component {
161 171
     })
162 172
       .then(response => {
163 173
         message.success("评论成功!");
174
+        if (isFunction(cb)) cb();
164 175
         // 将数据写入到 list 中
165 176
         // 临时插入
166 177
         // 等到获取数据之后,删除临时数据
@@ -189,12 +200,10 @@ class App extends Component {
189 200
    * @param {object} data { comment_id, content, [reply_id] }
190 201
    */
191 202
   sCreateReply(data, cb) {
192
-    console.log("list: ", this.state.list);
193
-
194 203
     if (!data.content) return message.error("回复内容不能为空 ");
195 204
     this.handleChangeLoading("sCreateReply", true);
196 205
     const { API } = this.props;
197
-    axios(`${API}/replies`, {
206
+    this.axios(`${API}/replies`, {
198 207
       method: "post",
199 208
       data,
200 209
       withCredentials: true
@@ -238,7 +247,7 @@ class App extends Component {
238 247
   sCommentFavor(commentId, favored) {
239 248
     this.handleChangeLoading("sCommentFavor", true);
240 249
     const { API } = this.props;
241
-    axios(`${API}/comments/${commentId}/favor`, {
250
+    this.axios(`${API}/comments/${commentId}/favor`, {
242 251
       method: favored ? "delete" : "put",
243 252
       withCredentials: true
244 253
     })
@@ -274,27 +283,33 @@ class App extends Component {
274 283
    */
275 284
   sReplyFavor(replyId, commentId, favored) {
276 285
     this.handleChangeLoading("sReplyFavor", true);
277
-    console.log("replyId, commentId ", replyId, commentId);
278
-
279 286
     const { API } = this.props;
280
-    axios(`${API}/replies/${replyId}/favor`, {
287
+    this.axios(`${API}/replies/${replyId}/favor`, {
281 288
       method: favored ? "delete" : "put",
289
+      data: {
290
+        comment_id: commentId
291
+      },
282 292
       withCredentials: true
283 293
     })
284 294
       .then(response => {
285
-        console.log("response: ", response);
286
-
287 295
         message.success(favored ? "取消点赞成功!" : "点赞成功!");
288
-        // TODO: (2018.07.20 node) 对评论的回复点赞,报错
289
-        // // 更新 list 中的该项数据的 favored
290
-        // const list = this.state.list.map(item => {
291
-        //   if (item.id === replyId) {
292
-        //     item.favored = !favored;
293
-        //     item.favor_count += favored ? -1 : 1;
294
-        //   }
295
-        //   return item;
296
-        // });
297
-        // this.setState({ list });
296
+        // 更新 list 中的该项数据的 favored
297
+        const list = this.state.list.map(item => {
298
+          if (item.id === commentId) {
299
+            item.replies = item.replies.map(r => {
300
+              if (r.id === replyId) {
301
+                r.favored = !favored;
302
+                // r.favor_count =  response.data.favor_count;
303
+                // 点赞数 +1,而不是使用后端返回的点赞数
304
+                // 不然如果返回的不是增加 1,用户可能以为程序错误
305
+                r.favor_count += favored ? -1 : 1;
306
+              }
307
+              return r;
308
+            });
309
+          }
310
+          return item;
311
+        });
312
+        this.setState({ list });
298 313
       })
299 314
       .catch(error => {
300 315
         if (error.response && error.response.data && error.response.data.msg) {
@@ -314,7 +329,7 @@ class App extends Component {
314 329
   sOssSts() {
315 330
     this.handleChangeLoading("sOssSts", true);
316 331
     const { API } = this.props;
317
-    axios
332
+    this.axios
318 333
       .get(`${API}/oss/sts`)
319 334
       .then(response => {
320 335
         this.setState({ oss: { ...response.data } });

+ 1
- 0
src/axios.js View File

@@ -1,5 +1,6 @@
1 1
 import axios from "axios";
2 2
 
3 3
 axios.defaults.withCredentials = true;
4
+axios.defaults.headers.common["Authorization"] = "Bearer ";
4 5
 
5 6
 export default axios;

+ 12
- 4
src/components/CommentInput/index.js View File

@@ -9,12 +9,20 @@ class CommentInput extends Component {
9 9
     this.handleSubmit = this.handleSubmit.bind(this);
10 10
   }
11 11
 
12
-  handleSubmit(value) {
12
+  /**
13
+   * 提交评论
14
+   * @param {string} value 需要提交的评论的值
15
+   * @param {function} cb 提交成功后的回掉
16
+   */
17
+  handleSubmit(value, cb) {
13 18
     const { action, commentId, replyId, callback } = this.props;
14 19
     if (action === "comment") {
15
-      this.props.app.sCreateComment({
16
-        content: value
17
-      });
20
+      this.props.app.sCreateComment(
21
+        {
22
+          content: value
23
+        },
24
+        cb
25
+      );
18 26
     } else if (action === "reply") {
19 27
       this.props.app.sCreateReply(
20 28
         {

+ 3
- 0
src/components/ContentItem/index.css View File

@@ -29,6 +29,9 @@
29 29
   margin-left: 5px;
30 30
   cursor: pointer;
31 31
 }
32
+.comment-favor {
33
+  font-size: 20px;
34
+}
32 35
 .comment-favored {
33 36
   color: #4a90e2;
34 37
 }

+ 5
- 1
src/components/ContentItem/index.js View File

@@ -113,7 +113,11 @@ class CommentItem extends Component {
113 113
             >
114 114
               <Icon
115 115
                 type="like-o"
116
-                className={content.favored ? "comment-favored" : ""}
116
+                className={
117
+                  content.favored
118
+                    ? "comment-favor comment-favored"
119
+                    : "comment-favor"
120
+                }
117 121
               />
118 122
               &nbsp;{content.favor_count}
119 123
             </div>

+ 13
- 4
src/components/Editor/index.js View File

@@ -75,7 +75,7 @@ class Editor extends React.Component {
75 75
   }
76 76
 
77 77
   /**
78
-   * 上传文件 TODO:
78
+   * 上传文件
79 79
    * @param {object} param 文件对象
80 80
    */
81 81
   handleUpload({ uid, path }) {
@@ -97,7 +97,14 @@ class Editor extends React.Component {
97 97
         value += `[${OSS_LINK}${fileMap[item.uid]}]`;
98 98
       });
99 99
     }
100
-    this.props.onSubmit(value);
100
+    this.props.onSubmit(value, () => {
101
+      this.setState({
102
+        showUpload: false,
103
+        value: "",
104
+        fileList: [],
105
+        fileMap: {}
106
+      });
107
+    });
101 108
   }
102 109
 
103 110
   render() {
@@ -114,8 +121,10 @@ class Editor extends React.Component {
114 121
       emojiToolIcon,
115 122
       imageToolIcon
116 123
     } = this.props;
117
-
118 124
     const handleSubmit = this.handleSubmit;
125
+    const disabledSubmit =
126
+      btnDisabled ||
127
+      (!this.props.value && !this.state.value && !this.state.fileList.length);
119 128
     return (
120 129
       <div className="comment-editor">
121 130
         <TextArea
@@ -208,7 +217,7 @@ class Editor extends React.Component {
208 217
                 onClick={() => this.handleSubmit()}
209 218
                 type="primary"
210 219
                 loading={btnLoading}
211
-                disabled={btnDisabled}
220
+                disabled={disabledSubmit}
212 221
               >
213 222
                 {btnSubmitText}
214 223
               </Button>

+ 3
- 1
src/index.js View File

@@ -1,6 +1,7 @@
1 1
 import React, { Component } from "react";
2 2
 import ReactDOM from "react-dom";
3
-import { Button, Icon } from "antd";
3
+// e.g.
4
+// import { Button, Icon } from "antd";
4 5
 import App, { Editor } from "./App";
5 6
 import registerServiceWorker from "./registerServiceWorker";
6 7
 
@@ -36,6 +37,7 @@ class Index extends Component {
36 37
       </App>
37 38
     );
38 39
 
40
+    // e.g.
39 41
     // 复杂的用户法
40 42
     // const props = {
41 43
     //   type: 1,