Procházet zdrojové kódy

Merge pull request #4130 from ant-design/v4

merge  V4
zombieJ před 6 roky
rodič
revize
666b74d65d
100 změnil soubory, kde provedl 5348 přidání a 6161 odebrání
  1. 1 1
      .eslintignore
  2. 3 1
      .eslintrc.js
  3. 0 1
      .gitignore
  4. 5 3
      .prettierrc
  5. 5 2
      .stylelintrc.json
  6. 67 19
      config/config.js
  7. 60 0
      config/defaultSettings.ts
  8. 11 10
      config/plugin.config.js
  9. 0 297
      config/router.config.js
  10. 56 0
      create-umi/README.md
  11. 131 0
      create-umi/package.json
  12. 1 1
      jest-puppeteer.config.js
  13. 4199 0
      lambda/mock/index.js
  14. 0 336
      mock/api.js
  15. 0 196
      mock/chart.js
  16. 0 15
      mock/geographic.js
  17. 0 1784
      mock/geographic/city.json
  18. 0 138
      mock/geographic/province.json
  19. 0 0
      mock/notices.ts
  20. 0 177
      mock/profile.js
  21. 5 0
      mock/route.ts
  22. 0 131
      mock/rule.js
  23. 0 0
      mock/user.ts
  24. 72 37
      package.json
  25. 129 0
      scripts/fetch-blocks.js
  26. 0 3
      scripts/generateMock.js
  27. 0 23
      scripts/getPrettierFiles.js
  28. 161 0
      scripts/insertCode.js
  29. 0 50
      scripts/lint-prettier.js
  30. 0 46
      scripts/prettier.js
  31. 77 0
      scripts/repalceRouter.js
  32. 236 0
      scripts/router.config.js
  33. 0 11
      src/app.js
  34. 0 98
      src/components/ActiveChart/index.js
  35. 0 51
      src/components/ActiveChart/index.less
  36. 0 13
      src/components/ArticleListContent/index.d.ts
  37. 0 17
      src/components/ArticleListContent/index.js
  38. 0 38
      src/components/ArticleListContent/index.less
  39. 0 8
      src/components/Authorized/Authorized.js
  40. 29 0
      src/components/Authorized/Authorized.tsx
  41. 0 13
      src/components/Authorized/AuthorizedRoute.d.ts
  42. 0 15
      src/components/Authorized/AuthorizedRoute.js
  43. 32 0
      src/components/Authorized/AuthorizedRoute.tsx
  44. 0 55
      src/components/Authorized/CheckPermissions.test.js
  45. 18 5
      src/components/Authorized/CheckPermissions.js
  46. 28 10
      src/components/Authorized/PromiseRender.js
  47. 12 12
      src/components/Authorized/Secured.js
  48. 0 23
      src/components/Authorized/demo/AuthorizedArray.md
  49. 0 27
      src/components/Authorized/demo/AuthorizedFunction.md
  50. 0 25
      src/components/Authorized/demo/basic.md
  51. 0 28
      src/components/Authorized/demo/secured.md
  52. 0 32
      src/components/Authorized/index.d.ts
  53. 0 54
      src/components/Authorized/index.md
  54. 3 1
      src/components/Authorized/index.js
  55. 7 5
      src/components/Authorized/renderAuthorize.js
  56. 0 15
      src/components/AvatarList/AvatarItem.d.ts
  57. 0 46
      src/components/AvatarList/demo/maxLength.md
  58. 0 30
      src/components/AvatarList/demo/simple.md
  59. 0 14
      src/components/AvatarList/index.d.ts
  60. 0 24
      src/components/AvatarList/index.en-US.md
  61. 0 61
      src/components/AvatarList/index.js
  62. 0 50
      src/components/AvatarList/index.less
  63. 0 29
      src/components/AvatarList/index.test.js
  64. 0 25
      src/components/AvatarList/index.zh-CN.md
  65. 0 15
      src/components/Charts/Bar/index.d.ts
  66. 0 124
      src/components/Charts/Bar/index.js
  67. 0 14
      src/components/Charts/ChartCard/index.d.ts
  68. 0 82
      src/components/Charts/ChartCard/index.js
  69. 0 75
      src/components/Charts/ChartCard/index.less
  70. 0 8
      src/components/Charts/Field/index.d.ts
  71. 0 12
      src/components/Charts/Field/index.js
  72. 0 17
      src/components/Charts/Field/index.less
  73. 0 11
      src/components/Charts/Gauge/index.d.ts
  74. 0 167
      src/components/Charts/Gauge/index.js
  75. 0 29
      src/components/Charts/MiniArea/index.d.ts
  76. 0 108
      src/components/Charts/MiniArea/index.js
  77. 0 12
      src/components/Charts/MiniBar/index.d.ts
  78. 0 51
      src/components/Charts/MiniBar/index.js
  79. 0 11
      src/components/Charts/MiniProgress/index.d.ts
  80. 0 34
      src/components/Charts/MiniProgress/index.js
  81. 0 37
      src/components/Charts/MiniProgress/index.less
  82. 0 21
      src/components/Charts/Pie/index.d.ts
  83. 0 248
      src/components/Charts/Pie/index.js
  84. 0 94
      src/components/Charts/Pie/index.less
  85. 0 15
      src/components/Charts/Radar/index.d.ts
  86. 0 184
      src/components/Charts/Radar/index.js
  87. 0 46
      src/components/Charts/Radar/index.less
  88. 0 11
      src/components/Charts/TagCloud/index.d.ts
  89. 0 167
      src/components/Charts/TagCloud/index.js
  90. 0 6
      src/components/Charts/TagCloud/index.less
  91. 0 14
      src/components/Charts/TimelineChart/index.d.ts
  92. 0 120
      src/components/Charts/TimelineChart/index.js
  93. 0 3
      src/components/Charts/TimelineChart/index.less
  94. 0 10
      src/components/Charts/WaterWave/index.d.ts
  95. 0 213
      src/components/Charts/WaterWave/index.js
  96. 0 28
      src/components/Charts/WaterWave/index.less
  97. 0 62
      src/components/Charts/autoHeight.js
  98. 0 3
      src/components/Charts/bizcharts.d.ts
  99. 0 3
      src/components/Charts/bizcharts.js
  100. 0 0
      src/components/Charts/demo/bar.md

+ 1 - 1
.eslintignore

@@ -1,3 +1,3 @@
 /lambda/
 /scripts
-/config
+/config

+ 3 - 1
.eslintrc.js

@@ -10,8 +10,8 @@ module.exports = {
     jasmine: true,
   },
   globals: {
-    ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true, // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
     page: true,
+    ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
   },
   rules: {
     'react/jsx-filename-extension': [1, { extensions: ['.js'] }],
@@ -35,6 +35,8 @@ module.exports = {
     'linebreak-style': 0,
   },
   settings: {
+    // support import modules from TypeScript files in JavaScript files
+    'import/resolver': { node: { extensions: ['.js', '.ts', '.tsx'] } },
     polyfills: ['fetch', 'promises', 'url', 'object-assign'],
   },
 };

+ 0 - 1
.gitignore

@@ -26,7 +26,6 @@ package-lock.json
 .history
 *.log
 functions/*
-lambda/mock/index.js
 .temp/**
 
 # umi

+ 5 - 3
.prettierrc

@@ -1,12 +1,14 @@
 {
   "singleQuote": true,
-  "trailingComma": "es5",
+  "trailingComma": "all",
   "printWidth": 100,
   "proseWrap": "never",
   "overrides": [
     {
       "files": ".prettierrc",
-      "options": { "parser": "json" }
+      "options": {
+        "parser": "json"
+      }
     }
   ]
-}
+}

+ 5 - 2
.stylelintrc.json

@@ -5,9 +5,12 @@
     "stylelint-config-rational-order",
     "stylelint-config-prettier"
   ],
-  "plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
+  "plugins": [
+    "stylelint-order",
+    "stylelint-declaration-block-no-ignored-properties"
+  ],
   "rules": {
     "no-descending-specificity": null,
     "plugin/declaration-block-no-ignored-properties": true
   }
-}
+}

+ 67 - 19
config/config.js

@@ -1,15 +1,16 @@
 // https://umijs.org/config/
 import os from 'os';
-import pageRoutes from './router.config';
-import webpackPlugin from './plugin.config';
-import defaultSettings from '../src/defaultSettings';
 import slash from 'slash2';
-
+import { IPlugin, IConfig } from 'umi-types';
+import defaultSettings from './defaultSettings';
+import webpackPlugin from './plugin.config';
 const { pwa, primaryColor } = defaultSettings;
-// preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
-const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, TEST } = process.env;
 
-const plugins = [
+// preview.pro.ant.design only do not use in your production ;
+// preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
+
+const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, TEST, NODE_ENV } = process.env;
+const plugins: IPlugin[] = [
   [
     'umi-plugin-react',
     {
@@ -18,9 +19,12 @@ const plugins = [
         hmr: true,
       },
       locale: {
-        enable: true, // default false
-        default: 'zh-CN', // default zh-CN
-        baseNavigator: true, // default true, when it is true, will use `navigator.language` overwrite default
+        // default false
+        enable: true,
+        // default zh-CN
+        default: 'zh-CN',
+        // default true, when it is true, will use `navigator.language` overwrite default
+        baseNavigator: true,
       },
       dynamicImport: {
         loadingComponent: './components/PageLoading/index',
@@ -46,10 +50,18 @@ const plugins = [
         : {}),
     },
   ],
-];
-
-// 针对 preview.pro.ant.design 的 GA 统计代码
+  [
+    'umi-plugin-pro-block',
+    {
+      moveMock: false,
+      moveService: false,
+      modifyRequest: true,
+      autoAddMenu: true,
+    },
+  ],
+]; // 针对 preview.pro.ant.design 的 GA 统计代码
 // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
+
 if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') {
   plugins.push([
     'umi-plugin-ga',
@@ -59,6 +71,18 @@ if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') {
   ]);
 }
 
+const uglifyJSOptions =
+  NODE_ENV === 'production'
+    ? {
+        uglifyOptions: {
+          // remove console.* except console.error
+          compress: {
+            drop_console: true,
+            pure_funcs: ['console.error'],
+          },
+        },
+      }
+    : {};
 export default {
   // add for transfer to umi
   plugins,
@@ -72,7 +96,22 @@ export default {
   },
   devtool: ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION ? 'source-map' : false,
   // 路由配置
-  routes: pageRoutes,
+  routes: [
+    {
+      path: '/',
+      component: '../layouts/BasicLayout',
+      Routes: ['src/pages/Authorized'],
+      authority: ['admin', 'user'],
+      routes: [
+        {
+          path: '/',
+          name: 'welcome',
+          icon: 'smile',
+          component: './Welcome',
+        },
+      ],
+    },
+  ],
   // Theme for antd
   // https://ant.design/docs/react/customize-theme-cn
   theme: {
@@ -92,7 +131,13 @@ export default {
   disableRedirectHoist: true,
   cssLoaderOptions: {
     modules: true,
-    getLocalIdent: (context, localIdentName, localName) => {
+    getLocalIdent: (
+      context: {
+        resourcePath: string;
+      },
+      localIdentName: string,
+      localName: string,
+    ) => {
       if (
         context.resourcePath.includes('node_modules') ||
         context.resourcePath.includes('ant.design.pro.less') ||
@@ -100,21 +145,24 @@ export default {
       ) {
         return localName;
       }
+
       const match = context.resourcePath.match(/src(.*)/);
+
       if (match && match[1]) {
         const antdProPath = match[1].replace('.less', '');
         const arr = slash(antdProPath)
           .split('/')
-          .map(a => a.replace(/([A-Z])/g, '-$1'))
-          .map(a => a.toLowerCase());
+          .map((a: string) => a.replace(/([A-Z])/g, '-$1'))
+          .map((a: string) => a.toLowerCase());
         return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
       }
+
       return localName;
     },
   },
   manifest: {
     basePath: '/',
   },
-
+  uglifyJSOptions,
   chainWebpack: webpackPlugin,
-};
+} as IConfig;

+ 60 - 0
config/defaultSettings.ts

@@ -0,0 +1,60 @@
+import { MenuTheme } from 'antd/es/menu';
+
+export type ContentWidth = 'Fluid' | 'Fixed';
+
+export interface DefaultSettings {
+  /**
+   * theme for nav menu
+   */
+  navTheme: MenuTheme;
+  /**
+   * primary color of ant design
+   */
+  primaryColor: string;
+  /**
+   * nav menu position: `sidemenu` or `topmenu`
+   */
+  layout: 'sidemenu' | 'topmenu';
+  /**
+   * layout of content: `Fluid` or `Fixed`, only works when layout is topmenu
+   */
+  contentWidth: ContentWidth;
+  /**
+   * sticky header
+   */
+  fixedHeader: boolean;
+  /**
+   * auto hide header
+   */
+  autoHideHeader: boolean;
+  /**
+   * sticky siderbar
+   */
+  fixSiderbar: boolean;
+  menu: { locale: boolean };
+  title: string;
+  pwa: boolean;
+  // Your custom iconfont Symbol script Url
+  // eg://at.alicdn.com/t/font_1039637_btcrd5co4w.js
+  // 注意:如果需要图标多色,Iconfont 图标项目里要进行批量去色处理
+  // Usage: https://github.com/ant-design/ant-design-pro/pull/3517
+  iconfontUrl: string;
+  colorWeak: boolean;
+}
+
+export default {
+  navTheme: 'dark',
+  primaryColor: '#1890FF',
+  layout: 'sidemenu',
+  contentWidth: 'Fluid',
+  fixedHeader: false,
+  autoHideHeader: false,
+  fixSiderbar: false,
+  colorWeak: false,
+  menu: {
+    locale: true,
+  },
+  title: 'Ant Design Pro',
+  pwa: false,
+  iconfontUrl: '',
+} as DefaultSettings;

+ 11 - 10
config/plugin.config.js

@@ -4,7 +4,7 @@ import MergeLessPlugin from 'antd-pro-merge-less';
 import AntDesignThemePlugin from 'antd-theme-webpack-plugin';
 import path from 'path';
 
-function getModulePackageName(module) {
+function getModulePackageName(module: { context: string }) {
   if (!module.context) return null;
 
   const nodeModulesPath = path.join(__dirname, '../node_modules/');
@@ -14,16 +14,16 @@ function getModulePackageName(module) {
 
   const moduleRelativePath = module.context.substring(nodeModulesPath.length);
   const [moduleDirName] = moduleRelativePath.split(path.sep);
-  let packageName = moduleDirName;
+  let packageName: string | null = moduleDirName;
   // handle tree shaking
-  if (packageName.match('^_')) {
+  if (packageName && packageName.match('^_')) {
     // eslint-disable-next-line prefer-destructuring
-    packageName = packageName.match(/^_(@?[^@]+)/)[1];
+    packageName = packageName.match(/^_(@?[^@]+)/)![1];
   }
   return packageName;
 }
 
-export default config => {
+export default (config: any) => {
   // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
   if (
     process.env.ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ||
@@ -62,18 +62,19 @@ export default config => {
       minSize: 0,
       cacheGroups: {
         vendors: {
-          test: module => {
+          test: (module: { context: string }) => {
             const packageName = getModulePackageName(module);
             if (packageName) {
               return ['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0;
             }
             return false;
           },
-          name(module) {
+          name(module: { context: string }) {
             const packageName = getModulePackageName(module);
-
-            if (['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0) {
-              return 'viz'; // visualization package
+            if (packageName) {
+              if (['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0) {
+                return 'viz'; // visualization package
+              }
             }
             return 'misc';
           },

+ 0 - 297
config/router.config.js

@@ -1,297 +0,0 @@
-export default [
-  // user
-  {
-    path: '/user',
-    component: '../layouts/UserLayout',
-    routes: [
-      { path: '/user', redirect: '/user/login' },
-      { path: '/user/login', name: 'login', component: './User/Login' },
-      { path: '/user/register', name: 'register', component: './User/Register' },
-      {
-        path: '/user/register-result',
-        name: 'register.result',
-        component: './User/RegisterResult',
-      },
-      {
-        component: '404',
-      },
-    ],
-  },
-  // app
-  {
-    path: '/',
-    component: '../layouts/BasicLayout',
-    Routes: ['src/pages/Authorized'],
-    routes: [
-      // dashboard
-      { path: '/', redirect: '/dashboard/analysis', authority: ['admin', 'user'] },
-      {
-        path: '/dashboard',
-        name: 'dashboard',
-        icon: 'dashboard',
-        routes: [
-          {
-            path: '/dashboard/analysis',
-            name: 'analysis',
-            component: './Dashboard/Analysis',
-          },
-          {
-            path: '/dashboard/monitor',
-            name: 'monitor',
-            component: './Dashboard/Monitor',
-          },
-          {
-            path: '/dashboard/workplace',
-            name: 'workplace',
-            component: './Dashboard/Workplace',
-          },
-        ],
-      },
-      // forms
-      {
-        path: '/form',
-        icon: 'form',
-        name: 'form',
-        routes: [
-          {
-            path: '/form/basic-form',
-            name: 'basicform',
-            component: './Forms/BasicForm',
-          },
-          {
-            path: '/form/step-form',
-            name: 'stepform',
-            component: './Forms/StepForm',
-            hideChildrenInMenu: true,
-            routes: [
-              {
-                path: '/form/step-form',
-                redirect: '/form/step-form/info',
-              },
-              {
-                path: '/form/step-form/info',
-                name: 'info',
-                component: './Forms/StepForm/Step1',
-              },
-              {
-                path: '/form/step-form/confirm',
-                name: 'confirm',
-                component: './Forms/StepForm/Step2',
-              },
-              {
-                path: '/form/step-form/result',
-                name: 'result',
-                component: './Forms/StepForm/Step3',
-              },
-            ],
-          },
-          {
-            path: '/form/advanced-form',
-            name: 'advancedform',
-            authority: ['admin'],
-            component: './Forms/AdvancedForm',
-          },
-        ],
-      },
-      // list
-      {
-        path: '/list',
-        icon: 'table',
-        name: 'list',
-        routes: [
-          {
-            path: '/list/table-list',
-            name: 'searchtable',
-            component: './List/TableList',
-          },
-          {
-            path: '/list/basic-list',
-            name: 'basiclist',
-            component: './List/BasicList',
-          },
-          {
-            path: '/list/card-list',
-            name: 'cardlist',
-            component: './List/CardList',
-          },
-          {
-            path: '/list/search',
-            name: 'searchlist',
-            component: './List/List',
-            routes: [
-              {
-                path: '/list/search',
-                redirect: '/list/search/articles',
-              },
-              {
-                path: '/list/search/articles',
-                name: 'articles',
-                component: './List/Articles',
-              },
-              {
-                path: '/list/search/projects',
-                name: 'projects',
-                component: './List/Projects',
-              },
-              {
-                path: '/list/search/applications',
-                name: 'applications',
-                component: './List/Applications',
-              },
-            ],
-          },
-        ],
-      },
-      {
-        path: '/profile',
-        name: 'profile',
-        icon: 'profile',
-        routes: [
-          // profile
-          {
-            path: '/profile/basic',
-            name: 'basic',
-            component: './Profile/BasicProfile',
-          },
-          {
-            path: '/profile/basic/:id',
-            hideInMenu: true,
-            component: './Profile/BasicProfile',
-          },
-          {
-            path: '/profile/advanced',
-            name: 'advanced',
-            authority: ['admin'],
-            component: './Profile/AdvancedProfile',
-          },
-        ],
-      },
-      {
-        name: 'result',
-        icon: 'check-circle-o',
-        path: '/result',
-        routes: [
-          // result
-          {
-            path: '/result/success',
-            name: 'success',
-            component: './Result/Success',
-          },
-          { path: '/result/fail', name: 'fail', component: './Result/Error' },
-        ],
-      },
-      {
-        name: 'exception',
-        icon: 'warning',
-        path: '/exception',
-        routes: [
-          // exception
-          {
-            path: '/exception/403',
-            name: 'not-permission',
-            component: './Exception/403',
-          },
-          {
-            path: '/exception/404',
-            name: 'not-find',
-            component: './Exception/404',
-          },
-          {
-            path: '/exception/500',
-            name: 'server-error',
-            component: './Exception/500',
-          },
-          {
-            path: '/exception/trigger',
-            name: 'trigger',
-            hideInMenu: true,
-            component: './Exception/TriggerException',
-          },
-        ],
-      },
-      {
-        name: 'account',
-        icon: 'user',
-        path: '/account',
-        routes: [
-          {
-            path: '/account/center',
-            name: 'center',
-            component: './Account/Center/Center',
-            routes: [
-              {
-                path: '/account/center',
-                redirect: '/account/center/articles',
-              },
-              {
-                path: '/account/center/articles',
-                component: './Account/Center/Articles',
-              },
-              {
-                path: '/account/center/applications',
-                component: './Account/Center/Applications',
-              },
-              {
-                path: '/account/center/projects',
-                component: './Account/Center/Projects',
-              },
-            ],
-          },
-          {
-            path: '/account/settings',
-            name: 'settings',
-            component: './Account/Settings/Info',
-            routes: [
-              {
-                path: '/account/settings',
-                redirect: '/account/settings/base',
-              },
-              {
-                path: '/account/settings/base',
-                component: './Account/Settings/BaseView',
-              },
-              {
-                path: '/account/settings/security',
-                component: './Account/Settings/SecurityView',
-              },
-              {
-                path: '/account/settings/binding',
-                component: './Account/Settings/BindingView',
-              },
-              {
-                path: '/account/settings/notification',
-                component: './Account/Settings/NotificationView',
-              },
-            ],
-          },
-        ],
-      },
-      //  editor
-      {
-        name: 'editor',
-        icon: 'highlight',
-        path: '/editor',
-        routes: [
-          {
-            path: '/editor/flow',
-            name: 'flow',
-            component: './Editor/GGEditor/Flow',
-          },
-          {
-            path: '/editor/mind',
-            name: 'mind',
-            component: './Editor/GGEditor/Mind',
-          },
-          {
-            path: '/editor/koni',
-            name: 'koni',
-            component: './Editor/GGEditor/Koni',
-          },
-        ],
-      },
-      {
-        component: '404',
-      },
-    ],
-  },
-];

+ 56 - 0
create-umi/README.md

@@ -0,0 +1,56 @@
+# Ant Design Pro
+
+This project is initialized with [Ant Design Pro](https://pro.ant.design). Follow is the quick guide for how to use.
+
+## Environment Prepare
+
+Install `node_modules`:
+```bash
+npm install
+```
+
+or
+
+```bash
+yarn
+```
+
+## Provided Scripts
+
+Ant Design Pro provides some useful script to help you quick start and build with web project, code style check and test.
+
+Scripts provided in `package.json`. It's safe to modify or add additional script:
+
+### Start project
+
+```bash
+npm start
+```
+
+### Build project
+
+```bash
+npm run build
+```
+
+### Check code style
+
+```bash
+npm run lint
+```
+
+You can also use script to auto fix some lint error:
+
+```bash
+npm run lint:fix
+```
+
+### Test code
+
+```bash
+npm test
+```
+
+## More
+
+You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro).

+ 131 - 0
create-umi/package.json

@@ -0,0 +1,131 @@
+{
+  "name": "ant-design-pro",
+  "version": "4.0.0",
+  "private": true,
+  "description": "An out-of-box UI solution for enterprise applications",
+  "scripts": {
+    "analyze": "cross-env ANALYZE=1 umi build",
+    "build": "umi build",
+    "generateMock": "node ./scripts/generateMock",
+    "lint": "npm run lint:js && npm run lint:ts && npm run lint:style && npm run lint:prettier",
+    "lint-staged": "lint-staged",
+    "lint-staged:js": "eslint --ext .js",
+    "lint-staged:ts": "tslint",
+    "lint:fix": "eslint --fix --ext .js src tests && npm run lint:style && npm run tslint:fix",
+    "lint:js": "eslint --ext .js src tests",
+    "lint:prettier": "check-prettier lint",
+    "lint:style": "stylelint --fix 'src/**/*.less' --syntax less",
+    "lint:ts": "tslint -p . -c tslint.yml",
+    "prettier": " check-prettier write",
+    "start": "umi dev",
+    "start:no-mock": "cross-env MOCK=none umi dev",
+    "test": "umi test",
+    "test:all": "node ./tests/run-tests.js",
+    "test:component": "umi test ./src/components",
+    "tslint:fix": "tslint --fix 'src/**/*.ts*'"
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "npm run lint-staged"
+    }
+  },
+  "lint-staged": {
+    "**/*.less": "stylelint --syntax less",
+    "**/*.{js,jsx}": "npm run lint-staged:js",
+    "**/*.{js,ts,tsx,md,json,jsx,less}": [ "npm run prettier", "git add" ],
+    "**/*.{ts,tsx}": "npm run lint-staged:ts"
+  },
+  "browserslist": [ "> 1%", "last 2 versions", "not ie <= 10" ],
+  "dependencies": {
+    "@ant-design/pro-layout": "^4.2.0",
+    "@antv/data-set": "^0.10.1",
+    "antd": "^3.16.1",
+    "bizcharts": "^3.5.3-beta.0",
+    "bizcharts-plugin-slider": "^2.1.1-beta.1",
+    "classnames": "^2.2.6",
+    "dva": "^2.4.0",
+    "lodash": "^4.17.10",
+    "lodash-decorators": "^6.0.0",
+    "memoize-one": "^5.0.0",
+    "moment": "^2.22.2",
+    "numeral": "^2.0.6",
+    "omit.js": "^1.0.0",
+    "path-to-regexp": "^2.4.0",
+    "qs": "^6.7.0",
+    "rc-animate": "^2.4.4",
+    "react": "^16.8.5",
+    "react-container-query": "^0.11.0",
+    "react-copy-to-clipboard": "^5.0.1",
+    "react-document-title": "^2.0.3",
+    "react-dom": "^16.7.0",
+    "react-fittext": "^1.0.0",
+    "react-media": "^1.9.2",
+    "react-media-hook2": "^1.0.2"
+  },
+  "devDependencies": {
+    "@types/classnames": "^2.2.7",
+    "@types/history": "^4.7.2",
+    "@types/lodash": "^4.14.123",
+    "@types/react": "^16.8.1",
+    "@types/react-document-title": "^2.0.3",
+    "@types/react-dom": "^16.0.11",
+    "antd-pro-merge-less": "^1.0.0",
+    "antd-theme-webpack-plugin": "^1.2.0",
+    "babel-eslint": "^10.0.1",
+    "chalk": "^2.4.2",
+    "check-prettier": "^1.0.1",
+    "cross-env": "^5.2.0",
+    "cross-port-killer": "^1.0.1",
+    "enzyme": "^3.9.0",
+    "eslint": "^5.13.0",
+    "eslint-config-airbnb": "^17.1.0",
+    "eslint-config-prettier": "^4.1.0",
+    "eslint-plugin-babel": "^5.3.0",
+    "eslint-plugin-compat": "^2.6.3",
+    "eslint-plugin-import": "^2.16.0",
+    "eslint-plugin-jsx-a11y": "^6.2.1",
+    "eslint-plugin-markdown": "^1.0.0",
+    "eslint-plugin-react": "^7.12.4",
+    "express": "^4.16.4",
+    "gh-pages": "^2.0.1",
+    "husky": "^2.2.0",
+    "jest-puppeteer": "^4.1.0",
+    "jsdom-global": "^3.0.2",
+    "less": "^3.9.0",
+    "lint-staged": "^8.1.1",
+    "merge-umi-mock-data": "^1.0.4",
+    "mockjs": "^1.0.1-beta3",
+    "prettier": "^1.17.0",
+    "serverless-http": "^2.0.1",
+    "slash2": "^2.0.0",
+    "stylelint": "^9.10.1",
+    "stylelint-config-css-modules": "^1.3.0",
+    "stylelint-config-prettier": "^5.0.0",
+    "stylelint-config-rational-order": "^0.1.0",
+    "stylelint-config-standard": "^18.2.0",
+    "stylelint-declaration-block-no-ignored-properties": "^2.1.0",
+    "stylelint-order": "^2.0.0",
+    "tslint": "^5.12.1",
+    "tslint-config-prettier": "^1.17.0",
+    "tslint-eslint-rules": "^5.4.0",
+    "tslint-react": "^3.6.0",
+    "umi": "^2.7.0-beta.2",
+    "umi-plugin-ga": "^1.1.3",
+    "umi-plugin-pro-block": "^1.3.0",
+    "umi-plugin-react": "^1.8.0-beta.1",
+    "umi-request": "^1.0.0"
+  },
+  "optionalDependencies": {
+    "puppeteer": "^1.12.1"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "checkFiles": [
+    "src/**/*.js*",
+    "src/**/*.ts*",
+    "src/**/*.less",
+    "config/**/*.js*",
+    "scripts/**/*.js"
+  ]
+}

+ 1 - 1
jest-puppeteer.config.js

@@ -6,7 +6,7 @@ module.exports = {
       '--disable-dev-shm-usage',
       '--no-first-run',
       '--no-zygote',
-      '--no-sandbox'
+      '--no-sandbox',
     ],
   },
 };

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4199 - 0
lambda/mock/index.js


+ 0 - 336
mock/api.js

@@ -1,336 +0,0 @@
-import mockjs from 'mockjs';
-
-const titles = [
-  'Alipay',
-  'Angular',
-  'Ant Design',
-  'Ant Design Pro',
-  'Bootstrap',
-  'React',
-  'Vue',
-  'Webpack',
-];
-const avatars = [
-  'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png', // Alipay
-  'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png', // Angular
-  'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png', // Ant Design
-  'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png', // Ant Design Pro
-  'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png', // Bootstrap
-  'https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png', // React
-  'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png', // Vue
-  'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', // Webpack
-];
-
-const avatars2 = [
-  'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/cnrhVkzwxjPwAaCfPbdc.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/gaOngJwsRYRaVAuXXcmB.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/ubnKSIfAJTxIgXOKlciN.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/WhxKECPNujWoWEFNdnJE.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/psOgztMplJMGpVEqfcgF.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/ZpBqSxLxVEXfcUNoPKrz.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/laiEnJdGHVOhJrUShBaJ.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/UrQsqscbKEpNuJcvBZBu.png',
-];
-
-const covers = [
-  'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/iXjVmWVHbCJAyqvDxdtx.png',
-  'https://gw.alipayobjects.com/zos/rmsportal/gLaIAoVWTtLbBWZNYEMg.png',
-];
-const desc = [
-  '那是一种内在的东西, 他们到达不了,也无法触及的',
-  '希望是一个好东西,也许是最好的,好东西是不会消亡的',
-  '生命就像一盒巧克力,结果往往出人意料',
-  '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
-  '那时候我只会想自己想要什么,从不想自己拥有什么',
-];
-
-const user = [
-  '付小小',
-  '曲丽丽',
-  '林东东',
-  '周星星',
-  '吴加好',
-  '朱偏右',
-  '鱼酱',
-  '乐哥',
-  '谭小仪',
-  '仲尼',
-];
-
-function fakeList(count) {
-  const list = [];
-  for (let i = 0; i < count; i += 1) {
-    list.push({
-      id: `fake-list-${i}`,
-      owner: user[i % 10],
-      title: titles[i % 8],
-      avatar: avatars[i % 8],
-      cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
-      status: ['active', 'exception', 'normal'][i % 3],
-      percent: Math.ceil(Math.random() * 50) + 50,
-      logo: avatars[i % 8],
-      href: 'https://ant.design',
-      updatedAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
-      createdAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
-      subDescription: desc[i % 5],
-      description:
-        '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。',
-      activeUser: Math.ceil(Math.random() * 100000) + 100000,
-      newUser: Math.ceil(Math.random() * 1000) + 1000,
-      star: Math.ceil(Math.random() * 100) + 100,
-      like: Math.ceil(Math.random() * 100) + 100,
-      message: Math.ceil(Math.random() * 10) + 10,
-      content:
-        '段落示意:蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。',
-      members: [
-        {
-          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ZiESqWwCXBRQoaPONSJe.png',
-          name: '曲丽丽',
-          id: 'member1',
-        },
-        {
-          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/tBOxZPlITHqwlGjsJWaF.png',
-          name: '王昭君',
-          id: 'member2',
-        },
-        {
-          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/sBxjgqiuHMGRkIjqlQCd.png',
-          name: '董娜娜',
-          id: 'member3',
-        },
-      ],
-    });
-  }
-
-  return list;
-}
-
-let sourceData;
-
-function getFakeList(req, res) {
-  const params = req.query;
-
-  const count = params.count * 1 || 20;
-
-  const result = fakeList(count);
-  sourceData = result;
-  return res.json(result);
-}
-
-function postFakeList(req, res) {
-  const { /* url = '', */ body } = req;
-  // const params = getUrlParams(url);
-  const { method, id } = body;
-  // const count = (params.count * 1) || 20;
-  let result = sourceData;
-
-  switch (method) {
-    case 'delete':
-      result = result.filter(item => item.id !== id);
-      break;
-    case 'update':
-      result.forEach((item, i) => {
-        if (item.id === id) {
-          result[i] = Object.assign(item, body);
-        }
-      });
-      break;
-    case 'post':
-      result.unshift({
-        body,
-        id: `fake-list-${result.length}`,
-        createdAt: new Date().getTime(),
-      });
-      break;
-    default:
-      break;
-  }
-
-  return res.json(result);
-}
-
-const getNotice = [
-  {
-    id: 'xxx1',
-    title: titles[0],
-    logo: avatars[0],
-    description: '那是一种内在的东西,他们到达不了,也无法触及的',
-    updatedAt: new Date(),
-    member: '科学搬砖组',
-    href: '',
-    memberLink: '',
-  },
-  {
-    id: 'xxx2',
-    title: titles[1],
-    logo: avatars[1],
-    description: '希望是一个好东西,也许是最好的,好东西是不会消亡的',
-    updatedAt: new Date('2017-07-24'),
-    member: '全组都是吴彦祖',
-    href: '',
-    memberLink: '',
-  },
-  {
-    id: 'xxx3',
-    title: titles[2],
-    logo: avatars[2],
-    description: '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
-    updatedAt: new Date(),
-    member: '中二少女团',
-    href: '',
-    memberLink: '',
-  },
-  {
-    id: 'xxx4',
-    title: titles[3],
-    logo: avatars[3],
-    description: '那时候我只会想自己想要什么,从不想自己拥有什么',
-    updatedAt: new Date('2017-07-23'),
-    member: '程序员日常',
-    href: '',
-    memberLink: '',
-  },
-  {
-    id: 'xxx5',
-    title: titles[4],
-    logo: avatars[4],
-    description: '凛冬将至',
-    updatedAt: new Date('2017-07-23'),
-    member: '高逼格设计天团',
-    href: '',
-    memberLink: '',
-  },
-  {
-    id: 'xxx6',
-    title: titles[5],
-    logo: avatars[5],
-    description: '生命就像一盒巧克力,结果往往出人意料',
-    updatedAt: new Date('2017-07-23'),
-    member: '骗你来学计算机',
-    href: '',
-    memberLink: '',
-  },
-];
-
-const getActivities = [
-  {
-    id: 'trend-1',
-    updatedAt: new Date(),
-    user: {
-      name: '曲丽丽',
-      avatar: avatars2[0],
-    },
-    group: {
-      name: '高逼格设计天团',
-      link: 'http://github.com/',
-    },
-    project: {
-      name: '六月迭代',
-      link: 'http://github.com/',
-    },
-    template: '在 @{group} 新建项目 @{project}',
-  },
-  {
-    id: 'trend-2',
-    updatedAt: new Date(),
-    user: {
-      name: '付小小',
-      avatar: avatars2[1],
-    },
-    group: {
-      name: '高逼格设计天团',
-      link: 'http://github.com/',
-    },
-    project: {
-      name: '六月迭代',
-      link: 'http://github.com/',
-    },
-    template: '在 @{group} 新建项目 @{project}',
-  },
-  {
-    id: 'trend-3',
-    updatedAt: new Date(),
-    user: {
-      name: '林东东',
-      avatar: avatars2[2],
-    },
-    group: {
-      name: '中二少女团',
-      link: 'http://github.com/',
-    },
-    project: {
-      name: '六月迭代',
-      link: 'http://github.com/',
-    },
-    template: '在 @{group} 新建项目 @{project}',
-  },
-  {
-    id: 'trend-4',
-    updatedAt: new Date(),
-    user: {
-      name: '周星星',
-      avatar: avatars2[4],
-    },
-    project: {
-      name: '5 月日常迭代',
-      link: 'http://github.com/',
-    },
-    template: '将 @{project} 更新至已发布状态',
-  },
-  {
-    id: 'trend-5',
-    updatedAt: new Date(),
-    user: {
-      name: '朱偏右',
-      avatar: avatars2[3],
-    },
-    project: {
-      name: '工程效能',
-      link: 'http://github.com/',
-    },
-    comment: {
-      name: '留言',
-      link: 'http://github.com/',
-    },
-    template: '在 @{project} 发布了 @{comment}',
-  },
-  {
-    id: 'trend-6',
-    updatedAt: new Date(),
-    user: {
-      name: '乐哥',
-      avatar: avatars2[5],
-    },
-    group: {
-      name: '程序员日常',
-      link: 'http://github.com/',
-    },
-    project: {
-      name: '品牌迭代',
-      link: 'http://github.com/',
-    },
-    template: '在 @{group} 新建项目 @{project}',
-  },
-];
-
-function getFakeCaptcha(req, res) {
-  return res.json('captcha-xxx');
-}
-
-export default {
-  'GET /api/project/notice': getNotice,
-  'GET /api/activities': getActivities,
-  'POST /api/forms': (req, res) => {
-    res.send({ message: 'Ok' });
-  },
-  'GET /api/tags': mockjs.mock({
-    'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }],
-  }),
-  'GET /api/fake_list': getFakeList,
-  'POST /api/fake_list': postFakeList,
-  'GET /api/captcha': getFakeCaptcha,
-};

+ 0 - 196
mock/chart.js

@@ -1,196 +0,0 @@
-import moment from 'moment';
-
-// mock data
-const visitData = [];
-const beginDay = new Date().getTime();
-
-const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
-for (let i = 0; i < fakeY.length; i += 1) {
-  visitData.push({
-    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
-    y: fakeY[i],
-  });
-}
-
-const visitData2 = [];
-const fakeY2 = [1, 6, 4, 8, 3, 7, 2];
-for (let i = 0; i < fakeY2.length; i += 1) {
-  visitData2.push({
-    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
-    y: fakeY2[i],
-  });
-}
-
-const salesData = [];
-for (let i = 0; i < 12; i += 1) {
-  salesData.push({
-    x: `${i + 1}月`,
-    y: Math.floor(Math.random() * 1000) + 200,
-  });
-}
-const searchData = [];
-for (let i = 0; i < 50; i += 1) {
-  searchData.push({
-    index: i + 1,
-    keyword: `搜索关键词-${i}`,
-    count: Math.floor(Math.random() * 1000),
-    range: Math.floor(Math.random() * 100),
-    status: Math.floor((Math.random() * 10) % 2),
-  });
-}
-const salesTypeData = [
-  {
-    x: '家用电器',
-    y: 4544,
-  },
-  {
-    x: '食用酒水',
-    y: 3321,
-  },
-  {
-    x: '个护健康',
-    y: 3113,
-  },
-  {
-    x: '服饰箱包',
-    y: 2341,
-  },
-  {
-    x: '母婴产品',
-    y: 1231,
-  },
-  {
-    x: '其他',
-    y: 1231,
-  },
-];
-
-const salesTypeDataOnline = [
-  {
-    x: '家用电器',
-    y: 244,
-  },
-  {
-    x: '食用酒水',
-    y: 321,
-  },
-  {
-    x: '个护健康',
-    y: 311,
-  },
-  {
-    x: '服饰箱包',
-    y: 41,
-  },
-  {
-    x: '母婴产品',
-    y: 121,
-  },
-  {
-    x: '其他',
-    y: 111,
-  },
-];
-
-const salesTypeDataOffline = [
-  {
-    x: '家用电器',
-    y: 99,
-  },
-  {
-    x: '食用酒水',
-    y: 188,
-  },
-  {
-    x: '个护健康',
-    y: 344,
-  },
-  {
-    x: '服饰箱包',
-    y: 255,
-  },
-  {
-    x: '其他',
-    y: 65,
-  },
-];
-
-const offlineData = [];
-for (let i = 0; i < 10; i += 1) {
-  offlineData.push({
-    name: `Stores ${i}`,
-    cvr: Math.ceil(Math.random() * 9) / 10,
-  });
-}
-const offlineChartData = [];
-for (let i = 0; i < 20; i += 1) {
-  offlineChartData.push({
-    x: new Date().getTime() + 1000 * 60 * 30 * i,
-    y1: Math.floor(Math.random() * 100) + 10,
-    y2: Math.floor(Math.random() * 100) + 10,
-  });
-}
-
-const radarOriginData = [
-  {
-    name: '个人',
-    ref: 10,
-    koubei: 8,
-    output: 4,
-    contribute: 5,
-    hot: 7,
-  },
-  {
-    name: '团队',
-    ref: 3,
-    koubei: 9,
-    output: 6,
-    contribute: 3,
-    hot: 1,
-  },
-  {
-    name: '部门',
-    ref: 4,
-    koubei: 1,
-    output: 6,
-    contribute: 5,
-    hot: 7,
-  },
-];
-
-const radarData = [];
-const radarTitleMap = {
-  ref: '引用',
-  koubei: '口碑',
-  output: '产量',
-  contribute: '贡献',
-  hot: '热度',
-};
-radarOriginData.forEach(item => {
-  Object.keys(item).forEach(key => {
-    if (key !== 'name') {
-      radarData.push({
-        name: item.name,
-        label: radarTitleMap[key],
-        value: item[key],
-      });
-    }
-  });
-});
-
-const getFakeChartData = {
-  visitData,
-  visitData2,
-  salesData,
-  searchData,
-  offlineData,
-  offlineChartData,
-  salesTypeData,
-  salesTypeDataOnline,
-  salesTypeDataOffline,
-  radarData,
-};
-
-export default {
-  'GET /api/fake_chart_data': getFakeChartData,
-};

+ 0 - 15
mock/geographic.js

@@ -1,15 +0,0 @@
-import city from './geographic/city.json';
-import province from './geographic/province.json';
-
-function getProvince(req, res) {
-  return res.json(province);
-}
-
-function getCity(req, res) {
-  return res.json(city[req.params.province]);
-}
-
-export default {
-  'GET /api/geographic/province': getProvince,
-  'GET /api/geographic/city/:province': getCity,
-};

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 1784
mock/geographic/city.json


+ 0 - 138
mock/geographic/province.json

@@ -1,138 +0,0 @@
-[
-  {
-    "name": "北京市",
-    "id": "110000"
-  },
-  {
-    "name": "天津市",
-    "id": "120000"
-  },
-  {
-    "name": "河北省",
-    "id": "130000"
-  },
-  {
-    "name": "山西省",
-    "id": "140000"
-  },
-  {
-    "name": "内蒙古自治区",
-    "id": "150000"
-  },
-  {
-    "name": "辽宁省",
-    "id": "210000"
-  },
-  {
-    "name": "吉林省",
-    "id": "220000"
-  },
-  {
-    "name": "黑龙江省",
-    "id": "230000"
-  },
-  {
-    "name": "上海市",
-    "id": "310000"
-  },
-  {
-    "name": "江苏省",
-    "id": "320000"
-  },
-  {
-    "name": "浙江省",
-    "id": "330000"
-  },
-  {
-    "name": "安徽省",
-    "id": "340000"
-  },
-  {
-    "name": "福建省",
-    "id": "350000"
-  },
-  {
-    "name": "江西省",
-    "id": "360000"
-  },
-  {
-    "name": "山东省",
-    "id": "370000"
-  },
-  {
-    "name": "河南省",
-    "id": "410000"
-  },
-  {
-    "name": "湖北省",
-    "id": "420000"
-  },
-  {
-    "name": "湖南省",
-    "id": "430000"
-  },
-  {
-    "name": "广东省",
-    "id": "440000"
-  },
-  {
-    "name": "广西壮族自治区",
-    "id": "450000"
-  },
-  {
-    "name": "海南省",
-    "id": "460000"
-  },
-  {
-    "name": "重庆市",
-    "id": "500000"
-  },
-  {
-    "name": "四川省",
-    "id": "510000"
-  },
-  {
-    "name": "贵州省",
-    "id": "520000"
-  },
-  {
-    "name": "云南省",
-    "id": "530000"
-  },
-  {
-    "name": "西藏自治区",
-    "id": "540000"
-  },
-  {
-    "name": "陕西省",
-    "id": "610000"
-  },
-  {
-    "name": "甘肃省",
-    "id": "620000"
-  },
-  {
-    "name": "青海省",
-    "id": "630000"
-  },
-  {
-    "name": "宁夏回族自治区",
-    "id": "640000"
-  },
-  {
-    "name": "新疆维吾尔自治区",
-    "id": "650000"
-  },
-  {
-    "name": "台湾省",
-    "id": "710000"
-  },
-  {
-    "name": "香港特别行政区",
-    "id": "810000"
-  },
-  {
-    "name": "澳门特别行政区",
-    "id": "820000"
-  }
-]

mock/notices.js → mock/notices.ts


+ 0 - 177
mock/profile.js

@@ -1,177 +0,0 @@
-import mockjs from 'mockjs';
-
-const basicGoods = [
-  {
-    id: '1234561',
-    name: '矿泉水 550ml',
-    barcode: '12421432143214321',
-    price: '2.00',
-    num: '1',
-    amount: '2.00',
-  },
-  {
-    id: '1234562',
-    name: '凉茶 300ml',
-    barcode: '12421432143214322',
-    price: '3.00',
-    num: '2',
-    amount: '6.00',
-  },
-  {
-    id: '1234563',
-    name: '好吃的薯片',
-    barcode: '12421432143214323',
-    price: '7.00',
-    num: '4',
-    amount: '28.00',
-  },
-  {
-    id: '1234564',
-    name: '特别好吃的蛋卷',
-    barcode: '12421432143214324',
-    price: '8.50',
-    num: '3',
-    amount: '25.50',
-  },
-];
-
-const basicProgress = [
-  {
-    key: '1',
-    time: '2017-10-01 14:10',
-    rate: '联系客户',
-    status: 'processing',
-    operator: '取货员 ID1234',
-    cost: '5mins',
-  },
-  {
-    key: '2',
-    time: '2017-10-01 14:05',
-    rate: '取货员出发',
-    status: 'success',
-    operator: '取货员 ID1234',
-    cost: '1h',
-  },
-  {
-    key: '3',
-    time: '2017-10-01 13:05',
-    rate: '取货员接单',
-    status: 'success',
-    operator: '取货员 ID1234',
-    cost: '5mins',
-  },
-  {
-    key: '4',
-    time: '2017-10-01 13:00',
-    rate: '申请审批通过',
-    status: 'success',
-    operator: '系统',
-    cost: '1h',
-  },
-  {
-    key: '5',
-    time: '2017-10-01 12:00',
-    rate: '发起退货申请',
-    status: 'success',
-    operator: '用户',
-    cost: '5mins',
-  },
-];
-
-const advancedOperation1 = [
-  {
-    key: 'op1',
-    type: '订购关系生效',
-    name: '曲丽丽',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '-',
-  },
-  {
-    key: 'op2',
-    type: '财务复审',
-    name: '付小小',
-    status: 'reject',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '不通过原因',
-  },
-  {
-    key: 'op3',
-    type: '部门初审',
-    name: '周毛毛',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '-',
-  },
-  {
-    key: 'op4',
-    type: '提交订单',
-    name: '林东东',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '很棒',
-  },
-  {
-    key: 'op5',
-    type: '创建订单',
-    name: '汗牙牙',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '-',
-  },
-];
-
-const advancedOperation2 = [
-  {
-    key: 'op1',
-    type: '订购关系生效',
-    name: '曲丽丽',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '-',
-  },
-];
-
-const advancedOperation3 = [
-  {
-    key: 'op1',
-    type: '创建订单',
-    name: '汗牙牙',
-    status: 'agree',
-    updatedAt: '2017-10-03  19:23:12',
-    memo: '-',
-  },
-];
-const getProfileAdvancedData = {
-  advancedOperation1,
-  advancedOperation2,
-  advancedOperation3,
-};
-
-const { Random } = mockjs;
-
-export default {
-  'GET /api/profile/advanced': getProfileAdvancedData,
-  'GET /api/profile/basic': (req, res) => {
-    const { id } = req.query;
-    const application = {
-      id,
-      status: '已取货',
-      orderNo: Random.id(),
-      childOrderNo: Random.id(),
-    };
-    const userInfo = {
-      name: Random.cname(),
-      tel: '18100000000',
-      delivery: '菜鸟物流',
-      addr: '浙江省杭州市西湖区万塘路18号',
-      remark: '备注',
-    };
-    res.json({
-      userInfo,
-      application,
-      basicGoods,
-      basicProgress,
-    });
-  },
-};

+ 5 - 0
mock/route.ts

@@ -0,0 +1,5 @@
+export default {
+  '/api/auth_routes': {
+    '/form/advanced-form': { authority: ['admin', 'user'] },
+  },
+};

+ 0 - 131
mock/rule.js

@@ -1,131 +0,0 @@
-import { parse } from 'url';
-
-// mock tableListDataSource
-let tableListDataSource = [];
-for (let i = 0; i < 46; i += 1) {
-  tableListDataSource.push({
-    key: i,
-    disabled: i % 6 === 0,
-    href: 'https://ant.design',
-    avatar: [
-      'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
-      'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
-    ][i % 2],
-    name: `TradeCode ${i}`,
-    title: `一个任务名称 ${i}`,
-    owner: '曲丽丽',
-    desc: '这是一段描述',
-    callNo: Math.floor(Math.random() * 1000),
-    status: Math.floor(Math.random() * 10) % 4,
-    updatedAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
-    createdAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
-    progress: Math.ceil(Math.random() * 100),
-  });
-}
-
-function getRule(req, res, u) {
-  let url = u;
-  if (!url || Object.prototype.toString.call(url) !== '[object String]') {
-    url = req.url; // eslint-disable-line
-  }
-
-  const params = parse(url, true).query;
-
-  let dataSource = tableListDataSource;
-
-  if (params.sorter) {
-    const s = params.sorter.split('_');
-    dataSource = dataSource.sort((prev, next) => {
-      if (s[1] === 'descend') {
-        return next[s[0]] - prev[s[0]];
-      }
-      return prev[s[0]] - next[s[0]];
-    });
-  }
-
-  if (params.status) {
-    const status = params.status.split(',');
-    let filterDataSource = [];
-    status.forEach(s => {
-      filterDataSource = filterDataSource.concat(
-        dataSource.filter(data => parseInt(data.status, 10) === parseInt(s[0], 10))
-      );
-    });
-    dataSource = filterDataSource;
-  }
-
-  if (params.name) {
-    dataSource = dataSource.filter(data => data.name.indexOf(params.name) > -1);
-  }
-
-  let pageSize = 10;
-  if (params.pageSize) {
-    pageSize = params.pageSize * 1;
-  }
-
-  const result = {
-    list: dataSource,
-    pagination: {
-      total: dataSource.length,
-      pageSize,
-      current: parseInt(params.currentPage, 10) || 1,
-    },
-  };
-
-  return res.json(result);
-}
-
-function postRule(req, res, u, b) {
-  let url = u;
-  if (!url || Object.prototype.toString.call(url) !== '[object String]') {
-    url = req.url; // eslint-disable-line
-  }
-
-  const body = (b && b.body) || req.body;
-  const { method, name, desc, key } = body;
-
-  switch (method) {
-    /* eslint no-case-declarations:0 */
-    case 'delete':
-      tableListDataSource = tableListDataSource.filter(item => key.indexOf(item.key) === -1);
-      break;
-    case 'post':
-      const i = Math.ceil(Math.random() * 10000);
-      tableListDataSource.unshift({
-        key: i,
-        href: 'https://ant.design',
-        avatar: [
-          'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
-          'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
-        ][i % 2],
-        name: `TradeCode ${i}`,
-        title: `一个任务名称 ${i}`,
-        owner: '曲丽丽',
-        desc,
-        callNo: Math.floor(Math.random() * 1000),
-        status: Math.floor(Math.random() * 10) % 2,
-        updatedAt: new Date(),
-        createdAt: new Date(),
-        progress: Math.ceil(Math.random() * 100),
-      });
-      break;
-    case 'update':
-      tableListDataSource = tableListDataSource.map(item => {
-        if (item.key === key) {
-          Object.assign(item, { desc, name });
-          return item;
-        }
-        return item;
-      });
-      break;
-    default:
-      break;
-  }
-
-  return getRule(req, res, u);
-}
-
-export default {
-  'GET /api/rule': getRule,
-  'POST /api/rule': postRule,
-};

mock/user.js → mock/user.ts


+ 72 - 37
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ant-design-pro",
-  "version": "2.3.1",
+  "version": "4.0.0",
   "private": true,
   "description": "An out-of-box UI solution for enterprise applications",
   "scripts": {
@@ -13,23 +13,26 @@
     "docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up",
     "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro",
     "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro",
-    "functions:build": "npm run generateMock && netlify-lambda build ./lambda",
-    "functions:run": "npm run generateMock && cross-env NODE_ENV=dev netlify-lambda serve ./lambda",
+    "fetch:blocks": "node ./scripts/fetch-blocks.js",
+    "functions:build": "netlify-lambda build ./lambda",
+    "functions:run": "cross-env NODE_ENV=dev netlify-lambda serve ./lambda",
     "generateMock": "node ./scripts/generateMock",
-    "lint": "eslint --ext .js src mock tests && npm run lint:style && npm run lint:prettier",
+    "lint": "npm run lint:js && npm run lint:ts && npm run lint:style && npm run lint:prettier",
     "lint-staged": "lint-staged",
     "lint-staged:js": "eslint --ext .js",
-    "lint:fix": "eslint --fix --ext .js src mock tests && stylelint --fix 'src/**/*.less' --syntax less",
+    "lint-staged:ts": "tslint",
+    "lint:fix": "eslint --fix --ext .js src tests && npm run lint:style && npm run tslint:fix",
+    "lint:js": "eslint --ext .js src tests",
     "lint:prettier": "check-prettier lint",
-    "lint:style": "stylelint 'src/**/*.less' --syntax less",
-    "prettier": "node ./scripts/prettier.js",
-    "site": "umi build && npm run functions:build",
+    "lint:style": "stylelint --fix 'src/**/*.less' --syntax less",
+    "lint:ts": "tslint -p . -c tslint.yml",
+    "prettier": " check-prettier write",
+    "site": "npm run fetch:blocks && npm run functions:build && umi build",
     "start": "umi dev",
     "start:no-mock": "cross-env MOCK=none umi dev",
     "test": "umi test",
     "test:all": "node ./tests/run-tests.js",
     "test:component": "umi test ./src/components",
-    "tslint": "npm run tslint:fix",
     "tslint:fix": "tslint --fix 'src/**/*.ts*'"
   },
   "husky": {
@@ -40,10 +43,11 @@
   "lint-staged": {
     "**/*.less": "stylelint --syntax less",
     "**/*.{js,jsx}": "npm run lint-staged:js",
-    "**/*.{js,ts,tsx,json,jsx,less}": [
-      "node ./scripts/lint-prettier.js",
+    "**/*.{js,ts,tsx,md,json,jsx,less}": [
+      "npm run prettier",
       "git add"
-    ]
+    ],
+    "**/*.{ts,tsx}": "npm run lint-staged:ts"
   },
   "browserslist": [
     "> 1%",
@@ -51,42 +55,42 @@
     "not ie <= 10"
   ],
   "dependencies": {
+    "@ant-design/pro-layout": "^4.2.0",
     "@antv/data-set": "^0.10.1",
     "antd": "^3.16.1",
-    "bizcharts": "^3.5.3-beta.0",
-    "bizcharts-plugin-slider": "^2.1.1-beta.1",
     "classnames": "^2.2.6",
-    "dva": "^2.4.1",
-    "enquire-js": "^0.2.1",
-    "express": "^4.16.4",
-    "gg-editor": "^2.0.2",
-    "lodash": "^4.17.11",
-    "lodash-decorators": "^6.0.1",
+    "dva": "^2.4.0",
+    "lodash": "^4.17.10",
+    "lodash-decorators": "^6.0.0",
     "memoize-one": "^5.0.0",
-    "moment": "^2.24.0",
-    "netlify-lambda": "^1.4.3",
-    "numeral": "^2.0.6",
-    "nzh": "^1.0.4",
+    "moment": "^2.22.2",
     "omit.js": "^1.0.0",
-    "path-to-regexp": "^3.0.0",
-    "prop-types": "^15.6.2",
-    "qs": "^6.6.0",
-    "rc-animate": "^2.6.0",
-    "react": "^16.7.0",
+    "path-to-regexp": "^2.4.0",
+    "prop-types": "^15.7.2",
+    "qs": "^6.7.0",
+    "rc-animate": "^2.4.4",
+    "react": "^16.8.5",
     "react-container-query": "^0.11.0",
     "react-copy-to-clipboard": "^5.0.1",
     "react-document-title": "^2.0.3",
     "react-dom": "^16.7.0",
-    "react-fittext": "^1.0.0",
     "react-media": "^1.9.2",
-    "resize-observer-polyfill": "^1.5.1",
-    "umi": "^2.4.4",
-    "umi-plugin-react": "^1.7.2",
-    "umi-request": "^1.0.5"
+    "react-media-hook2": "^1.0.2",
+    "umi": "^2.7.0-beta.2",
+    "umi-plugin-ga": "^1.1.3",
+    "umi-plugin-locale": "^2.8.0-beta.1",
+    "umi-plugin-pro-block": "^1.3.0",
+    "umi-plugin-react": "^1.8.0-beta.1",
+    "umi-request": "^1.0.7"
   },
   "devDependencies": {
+    "@types/classnames": "^2.2.7",
     "@types/history": "^4.7.2",
+    "@types/jest": "^24.0.13",
+    "@types/lodash": "^4.14.123",
+    "@types/qs": "^6.5.3",
     "@types/react": "^16.8.1",
+    "@types/react-document-title": "^2.0.3",
     "@types/react-dom": "^16.0.11",
     "antd-pro-merge-less": "^1.0.0",
     "antd-theme-webpack-plugin": "^1.2.0",
@@ -105,6 +109,7 @@
     "eslint-plugin-jsx-a11y": "^6.2.1",
     "eslint-plugin-markdown": "^1.0.0",
     "eslint-plugin-react": "^7.12.4",
+    "express": "^4.16.4",
     "gh-pages": "^2.0.1",
     "husky": "^2.2.0",
     "jest-puppeteer": "^4.1.0",
@@ -113,6 +118,8 @@
     "lint-staged": "^8.1.1",
     "merge-umi-mock-data": "^1.0.4",
     "mockjs": "^1.0.1-beta3",
+    "netlify-lambda": "^1.4.3",
+    "node-fetch": "^2.6.0",
     "prettier": "^1.17.0",
     "serverless-http": "^2.0.1",
     "slash2": "^2.0.0",
@@ -125,8 +132,8 @@
     "stylelint-order": "^2.0.0",
     "tslint": "^5.12.1",
     "tslint-config-prettier": "^1.17.0",
-    "tslint-react": "^3.6.0",
-    "umi-plugin-ga": "^1.1.3"
+    "tslint-eslint-rules": "^5.4.0",
+    "tslint-react": "^3.6.0"
   },
   "optionalDependencies": {
     "puppeteer": "^1.12.1"
@@ -140,5 +147,33 @@
     "src/**/*.less",
     "config/**/*.js*",
     "scripts/**/*.js"
-  ]
+  ],
+  "create-umi": {
+    "copy": [
+      [
+        "create-umi/README.md",
+        "README.md"
+      ],
+      [
+        "create-umi/package.json",
+        "package.json"
+      ]
+    ],
+    "ignore": [
+      ".dockerignore",
+      ".git",
+      ".gitpod.yml",
+      "CODE_OF_CONDUCT.md",
+      "Dockerfile",
+      "Dockerfile.*",
+      "lambda",
+      "LICENSE",
+      "netlify.toml",
+      "README.*.md",
+      "scripts",
+      "azure-pipelines.yml",
+      "docker",
+      "create-umi"
+    ]
+  }
 }

+ 129 - 0
scripts/fetch-blocks.js

@@ -0,0 +1,129 @@
+const path = require('path');
+const fs = require('fs');
+const fetch = require('node-fetch');
+const exec = require('child_process').exec;
+const getNewRouteCode = require('./repalceRouter');
+const router = require('./router.config');
+const chalk = require('chalk');
+const insertCode = require('./insertCode');
+
+const fetchGithubFiles = async () => {
+  const ignoreFile = ['_scripts'];
+  const data = await fetch(`https://api.github.com/repos/ant-design/pro-blocks/git/trees/master`);
+  if (data.status !== 200) {
+    return;
+  }
+  const { tree } = await data.json();
+  const files = tree.filter(file => file.type === 'tree' && !ignoreFile.includes(file.path));
+  return Promise.resolve(files);
+};
+
+const relativePath = path.join(__dirname, '../config/config.ts');
+
+const findAllInstallRouter = router => {
+  let routers = [];
+  router.forEach(item => {
+    if (item.component && item.path) {
+      if (item.path !== '/user' || item.path !== '/') {
+        routers.push({
+          ...item,
+          routes: !!item.routes,
+        });
+      }
+    }
+    if (item.routes) {
+      routers = routers.concat(findAllInstallRouter(item.routes));
+    }
+  });
+  return routers;
+};
+
+const filterParentRouter = (router, layout) => {
+  return [...router]
+    .map(item => {
+      if (item.routes && (!router.component || layout)) {
+        return { ...item, routes: filterParentRouter(item.routes, false) };
+      }
+      if (item.redirect) {
+        return item;
+      }
+      return null;
+    })
+    .filter(item => item);
+};
+const firstUpperCase = pathString => {
+  return pathString
+    .replace('.', '')
+    .split(/\/|\-/)
+    .map(s => s.toLowerCase().replace(/( |^)[a-z]/g, L => L.toUpperCase()))
+    .filter(s => s)
+    .join('');
+};
+
+const execCmd = shell => {
+  return new Promise((resolve, reject) => {
+    exec(shell, { encoding: 'utf8' }, (error, statusbar) => {
+      if (error) {
+        console.log(error);
+        return reject(error);
+      }
+      console.log(statusbar);
+      resolve();
+    });
+  });
+};
+
+// replace router config
+const parentRouter = filterParentRouter(router, true);
+const { routesPath, code } = getNewRouteCode(relativePath, parentRouter);
+// write ParentRouter
+fs.writeFileSync(routesPath, code);
+
+const installBlock = async () => {
+  let gitFiles = await fetchGithubFiles();
+  const installRouters = findAllInstallRouter(router);
+  const installBlockIteration = async i => {
+    const item = installRouters[i];
+
+    if (!item || !item.path) {
+      return Promise.resolve();
+    }
+    const gitPath = firstUpperCase(item.path);
+    // 如果这个区块在 git 上存在
+    if (gitFiles.find(file => file.path === gitPath)) {
+      console.log('install ' + chalk.green(item.name) + ' to: ' + chalk.yellow(item.path));
+      gitFiles = gitFiles.filter(file => file.path !== gitPath);
+      const skipModifyRouter = item.routes ? '--skip-modify-routes' : '';
+      const cmd = `umi block add https://github.com/ant-design/pro-blocks/tree/master/${gitPath}  --path=${
+        item.path
+      } ${skipModifyRouter}`;
+      try {
+        await execCmd(cmd);
+        console.log(`install ${chalk.hex('#1890ff')(item.name)} success`);
+      } catch (error) {
+        console.error(error);
+      }
+    }
+    return installBlockIteration(i + 1);
+  };
+  // 安装路由中设置的区块
+  await installBlockIteration(0);
+
+  const installGitFile = async i => {
+    const item = gitFiles[i];
+    if (!item || !item.path) {
+      return Promise.resolve();
+    }
+    console.log('install ' + chalk.green(item.path));
+    const cmd = `umi block add https://github.com/ant-design/pro-blocks/tree/master/${item.path}`;
+    await execCmd(cmd);
+    return installBlockIteration(1);
+  };
+
+  // 安装 router 中没有的剩余区块.
+  installGitFile(0);
+};
+installBlock().then(() => {
+  // 插入 pro 需要的演示代码
+  insertCode();
+});

+ 0 - 3
scripts/generateMock.js

@@ -1,3 +0,0 @@
-const generateMock = require('merge-umi-mock-data');
-const path = require('path');
-generateMock(path.join(__dirname, '../mock'), path.join(__dirname, '../lambda/mock/index.js'));

+ 0 - 23
scripts/getPrettierFiles.js

@@ -1,23 +0,0 @@
-const glob = require('glob');
-
-const getPrettierFiles = () => {
-  let files = [];
-  const jsFiles = glob.sync('src/**/*.js*', { ignore: ['**/node_modules/**', 'build/**'] });
-  const tsFiles = glob.sync('src/**/*.ts*', { ignore: ['**/node_modules/**', 'build/**'] });
-  const configFiles = glob.sync('config/**/*.js*', { ignore: ['**/node_modules/**', 'build/**'] });
-  const scriptFiles = glob.sync('scripts/**/*.js');
-  const lessFiles = glob.sync('src/**/*.less*', { ignore: ['**/node_modules/**', 'build/**'] });
-  const mdFiles = glob.sync('src/**/*.md*', { ignore: ['**/node_modules/**', 'build/**'] });
-  files = files.concat(jsFiles);
-  files = files.concat(tsFiles);
-  files = files.concat(configFiles);
-  files = files.concat(scriptFiles);
-  files = files.concat(lessFiles);
-  files = files.concat(mdFiles);
-  if (!files.length) {
-    return;
-  }
-  return files;
-};
-
-module.exports = getPrettierFiles;

+ 161 - 0
scripts/insertCode.js

@@ -0,0 +1,161 @@
+const parser = require('@babel/parser');
+const traverse = require('@babel/traverse');
+const generate = require('@babel/generator');
+const t = require('@babel/types');
+const fs = require('fs');
+const path = require('path');
+const prettier = require('prettier');
+const chalk = require('chalk');
+
+const parseCode = code => {
+  return parser.parse(code, {
+    sourceType: 'module',
+    plugins: ['typescript', 'jsx'],
+  }).program.body[0];
+};
+
+/**
+ * 生成代码
+ * @param {*} ast
+ */
+function generateCode(ast) {
+  const newCode = generate.default(ast, {}).code;
+  return prettier.format(newCode, {
+    // format same as ant-design-pro
+    singleQuote: true,
+    trailingComma: 'es5',
+    printWidth: 100,
+    parser: 'typescript',
+  });
+}
+
+const SettingCodeString = `
+  <SettingDrawer
+    settings={settings}
+    onSettingChange={config =>
+    dispatch({
+        type: 'settings/changeSetting',
+        payload: config,
+    })
+    }
+  />
+`;
+
+const mapAst = (configPath, callBack) => {
+  const ast = parser.parse(fs.readFileSync(configPath, 'utf-8'), {
+    sourceType: 'module',
+    plugins: ['typescript', 'jsx'],
+  });
+  // 查询当前配置文件是否导出 routes 属性
+  traverse.default(ast, {
+    Program({ node }) {
+      const { body } = node;
+      callBack(body);
+    },
+  });
+  return generateCode(ast);
+};
+
+const insertBasicLayout = configPath => {
+  return mapAst(configPath, body => {
+    const index = body.findIndex(item => {
+      return item.type !== 'ImportDeclaration';
+    });
+
+    body.forEach(item => {
+      // 从包中导出 SettingDrawer
+      if (item.type === 'ImportDeclaration') {
+        if (item.source.value === '@ant-design/pro-layout') {
+          item.specifiers.push(parseCode(`SettingDrawer`).expression);
+        }
+      }
+      if (item.type === 'VariableDeclaration') {
+        const {
+          id,
+          init: { body },
+        } = item.declarations[0];
+        // 给 BasicLayout 中插入 button 和 设置抽屉
+        if (id.name === `BasicLayout`) {
+          body.body.forEach(node => {
+            if (node.type === 'ReturnStatement') {
+              const JSXFragment = parseCode(`<></>`).expression;
+              JSXFragment.children.push({ ...node.argument });
+              JSXFragment.children.push(parseCode(SettingCodeString).expression);
+              node.argument = JSXFragment;
+            }
+          });
+        }
+      }
+    });
+  });
+};
+
+const insertBlankLayout = configPath => {
+  return mapAst(configPath, body => {
+    const index = body.findIndex(item => {
+      return item.type !== 'ImportDeclaration';
+    });
+    // 从组件中导入 CopyBlock
+    body.splice(
+      index,
+      0,
+      parseCode(`import CopyBlock from '@/components/CopyBlock';
+    `),
+    );
+    body.forEach(item => {
+      if (item.type === 'VariableDeclaration') {
+        const { id, init } = item.declarations[0];
+        // 给 BasicLayout 中插入 button 和 设置抽屉
+        if (id.name === `Layout`) {
+          const JSXFragment = parseCode(`<></>`).expression;
+          JSXFragment.children.push({ ...init.body });
+          JSXFragment.children.push(parseCode(` <CopyBlock id={Date.now()}/>`).expression);
+          init.body = JSXFragment;
+        }
+      }
+    });
+  });
+};
+
+const insertRightContent = configPath => {
+  return mapAst(configPath, body => {
+    const index = body.findIndex(item => {
+      return item.type !== 'ImportDeclaration';
+    });
+    // 从组件中导入 CopyBlock
+    body.splice(index, 0, parseCode(`import NoticeIconView from './NoticeIconView';`));
+
+    body.forEach(item => {
+      if (item.type === 'ClassDeclaration') {
+        const classBody = item.body.body[0].body;
+        classBody.body.forEach(node => {
+          if (node.type === 'ReturnStatement') {
+            const index = node.argument.children.findIndex(item => {
+              if (item.type === 'JSXElement') {
+                if (item.openingElement.name.name === 'Avatar') {
+                  return true;
+                }
+              }
+            });
+            node.argument.children.splice(index, 1, parseCode(`<Avatar menu />`).expression);
+            node.argument.children.splice(index, 0, parseCode(`<NoticeIconView />`).expression);
+          }
+        });
+      }
+    });
+  });
+};
+
+module.exports = () => {
+  const basicLayoutPath = path.join(__dirname, '../src/layouts/BasicLayout.tsx');
+  fs.writeFileSync(basicLayoutPath, insertBasicLayout(basicLayoutPath));
+  console.log(`insert ${chalk.hex('#1890ff')('BasicLayout')} success`);
+
+  const rightContentPath = path.join(__dirname, '../src/components/GlobalHeader/RightContent.tsx');
+  fs.writeFileSync(rightContentPath, insertRightContent(rightContentPath));
+  console.log(`insert ${chalk.hex('#1890ff')('RightContent')} success`);
+
+  const blankLayoutPath = path.join(__dirname, '../src/layouts/BlankLayout.tsx');
+  fs.writeFileSync(blankLayoutPath, insertBlankLayout(blankLayoutPath));
+  console.log(`insert ${chalk.hex('#1890ff')('blankLayoutPath')} success`);
+};

+ 0 - 50
scripts/lint-prettier.js

@@ -1,50 +0,0 @@
-/**
- * copy to https://github.com/facebook/react/blob/master/scripts/prettier/index.js
- * prettier api doc https://prettier.io/docs/en/api.html
- *----------*****--------------
- *  lint file is prettier
- *----------*****--------------
- */
-
-const prettier = require('prettier');
-const fs = require('fs');
-const chalk = require('chalk');
-const prettierConfigPath = require.resolve('../.prettierrc');
-
-const files = process.argv.slice(2);
-
-let didError = false;
-
-files.forEach(file => {
-  Promise.all([
-    prettier.resolveConfig(file, {
-      config: prettierConfigPath,
-    }),
-    prettier.getFileInfo(file),
-  ])
-    .then(resolves => {
-      const [options, fileInfo] = resolves;
-      if (fileInfo.ignored) {
-        return;
-      }
-      const input = fs.readFileSync(file, 'utf8');
-      const withParserOptions = {
-        ...options,
-        parser: fileInfo.inferredParser,
-      };
-      const output = prettier.format(input, withParserOptions);
-      if (output !== input) {
-        fs.writeFileSync(file, output, 'utf8');
-        console.log(chalk.green(`${file} is prettier`));
-      }
-    })
-    .catch(e => {
-      didError = true;
-    })
-    .finally(() => {
-      if (didError) {
-        process.exit(1);
-      }
-      console.log(chalk.hex('#1890FF')('prettier success!'));
-    });
-});

+ 0 - 46
scripts/prettier.js

@@ -1,46 +0,0 @@
-/**
- * copy to https://github.com/facebook/react/blob/master/scripts/prettier/index.js
- * prettier api doc https://prettier.io/docs/en/api.html
- *----------*****--------------
- *  prettier all js and all ts.
- *----------*****--------------
- */
-
-const prettier = require('prettier');
-const fs = require('fs');
-const getPrettierFiles = require('./getPrettierFiles');
-const prettierConfigPath = require.resolve('../.prettierrc');
-const chalk = require('chalk');
-
-let didError = false;
-
-const files = getPrettierFiles();
-
-files.forEach(file => {
-  const options = prettier.resolveConfig.sync(file, {
-    config: prettierConfigPath,
-  });
-  const fileInfo = prettier.getFileInfo.sync(file);
-  if (fileInfo.ignored) {
-    return;
-  }
-  try {
-    const input = fs.readFileSync(file, 'utf8');
-    const withParserOptions = {
-      ...options,
-      parser: fileInfo.inferredParser,
-    };
-    const output = prettier.format(input, withParserOptions);
-    if (output !== input) {
-      fs.writeFileSync(file, output, 'utf8');
-      console.log(chalk.green(`${file} is prettier`));
-    }
-  } catch (e) {
-    didError = true;
-  }
-});
-
-if (didError) {
-  process.exit(1);
-}
-console.log(chalk.hex('#1890FF')('prettier success!'));

+ 77 - 0
scripts/repalceRouter.js

@@ -0,0 +1,77 @@
+const parser = require('@babel/parser');
+const traverse = require('@babel/traverse');
+const generate = require('@babel/generator');
+const t = require('@babel/types');
+const fs = require('fs');
+const prettier = require('prettier');
+
+const getNewRouteCode = (configPath, newRoute) => {
+  const ast = parser.parse(fs.readFileSync(configPath, 'utf-8'), {
+    sourceType: 'module',
+    plugins: ['typescript'],
+  });
+  let routesNode = null;
+  const importModules = [];
+  // 查询当前配置文件是否导出 routes 属性
+  traverse.default(ast, {
+    Program({ node }) {
+      // find import
+      const { body } = node;
+      body.forEach(item => {
+        if (t.isImportDeclaration(item)) {
+          const { specifiers } = item;
+          const defaultEpecifier = specifiers.find(s => {
+            return t.isImportDefaultSpecifier(s) && t.isIdentifier(s.local);
+          });
+          if (defaultEpecifier && t.isStringLiteral(item.source)) {
+            importModules.push({
+              identifierName: defaultEpecifier.local.name,
+              modulePath: item.source.value,
+            });
+          }
+        }
+      });
+    },
+    ObjectExpression({ node, parent }) {
+      // find routes on object, like { routes: [] }
+      if (t.isArrayExpression(parent)) {
+        // children routes
+        return;
+      }
+      const { properties } = node;
+      properties.forEach(p => {
+        const { key, value } = p;
+        if (t.isObjectProperty(p) && t.isIdentifier(key) && key.name === 'routes') {
+          if (value) {
+            // find json file program expression
+            (p.value = parser.parse(JSON.stringify(newRoute)).program.body[0].expression),
+              (routesNode = value);
+          }
+        }
+      });
+    },
+  });
+  if (routesNode) {
+    const code = generateCode(ast);
+    return { code, routesPath: configPath };
+  } else {
+    throw new Error('route array config not found.');
+  }
+};
+
+/**
+ * 生成代码
+ * @param {*} ast
+ */
+function generateCode(ast) {
+  const newCode = generate.default(ast, {}).code;
+  return prettier.format(newCode, {
+    // format same as ant-design-pro
+    singleQuote: true,
+    trailingComma: 'es5',
+    printWidth: 100,
+    parser: 'typescript',
+  });
+}
+
+module.exports = getNewRouteCode;

+ 236 - 0
scripts/router.config.js

@@ -0,0 +1,236 @@
+module.exports = [
+  {
+    path: '/',
+    component: '../layouts/BlankLayout',
+    routes: [
+      // user
+      {
+        path: '/user',
+        component: '../layouts/UserLayout',
+        routes: [
+          { path: '/user/login', name: 'login', component: './User/Login' },
+          { path: '/user/register', name: 'register', component: './User/Register' },
+          {
+            path: '/user/register-result',
+            name: 'register.result',
+            component: './User/RegisterResult',
+          },
+          { path: '/user', redirect: '/user/login' },
+          {
+            component: '404',
+          },
+        ],
+      },
+      // app
+      {
+        path: '/',
+        component: '../layouts/BasicLayout',
+        Routes: ['src/pages/Authorized'],
+        authority: ['admin', 'user'],
+        routes: [
+          // dashboard
+          {
+            path: '/dashboard',
+            name: 'dashboard',
+            icon: 'dashboard',
+            routes: [
+              {
+                path: '/dashboard/analysis',
+                name: 'analysis',
+                component: './Dashboard/Analysis',
+              },
+              {
+                path: '/dashboard/monitor',
+                name: 'monitor',
+                component: './Dashboard/Monitor',
+              },
+              {
+                path: '/dashboard/workplace',
+                name: 'workplace',
+                component: './Dashboard/Workplace',
+              },
+            ],
+          },
+          // forms
+          {
+            path: '/form',
+            icon: 'form',
+            name: 'form',
+            routes: [
+              {
+                path: '/form/basic-form',
+                name: 'basicform',
+                component: './Form/BasicForm',
+              },
+              {
+                path: '/form/step-form',
+                name: 'stepform',
+                component: './Form/StepForm',
+              },
+              {
+                path: '/form/advanced-form',
+                name: 'advancedform',
+                authority: ['admin'],
+                component: './Form/AdvancedForm',
+              },
+            ],
+          },
+          // list
+          {
+            path: '/list',
+            icon: 'table',
+            name: 'list',
+            routes: [
+              {
+                path: '/list/table-list',
+                name: 'searchtable',
+                component: './list/Tablelist',
+              },
+              {
+                path: '/list/basic-list',
+                name: 'basiclist',
+                component: './list/Basiclist',
+              },
+              {
+                path: '/list/card-list',
+                name: 'cardlist',
+                component: './list/Cardlist',
+              },
+              {
+                path: '/list/search',
+                name: 'search-list',
+                component: './list/search',
+                routes: [
+                  {
+                    path: '/list/search/articles',
+                    name: 'articles',
+                    component: './list/Articles',
+                  },
+                  {
+                    path: '/list/search/projects',
+                    name: 'projects',
+                    component: './list/Projects',
+                  },
+                  {
+                    path: '/list/search/applications',
+                    name: 'applications',
+                    component: './list/Applications',
+                  },
+                  {
+                    path: '/list/search',
+                    redirect: '/list/search/articles',
+                  },
+                ],
+              },
+            ],
+          },
+          {
+            path: '/profile',
+            name: 'profile',
+            icon: 'profile',
+            routes: [
+              // profile
+              {
+                path: '/profile/basic',
+                name: 'basic',
+                component: './Profile/BasicProfile',
+              },
+              {
+                path: '/profile/basic/:id',
+                hideInMenu: true,
+                component: './Profile/BasicProfile',
+              },
+              {
+                path: '/profile/advanced',
+                name: 'advanced',
+                authority: ['admin'],
+                component: './Profile/AdvancedProfile',
+              },
+            ],
+          },
+          {
+            name: 'result',
+            icon: 'check-circle-o',
+            path: '/result',
+            routes: [
+              // result
+              {
+                path: '/result/success',
+                name: 'success',
+                component: './Result/Success',
+              },
+              { path: '/result/fail', name: 'fail', component: './Result/Error' },
+            ],
+          },
+          {
+            name: 'exception',
+            icon: 'warning',
+            path: '/exception',
+            routes: [
+              // exception
+              {
+                path: '/exception/403',
+                name: 'not-permission',
+                component: './Exception/403',
+              },
+              {
+                path: '/exception/404',
+                name: 'not-find',
+                component: './Exception/404',
+              },
+              {
+                path: '/exception/500',
+                name: 'server-error',
+                component: './Exception/500',
+              },
+            ],
+          },
+          {
+            name: 'account',
+            icon: 'user',
+            path: '/account',
+            routes: [
+              {
+                path: '/account/center',
+                name: 'center',
+                component: './Account/Center/Center',
+              },
+              {
+                path: '/account/settings',
+                name: 'settings',
+                component: './Account/Settings/Info',
+              },
+            ],
+          },
+          //  editor
+          {
+            name: 'editor',
+            icon: 'highlight',
+            path: '/editor',
+            routes: [
+              {
+                path: '/editor/flow',
+                name: 'flow',
+                component: './Editor/GGEditor/Flow',
+              },
+              {
+                path: '/editor/mind',
+                name: 'mind',
+                component: './Editor/GGEditor/Mind',
+              },
+              {
+                path: '/editor/koni',
+                name: 'koni',
+                component: './Editor/GGEditor/Koni',
+              },
+            ],
+          },
+          { path: '/', redirect: '/dashboard/analysis', authority: ['admin', 'user'] },
+          {
+            component: '404',
+          },
+        ],
+      },
+    ],
+  },
+];

+ 0 - 11
src/app.js

@@ -1,11 +0,0 @@
-export const dva = {
-  config: {
-    onError(err) {
-      err.preventDefault();
-    },
-  },
-};
-
-export function render(oldRender) {
-  oldRender();
-}

+ 0 - 98
src/components/ActiveChart/index.js

@@ -1,98 +0,0 @@
-import React, { Component } from 'react';
-import { MiniArea } from '../Charts';
-import NumberInfo from '../NumberInfo';
-import styles from './index.less';
-
-function fixedZero(val) {
-  return val * 1 < 10 ? `0${val}` : val;
-}
-
-function getActiveData() {
-  const activeData = [];
-  for (let i = 0; i < 24; i += 1) {
-    activeData.push({
-      x: `${fixedZero(i)}:00`,
-      y: Math.floor(Math.random() * 200) + i * 50,
-    });
-  }
-  return activeData;
-}
-
-export default class ActiveChart extends Component {
-  state = {
-    activeData: getActiveData(),
-  };
-
-  componentDidMount() {
-    this.loopData();
-  }
-
-  componentWillUnmount() {
-    clearTimeout(this.timer);
-    cancelAnimationFrame(this.requestRef);
-  }
-
-  loopData = () => {
-    this.timer = setTimeout(() => {
-      this.setState(
-        {
-          activeData: getActiveData(),
-        },
-        () => {
-          this.loopData();
-        }
-      );
-    }, 500);
-  };
-
-  render() {
-    const { activeData = [] } = this.state;
-
-    return (
-      <div className={styles.activeChart}>
-        <NumberInfo subTitle="目标评估" total="有望达到预期" />
-        <div style={{ marginTop: 32 }}>
-          <MiniArea
-            animate={false}
-            line
-            borderWidth={2}
-            height={84}
-            scale={{
-              y: {
-                tickCount: 3,
-              },
-            }}
-            yAxis={{
-              tickLine: false,
-              label: false,
-              title: false,
-              line: false,
-            }}
-            data={activeData}
-          />
-        </div>
-        {activeData && (
-          <div>
-            <div className={styles.activeChartGrid}>
-              <p>{[...activeData].sort()[activeData.length - 1].y + 200} 亿元</p>
-              <p>{[...activeData].sort()[Math.floor(activeData.length / 2)].y} 亿元</p>
-            </div>
-            <div className={styles.dashedLine}>
-              <div className={styles.line} />
-            </div>
-            <div className={styles.dashedLine}>
-              <div className={styles.line} />
-            </div>
-          </div>
-        )}
-        {activeData && (
-          <div className={styles.activeChartLegend}>
-            <span>00:00</span>
-            <span>{activeData[Math.floor(activeData.length / 2)].x}</span>
-            <span>{activeData[activeData.length - 1].x}</span>
-          </div>
-        )}
-      </div>
-    );
-  }
-}

+ 0 - 51
src/components/ActiveChart/index.less

@@ -1,51 +0,0 @@
-.activeChart {
-  position: relative;
-}
-.activeChartGrid {
-  p {
-    position: absolute;
-    top: 80px;
-  }
-  p:last-child {
-    top: 115px;
-  }
-}
-.activeChartLegend {
-  position: relative;
-  height: 20px;
-  margin-top: 8px;
-  font-size: 0;
-  line-height: 20px;
-  span {
-    display: inline-block;
-    width: 33.33%;
-    font-size: 12px;
-    text-align: center;
-  }
-  span:first-child {
-    text-align: left;
-  }
-  span:last-child {
-    text-align: right;
-  }
-}
-.dashedLine {
-  position: relative;
-  top: -70px;
-  left: -3px;
-  height: 1px;
-
-  .line {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    background-image: linear-gradient(to right, transparent 50%, #e9e9e9 50%);
-    background-size: 6px;
-  }
-}
-
-.dashedLine:last-child {
-  top: -36px;
-}

+ 0 - 13
src/components/ArticleListContent/index.d.ts

@@ -1,13 +0,0 @@
-import React from 'react';
-
-export interface ApplicationsProps {
-  data: {
-    content?: string;
-    updatedAt?: any;
-    avatar?: string;
-    owner?: string;
-    href?: string;
-  };
-}
-
-export default class ArticleListContent extends React.Component<ApplicationsProps, any> {}

+ 0 - 17
src/components/ArticleListContent/index.js

@@ -1,17 +0,0 @@
-import React from 'react';
-import moment from 'moment';
-import { Avatar } from 'antd';
-import styles from './index.less';
-
-const ArticleListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => (
-  <div className={styles.listContent}>
-    <div className={styles.description}>{content}</div>
-    <div className={styles.extra}>
-      <Avatar src={avatar} size="small" />
-      <a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
-      <em>{moment(updatedAt).format('YYYY-MM-DD HH:mm')}</em>
-    </div>
-  </div>
-);
-
-export default ArticleListContent;

+ 0 - 38
src/components/ArticleListContent/index.less

@@ -1,38 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.listContent {
-  .description {
-    max-width: 720px;
-    line-height: 22px;
-  }
-  .extra {
-    margin-top: 16px;
-    color: @text-color-secondary;
-    line-height: 22px;
-    & > :global(.ant-avatar) {
-      position: relative;
-      top: 1px;
-      width: 20px;
-      height: 20px;
-      margin-right: 8px;
-      vertical-align: top;
-    }
-    & > em {
-      margin-left: 16px;
-      color: @disabled-color;
-      font-style: normal;
-    }
-  }
-}
-
-@media screen and (max-width: @screen-xs) {
-  .listContent {
-    .extra {
-      & > em {
-        display: block;
-        margin-top: 8px;
-        margin-left: 0;
-      }
-    }
-  }
-}

+ 0 - 8
src/components/Authorized/Authorized.js

@@ -1,8 +0,0 @@
-import CheckPermissions from './CheckPermissions';
-
-const Authorized = ({ children, authority, noMatch = null }) => {
-  const childrenRender = typeof children === 'undefined' ? null : children;
-  return CheckPermissions(authority, childrenRender, noMatch);
-};
-
-export default Authorized;

+ 29 - 0
src/components/Authorized/Authorized.tsx

@@ -0,0 +1,29 @@
+import CheckPermissions from './CheckPermissions';
+import { IAuthorityType } from './CheckPermissions';
+import Secured from './Secured';
+import check from './CheckPermissions';
+import AuthorizedRoute from './AuthorizedRoute';
+import React from 'react';
+
+interface IAuthorizedProps {
+  authority: IAuthorityType;
+  noMatch?: React.ReactNode;
+}
+
+type IAuthorizedType = React.FunctionComponent<IAuthorizedProps> & {
+  Secured: typeof Secured;
+  check: typeof check;
+  AuthorizedRoute: typeof AuthorizedRoute;
+};
+
+const Authorized: React.FunctionComponent<IAuthorizedProps> = ({
+  children,
+  authority,
+  noMatch = null,
+}) => {
+  const childrenRender: React.ReactNode = typeof children === 'undefined' ? null : children;
+  const dom = CheckPermissions(authority, childrenRender, noMatch);
+  return <>{dom}</>;
+};
+
+export default Authorized as IAuthorizedType;

+ 0 - 13
src/components/Authorized/AuthorizedRoute.d.ts

@@ -1,13 +0,0 @@
-import React from 'react';
-import { RouteProps } from 'react-router';
-
-type authorityFN = (currentAuthority?: string) => boolean;
-
-type authority = string | string[] | authorityFN | Promise<any>;
-
-export interface IAuthorizedRouteProps extends RouteProps {
-  authority: authority;
-}
-export { authority };
-
-export default class AuthorizedRoute extends React.Component<IAuthorizedRouteProps, any> {}

+ 0 - 15
src/components/Authorized/AuthorizedRoute.js

@@ -1,15 +0,0 @@
-import React from 'react';
-import { Route, Redirect } from 'umi';
-import Authorized from './Authorized';
-
-// TODO: umi只会返回render和rest
-const AuthorizedRoute = ({ component: Component, render, authority, redirectPath, ...rest }) => (
-  <Authorized
-    authority={authority}
-    noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
-  >
-    <Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} />
-  </Authorized>
-);
-
-export default AuthorizedRoute;

+ 32 - 0
src/components/Authorized/AuthorizedRoute.tsx

@@ -0,0 +1,32 @@
+import React from 'react';
+import { Route, Redirect } from 'umi';
+import Authorized from './Authorized';
+import { IAuthorityType } from './CheckPermissions';
+
+interface IAuthorizedRoutePops {
+  currentAuthority: string;
+  component: React.ComponentClass<any, any>;
+  render: (props: any) => React.ReactNode;
+  redirectPath: string;
+  authority: IAuthorityType;
+}
+
+const AuthorizedRoute: React.SFC<IAuthorizedRoutePops> = ({
+  component: Component,
+  render,
+  authority,
+  redirectPath,
+  ...rest
+}) => (
+  <Authorized
+    authority={authority}
+    noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
+  >
+    <Route
+      {...rest}
+      render={(props: any) => (Component ? <Component {...props} /> : render(props))}
+    />
+  </Authorized>
+);
+
+export default AuthorizedRoute;

+ 0 - 55
src/components/Authorized/CheckPermissions.test.js

@@ -1,55 +0,0 @@
-import { checkPermissions } from './CheckPermissions';
-
-const target = 'ok';
-const error = 'error';
-
-describe('test CheckPermissions', () => {
-  it('Correct string permission authentication', () => {
-    expect(checkPermissions('user', 'user', target, error)).toEqual('ok');
-  });
-  it('Correct string permission authentication', () => {
-    expect(checkPermissions('user', 'NULL', target, error)).toEqual('error');
-  });
-  it('authority is undefined , return ok', () => {
-    expect(checkPermissions(null, 'NULL', target, error)).toEqual('ok');
-  });
-  it('currentAuthority is undefined , return error', () => {
-    expect(checkPermissions('admin', null, target, error)).toEqual('error');
-  });
-  it('Wrong string permission authentication', () => {
-    expect(checkPermissions('admin', 'user', target, error)).toEqual('error');
-  });
-  it('Correct Array permission authentication', () => {
-    expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual('ok');
-  });
-  it('Wrong Array permission authentication,currentAuthority error', () => {
-    expect(checkPermissions(['user', 'admin'], 'user,admin', target, error)).toEqual('error');
-  });
-  it('Wrong Array permission authentication', () => {
-    expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual('error');
-  });
-  it('Wrong Function permission authentication', () => {
-    expect(checkPermissions(() => false, 'guest', target, error)).toEqual('error');
-  });
-  it('Correct Function permission authentication', () => {
-    expect(checkPermissions(() => true, 'guest', target, error)).toEqual('ok');
-  });
-  it('authority is string, currentAuthority is array, return ok', () => {
-    expect(checkPermissions('user', ['user'], target, error)).toEqual('ok');
-  });
-  it('authority is string, currentAuthority is array, return ok', () => {
-    expect(checkPermissions('user', ['user', 'admin'], target, error)).toEqual('ok');
-  });
-  it('authority is array, currentAuthority is array, return ok', () => {
-    expect(checkPermissions(['user', 'admin'], ['user', 'admin'], target, error)).toEqual('ok');
-  });
-  it('Wrong Function permission authentication', () => {
-    expect(checkPermissions(() => false, ['user'], target, error)).toEqual('error');
-  });
-  it('Correct Function permission authentication', () => {
-    expect(checkPermissions(() => true, ['user'], target, error)).toEqual('ok');
-  });
-  it('authority is undefined , return ok', () => {
-    expect(checkPermissions(null, ['user'], target, error)).toEqual('ok');
-  });
-});

+ 18 - 5
src/components/Authorized/CheckPermissions.js

@@ -3,6 +3,13 @@ import React from 'react';
 import PromiseRender from './PromiseRender';
 import { CURRENT } from './renderAuthorize';
 
+export type IAuthorityType =
+  | undefined
+  | string
+  | string[]
+  | Promise<any>
+  | ((currentAuthority: string | string[]) => IAuthorityType);
+
 /**
  * 通用权限检查方法
  * Common check permissions method
@@ -11,7 +18,12 @@ import { CURRENT } from './renderAuthorize';
  * @param { 通过的组件 | Passing components } target
  * @param { 未通过的组件 | no pass components } Exception
  */
-const checkPermissions = (authority, currentAuthority, target, Exception) => {
+const checkPermissions = <T, K>(
+  authority: IAuthorityType,
+  currentAuthority: string | string[],
+  target: T,
+  Exception: K,
+): T | K | React.ReactNode => {
   // 没有判定权限.默认查看所有
   // Retirement authority, return target;
   if (!authority) {
@@ -41,7 +53,7 @@ const checkPermissions = (authority, currentAuthority, target, Exception) => {
   }
   // Promise 处理
   if (authority instanceof Promise) {
-    return <PromiseRender ok={target} error={Exception} promise={authority} />;
+    return <PromiseRender<T, K> ok={target} error={Exception} promise={authority} />;
   }
   // Function 处理
   if (typeof authority === 'function') {
@@ -49,7 +61,7 @@ const checkPermissions = (authority, currentAuthority, target, Exception) => {
       const bool = authority(currentAuthority);
       // 函数执行后返回值是 Promise
       if (bool instanceof Promise) {
-        return <PromiseRender ok={target} error={Exception} promise={bool} />;
+        return <PromiseRender<T, K> ok={target} error={Exception} promise={bool} />;
       }
       if (bool) {
         return target;
@@ -64,7 +76,8 @@ const checkPermissions = (authority, currentAuthority, target, Exception) => {
 
 export { checkPermissions };
 
-const check = (authority, target, Exception) =>
-  checkPermissions(authority, CURRENT, target, Exception);
+function check<T, K>(authority: IAuthorityType, target: T, Exception: K): T | K | React.ReactNode {
+  return checkPermissions<T, K>(authority, CURRENT, target, Exception);
+}
 
 export default check;

+ 28 - 10
src/components/Authorized/PromiseRender.js

@@ -4,16 +4,32 @@ import React from 'react';
 // eslint-disable-next-line import/no-cycle
 import { isComponentClass } from './Secured';
 
-export default class PromiseRender extends React.Component {
-  state = {
-    component: null,
+interface IPromiseRenderProps<T, K> {
+  ok: T;
+  error: K;
+  promise: Promise<any>;
+}
+
+interface IPromiseRenderState {
+  component: React.ComponentClass<any, any> | React.FunctionComponent<any>;
+}
+
+export default class PromiseRender<T, K> extends React.Component<
+  IPromiseRenderProps<T, K>,
+  IPromiseRenderState
+> {
+  state: IPromiseRenderState = {
+    component: () => null,
   };
 
   componentDidMount() {
     this.setRenderComponent(this.props);
   }
 
-  shouldComponentUpdate = (nextProps, nextState) => {
+  shouldComponentUpdate = (
+    nextProps: IPromiseRenderProps<T, K>,
+    nextState: IPromiseRenderState,
+  ) => {
     const { component } = this.state;
     if (!isEqual(nextProps, this.props)) {
       this.setRenderComponent(nextProps);
@@ -23,7 +39,7 @@ export default class PromiseRender extends React.Component {
   };
 
   // set render Component : ok or error
-  setRenderComponent(props) {
+  setRenderComponent(props: IPromiseRenderProps<T, K>) {
     const ok = this.checkIsInstantiation(props.ok);
     const error = this.checkIsInstantiation(props.error);
     props.promise
@@ -43,15 +59,17 @@ export default class PromiseRender extends React.Component {
   // AuthorizedRoute is already instantiated
   // Authorized  render is already instantiated, children is no instantiated
   // Secured is not instantiated
-  checkIsInstantiation = target => {
+  checkIsInstantiation = (
+    target: React.ReactNode | React.ComponentClass<any, any>,
+  ): React.FunctionComponent<any> => {
     if (isComponentClass(target)) {
-      const Target = target;
-      return props => <Target {...props} />;
+      const Target = target as React.ComponentClass<any, any>;
+      return (props: any) => <Target {...props} />;
     }
     if (React.isValidElement(target)) {
-      return props => React.cloneElement(target, props);
+      return (props: any) => React.cloneElement(target, props);
     }
-    return () => target;
+    return () => target as (React.ReactNode & null);
   };
 
   render() {

+ 12 - 12
src/components/Authorized/Secured.js

@@ -1,15 +1,15 @@
 import React from 'react';
-import Exception from '../Exception';
-// eslint-disable-next-line import/no-cycle
 import CheckPermissions from './CheckPermissions';
 
 /**
  * 默认不能访问任何页面
  * default is "NULL"
  */
-const Exception403 = () => <Exception type="403" />;
+const Exception403 = () => 403;
 
-export const isComponentClass = component => {
+export const isComponentClass = (
+  component: React.ComponentClass<any, any> | React.ReactNode,
+): boolean => {
   if (!component) return false;
   const proto = Object.getPrototypeOf(component);
   if (proto === React.Component || proto === Function.prototype) return true;
@@ -20,13 +20,13 @@ export const isComponentClass = component => {
 // AuthorizedRoute is already instantiated
 // Authorized  render is already instantiated, children is no instantiated
 // Secured is not instantiated
-const checkIsInstantiation = target => {
+const checkIsInstantiation = (target: React.ComponentClass<any, any> | React.ReactNode) => {
   if (isComponentClass(target)) {
-    const Target = target;
-    return props => <Target {...props} />;
+    const Target = target as React.ComponentClass<any, any>;
+    return (props: any) => <Target {...props} />;
   }
   if (React.isValidElement(target)) {
-    return props => React.cloneElement(target, props);
+    return (props: any) => React.cloneElement(target, props);
   }
   return () => target;
 };
@@ -46,20 +46,20 @@ const checkIsInstantiation = target => {
  * @param {string | function | Promise} authority
  * @param {ReactNode} error 非必需参数
  */
-const authorize = (authority, error) => {
+const authorize = (authority: string, error?: React.ReactNode) => {
   /**
    * conversion into a class
    * 防止传入字符串时找不到staticContext造成报错
    * String parameters can cause staticContext not found error
    */
-  let classError = false;
+  let classError: boolean | React.FunctionComponent<any> = false;
   if (error) {
-    classError = () => error;
+    classError = (() => error) as React.FunctionComponent<any>;
   }
   if (!authority) {
     throw new Error('authority is required');
   }
-  return function decideAuthority(target) {
+  return function decideAuthority(target: React.ComponentClass<any, any> | React.ReactNode) {
     const component = CheckPermissions(authority, target, classError || Exception403);
     return checkIsInstantiation(component);
   };

+ 0 - 23
src/components/Authorized/demo/AuthorizedArray.md

@@ -1,23 +0,0 @@
----
-order: 1
-title:
-  zh-CN: 使用数组作为参数
-  en-US: Use Array as a parameter
----
-
-Use Array as a parameter
-
-```jsx
-import RenderAuthorized from 'ant-design-pro/lib/Authorized';
-import { Alert } from 'antd';
-
-const Authorized = RenderAuthorized('user');
-const noMatch = <Alert message="No permission." type="error" showIcon />;
-
-ReactDOM.render(
-  <Authorized authority={['user', 'admin']} noMatch={noMatch}>
-    <Alert message="Use Array as a parameter passed!" type="success" showIcon />
-  </Authorized>,
-  mountNode
-);
-```

+ 0 - 27
src/components/Authorized/demo/AuthorizedFunction.md

@@ -1,27 +0,0 @@
----
-order: 2
-title:
-  zh-CN: 使用方法作为参数
-  en-US: Use function as a parameter
----
-
-Use Function as a parameter
-
-```jsx
-import RenderAuthorized from 'ant-design-pro/lib/Authorized';
-import { Alert } from 'antd';
-
-const Authorized = RenderAuthorized('user');
-const noMatch = <Alert message="No permission." type="error" showIcon />;
-
-const havePermission = () => {
-  return false;
-};
-
-ReactDOM.render(
-  <Authorized authority={havePermission} noMatch={noMatch}>
-    <Alert message="Use Function as a parameter passed!" type="success" showIcon />
-  </Authorized>,
-  mountNode
-);
-```

+ 0 - 25
src/components/Authorized/demo/basic.md

@@ -1,25 +0,0 @@
----
-order: 0
-title:
-  zh-CN: 基本使用
-  en-US: Basic use
----
-
-Basic use
-
-```jsx
-import RenderAuthorized from 'ant-design-pro/lib/Authorized';
-import { Alert } from 'antd';
-
-const Authorized = RenderAuthorized('user');
-const noMatch = <Alert message="No permission." type="error" showIcon />;
-
-ReactDOM.render(
-  <div>
-    <Authorized authority="admin" noMatch={noMatch}>
-      <Alert message="user Passed!" type="success" showIcon />
-    </Authorized>
-  </div>,
-  mountNode
-);
-```

+ 0 - 28
src/components/Authorized/demo/secured.md

@@ -1,28 +0,0 @@
----
-order: 3
-title:
-  zh-CN: 注解基本使用
-  en-US: Basic use secured
----
-
-secured demo used
-
-```jsx
-import RenderAuthorized from 'ant-design-pro/lib/Authorized';
-import { Alert } from 'antd';
-
-const { Secured } = RenderAuthorized('user');
-
-@Secured('admin')
-class TestSecuredString extends React.Component {
-  render() {
-    return <Alert message="user Passed!" type="success" showIcon />;
-  }
-}
-ReactDOM.render(
-  <div>
-    <TestSecuredString />
-  </div>,
-  mountNode
-);
-```

+ 0 - 32
src/components/Authorized/index.d.ts

@@ -1,32 +0,0 @@
-import React from 'react';
-import AuthorizedRoute, { authority } from './AuthorizedRoute';
-export type IReactComponent<P = any> =
-  | React.StatelessComponent<P>
-  | React.ComponentClass<P>
-  | React.ClassicComponentClass<P>;
-
-type Secured = (
-  authority: authority,
-  error?: React.ReactNode
-) => <T extends IReactComponent>(target: T) => T;
-
-type check = <T extends IReactComponent, S extends IReactComponent>(
-  authority: authority,
-  target: T,
-  Exception: S
-) => T | S;
-
-export interface IAuthorizedProps {
-  authority: authority;
-  noMatch?: React.ReactNode;
-}
-
-export class Authorized extends React.Component<IAuthorizedProps, any> {
-  public static Secured: Secured;
-  public static AuthorizedRoute: typeof AuthorizedRoute;
-  public static check: check;
-}
-
-declare function renderAuthorize(currentAuthority: string): typeof Authorized;
-
-export default renderAuthorize;

+ 0 - 54
src/components/Authorized/index.md

@@ -1,54 +0,0 @@
----
-title: Authorized
-subtitle: 权限
-cols: 1
-order: 15
----
-
-权限组件,通过比对现有权限与准入权限,决定相关元素的展示。
-
-## API
-
-### RenderAuthorized
-
-`RenderAuthorized: (currentAuthority: string | () => string) => Authorized`
-
-权限组件默认 export RenderAuthorized 函数,它接收当前权限作为参数,返回一个权限对象,该对象提供以下几种使用方式。
-
-### Authorized
-
-最基础的权限控制。
-
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| children | 正常渲染的元素,权限判断通过时展示 | ReactNode | - |
-| authority | 准入权限/权限判断 | `string | array | Promise | (currentAuthority) => boolean | Promise` | - |
-| noMatch | 权限异常渲染元素,权限判断不通过时展示 | ReactNode | - |
-
-### Authorized.AuthorizedRoute
-
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| authority | 准入权限/权限判断 | `string | array | Promise | (currentAuthority) => boolean | Promise` | - |
-| redirectPath | 权限异常时重定向的页面路由 | string | - |
-
-其余参数与 `Route` 相同。
-
-### Authorized.Secured
-
-注解方式,`@Authorized.Secured(authority, error)`
-
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| authority | 准入权限/权限判断 | `string | Promise | (currentAuthority) => boolean | Promise` | - |
-| error | 权限异常时渲染元素 | ReactNode | <Exception type="403" /> |
-
-### Authorized.check
-
-函数形式的 Authorized,用于某些不能被 HOC 包裹的组件。 `Authorized.check(authority, target, Exception)` 注意:传入一个 Promise 时,无论正确还是错误返回的都是一个 ReactClass。
-
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| authority | 准入权限/权限判断 | `string | Promise | (currentAuthority) => boolean | Promise` | - |
-| target | 权限判断通过时渲染的元素 | ReactNode | - |
-| Exception | 权限异常时渲染元素 | ReactNode | - |

+ 3 - 1
src/components/Authorized/index.js

@@ -8,4 +8,6 @@ Authorized.Secured = Secured;
 Authorized.AuthorizedRoute = AuthorizedRoute;
 Authorized.check = check;
 
-export default renderAuthorize(Authorized);
+const RenderAuthorize = renderAuthorize(Authorized);
+
+export default RenderAuthorize;

+ 7 - 5
src/components/Authorized/renderAuthorize.js

@@ -1,10 +1,12 @@
-/* eslint-disable import/no-mutable-exports */
-let CURRENT = 'NULL';
+let CURRENT: string | string[] = 'NULL';
+type CurrentAuthorityType = string | string[] | (() => typeof CURRENT);
 /**
  * use  authority or getAuthority
  * @param {string|()=>String} currentAuthority
  */
-const renderAuthorize = Authorized => currentAuthority => {
+const renderAuthorize = <T>(Authorized: T): ((currentAuthority: CurrentAuthorityType) => T) => (
+  currentAuthority: CurrentAuthorityType,
+) => {
   if (currentAuthority) {
     if (typeof currentAuthority === 'function') {
       CURRENT = currentAuthority();
@@ -13,7 +15,7 @@ const renderAuthorize = Authorized => currentAuthority => {
       Object.prototype.toString.call(currentAuthority) === '[object String]' ||
       Array.isArray(currentAuthority)
     ) {
-      CURRENT = currentAuthority;
+      CURRENT = currentAuthority as string[];
     }
   } else {
     CURRENT = 'NULL';
@@ -22,4 +24,4 @@ const renderAuthorize = Authorized => currentAuthority => {
 };
 
 export { CURRENT };
-export default Authorized => renderAuthorize(Authorized);
+export default <T>(Authorized: T) => renderAuthorize<T>(Authorized);

+ 0 - 15
src/components/AvatarList/AvatarItem.d.ts

@@ -1,15 +0,0 @@
-import React from 'react';
-
-export declare type SizeType = number | 'small' | 'default' | 'large';
-
-export interface AvatarItemProps {
-  tips: React.ReactNode;
-  src: string;
-  size?: SizeType;
-  style?: React.CSSProperties;
-  onClick?: () => void;
-}
-
-export default class AvatarItem extends React.Component<AvatarItemProps, any> {
-  constructor(props: AvatarItemProps);
-}

+ 0 - 46
src/components/AvatarList/demo/maxLength.md

@@ -1,46 +0,0 @@
----
-order: 0
-title:
-  zh-CN: 要显示的最大项目
-  en-US: Max Items to Show
----
-
-`maxLength` attribute specifies the maximum number of items to show while `excessItemsStyle` style the excess item component.
-
-```jsx
-import AvatarList from 'ant-design-pro/lib/AvatarList';
-
-ReactDOM.render(
-  <AvatarList
-    size="mini"
-    maxLength={3}
-    excessItemsStyle={{ color: '#f56a00', backgroundColor: '#fde3cf' }}
-  >
-    <AvatarList.Item
-      tips="Jake"
-      src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png"
-    />
-    <AvatarList.Item
-      tips="Andy"
-      src="https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png"
-    />
-    <AvatarList.Item
-      tips="Niko"
-      src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png"
-    />
-    <AvatarList.Item
-      tips="Niko"
-      src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png"
-    />
-    <AvatarList.Item
-      tips="Niko"
-      src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png"
-    />
-    <AvatarList.Item
-      tips="Niko"
-      src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png"
-    />
-  </AvatarList>,
-  mountNode
-);
-```

+ 0 - 30
src/components/AvatarList/demo/simple.md

@@ -1,30 +0,0 @@
----
-order: 0
-title:
-  zh-CN: 基础样例
-  en-US: Basic Usage
----
-
-Simplest of usage.
-
-```jsx
-import AvatarList from 'ant-design-pro/lib/AvatarList';
-
-ReactDOM.render(
-  <AvatarList size="mini">
-    <AvatarList.Item
-      tips="Jake"
-      src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png"
-    />
-    <AvatarList.Item
-      tips="Andy"
-      src="https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png"
-    />
-    <AvatarList.Item
-      tips="Niko"
-      src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png"
-    />
-  </AvatarList>,
-  mountNode
-);
-```

+ 0 - 14
src/components/AvatarList/index.d.ts

@@ -1,14 +0,0 @@
-import React from 'react';
-import AvatarItem, { AvatarItemProps, SizeType } from './AvatarItem';
-
-export interface AvatarListProps {
-  Item?: React.ReactElement<AvatarItemProps>;
-  size?: SizeType;
-  maxLength?: number;
-  excessItemsStyle?: React.CSSProperties;
-  style?: React.CSSProperties;
-  children: React.ReactElement<AvatarItemProps> | Array<React.ReactElement<AvatarItemProps>>;
-}
-export default class AvatarList extends React.Component<AvatarListProps, any> {
-  public static Item: typeof AvatarItem;
-}

+ 0 - 24
src/components/AvatarList/index.en-US.md

@@ -1,24 +0,0 @@
----
-title: AvatarList
-order: 1
-cols: 1
----
-
-A list of user's avatar for project or group member list frequently. If a large or small AvatarList is desired, set the `size` property to either `large` or `small` and `mini` respectively. Omit the `size` property for a AvatarList with the default size.
-
-## API
-
-### AvatarList
-
-| Property         | Description           | Type                                 | Default   |
-| ---------------- | --------------------- | ------------------------------------ | --------- |
-| size             | size of list          | `large`、`small` 、`mini`, `default` | `default` |
-| maxLength        | max items to show     | number                               | -         |
-| excessItemsStyle | the excess item style | CSSProperties                        | -         |
-
-### AvatarList.Item
-
-| Property | Description                                  | Type      | Default |
-| -------- | -------------------------------------------- | --------- | ------- |
-| tips     | title tips for avatar item                   | ReactNode | -       |
-| src      | the address of the image for an image avatar | string    | -       |

+ 0 - 61
src/components/AvatarList/index.js

@@ -1,61 +0,0 @@
-import React from 'react';
-import { Tooltip, Avatar } from 'antd';
-import classNames from 'classnames';
-
-import styles from './index.less';
-
-const avatarSizeToClassName = size =>
-  classNames(styles.avatarItem, {
-    [styles.avatarItemLarge]: size === 'large',
-    [styles.avatarItemSmall]: size === 'small',
-    [styles.avatarItemMini]: size === 'mini',
-  });
-
-const AvatarList = ({ children, size, maxLength, excessItemsStyle, ...other }) => {
-  const numOfChildren = React.Children.count(children);
-  const numToShow = maxLength >= numOfChildren ? numOfChildren : maxLength;
-
-  const childrenWithProps = React.Children.toArray(children)
-    .slice(0, numToShow)
-    .map(child =>
-      React.cloneElement(child, {
-        size,
-      })
-    );
-
-  if (numToShow < numOfChildren) {
-    const cls = avatarSizeToClassName(size);
-
-    childrenWithProps.push(
-      <li key="exceed" className={cls}>
-        <Avatar size={size} style={excessItemsStyle}>{`+${numOfChildren - maxLength}`}</Avatar>
-      </li>
-    );
-  }
-
-  return (
-    <div {...other} className={styles.avatarList}>
-      <ul> {childrenWithProps} </ul>
-    </div>
-  );
-};
-
-const Item = ({ src, size, tips, onClick = () => {} }) => {
-  const cls = avatarSizeToClassName(size);
-
-  return (
-    <li className={cls} onClick={onClick}>
-      {tips ? (
-        <Tooltip title={tips}>
-          <Avatar src={src} size={size} style={{ cursor: 'pointer' }} />
-        </Tooltip>
-      ) : (
-        <Avatar src={src} size={size} />
-      )}
-    </li>
-  );
-};
-
-AvatarList.Item = Item;
-
-export default AvatarList;

+ 0 - 50
src/components/AvatarList/index.less

@@ -1,50 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.avatarList {
-  display: inline-block;
-  ul {
-    display: inline-block;
-    margin-left: 8px;
-    font-size: 0;
-  }
-}
-
-.avatarItem {
-  display: inline-block;
-  width: @avatar-size-base;
-  height: @avatar-size-base;
-  margin-left: -8px;
-  font-size: @font-size-base;
-  :global {
-    .ant-avatar {
-      border: 1px solid #fff;
-    }
-  }
-}
-
-.avatarItemLarge {
-  width: @avatar-size-lg;
-  height: @avatar-size-lg;
-}
-
-.avatarItemSmall {
-  width: @avatar-size-sm;
-  height: @avatar-size-sm;
-}
-
-.avatarItemMini {
-  width: 20px;
-  height: 20px;
-  :global {
-    .ant-avatar {
-      width: 20px;
-      height: 20px;
-      line-height: 20px;
-
-      .ant-avatar-string {
-        font-size: 12px;
-        line-height: 18px;
-      }
-    }
-  }
-}

+ 0 - 29
src/components/AvatarList/index.test.js

@@ -1,29 +0,0 @@
-import React from 'react';
-import range from 'lodash/range';
-import { mount } from 'enzyme';
-import AvatarList from './index';
-
-const renderItems = numItems =>
-  range(numItems).map(i => (
-    <AvatarList.Item
-      key={i}
-      tips="Jake"
-      src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png"
-    />
-  ));
-
-describe('AvatarList', () => {
-  it('renders all items', () => {
-    const wrapper = mount(<AvatarList>{renderItems(4)}</AvatarList>);
-    expect(wrapper.find('AvatarList').length).toBe(1);
-    expect(wrapper.find('Item').length).toBe(4);
-    expect(wrapper.findWhere(node => node.key() === 'exceed').length).toBe(0);
-  });
-
-  it('renders max of 3 items', () => {
-    const wrapper = mount(<AvatarList maxLength={3}>{renderItems(4)}</AvatarList>);
-    expect(wrapper.find('AvatarList').length).toBe(1);
-    expect(wrapper.find('Item').length).toBe(3);
-    expect(wrapper.findWhere(node => node.key() === 'exceed').length).toBe(1);
-  });
-});

+ 0 - 25
src/components/AvatarList/index.zh-CN.md

@@ -1,25 +0,0 @@
----
-title: AvatarList
-subtitle: 用户头像列表
-order: 1
-cols: 1
----
-
-一组用户头像,常用在项目/团队成员列表。可通过设置 `size` 属性来指定头像大小。
-
-## API
-
-### AvatarList
-
-| 参数             | 说明             | 类型                                 | 默认值    |
-| ---------------- | ---------------- | ------------------------------------ | --------- |
-| size             | 头像大小         | `large`、`small` 、`mini`, `default` | `default` |
-| maxLength        | 要显示的最大项目 | number                               | -         |
-| excessItemsStyle | 多余的项目风格   | CSSProperties                        | -         |
-
-### AvatarList.Item
-
-| 参数 | 说明         | 类型      | 默认值 |
-| ---- | ------------ | --------- | ------ |
-| tips | 头像展示文案 | ReactNode | -      |
-| src  | 头像图片连接 | string    | -      |

+ 0 - 15
src/components/Charts/Bar/index.d.ts

@@ -1,15 +0,0 @@
-import React from 'react';
-export interface IBarProps {
-  title: React.ReactNode;
-  color?: string;
-  padding?: [number, number, number, number];
-  height: number;
-  data: Array<{
-    x: string;
-    y: number;
-  }>;
-  autoLabel?: boolean;
-  style?: React.CSSProperties;
-}
-
-export default class Bar extends React.Component<IBarProps, any> {}

+ 0 - 124
src/components/Charts/Bar/index.js

@@ -1,124 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import ResizeObserver from 'resize-observer-polyfill';
-import styles from '../index.less';
-
-class Bar extends Component {
-  state = {
-    height: 0,
-    autoHideXLabels: false,
-  };
-
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
-  resizeObserver() {
-    const ro = new ResizeObserver(entries => {
-      const { width, height } = entries[0].contentRect;
-      this.resize();
-      this.setState(preState => {
-        if (preState.width !== width || preState.height !== height) {
-          return {
-            height,
-          };
-        }
-        return null;
-      });
-    });
-    if (this.root) {
-      ro.observe(this.root);
-    }
-  }
-
-  @Bind()
-  @Debounce(400)
-  resize() {
-    if (!this.node) {
-      return;
-    }
-    const canvasWidth = this.node.parentNode.clientWidth;
-    const { data = [], autoLabel = true } = this.props;
-    if (!autoLabel) {
-      return;
-    }
-    const minWidth = data.length * 30;
-    const { autoHideXLabels } = this.state;
-
-    if (canvasWidth <= minWidth) {
-      if (!autoHideXLabels) {
-        this.setState({
-          autoHideXLabels: true,
-        });
-      }
-    } else if (autoHideXLabels) {
-      this.setState({
-        autoHideXLabels: false,
-      });
-    }
-  }
-
-  render() {
-    const {
-      height: propsHeight,
-      title,
-      forceFit = true,
-      data,
-      color = 'rgba(24, 144, 255, 0.85)',
-      padding,
-    } = this.props;
-
-    const { autoHideXLabels } = this.state;
-
-    const scale = {
-      x: {
-        type: 'cat',
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    const tooltip = [
-      'x*y',
-      (x, y) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-    const { height: stateHeight } = this.state;
-    const height = propsHeight || stateHeight;
-    return (
-      <div className={styles.chart} style={{ height }} ref={this.handleRoot}>
-        <div ref={this.handleRef}>
-          {title && <h4 style={{ marginBottom: 20 }}>{title}</h4>}
-          <Chart
-            scale={scale}
-            height={title ? height - 41 : height}
-            forceFit={forceFit}
-            data={data}
-            padding={padding || 'auto'}
-          >
-            <Axis
-              name="x"
-              title={false}
-              label={autoHideXLabels ? false : {}}
-              tickLine={autoHideXLabels ? false : {}}
-            />
-            <Axis name="y" min={0} />
-            <Tooltip showTitle={false} crosshairs={false} />
-            <Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
-          </Chart>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default Bar;

+ 0 - 14
src/components/Charts/ChartCard/index.d.ts

@@ -1,14 +0,0 @@
-import { CardProps } from 'antd/lib/card';
-import React from 'react';
-
-export interface IChartCardProps extends CardProps {
-  title: React.ReactNode;
-  action?: React.ReactNode;
-  total?: React.ReactNode | number | (() => React.ReactNode | number);
-  footer?: React.ReactNode;
-  contentHeight?: number;
-  avatar?: React.ReactNode;
-  style?: React.CSSProperties;
-}
-
-export default class ChartCard extends React.Component<IChartCardProps, any> {}

+ 0 - 82
src/components/Charts/ChartCard/index.js

@@ -1,82 +0,0 @@
-import React from 'react';
-import { Card } from 'antd';
-import classNames from 'classnames';
-
-import styles from './index.less';
-
-const renderTotal = total => {
-  let totalDom;
-  switch (typeof total) {
-    case 'undefined':
-      totalDom = null;
-      break;
-    case 'function':
-      totalDom = <div className={styles.total}>{total()}</div>;
-      break;
-    default:
-      totalDom = <div className={styles.total}>{total}</div>;
-  }
-  return totalDom;
-};
-
-class ChartCard extends React.PureComponent {
-  renderConnet = () => {
-    const { contentHeight, title, avatar, action, total, footer, children, loading } = this.props;
-    if (loading) {
-      return false;
-    }
-    return (
-      <div className={styles.chartCard}>
-        <div
-          className={classNames(styles.chartTop, {
-            [styles.chartTopMargin]: !children && !footer,
-          })}
-        >
-          <div className={styles.avatar}>{avatar}</div>
-          <div className={styles.metaWrap}>
-            <div className={styles.meta}>
-              <span className={styles.title}>{title}</span>
-              <span className={styles.action}>{action}</span>
-            </div>
-            {renderTotal(total)}
-          </div>
-        </div>
-        {children && (
-          <div className={styles.content} style={{ height: contentHeight || 'auto' }}>
-            <div className={contentHeight && styles.contentFixed}>{children}</div>
-          </div>
-        )}
-        {footer && (
-          <div
-            className={classNames(styles.footer, {
-              [styles.footerMargin]: !children,
-            })}
-          >
-            {footer}
-          </div>
-        )}
-      </div>
-    );
-  };
-
-  render() {
-    const {
-      loading = false,
-      contentHeight,
-      title,
-      avatar,
-      action,
-      total,
-      footer,
-      children,
-      ...rest
-    } = this.props;
-    return (
-      <Card loading={loading} bodyStyle={{ padding: '20px 24px 8px 24px' }} {...rest}>
-        {this.renderConnet()}
-      </Card>
-    );
-  }
-}
-
-export default ChartCard;

+ 0 - 75
src/components/Charts/ChartCard/index.less

@@ -1,75 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.chartCard {
-  position: relative;
-  .chartTop {
-    position: relative;
-    width: 100%;
-    overflow: hidden;
-  }
-  .chartTopMargin {
-    margin-bottom: 12px;
-  }
-  .chartTopHasMargin {
-    margin-bottom: 20px;
-  }
-  .metaWrap {
-    float: left;
-  }
-  .avatar {
-    position: relative;
-    top: 4px;
-    float: left;
-    margin-right: 20px;
-    img {
-      border-radius: 100%;
-    }
-  }
-  .meta {
-    height: 22px;
-    color: @text-color-secondary;
-    font-size: @font-size-base;
-    line-height: 22px;
-  }
-  .action {
-    position: absolute;
-    top: 4px;
-    right: 0;
-    line-height: 1;
-    cursor: pointer;
-  }
-  .total {
-    height: 38px;
-    margin-top: 4px;
-    margin-bottom: 0;
-    overflow: hidden;
-    color: @heading-color;
-    font-size: 30px;
-    line-height: 38px;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    word-break: break-all;
-  }
-  .content {
-    position: relative;
-    width: 100%;
-    margin-bottom: 12px;
-  }
-  .contentFixed {
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-  }
-  .footer {
-    margin-top: 8px;
-    padding-top: 9px;
-    border-top: 1px solid @border-color-split;
-    & > * {
-      position: relative;
-    }
-  }
-  .footerMargin {
-    margin-top: 20px;
-  }
-}

+ 0 - 8
src/components/Charts/Field/index.d.ts

@@ -1,8 +0,0 @@
-import React from 'react';
-export interface IFieldProps {
-  label: React.ReactNode;
-  value: React.ReactNode;
-  style?: React.CSSProperties;
-}
-
-export default class Field extends React.Component<IFieldProps, any> {}

+ 0 - 12
src/components/Charts/Field/index.js

@@ -1,12 +0,0 @@
-import React from 'react';
-
-import styles from './index.less';
-
-const Field = ({ label, value, ...rest }) => (
-  <div className={styles.field} {...rest}>
-    <span className={styles.label}>{label}</span>
-    <span className={styles.number}>{value}</span>
-  </div>
-);
-
-export default Field;

+ 0 - 17
src/components/Charts/Field/index.less

@@ -1,17 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.field {
-  margin: 0;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  .label,
-  .number {
-    font-size: @font-size-base;
-    line-height: 22px;
-  }
-  .number {
-    margin-left: 8px;
-    color: @heading-color;
-  }
-}

+ 0 - 11
src/components/Charts/Gauge/index.d.ts

@@ -1,11 +0,0 @@
-import React from 'react';
-export interface IGaugeProps {
-  title: React.ReactNode;
-  color?: string;
-  height: number;
-  bgColor?: number;
-  percent: number;
-  style?: React.CSSProperties;
-}
-
-export default class Gauge extends React.Component<IGaugeProps, any> {}

+ 0 - 167
src/components/Charts/Gauge/index.js

@@ -1,167 +0,0 @@
-import React from 'react';
-import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
-import autoHeight from '../autoHeight';
-
-const { Arc, Html, Line } = Guide;
-
-const defaultFormatter = val => {
-  switch (val) {
-    case '2':
-      return '差';
-    case '4':
-      return '中';
-    case '6':
-      return '良';
-    case '8':
-      return '优';
-    default:
-      return '';
-  }
-};
-
-Shape.registerShape('point', 'pointer', {
-  drawShape(cfg, group) {
-    let point = cfg.points[0];
-    point = this.parsePoint(point);
-    const center = this.parsePoint({
-      x: 0,
-      y: 0,
-    });
-    group.addShape('line', {
-      attrs: {
-        x1: center.x,
-        y1: center.y,
-        x2: point.x,
-        y2: point.y,
-        stroke: cfg.color,
-        lineWidth: 2,
-        lineCap: 'round',
-      },
-    });
-    return group.addShape('circle', {
-      attrs: {
-        x: center.x,
-        y: center.y,
-        r: 6,
-        stroke: cfg.color,
-        lineWidth: 3,
-        fill: '#fff',
-      },
-    });
-  },
-});
-
-@autoHeight()
-class Gauge extends React.Component {
-  render() {
-    const {
-      title,
-      height,
-      percent,
-      forceFit = true,
-      formatter = defaultFormatter,
-      color = '#2F9CFF',
-      bgColor = '#F0F2F5',
-    } = this.props;
-    const cols = {
-      value: {
-        type: 'linear',
-        min: 0,
-        max: 10,
-        tickCount: 6,
-        nice: true,
-      },
-    };
-    const data = [{ value: percent / 10 }];
-    return (
-      <Chart height={height} data={data} scale={cols} padding={[-16, 0, 16, 0]} forceFit={forceFit}>
-        <Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={0.8} />
-        <Axis name="1" line={null} />
-        <Axis
-          line={null}
-          tickLine={null}
-          subTickLine={null}
-          name="value"
-          zIndex={2}
-          gird={null}
-          label={{
-            offset: -12,
-            formatter,
-            textStyle: {
-              fontSize: 12,
-              fill: 'rgba(0, 0, 0, 0.65)',
-              textAlign: 'center',
-            },
-          }}
-        />
-        <Guide>
-          <Line
-            start={[3, 0.905]}
-            end={[3, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: null,
-              lineWidth: 2,
-            }}
-          />
-          <Line
-            start={[5, 0.905]}
-            end={[5, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: null,
-              lineWidth: 3,
-            }}
-          />
-          <Line
-            start={[7, 0.905]}
-            end={[7, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: null,
-              lineWidth: 3,
-            }}
-          />
-          <Arc
-            zIndex={0}
-            start={[0, 0.965]}
-            end={[10, 0.965]}
-            style={{
-              stroke: bgColor,
-              lineWidth: 10,
-            }}
-          />
-          <Arc
-            zIndex={1}
-            start={[0, 0.965]}
-            end={[data[0].value, 0.965]}
-            style={{
-              stroke: color,
-              lineWidth: 10,
-            }}
-          />
-          <Html
-            position={['50%', '95%']}
-            html={() => `
-                <div style="width: 300px;text-align: center;font-size: 12px!important;">
-                  <p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
-                  <p style="font-size: 24px;color: rgba(0,0,0,0.85);margin: 0;">
-                    ${(data[0].value * 10).toFixed(2)}%
-                  </p>
-                </div>`}
-          />
-        </Guide>
-        <Geom
-          line={false}
-          type="point"
-          position="value*1"
-          shape="pointer"
-          color={color}
-          active={false}
-        />
-      </Chart>
-    );
-  }
-}
-
-export default Gauge;

+ 0 - 29
src/components/Charts/MiniArea/index.d.ts

@@ -1,29 +0,0 @@
-import React from 'react';
-
-// g2已经更新到3.0
-// 不带的写了
-
-export interface IAxis {
-  title: any;
-  line: any;
-  gridAlign: any;
-  labels: any;
-  tickLine: any;
-  grid: any;
-}
-
-export interface IMiniAreaProps {
-  color?: string;
-  height: number;
-  borderColor?: string;
-  line?: boolean;
-  animate?: boolean;
-  xAxis?: IAxis;
-  yAxis?: IAxis;
-  data: Array<{
-    x: number | string;
-    y: number;
-  }>;
-}
-
-export default class MiniArea extends React.Component<IMiniAreaProps, any> {}

+ 0 - 108
src/components/Charts/MiniArea/index.js

@@ -1,108 +0,0 @@
-import React from 'react';
-import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
-import autoHeight from '../autoHeight';
-import styles from '../index.less';
-
-@autoHeight()
-class MiniArea extends React.PureComponent {
-  render() {
-    const {
-      height,
-      data = [],
-      forceFit = true,
-      color = 'rgba(24, 144, 255, 0.2)',
-      borderColor = '#1089ff',
-      scale = {},
-      borderWidth = 2,
-      line,
-      xAxis,
-      yAxis,
-      animate = true,
-    } = this.props;
-
-    const padding = [36, 5, 30, 5];
-
-    const scaleProps = {
-      x: {
-        type: 'cat',
-        range: [0, 1],
-        ...scale.x,
-      },
-      y: {
-        min: 0,
-        ...scale.y,
-      },
-    };
-
-    const tooltip = [
-      'x*y',
-      (x, y) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-
-    const chartHeight = height + 54;
-
-    return (
-      <div className={styles.miniChart} style={{ height }}>
-        <div className={styles.chartContent}>
-          {height > 0 && (
-            <Chart
-              animate={animate}
-              scale={scaleProps}
-              height={chartHeight}
-              forceFit={forceFit}
-              data={data}
-              padding={padding}
-            >
-              <Axis
-                key="axis-x"
-                name="x"
-                label={false}
-                line={false}
-                tickLine={false}
-                grid={false}
-                {...xAxis}
-              />
-              <Axis
-                key="axis-y"
-                name="y"
-                label={false}
-                line={false}
-                tickLine={false}
-                grid={false}
-                {...yAxis}
-              />
-              <Tooltip showTitle={false} crosshairs={false} />
-              <Geom
-                type="area"
-                position="x*y"
-                color={color}
-                tooltip={tooltip}
-                shape="smooth"
-                style={{
-                  fillOpacity: 1,
-                }}
-              />
-              {line ? (
-                <Geom
-                  type="line"
-                  position="x*y"
-                  shape="smooth"
-                  color={borderColor}
-                  size={borderWidth}
-                  tooltip={false}
-                />
-              ) : (
-                <span style={{ display: 'none' }} />
-              )}
-            </Chart>
-          )}
-        </div>
-      </div>
-    );
-  }
-}
-
-export default MiniArea;

+ 0 - 12
src/components/Charts/MiniBar/index.d.ts

@@ -1,12 +0,0 @@
-import React from 'react';
-export interface IMiniBarProps {
-  color?: string;
-  height: number;
-  data: Array<{
-    x: number | string;
-    y: number;
-  }>;
-  style?: React.CSSProperties;
-}
-
-export default class MiniBar extends React.Component<IMiniBarProps, any> {}

+ 0 - 51
src/components/Charts/MiniBar/index.js

@@ -1,51 +0,0 @@
-import React from 'react';
-import { Chart, Tooltip, Geom } from 'bizcharts';
-import autoHeight from '../autoHeight';
-import styles from '../index.less';
-
-@autoHeight()
-class MiniBar extends React.Component {
-  render() {
-    const { height, forceFit = true, color = '#1890FF', data = [] } = this.props;
-
-    const scale = {
-      x: {
-        type: 'cat',
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    const padding = [36, 5, 30, 5];
-
-    const tooltip = [
-      'x*y',
-      (x, y) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-
-    // for tooltip not to be hide
-    const chartHeight = height + 54;
-
-    return (
-      <div className={styles.miniChart} style={{ height }}>
-        <div className={styles.chartContent}>
-          <Chart
-            scale={scale}
-            height={chartHeight}
-            forceFit={forceFit}
-            data={data}
-            padding={padding}
-          >
-            <Tooltip showTitle={false} crosshairs={false} />
-            <Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
-          </Chart>
-        </div>
-      </div>
-    );
-  }
-}
-export default MiniBar;

+ 0 - 11
src/components/Charts/MiniProgress/index.d.ts

@@ -1,11 +0,0 @@
-import React from 'react';
-export interface IMiniProgressProps {
-  target: number;
-  targetLabel: string;
-  color?: string;
-  strokeWidth?: number;
-  percent?: number;
-  style?: React.CSSProperties;
-}
-
-export default class MiniProgress extends React.Component<IMiniProgressProps, any> {}

+ 0 - 34
src/components/Charts/MiniProgress/index.js

@@ -1,34 +0,0 @@
-import React from 'react';
-import { Tooltip } from 'antd';
-import styles from './index.less';
-
-const MiniProgress = ({
-  targetLabel,
-  target,
-  color = 'rgb(19, 194, 194)',
-  strokeWidth,
-  percent,
-}) => {
-  return (
-    <div className={styles.miniProgress}>
-      <Tooltip title={targetLabel}>
-        <div className={styles.target} style={{ left: target ? `${target}%` : null }}>
-          <span style={{ backgroundColor: color || null }} />
-          <span style={{ backgroundColor: color || null }} />
-        </div>
-      </Tooltip>
-      <div className={styles.progressWrap}>
-        <div
-          className={styles.progress}
-          style={{
-            backgroundColor: color || null,
-            width: percent ? `${percent}%` : null,
-            height: strokeWidth || null,
-          }}
-        />
-      </div>
-    </div>
-  );
-};
-
-export default MiniProgress;

+ 0 - 37
src/components/Charts/MiniProgress/index.less

@@ -1,37 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.miniProgress {
-  position: relative;
-  width: 100%;
-  padding: 5px 0;
-  .progressWrap {
-    position: relative;
-    background-color: @background-color-base;
-  }
-  .progress {
-    width: 0;
-    height: 100%;
-    background-color: @primary-color;
-    border-radius: 1px 0 0 1px;
-    transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
-  }
-  .target {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    z-index: 9;
-    width: 20px;
-    span {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 2px;
-      height: 4px;
-      border-radius: 100px;
-    }
-    span:last-child {
-      top: auto;
-      bottom: 0;
-    }
-  }
-}

+ 0 - 21
src/components/Charts/Pie/index.d.ts

@@ -1,21 +0,0 @@
-import React from 'react';
-export interface IPieProps {
-  animate?: boolean;
-  color?: string;
-  colors?: string[];
-  height: number;
-  hasLegend?: boolean;
-  padding?: [number, number, number, number];
-  percent?: number;
-  data?: Array<{
-    x: string | string;
-    y: number;
-  }>;
-  total?: React.ReactNode | number | (() => React.ReactNode | number);
-  title?: React.ReactNode;
-  tooltip?: boolean;
-  valueFormat?: (value: string) => string | React.ReactNode;
-  subTitle?: React.ReactNode;
-}
-
-export default class Pie extends React.Component<IPieProps, any> {}

+ 0 - 248
src/components/Charts/Pie/index.js

@@ -1,248 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
-import { DataView } from '@antv/data-set';
-import { Divider } from 'antd';
-import classNames from 'classnames';
-import ReactFitText from 'react-fittext';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import styles from './index.less';
-
-/* eslint react/no-danger:0 */
-class Pie extends Component {
-  state = {
-    height: 0,
-    legendData: [],
-    legendBlock: false,
-  };
-
-  componentDidUpdate(preProps) {
-    const { data } = this.props;
-    if (data !== preProps.data) {
-      // because of charts data create when rendered
-      // so there is a trick for get rendered time
-      this.getLegendData();
-    }
-  }
-
-  getG2Instance = chart => {
-    this.chart = chart;
-    requestAnimationFrame(() => {
-      this.getLegendData();
-    });
-  };
-
-  // for custom lengend view
-  getLegendData = () => {
-    if (!this.chart) return;
-    const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
-    if (!geom) return;
-    const items = geom.get('dataArray') || []; // 获取图形对应的
-
-    const legendData = items.map(item => {
-      /* eslint no-underscore-dangle:0 */
-      const origin = item[0]._origin;
-      origin.color = item[0].color;
-      origin.checked = true;
-      return origin;
-    });
-
-    this.setState({
-      legendData,
-    });
-  };
-
-  handleRoot = n => {
-    this.root = n;
-  };
-
-  handleLegendClick = (item, i) => {
-    const newItem = item;
-    newItem.checked = !newItem.checked;
-
-    const { legendData } = this.state;
-    legendData[i] = newItem;
-
-    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
-
-    if (this.chart) {
-      this.chart.filter('x', val => filteredLegendData.indexOf(val) > -1);
-    }
-
-    this.setState({
-      legendData,
-    });
-  };
-
-  // for window resize auto responsive legend
-  @Bind()
-  @Debounce(300)
-  resize() {
-    const { hasLegend } = this.props;
-    const { legendBlock } = this.state;
-    if (!hasLegend || !this.root) {
-      window.removeEventListener('resize', this.resize);
-      return;
-    }
-    if (this.root.parentNode.clientWidth <= 380) {
-      if (!legendBlock) {
-        this.setState({
-          legendBlock: true,
-        });
-      }
-    } else if (legendBlock) {
-      this.setState({
-        legendBlock: false,
-      });
-    }
-  }
-
-  render() {
-    const {
-      valueFormat,
-      subTitle,
-      total,
-      hasLegend = false,
-      className,
-      style,
-      height,
-      percent,
-      color,
-      inner = 0.75,
-      animate = true,
-      colors,
-      lineWidth = 1,
-    } = this.props;
-
-    const { legendData, height: stateHeight, legendBlock } = this.state;
-    const pieClassName = classNames(styles.pie, className, {
-      [styles.hasLegend]: !!hasLegend,
-      [styles.legendBlock]: legendBlock,
-    });
-
-    const {
-      data: propsData,
-      selected: propsSelected = true,
-      tooltip: propsTooltip = true,
-    } = this.props;
-
-    let data = propsData || [];
-    let selected = propsSelected;
-    let tooltip = propsTooltip;
-
-    const defaultColors = colors;
-    selected = selected || true;
-    tooltip = tooltip || true;
-    let formatColor;
-
-    const scale = {
-      x: {
-        type: 'cat',
-        range: [0, 1],
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    if (percent || percent === 0) {
-      selected = false;
-      tooltip = false;
-      formatColor = value => {
-        if (value === '占比') {
-          return color || 'rgba(24, 144, 255, 0.85)';
-        }
-        return '#F0F2F5';
-      };
-
-      data = [
-        {
-          x: '占比',
-          y: parseFloat(percent),
-        },
-        {
-          x: '反比',
-          y: 100 - parseFloat(percent),
-        },
-      ];
-    }
-
-    const tooltipFormat = [
-      'x*percent',
-      (x, p) => ({
-        name: x,
-        value: `${(p * 100).toFixed(2)}%`,
-      }),
-    ];
-
-    const padding = [12, 0, 12, 0];
-
-    const dv = new DataView();
-    dv.source(data).transform({
-      type: 'percent',
-      field: 'y',
-      dimension: 'x',
-      as: 'percent',
-    });
-
-    return (
-      <div ref={this.handleRoot} className={pieClassName} style={style}>
-        <ReactFitText maxFontSize={25}>
-          <div className={styles.chart}>
-            <Chart
-              scale={scale}
-              height={height || stateHeight}
-              data={dv}
-              padding={padding}
-              animate={animate}
-              onGetG2Instance={this.getG2Instance}
-            >
-              {!!tooltip && <Tooltip showTitle={false} />}
-              <Coord type="theta" innerRadius={inner} />
-              <Geom
-                style={{ lineWidth, stroke: '#fff' }}
-                tooltip={tooltip && tooltipFormat}
-                type="intervalStack"
-                position="percent"
-                color={['x', percent || percent === 0 ? formatColor : defaultColors]}
-                selected={selected}
-              />
-            </Chart>
-
-            {(subTitle || total) && (
-              <div className={styles.total}>
-                {subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
-                {/* eslint-disable-next-line */}
-                {total && (
-                  <div className="pie-stat">{typeof total === 'function' ? total() : total}</div>
-                )}
-              </div>
-            )}
-          </div>
-        </ReactFitText>
-        {hasLegend && (
-          <ul className={styles.legend}>
-            {legendData.map((item, i) => (
-              <li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
-                <span
-                  className={styles.dot}
-                  style={{
-                    backgroundColor: !item.checked ? '#aaa' : item.color,
-                  }}
-                />
-                <span className={styles.legendTitle}>{item.x}</span>
-                <Divider type="vertical" />
-                <span className={styles.percent}>
-                  {`${(Number.isNaN(item.percent) ? 0 : item.percent * 100).toFixed(2)}%`}
-                </span>
-                <span className={styles.value}>{valueFormat ? valueFormat(item.y) : item.y}</span>
-              </li>
-            ))}
-          </ul>
-        )}
-      </div>
-    );
-  }
-}
-
-export default Pie;

+ 0 - 94
src/components/Charts/Pie/index.less

@@ -1,94 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.pie {
-  position: relative;
-  .chart {
-    position: relative;
-  }
-  &.hasLegend .chart {
-    width: ~'calc(100% - 240px)';
-  }
-  .legend {
-    position: absolute;
-    top: 50%;
-    right: 0;
-    min-width: 200px;
-    margin: 0 20px;
-    padding: 0;
-    list-style: none;
-    transform: translateY(-50%);
-    li {
-      height: 22px;
-      margin-bottom: 16px;
-      line-height: 22px;
-      cursor: pointer;
-      &:last-child {
-        margin-bottom: 0;
-      }
-    }
-  }
-  .dot {
-    position: relative;
-    top: -1px;
-    display: inline-block;
-    width: 8px;
-    height: 8px;
-    margin-right: 8px;
-    border-radius: 8px;
-  }
-  .line {
-    display: inline-block;
-    width: 1px;
-    height: 16px;
-    margin-right: 8px;
-    background-color: @border-color-split;
-  }
-  .legendTitle {
-    color: @text-color;
-  }
-  .percent {
-    color: @text-color-secondary;
-  }
-  .value {
-    position: absolute;
-    right: 0;
-  }
-  .title {
-    margin-bottom: 8px;
-  }
-  .total {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    max-height: 62px;
-    text-align: center;
-    transform: translate(-50%, -50%);
-    & > h4 {
-      height: 22px;
-      margin-bottom: 8px;
-      color: @text-color-secondary;
-      font-weight: normal;
-      font-size: 14px;
-      line-height: 22px;
-    }
-    & > p {
-      display: block;
-      height: 32px;
-      color: @heading-color;
-      font-size: 1.2em;
-      line-height: 32px;
-      white-space: nowrap;
-    }
-  }
-}
-
-.legendBlock {
-  &.hasLegend .chart {
-    width: 100%;
-    margin: 0 0 32px 0;
-  }
-  .legend {
-    position: relative;
-    transform: none;
-  }
-}

+ 0 - 15
src/components/Charts/Radar/index.d.ts

@@ -1,15 +0,0 @@
-import React from 'react';
-export interface IRadarProps {
-  title?: React.ReactNode;
-  height: number;
-  padding?: [number, number, number, number];
-  hasLegend?: boolean;
-  data: Array<{
-    name: string;
-    label: string;
-    value: string;
-  }>;
-  style?: React.CSSProperties;
-}
-
-export default class Radar extends React.Component<IRadarProps, any> {}

+ 0 - 184
src/components/Charts/Radar/index.js

@@ -1,184 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Tooltip, Geom, Coord, Axis } from 'bizcharts';
-import { Row, Col } from 'antd';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-/* eslint react/no-danger:0 */
-@autoHeight()
-class Radar extends Component {
-  state = {
-    legendData: [],
-  };
-
-  componentDidMount() {
-    this.getLegendData();
-  }
-
-  componentDidUpdate(preProps) {
-    const { data } = this.props;
-    if (data !== preProps.data) {
-      this.getLegendData();
-    }
-  }
-
-  getG2Instance = chart => {
-    this.chart = chart;
-  };
-
-  // for custom lengend view
-  getLegendData = () => {
-    if (!this.chart) return;
-    const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
-    if (!geom) return;
-    const items = geom.get('dataArray') || []; // 获取图形对应的
-
-    const legendData = items.map(item => {
-      // eslint-disable-next-line
-      const origins = item.map(t => t._origin);
-      const result = {
-        name: origins[0].name,
-        color: item[0].color,
-        checked: true,
-        value: origins.reduce((p, n) => p + n.value, 0),
-      };
-
-      return result;
-    });
-
-    this.setState({
-      legendData,
-    });
-  };
-
-  handleRef = n => {
-    this.node = n;
-  };
-
-  handleLegendClick = (item, i) => {
-    const newItem = item;
-    newItem.checked = !newItem.checked;
-
-    const { legendData } = this.state;
-    legendData[i] = newItem;
-
-    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.name);
-
-    if (this.chart) {
-      this.chart.filter('name', val => filteredLegendData.indexOf(val) > -1);
-      this.chart.repaint();
-    }
-
-    this.setState({
-      legendData,
-    });
-  };
-
-  render() {
-    const defaultColors = [
-      '#1890FF',
-      '#FACC14',
-      '#2FC25B',
-      '#8543E0',
-      '#F04864',
-      '#13C2C2',
-      '#fa8c16',
-      '#a0d911',
-    ];
-
-    const {
-      data = [],
-      height = 0,
-      title,
-      hasLegend = false,
-      forceFit = true,
-      tickCount = 5,
-      padding = [35, 30, 16, 30],
-      animate = true,
-      colors = defaultColors,
-    } = this.props;
-
-    const { legendData } = this.state;
-
-    const scale = {
-      value: {
-        min: 0,
-        tickCount,
-      },
-    };
-
-    const chartHeight = height - (hasLegend ? 80 : 22);
-
-    return (
-      <div className={styles.radar} style={{ height }}>
-        {title && <h4>{title}</h4>}
-        <Chart
-          scale={scale}
-          height={chartHeight}
-          forceFit={forceFit}
-          data={data}
-          padding={padding}
-          animate={animate}
-          onGetG2Instance={this.getG2Instance}
-        >
-          <Tooltip />
-          <Coord type="polar" />
-          <Axis
-            name="label"
-            line={null}
-            tickLine={null}
-            grid={{
-              lineStyle: {
-                lineDash: null,
-              },
-              hideFirstLine: false,
-            }}
-          />
-          <Axis
-            name="value"
-            grid={{
-              type: 'polygon',
-              lineStyle: {
-                lineDash: null,
-              },
-            }}
-          />
-          <Geom type="line" position="label*value" color={['name', colors]} size={1} />
-          <Geom
-            type="point"
-            position="label*value"
-            color={['name', colors]}
-            shape="circle"
-            size={3}
-          />
-        </Chart>
-        {hasLegend && (
-          <Row className={styles.legend}>
-            {legendData.map((item, i) => (
-              <Col
-                span={24 / legendData.length}
-                key={item.name}
-                onClick={() => this.handleLegendClick(item, i)}
-              >
-                <div className={styles.legendItem}>
-                  <p>
-                    <span
-                      className={styles.dot}
-                      style={{
-                        backgroundColor: !item.checked ? '#aaa' : item.color,
-                      }}
-                    />
-                    <span>{item.name}</span>
-                  </p>
-                  <h6>{item.value}</h6>
-                </div>
-              </Col>
-            ))}
-          </Row>
-        )}
-      </div>
-    );
-  }
-}
-
-export default Radar;

+ 0 - 46
src/components/Charts/Radar/index.less

@@ -1,46 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.radar {
-  .legend {
-    margin-top: 16px;
-    .legendItem {
-      position: relative;
-      color: @text-color-secondary;
-      line-height: 22px;
-      text-align: center;
-      cursor: pointer;
-      p {
-        margin: 0;
-      }
-      h6 {
-        margin-top: 4px;
-        margin-bottom: 0;
-        padding-left: 16px;
-        color: @heading-color;
-        font-size: 24px;
-        line-height: 32px;
-      }
-      &::after {
-        position: absolute;
-        top: 8px;
-        right: 0;
-        width: 1px;
-        height: 40px;
-        background-color: @border-color-split;
-        content: '';
-      }
-    }
-    > :last-child .legendItem::after {
-      display: none;
-    }
-    .dot {
-      position: relative;
-      top: -1px;
-      display: inline-block;
-      width: 6px;
-      height: 6px;
-      margin-right: 6px;
-      border-radius: 6px;
-    }
-  }
-}

+ 0 - 11
src/components/Charts/TagCloud/index.d.ts

@@ -1,11 +0,0 @@
-import React from 'react';
-export interface ITagCloudProps {
-  data: Array<{
-    name: string;
-    value: number;
-  }>;
-  height: number;
-  style?: React.CSSProperties;
-}
-
-export default class TagCloud extends React.Component<ITagCloudProps, any> {}

+ 0 - 167
src/components/Charts/TagCloud/index.js

@@ -1,167 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
-import DataSet from '@antv/data-set';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import classNames from 'classnames';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-/* eslint no-underscore-dangle: 0 */
-/* eslint no-param-reassign: 0 */
-
-const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
-
-@autoHeight()
-class TagCloud extends Component {
-  state = {
-    dv: null,
-  };
-
-  componentDidMount() {
-    this.initTagCloud();
-    this.renderChart();
-  }
-
-  componentDidUpdate(preProps) {
-    const { data } = this.props;
-    if (JSON.stringify(preProps.data) !== JSON.stringify(data)) {
-      this.renderChart(this.props);
-    }
-  }
-
-  componentWillUnmount() {
-    this.isUnmount = true;
-  }
-
-  saveRootRef = node => {
-    this.root = node;
-  };
-
-  initTagCloud = () => {
-    function getTextAttrs(cfg) {
-      return Object.assign({}, cfg.style, {
-        fillOpacity: cfg.opacity,
-        fontSize: cfg.origin._origin.size,
-        rotate: cfg.origin._origin.rotate,
-        text: cfg.origin._origin.text,
-        textAlign: 'center',
-        fontFamily: cfg.origin._origin.font,
-        fill: cfg.color,
-        textBaseline: 'Alphabetic',
-      });
-    }
-
-    // 给point注册一个词云的shape
-    Shape.registerShape('point', 'cloud', {
-      drawShape(cfg, container) {
-        const attrs = getTextAttrs(cfg);
-        return container.addShape('text', {
-          attrs: Object.assign(attrs, {
-            x: cfg.x,
-            y: cfg.y,
-          }),
-        });
-      },
-    });
-  };
-
-  @Bind()
-  @Debounce(500)
-  renderChart(nextProps) {
-    // const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
-    const { data, height } = nextProps || this.props;
-
-    if (data.length < 1 || !this.root) {
-      return;
-    }
-
-    const h = height;
-    const w = this.root.offsetWidth;
-
-    const onload = () => {
-      const dv = new DataSet.View().source(data);
-      const range = dv.range('value');
-      const [min, max] = range;
-      dv.transform({
-        type: 'tag-cloud',
-        fields: ['name', 'value'],
-        imageMask: this.imageMask,
-        font: 'Verdana',
-        size: [w, h], // 宽高设置最好根据 imageMask 做调整
-        padding: 0,
-        timeInterval: 5000, // max execute time
-        rotate() {
-          return 0;
-        },
-        fontSize(d) {
-          // eslint-disable-next-line
-          return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5;
-        },
-      });
-
-      if (this.isUnmount) {
-        return;
-      }
-
-      this.setState({
-        dv,
-        w,
-        h,
-      });
-    };
-
-    if (!this.imageMask) {
-      this.imageMask = new Image();
-      this.imageMask.crossOrigin = '';
-      this.imageMask.src = imgUrl;
-
-      this.imageMask.onload = onload;
-    } else {
-      onload();
-    }
-  }
-
-  render() {
-    const { className, height } = this.props;
-    const { dv, w, h } = this.state;
-
-    return (
-      <div
-        className={classNames(styles.tagCloud, className)}
-        style={{ width: '100%', height }}
-        ref={this.saveRootRef}
-      >
-        {dv && (
-          <Chart
-            width={w}
-            height={h}
-            data={dv}
-            padding={0}
-            scale={{
-              x: { nice: false },
-              y: { nice: false },
-            }}
-          >
-            <Tooltip showTitle={false} />
-            <Coord reflect="y" />
-            <Geom
-              type="point"
-              position="x*y"
-              color="text"
-              shape="cloud"
-              tooltip={[
-                'text*value',
-                function trans(text, value) {
-                  return { name: text, value };
-                },
-              ]}
-            />
-          </Chart>
-        )}
-      </div>
-    );
-  }
-}
-
-export default TagCloud;

+ 0 - 6
src/components/Charts/TagCloud/index.less

@@ -1,6 +0,0 @@
-.tagCloud {
-  overflow: hidden;
-  canvas {
-    transform-origin: 0 0;
-  }
-}

+ 0 - 14
src/components/Charts/TimelineChart/index.d.ts

@@ -1,14 +0,0 @@
-import React from 'react';
-export interface ITimelineChartProps {
-  data: Array<{
-    x: number;
-    y1: number;
-    y2?: number;
-  }>;
-  titleMap: { y1: string; y2?: string };
-  padding?: [number, number, number, number];
-  height?: number;
-  style?: React.CSSProperties;
-}
-
-export default class TimelineChart extends React.Component<ITimelineChartProps, any> {}

+ 0 - 120
src/components/Charts/TimelineChart/index.js

@@ -1,120 +0,0 @@
-import React from 'react';
-import { Chart, Tooltip, Geom, Legend, Axis } from 'bizcharts';
-import DataSet from '@antv/data-set';
-import Slider from 'bizcharts-plugin-slider';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-@autoHeight()
-class TimelineChart extends React.Component {
-  render() {
-    const {
-      title,
-      height = 400,
-      padding = [60, 20, 40, 40],
-      titleMap = {
-        y1: 'y1',
-        y2: 'y2',
-      },
-      borderWidth = 2,
-      data: sourceData,
-    } = this.props;
-
-    const data = Array.isArray(sourceData) ? sourceData : [{ x: 0, y1: 0, y2: 0 }];
-
-    data.sort((a, b) => a.x - b.x);
-
-    let max;
-    if (data[0] && data[0].y1 && data[0].y2) {
-      max = Math.max(
-        [...data].sort((a, b) => b.y1 - a.y1)[0].y1,
-        [...data].sort((a, b) => b.y2 - a.y2)[0].y2
-      );
-    }
-
-    const ds = new DataSet({
-      state: {
-        start: data[0].x,
-        end: data[data.length - 1].x,
-      },
-    });
-
-    const dv = ds.createView();
-    dv.source(data)
-      .transform({
-        type: 'filter',
-        callback: obj => {
-          const date = obj.x;
-          return date <= ds.state.end && date >= ds.state.start;
-        },
-      })
-      .transform({
-        type: 'map',
-        callback(row) {
-          const newRow = { ...row };
-          newRow[titleMap.y1] = row.y1;
-          newRow[titleMap.y2] = row.y2;
-          return newRow;
-        },
-      })
-      .transform({
-        type: 'fold',
-        fields: [titleMap.y1, titleMap.y2], // 展开字段集
-        key: 'key', // key字段
-        value: 'value', // value字段
-      });
-
-    const timeScale = {
-      type: 'time',
-      tickInterval: 60 * 60 * 1000,
-      mask: 'HH:mm',
-      range: [0, 1],
-    };
-
-    const cols = {
-      x: timeScale,
-      value: {
-        max,
-        min: 0,
-      },
-    };
-
-    const SliderGen = () => (
-      <Slider
-        padding={[0, padding[1] + 20, 0, padding[3]]}
-        width="auto"
-        height={26}
-        xAxis="x"
-        yAxis="y1"
-        scales={{ x: timeScale }}
-        data={data}
-        start={ds.state.start}
-        end={ds.state.end}
-        backgroundChart={{ type: 'line' }}
-        onChange={({ startValue, endValue }) => {
-          ds.setState('start', startValue);
-          ds.setState('end', endValue);
-        }}
-      />
-    );
-
-    return (
-      <div className={styles.timelineChart} style={{ height: height + 30 }}>
-        <div>
-          {title && <h4>{title}</h4>}
-          <Chart height={height} padding={padding} data={dv} scale={cols} forceFit>
-            <Axis name="x" />
-            <Tooltip />
-            <Legend name="key" position="top" />
-            <Geom type="line" position="x*value" size={borderWidth} color="key" />
-          </Chart>
-          <div style={{ marginRight: -20 }}>
-            <SliderGen />
-          </div>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default TimelineChart;

+ 0 - 3
src/components/Charts/TimelineChart/index.less

@@ -1,3 +0,0 @@
-.timelineChart {
-  background: #fff;
-}

+ 0 - 10
src/components/Charts/WaterWave/index.d.ts

@@ -1,10 +0,0 @@
-import React from 'react';
-export interface IWaterWaveProps {
-  title: React.ReactNode;
-  color?: string;
-  height: number;
-  percent: number;
-  style?: React.CSSProperties;
-}
-
-export default class WaterWave extends React.Component<IWaterWaveProps, any> {}

+ 0 - 213
src/components/Charts/WaterWave/index.js

@@ -1,213 +0,0 @@
-import React, { PureComponent } from 'react';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-/* eslint no-return-assign: 0 */
-/* eslint no-mixed-operators: 0 */
-// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
-
-@autoHeight()
-class WaterWave extends PureComponent {
-  state = {
-    radio: 1,
-  };
-
-  componentDidMount() {
-    this.renderChart();
-    this.resize();
-    window.addEventListener(
-      'resize',
-      () => {
-        requestAnimationFrame(() => this.resize());
-      },
-      { passive: true }
-    );
-  }
-
-  componentDidUpdate(props) {
-    const { percent } = this.props;
-    if (props.percent !== percent) {
-      // 不加这个会造成绘制缓慢
-      this.renderChart('update');
-    }
-  }
-
-  componentWillUnmount() {
-    cancelAnimationFrame(this.timer);
-    if (this.node) {
-      this.node.innerHTML = '';
-    }
-    window.removeEventListener('resize', this.resize);
-  }
-
-  resize = () => {
-    if (this.root) {
-      const { height } = this.props;
-      const { offsetWidth } = this.root.parentNode;
-      this.setState({
-        radio: offsetWidth < height ? offsetWidth / height : 1,
-      });
-    }
-  };
-
-  renderChart(type) {
-    const { percent, color = '#1890FF' } = this.props;
-    const data = percent / 100;
-    const self = this;
-    cancelAnimationFrame(this.timer);
-
-    if (!this.node || (data !== 0 && !data)) {
-      return;
-    }
-
-    const canvas = this.node;
-    const ctx = canvas.getContext('2d');
-    const canvasWidth = canvas.width;
-    const canvasHeight = canvas.height;
-    const radius = canvasWidth / 2;
-    const lineWidth = 2;
-    const cR = radius - lineWidth;
-
-    ctx.beginPath();
-    ctx.lineWidth = lineWidth * 2;
-
-    const axisLength = canvasWidth - lineWidth;
-    const unit = axisLength / 8;
-    const range = 0.2; // 振幅
-    let currRange = range;
-    const xOffset = lineWidth;
-    let sp = 0; // 周期偏移量
-    let currData = 0;
-    const waveupsp = 0.005; // 水波上涨速度
-
-    let arcStack = [];
-    const bR = radius - lineWidth;
-    const circleOffset = -(Math.PI / 2);
-    let circleLock = true;
-
-    for (let i = circleOffset; i < circleOffset + 2 * Math.PI; i += 1 / (8 * Math.PI)) {
-      arcStack.push([radius + bR * Math.cos(i), radius + bR * Math.sin(i)]);
-    }
-
-    const cStartPoint = arcStack.shift();
-    ctx.strokeStyle = color;
-    ctx.moveTo(cStartPoint[0], cStartPoint[1]);
-
-    function drawSin() {
-      ctx.beginPath();
-      ctx.save();
-
-      const sinStack = [];
-      for (let i = xOffset; i <= xOffset + axisLength; i += 20 / axisLength) {
-        const x = sp + (xOffset + i) / unit;
-        const y = Math.sin(x) * currRange;
-        const dx = i;
-        const dy = 2 * cR * (1 - currData) + (radius - cR) - unit * y;
-
-        ctx.lineTo(dx, dy);
-        sinStack.push([dx, dy]);
-      }
-
-      const startPoint = sinStack.shift();
-
-      ctx.lineTo(xOffset + axisLength, canvasHeight);
-      ctx.lineTo(xOffset, canvasHeight);
-      ctx.lineTo(startPoint[0], startPoint[1]);
-
-      const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight);
-      gradient.addColorStop(0, '#ffffff');
-      gradient.addColorStop(1, color);
-      ctx.fillStyle = gradient;
-      ctx.fill();
-      ctx.restore();
-    }
-
-    function render() {
-      ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-      if (circleLock && type !== 'update') {
-        if (arcStack.length) {
-          const temp = arcStack.shift();
-          ctx.lineTo(temp[0], temp[1]);
-          ctx.stroke();
-        } else {
-          circleLock = false;
-          ctx.lineTo(cStartPoint[0], cStartPoint[1]);
-          ctx.stroke();
-          arcStack = null;
-
-          ctx.globalCompositeOperation = 'destination-over';
-          ctx.beginPath();
-          ctx.lineWidth = lineWidth;
-          ctx.arc(radius, radius, bR, 0, 2 * Math.PI, 1);
-
-          ctx.beginPath();
-          ctx.save();
-          ctx.arc(radius, radius, radius - 3 * lineWidth, 0, 2 * Math.PI, 1);
-
-          ctx.restore();
-          ctx.clip();
-          ctx.fillStyle = color;
-        }
-      } else {
-        if (data >= 0.85) {
-          if (currRange > range / 4) {
-            const t = range * 0.01;
-            currRange -= t;
-          }
-        } else if (data <= 0.1) {
-          if (currRange < range * 1.5) {
-            const t = range * 0.01;
-            currRange += t;
-          }
-        } else {
-          if (currRange <= range) {
-            const t = range * 0.01;
-            currRange += t;
-          }
-          if (currRange >= range) {
-            const t = range * 0.01;
-            currRange -= t;
-          }
-        }
-        if (data - currData > 0) {
-          currData += waveupsp;
-        }
-        if (data - currData < 0) {
-          currData -= waveupsp;
-        }
-
-        sp += 0.07;
-        drawSin();
-      }
-      self.timer = requestAnimationFrame(render);
-    }
-    render();
-  }
-
-  render() {
-    const { radio } = this.state;
-    const { percent, title, height } = this.props;
-    return (
-      <div
-        className={styles.waterWave}
-        ref={n => (this.root = n)}
-        style={{ transform: `scale(${radio})` }}
-      >
-        <div style={{ width: height, height, overflow: 'hidden' }}>
-          <canvas
-            className={styles.waterWaveCanvasWrapper}
-            ref={n => (this.node = n)}
-            width={height * 2}
-            height={height * 2}
-          />
-        </div>
-        <div className={styles.text} style={{ width: height }}>
-          {title && <span>{title}</span>}
-          <h4>{percent}%</h4>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default WaterWave;

+ 0 - 28
src/components/Charts/WaterWave/index.less

@@ -1,28 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.waterWave {
-  position: relative;
-  display: inline-block;
-  transform-origin: left;
-  .text {
-    position: absolute;
-    top: 32px;
-    left: 0;
-    width: 100%;
-    text-align: center;
-    span {
-      color: @text-color-secondary;
-      font-size: 14px;
-      line-height: 22px;
-    }
-    h4 {
-      color: @heading-color;
-      font-size: 24px;
-      line-height: 32px;
-    }
-  }
-  .waterWaveCanvasWrapper {
-    transform: scale(0.5);
-    transform-origin: 0 0;
-  }
-}

+ 0 - 62
src/components/Charts/autoHeight.js

@@ -1,62 +0,0 @@
-/* eslint eqeqeq: 0 */
-import React from 'react';
-
-function computeHeight(node) {
-  const totalHeight = parseInt(getComputedStyle(node).height, 10);
-  const padding =
-    parseInt(getComputedStyle(node).paddingTop, 10) +
-    parseInt(getComputedStyle(node).paddingBottom, 10);
-  return totalHeight - padding;
-}
-
-function getAutoHeight(n) {
-  if (!n) {
-    return 0;
-  }
-
-  let node = n;
-
-  let height = computeHeight(node);
-
-  while (!height) {
-    node = node.parentNode;
-    if (node) {
-      height = computeHeight(node);
-    } else {
-      break;
-    }
-  }
-
-  return height;
-}
-
-const autoHeight = () => WrappedComponent =>
-  class extends React.Component {
-    state = {
-      computedHeight: 0,
-    };
-
-    componentDidMount() {
-      const { height } = this.props;
-      if (!height) {
-        const h = getAutoHeight(this.root);
-        // eslint-disable-next-line
-        this.setState({ computedHeight: h });
-      }
-    }
-
-    handleRoot = node => {
-      this.root = node;
-    };
-
-    render() {
-      const { height } = this.props;
-      const { computedHeight } = this.state;
-      const h = height || computedHeight;
-      return (
-        <div ref={this.handleRoot}>{h > 0 && <WrappedComponent {...this.props} height={h} />}</div>
-      );
-    }
-  };
-
-export default autoHeight;

+ 0 - 3
src/components/Charts/bizcharts.d.ts

@@ -1,3 +0,0 @@
-import * as BizChart from 'bizcharts';
-
-export = BizChart;

+ 0 - 3
src/components/Charts/bizcharts.js

@@ -1,3 +0,0 @@
-import * as BizChart from 'bizcharts';
-
-export default BizChart;

+ 0 - 0
src/components/Charts/demo/bar.md


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů