From b9b885953ce5bb15447e3b7c32b765cb4288015c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=B8=85?= Date: Mon, 24 Jun 2019 15:39:58 +0800 Subject: [PATCH] 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 --- .gitignore | 2 + CNAME | 1 + config/config.ts | 6 + config/plugin.config.ts | 27 +- lambda/api.js | 15 ++ package.json | 10 +- scripts/fetch-blocks.js | 130 ---------- scripts/insertCode.js | 161 ------------ scripts/repalceRouter.js | 77 ------ scripts/router.config.js | 236 ------------------ .../SettingDrawer/themeColorClient.ts | 2 +- src/layouts/BasicLayout.tsx | 2 +- src/layouts/UserLayout.tsx | 2 +- src/models/connect.d.ts | 3 +- src/models/login.ts | 4 +- 15 files changed, 42 insertions(+), 636 deletions(-) create mode 100644 CNAME delete mode 100644 scripts/fetch-blocks.js delete mode 100644 scripts/insertCode.js delete mode 100644 scripts/repalceRouter.js delete mode 100644 scripts/router.config.js diff --git a/.gitignore b/.gitignore index 18b814ab..7fd9f581 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ functions/* screenshot .firebase .eslintcache + +build diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..09f9f3f3 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +test.preview.pro.ant.design \ No newline at end of file diff --git a/config/config.ts b/config/config.ts index 97a98c68..501635d8 100644 --- a/config/config.ts +++ b/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 { diff --git a/config/plugin.config.ts b/config/plugin.config.ts index 4b4ed895..d62068e6 100644 --- a/config/plugin.config.ts +++ b/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', diff --git a/lambda/api.js b/lambda/api.js index e0c147a6..105f0b04 100644 --- a/lambda/api.js +++ b/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); diff --git a/package.json b/package.json index a1e88b5a..d96aab83 100644 --- a/package.json +++ b/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" }, diff --git a/scripts/fetch-blocks.js b/scripts/fetch-blocks.js deleted file mode 100644 index 996ef78f..00000000 --- a/scripts/fetch-blocks.js +++ /dev/null @@ -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(); -}); diff --git a/scripts/insertCode.js b/scripts/insertCode.js deleted file mode 100644 index 298df951..00000000 --- a/scripts/insertCode.js +++ /dev/null @@ -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 = ` - - 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(` `).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(``).expression); - node.argument.children.splice(index, 0, parseCode(``).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`); -}; diff --git a/scripts/repalceRouter.js b/scripts/repalceRouter.js deleted file mode 100644 index 4bb3c4f4..00000000 --- a/scripts/repalceRouter.js +++ /dev/null @@ -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; diff --git a/scripts/router.config.js b/scripts/router.config.js deleted file mode 100644 index 38a90a1b..00000000 --- a/scripts/router.config.js +++ /dev/null @@ -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', - }, - ], - }, - ], - }, -]; diff --git a/src/components/SettingDrawer/themeColorClient.ts b/src/components/SettingDrawer/themeColorClient.ts index 8aa3b360..355a99ae 100644 --- a/src/components/SettingDrawer/themeColorClient.ts +++ b/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模式下用相对路径 diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index 2ac74fcc..00a36070 100644 --- a/src/layouts/BasicLayout.tsx +++ b/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 { breadcrumbNameMap: { [path: string]: MenuDataItem; }; diff --git a/src/layouts/UserLayout.tsx b/src/layouts/UserLayout.tsx index 6f916fbc..55cf9314 100644 --- a/src/layouts/UserLayout.tsx +++ b/src/layouts/UserLayout.tsx @@ -26,7 +26,7 @@ const UserLayout: React.SFC = props => { pathname: '', }, } = props; - const { breadcrumb } = getMenuData(routes, props); + const { breadcrumb } = getMenuData(routes); return ( - extends Partial> { +export interface ConnectProps extends Partial> { dispatch?: Dispatch; } diff --git a/src/models/login.ts b/src/models/login.ts index 4e250a79..3dd5a824 100644 --- a/src/models/login.ts +++ b/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]); } -- GitLab