Skip to content
This repository was archived by the owner on Jan 26, 2022. It is now read-only.

Commit e7a199b

Browse files
committed
feat: refactor project basic layout, basic config, upgrade to Antd V4
1 parent da97fa6 commit e7a199b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+8334
-25950
lines changed

.commitlintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = { extends: ['@commitlint/config-conventional'] }

.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"printWidth": 120,
3+
"singleQuote": true,
4+
"trailingComma": "es5",
5+
"arrowParens": "always"
6+
}

husky.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const isWin = process.platform === 'win32';
2+
const commands = ['lint-staged', isWin ? 'npm run jest:win' : 'npm run jest'];
3+
4+
const tasks = (arr) => arr.join(' && ');
5+
6+
module.exports = {
7+
hooks: {
8+
'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
9+
'pre-commit': tasks(commands),
10+
},
11+
};

package-lock.json

Lines changed: 0 additions & 20349 deletions
This file was deleted.

package.json

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,56 @@
44
"version": "0.1.0",
55
"private": true,
66
"dependencies": {
7-
"@storybook/addon-knobs": "^5.2.1",
8-
"@types/classnames": "^2.2.8",
7+
"@ant-design/compatible": "^1.0.5",
8+
"@commitlint/cli": "^9.1.1",
9+
"@commitlint/config-conventional": "^9.1.1",
10+
"@storybook/addon-knobs": "^6.0.4",
11+
"@testing-library/react": "^10.4.8",
12+
"@types/classnames": "^2.2.10",
913
"@types/dva": "^1.1.0",
10-
"@types/enzyme": "^3.9.4",
11-
"@types/enzyme-adapter-react-16": "^1.0.5",
12-
"@types/jest": "^24.0.18",
13-
"@types/node": "^12.7.5",
14-
"@types/qs": "^6.5.3",
14+
"@types/enzyme": "^3.10.5",
15+
"@types/enzyme-adapter-react-16": "^1.0.6",
16+
"@types/jest": "^26.0.9",
17+
"@types/node": "^14.0.27",
18+
"@types/nprogress": "^0.2.0",
19+
"@types/qs": "^6.9.4",
1520
"@types/react": "^16.9.2",
16-
"@types/react-document-title": "^2.0.3",
21+
"@types/react-document-title": "^2.0.4",
1722
"@types/react-dom": "^16.9.0",
1823
"@types/react-infinite-scroller": "^1.2.1",
19-
"@types/react-loadable": "^5.5.1",
20-
"@types/redux-logger": "^3.0.7",
24+
"@types/react-loadable": "^5.5.3",
25+
"@types/react-motion": "^0.0.29",
26+
"@types/redux-logger": "^3.0.8",
2127
"@types/storybook__addon-knobs": "^5.0.4",
22-
"@types/storybook__react": "^4.0.2",
23-
"antd": "^3.23.4",
24-
"axios": "^0.19.0",
28+
"@types/storybook__react": "^5.2.1",
29+
"antd": "^4.5.4",
30+
"axios": "^0.19.2",
2531
"classnames": "^2.2.6",
32+
"commitizen": "^4.1.2",
2633
"date-fns": "^2.2.1",
2734
"dva": "^2.4.1",
2835
"dva-loading": "^3.0.14",
29-
"enzyme": "^3.10.0",
30-
"enzyme-adapter-react-16": "^1.14.0",
31-
"enzyme-to-json": "^3.3.5",
36+
"enzyme": "^3.11.0",
37+
"enzyme-adapter-react-16": "^1.15.3",
38+
"enzyme-to-json": "^3.5.0",
3239
"faker": "^4.1.0",
33-
"history": "^4.10.1",
34-
"jest-fetch-mock": "^2.1.2",
35-
"lodash": "^4.17.11",
40+
"history": "^5.0.0",
41+
"jest-fetch-mock": "^3.0.3",
42+
"lodash": "^4.17.19",
3643
"lodash-decorators": "^6.0.1",
37-
"node-sass": "^4.12.0",
38-
"path-to-regexp": "^3.1.0",
44+
"node-sass": "^4.14.1",
45+
"nprogress": "^0.2.0",
46+
"path-to-regexp": "^6.1.0",
3947
"qs": "^6.9.0",
4048
"query-string": "^6.8.3",
41-
"react": "^16.8.6",
49+
"react": "^16.13.1",
4250
"react-document-title": "^2.0.3",
43-
"react-dom": "^16.8.6",
51+
"react-dom": "^16.13.1",
4452
"react-hot-loader": "^4.12.14",
4553
"react-infinite-scroller": "^1.2.4",
4654
"react-loadable": "^5.5.0",
47-
"react-test-renderer": "^16.8.6",
55+
"react-motion": "^0.5.2",
56+
"react-test-renderer": "^16.13.1",
4857
"redux-logger": "^3.0.6",
4958
"source-map-explorer": "^2.1.0",
5059
"typescript": "^3.6.3"
@@ -56,17 +65,14 @@
5665
"build": "react-app-rewired build",
5766
"staging": "cross-env REACT_APP_BUILD=staging react-app-rewired start",
5867
"test": "react-app-rewired test",
59-
"jest": "CI=true react-app-rewired test",
68+
"jest": "CI=true yarn test",
69+
"jest:win": "set CI=true&&yarn test",
70+
"coverage": "npm test -- --coverage",
6071
"tslint": "tslint --fix 'src/**/*.(ts|tsx)'",
6172
"mock": "json-server mock/db.js",
6273
"storybook": "start-storybook -p 9009 -s public",
6374
"build-storybook": "build-storybook -s public"
6475
},
65-
"husky": {
66-
"hooks": {
67-
"pre-commit": "lint-staged && npm run jest"
68-
}
69-
},
7076
"lint-staged": {
7177
"*.(ts|tsx)": [
7278
"npm run check"
@@ -82,28 +88,33 @@
8288
"not op_mini all"
8389
],
8490
"devDependencies": {
85-
"@storybook/addon-actions": "^5.1.9",
86-
"@storybook/addon-info": "^5.1.9",
87-
"@storybook/addon-links": "^5.1.9",
88-
"@storybook/addons": "^5.1.9",
89-
"@storybook/react": "^5.1.9",
90-
"babel-plugin-import": "^1.12.0",
91-
"cross-env": "^5.2.0",
92-
"customize-cra": "^0.5.0",
93-
"husky": "^3.0.3",
94-
"lint-staged": "^9.2.1",
91+
"@storybook/addon-actions": "^6.0.4",
92+
"@storybook/addon-info": "^5.3.19",
93+
"@storybook/addon-links": "^6.0.4",
94+
"@storybook/addons": "^6.0.4",
95+
"@storybook/react": "^6.0.4",
96+
"babel-plugin-import": "^1.13.0",
97+
"cross-env": "^7.0.2",
98+
"customize-cra": "^1.0.0",
99+
"husky": "^4.2.5",
100+
"lint-staged": "^10.2.11",
95101
"react-app-rewire-hot-loader": "^2.0.1",
96-
"react-app-rewired": "^2.1.1",
97-
"react-scripts": "^3.0.1",
98-
"redux-mock-store": "^1.5.3",
99-
"tslint": "^5.18.0",
102+
"react-app-rewired": "^2.1.6",
103+
"react-scripts": "^3.4.2",
104+
"redux-mock-store": "^1.5.4",
105+
"tslint": "^6.1.3",
100106
"tslint-eslint-rules": "^5.4.0",
101107
"tslint-lines-between-class-members": "^1.3.4",
102-
"tslint-react": "^4.0.0",
103-
"tslint-react-hooks": "^2.1.1",
104-
"webpack-cli": "^3.3.5"
108+
"tslint-react": "^5.0.0",
109+
"tslint-react-hooks": "^2.2.2",
110+
"webpack-cli": "^3.3.12"
105111
},
106112
"engines": {
107113
"node": ">= 8.9.0"
114+
},
115+
"config": {
116+
"commitizen": {
117+
"path": "./node_modules/cz-conventional-changelog"
118+
}
108119
}
109120
}

public/css/nprogress.css

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Make clicks pass-through */
2+
#nprogress {
3+
pointer-events: none;
4+
}
5+
6+
#nprogress .bar {
7+
background: #29d;
8+
9+
position: fixed;
10+
z-index: 1031;
11+
top: 0;
12+
left: 0;
13+
14+
width: 100%;
15+
height: 2px;
16+
}
17+
18+
/* Fancy blur effect */
19+
#nprogress .peg {
20+
display: block;
21+
position: absolute;
22+
right: 0px;
23+
width: 100px;
24+
height: 100%;
25+
box-shadow: 0 0 10px #29d, 0 0 5px #29d;
26+
opacity: 1.0;
27+
28+
-webkit-transform: rotate(3deg) translate(0px, -4px);
29+
-ms-transform: rotate(3deg) translate(0px, -4px);
30+
transform: rotate(3deg) translate(0px, -4px);
31+
}
32+
33+
/* Remove these to get rid of the spinner */
34+
#nprogress .spinner {
35+
display: block;
36+
position: fixed;
37+
z-index: 1031;
38+
top: 15px;
39+
right: 15px;
40+
}
41+
42+
#nprogress .spinner-icon {
43+
width: 18px;
44+
height: 18px;
45+
box-sizing: border-box;
46+
47+
border: solid 2px transparent;
48+
border-top-color: #29d;
49+
border-left-color: #29d;
50+
border-radius: 50%;
51+
52+
-webkit-animation: nprogress-spinner 400ms linear infinite;
53+
animation: nprogress-spinner 400ms linear infinite;
54+
}
55+
56+
.nprogress-custom-parent {
57+
overflow: hidden;
58+
position: relative;
59+
}
60+
61+
.nprogress-custom-parent #nprogress .spinner,
62+
.nprogress-custom-parent #nprogress .bar {
63+
position: absolute;
64+
}
65+
66+
@-webkit-keyframes nprogress-spinner {
67+
0% { -webkit-transform: rotate(0deg); }
68+
100% { -webkit-transform: rotate(360deg); }
69+
}
70+
@keyframes nprogress-spinner {
71+
0% { transform: rotate(0deg); }
72+
100% { transform: rotate(360deg); }
73+
}
74+

public/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
1414
-->
1515
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
16+
<link rel='stylesheet' href='%PUBLIC_URL%/css/nprogress.css' />
1617
<!--
1718
Notice the use of %PUBLIC_URL% in the tags above.
1819
It will be replaced with the URL of the `public` folder during the build.

src/App.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import './App.css';
2-
31
import { Layout } from 'antd';
42
import { connect } from 'dva';
53
import React, { FC } from 'react';
64

7-
import { Content, ErrorBoundary, Footer, Header, SideBar } from './components';
5+
import { BreadCrumbs, Content, ErrorBoundary, Footer, Header, SideBar } from './components';
86
import { Auth } from './models/global';
9-
import AppRoutes from './routes';
10-
import routesConfig from './routes/config';
7+
import { AppRoutes } from './routes';
8+
import { appRoutes } from './routes/config';
119
import { getFlatMenuKeys } from './utils/utils';
1210

13-
const menu = routesConfig.app;
11+
import './App.css';
12+
13+
const menu = appRoutes.app;
1414
const flatMenuKeys = getFlatMenuKeys(menu);
1515

1616
interface DvaProps {
@@ -29,13 +29,19 @@ const App: FC<Props> = (props: Props) => {
2929

3030
return (
3131
<Layout className="App">
32-
<SideBar collapsed={collapsed} menu={menu} onCollapse={onCollapse}
33-
flatMenuKeys={flatMenuKeys} location={location} />
32+
<SideBar
33+
menu={menu}
34+
location={location}
35+
collapsed={collapsed}
36+
onCollapse={onCollapse}
37+
flatMenuKeys={flatMenuKeys}
38+
/>
3439
<Layout>
3540
<Header />
3641
<Content>
42+
<BreadCrumbs menu={menu} url={location.pathname} />
3743
<ErrorBoundary>
38-
<AppRoutes app={app} auth={auth} />
44+
<AppRoutes menu={menu} app={app} auth={auth} />
3945
</ErrorBoundary>
4046
</Content>
4147
<Footer className="Footer" />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { storiesOf } from '@storybook/react';
2+
import React from 'react';
3+
4+
import { appRoutes } from '../../routes';
5+
import BreadCrumbs from './BreadCrumbs';
6+
7+
storiesOf('BreadCrumbs', module).add('default', () => <BreadCrumbs menu={appRoutes.app} url="/app/dashboard" />);
Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,50 @@
1-
import { Breadcrumb } from 'antd';
1+
import { Breadcrumb, Typography } from 'antd';
22
import { Link } from 'dva/router';
3-
import React, { PureComponent } from 'react';
3+
import React, { FC } from 'react';
44

5-
interface InternalProps {
6-
first?: string;
7-
second?: string;
5+
import { RouteConfig } from '../../routes';
6+
import { getBreadcrumbNameMap, urlToList } from '../../utils/utils';
7+
8+
const { Item } = Breadcrumb;
9+
const { Text } = Typography;
10+
11+
// 渲染 Breadcrumb 子节点
12+
// Render the Breadcrumb child node
13+
interface DefaultItemProps {
14+
path: string;
15+
name: string;
16+
component?: string;
817
}
918

10-
class BreadCrumbs extends PureComponent<InternalProps> {
11-
12-
public render() {
13-
const { first, second } = this.props;
14-
15-
return (
16-
<span>
17-
<Breadcrumb style={{ margin: '12px 0' }}>
18-
<Breadcrumb.Item>
19-
<Link to={'/app/dashboard'}>首页</Link>
20-
</Breadcrumb.Item>
21-
{first && <Breadcrumb.Item>{first}</Breadcrumb.Item>}
22-
{second && <Breadcrumb.Item>{second}</Breadcrumb.Item>}
23-
</Breadcrumb>
24-
</span>
25-
);
26-
}
19+
export const DefaultItem: FC<DefaultItemProps> = (props) => {
20+
const { path, component, name } = props;
21+
return component ? <Link to={path}>{name}</Link> : <Text>{name}</Text>;
22+
};
23+
24+
interface Props {
25+
url: string;
26+
menu: RouteConfig[];
2727
}
2828

29+
export const BreadCrumbs: FC<Props> = (props) => {
30+
const { url, menu } = props;
31+
const urlList = urlToList(url);
32+
const breadCrumbsMap = getBreadcrumbNameMap(menu);
33+
const breadCrumbs = urlList.map((item: string) => breadCrumbsMap[item]).filter((item) => item && item);
34+
35+
if (!(breadCrumbs && breadCrumbs.length)) {
36+
return null;
37+
}
38+
39+
return (
40+
<Breadcrumb style={{ margin: '12px 16px' }}>
41+
{breadCrumbs.map((item: RouteConfig) => (
42+
<Item key={item.path}>
43+
<DefaultItem path={item.path} name={item.name} component={item.component} />
44+
</Item>
45+
))}
46+
</Breadcrumb>
47+
);
48+
};
49+
2950
export default BreadCrumbs;

0 commit comments

Comments
 (0)