Prechádzať zdrojové kódy

support Access-Control-Allow-Headers (#4576)

* support Access-Control-Allow-Headers

* add magic code

* add magic code

* add magic!!!! code

* try auto publish

* new plugin

* update script

* use fetch-blocks package

* add env

* add fetch-blocks package

* fix ci error

* fix lint error

* delete extra comments

* use https://ant-design-pro.netlify.com
陈帅 6 rokov pred
rodič
commit
b9b885953c

+ 2 - 0
.gitignore

@@ -36,3 +36,5 @@ functions/*
 screenshot
 .firebase
 .eslintcache
+
+build

+ 1 - 0
CNAME

@@ -0,0 +1 @@
+test.preview.pro.ant.design

+ 6 - 0
config/config.ts

@@ -67,6 +67,12 @@ if (isAntDesignProPreview) {
       code: 'UA-72788897-6',
     },
   ]);
+  plugins.push([
+    'umi-plugin-pro',
+    {
+      serverUrl: 'https://ant-design-pro.netlify.com',
+    },
+  ]);
 }
 
 export default {

+ 4 - 23
config/plugin.config.ts

@@ -25,21 +25,11 @@ function getModulePackageName(module: { context: string }) {
 }
 
 export default (config: any) => {
-  // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
+  // preview.pro.ant.design only do not use in your production;
   if (
     process.env.ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ||
     process.env.NODE_ENV !== 'production'
   ) {
-    // 将所有 less 合并为一个供 themePlugin使用
-    // const outFile = path.join(__dirname, '../.temp/ant-design-pro.less');
-    // const stylesDir = path.join(__dirname, '../src/');
-
-    // config.plugin('merge-less').use(MergeLessPlugin, [
-    //   {
-    //     stylesDir,
-    //     outFile,
-    //   },
-    // ]);
     config.plugin('webpack-theme-color-replacer').use(ThemeColorReplacer, [
       {
         fileName: 'css/theme-colors.css',
@@ -59,21 +49,12 @@ export default (config: any) => {
         },
       },
     ]);
-    // config.plugin('ant-design-theme').use(AntDesignThemePlugin, [
-    //   {
-    //     antDir: path.join(__dirname, '../node_modules/antd'),
-    //     stylesDir,
-    //     varFile: path.join(__dirname, '../node_modules/antd/es/style/themes/default.less'),
-    //     mainLessFile: outFile, //     themeVariables: ['@primary-color'],
-    //     indexFileName: 'index.html',
-    //     generateOne: true,
-    //     lessUrl: 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js',
-    //   },
-    // ]);
   }
+
   // optimize chunks
   config.optimization
-    .runtimeChunk(false) // share the same chunks across different modules
+    // share the same chunks across different modules
+    .runtimeChunk(false)
     .splitChunks({
       chunks: 'async',
       name: 'vendors',

+ 15 - 0
lambda/api.js

@@ -6,6 +6,21 @@ const matchMock = require('./mock/matchMock');
 
 const app = express();
 
+app.all('*', (req, res, next) => {
+  res.header('Access-Control-Allow-Origin', '*');
+  res.header(
+    'Access-Control-Allow-Headers',
+    'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild',
+  );
+  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
+
+  if (req.method == 'OPTIONS') {
+    res.send(200);
+  } else {
+    next();
+  }
+});
+
 app.use(matchMock);
 
 exports.handler = serverLess(app);

+ 7 - 3
package.json

@@ -6,6 +6,7 @@
   "scripts": {
     "analyze": "cross-env ANALYZE=1 umi build",
     "build": "umi build",
+    "deploy": "cross-env ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION=site npm run site && npm run gh-pages",
     "docker-hub:build": "docker build  -f Dockerfile.hub -t  ant-design-pro ./",
     "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build",
     "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up",
@@ -13,10 +14,11 @@
     "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",
-    "fetch:blocks": "node ./scripts/fetch-blocks.js",
+    "fetch:blocks": "fetch-blocks",
     "format-imports": "import-sort --write '**/*.{js,jsx,ts,tsx}'",
     "functions:build": "netlify-lambda build ./lambda",
     "functions:run": "cross-env NODE_ENV=dev netlify-lambda serve ./lambda",
+    "gh-pages": "cp CNAME ./dist/ && gh-pages -d dist",
     "lint": "npm run lint:js && npm run lint:style && npm run lint:prettier",
     "lint-staged": "lint-staged",
     "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
@@ -25,7 +27,7 @@
     "lint:prettier": "check-prettier lint",
     "lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
     "prettier": "prettier -c --write **/*",
-    "site": "npm run fetch:blocks && npm run functions:build && umi build",
+    "site": "npm run fetch:blocks && npm run build && npm run functions:build",
     "start": "umi dev",
     "start:no-mock": "cross-env MOCK=none umi dev",
     "test": "umi test",
@@ -75,7 +77,6 @@
     "react-media-hook2": "^1.0.5",
     "redux": "^4.0.1",
     "umi": "^2.7.2",
-    "umi-plugin-ga": "^1.1.3",
     "umi-plugin-pro-block": "^1.3.2",
     "umi-plugin-react": "^1.8.2",
     "umi-request": "^1.0.7"
@@ -99,6 +100,7 @@
     "enzyme": "^3.9.0",
     "eslint": "^5.16.0",
     "express": "^4.17.1",
+    "fetch-blocks": "^1.0.0",
     "gh-pages": "^2.0.1",
     "husky": "^2.3.0",
     "import-sort-cli": "^6.0.0",
@@ -115,6 +117,8 @@
     "serverless-http": "^2.0.2",
     "slash2": "^2.0.0",
     "stylelint": "^10.1.0",
+    "umi-plugin-ga": "^1.1.3",
+    "umi-plugin-pro": "^1.0.2",
     "umi-types": "^0.3.8",
     "webpack-theme-color-replacer": "^1.1.5"
   },

+ 0 - 130
scripts/fetch-blocks.js

@@ -1,130 +0,0 @@
-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.path && item.component === '404') {
-        return 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 - 161
scripts/insertCode.js

@@ -1,161 +0,0 @@
-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 === 'VariableDeclaration') {
-        const classBody = item.declarations[0].init.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 - 77
scripts/repalceRouter.js

@@ -1,77 +0,0 @@
-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;

+ 0 - 236
scripts/router.config.js

@@ -1,236 +0,0 @@
-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',
-          },
-        ],
-      },
-    ],
-  },
-];

+ 1 - 1
src/components/SettingDrawer/themeColorClient.ts

@@ -12,7 +12,7 @@ export default {
     const colorPalettes = generate(color);
     return lightens.concat(colorPalettes);
   },
-  changeColor(newColor: string) {
+  changeColor(newColor?: string) {
     const lastColor = this.lastColor || this.primaryColor;
     const options = {
       // hash模式下用相对路径

+ 1 - 1
src/layouts/BasicLayout.tsx

@@ -20,7 +20,7 @@ import { formatMessage } from 'umi-plugin-react/locale';
 import { isAntDesignPro } from '@/utils/utils';
 import logo from '../assets/logo.svg';
 
-export interface BasicLayoutProps extends ProLayoutProps, ConnectProps {
+export interface BasicLayoutProps extends ProLayoutProps, Omit<ConnectProps, 'location'> {
   breadcrumbNameMap: {
     [path: string]: MenuDataItem;
   };

+ 1 - 1
src/layouts/UserLayout.tsx

@@ -26,7 +26,7 @@ const UserLayout: React.SFC<UserLayoutProps> = props => {
       pathname: '',
     },
   } = props;
-  const { breadcrumb } = getMenuData(routes, props);
+  const { breadcrumb } = getMenuData(routes);
 
   return (
     <DocumentTitle

+ 1 - 2
src/models/connect.d.ts

@@ -49,7 +49,6 @@ export interface Route extends MenuDataItem {
 /**
  * @type T: Params matched in dynamic routing
  */
-export interface ConnectProps<T extends { [key: string]: any } = {}>
-  extends Partial<RouterTypes<Route, T>> {
+export interface ConnectProps<T = {}> extends Partial<RouterTypes<Route, T>> {
   dispatch?: Dispatch;
 }

+ 3 - 1
src/models/login.ts

@@ -4,7 +4,9 @@ import { parse, stringify } from 'qs';
 import { EffectsCommandMap } from 'dva';
 import { routerRedux } from 'dva/router';
 
-export function getPageQuery(): string {
+export function getPageQuery(): {
+  [key: string]: string;
+} {
   return parse(window.location.href.split('?')[1]);
 }