Browse Source

features: use umi 3 (#6039)

* refactor: use umi 3

* fix: lint

* fix: d.ts

* fix: ignoreMomentLocale

* feat: add preset ui

* fix: preset

* fix: plugins

* fix: plugin

* fix: config

* fix: antd locale

* 🐛 bugfix: update types

* 🐛 bugfix:fix types error

* feat: add @umijs/plugin-blocks

* block support umi@3

* update deps

* update deps

* remove umi-plugin-antd-icon-config

* lint: fix ts error

* ignore: ignore build

* 🚀 Deploy: do not run yarn lint

* fix e2e test

* fix e2e test

* fix lgmt error

* 🚀 Deploy: add GA_KEY

Co-authored-by: chenshuai2144 <qixian.cs@outlook.com>
pull/6094/head
信鑫-King 6 years ago
committed by GitHub
parent
commit
06dd7fa621
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      .github/workflows/deploy.yml
  2. 1
      .prettierignore
  3. 153
      config/config.ts
  4. 115
      config/themePluginConfig.ts
  5. 12
      jest-puppeteer.config.js
  6. 1
      jest.config.js
  7. 18
      mock/listTableList.ts
  8. 34
      package.json
  9. 2
      src/components/Authorized/Authorized.tsx
  10. 9
      src/components/GlobalHeader/AvatarDropdown.tsx
  11. 6
      src/components/GlobalHeader/NoticeIconView.tsx
  12. 6
      src/components/GlobalHeader/RightContent.tsx
  13. 2
      src/components/SelectLang/index.tsx
  14. 14
      src/e2e/baseLayout.e2e.js
  15. 16
      src/e2e/getBrowser.js
  16. 21
      src/e2e/topMenu.e2e.js
  17. 2
      src/global.tsx
  18. 7
      src/layouts/BasicLayout.tsx
  19. 5
      src/layouts/SecurityLayout.tsx
  20. 9
      src/layouts/UserLayout.tsx
  21. 9
      src/models/connect.d.ts
  22. 3
      src/models/global.ts
  23. 8
      src/models/login.ts
  24. 2
      src/models/setting.ts
  25. 3
      src/models/user.ts
  26. 4
      src/pages/404.tsx
  27. 5
      src/pages/Authorized.tsx
  28. 3
      src/pages/user/login/components/Login/index.tsx
  29. 6
      src/pages/user/login/index.tsx
  30. 16
      src/utils/authority.test.ts
  31. 16
      tsconfig.json

5
.github/workflows/deploy.yml

@ -11,11 +11,12 @@ jobs:
uses: actions/checkout@master
- run: yarn
- run: yarn run lint
- run: yarn run tsc
# - run: yarn run tsc
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@master
env:
CI: true
GA_KEY: UA-72788897-6
PROGRESS: none
GIT_CONFIG_NAME: qixian.cs
GIT_CONFIG_EMAIL: qixian.cs@outlook.com
@ -24,4 +25,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }}
BRANCH: gh-pages
FOLDER: 'dist/'
BUILD_SCRIPT: yarn && npm uninstall husky && npm run site && git checkout . && git clean -df
BUILD_SCRIPT: yarn && npm uninstall husky && yarn add umi-plugin-antd-theme umi-plugin-pro && npm run site && git checkout . && git clean -df

1
.prettierignore

@ -19,3 +19,4 @@ LICENSE
yarn-error.log
.history
CNAME
/build

153
config/config.ts

@ -1,87 +1,32 @@
import { IConfig, IPlugin } from 'umi-types';
import defaultSettings from './defaultSettings'; // https://umijs.org/config/
import slash from 'slash2';
import themePluginConfig from './themePluginConfig';
// https://umijs.org/config/
import { defineConfig, utils } from 'umi';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import webpackPlugin from './plugin.config';
const { pwa } = defaultSettings;
const { winPath } = utils;
// 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, REACT_APP_ENV } = process.env;
const isAntDesignProPreview = ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site';
const plugins: IPlugin[] = [
['umi-plugin-antd-icon-config', {}],
[
'umi-plugin-react',
{
antd: true,
dva: {
hmr: true,
},
locale: {
// 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',
webpackChunkName: true,
level: 3,
},
pwa: pwa
? {
workboxPluginMode: 'InjectManifest',
workboxOptions: {
importWorkboxFrom: 'local',
},
}
: false,
// default close dll, because issue https://github.com/ant-design/ant-design-pro/issues/4665
// dll features https://webpack.js.org/plugins/dll-plugin/
// dll: {
// include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'],
// exclude: ['@babel/runtime'],
// },
},
],
[
'umi-plugin-pro-block',
{
moveMock: false,
moveService: false,
modifyRequest: true,
autoAddMenu: true,
},
],
];
const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, REACT_APP_ENV, GA_KEY } = process.env;
if (isAntDesignProPreview) {
// 针对 preview.pro.ant.design 的 GA 统计代码
plugins.push([
'umi-plugin-ga',
{
code: 'UA-72788897-6',
},
]);
plugins.push([
'umi-plugin-pro',
{
serverUrl: 'https://proapi.azurewebsites.net',
},
]);
plugins.push(['umi-plugin-antd-theme', themePluginConfig]);
}
export default {
plugins,
export default defineConfig({
hash: true,
antd: {},
analytics: GA_KEY ? { ga: GA_KEY } : false,
dva: {
hmr: true,
},
locale: {
// default zh-CN
default: 'zh-CN',
// default true, when it is true, will use `navigator.language` overwrite default
antd: true,
baseNavigator: true,
},
dynamicImport: {
loading: '@/components/PageLoading/index',
},
targets: {
ie: 11,
},
@ -164,36 +109,36 @@ export default {
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION || '', // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
},
ignoreMomentLocale: true,
lessLoaderOptions: {
lessLoader: {
javascriptEnabled: true,
},
disableRedirectHoist: true,
cssLoaderOptions: {
modules: true,
getLocalIdent: (
context: {
resourcePath: string;
},
_: string,
localName: string,
) => {
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
context.resourcePath.includes('global.less')
) {
cssLoader: {
modules: {
getLocalIdent: (
context: {
resourcePath: string;
},
_: string,
localName: string,
) => {
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
context.resourcePath.includes('global.less')
) {
return localName;
}
const match = context.resourcePath.match(/src(.*)/);
if (match && match[1]) {
const antdProPath = match[1].replace('.less', '');
const arr = winPath(antdProPath)
.split('/')
.map((a: string) => a.replace(/([A-Z])/g, '-$1'))
.map((a: string) => a.toLowerCase());
return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
}
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: string) => a.replace(/([A-Z])/g, '-$1'))
.map((a: string) => a.toLowerCase());
return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
}
return localName;
},
},
},
manifest: {
@ -201,4 +146,4 @@ export default {
},
proxy: proxy[REACT_APP_ENV || 'dev'],
chainWebpack: webpackPlugin,
} as IConfig;
});

115
config/themePluginConfig.ts

@ -1,115 +0,0 @@
export default {
theme: [
{
key: 'dark',
fileName: 'dark.css',
theme: 'dark',
},
{
key: 'dust',
fileName: 'dust.css',
modifyVars: {
'@primary-color': '#F5222D',
},
},
{
key: 'volcano',
fileName: 'volcano.css',
modifyVars: {
'@primary-color': '#FA541C',
},
},
{
key: 'sunset',
fileName: 'sunset.css',
modifyVars: {
'@primary-color': '#FAAD14',
},
},
{
key: 'cyan',
fileName: 'cyan.css',
modifyVars: {
'@primary-color': '#13C2C2',
},
},
{
key: 'green',
fileName: 'green.css',
modifyVars: {
'@primary-color': '#52C41A',
},
},
{
key: 'geekblue',
fileName: 'geekblue.css',
modifyVars: {
'@primary-color': '#2F54EB',
},
},
{
key: 'purple',
fileName: 'purple.css',
modifyVars: {
'@primary-color': '#722ED1',
},
},
{
key: 'dust',
theme: 'dark',
fileName: 'dark-dust.css',
modifyVars: {
'@primary-color': '#F5222D',
},
},
{
key: 'volcano',
theme: 'dark',
fileName: 'dark-volcano.css',
modifyVars: {
'@primary-color': '#FA541C',
},
},
{
key: 'sunset',
theme: 'dark',
fileName: 'dark-sunset.css',
modifyVars: {
'@primary-color': '#FAAD14',
},
},
{
key: 'cyan',
theme: 'dark',
fileName: 'dark-cyan.css',
modifyVars: {
'@primary-color': '#13C2C2',
},
},
{
key: 'green',
theme: 'dark',
fileName: 'dark-green.css',
modifyVars: {
'@primary-color': '#52C41A',
},
},
{
key: 'geekblue',
theme: 'dark',
fileName: 'dark-geekblue.css',
modifyVars: {
'@primary-color': '#2F54EB',
},
},
{
key: 'purple',
theme: 'dark',
fileName: 'dark-purple.css',
modifyVars: {
'@primary-color': '#722ED1',
},
},
],
};

12
jest-puppeteer.config.js

@ -1,12 +0,0 @@
// ps https://github.com/GoogleChrome/puppeteer/issues/3120
module.exports = {
launch: {
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--no-first-run',
'--no-zygote',
'--no-sandbox',
],
},
};

1
jest.config.js

@ -1,6 +1,5 @@
module.exports = {
testURL: 'http://localhost:8000',
preset: 'jest-puppeteer',
extraSetupFiles: ['./tests/setupTests.js'],
globals: {
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false,

18
src/pages/ListTableList/_mock.ts → mock/listTableList.ts

@ -1,7 +1,7 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { Request, Response } from 'express';
import { parse } from 'url';
import { TableListItem, TableListParams } from './data.d';
import { TableListItem, TableListParams } from '@/pages/ListTableList/data';
// mock tableListDataSource
const genList = (current: number, pageSize: number) => {
@ -34,13 +34,12 @@ const genList = (current: number, pageSize: number) => {
let tableListDataSource = genList(1, 100);
function getRule(req: Request, res: Response, u: string) {
let url = u;
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
// eslint-disable-next-line prefer-destructuring
url = req.url;
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}
const { current = 1, pageSize = 10 } = req.query;
const params = (parse(url, true).query as unknown) as TableListParams;
const params = (parse(realUrl, true).query as unknown) as TableListParams;
let dataSource = [...tableListDataSource].slice((current - 1) * pageSize, current * pageSize);
if (params.sorter) {
@ -84,10 +83,9 @@ function getRule(req: Request, res: Response, u: string) {
}
function postRule(req: Request, res: Response, u: string, b: Request) {
let url = u;
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
// eslint-disable-next-line prefer-destructuring
url = req.url;
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}
const body = (b && b.body) || req.body;

34
package.json

@ -14,10 +14,10 @@
"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": "pro fetch-blocks && npm run prettier",
"fetch:blocks": "pro fetch-blocks --branch=umi@3 && npm run prettier",
"gh-pages": "cp CNAME ./dist/ && gh-pages -d dist",
"i18n-remove": "pro i18n-remove --locale=zh-CN --write",
"lint": "npm run lint:js && npm run lint:style && npm run lint:prettier",
"lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier",
"lint:prettier": "prettier --check \"**/*\" --end-of-line auto",
"lint-staged": "lint-staged",
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
@ -36,8 +36,7 @@
"test": "umi test",
"test:all": "node ./tests/run-tests.js",
"test:component": "umi test ./src/components",
"tsc": "tsc",
"ui": "umi ui"
"tsc": "tsc"
},
"husky": {
"hooks": {
@ -57,28 +56,20 @@
"not ie <= 10"
],
"dependencies": {
"@ant-design/icons": "^4.0.0-alpha.19",
"@ant-design/icons": "^4.0.0",
"@ant-design/pro-layout": "^5.0.0",
"@ant-design/pro-table": "^2.0.0",
"@antv/data-set": "^0.11.1",
"antd": "^4.0.2",
"antd": "^4.0.0",
"classnames": "^2.2.6",
"dva": "^2.6.0-beta.16",
"lodash": "^4.17.11",
"moment": "^2.24.0",
"omit.js": "^1.0.2",
"path-to-regexp": "2.4.0",
"qs": "^6.9.0",
"react": "^16.8.6",
"react-copy-to-clipboard": "^5.0.1",
"react-dom": "^16.8.6",
"react-helmet": "^5.2.1",
"redux": "^4.0.1",
"umi": "^2.13.0",
"umi-plugin-antd-icon-config": "^1.0.2",
"umi-plugin-antd-theme": "1.2.0-0",
"umi-plugin-pro-block": "^1.3.2",
"umi-plugin-react": "^1.14.10",
"umi": "^3.0.0",
"umi-request": "^1.0.8",
"use-merge-value": "^1.0.1"
},
@ -94,6 +85,10 @@
"@types/react-dom": "^16.8.4",
"@types/react-helmet": "^5.0.13",
"@umijs/fabric": "^2.0.2",
"@umijs/plugin-blocks": "^2.0.5",
"@umijs/preset-ant-design-pro": "^1.0.1",
"@umijs/preset-react": "^1.3.0",
"@umijs/preset-ui": "^2.0.9",
"chalk": "^3.0.0",
"cross-env": "^7.0.0",
"cross-port-killer": "^1.1.1",
@ -101,19 +96,12 @@
"express": "^4.17.1",
"gh-pages": "^2.0.1",
"husky": "^4.0.7",
"jest-puppeteer": "^4.2.0",
"jsdom-global": "^3.0.2",
"lint-staged": "^10.0.0",
"mockjs": "^1.0.1-beta3",
"node-fetch": "^2.6.0",
"prettier": "^1.19.1",
"pro-download": "1.0.1",
"serverless-http": "^2.0.2",
"stylelint": "^13.0.0",
"umi-plugin-antd-icon-config": "^1.0.2",
"umi-plugin-ga": "^1.1.3",
"umi-plugin-pro": "^1.0.3",
"umi-types": "^0.5.9"
"stylelint": "^13.0.0"
},
"optionalDependencies": {
"puppeteer": "^2.0.0"

2
src/components/Authorized/Authorized.tsx

@ -21,7 +21,7 @@ const Authorized: React.FunctionComponent<AuthorizedProps> = ({
authority,
noMatch = (
<Result
status={403}
status="403"
title="403"
subTitle="Sorry, you are not authorized to access this page."
/>

9
src/components/GlobalHeader/AvatarDropdown.tsx

@ -2,14 +2,13 @@ import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons
import { Avatar, Menu, Spin } from 'antd';
import { ClickParam } from 'antd/es/menu';
import React from 'react';
import { connect } from 'dva';
import { router } from 'umi';
import { ConnectProps, ConnectState } from '@/models/connect';
import { history, ConnectProps, connect } from 'umi';
import { ConnectState } from '@/models/connect';
import { CurrentUser } from '@/models/user';
import HeaderDropdown from '../HeaderDropdown';
import styles from './index.less';
export interface GlobalHeaderRightProps extends ConnectProps {
export interface GlobalHeaderRightProps extends Partial<ConnectProps> {
currentUser?: CurrentUser;
menu?: boolean;
}
@ -30,7 +29,7 @@ class AvatarDropdown extends React.Component<GlobalHeaderRightProps> {
return;
}
router.push(`/account/${key}`);
history.push(`/account/${key}`);
};
render(): React.ReactNode {

6
src/components/GlobalHeader/NoticeIconView.tsx

@ -1,15 +1,15 @@
import React, { Component } from 'react';
import { connect, ConnectProps } from 'umi';
import { Tag, message } from 'antd';
import { connect } from 'dva';
import groupBy from 'lodash/groupBy';
import moment from 'moment';
import { NoticeItem } from '@/models/global';
import { CurrentUser } from '@/models/user';
import { ConnectProps, ConnectState } from '@/models/connect';
import { ConnectState } from '@/models/connect';
import NoticeIcon from '../NoticeIcon';
import styles from './index.less';
export interface GlobalHeaderRightProps extends ConnectProps {
export interface GlobalHeaderRightProps extends Partial<ConnectProps> {
notices?: NoticeItem[];
currentUser?: CurrentUser;
fetchingNotices?: boolean;

6
src/components/GlobalHeader/RightContent.tsx

@ -1,15 +1,15 @@
import { Tooltip, Tag } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import React from 'react';
import { connect } from 'dva';
import { ConnectProps, ConnectState } from '@/models/connect';
import { connect, ConnectProps } from 'umi';
import { ConnectState } from '@/models/connect';
import Avatar from './AvatarDropdown';
import HeaderSearch from '../HeaderSearch';
import SelectLang from '../SelectLang';
import styles from './index.less';
export type SiderTheme = 'light' | 'dark';
export interface GlobalHeaderRightProps extends ConnectProps {
export interface GlobalHeaderRightProps extends Partial<ConnectProps> {
theme?: SiderTheme;
layout: 'sidemenu' | 'topmenu';
}

2
src/components/SelectLang/index.tsx

@ -1,6 +1,6 @@
import { GlobalOutlined } from '@ant-design/icons';
import { Menu } from 'antd';
import { getLocale, setLocale } from 'umi-plugin-react/locale';
import { getLocale, setLocale } from 'umi';
import { ClickParam } from 'antd/es/menu';
import React from 'react';
import classNames from 'classnames';

14
src/e2e/baseLayout.e2e.js

@ -3,6 +3,8 @@ const RouterConfig = require('../../config/config').default.routes;
const BASE_URL = `http://localhost:${process.env.PORT || 8000}`;
const getBrowser = require('./getBrowser');
function formatter(routes, parentPath = '') {
const fixedParentPath = parentPath.replace(/\/{1,}/g, '/');
let result = [];
@ -19,7 +21,15 @@ function formatter(routes, parentPath = '') {
return uniq(result.filter(item => !!item));
}
let browser;
let page;
beforeAll(async () => {
browser = await getBrowser();
});
beforeEach(async () => {
page = await browser.newPage();
await page.goto(`${BASE_URL}`);
await page.evaluate(() => {
localStorage.setItem('antd-pro-authority', '["admin"]');
@ -43,3 +53,7 @@ describe('Ant Design Pro E2E test', () => {
it(`test pages ${route}`, testPage(route));
});
});
afterAll(() => {
browser.close();
});

16
src/e2e/getBrowser.js

@ -0,0 +1,16 @@
import puppeteer from 'puppeteer';
const getBrowser = async () => {
const browser = await puppeteer.launch({
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--no-first-run',
'--no-zygote',
'--no-sandbox',
],
});
return browser;
};
module.exports = getBrowser;

21
src/e2e/topMenu.e2e.js

@ -1,5 +1,22 @@
const getBrowser = require('./getBrowser');
const BASE_URL = `http://localhost:${process.env.PORT || 8000}`;
let browser;
let page;
beforeAll(async () => {
browser = await getBrowser();
});
beforeEach(async () => {
page = await browser.newPage();
await page.goto(`${BASE_URL}`);
await page.evaluate(() => {
localStorage.setItem('antd-pro-authority', '["admin"]');
});
});
describe('Homepage', () => {
it('topmenu should have footer', async () => {
const params = '?navTheme=light&layout=topmenu';
@ -13,3 +30,7 @@ describe('Homepage', () => {
expect(haveFooter).toBeTruthy();
});
});
afterAll(() => {
browser.close();
});

2
src/global.tsx

@ -1,7 +1,7 @@
import { Button, message, notification } from 'antd';
import React from 'react';
import { formatMessage } from 'umi-plugin-react/locale';
import { formatMessage } from 'umi';
import defaultSettings from '../config/defaultSettings';
const { pwa } = defaultSettings;

7
src/layouts/BasicLayout.tsx

@ -9,11 +9,8 @@ import ProLayout, {
Settings,
DefaultFooter,
} from '@ant-design/pro-layout';
import { formatMessage } from 'umi-plugin-react/locale';
import React, { useEffect } from 'react';
import { Link } from 'umi';
import { Dispatch } from 'redux';
import { connect } from 'dva';
import { Link, useIntl, connect, Dispatch } from 'umi';
import { GithubOutlined } from '@ant-design/icons';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
@ -121,6 +118,8 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/') || {
authority: undefined,
};
const { formatMessage } = useIntl();
return (
<ProLayout
logo={logo}

5
src/layouts/SecurityLayout.tsx

@ -1,9 +1,8 @@
import React from 'react';
import { connect } from 'dva';
import { PageLoading } from '@ant-design/pro-layout';
import { Redirect } from 'umi';
import { Redirect, connect, ConnectProps } from 'umi';
import { stringify } from 'querystring';
import { ConnectState, ConnectProps } from '@/models/connect';
import { ConnectState } from '@/models/connect';
import { CurrentUser } from '@/models/user';
interface SecurityLayoutProps extends ConnectProps {

9
src/layouts/UserLayout.tsx

@ -1,15 +1,13 @@
import { DefaultFooter, MenuDataItem, getMenuData, getPageTitle } from '@ant-design/pro-layout';
import { Helmet } from 'react-helmet';
import { Link } from 'umi';
import { Link, useIntl, ConnectProps, connect } from 'umi';
import React from 'react';
import { formatMessage } from 'umi-plugin-react/locale';
import { connect } from 'dva';
import SelectLang from '@/components/SelectLang';
import { ConnectProps, ConnectState } from '@/models/connect';
import { ConnectState } from '@/models/connect';
import logo from '../assets/logo.svg';
import styles from './UserLayout.less';
export interface UserLayoutProps extends ConnectProps {
export interface UserLayoutProps extends Partial<ConnectProps> {
breadcrumbNameMap: {
[path: string]: MenuDataItem;
};
@ -28,6 +26,7 @@ const UserLayout: React.FC<UserLayoutProps> = props => {
pathname: '',
},
} = props;
const { formatMessage } = useIntl();
const { breadcrumb } = getMenuData(routes);
const title = getPageTitle({
pathname: location.pathname,

9
src/models/connect.d.ts

@ -1,6 +1,4 @@
import { AnyAction } from 'redux';
import { MenuDataItem } from '@ant-design/pro-layout';
import { RouterTypes } from 'umi';
import { GlobalModelState } from './global';
import { DefaultSettings as SettingModelState } from '../../config/defaultSettings';
import { UserModelState } from './user';
@ -31,10 +29,3 @@ export interface ConnectState {
export interface Route extends MenuDataItem {
routes?: Route[];
}
/**
* @type T: Params matched in dynamic routing
*/
export interface ConnectProps<T = {}> extends Partial<RouterTypes<Route, T>> {
dispatch?: Dispatch<AnyAction>;
}

3
src/models/global.ts

@ -1,5 +1,4 @@
import { Reducer } from 'redux';
import { Subscription, Effect } from 'dva';
import { Subscription, Reducer, Effect } from 'umi';
import { NoticeIconData } from '@/components/NoticeIcon';
import { queryNotices } from '@/services/user';

8
src/models/login.ts

@ -1,7 +1,5 @@
import { Reducer } from 'redux';
import { Effect } from 'dva';
import { stringify } from 'querystring';
import { router } from 'umi';
import { history, Reducer, Effect } from 'umi';
import { fakeAccountLogin } from '@/services/login';
import { setAuthority } from '@/utils/authority';
@ -56,7 +54,7 @@ const Model: LoginModelType = {
return;
}
}
router.replace(redirect || '/');
history.replace(redirect || '/');
}
},
@ -64,7 +62,7 @@ const Model: LoginModelType = {
const { redirect } = getPageQuery();
// Note: There may be security issues, please note
if (window.location.pathname !== '/user/login' && !redirect) {
router.replace({
history.replace({
pathname: '/user/login',
search: stringify({
redirect: window.location.href,

2
src/models/setting.ts

@ -1,4 +1,4 @@
import { Reducer } from 'redux';
import { Reducer } from 'umi';
import defaultSettings, { DefaultSettings } from '../../config/defaultSettings';
export interface SettingModelType {

3
src/models/user.ts

@ -1,5 +1,4 @@
import { Effect } from 'dva';
import { Reducer } from 'redux';
import { Effect, Reducer } from 'umi';
import { queryCurrent, query as queryUsers } from '@/services/user';

4
src/pages/404.tsx

@ -1,6 +1,6 @@
import { Button, Result } from 'antd';
import React from 'react';
import { router } from 'umi';
import { history } from 'umi';
const NoFoundPage: React.FC<{}> = () => (
<Result
@ -8,7 +8,7 @@ const NoFoundPage: React.FC<{}> = () => (
title="404"
subTitle="Sorry, the page you visited does not exist."
extra={
<Button type="primary" onClick={() => router.push('/')}>
<Button type="primary" onClick={() => history.push('/')}>
Back Home
</Button>
}

5
src/pages/Authorized.tsx

@ -1,9 +1,8 @@
import React from 'react';
import { Redirect } from 'umi';
import { connect } from 'dva';
import { Redirect, connect, ConnectProps } from 'umi';
import Authorized from '@/utils/Authorized';
import { getRouteAuthority } from '@/utils/utils';
import { ConnectProps, ConnectState, UserModelState } from '@/models/connect';
import { ConnectState, UserModelState } from '@/models/connect';
interface AuthComponentProps extends ConnectProps {
user: UserModelState;

3
src/pages/user/login/components/Login/index.tsx

@ -33,7 +33,7 @@ interface LoginType extends React.FC<LoginProps> {
const Login: LoginType = props => {
const { className } = props;
const [tabs, setTabs] = useState<string[]>([]);
const [active, setActive] = useState();
const [active, setActive] = useState({});
const [type, setType] = useMergeValue('', {
value: props.activeKey,
onChange: props.onTabChange,
@ -65,6 +65,7 @@ const Login: LoginType = props => {
},
},
updateActive: activeItem => {
if (!active) return;
if (active[type]) {
active[type].push(activeItem);
} else {

6
src/pages/user/login/index.tsx

@ -1,9 +1,7 @@
import { AlipayCircleOutlined, TaobaoCircleOutlined, WeiboCircleOutlined } from '@ant-design/icons';
import { Alert, Checkbox } from 'antd';
import React, { useState } from 'react';
import { Dispatch, AnyAction } from 'redux';
import { Link } from 'umi';
import { connect } from 'dva';
import { Link, connect, Dispatch } from 'umi';
import { StateType } from '@/models/login';
import { LoginParamsType } from '@/services/login';
import { ConnectState } from '@/models/connect';
@ -13,7 +11,7 @@ import styles from './style.less';
const { Tab, UserName, Password, Mobile, Captcha, Submit } = LoginFrom;
interface LoginProps {
dispatch: Dispatch<AnyAction>;
dispatch: Dispatch;
userLogin: StateType;
submitting?: boolean;
}

16
src/utils/authority.test.ts

@ -1,16 +0,0 @@
import { getAuthority } from './authority';
describe('getAuthority should be strong', () => {
it('string', () => {
expect(getAuthority('admin')).toEqual(['admin']);
});
it('array with double quotes', () => {
expect(getAuthority('"admin"')).toEqual(['admin']);
});
it('array with single item', () => {
expect(getAuthority('["admin"]')).toEqual(['admin']);
});
it('array with multiple items', () => {
expect(getAuthority('["admin", "guest"]')).toEqual(['admin', 'guest']);
});
});

16
tsconfig.json

@ -18,19 +18,9 @@
"experimentalDecorators": true,
"strict": true,
"paths": {
"@/*": ["./src/*"]
"@/*": ["./src/*"],
"@@/*": ["./src/.umi/*"]
}
},
"exclude": [
"node_modules",
"build",
"dist",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts",
"tslint:latest",
"tslint-config-prettier"
]
"exclude": ["node_modules", "build", "dist", "scripts", "src/.umi/*", "webpack", "jest"]
}

Loading…
Cancel
Save