Browse Source

Merge branch 'component' of node/npmcomment into master

node 6 years ago
parent
commit
875a3dd0e6

+ 68
- 6
README.md View File

17
 然后在代码里面引入 `comment` 组件:
17
 然后在代码里面引入 `comment` 组件:
18
 
18
 
19
 ```jsx
19
 ```jsx
20
-import Comment from 'comment'
20
+import Comment, { Editor } from 'comment'
21
 
21
 
22
 // ...
22
 // ...
23
 
23
 
24
 render() {
24
 render() {
25
   return (
25
   return (
26
-    <Comment />
26
+    <Comment>
27
+      <Editor />
28
+    </Comment>
27
   )
29
   )
28
 }
30
 }
29
 ```
31
 ```
33
 
35
 
34
 ### 作为静态文件引入
36
 ### 作为静态文件引入
35
 
37
 
36
-首先引入 OSS SDK,用于直传文件到 OSS。
38
+作为静态问卷使用的话,首先需要在 `index.js` 里面设置好组件的 `props`:
37
 
39
 
38
-然后分别通过 link 和 script 标签引入打包后的文件。
40
+```js
41
+// ...
42
+const props = {
43
+  type: 1,
44
+  businessId: "1",
45
+  API: "http://api.links123.net/comment/v1",
46
+  showList: false
47
+};
48
+
49
+const editorProps = {
50
+  showEmoji: true,
51
+  placeholder: "说点什么吧",
52
+  rows: 5,
53
+};
54
+
55
+
56
+// ...
57
+<App {...props}>
58
+    <Editor {...editorProps} />
59
+</App>
60
+```
61
+
62
+然后再进行打包:
63
+
64
+```
65
+$ yarn build
66
+```
67
+
68
+打包后会得到静态问卷,分别通过 link 和 script 标签在你的项目里面引入打包后的文件。
39
 
69
 
40
-再创建一个 id 为 `root-comment` 的标签,作为渲染通用评论的跟元素。
70
+
71
+然后还需要引入 OSS SDK,用于直传文件到 OSS。
72
+
73
+
74
+最后创建一个 id 为 `root-comment` 的标签,作为渲染通用评论的跟元素。
41
 
75
 
42
 如下所示:
76
 如下所示:
43
 
77
 
59
 </html>
93
 </html>
60
 ```
94
 ```
61
 
95
 
96
+## Props
97
+
98
+#### Comment
99
+
100
+
101
+| props | type   | default  | required | description |
102
+| ----- | -------| -------- | -------- | ----------- |
103
+| type  | number |          | true     | 评论的 type  |
104
+| businessId | string |     | true     | 评论的 business id|
105
+| API  | string | http://api.links123.net/comment/v1 | false | API 前缀|
106
+| showList | boolean |   true  | true     | 是否显示评论列表|
107
+| showEditor | boolean |   true  | true     | 是否显示评论输入框|
108
+
109
+
110
+##### Editor
111
+
112
+| props | type   | default  | required | description |
113
+| ----- | -------| -------- | -------- | ----------- |
114
+| rows  | number |       5   | false     | 编辑器的高度  |
115
+| placeholder | string |  说点什么吧...   | false     | 评论的中的提示文字|
116
+| submitText | string |  发表  | false     | 提交按钮的文字|
117
+| showEmoji | boolean |   true  | false     | 是否显示 Toolbar 中表情工具|
118
+| showUpload | boolean |   true  | false     | 是否显示 Toolbar 中 上传图片工具|
119
+| onChange | function |     | false     | 编辑器内容改变的回调函数|
120
+| onSubmit | function |     | false     | TODO... 尚未完成。点击提交按钮的回调函数|
121
+
62
 
122
 
63
 ## 开发
123
 ## 开发
64
 
124
 
76
 ## TODO
136
 ## TODO
77
 
137
 
78
 - [ ] 前后端统一错误码
138
 - [ ] 前后端统一错误码
79
-- [ ] type 和 businessID 的定义
139
+- [x] type 和 businessID 的定义
140
+- [ ] Editor onSubmit 回调
141
+

+ 60
- 32
lib/App.js View File

3
 Object.defineProperty(exports, "__esModule", {
3
 Object.defineProperty(exports, "__esModule", {
4
   value: true
4
   value: true
5
 });
5
 });
6
+exports.Editor = undefined;
6
 
7
 
7
 var _message2 = require("antd/es/message");
8
 var _message2 = require("antd/es/message");
8
 
9
 
18
 
19
 
19
 var _react2 = _interopRequireDefault(_react);
20
 var _react2 = _interopRequireDefault(_react);
20
 
21
 
22
+var _propTypes = require("prop-types");
23
+
24
+var _propTypes2 = _interopRequireDefault(_propTypes);
25
+
21
 var _axios = require("./axios");
26
 var _axios = require("./axios");
22
 
27
 
23
 var _axios2 = _interopRequireDefault(_axios);
28
 var _axios2 = _interopRequireDefault(_axios);
36
 
41
 
37
 var _CommentList2 = _interopRequireDefault(_CommentList);
42
 var _CommentList2 = _interopRequireDefault(_CommentList);
38
 
43
 
44
+var _Editor = require("./components/Editor");
45
+
46
+var _Editor2 = _interopRequireDefault(_Editor);
47
+
39
 require("./App.css");
48
 require("./App.css");
40
 
49
 
41
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
50
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
45
 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; }
54
 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; }
46
 
55
 
47
 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; }
56
 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; }
48
-// import * as mock from "./mock";
49
-
50
 
57
 
51
 var App = function (_Component) {
58
 var App = function (_Component) {
52
   _inherits(App, _Component);
59
   _inherits(App, _Component);
81
 
88
 
82
   _createClass(App, [{
89
   _createClass(App, [{
83
     key: "componentDidMount",
90
     key: "componentDidMount",
84
-    value: function componentDidMount() {
85
-      this.sGetComment();
86
-    }
91
+    value: function componentDidMount() {}
87
 
92
 
88
     /**
93
     /**
89
      * 改变 loading 状态
94
      * 改变 loading 状态
110
       var _this2 = this;
115
       var _this2 = this;
111
 
116
 
112
       var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
117
       var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
113
-          _ref$type = _ref.type,
114
-          type = _ref$type === undefined ? 1 : _ref$type,
115
-          _ref$businessId = _ref.businessId,
116
-          businessId = _ref$businessId === undefined ? 1 : _ref$businessId,
117
           _ref$page = _ref.page,
118
           _ref$page = _ref.page,
118
           page = _ref$page === undefined ? 1 : _ref$page;
119
           page = _ref$page === undefined ? 1 : _ref$page;
119
 
120
 
120
       this.handleChangeLoading("sGetComment", true);
121
       this.handleChangeLoading("sGetComment", true);
121
-      // 测试数据列表
122
-      // const { comments } = mock;
123
-      // this.setState({
124
-      //   list: comments.list,
125
-      //   page: 1,
126
-      //   total: 100
127
-      // });
128
-      // this.handleChangeLoading("sGetComment", false);
129
-      // return;
130
-      _axios2.default.get(_constant.URL + "/comments?type=" + type + "&business_id=" + businessId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
122
+      var _props = this.props,
123
+          API = _props.API,
124
+          type = _props.type,
125
+          businessId = _props.businessId;
126
+
127
+      _axios2.default.get(API + "/comments?type=" + type + "&business_id=" + businessId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
131
         var _response$data = response.data,
128
         var _response$data = response.data,
132
             list = _response$data.list,
129
             list = _response$data.list,
133
             page = _response$data.page,
130
             page = _response$data.page,
181
           page = _ref2$page === undefined ? 1 : _ref2$page;
178
           page = _ref2$page === undefined ? 1 : _ref2$page;
182
 
179
 
183
       this.handleChangeLoading("sGetReply", true);
180
       this.handleChangeLoading("sGetReply", true);
184
-      _axios2.default.get(_constant.URL + "/replies?comment_id=" + commentId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
181
+      var API = this.props.API;
182
+
183
+      _axios2.default.get(API + "/replies?comment_id=" + commentId + "&page=" + page + "&limit=" + _constant.LIMIT).then(function (response) {
185
         var replies = response.data.list;
184
         var replies = response.data.list;
186
 
185
 
187
         if (!replies) {
186
         if (!replies) {
219
 
218
 
220
     /**
219
     /**
221
      * 添加评论
220
      * 添加评论
222
-     * @param {object} data { type, business_id, content }
221
+     * @param {string} content comment content
223
      */
222
      */
224
 
223
 
225
   }, {
224
   }, {
226
     key: "sCreateComment",
225
     key: "sCreateComment",
227
-    value: function sCreateComment(data) {
226
+    value: function sCreateComment(content) {
228
       var _this4 = this;
227
       var _this4 = this;
229
 
228
 
230
-      if (!data.content) return _message3.default.error("评论内容不能为空 ");
229
+      if (!content) return _message3.default.error("评论内容不能为空 ");
231
       this.handleChangeLoading("sCreateComment", true);
230
       this.handleChangeLoading("sCreateComment", true);
232
-      (0, _axios2.default)(_constant.URL + "/comments", {
231
+      var _props2 = this.props,
232
+          API = _props2.API,
233
+          type = _props2.type,
234
+          businessId = _props2.businessId;
235
+
236
+      (0, _axios2.default)(API + "/comments", {
233
         method: "post",
237
         method: "post",
234
-        data: data,
238
+        data: {
239
+          type: type,
240
+          business_id: businessId,
241
+          content: content
242
+        },
235
         withCredentials: true
243
         withCredentials: true
236
       }).then(function (response) {
244
       }).then(function (response) {
237
         _message3.default.success("评论成功!");
245
         _message3.default.success("评论成功!");
268
 
276
 
269
       if (!data.content) return _message3.default.error("回复内容不能为空 ");
277
       if (!data.content) return _message3.default.error("回复内容不能为空 ");
270
       this.handleChangeLoading("sCreateReply", true);
278
       this.handleChangeLoading("sCreateReply", true);
271
-      (0, _axios2.default)(_constant.URL + "/replies", {
279
+      var API = this.props.API;
280
+
281
+      (0, _axios2.default)(API + "/replies", {
272
         method: "post",
282
         method: "post",
273
         data: data,
283
         data: data,
274
         withCredentials: true
284
         withCredentials: true
275
       }).then(function (response) {
285
       }).then(function (response) {
276
-        // console.log("response: ", response.data);
277
         // // 将该条数据插入到 list 中
286
         // // 将该条数据插入到 list 中
278
         // const list = this.state.list.map(item => {
287
         // const list = this.state.list.map(item => {
279
         //   if (item.id === data.comment_id) {
288
         //   if (item.id === data.comment_id) {
310
       var _this6 = this;
319
       var _this6 = this;
311
 
320
 
312
       this.handleChangeLoading("sCommentFavor", true);
321
       this.handleChangeLoading("sCommentFavor", true);
313
-      (0, _axios2.default)(_constant.URL + "/comments/" + commentId + "/favor", {
322
+      var API = this.props.API;
323
+
324
+      (0, _axios2.default)(API + "/comments/" + commentId + "/favor", {
314
         method: favored ? "delete" : "put",
325
         method: favored ? "delete" : "put",
315
         withCredentials: true
326
         withCredentials: true
316
       }).then(function (response) {
327
       }).then(function (response) {
345
       var _this7 = this;
356
       var _this7 = this;
346
 
357
 
347
       this.handleChangeLoading("sOssSts", true);
358
       this.handleChangeLoading("sOssSts", true);
348
-      _axios2.default.get(_constant.URL + "/oss/sts").then(function (response) {
359
+      var API = this.props.API;
360
+
361
+      _axios2.default.get(API + "/oss/sts").then(function (response) {
349
         _this7.setState({ oss: _extends({}, response.data) });
362
         _this7.setState({ oss: _extends({}, response.data) });
350
       }).catch(function (error) {
363
       }).catch(function (error) {
351
         if (error.response && error.response.data && error.response.data.msg) {
364
         if (error.response && error.response.data && error.response.data.msg) {
361
     key: "render",
374
     key: "render",
362
     value: function render() {
375
     value: function render() {
363
       // 添加到 Context 的数据
376
       // 添加到 Context 的数据
364
-      var value = _extends({}, this.state, {
377
+      var value = _extends({}, this.state, this.props, {
365
         sCreateComment: this.sCreateComment,
378
         sCreateComment: this.sCreateComment,
366
         sGetComment: this.sGetComment,
379
         sGetComment: this.sGetComment,
367
         sCommentFavor: this.sCommentFavor,
380
         sCommentFavor: this.sCommentFavor,
376
         _react2.default.createElement(
389
         _react2.default.createElement(
377
           "div",
390
           "div",
378
           { className: "comment" },
391
           { className: "comment" },
379
-          _react2.default.createElement(_CommentInput2.default, null),
380
-          _react2.default.createElement(
392
+          this.props.showEditor && _react2.default.createElement(_CommentInput2.default, { content: this.props.children }),
393
+          this.props.showList && _react2.default.createElement(
381
             "div",
394
             "div",
382
             { style: { marginTop: 20 } },
395
             { style: { marginTop: 20 } },
383
             _react2.default.createElement(_CommentList2.default, null)
396
             _react2.default.createElement(_CommentList2.default, null)
390
   return App;
403
   return App;
391
 }(_react.Component);
404
 }(_react.Component);
392
 
405
 
406
+App.propTypes = {
407
+  type: _propTypes2.default.number.isRequired, // 评论的 type
408
+  businessId: _propTypes2.default.string.isRequired, // 评论的 business_id
409
+  API: _propTypes2.default.string, // 评论的 API 前缀
410
+  showList: _propTypes2.default.bool, // 是否显示评论列表
411
+  showEditor: _propTypes2.default.bool // 是否显示评论输入框
412
+};
413
+
414
+App.defaultProps = {
415
+  API: "http://api.links123.net/comment/v1",
416
+  showList: true,
417
+  showEditor: true
418
+};
419
+
420
+exports.Editor = _Editor2.default;
393
 exports.default = App;
421
 exports.default = App;
394
 //# sourceMappingURL=App.js.map
422
 //# sourceMappingURL=App.js.map

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


+ 12
- 0
lib/CHANGELOG.md View File

1
+# CHANGELOG
2
+
3
+
4
+## 0.1.0
5
+
6
+- [x] 不兼容更新。
7
+- [x] 添加了很多 `Props`
8
+- [x] 组件导出为 `Comment` 和 `Editor`
9
+
10
+
11
+
12
+

+ 34
- 24
lib/components/CommentInput/index.js View File

4
   value: true
4
   value: true
5
 });
5
 });
6
 
6
 
7
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8
+
7
 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; }; }();
9
 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; }; }();
8
 
10
 
9
 var _react = require("react");
11
 var _react = require("react");
20
 
22
 
21
 var _Comment2 = _interopRequireDefault(_Comment);
23
 var _Comment2 = _interopRequireDefault(_Comment);
22
 
24
 
23
-var _Editor = require("../Editor");
24
-
25
-var _Editor2 = _interopRequireDefault(_Editor);
26
-
27
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28
 
26
 
29
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
27
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
32
 
30
 
33
 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; }
31
 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; }
34
 
32
 
35
-var PLACEHOLDER = {
36
-  normal: "说点什么吧...",
37
-  default: "说点什么吧..."
38
-};
39
-
40
 var CommentInput = function (_Component) {
33
 var CommentInput = function (_Component) {
41
   _inherits(CommentInput, _Component);
34
   _inherits(CommentInput, _Component);
42
 
35
 
61
 
54
 
62
   _createClass(CommentInput, [{
55
   _createClass(CommentInput, [{
63
     key: "handleChange",
56
     key: "handleChange",
64
-    value: function handleChange(e) {
65
-      this.setState({ value: e.target.value });
57
+    value: function handleChange(value) {
58
+      this.setState({ value: value });
66
     }
59
     }
67
   }, {
60
   }, {
68
     key: "handleChangeFileList",
61
     key: "handleChangeFileList",
76
 
69
 
77
       value += "[" + emojiId + "]";
70
       value += "[" + emojiId + "]";
78
       this.setState({ value: value });
71
       this.setState({ value: value });
72
+      _react2.default.Children.forEach(this.props.content, function (child) {
73
+        // 如果 Editor 的父组件传入了 onChange 事件,则需要将改变之后的值传递给父组件
74
+        if (child.props.onChange) {
75
+          child.props.onChange(value);
76
+        }
77
+      });
79
     }
78
     }
80
   }, {
79
   }, {
81
     key: "handleUpload",
80
     key: "handleUpload",
96
           fileList = _state.fileList;
95
           fileList = _state.fileList;
97
 
96
 
98
       if (fileList.length) {
97
       if (fileList.length) {
98
+        value += "<br/>";
99
         fileList.forEach(function (item) {
99
         fileList.forEach(function (item) {
100
           value += "[" + _constant.OSS_LINK + fileMap[item.uid] + "]";
100
           value += "[" + _constant.OSS_LINK + fileMap[item.uid] + "]";
101
         });
101
         });
109
 
109
 
110
       if (type === "normal") {
110
       if (type === "normal") {
111
         this.props.app.sCreateComment({
111
         this.props.app.sCreateComment({
112
-          type: 1,
113
-          business_id: "1",
114
           content: value
112
           content: value
115
         });
113
         });
116
       } else if (type === "comment") {
114
       } else if (type === "comment") {
129
           return handleToggleInput();
127
           return handleToggleInput();
130
         });
128
         });
131
       }
129
       }
130
+
131
+      _react2.default.Children.forEach(this.props.content, function (child) {
132
+        // 如果 Editor 的父组件传入了 onSubmit 事件,则需要将改变之后的值传递给父组件
133
+        if (child.props.onSubmit) {
134
+          child.props.onSubmit(value);
135
+        }
136
+      });
132
     }
137
     }
133
   }, {
138
   }, {
134
     key: "render",
139
     key: "render",
135
     value: function render() {
140
     value: function render() {
141
+      var _this2 = this;
142
+
136
       var type = this.props.type;
143
       var type = this.props.type;
137
       var _state2 = this.state,
144
       var _state2 = this.state,
138
           value = _state2.value,
145
           value = _state2.value,
139
           fileList = _state2.fileList;
146
           fileList = _state2.fileList;
140
 
147
 
141
 
148
 
149
+      var childrenWithProps = _react2.default.Children.map(this.props.content, function (child) {
150
+        return _react2.default.cloneElement(child, _extends({
151
+          value: value,
152
+          fileList: fileList,
153
+          onChange: _this2.handleChange,
154
+          onSubmit: _this2.handleSubmit,
155
+          onChangeFileList: _this2.handleChangeFileList,
156
+          onChangeEmoji: _this2.handleChangeEmoji,
157
+          onUpload: _this2.handleUpload,
158
+          loading: _this2.props.app.loading.sCreateComment
159
+        }, child.props));
160
+      });
161
+
142
       return _react2.default.createElement(
162
       return _react2.default.createElement(
143
         "div",
163
         "div",
144
         null,
164
         null,
170
         _react2.default.createElement(
190
         _react2.default.createElement(
171
           "div",
191
           "div",
172
           { style: { marginTop: 40 } },
192
           { style: { marginTop: 40 } },
173
-          _react2.default.createElement(_Editor2.default, {
174
-            value: value,
175
-            placeholder: PLACEHOLDER[type] || PLACEHOLDER.default,
176
-            fileList: fileList,
177
-            onChange: this.handleChange,
178
-            onSubmit: this.handleSubmit,
179
-            onChangeFileList: this.handleChangeFileList,
180
-            onChangeEmoji: this.handleChangeEmoji,
181
-            onUpload: this.handleUpload,
182
-            loading: this.props.app.loading.sCreateComment
183
-          })
193
+          childrenWithProps
184
         )
194
         )
185
       );
195
       );
186
     }
196
     }

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


+ 5
- 0
lib/components/CommentList/index.js View File

47
   }
47
   }
48
 
48
 
49
   _createClass(CommentList, [{
49
   _createClass(CommentList, [{
50
+    key: "componentWillMount",
51
+    value: function componentWillMount() {
52
+      this.props.app.sGetComment();
53
+    }
54
+  }, {
50
     key: "render",
55
     key: "render",
51
     value: function render() {
56
     value: function render() {
52
       var _props$app = this.props.app,
57
       var _props$app = this.props.app,

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

1
-{"version":3,"sources":["../../../src/components/CommentList/index.js"],"names":["CommentList","props","state","app","list","page","loading","isNoMoreComment","sGetComment","spinning","Boolean","sCommentFavor","map","item","id","Component","propTypes"],"mappings":";;;;;;;;;;;;;;AAAA;;;;AAEA;;;;AACA;;;;AACA;;;;;;;;;;IAEMA,W;;;AACJ,uBAAYC,KAAZ,EAAmB;AAAA;;AAAA,0HACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa,EAAb;AAFiB;AAGlB;;;;6BAEQ;AAAA,uBAOH,KAAKD,KAAL,CAAWE,GAPR;AAAA,UAELC,IAFK,cAELA,IAFK;AAAA,UAGLC,IAHK,cAGLA,IAHK;AAAA,UAILC,OAJK,cAILA,OAJK;AAAA,UAKLC,eALK,cAKLA,eALK;AAAA,UAMLC,WANK,cAMLA,WANK;;;AASP,UAAMC,WAAWC,QAAQJ,QAAQE,WAAR,IAAuBF,QAAQK,aAAvC,CAAjB;AACA,aACE;AAAA;AAAA;AACE;AAAA;AAAA,YAAM,UAAUF,QAAhB;AACGL,eAAKQ,GAAL,CAAS;AAAA,mBACR,8BAAC,oBAAD,IAAY,SAASC,IAArB,EAA2B,KAAKA,KAAKC,EAArC,EAAyC,WAAWD,KAAKC,EAAzD,GADQ;AAAA,WAAT,CADH;AAKG,WAACP,eAAD,IACC;AAAA;AAAA;AACE,yBAAU,UADZ;AAEE,uBAAS;AAAA,uBAAMC,YAAY,EAAEH,MAAMA,OAAO,CAAf,EAAZ,CAAN;AAAA;AAFX;AAIE;AAAA;AAAA;AAAA;AAAA;AAJF;AANJ;AADF,OADF;AAkBD;;;;EAlCuBU,gB;;AAqC1Bf,YAAYgB,SAAZ,GAAwB,EAAxB;;kBAEe,uBAAQhB,WAAR,C","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport { Spin } from \"antd\";\nimport Comment from \"../../Comment\";\nimport CommentBox from \"../CommentBox\";\nimport \"./index.css\";\n\nclass CommentList extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {};\n  }\n\n  render() {\n    const {\n      list,\n      page,\n      loading,\n      isNoMoreComment,\n      sGetComment\n    } = this.props.app;\n\n    const spinning = Boolean(loading.sGetComment || loading.sCommentFavor);\n    return (\n      <div>\n        <Spin spinning={spinning}>\n          {list.map(item => (\n            <CommentBox content={item} key={item.id} commentId={item.id} />\n          ))}\n\n          {!isNoMoreComment && (\n            <div\n              className=\"showMore\"\n              onClick={() => sGetComment({ page: page + 1 })}\n            >\n              <span>查看更多评论</span>\n            </div>\n          )}\n        </Spin>\n      </div>\n    );\n  }\n}\n\nCommentList.propTypes = {};\n\nexport default Comment(CommentList);\n"]}
1
+{"version":3,"sources":["../../../src/components/CommentList/index.js"],"names":["CommentList","props","state","app","sGetComment","list","page","loading","isNoMoreComment","spinning","Boolean","sCommentFavor","map","item","id","Component","propTypes"],"mappings":";;;;;;;;;;;;;;AAAA;;;;AAEA;;;;AACA;;;;AACA;;;;;;;;;;IAEMA,W;;;AACJ,uBAAYC,KAAZ,EAAmB;AAAA;;AAAA,0HACXA,KADW;;AAEjB,UAAKC,KAAL,GAAa,EAAb;AAFiB;AAGlB;;;;yCAEoB;AACnB,WAAKD,KAAL,CAAWE,GAAX,CAAeC,WAAf;AACD;;;6BAEQ;AAAA,uBAOH,KAAKH,KAAL,CAAWE,GAPR;AAAA,UAELE,IAFK,cAELA,IAFK;AAAA,UAGLC,IAHK,cAGLA,IAHK;AAAA,UAILC,OAJK,cAILA,OAJK;AAAA,UAKLC,eALK,cAKLA,eALK;AAAA,UAMLJ,WANK,cAMLA,WANK;;;AASP,UAAMK,WAAWC,QAAQH,QAAQH,WAAR,IAAuBG,QAAQI,aAAvC,CAAjB;AACA,aACE;AAAA;AAAA;AACE;AAAA;AAAA,YAAM,UAAUF,QAAhB;AACGJ,eAAKO,GAAL,CAAS;AAAA,mBACR,8BAAC,oBAAD,IAAY,SAASC,IAArB,EAA2B,KAAKA,KAAKC,EAArC,EAAyC,WAAWD,KAAKC,EAAzD,GADQ;AAAA,WAAT,CADH;AAKG,WAACN,eAAD,IACC;AAAA;AAAA;AACE,yBAAU,UADZ;AAEE,uBAAS;AAAA,uBAAMJ,YAAY,EAAEE,MAAMA,OAAO,CAAf,EAAZ,CAAN;AAAA;AAFX;AAIE;AAAA;AAAA;AAAA;AAAA;AAJF;AANJ;AADF,OADF;AAkBD;;;;EAtCuBS,gB;;AAyC1Bf,YAAYgB,SAAZ,GAAwB,EAAxB;;kBAEe,uBAAQhB,WAAR,C","file":"index.js","sourcesContent":["import React, { Component } from \"react\";\nimport { Spin } from \"antd\";\nimport Comment from \"../../Comment\";\nimport CommentBox from \"../CommentBox\";\nimport \"./index.css\";\n\nclass CommentList extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {};\n  }\n\n  componentWillMount() {\n    this.props.app.sGetComment();\n  }\n\n  render() {\n    const {\n      list,\n      page,\n      loading,\n      isNoMoreComment,\n      sGetComment\n    } = this.props.app;\n\n    const spinning = Boolean(loading.sGetComment || loading.sCommentFavor);\n    return (\n      <div>\n        <Spin spinning={spinning}>\n          {list.map(item => (\n            <CommentBox content={item} key={item.id} commentId={item.id} />\n          ))}\n\n          {!isNoMoreComment && (\n            <div\n              className=\"showMore\"\n              onClick={() => sGetComment({ page: page + 1 })}\n            >\n              <span>查看更多评论</span>\n            </div>\n          )}\n        </Spin>\n      </div>\n    );\n  }\n}\n\nCommentList.propTypes = {};\n\nexport default Comment(CommentList);\n"]}

+ 2
- 0
lib/components/Editor/Emoji.js View File

25
 // 每页 20  5*4
25
 // 每页 20  5*4
26
 // 共 20 * 3 = 60 (实际是 54)
26
 // 共 20 * 3 = 60 (实际是 54)
27
 
27
 
28
+// class Emoji
29
+
28
 var Emoji = function Emoji(_ref) {
30
 var Emoji = function Emoji(_ref) {
29
   var _onClick = _ref.onClick;
31
   var _onClick = _ref.onClick;
30
 
32
 

+ 1
- 1
lib/components/Editor/Emoji.js.map View File

1
-{"version":3,"sources":["../../../src/components/Editor/Emoji.js"],"names":["Emoji","onClick","content","i","emoji","length","push","map","item","index","value","prefixUrl","ext","title","display"],"mappings":";;;;;;;;;;;;AAAA;;;;AAEA;;;;AACA;;;;AACA;AACA;;AAEA,IAAMA,QAAQ,SAARA,KAAQ,OAAiB;AAAA,MAAdC,QAAc,QAAdA,OAAc;;AAC7B,MAAMC,UAAU,CAAC,EAAD,EAAK,EAAL,EAAS,EAAT,CAAhB;;AAEA,OAAK,IAAIC,IAAI,CAAb,EAAgBA,IAAIC,gBAAMC,MAA1B,EAAkCF,GAAlC,EAAuC;AACrC,QAAIA,IAAI,EAAR,EAAY;AACVD,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD,KAFD,MAEO,IAAIA,IAAI,EAAR,EAAY;AACjBD,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD,KAFM,MAEA,IAAIA,IAAIC,gBAAMC,MAAd,EAAsB;AAC3BH,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD;AACF;AACD,SACE;AAAA;AAAA;AACE;AAAA;AAAA;AACGD,cAAQ,CAAR,EAAWK,GAAX,CAAe,UAACC,IAAD,EAAOC,KAAP;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKD,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH,KADF;AAcE;AAAA;AAAA;AACGX,cAAQ,CAAR,EAAWK,GAAX,CAAe,UAACC,IAAD,EAAOC,KAAP;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKD,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH,KAdF;AA2BE;AAAA;AAAA;AACGX,cAAQ,CAAR,EAAWK,GAAX,CAAe;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKC,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH;AA3BF,GADF;AA2CD,CAvDD;;kBAyDeb,K","file":"Emoji.js","sourcesContent":["import React from \"react\";\nimport { Carousel } from \"antd\";\nimport emoji, { prefixUrl, ext } from \"../../emoji\";\nimport \"./Emoji.css\";\n// 每页 20  5*4\n// 共 20 * 3 = 60 (实际是 54)\n\nconst Emoji = ({ onClick }) => {\n  const content = [[], [], []];\n\n  for (let i = 0; i < emoji.length; i++) {\n    if (i < 20) {\n      content[0].push(emoji[i]);\n    } else if (i < 40) {\n      content[1].push(emoji[i]);\n    } else if (i < emoji.length) {\n      content[2].push(emoji[i]);\n    }\n  }\n  return (\n    <Carousel>\n      <div>\n        {content[0].map((item, index) => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n      <div>\n        {content[1].map((item, index) => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n      <div>\n        {content[2].map(item => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n    </Carousel>\n  );\n};\n\nexport default Emoji;\n"]}
1
+{"version":3,"sources":["../../../src/components/Editor/Emoji.js"],"names":["Emoji","onClick","content","i","emoji","length","push","map","item","index","value","prefixUrl","ext","title","display"],"mappings":";;;;;;;;;;;;AAAA;;;;AAEA;;;;AACA;;;;AACA;AACA;;AAEA;;AAEA,IAAMA,QAAQ,SAARA,KAAQ,OAAiB;AAAA,MAAdC,QAAc,QAAdA,OAAc;;AAC7B,MAAMC,UAAU,CAAC,EAAD,EAAK,EAAL,EAAS,EAAT,CAAhB;;AAEA,OAAK,IAAIC,IAAI,CAAb,EAAgBA,IAAIC,gBAAMC,MAA1B,EAAkCF,GAAlC,EAAuC;AACrC,QAAIA,IAAI,EAAR,EAAY;AACVD,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD,KAFD,MAEO,IAAIA,IAAI,EAAR,EAAY;AACjBD,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD,KAFM,MAEA,IAAIA,IAAIC,gBAAMC,MAAd,EAAsB;AAC3BH,cAAQ,CAAR,EAAWI,IAAX,CAAgBF,gBAAMD,CAAN,CAAhB;AACD;AACF;AACD,SACE;AAAA;AAAA;AACE;AAAA;AAAA;AACGD,cAAQ,CAAR,EAAWK,GAAX,CAAe,UAACC,IAAD,EAAOC,KAAP;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKD,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH,KADF;AAcE;AAAA;AAAA;AACGX,cAAQ,CAAR,EAAWK,GAAX,CAAe,UAACC,IAAD,EAAOC,KAAP;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKD,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH,KAdF;AA2BE;AAAA;AAAA;AACGX,cAAQ,CAAR,EAAWK,GAAX,CAAe;AAAA,eACd;AAAA;AAAA,YAAK,WAAU,MAAf,EAAsB,KAAKC,KAAKE,KAAhC;AACE,kDAAM,WAAU,QAAhB,GADF;AAEE;AACE,sBAAQC,gBAAR,GAAoBH,KAAKE,KAAzB,SAAkCE,UADpC;AAEE,iBAAKJ,KAAKK,KAFZ;AAGE,mBAAO,EAAEC,SAAS,cAAX,EAHT;AAIE,qBAAS;AAAA,qBAAMb,SAAQO,KAAKK,KAAb,CAAN;AAAA;AAJX;AAFF,SADc;AAAA,OAAf;AADH;AA3BF,GADF;AA2CD,CAvDD;;kBAyDeb,K","file":"Emoji.js","sourcesContent":["import React from \"react\";\nimport { Carousel } from \"antd\";\nimport emoji, { prefixUrl, ext } from \"../../emoji\";\nimport \"./Emoji.css\";\n// 每页 20  5*4\n// 共 20 * 3 = 60 (实际是 54)\n\n// class Emoji\n\nconst Emoji = ({ onClick }) => {\n  const content = [[], [], []];\n\n  for (let i = 0; i < emoji.length; i++) {\n    if (i < 20) {\n      content[0].push(emoji[i]);\n    } else if (i < 40) {\n      content[1].push(emoji[i]);\n    } else if (i < emoji.length) {\n      content[2].push(emoji[i]);\n    }\n  }\n  return (\n    <Carousel>\n      <div>\n        {content[0].map((item, index) => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n      <div>\n        {content[1].map((item, index) => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n      <div>\n        {content[2].map(item => (\n          <div className=\"item\" key={item.value}>\n            <span className=\"helper\" />\n            <img\n              src={`${prefixUrl}${item.value}.${ext}`}\n              alt={item.title}\n              style={{ display: \"inline-block\" }}\n              onClick={() => onClick(item.title)}\n            />\n          </div>\n        ))}\n      </div>\n    </Carousel>\n  );\n};\n\nexport default Emoji;\n"]}

+ 54
- 22
lib/components/Editor/index.js View File

20
 
20
 
21
 var _input2 = _interopRequireDefault(_input);
21
 var _input2 = _interopRequireDefault(_input);
22
 
22
 
23
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
24
+
23
 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
25
 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; }; }();
24
 
26
 
25
 require("antd/es/button/style/css");
27
 require("antd/es/button/style/css");
34
 
36
 
35
 var _react2 = _interopRequireDefault(_react);
37
 var _react2 = _interopRequireDefault(_react);
36
 
38
 
39
+var _propTypes = require("prop-types");
40
+
41
+var _propTypes2 = _interopRequireDefault(_propTypes);
42
+
37
 var _constant = require("../../constant");
43
 var _constant = require("../../constant");
38
 
44
 
39
 var _Upload = require("./Upload");
45
 var _Upload = require("./Upload");
52
 
58
 
53
 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; }
59
 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; }
54
 
60
 
55
-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; } // https://github.com/lovasoa/react-contenteditable/blob/master/src/react-contenteditable.js
56
-
57
-// import styles from "./index.less";
58
-
61
+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; }
59
 
62
 
60
 var TextArea = _input2.default.TextArea;
63
 var TextArea = _input2.default.TextArea;
64
+// 设置 Editor 组件的默认值
65
+// 不能在 Editor.defaultProps 中设置
66
+// 因为 Editor 在 ComponentInput 中调用
67
+// 在 ComponentInput 中,需要使用 Editor 的 props 覆盖 ComponentInput 传入的 props
68
+
69
+var EditorDefaultProps = {
70
+  rows: 5,
71
+  placeholder: "说点什么吧...",
72
+  showEmoji: true,
73
+  showUpload: true,
74
+  submitText: "发表",
75
+  onChange: function onChange() {}
76
+};
61
 
77
 
62
 var Editor = function (_React$Component) {
78
 var Editor = function (_React$Component) {
63
   _inherits(Editor, _React$Component);
79
   _inherits(Editor, _React$Component);
97
     value: function render() {
113
     value: function render() {
98
       var _this2 = this;
114
       var _this2 = this;
99
 
115
 
100
-      var _props = this.props,
101
-          value = _props.value,
102
-          onChange = _props.onChange,
103
-          placeholder = _props.placeholder,
104
-          fileList = _props.fileList,
105
-          onChangeFileList = _props.onChangeFileList,
106
-          onUpload = _props.onUpload;
116
+      var props = _extends({}, EditorDefaultProps, this.props);
117
+      var value = props.value,
118
+          _onChange = props.onChange,
119
+          onSubmit = props.onSubmit,
120
+          loading = props.loading,
121
+          placeholder = props.placeholder,
122
+          fileList = props.fileList,
123
+          onChangeFileList = props.onChangeFileList,
124
+          rows = props.rows,
125
+          onUpload = props.onUpload,
126
+          showEmoji = props.showEmoji,
127
+          showUpload = props.showUpload,
128
+          submitText = props.submitText;
129
+
107
 
130
 
108
       return _react2.default.createElement(
131
       return _react2.default.createElement(
109
         "div",
132
         "div",
110
         { className: "editor" },
133
         { className: "editor" },
111
         _react2.default.createElement(TextArea, {
134
         _react2.default.createElement(TextArea, {
112
           value: value,
135
           value: value,
113
-          onChange: onChange,
114
-          rows: 5,
136
+          onChange: function onChange(e) {
137
+            return _onChange(e.target.value);
138
+          },
139
+          rows: rows,
115
           placeholder: placeholder
140
           placeholder: placeholder
116
         }),
141
         }),
117
         _react2.default.createElement(
142
         _react2.default.createElement(
120
           _react2.default.createElement(
145
           _react2.default.createElement(
121
             "div",
146
             "div",
122
             { style: { float: "left", margin: "8px 11px" } },
147
             { style: { float: "left", margin: "8px 11px" } },
123
-            _react2.default.createElement(
148
+            showEmoji && _react2.default.createElement(
124
               _popover2.default,
149
               _popover2.default,
125
               {
150
               {
126
                 trigger: "click",
151
                 trigger: "click",
135
               },
160
               },
136
               _react2.default.createElement(_icon2.default, { type: "smile-o", className: "icon" })
161
               _react2.default.createElement(_icon2.default, { type: "smile-o", className: "icon" })
137
             ),
162
             ),
138
-            _react2.default.createElement(
163
+            showUpload && _react2.default.createElement(
139
               _popover2.default,
164
               _popover2.default,
140
               {
165
               {
141
                 visible: this.state.showUpload,
166
                 visible: this.state.showUpload,
142
                 overlayStyle: { zIndex: 999 },
167
                 overlayStyle: { zIndex: 999 },
143
                 content: _react2.default.createElement(
168
                 content: _react2.default.createElement(
144
                   "div",
169
                   "div",
145
-                  { style: { width: 112 * _constant.MAX_UPLOAD_NUMBER, minHeight: 100 } },
170
+                  {
171
+                    style: { width: 112 * _constant.MAX_UPLOAD_NUMBER, minHeight: 100 }
172
+                  },
146
                   _react2.default.createElement(_Upload2.default, {
173
                   _react2.default.createElement(_Upload2.default, {
147
                     onChangeFileList: onChangeFileList,
174
                     onChangeFileList: onChangeFileList,
148
                     onUpload: onUpload,
175
                     onUpload: onUpload,
193
             { style: { float: "right", margin: "5px 11px" } },
220
             { style: { float: "right", margin: "5px 11px" } },
194
             _react2.default.createElement(
221
             _react2.default.createElement(
195
               _button2.default,
222
               _button2.default,
196
-              {
197
-                onClick: this.props.onSubmit,
198
-                type: "primary",
199
-                loading: this.props.loading
200
-              },
201
-              "\u53D1\u8868"
223
+              { onClick: onSubmit, type: "primary", loading: loading },
224
+              submitText
202
             )
225
             )
203
           )
226
           )
204
         )
227
         )
209
   return Editor;
232
   return Editor;
210
 }(_react2.default.Component);
233
 }(_react2.default.Component);
211
 
234
 
235
+Editor.propTypes = {
236
+  rows: _propTypes2.default.number,
237
+  placeholder: _propTypes2.default.string,
238
+  showEmoji: _propTypes2.default.bool,
239
+  showUpload: _propTypes2.default.bool,
240
+  submitText: _propTypes2.default.string,
241
+  onChange: _propTypes2.default.func
242
+};
243
+
212
 exports.default = Editor;
244
 exports.default = Editor;
213
 //# sourceMappingURL=index.js.map
245
 //# sourceMappingURL=index.js.map

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


+ 0
- 3
lib/constant.js View File

3
 Object.defineProperty(exports, "__esModule", {
3
 Object.defineProperty(exports, "__esModule", {
4
   value: true
4
   value: true
5
 });
5
 });
6
-// export const URL = "http://121.41.20.11:8082/v1";
7
-var URL = exports.URL = "http://api.links123.net/comment/v1";
8
-
9
 var ERROR_DEFAULT = exports.ERROR_DEFAULT = "出错了!";
6
 var ERROR_DEFAULT = exports.ERROR_DEFAULT = "出错了!";
10
 
7
 
11
 var LIMIT = exports.LIMIT = 10; // 默认 limit
8
 var LIMIT = exports.LIMIT = 10; // 默认 limit

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

1
-{"version":3,"sources":["../src/constant.js"],"names":["URL","ERROR_DEFAULT","LIMIT","OSS_ENDPOINT","OSS_BUCKET","DRIVER_LICENSE_PATH","OSS_LINK","MAX_UPLOAD_NUMBER","REGEXP"],"mappings":";;;;;AAAA;AACO,IAAMA,oBAAM,oCAAZ;;AAEA,IAAMC,wCAAgB,MAAtB;;AAEA,IAAMC,wBAAQ,EAAd,C,CAAkB;;AAElB,IAAMC,sCAAe,6BAArB;AACA,IAAMC,kCAAa,eAAnB;AACA,IAAMC,oDAAsB,UAA5B;;AAEA,IAAMC,8BAAW,kDAAjB;;AAEA,IAAMC,gDAAoB,CAA1B;;AAEA,IAAMC,0BAAS,UAAf","file":"constant.js","sourcesContent":["// export const URL = \"http://121.41.20.11:8082/v1\";\nexport const URL = \"http://api.links123.net/comment/v1\";\n\nexport const ERROR_DEFAULT = \"出错了!\";\n\nexport const LIMIT = 10; // 默认 limit\n\nexport const OSS_ENDPOINT = \"oss-cn-beijing.aliyuncs.com\";\nexport const OSS_BUCKET = \"links-comment\";\nexport const DRIVER_LICENSE_PATH = \"/comment\";\n\nexport const OSS_LINK = \"http://links-comment.oss-cn-beijing.aliyuncs.com\";\n\nexport const MAX_UPLOAD_NUMBER = 4;\n\nexport const REGEXP = /\\[.+?\\]/g;\n"]}
1
+{"version":3,"sources":["../src/constant.js"],"names":["ERROR_DEFAULT","LIMIT","OSS_ENDPOINT","OSS_BUCKET","DRIVER_LICENSE_PATH","OSS_LINK","MAX_UPLOAD_NUMBER","REGEXP"],"mappings":";;;;;AAAO,IAAMA,wCAAgB,MAAtB;;AAEA,IAAMC,wBAAQ,EAAd,C,CAAkB;;AAElB,IAAMC,sCAAe,6BAArB;AACA,IAAMC,kCAAa,eAAnB;AACA,IAAMC,oDAAsB,UAA5B;;AAEA,IAAMC,8BAAW,kDAAjB;;AAEA,IAAMC,gDAAoB,CAA1B;;AAEA,IAAMC,0BAAS,UAAf","file":"constant.js","sourcesContent":["export const ERROR_DEFAULT = \"出错了!\";\n\nexport const LIMIT = 10; // 默认 limit\n\nexport const OSS_ENDPOINT = \"oss-cn-beijing.aliyuncs.com\";\nexport const OSS_BUCKET = \"links-comment\";\nexport const DRIVER_LICENSE_PATH = \"/comment\";\n\nexport const OSS_LINK = \"http://links-comment.oss-cn-beijing.aliyuncs.com\";\n\nexport const MAX_UPLOAD_NUMBER = 4;\n\nexport const REGEXP = /\\[.+?\\]/g;\n"]}

+ 19
- 1
lib/index.js View File

18
 
18
 
19
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
 
20
 
21
-_reactDom2.default.render(_react2.default.createElement(_App2.default, null), document.getElementById("root-comment"));
21
+var props = {
22
+  type: 1,
23
+  businessId: "1",
24
+  API: "http://api.links123.net/comment/v1",
25
+  showList: false
26
+};
27
+
28
+var editorProps = {
29
+  showEmoji: true,
30
+  placeholder: "说点什么吧",
31
+  rows: 5
32
+  // onSubmit={v => console.log()} // TODO...
33
+};
34
+
35
+_reactDom2.default.render(_react2.default.createElement(
36
+  _App2.default,
37
+  props,
38
+  _react2.default.createElement(_App.Editor, editorProps)
39
+), document.getElementById("root-comment"));
22
 (0, _registerServiceWorker2.default)();
40
 (0, _registerServiceWorker2.default)();
23
 //# sourceMappingURL=index.js.map
41
 //# sourceMappingURL=index.js.map

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

1
-{"version":3,"sources":["../src/index.js"],"names":["ReactDOM","render","document","getElementById"],"mappings":";;AAAA;;;;AACA;;;;AACA;;;;AACA;;;;;;AAEAA,mBAASC,MAAT,CAAgB,8BAAC,aAAD,OAAhB,EAAyBC,SAASC,cAAT,CAAwB,cAAxB,CAAzB;AACA","file":"index.js","sourcesContent":["import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport App from \"./App\";\nimport registerServiceWorker from \"./registerServiceWorker\";\n\nReactDOM.render(<App />, document.getElementById(\"root-comment\"));\nregisterServiceWorker();\n"]}
1
+{"version":3,"sources":["../src/index.js"],"names":["props","type","businessId","API","showList","editorProps","showEmoji","placeholder","rows","ReactDOM","render","document","getElementById"],"mappings":";;AAAA;;;;AACA;;;;AACA;;;;AACA;;;;;;AAEA,IAAMA,QAAQ;AACZC,QAAM,CADM;AAEZC,cAAY,GAFA;AAGZC,OAAK,oCAHO;AAIZC,YAAU;AAJE,CAAd;;AAOA,IAAMC,cAAc;AAClBC,aAAW,IADO;AAElBC,eAAa,OAFK;AAGlBC,QAAM;AACN;AAJkB,CAApB;;AAOAC,mBAASC,MAAT,CACE;AAAC,eAAD;AAASV,OAAT;AACE,gCAAC,WAAD,EAAYK,WAAZ;AADF,CADF,EAIEM,SAASC,cAAT,CAAwB,cAAxB,CAJF;AAMA","file":"index.js","sourcesContent":["import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport App, { Editor } from \"./App\";\nimport registerServiceWorker from \"./registerServiceWorker\";\n\nconst props = {\n  type: 1,\n  businessId: \"1\",\n  API: \"http://api.links123.net/comment/v1\",\n  showList: false\n};\n\nconst editorProps = {\n  showEmoji: true,\n  placeholder: \"说点什么吧\",\n  rows: 5\n  // onSubmit={v => console.log()} // TODO...\n};\n\nReactDOM.render(\n  <App {...props}>\n    <Editor {...editorProps} />\n  </App>,\n  document.getElementById(\"root-comment\")\n);\nregisterServiceWorker();\n"]}

+ 21
- 0
lib/lang/index.js View File

1
+"use strict";
2
+
3
+Object.defineProperty(exports, "__esModule", {
4
+  value: true
5
+});
6
+// 语言包
7
+// 英文短语和中文提示的对应
8
+var data = {
9
+  "auth failed": "请先登录",
10
+  "create comment failed": "创建评论失败",
11
+  "comment favor failed": "评论点赞失败",
12
+  "delete comment favor failed": "评论取消点赞失败",
13
+  "get comments failed": "获取评论列表失败",
14
+  "create reply failed": "创建回复失败",
15
+  "reply favor failed": "回复点赞失败",
16
+  "delete reply favor failed": "删除回复点赞失败",
17
+  "get replies failed": "获取回复列表失败"
18
+};
19
+
20
+exports.default = data;
21
+//# sourceMappingURL=index.js.map

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

1
+{"version":3,"sources":["../../src/lang/index.js"],"names":["data"],"mappings":";;;;;AAAA;AACA;AACA,IAAMA,OAAO;AACX,iBAAe,MADJ;AAEX,2BAAyB,QAFd;AAGX,0BAAwB,QAHb;AAIX,iCAA+B,UAJpB;AAKX,yBAAuB,UALZ;AAMX,yBAAuB,QANZ;AAOX,wBAAsB,QAPX;AAQX,+BAA6B,UARlB;AASX,wBAAsB;AATX,CAAb;;kBAYeA,I","file":"index.js","sourcesContent":["// 语言包\n// 英文短语和中文提示的对应\nconst data = {\n  \"auth failed\": \"请先登录\",\n  \"create comment failed\": \"创建评论失败\",\n  \"comment favor failed\": \"评论点赞失败\",\n  \"delete comment favor failed\": \"评论取消点赞失败\",\n  \"get comments failed\": \"获取评论列表失败\",\n  \"create reply failed\": \"创建回复失败\",\n  \"reply favor failed\": \"回复点赞失败\",\n  \"delete reply favor failed\": \"删除回复点赞失败\",\n  \"get replies failed\": \"获取回复列表失败\"\n};\n\nexport default data;\n"]}

+ 3
- 2
package.json View File

1
 {
1
 {
2
   "name": "comment",
2
   "name": "comment",
3
-  "version": "0.0.1",
3
+  "version": "0.1.0",
4
   "main": "lib/App.js",
4
   "main": "lib/App.js",
5
   "description": "通用评论",
5
   "description": "通用评论",
6
   "keywords": [
6
   "keywords": [
17
     "antd": "^3.6.6",
17
     "antd": "^3.6.6",
18
     "axios": "^0.18.0",
18
     "axios": "^0.18.0",
19
     "dayjs": "^1.7.2",
19
     "dayjs": "^1.7.2",
20
+    "prop-types": "^15.6.2",
20
     "react": "^16.4.1",
21
     "react": "^16.4.1",
21
     "react-dom": "^16.4.1",
22
     "react-dom": "^16.4.1",
22
     "react-scripts": "1.1.4",
23
     "react-scripts": "1.1.4",
30
   },
31
   },
31
   "scripts": {
32
   "scripts": {
32
     "precommit": "lint-staged",
33
     "precommit": "lint-staged",
33
-    "prettier": "prettier --write src/**/*.{js,jsx,json,css,less}",
34
+    "prettier": "prettier --trailing-comma --write 'src/**/*.{js,jsx,json,css,less}'",
34
     "start": "react-app-rewired start",
35
     "start": "react-app-rewired start",
35
     "build": "react-app-rewired build",
36
     "build": "react-app-rewired build",
36
     "test": "react-app-rewired test --env=jsdom",
37
     "test": "react-app-rewired test --env=jsdom",

+ 50
- 30
src/App.js View File

1
 import React, { Component } from "react";
1
 import React, { Component } from "react";
2
+import PropTypes from "prop-types";
2
 import { message } from "antd";
3
 import { message } from "antd";
3
 import axios from "./axios";
4
 import axios from "./axios";
4
-import { URL, ERROR_DEFAULT, LIMIT } from "./constant";
5
+import { ERROR_DEFAULT, LIMIT } from "./constant";
5
 import { CommentContext } from "./Comment";
6
 import { CommentContext } from "./Comment";
6
 import { isFunction } from "./helper";
7
 import { isFunction } from "./helper";
7
 import CommentInput from "./components/CommentInput";
8
 import CommentInput from "./components/CommentInput";
8
 import CommentList from "./components/CommentList";
9
 import CommentList from "./components/CommentList";
9
-// import * as mock from "./mock";
10
+import Editor from "./components/Editor";
10
 import "./App.css";
11
 import "./App.css";
11
 
12
 
12
 class App extends Component {
13
 class App extends Component {
34
     this.sOssSts = this.sOssSts.bind(this);
35
     this.sOssSts = this.sOssSts.bind(this);
35
   }
36
   }
36
 
37
 
37
-  componentDidMount() {
38
-    this.sGetComment();
39
-  }
38
+  componentDidMount() {}
40
 
39
 
41
   /**
40
   /**
42
    * 改变 loading 状态
41
    * 改变 loading 状态
52
   /**
51
   /**
53
    * 获取评论列表
52
    * 获取评论列表
54
    */
53
    */
55
-  sGetComment({ type = 1, businessId = 1, page = 1 } = {}) {
54
+  sGetComment({ page = 1 } = {}) {
56
     this.handleChangeLoading("sGetComment", true);
55
     this.handleChangeLoading("sGetComment", true);
57
-    // 测试数据列表
58
-    // const { comments } = mock;
59
-    // this.setState({
60
-    //   list: comments.list,
61
-    //   page: 1,
62
-    //   total: 100
63
-    // });
64
-    // this.handleChangeLoading("sGetComment", false);
65
-    // return;
56
+    const { API, type, businessId } = this.props;
66
     axios
57
     axios
67
       .get(
58
       .get(
68
-        `${URL}/comments?type=${type}&business_id=${businessId}&page=${page}&limit=${LIMIT}`
59
+        `${API}/comments?type=${type}&business_id=${businessId}&page=${page}&limit=${LIMIT}`
69
       )
60
       )
70
       .then(response => {
61
       .then(response => {
71
         const { list, page, total } = response.data;
62
         const { list, page, total } = response.data;
106
    */
97
    */
107
   sGetReply({ commentId, page = 1 } = {}) {
98
   sGetReply({ commentId, page = 1 } = {}) {
108
     this.handleChangeLoading("sGetReply", true);
99
     this.handleChangeLoading("sGetReply", true);
100
+    const { API } = this.props;
109
     axios
101
     axios
110
-      .get(`${URL}/replies?comment_id=${commentId}&page=${page}&limit=${LIMIT}`)
102
+      .get(`${API}/replies?comment_id=${commentId}&page=${page}&limit=${LIMIT}`)
111
       .then(response => {
103
       .then(response => {
112
         const { list: replies } = response.data;
104
         const { list: replies } = response.data;
113
         if (!replies) {
105
         if (!replies) {
147
 
139
 
148
   /**
140
   /**
149
    * 添加评论
141
    * 添加评论
150
-   * @param {object} data { type, business_id, content }
142
+   * @param {string} content comment content
151
    */
143
    */
152
-  sCreateComment(data) {
153
-    if (!data.content) return message.error("评论内容不能为空 ");
144
+  sCreateComment(content) {
145
+    if (!content) return message.error("评论内容不能为空 ");
154
     this.handleChangeLoading("sCreateComment", true);
146
     this.handleChangeLoading("sCreateComment", true);
155
-    axios(`${URL}/comments`, {
147
+    const { API, type, businessId } = this.props;
148
+    axios(`${API}/comments`, {
156
       method: "post",
149
       method: "post",
157
-      data,
150
+      data: {
151
+        type,
152
+        business_id: businessId,
153
+        content
154
+      },
158
       withCredentials: true
155
       withCredentials: true
159
     })
156
     })
160
       .then(response => {
157
       .then(response => {
189
   sCreateReply(data, cb) {
186
   sCreateReply(data, cb) {
190
     if (!data.content) return message.error("回复内容不能为空 ");
187
     if (!data.content) return message.error("回复内容不能为空 ");
191
     this.handleChangeLoading("sCreateReply", true);
188
     this.handleChangeLoading("sCreateReply", true);
192
-    axios(`${URL}/replies`, {
189
+    const { API } = this.props;
190
+    axios(`${API}/replies`, {
193
       method: "post",
191
       method: "post",
194
       data,
192
       data,
195
       withCredentials: true
193
       withCredentials: true
196
     })
194
     })
197
       .then(response => {
195
       .then(response => {
198
-        // console.log("response: ", response.data);
199
         // // 将该条数据插入到 list 中
196
         // // 将该条数据插入到 list 中
200
         // const list = this.state.list.map(item => {
197
         // const list = this.state.list.map(item => {
201
         //   if (item.id === data.comment_id) {
198
         //   if (item.id === data.comment_id) {
229
    */
226
    */
230
   sCommentFavor(commentId, favored) {
227
   sCommentFavor(commentId, favored) {
231
     this.handleChangeLoading("sCommentFavor", true);
228
     this.handleChangeLoading("sCommentFavor", true);
232
-    axios(`${URL}/comments/${commentId}/favor`, {
229
+    const { API } = this.props;
230
+    axios(`${API}/comments/${commentId}/favor`, {
233
       method: favored ? "delete" : "put",
231
       method: favored ? "delete" : "put",
234
       withCredentials: true
232
       withCredentials: true
235
     })
233
     })
262
    */
260
    */
263
   sOssSts() {
261
   sOssSts() {
264
     this.handleChangeLoading("sOssSts", true);
262
     this.handleChangeLoading("sOssSts", true);
263
+    const { API } = this.props;
265
     axios
264
     axios
266
-      .get(`${URL}/oss/sts`)
265
+      .get(`${API}/oss/sts`)
267
       .then(response => {
266
       .then(response => {
268
         this.setState({ oss: { ...response.data } });
267
         this.setState({ oss: { ...response.data } });
269
       })
268
       })
283
     // 添加到 Context 的数据
282
     // 添加到 Context 的数据
284
     const value = {
283
     const value = {
285
       ...this.state,
284
       ...this.state,
285
+      ...this.props,
286
       sCreateComment: this.sCreateComment,
286
       sCreateComment: this.sCreateComment,
287
       sGetComment: this.sGetComment,
287
       sGetComment: this.sGetComment,
288
       sCommentFavor: this.sCommentFavor,
288
       sCommentFavor: this.sCommentFavor,
294
     return (
294
     return (
295
       <CommentContext.Provider value={value}>
295
       <CommentContext.Provider value={value}>
296
         <div className="comment">
296
         <div className="comment">
297
-          <CommentInput />
298
-          <div style={{ marginTop: 20 }}>
299
-            <CommentList />
300
-          </div>
297
+          {this.props.showEditor && (
298
+            <CommentInput content={this.props.children} />
299
+          )}
300
+          {this.props.showList && (
301
+            <div style={{ marginTop: 20 }}>
302
+              <CommentList />
303
+            </div>
304
+          )}
301
         </div>
305
         </div>
302
       </CommentContext.Provider>
306
       </CommentContext.Provider>
303
     );
307
     );
304
   }
308
   }
305
 }
309
 }
306
 
310
 
311
+App.propTypes = {
312
+  type: PropTypes.number.isRequired, // 评论的 type
313
+  businessId: PropTypes.string.isRequired, // 评论的 business_id
314
+  API: PropTypes.string, // 评论的 API 前缀
315
+  showList: PropTypes.bool, // 是否显示评论列表
316
+  showEditor: PropTypes.bool // 是否显示评论输入框
317
+};
318
+
319
+App.defaultProps = {
320
+  API: "http://api.links123.net/comment/v1",
321
+  showList: true,
322
+  showEditor: true
323
+};
324
+
325
+export { Editor };
326
+
307
 export default App;
327
 export default App;

+ 12
- 0
src/CHANGELOG.md View File

1
+# CHANGELOG
2
+
3
+
4
+## 0.1.0
5
+
6
+- [x] 不兼容更新。
7
+- [x] 添加了很多 `Props`
8
+- [x] 组件导出为 `Comment` 和 `Editor`
9
+
10
+
11
+
12
+

+ 31
- 23
src/components/CommentInput/index.js View File

2
 import PropTypes from "prop-types";
2
 import PropTypes from "prop-types";
3
 import { OSS_LINK } from "../../constant";
3
 import { OSS_LINK } from "../../constant";
4
 import Comment from "../../Comment";
4
 import Comment from "../../Comment";
5
-import Editor from "../Editor";
6
-
7
-const PLACEHOLDER = {
8
-  normal: "说点什么吧...",
9
-  default: "说点什么吧..."
10
-};
11
 
5
 
12
 class CommentInput extends Component {
6
 class CommentInput extends Component {
13
   constructor(props) {
7
   constructor(props) {
25
     this.handleUpload = this.handleUpload.bind(this);
19
     this.handleUpload = this.handleUpload.bind(this);
26
   }
20
   }
27
 
21
 
28
-  handleChange(e) {
29
-    this.setState({ value: e.target.value });
22
+  handleChange(value) {
23
+    this.setState({ value });
30
   }
24
   }
31
 
25
 
32
   handleChangeFileList(fileList) {
26
   handleChangeFileList(fileList) {
37
     let { value } = this.state;
31
     let { value } = this.state;
38
     value += `[${emojiId}]`;
32
     value += `[${emojiId}]`;
39
     this.setState({ value });
33
     this.setState({ value });
34
+    React.Children.forEach(this.props.content, child => {
35
+      // 如果 Editor 的父组件传入了 onChange 事件,则需要将改变之后的值传递给父组件
36
+      if (child.props.onChange) {
37
+        child.props.onChange(value);
38
+      }
39
+    });
40
   }
40
   }
41
 
41
 
42
   handleUpload({ uid, path }) {
42
   handleUpload({ uid, path }) {
48
   handleSubmit() {
48
   handleSubmit() {
49
     let { value, fileMap, fileList } = this.state;
49
     let { value, fileMap, fileList } = this.state;
50
     if (fileList.length) {
50
     if (fileList.length) {
51
+      value += "<br/>";
51
       fileList.forEach(item => {
52
       fileList.forEach(item => {
52
         value += `[${OSS_LINK}${fileMap[item.uid]}]`;
53
         value += `[${OSS_LINK}${fileMap[item.uid]}]`;
53
       });
54
       });
56
     const { type, commentId, replyId, handleToggleInput } = this.props;
57
     const { type, commentId, replyId, handleToggleInput } = this.props;
57
     if (type === "normal") {
58
     if (type === "normal") {
58
       this.props.app.sCreateComment({
59
       this.props.app.sCreateComment({
59
-        type: 1,
60
-        business_id: "1",
61
         content: value
60
         content: value
62
       });
61
       });
63
     } else if (type === "comment") {
62
     } else if (type === "comment") {
78
         () => handleToggleInput()
77
         () => handleToggleInput()
79
       );
78
       );
80
     }
79
     }
80
+
81
+    React.Children.forEach(this.props.content, child => {
82
+      // 如果 Editor 的父组件传入了 onSubmit 事件,则需要将改变之后的值传递给父组件
83
+      if (child.props.onSubmit) {
84
+        child.props.onSubmit(value);
85
+      }
86
+    });
81
   }
87
   }
82
 
88
 
83
   render() {
89
   render() {
84
     const { type } = this.props;
90
     const { type } = this.props;
85
     const { value, fileList } = this.state;
91
     const { value, fileList } = this.state;
86
 
92
 
93
+    const childrenWithProps = React.Children.map(this.props.content, child => {
94
+      return React.cloneElement(child, {
95
+        value: value,
96
+        fileList: fileList,
97
+        onChange: this.handleChange,
98
+        onSubmit: this.handleSubmit,
99
+        onChangeFileList: this.handleChangeFileList,
100
+        onChangeEmoji: this.handleChangeEmoji,
101
+        onUpload: this.handleUpload,
102
+        loading: this.props.app.loading.sCreateComment,
103
+        ...child.props
104
+      });
105
+    });
106
+
87
     return (
107
     return (
88
       <div>
108
       <div>
89
         {type === "normal" ? (
109
         {type === "normal" ? (
105
             </span>
125
             </span>
106
           </div>
126
           </div>
107
         ) : null}
127
         ) : null}
108
-        <div style={{ marginTop: 40 }}>
109
-          <Editor
110
-            value={value}
111
-            placeholder={PLACEHOLDER[type] || PLACEHOLDER.default}
112
-            fileList={fileList}
113
-            onChange={this.handleChange}
114
-            onSubmit={this.handleSubmit}
115
-            onChangeFileList={this.handleChangeFileList}
116
-            onChangeEmoji={this.handleChangeEmoji}
117
-            onUpload={this.handleUpload}
118
-            loading={this.props.app.loading.sCreateComment}
119
-          />
120
-        </div>
128
+        <div style={{ marginTop: 40 }}>{childrenWithProps}</div>
121
       </div>
129
       </div>
122
     );
130
     );
123
   }
131
   }

+ 4
- 0
src/components/CommentList/index.js View File

10
     this.state = {};
10
     this.state = {};
11
   }
11
   }
12
 
12
 
13
+  componentWillMount() {
14
+    this.props.app.sGetComment();
15
+  }
16
+
13
   render() {
17
   render() {
14
     const {
18
     const {
15
       list,
19
       list,

+ 2
- 0
src/components/Editor/Emoji.js View File

5
 // 每页 20  5*4
5
 // 每页 20  5*4
6
 // 共 20 * 3 = 60 (实际是 54)
6
 // 共 20 * 3 = 60 (实际是 54)
7
 
7
 
8
+// class Emoji
9
+
8
 const Emoji = ({ onClick }) => {
10
 const Emoji = ({ onClick }) => {
9
   const content = [[], [], []];
11
   const content = [[], [], []];
10
 
12
 

+ 97
- 65
src/components/Editor/index.js View File

1
-// https://github.com/lovasoa/react-contenteditable/blob/master/src/react-contenteditable.js
2
 import React from "react";
1
 import React from "react";
2
+import PropTypes from "prop-types";
3
 import { Icon, Button, Popover, Input } from "antd";
3
 import { Icon, Button, Popover, Input } from "antd";
4
 import { MAX_UPLOAD_NUMBER } from "../../constant";
4
 import { MAX_UPLOAD_NUMBER } from "../../constant";
5
 import Upload from "./Upload";
5
 import Upload from "./Upload";
6
 import Emoji from "./Emoji";
6
 import Emoji from "./Emoji";
7
-// import styles from "./index.less";
8
 import "./index.css";
7
 import "./index.css";
9
 
8
 
10
 const { TextArea } = Input;
9
 const { TextArea } = Input;
10
+// 设置 Editor 组件的默认值
11
+// 不能在 Editor.defaultProps 中设置
12
+// 因为 Editor 在 ComponentInput 中调用
13
+// 在 ComponentInput 中,需要使用 Editor 的 props 覆盖 ComponentInput 传入的 props
14
+const EditorDefaultProps = {
15
+  rows: 5,
16
+  placeholder: "说点什么吧...",
17
+  showEmoji: true,
18
+  showUpload: true,
19
+  submitText: "发表",
20
+  onChange: () => {}
21
+};
11
 
22
 
12
-export default class Editor extends React.Component {
23
+class Editor extends React.Component {
13
   constructor(props) {
24
   constructor(props) {
14
     super(props);
25
     super(props);
15
     this.state = {
26
     this.state = {
34
   }
45
   }
35
 
46
 
36
   render() {
47
   render() {
48
+    const props = { ...EditorDefaultProps, ...this.props };
37
     const {
49
     const {
38
       value,
50
       value,
39
       onChange,
51
       onChange,
52
+      onSubmit,
53
+      loading,
40
       placeholder,
54
       placeholder,
41
       fileList,
55
       fileList,
42
       onChangeFileList,
56
       onChangeFileList,
43
-      onUpload
44
-    } = this.props;
57
+      rows,
58
+      onUpload,
59
+      showEmoji,
60
+      showUpload,
61
+      submitText
62
+    } = props;
63
+
45
     return (
64
     return (
46
       <div className="editor">
65
       <div className="editor">
47
         <TextArea
66
         <TextArea
48
           value={value}
67
           value={value}
49
-          onChange={onChange}
50
-          rows={5}
68
+          onChange={e => onChange(e.target.value)}
69
+          rows={rows}
51
           placeholder={placeholder}
70
           placeholder={placeholder}
52
         />
71
         />
53
 
72
 
54
         <div className="toolbar">
73
         <div className="toolbar">
55
           <div style={{ float: "left", margin: "8px 11px" }}>
74
           <div style={{ float: "left", margin: "8px 11px" }}>
56
-            <Popover
57
-              trigger="click"
58
-              placement="bottomLeft"
59
-              autoAdjustOverflow={false}
60
-              content={
61
-                <div style={{ width: 200 }}>
62
-                  <Emoji onClick={this.handleClickEmoji} />
63
-                </div>
64
-              }
65
-              overlayClassName="feed"
66
-            >
67
-              <Icon type="smile-o" className="icon" />
68
-            </Popover>
75
+            {showEmoji && (
76
+              <Popover
77
+                trigger="click"
78
+                placement="bottomLeft"
79
+                autoAdjustOverflow={false}
80
+                content={
81
+                  <div style={{ width: 200 }}>
82
+                    <Emoji onClick={this.handleClickEmoji} />
83
+                  </div>
84
+                }
85
+                overlayClassName="feed"
86
+              >
87
+                <Icon type="smile-o" className="icon" />
88
+              </Popover>
89
+            )}
69
 
90
 
70
-            <Popover
71
-              visible={this.state.showUpload}
72
-              overlayStyle={{ zIndex: 999 }}
73
-              content={
74
-                <div style={{ width: 112 * MAX_UPLOAD_NUMBER, minHeight: 100 }}>
75
-                  <Upload
76
-                    onChangeFileList={onChangeFileList}
77
-                    onUpload={onUpload}
78
-                    fileList={fileList}
79
-                  />
80
-                </div>
81
-              }
82
-              placement="bottomLeft"
83
-              title={
84
-                <div style={{ margin: "5px auto" }}>
85
-                  <span>
86
-                    上传图片
87
-                    <span style={{ color: "#666", fontWeight: 400 }}>
88
-                      (您还能上传{MAX_UPLOAD_NUMBER - fileList.length}张图片)
91
+            {showUpload && (
92
+              <Popover
93
+                visible={this.state.showUpload}
94
+                overlayStyle={{ zIndex: 999 }}
95
+                content={
96
+                  <div
97
+                    style={{ width: 112 * MAX_UPLOAD_NUMBER, minHeight: 100 }}
98
+                  >
99
+                    <Upload
100
+                      onChangeFileList={onChangeFileList}
101
+                      onUpload={onUpload}
102
+                      fileList={fileList}
103
+                    />
104
+                  </div>
105
+                }
106
+                placement="bottomLeft"
107
+                title={
108
+                  <div style={{ margin: "5px auto" }}>
109
+                    <span>
110
+                      上传图片
111
+                      <span style={{ color: "#666", fontWeight: 400 }}>
112
+                        (您还能上传{MAX_UPLOAD_NUMBER - fileList.length}张图片)
113
+                      </span>
89
                     </span>
114
                     </span>
90
-                  </span>
91
-                  <Icon
92
-                    type="close"
93
-                    onClick={() => this.handleShowUpload(false)}
94
-                    style={{
95
-                      float: "right",
96
-                      cursor: "pointer",
97
-                      marginTop: 4
98
-                    }}
99
-                  />
100
-                </div>
101
-              }
102
-            >
103
-              <Icon
104
-                type="picture"
105
-                className="icon"
106
-                style={{ marginLeft: 10 }}
107
-                onClick={() => this.handleShowUpload(true)}
108
-              />
109
-            </Popover>
115
+                    <Icon
116
+                      type="close"
117
+                      onClick={() => this.handleShowUpload(false)}
118
+                      style={{
119
+                        float: "right",
120
+                        cursor: "pointer",
121
+                        marginTop: 4
122
+                      }}
123
+                    />
124
+                  </div>
125
+                }
126
+              >
127
+                <Icon
128
+                  type="picture"
129
+                  className="icon"
130
+                  style={{ marginLeft: 10 }}
131
+                  onClick={() => this.handleShowUpload(true)}
132
+                />
133
+              </Popover>
134
+            )}
110
           </div>
135
           </div>
111
 
136
 
112
           <div style={{ float: "right", margin: "5px 11px" }}>
137
           <div style={{ float: "right", margin: "5px 11px" }}>
113
-            <Button
114
-              onClick={this.props.onSubmit}
115
-              type="primary"
116
-              loading={this.props.loading}
117
-            >
118
-              发表
138
+            <Button onClick={onSubmit} type="primary" loading={loading}>
139
+              {submitText}
119
             </Button>
140
             </Button>
120
           </div>
141
           </div>
121
         </div>
142
         </div>
123
     );
144
     );
124
   }
145
   }
125
 }
146
 }
147
+
148
+Editor.propTypes = {
149
+  rows: PropTypes.number,
150
+  placeholder: PropTypes.string,
151
+  showEmoji: PropTypes.bool,
152
+  showUpload: PropTypes.bool,
153
+  submitText: PropTypes.string,
154
+  onChange: PropTypes.func
155
+};
156
+
157
+export default Editor;

+ 0
- 3
src/constant.js View File

1
-// export const URL = "http://121.41.20.11:8082/v1";
2
-export const URL = "http://api.links123.net/comment/v1";
3
-
4
 export const ERROR_DEFAULT = "出错了!";
1
 export const ERROR_DEFAULT = "出错了!";
5
 
2
 
6
 export const LIMIT = 10; // 默认 limit
3
 export const LIMIT = 10; // 默认 limit

+ 21
- 2
src/index.js View File

1
 import React from "react";
1
 import React from "react";
2
 import ReactDOM from "react-dom";
2
 import ReactDOM from "react-dom";
3
-import App from "./App";
3
+import App, { Editor } from "./App";
4
 import registerServiceWorker from "./registerServiceWorker";
4
 import registerServiceWorker from "./registerServiceWorker";
5
 
5
 
6
-ReactDOM.render(<App />, document.getElementById("root-comment"));
6
+const props = {
7
+  type: 1,
8
+  businessId: "1",
9
+  API: "http://api.links123.net/comment/v1",
10
+  showList: false
11
+};
12
+
13
+const editorProps = {
14
+  showEmoji: true,
15
+  placeholder: "说点什么吧",
16
+  rows: 5
17
+  // onSubmit={v => console.log()} // TODO...
18
+};
19
+
20
+ReactDOM.render(
21
+  <App {...props}>
22
+    <Editor {...editorProps} />
23
+  </App>,
24
+  document.getElementById("root-comment")
25
+);
7
 registerServiceWorker();
26
 registerServiceWorker();

+ 15
- 0
src/lang/index.js View File

1
+// 语言包
2
+// 英文短语和中文提示的对应
3
+const data = {
4
+  "auth failed": "请先登录",
5
+  "create comment failed": "创建评论失败",
6
+  "comment favor failed": "评论点赞失败",
7
+  "delete comment favor failed": "评论取消点赞失败",
8
+  "get comments failed": "获取评论列表失败",
9
+  "create reply failed": "创建回复失败",
10
+  "reply favor failed": "回复点赞失败",
11
+  "delete reply favor failed": "删除回复点赞失败",
12
+  "get replies failed": "获取回复列表失败"
13
+};
14
+
15
+export default data;