Roxas 3 years ago
commit
13aa5d59d8

+ 104
- 0
.gitignore View File

@@ -0,0 +1,104 @@
1
+# Logs
2
+logs
3
+*.log
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+lerna-debug.log*
8
+
9
+# Diagnostic reports (https://nodejs.org/api/report.html)
10
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11
+
12
+# Runtime data
13
+pids
14
+*.pid
15
+*.seed
16
+*.pid.lock
17
+
18
+# Directory for instrumented libs generated by jscoverage/JSCover
19
+lib-cov
20
+
21
+# Coverage directory used by tools like istanbul
22
+coverage
23
+*.lcov
24
+
25
+# nyc test coverage
26
+.nyc_output
27
+
28
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29
+.grunt
30
+
31
+# Bower dependency directory (https://bower.io/)
32
+bower_components
33
+
34
+# node-waf configuration
35
+.lock-wscript
36
+
37
+# Compiled binary addons (https://nodejs.org/api/addons.html)
38
+build/Release
39
+
40
+# Dependency directories
41
+node_modules/
42
+jspm_packages/
43
+
44
+# TypeScript v1 declaration files
45
+typings/
46
+
47
+# TypeScript cache
48
+*.tsbuildinfo
49
+
50
+# Optional npm cache directory
51
+.npm
52
+
53
+# Optional eslint cache
54
+.eslintcache
55
+
56
+# Microbundle cache
57
+.rpt2_cache/
58
+.rts2_cache_cjs/
59
+.rts2_cache_es/
60
+.rts2_cache_umd/
61
+
62
+# Optional REPL history
63
+.node_repl_history
64
+
65
+# Output of 'npm pack'
66
+*.tgz
67
+
68
+# Yarn Integrity file
69
+.yarn-integrity
70
+
71
+# dotenv environment variables file
72
+.env
73
+.env.test
74
+
75
+# parcel-bundler cache (https://parceljs.org/)
76
+.cache
77
+
78
+# Next.js build output
79
+.next
80
+
81
+# Nuxt.js build / generate output
82
+.nuxt
83
+dist
84
+
85
+# Gatsby files
86
+.cache/
87
+# Comment in the public line in if your project uses Gatsby and *not* Next.js
88
+# https://nextjs.org/blog/next-9-1#public-directory-support
89
+# public
90
+
91
+# vuepress build output
92
+.vuepress/dist
93
+
94
+# Serverless directories
95
+.serverless/
96
+
97
+# FuseBox cache
98
+.fusebox/
99
+
100
+# DynamoDB Local files
101
+.dynamodb/
102
+
103
+# TernJS port file
104
+.tern-port

+ 9
- 0
.storybook/addons.js View File

@@ -0,0 +1,9 @@
1
+import '@storybook/addon-actions/register';
2
+import '@storybook/addon-links/register';
3
+import '@storybook/addon-notes/register';
4
+import '@storybook/addon-knobs/register';
5
+import '@storybook/addon-viewport/register';
6
+import '@storybook/addon-console';
7
+import '@storybook/addon-storysource/register';
8
+import 'storybook-addon-themes';
9
+import 'storybook-readme/register';

+ 25
- 0
.storybook/config.js View File

@@ -0,0 +1,25 @@
1
+import { configure, getStorybook } from '@storybook/react';
2
+import { addParameters } from '@storybook/react';
3
+import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport';
4
+import { addDecorator } from '@storybook/react';
5
+import { withConsole } from '@storybook/addon-console';
6
+import theme from './theme';
7
+
8
+import 'antd/dist/antd.less';
9
+
10
+addParameters({
11
+  info: { inline: true },
12
+  viewport: {
13
+    viewports: INITIAL_VIEWPORTS,
14
+    defaultViewport: 'someDefault',
15
+  },
16
+  options: { theme },
17
+});
18
+// automatically import all files ending in *.stories.tsx
19
+configure(
20
+  require.context('../stories', true, /\.stories\.(t|j)sx?$/), module
21
+)
22
+
23
+addDecorator((storyFn, context) => withConsole()(storyFn)(context));
24
+
25
+export { getStorybook }

+ 1
- 0
.storybook/preview-head.html View File

@@ -0,0 +1 @@
1
+<link rel="stylesheet" href="//at.alicdn.com/t/font_1158309_1tkgtp97s75.css" />

+ 37
- 0
.storybook/theme.js View File

@@ -0,0 +1,37 @@
1
+import { create } from '@storybook/theming/create';
2
+
3
+export default create({
4
+  base: 'light',
5
+
6
+  colorPrimary: '#fc4747',
7
+  colorSecondary: '#fc695a',
8
+
9
+  // UI
10
+  appBg: 'white',
11
+  appContentBg: 'white',
12
+  appBorderColor: 'grey',
13
+  appBorderRadius: 4,
14
+
15
+  // Typography
16
+  fontBase: '"Open Sans", sans-serif',
17
+  fontCode: 'monospace',
18
+
19
+  // Text colors
20
+  textColor: 'black',
21
+  textInverseColor: 'rgba(255,255,255,0.9)',
22
+
23
+  // Toolbar default and active colors
24
+  barTextColor: 'black',
25
+  barSelectedColor: 'white',
26
+  barBg: '#fc4747',
27
+
28
+  // Form colors
29
+  inputBg: 'white',
30
+  inputBorder: 'silver',
31
+  inputTextColor: 'black',
32
+  inputBorderRadius: 4,
33
+
34
+  brandTitle: 'BilingoUI',
35
+  brandUrl: 'https://www.bilingo.com/',
36
+  brandImage: 'https://a.links123.cn/common/imgs/logo_en_mobile@2x.png?2019021101',
37
+});

+ 72
- 0
.storybook/webpack.config.js View File

@@ -0,0 +1,72 @@
1
+const fs = require('fs');
2
+const path = require('path');
3
+
4
+module.exports = ({ config }) => {
5
+  config.resolve.modules =  ['node_modules'];
6
+  config.module.rules.push({
7
+    test: /\.stories\.tsx?$/,
8
+    loaders: [require.resolve('@storybook/source-loader')],
9
+    enforce: 'pre',
10
+  });
11
+  config.module.rules.push({
12
+    test: /\.less$/,
13
+    include: /node_modules|antd\.less/,
14
+    use: [
15
+      "style-loader",
16
+      "css-loader",
17
+      {
18
+        loader: "less-loader",
19
+        options: {
20
+          javascriptEnabled: true
21
+        }
22
+      }
23
+    ]
24
+  });
25
+  config.module.rules.push({
26
+    test: /\.less$/,
27
+    use: [
28
+    'style-loader', 
29
+    {
30
+      loader: 'css-loader',// translates CSS into CommonJS
31
+      options: {
32
+        modules: {
33
+          localIdentName: '[name]__[local]___[hash:base64:5]',
34
+        },
35
+      }
36
+    },
37
+    'postcss-loader',
38
+    {
39
+      loader: 'less-loader',
40
+      options: {
41
+        config: {
42
+          path: path.join(path.resolve(__dirname, '..'), 'postcss.config.js')
43
+        },
44
+        javascriptEnabled: true,
45
+      },
46
+    }],
47
+    exclude: /node_modules|antd\.less/,
48
+  });
49
+  config.module.rules.push({
50
+    test: /\.(ts|tsx)$/,
51
+    use: [
52
+      {
53
+        loader: require.resolve('babel-loader'),
54
+        options: {
55
+          presets: [['react-app', { flow: false, typescript: true }]],
56
+        }
57
+      },
58
+      // Optional
59
+      {
60
+        loader: require.resolve("react-docgen-typescript-loader")
61
+      },
62
+    ]
63
+  });
64
+  config.resolve.extensions.push(".ts", ".tsx");
65
+  config.resolve.alias = {
66
+    ...config.resolve.alias,
67
+    '@': `${path.resolve(fs.realpathSync(process.cwd()), './src')}`,
68
+    '@components': `${path.resolve(fs.realpathSync(process.cwd()), './src')}/components`,
69
+  }
70
+  config.output.library = "[name]";
71
+  return config;
72
+};

+ 124
- 0
package.json View File

@@ -0,0 +1,124 @@
1
+{
2
+  "name": "base-ui",
3
+  "version": "1.0.0",
4
+  "description": "a base components ui lib",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "start": "react-app-rewired start",
8
+    "build": "react-app-rewired build",
9
+    "test": "react-app-rewired test",
10
+    "eject": "react-app-rewired eject",
11
+    "build:lib": "rimraf lib && rimraf eslib && rollup -c ./rollup.config.js",
12
+    "storybook": "start-storybook -p 9009 -s public",
13
+    "build-storybook": "build-storybook -s public"
14
+  },
15
+  "dependencies": {
16
+    "@testing-library/jest-dom": "^4.2.4",
17
+    "@testing-library/react": "^9.3.2",
18
+    "@testing-library/user-event": "^7.1.2",
19
+    "@types/axios": "^0.14.0",
20
+    "@types/braft-editor": "^2.2.0",
21
+    "@types/classnames": "^2.2.9",
22
+    "@types/jest": "^24.0.0",
23
+    "@types/node": "^12.0.0",
24
+    "@types/react": "^16.9.0",
25
+    "@types/react-dom": "^16.9.0",
26
+    "@types/react-intl": "^3.0.0",
27
+    "@wessberg/rollup-plugin-ts": "^1.2.15",
28
+    "antd": "^4.3.4",
29
+    "axios": "^0.19.2",
30
+    "classnames": "^2.2.6",
31
+    "immutable": "^4.0.0-rc.12",
32
+    "react-scripts": "3.3.0",
33
+    "rollup-plugin-visualizer": "^3.3.1",
34
+    "typescript": "~3.7.2"
35
+  },
36
+  "author": "thewindsword",
37
+  "license": "MIT",
38
+  "eslintConfig": {
39
+    "extends": "react-app"
40
+  },
41
+  "browserslist": {
42
+    "production": [
43
+      ">0.2%",
44
+      "not dead",
45
+      "not op_mini all"
46
+    ],
47
+    "development": [
48
+      "last 1 chrome version",
49
+      "last 1 firefox version",
50
+      "last 1 safari version"
51
+    ]
52
+  },
53
+  "devDependencies": {
54
+    "@babel/cli": "^7.7.5",
55
+    "@babel/core": "^7.7.5",
56
+    "@babel/plugin-proposal-class-properties": "^7.7.4",
57
+    "@babel/plugin-proposal-export-default-from": "^7.7.4",
58
+    "@babel/polyfill": "^7.7.0",
59
+    "@babel/preset-env": "^7.7.6",
60
+    "@babel/preset-react": "^7.7.4",
61
+    "@babel/preset-typescript": "^7.7.4",
62
+    "@rollup/plugin-alias": "^3.0.0",
63
+    "@rollup/plugin-commonjs": "^11.0.0",
64
+    "@rollup/plugin-image": "^2.0.0",
65
+    "@rollup/plugin-node-resolve": "^6.0.0",
66
+    "@rollup/plugin-url": "^4.0.0",
67
+    "@storybook/addon-actions": "^5.2.8",
68
+    "@storybook/addon-console": "^1.2.1",
69
+    "@storybook/addon-info": "^5.2.8",
70
+    "@storybook/addon-knobs": "^5.2.8",
71
+    "@storybook/addon-links": "^5.2.8",
72
+    "@storybook/addon-notes": "^5.2.8",
73
+    "@storybook/addon-storysource": "^5.2.8",
74
+    "@storybook/addon-viewport": "^5.2.8",
75
+    "@storybook/addons": "^5.2.8",
76
+    "@storybook/react": "^5.2.8",
77
+    "@types/draft-js": "^0.10.38",
78
+    "@types/storybook-readme": "^5.0.4",
79
+    "@types/storybook__addon-info": "^5.2.1",
80
+    "@typescript-eslint/eslint-plugin": "^2.16.0",
81
+    "@typescript-eslint/parser": "^2.16.0",
82
+    "autoprefixer": "^9.7.3",
83
+    "babel-loader": "^8.0.6",
84
+    "babel-plugin-import": "^1.13.0",
85
+    "cross-env": "^6.0.3",
86
+    "css-loader": "^3.2.1",
87
+    "draftjs-utils": "^0.10.2",
88
+    "eslint": "^6.8.0",
89
+    "file-loader": "^5.0.2",
90
+    "less": "^3.10.3",
91
+    "less-loader": "^5.0.0",
92
+    "node-eval": "^2.0.0",
93
+    "postcss-loader": "^3.0.0",
94
+    "postcss-url": "^8.0.0",
95
+    "react": "^16.12.0",
96
+    "react-app-rewired": "^2.1.5",
97
+    "react-docgen-typescript-loader": "^3.6.0",
98
+    "react-dom": "^16.12.0",
99
+    "rimraf": "^3.0.0",
100
+    "rollup": "^1.27.13",
101
+    "rollup-plugin-alias": "^2.2.0",
102
+    "rollup-plugin-analyzer": "^3.2.2",
103
+    "rollup-plugin-babel": "^4.3.3",
104
+    "rollup-plugin-eslint": "^7.0.0",
105
+    "rollup-plugin-json": "^4.0.0",
106
+    "rollup-plugin-less": "^1.1.2",
107
+    "rollup-plugin-node-resolve": "^5.2.0",
108
+    "rollup-plugin-peer-deps-external": "^2.2.0",
109
+    "rollup-plugin-postcss-modules": "^2.0.1",
110
+    "rollup-plugin-replace": "^2.2.0",
111
+    "rollup-plugin-sourcemaps": "^0.5.0",
112
+    "rollup-plugin-typescript2": "^0.25.3",
113
+    "storybook-addon-themes": "^5.3.0",
114
+    "storybook-readme": "^5.0.8",
115
+    "style-loader": "^1.0.1",
116
+    "ts-loader": "^6.2.1",
117
+    "tslib": "^1.10.0"
118
+  },
119
+  "peerDependencies": {
120
+    "antd": "^4.3.4",
121
+    "react": "^16.12.0",
122
+    "react-dom": "^16.12.0"
123
+  }
124
+}

+ 5
- 0
postcss.config.js View File

@@ -0,0 +1,5 @@
1
+module.exports = {  
2
+  plugins: [
3
+    require('autoprefixer'),
4
+  ]
5
+} 

+ 173
- 0
rollup.config.js View File

@@ -0,0 +1,173 @@
1
+import resolve from "@rollup/plugin-node-resolve";
2
+import commonjs from "@rollup/plugin-commonjs";
3
+import image from '@rollup/plugin-image';
4
+import alias from '@rollup/plugin-alias';
5
+import postcss from 'rollup-plugin-postcss-modules'
6
+import babel from "rollup-plugin-babel";
7
+import { DEFAULT_EXTENSIONS } from '@babel/core';
8
+import json from "rollup-plugin-json";
9
+import autoprefixer from 'autoprefixer';
10
+import postcssUrl from 'postcss-url';
11
+import peerDepsExternal from 'rollup-plugin-peer-deps-external';
12
+import visualizer from 'rollup-plugin-visualizer';
13
+import analyze from 'rollup-plugin-analyzer';
14
+import ts from "@wessberg/rollup-plugin-ts";
15
+// import typescript from 'rollup-plugin-typescript2';
16
+// import sourcemaps from 'rollup-plugin-sourcemaps';
17
+
18
+// import url from '@rollup/plugin-url';
19
+// import less from "rollup-plugin-less";
20
+import nodeEval from 'node-eval';
21
+
22
+export function getModuleExports(moduleId) {
23
+  const id = require.resolve(moduleId)
24
+  const moduleOut = nodeEval(fs.readFileSync(id).toString(), id)
25
+  let result = []
26
+  const excludeExports = /^(default|__)/
27
+  if (moduleOut && typeof moduleOut === 'object') {
28
+      result = Object.keys(moduleOut)
29
+          .filter(name => !excludeExports.test(name))
30
+  }
31
+  return result
32
+}
33
+
34
+export function getNamedExports(moduleIds) {
35
+  const result = {}
36
+  moduleIds.forEach( id => {
37
+      result[id] = getModuleExports(id)
38
+  })
39
+  return result
40
+}
41
+
42
+const fs = require('fs');
43
+const path = require('path');
44
+const componentsFold = 'src/components';
45
+const cModuleNames = fs.readdirSync(path.resolve(componentsFold));
46
+const cModuleMap = cModuleNames.reduce((prev, name) => {
47
+  const modulePath = `${componentsFold}/${name}`;
48
+  prev[name] = `${modulePath}/index.ts`;
49
+  const child = fs.readdirSync(path.resolve(modulePath));
50
+  child.forEach(c => {
51
+    const childFoldPath = `${modulePath}/${c}`;
52
+    const isDir = fs.statSync(childFoldPath).isDirectory();
53
+    if (isDir) {
54
+      if (fs.existsSync(`${childFoldPath}/index.tsx`)) {
55
+        prev[c] = `${childFoldPath}/index.tsx`;
56
+      }
57
+      if (c === 'Common' && fs.existsSync(childFoldPath) && fs.statSync(childFoldPath).isDirectory()) {
58
+        const commonComponentsArr = fs.readdirSync(childFoldPath);
59
+        commonComponentsArr.forEach(commonComponentFold => {
60
+          const commonComponentFoldPath = `${childFoldPath}/${commonComponentFold}`;
61
+          const isCommonComponentDir = fs.statSync(commonComponentFoldPath).isDirectory();
62
+          if (isCommonComponentDir && fs.existsSync(`${commonComponentFoldPath}/index.tsx`)) {
63
+            prev[`${commonComponentFold}`] = `${commonComponentFoldPath}/index.tsx`;
64
+          }
65
+        });
66
+      }
67
+    }
68
+  });
69
+  return prev;
70
+}, {});
71
+
72
+const extensions = [ ...DEFAULT_EXTENSIONS, '.js', '.jsx', '.ts', '.tsx'];
73
+
74
+export default {
75
+  input: {
76
+    '.': "src/lib-build.ts",
77
+    ...cModuleMap
78
+  },
79
+  output: [
80
+    {
81
+      dir: "lib",
82
+      sourcemap: true,
83
+      entryFileNames: '[name]/index.js',
84
+      exports: 'named',
85
+      // file: "lib/bundle.js",
86
+      format: "cjs"
87
+    },
88
+    {
89
+      dir: "eslib",
90
+      sourcemap: true,
91
+      entryFileNames: '[name]/index.js',
92
+      exports: 'named',
93
+      // file: "lib/bundle.js",
94
+      format: "es"
95
+    }
96
+  ],
97
+  plugins: [
98
+    peerDepsExternal(),
99
+    resolve({
100
+      mainFields: ['jsnext'],
101
+      preferBuiltins: true,
102
+      browser: true,
103
+      extensions,
104
+    }),
105
+    image(),
106
+    json(),
107
+    // sourcemaps(),
108
+    commonjs({
109
+      include: /node_modules/,
110
+      browser: true,
111
+      namedExports: {
112
+        ...getNamedExports([
113
+          'prop-types',
114
+          'draft-js',
115
+        ]),
116
+        'braft-extensions/dist/emoticon': ['defaultEmoticons']
117
+      },
118
+    }),
119
+    // url(),
120
+    // less(),
121
+    postcss({
122
+      extensions: ['.css', '.less'],
123
+      plugins: [
124
+        autoprefixer(),
125
+        postcssUrl({
126
+          url: 'inline'
127
+        }),
128
+      ],
129
+      modules: true,
130
+    }),
131
+    ts({
132
+      exclude: "node_modules/**",
133
+      transpiler: "babel",
134
+      hook: {
135
+        outputPath: (path, kind) => {
136
+          return path
137
+        }
138
+      }
139
+    }),
140
+    // typescript({
141
+    //   include: ["*.js+(|x)", "**/*.js+(|x)", "*.ts+(|x)", "**/*.ts+(|x)"],
142
+    //   verbosity: 3,
143
+    //   clean: true,
144
+    //   typescript: require('typescript'),
145
+    //   // useTsconfigDeclarationDir: true,
146
+    //   rollupCommonJSResolveHack: true,
147
+    //   objectHashIgnoreUnknownHack: true,
148
+    // }),
149
+    babel({
150
+      exclude: "node_modules/**",
151
+      runtimeHelpers: true,
152
+      extensions,
153
+    }),
154
+    alias({
155
+      entries: [
156
+        { find: '@', replacement: 'src' },
157
+        { find: '@components', replacement: 'src/components' },
158
+      ],
159
+    }),
160
+    visualizer({
161
+      sourcemap: true,
162
+      open: true,
163
+    }),
164
+    analyze(),
165
+  ],
166
+  onwarn: function(warning) {
167
+    // Skip certain warnings
168
+    // should intercept ... but doesn't in some rollup versions
169
+    if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
170
+    // console.warn everything else
171
+    console.warn( warning.message );
172
+  }
173
+};

+ 35
- 0
src/components/comment/CommentItem.tsx View File

@@ -0,0 +1,35 @@
1
+import React, { Component } from 'react'
2
+
3
+export interface CommentItemData {
4
+  content: string;
5
+  created: number;
6
+  favor_count: number;
7
+  favored: boolean;
8
+  id: string;
9
+  is_speak: boolean;
10
+  medias: any;
11
+  replies: Array<any>
12
+  reply_count: number;
13
+  user_avatar: string;
14
+  user_id: number;
15
+  user_name: string;
16
+}
17
+
18
+interface IP {
19
+  data: CommentItemData;
20
+}
21
+
22
+interface IS {}
23
+
24
+export default class CommentItem extends Component<IP, IS> {
25
+  render() {
26
+    console.log(this.props.data.content);
27
+    return (
28
+      <div>
29
+        {
30
+          this.props.data.content
31
+        }
32
+      </div>
33
+    )
34
+  }
35
+}

+ 20
- 0
src/components/comment/CommentList.tsx View File

@@ -0,0 +1,20 @@
1
+import React, { PureComponent } from 'react'
2
+import CommentItem, { CommentItemData } from './CommentItem'
3
+
4
+interface IP {
5
+  list: Array<CommentItemData>
6
+}
7
+
8
+interface IS {
9
+
10
+}
11
+
12
+export default class CommentList extends PureComponent<IP, IS> {
13
+  render() {
14
+    return (
15
+      <div>
16
+        {this.props.list.map(i => <CommentItem data={i} />)}
17
+      </div>
18
+    )
19
+  }
20
+}

+ 13
- 0
src/components/comment/README.md View File

@@ -0,0 +1,13 @@
1
+# comment
2
+
3
+通用评论组件
4
+
5
+** `veresion 0.1` **
6
+
7
+## Getting Started
8
+
9
+
10
+## Running the tests
11
+
12
+
13
+## Built

+ 34
- 0
src/components/comment/config/constant.js View File

@@ -0,0 +1,34 @@
1
+export const ERROR_DEFAULT = "出错了!";
2
+
3
+export const LIMIT = 10; // 默认 limit
4
+
5
+export const DRIVER_LICENSE_PATH = "/comment";
6
+
7
+export const OSS_LINK = "//links-comment.oss-cn-beijing.aliyuncs.com";
8
+
9
+export const MAX_UPLOAD_NUMBER = 4;
10
+
11
+export const URL_REGEXP = /((http(s)?:)?\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g;
12
+
13
+export const REGEXP = /\[[^[\]]+?\]/g;
14
+
15
+export const AVATAR = "";
16
+
17
+export const IMAGE_SPLIT = "IMAGE_SPLIT";
18
+
19
+export const IMAGE_PROCESS = "?x-oss-process=image/resize,h_350";
20
+export const IMAGE_PROCESS_SMALL = "?x-oss-process=image/resize,h_100";
21
+export const IMAGE_PROCESS_LARGE = "?x-oss-process=image/resize,h_500";
22
+
23
+export const COMMENT_TYPE = {
24
+  COMMENT: "comment",
25
+  REPLY: "reply"
26
+};
27
+
28
+// 线上静态库地址
29
+export const LANGUAGE_LINK =
30
+  process.env.NODE_ENV === "production"
31
+    ? "//a.links123.cn/lang"
32
+    : "//a.links123.net/lang";
33
+
34
+export const COMMENT_API = `http://api.links123.net/comment/v1`

+ 18
- 0
src/components/comment/context/index.ts View File

@@ -0,0 +1,18 @@
1
+import React from 'react';
2
+import { LIMIT } from "@/components/comment/config/constant";
3
+
4
+export const CommentContext = React.createContext('comment')
5
+
6
+// const DEFAULT_TYPE = 1;
7
+// const DEFAULT_BUSSINESSID = 'test';
8
+// const DEFAULT_BUSSINESS_USER_ID = 4;
9
+// const DEFAULT_PAGE = 1;
10
+// const DEFAULT_LIMIT = LIMIT;
11
+
12
+export const DefaultValue = {
13
+  type: 1,
14
+  bussiness_id: 'test',
15
+  bussiness_user_id: 4,
16
+  page: 1,
17
+  limit: LIMIT,
18
+}

+ 14
- 0
src/components/comment/demo.jsx View File

@@ -0,0 +1,14 @@
1
+import React from 'react';
2
+import CommentCombine from './index';
3
+import styles from './index.less';
4
+
5
+export class CommentDemo extends React.Component {
6
+  render() {
7
+    return (
8
+      <div className={styles.playgroundWrapper}>
9
+        <CommentCombine />
10
+      </div>
11
+    )
12
+  }
13
+}
14
+export default CommentDemo;

+ 94
- 0
src/components/comment/index.jsx View File

@@ -0,0 +1,94 @@
1
+import React from 'react';
2
+import { getComment } from '@/services/comment';
3
+import { CommentContext, DefaultValue } from './context';
4
+import styles from './index.less';
5
+import CommentList from './CommentList';
6
+
7
+export class CommentCombine extends React.PureComponent {
8
+  constructor(props) {
9
+    super(props);
10
+    this.state = {
11
+      ...DefaultValue,
12
+    }
13
+  }
14
+
15
+  render() {
16
+    return (
17
+      <CommentContext.Provider value={this.state}>
18
+        <Comment />
19
+      </CommentContext.Provider>
20
+    )
21
+  }
22
+}
23
+
24
+export class Comment extends React.PureComponent {
25
+  static contextType = CommentContext;
26
+  static propTypes = {}
27
+  static defaultProps = {}
28
+
29
+  constructor(props) {
30
+    super(props);
31
+    this.state = {
32
+      comment_data: null,
33
+    };
34
+  }
35
+
36
+  componentDidMount = async () => {
37
+    const { type, limit, page, bussiness_id } = this.context;
38
+    const res = await getComment({
39
+      type,
40
+      limit,
41
+      page,
42
+      businessId: bussiness_id,
43
+    });
44
+    console.log("res:", res);
45
+    this.setState({
46
+      comment_data: res,
47
+    })
48
+  }
49
+
50
+  renderCommentList = (list) => {
51
+    // content: "[e101][e102]"
52
+    // created: 1582352617
53
+    // favor_count: 0
54
+    // favored: false
55
+    // id: "5e50c8e9818eda000192773d"
56
+    // is_speak: false
57
+    // medias: null
58
+    // replies: []
59
+    // reply_count: 0
60
+    // user_avatar: "https://links123-images.oss-cn-hangzhou.aliyuncs.com/avatar/2020/2/7/1326acc4b1609c8ecf52e94d58a38384.jpg?x-oss-process=image/resize,h_100"
61
+    // user_id: 71770
62
+    // user_name: "EvoKou"
63
+    return <CommentList list={list} />
64
+  }
65
+
66
+  renderComment = () => {
67
+    const { comment_data } = this.state;
68
+    if (comment_data === null) return "数据载入中";
69
+    const { list, total, page } = comment_data;
70
+    return (
71
+      <div>
72
+        total: {total}
73
+        page: {page}
74
+        <div>
75
+          {
76
+            this.renderCommentList(list)
77
+          }
78
+        </div>
79
+      </div>
80
+    )
81
+  }
82
+
83
+  render() {
84
+    console.log("context", this.context);
85
+    return (
86
+      <div>
87
+        {JSON.stringify(this.context)}
88
+        {this.renderComment()}
89
+      </div>
90
+    )
91
+  }
92
+}
93
+
94
+export default CommentCombine;

+ 3
- 0
src/components/comment/index.less View File

@@ -0,0 +1,3 @@
1
+.playgroundWrapper {
2
+  min-height: 100%;
3
+}

+ 14
- 0
src/helper/index.ts View File

@@ -0,0 +1,14 @@
1
+export function converObj(data: any) {
2
+  let _result = [];
3
+  for (let _key in data) {
4
+      let v = data[_key];
5
+      if (v.constructor === Array) {
6
+          v.forEach(function(_value) {
7
+              _result.push(`${_key}=${_value}`)
8
+          });
9
+      } else {
10
+          _result.push(`${_key}=${v}`)
11
+      }
12
+  }
13
+  return _result.join('&');
14
+}

+ 105
- 0
src/services/comment.ts View File

@@ -0,0 +1,105 @@
1
+import axios from "axios";
2
+import { converObj } from "@/helper";
3
+import { COMMENT_API } from "@/components/comment/config/constant";
4
+
5
+type CommonListResponse = {
6
+  list: Array<any>;
7
+  total: number;
8
+  page: number;
9
+};
10
+
11
+interface CommonResponse {
12
+  config: any;
13
+  data: CommonListResponse;
14
+  headers: any;
15
+  request: any;
16
+  status: number;
17
+  statusText: string;
18
+}
19
+
20
+
21
+export const getComment = async ({
22
+  type,
23
+  businessId,
24
+  isSpeak,
25
+  page,
26
+  limit,
27
+}: {
28
+  type: string;
29
+  businessId: string;
30
+  isSpeak?: boolean;
31
+  page: string;
32
+  limit: string;
33
+}): Promise<any> => {
34
+  const r: CommonResponse = await axios.get(`${COMMENT_API}/comments?${converObj({
35
+    type,
36
+    business_id: businessId,
37
+    page,
38
+    limit,
39
+  })}`);
40
+  return r.data;
41
+}
42
+
43
+export const createComment = async ({
44
+  type,
45
+  businessId,
46
+  businessUserId,
47
+  content,
48
+}: {
49
+  type: string;
50
+  businessId: string;
51
+  businessUserId: string;
52
+  content: string;
53
+}): Promise<any> => {
54
+  const r = await axios.post(`${COMMENT_API}/comments`, {
55
+    method: 'post',
56
+    withCredentials: true,
57
+    data: {
58
+      type,
59
+      businessId,
60
+      businessUserId,
61
+      content,
62
+    },
63
+  });
64
+  return r;
65
+}
66
+
67
+export const updateComment = async ({
68
+  id,
69
+  content,
70
+} : {
71
+  id: string;
72
+  content: string;
73
+}) => {
74
+  const r = await axios.post(`${COMMENT_API}/comments/${id}`, {
75
+    method: 'post',
76
+    withCredentials: true,
77
+    data: {
78
+      content,
79
+    },
80
+  });
81
+  return r;
82
+}
83
+
84
+export const deleteComment = async ({
85
+  id,
86
+}: {
87
+  id: string;
88
+}) => {
89
+  const r = await axios.delete(`${COMMENT_API}/comments/${id}`);
90
+  return r;
91
+}
92
+
93
+export const favorComment = async ({
94
+  id,
95
+  commentId,
96
+  userId,
97
+} : {
98
+  id: string;
99
+  commentId: string;
100
+  userId: number;
101
+}) => {
102
+  // const r = await axios
103
+}
104
+
105
+// export const getFavorUserList = async () => {}

+ 14
- 0
stories/comment.stories.jsx View File

@@ -0,0 +1,14 @@
1
+import React from 'react';
2
+import CommentDemo from '@/components/comment/demo';
3
+
4
+export default {
5
+  title: 'Comment',
6
+};
7
+
8
+export const comment = () => {
9
+  return (
10
+    <div>
11
+      <CommentDemo />
12
+    </div>
13
+  )
14
+}

+ 18
- 0
stories/index.stories.jsx View File

@@ -0,0 +1,18 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import { action } from '@storybook/addon-actions';
4
+
5
+export default {
6
+  component: Button,
7
+  title: 'Button',
8
+};
9
+
10
+export const text = () => <Button onClick={action('clicked')}>Hello Button</Button>;
11
+
12
+export const emoji = () => (
13
+  <Button onClick={action('clicked')}>
14
+    <span role="img" aria-label="so cool">
15
+      😀 😎 👍 💯
16
+    </span>
17
+  </Button>
18
+);

+ 49
- 0
tsconfig.json View File

@@ -0,0 +1,49 @@
1
+{
2
+  "compilerOptions": {
3
+    "target": "esnext",
4
+    "rootDirs": [
5
+      "src",
6
+      "stories"
7
+    ],
8
+    "lib": [
9
+      "dom",
10
+      "dom.iterable",
11
+      "esnext"
12
+    ],
13
+    "allowJs": true,
14
+    // rollup build:lib plugin require
15
+    "noEmitHelpers": false,
16
+    "importHelpers": true,
17
+    "noResolve": false,
18
+    "noEmit": false,
19
+    "inlineSourceMap": false,
20
+    // 
21
+    "declaration": true,
22
+    // "declarationDir": "./declare",
23
+    "skipLibCheck": true,
24
+    "esModuleInterop": true,
25
+    "removeComments": true,
26
+    "allowSyntheticDefaultImports": true,
27
+    "strict": true,
28
+    "forceConsistentCasingInFileNames": true,
29
+    "moduleResolution": "node",
30
+    "module": "esnext",
31
+    "resolveJsonModule": true,
32
+    "isolatedModules": true,
33
+    "noEmit": true,
34
+    "traceResolution": true,
35
+    "jsx": "react",
36
+    "baseUrl": ".",
37
+    "paths": {
38
+      "@/*": ["src/*"],
39
+      "@components/*": [ "src/components/*" ]
40
+    }
41
+  },
42
+  "include": [
43
+    "src/**/*",
44
+    "stories/**/*"
45
+  ],
46
+  "exclude": [
47
+    "node_modules"
48
+  ]
49
+}

+ 15386
- 0
yarn.lock
File diff suppressed because it is too large
View File