Browse Source

doc: UPDATE README.md

node 6 years ago
parent
commit
64b5440c39

+ 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
+

+ 1
- 1
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": [

+ 0
- 2
src/App.js View File

314
   API: PropTypes.string, // 评论的 API 前缀
314
   API: PropTypes.string, // 评论的 API 前缀
315
   showList: PropTypes.bool, // 是否显示评论列表
315
   showList: PropTypes.bool, // 是否显示评论列表
316
   showEditor: PropTypes.bool // 是否显示评论输入框
316
   showEditor: PropTypes.bool // 是否显示评论输入框
317
-  // editor: PropTypes.node, // 评论编辑器
318
 };
317
 };
319
 
318
 
320
 App.defaultProps = {
319
 App.defaultProps = {
321
   API: "http://api.links123.net/comment/v1",
320
   API: "http://api.links123.net/comment/v1",
322
   showList: true,
321
   showList: true,
323
   showEditor: true
322
   showEditor: true
324
-  // editor: <span>a</span>,
325
 };
323
 };
326
 
324
 
327
 export { Editor };
325
 export { Editor };

+ 5
- 0
src/CHANGELOG.md View File

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

+ 0
- 23
src/components/Editor.1/Emoji.css View File

1
-.item {
2
-  float: left;
3
-  width: 40px;
4
-  height: 40px;
5
-  cursor: pointer;
6
-  white-space: nowrap;
7
-  /* this is required unless you put the helper span closely near the img */
8
-  text-align: center;
9
-  margin: 0;
10
-}
11
-.item .helper {
12
-  display: inline-block;
13
-  height: 100%;
14
-  vertical-align: middle;
15
-}
16
-.item img {
17
-  margin: 0 auto;
18
-  vertical-align: middle;
19
-  padding: 3px;
20
-}
21
-.item img:hover {
22
-  border: 1px solid #40a9ff;
23
-}

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

1
-import React from "react";
2
-import { Carousel } from "antd";
3
-import emoji, { prefixUrl, ext } from "../../emoji";
4
-import "./Emoji.css";
5
-// 每页 20  5*4
6
-// 共 20 * 3 = 60 (实际是 54)
7
-
8
-const Emoji = ({ onClick }) => {
9
-  const content = [[], [], []];
10
-
11
-  for (let i = 0; i < emoji.length; i++) {
12
-    if (i < 20) {
13
-      content[0].push(emoji[i]);
14
-    } else if (i < 40) {
15
-      content[1].push(emoji[i]);
16
-    } else if (i < emoji.length) {
17
-      content[2].push(emoji[i]);
18
-    }
19
-  }
20
-  return (
21
-    <Carousel>
22
-      <div>
23
-        {content[0].map((item, index) => (
24
-          <div className="item" key={item.value}>
25
-            <span className="helper" />
26
-            <img
27
-              src={`${prefixUrl}${item.value}.${ext}`}
28
-              alt={item.title}
29
-              style={{ display: "inline-block" }}
30
-              onClick={() => onClick(item.title)}
31
-            />
32
-          </div>
33
-        ))}
34
-      </div>
35
-      <div>
36
-        {content[1].map((item, index) => (
37
-          <div className="item" key={item.value}>
38
-            <span className="helper" />
39
-            <img
40
-              src={`${prefixUrl}${item.value}.${ext}`}
41
-              alt={item.title}
42
-              style={{ display: "inline-block" }}
43
-              onClick={() => onClick(item.title)}
44
-            />
45
-          </div>
46
-        ))}
47
-      </div>
48
-      <div>
49
-        {content[2].map(item => (
50
-          <div className="item" key={item.value}>
51
-            <span className="helper" />
52
-            <img
53
-              src={`${prefixUrl}${item.value}.${ext}`}
54
-              alt={item.title}
55
-              style={{ display: "inline-block" }}
56
-              onClick={() => onClick(item.title)}
57
-            />
58
-          </div>
59
-        ))}
60
-      </div>
61
-    </Carousel>
62
-  );
63
-};
64
-
65
-export default Emoji;

+ 0
- 8
src/components/Editor.1/Upload.css View File

1
-.ant-upload-select-picture-card i {
2
-  font-size: 32px;
3
-  color: #999;
4
-}
5
-.ant-upload-select-picture-card .ant-upload-text {
6
-  margin-top: 8px;
7
-  color: #666;
8
-}

+ 0
- 132
src/components/Editor.1/Upload.js View File

1
-import React from "react";
2
-import { Upload, Icon, Modal, message } from "antd";
3
-import dayjs from "dayjs";
4
-import shortid from "shortid";
5
-import {
6
-  OSS_ENDPOINT,
7
-  OSS_BUCKET,
8
-  DRIVER_LICENSE_PATH,
9
-  ERROR_DEFAULT,
10
-  MAX_UPLOAD_NUMBER
11
-} from "../../constant";
12
-import Comment from "../../Comment";
13
-// import styles from "./Upload.less";
14
-import "./Upload.css";
15
-
16
-const client = oss => {
17
-  return new window.OSS.Wrapper({
18
-    accessKeyId: oss.access_key_id,
19
-    accessKeySecret: oss.access_key_secret,
20
-    stsToken: oss.security_token,
21
-    endpoint: OSS_ENDPOINT, //常量,你可以自己定义
22
-    bucket: OSS_BUCKET
23
-  });
24
-};
25
-
26
-const uploadPath = (path, file) => {
27
-  return `${path}/${dayjs().format("YYYYMMDD")}/${shortid.generate()}.${
28
-    file.type.split("/")[1]
29
-  }`;
30
-};
31
-
32
-const UploadToOss = (oss, path, file) => {
33
-  const url = uploadPath(path, file);
34
-  return new Promise((resolve, reject) => {
35
-    client(oss)
36
-      .multipartUpload(url, file)
37
-      .then(data => {
38
-        resolve(data);
39
-      })
40
-      .catch(error => {
41
-        reject(error);
42
-      });
43
-  });
44
-};
45
-
46
-class App extends React.Component {
47
-  constructor(props) {
48
-    super(props);
49
-    this.state = {
50
-      previewVisible: false,
51
-      previewImage: ""
52
-    };
53
-    this.handleCancel = this.handleCancel.bind(this);
54
-    this.handlePreview = this.handlePreview.bind(this);
55
-    this.handleChange = this.handleChange.bind(this);
56
-    this.customRequest = this.customRequest.bind(this);
57
-  }
58
-
59
-  componentDidMount() {
60
-    this.props.app.sOssSts();
61
-  }
62
-
63
-  handleCancel() {
64
-    this.setState({ previewVisible: false });
65
-  }
66
-
67
-  handlePreview(file) {
68
-    this.setState({
69
-      previewImage: file.url || file.thumbUrl,
70
-      previewVisible: true
71
-    });
72
-  }
73
-
74
-  handleChange({ fileList }) {
75
-    this.props.onChangeFileList(fileList);
76
-  }
77
-
78
-  customRequest(info) {
79
-    const { file } = info;
80
-    info.onProgress({ percent: 10 });
81
-    let reader = new FileReader();
82
-    reader.readAsDataURL(info.file);
83
-    reader.onloadend = () => {
84
-      info.onProgress({ percent: 20 });
85
-      // DRIVER_LICENSE_PATH oss 的存储路径位置
86
-      UploadToOss(this.props.app.oss, DRIVER_LICENSE_PATH, file)
87
-        .then(data => {
88
-          info.onProgress({ percent: 100 });
89
-          info.onSuccess();
90
-          this.props.onUpload({ path: data.name, uid: file.uid });
91
-        })
92
-        .catch(e => {
93
-          message.error(e.message || ERROR_DEFAULT);
94
-          info.onError(e);
95
-        });
96
-    };
97
-  }
98
-
99
-  render() {
100
-    const { previewVisible, previewImage } = this.state;
101
-    const { fileList } = this.props;
102
-    const uploadButton = (
103
-      <div>
104
-        <Icon type="plus" />
105
-        <div className="ant-upload-text">上传</div>
106
-      </div>
107
-    );
108
-    return (
109
-      <div>
110
-        <Upload
111
-          accept="image/jpg,image/jpeg,image/png,image/bmp"
112
-          listType="picture-card"
113
-          fileList={fileList}
114
-          customRequest={this.customRequest}
115
-          onPreview={this.handlePreview}
116
-          onChange={this.handleChange}
117
-        >
118
-          {fileList.length >= MAX_UPLOAD_NUMBER ? null : uploadButton}
119
-        </Upload>
120
-        <Modal
121
-          visible={previewVisible}
122
-          footer={null}
123
-          onCancel={this.handleCancel}
124
-        >
125
-          <img alt="upload" style={{ width: "100%" }} src={previewImage} />
126
-        </Modal>
127
-      </div>
128
-    );
129
-  }
130
-}
131
-
132
-export default Comment(App);

+ 0
- 82
src/components/Editor.1/index.css View File

1
-.editor {
2
-  box-sizing: border-box;
3
-  margin: 0;
4
-  padding: 0;
5
-  width: 100%;
6
-  max-width: 100%;
7
-  list-style: none;
8
-  position: relative;
9
-  display: block;
10
-  font-size: 14px;
11
-  line-height: 1.5;
12
-  color: rgba(0, 0, 0, 0.65);
13
-  background-color: #fff;
14
-  background-image: none;
15
-  border: 1px solid #d9d9d9;
16
-  border-radius: 4px;
17
-  transition: all 0.3s, height 0s;
18
-}
19
-.editor textarea.ant-input {
20
-  border: none;
21
-  border-bottom: 1px solid #eee;
22
-  border-bottom-right-radius: 0;
23
-  border-bottom-left-radius: 0;
24
-}
25
-.editor textarea.ant-input:hover {
26
-  border: none;
27
-  border-bottom: 1px solid #eee;
28
-}
29
-.editor textarea.ant-input:focus {
30
-  box-shadow: none;
31
-  border-bottom: 1px solid #eee;
32
-}
33
-.editor [contentEditable="true"]:empty:not(:focus):before {
34
-  content: attr(data-text);
35
-  color: #bfbfbf;
36
-}
37
-.editor:focus,
38
-.editor:hover {
39
-  border-color: #40a9ff;
40
-  outline: 0;
41
-  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
42
-}
43
-.content {
44
-  display: block;
45
-  box-sizing: border-box;
46
-  padding: 4px 10px;
47
-  width: 100%;
48
-  max-width: 100%;
49
-  height: 100%;
50
-  max-height: 110px;
51
-  overflow-y: auto;
52
-  overflow-x: auto;
53
-}
54
-.content:focus,
55
-.content:hover {
56
-  outline: 0;
57
-}
58
-.toolbar {
59
-  display: inline-block;
60
-  width: 100%;
61
-  margin: 5px 0 0 0;
62
-}
63
-.toolbar .icon {
64
-  font-size: 23px;
65
-  cursor: pointer;
66
-  transition: color 0.3s;
67
-}
68
-.toolbar .icon:hover {
69
-  color: #40a9ff;
70
-}
71
-.feed .ant-popover-inner-content {
72
-  padding: 12px 16px 20px 16px;
73
-}
74
-.feed .ant-carousel .slick-dots {
75
-  bottom: -10px;
76
-}
77
-.feed .ant-carousel .slick-dots li.slick-active button {
78
-  background-color: #7b868a;
79
-}
80
-.feed .ant-carousel .slick-dots li button {
81
-  background-color: #a2aeb5;
82
-}

+ 0
- 142
src/components/Editor.1/index.js View File

1
-import React from "react";
2
-import PropTypes from "prop-types";
3
-import { Icon, Button, Popover, Input } from "antd";
4
-import { MAX_UPLOAD_NUMBER } from "../../constant";
5
-import Upload from "./Upload";
6
-import Emoji from "./Emoji";
7
-import "./index.css";
8
-
9
-const { TextArea } = Input;
10
-
11
-class Editor extends React.Component {
12
-  constructor(props) {
13
-    super(props);
14
-    this.state = {
15
-      showUpload: false
16
-    };
17
-    this.handleClickEmoji = this.handleClickEmoji.bind(this);
18
-    this.handleShowUpload = this.handleShowUpload.bind(this);
19
-  }
20
-
21
-  componentDidMount() {}
22
-
23
-  handleClickEmoji(emojiId) {
24
-    this.props.onChangeEmoji(emojiId);
25
-  }
26
-
27
-  handleShowUpload(showUpload) {
28
-    if (typeof showUpload === "boolean") {
29
-      this.setState({ showUpload: showUpload });
30
-    } else {
31
-      this.setState({ showUpload: !this.state.showUpload });
32
-    }
33
-  }
34
-
35
-  render() {
36
-    const {
37
-      value,
38
-      onChange,
39
-      placeholder,
40
-      fileList,
41
-      onChangeFileList,
42
-      rows,
43
-      onUpload
44
-    } = this.props;
45
-
46
-    return (
47
-      <div className="editor">
48
-        <TextArea
49
-          value={value}
50
-          onChange={onChange}
51
-          rows={rows}
52
-          placeholder={placeholder}
53
-        />
54
-
55
-        <div className="toolbar">
56
-          {false && (
57
-            <div style={{ float: "left", margin: "8px 11px" }}>
58
-              <Popover
59
-                trigger="click"
60
-                placement="bottomLeft"
61
-                autoAdjustOverflow={false}
62
-                content={
63
-                  <div style={{ width: 200 }}>
64
-                    <Emoji onClick={this.handleClickEmoji} />
65
-                  </div>
66
-                }
67
-                overlayClassName="feed"
68
-              >
69
-                <Icon type="smile-o" className="icon" />
70
-              </Popover>
71
-
72
-              <Popover
73
-                visible={this.state.showUpload}
74
-                overlayStyle={{ zIndex: 999 }}
75
-                content={
76
-                  <div
77
-                    style={{ width: 112 * MAX_UPLOAD_NUMBER, minHeight: 100 }}
78
-                  >
79
-                    <Upload
80
-                      onChangeFileList={onChangeFileList}
81
-                      onUpload={onUpload}
82
-                      fileList={fileList}
83
-                    />
84
-                  </div>
85
-                }
86
-                placement="bottomLeft"
87
-                title={
88
-                  <div style={{ margin: "5px auto" }}>
89
-                    <span>
90
-                      上传图片
91
-                      <span style={{ color: "#666", fontWeight: 400 }}>
92
-                        (您还能上传{MAX_UPLOAD_NUMBER - fileList.length}张图片)
93
-                      </span>
94
-                    </span>
95
-                    <Icon
96
-                      type="close"
97
-                      onClick={() => this.handleShowUpload(false)}
98
-                      style={{
99
-                        float: "right",
100
-                        cursor: "pointer",
101
-                        marginTop: 4
102
-                      }}
103
-                    />
104
-                  </div>
105
-                }
106
-              >
107
-                <Icon
108
-                  type="picture"
109
-                  className="icon"
110
-                  style={{ marginLeft: 10 }}
111
-                  onClick={() => this.handleShowUpload(true)}
112
-                />
113
-              </Popover>
114
-            </div>
115
-          )}
116
-
117
-          <div style={{ float: "right", margin: "5px 11px" }}>
118
-            <Button
119
-              onClick={this.props.onSubmit}
120
-              type="primary"
121
-              loading={this.props.loading}
122
-            >
123
-              发表
124
-            </Button>
125
-          </div>
126
-        </div>
127
-      </div>
128
-    );
129
-  }
130
-}
131
-
132
-Editor.propTypes = {
133
-  rows: PropTypes.number,
134
-  placeholder: PropTypes.string
135
-};
136
-
137
-Editor.defaultProps = {
138
-  rows: 5,
139
-  placeholder: "说点什么吧..."
140
-};
141
-
142
-export default Editor;

+ 2
- 1
src/index.js View File

14
   showEmoji: true,
14
   showEmoji: true,
15
   placeholder: "说点什么吧",
15
   placeholder: "说点什么吧",
16
   rows: 5
16
   rows: 5
17
+  // onSubmit={v => console.log()} // TODO...
17
 };
18
 };
18
 
19
 
19
 ReactDOM.render(
20
 ReactDOM.render(
20
   <App {...props}>
21
   <App {...props}>
21
-    <Editor {...editorProps} onSubmit={v => console.log()} />
22
+    <Editor {...editorProps} />
22
   </App>,
23
   </App>,
23
   document.getElementById("root-comment")
24
   document.getElementById("root-comment")
24
 );
25
 );