Commit dc2118db authored by 愚道's avatar 愚道

upgrade to Ant Design Pro v2

parent 91e47a40
const path = require('path'); import routerConfig from './router.config';
export default { export default {
entry: 'src/index.js', plugins: [
extraBabelPlugins: [['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }]], [
env: { 'umi-plugin-react',
development: { {
extraBabelPlugins: ['dva-hmr'], antd: true,
}, dva: {
}, hmr: true,
},
},
],
],
externals: { externals: {
'@antv/data-set': 'DataSet', '@antv/data-set': 'DataSet',
rollbar: 'rollbar', rollbar: 'rollbar',
}, },
alias: {
components: path.resolve(__dirname, 'src/components/'),
},
ignoreMomentLocale: true, ignoreMomentLocale: true,
theme: './src/theme.js', theme: {
html: { // 'primary-color': '#10e99b',
template: './src/index.ejs', 'card-actions-background': '#f5f8fa',
}, },
lessLoaderOptions: { lessLoaderOptions: {
javascriptEnabled: true, javascriptEnabled: true,
...@@ -26,4 +27,5 @@ export default { ...@@ -26,4 +27,5 @@ export default {
disableDynamicImport: true, disableDynamicImport: true,
publicPath: '/', publicPath: '/',
hash: true, hash: true,
routes: routerConfig,
}; };
module.exports = [
{
path: '/',
component: '../layouts/BasicLayout',
routes: [
// dashboard
{ path: '/', redirect: '/dashboard/analysis' },
{
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' },
],
},
],
},
];
import { parse } from 'url'; import { parse } from 'url';
import mockjs from 'mockjs';
const titles = [ const titles = [
'Alipay', 'Alipay',
...@@ -69,7 +70,7 @@ export function fakeList(count) { ...@@ -69,7 +70,7 @@ export function fakeList(count) {
owner: user[i % 10], owner: user[i % 10],
title: titles[i % 8], title: titles[i % 8],
avatar: avatars[i % 8], avatar: avatars[i % 8],
cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - i % 4], cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
status: ['active', 'exception', 'normal'][i % 3], status: ['active', 'exception', 'normal'][i % 3],
percent: Math.ceil(Math.random() * 50) + 50, percent: Math.ceil(Math.random() * 50) + 50,
logo: avatars[i % 8], logo: avatars[i % 8],
...@@ -290,7 +291,14 @@ export const getActivities = [ ...@@ -290,7 +291,14 @@ export const getActivities = [
]; ];
export default { export default {
getNotice, 'GET /api/project/notice': getNotice,
getActivities, 'GET /api/activities': getActivities,
getFakeList,
'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,
}; };
...@@ -193,5 +193,5 @@ export const getFakeChartData = { ...@@ -193,5 +193,5 @@ export const getFakeChartData = {
}; };
export default { export default {
getFakeChartData, 'GET /api/fake_chart_data': getFakeChartData,
}; };
import mockjs from 'mockjs'; import mockjs from 'mockjs';
import { getRule, postRule } from './mock/rule';
import { getActivities, getNotice, getFakeList } from './mock/api';
import { getFakeChartData } from './mock/chart';
import { getProfileBasicData } from './mock/profile';
import { getProfileAdvancedData } from './mock/profile';
import { getNotices } from './mock/notices';
import { format, delay } from 'roadhog-api-doc';
// 是否禁用代理 export default {
const noProxy = process.env.NO_PROXY === 'true';
// 代码中会兼容本地 service mock 以及部署站点的静态数据
const proxy = {
// 支持值为 Object 和 Array // 支持值为 Object 和 Array
'GET /api/currentUser': { 'GET /api/currentUser': {
$desc: '获取当前用户接口', name: 'Serati Ma',
$params: { avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
pageSize: { userid: '00000001',
desc: '分页', notifyCount: 12,
exp: 2,
},
},
$body: {
name: 'Serati Ma',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
userid: '00000001',
notifyCount: 12,
},
}, },
// GET POST 可省略 // GET POST 可省略
'GET /api/users': [ 'GET /api/users': [
...@@ -49,28 +29,12 @@ const proxy = { ...@@ -49,28 +29,12 @@ const proxy = {
address: 'Sidney No. 1 Lake Park', address: 'Sidney No. 1 Lake Park',
}, },
], ],
'GET /api/project/notice': getNotice,
'GET /api/activities': getActivities,
'GET /api/rule': getRule,
'POST /api/rule': {
$params: {
pageSize: {
desc: '分页',
exp: 2,
},
},
$body: postRule,
},
'POST /api/forms': (req, res) => { 'POST /api/forms': (req, res) => {
res.send({ message: 'Ok' }); res.send({ message: 'Ok' });
}, },
'GET /api/tags': mockjs.mock({ 'GET /api/tags': mockjs.mock({
'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }], 'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }],
}), }),
'GET /api/fake_list': getFakeList,
'GET /api/fake_chart_data': getFakeChartData,
'GET /api/profile/basic': getProfileBasicData,
'GET /api/profile/advanced': getProfileAdvancedData,
'POST /api/login/account': (req, res) => { 'POST /api/login/account': (req, res) => {
const { password, userName, type } = req.body; const { password, userName, type } = req.body;
if (password === '888888' && userName === 'admin') { if (password === '888888' && userName === 'admin') {
...@@ -98,7 +62,6 @@ const proxy = { ...@@ -98,7 +62,6 @@ const proxy = {
'POST /api/register': (req, res) => { 'POST /api/register': (req, res) => {
res.send({ status: 'ok', currentAuthority: 'user' }); res.send({ status: 'ok', currentAuthority: 'user' });
}, },
'GET /api/notices': getNotices,
'GET /api/500': (req, res) => { 'GET /api/500': (req, res) => {
res.status(500).send({ res.status(500).send({
timestamp: 1513932555104, timestamp: 1513932555104,
...@@ -136,5 +99,3 @@ const proxy = { ...@@ -136,5 +99,3 @@ const proxy = {
}); });
}, },
}; };
export default (noProxy ? {} : delay(proxy, 1000));
...@@ -95,5 +95,5 @@ export const getNotices = (req, res) => { ...@@ -95,5 +95,5 @@ export const getNotices = (req, res) => {
]); ]);
}; };
export default { export default {
getNotices, 'GET /api/notices': getNotices,
}; };
...@@ -153,6 +153,6 @@ export const getProfileAdvancedData = { ...@@ -153,6 +153,6 @@ export const getProfileAdvancedData = {
}; };
export default { export default {
getProfileBasicData, 'GET /api/profile/basic': getProfileBasicData,
getProfileAdvancedData, 'GET /api/profile/advanced': getProfileAdvancedData,
}; };
...@@ -132,6 +132,14 @@ export function postRule(req, res, u, b) { ...@@ -132,6 +132,14 @@ export function postRule(req, res, u, b) {
} }
export default { export default {
getRule, 'GET /api/rule': getRule,
postRule, 'POST /api/rule': {
$params: {
pageSize: {
desc: '分页',
exp: 2,
},
},
$body: postRule,
},
}; };
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
"private": true, "private": true,
"scripts": { "scripts": {
"precommit": "npm run lint-staged", "precommit": "npm run lint-staged",
"start": "cross-env ESLINT=none roadhog dev", "start": "umi dev",
"start:no-proxy": "cross-env NO_PROXY=true ESLINT=none roadhog dev", "start:no-mock": "cross-env MOCK=none umi dev",
"build": "cross-env ESLINT=none roadhog build", "build": "umi build",
"site": "roadhog-api-doc static && gh-pages -d dist", "site": "roadhog-api-doc static && gh-pages -d dist",
"analyze": "cross-env ANALYZE=true roadhog build", "analyze": "cross-env ANALYZE=true roadhog build",
"lint:style": "stylelint \"src/**/*.less\" --syntax less", "lint:style": "stylelint \"src/**/*.less\" --syntax less",
...@@ -27,25 +27,24 @@ ...@@ -27,25 +27,24 @@
"bizcharts": "^3.1.10", "bizcharts": "^3.1.10",
"bizcharts-plugin-slider": "^2.0.1", "bizcharts-plugin-slider": "^2.0.1",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"dva": "^2.2.3",
"dva-loading": "^2.0.3",
"enquire-js": "^0.2.1", "enquire-js": "^0.2.1",
"lodash": "^4.17.10", "lodash": "^4.17.10",
"lodash-decorators": "^6.0.0", "lodash-decorators": "^6.0.0",
"lodash.isequal": "^4.5.0",
"memoize-one": "^4.0.0",
"moment": "^2.19.3", "moment": "^2.19.3",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"omit.js": "^1.0.0", "omit.js": "^1.0.0",
"path-to-regexp": "^2.1.0", "path-to-regexp": "^2.1.0",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"qs": "^6.5.0", "qs": "^6.5.0",
"react": "^16.4.1",
"react-container-query": "^0.11.0", "react-container-query": "^0.11.0",
"react-document-title": "^2.0.3", "react-document-title": "^2.0.3",
"react-dom": "^16.4.1",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"react-loadable": "^5.5.0",
"rollbar": "^2.3.4", "rollbar": "^2.3.4",
"setprototypeof": "^1.1.0", "setprototypeof": "^1.1.0",
"umi": "^2.0.0-beta.10",
"umi-plugin-react": "^1.0.0-beta.10",
"url-polyfill": "^1.0.10" "url-polyfill": "^1.0.10"
}, },
"devDependencies": { "devDependencies": {
......
import React, { createElement } from 'react';
import { Spin } from 'antd';
import pathToRegexp from 'path-to-regexp';
import Loadable from 'react-loadable';
import { getMenuData } from './menu';
let routerDataCache;
const getRouterDataCache = app => {
if (!routerDataCache) {
routerDataCache = getRouterData(app);
}
return routerDataCache;
};
const modelNotExisted = (app, model) =>
// eslint-disable-next-line
!app._models.some(({ namespace }) => {
return namespace === model.substring(model.lastIndexOf('/') + 1);
});
// wrapper of dynamic
const dynamicWrapper = (app, models, component) => {
// register models
models.forEach(model => {
if (modelNotExisted(app, model)) {
// eslint-disable-next-line
app.model(require(`../models/${model}`).default);
}
});
// () => require('module')
// transformed by babel-plugin-dynamic-import-node-sync
if (component.toString().indexOf('.then(') < 0) {
return props => {
return createElement(component().default, {
...props,
routerData: getRouterDataCache(app),
});
};
}
// () => import('module')
return Loadable({
loader: () => {
return component().then(raw => {
const Component = raw.default || raw;
return props =>
createElement(Component, {
...props,
routerData: getRouterDataCache(app),
});
});
},
loading: () => {
return <Spin size="large" className="global-spin" />;
},
});
};
function getFlatMenuData(menus) {
let keys = {};
menus.forEach(item => {
if (item.children) {
keys[item.path] = { ...item };
keys = { ...keys, ...getFlatMenuData(item.children) };
} else {
keys[item.path] = { ...item };
}
});
return keys;
}
function findMenuKey(menuData, path) {
const menuKey = Object.keys(menuData).find(key => pathToRegexp(path).test(key));
if (menuKey == null) {
if (path === '/') {
return null;
}
const lastIdx = path.lastIndexOf('/');
if (lastIdx < 0) {
return null;
}
if (lastIdx === 0) {
return findMenuKey(menuData, '/');
}
// 如果没有,使用上一层的配置
return findMenuKey(menuData, path.substr(0, lastIdx));
}
return menuKey;
}
export const getRouterData = app => {
const routerConfig = {
'/': {
component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
},
'/dashboard/analysis': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
},
'/dashboard/monitor': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},
'/dashboard/workplace': {
component: dynamicWrapper(app, ['project', 'activities', 'chart'], () =>
import('../routes/Dashboard/Workplace')
),
// hideInBreadcrumb: true,
// name: '工作台',
// authority: 'admin',
},
'/form/basic-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/BasicForm')),
},
'/form/step-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')),
},
'/form/step-form/info': {
name: '分步表单(填写转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step1')),
},
'/form/step-form/confirm': {
name: '分步表单(确认转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')),
},
'/form/step-form/result': {
name: '分步表单(完成)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')),
},
'/form/advanced-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/AdvancedForm')),
},
'/list/table-list': {
component: dynamicWrapper(app, ['rule'], () => import('../routes/List/TableList')),
},
'/list/basic-list': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/BasicList')),
},
'/list/card-list': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')),
},
'/list/search': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/List')),
},
'/list/search/projects': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')),
},
'/list/search/applications': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')),
},
'/list/search/articles': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')),
},
'/profile/basic': {
component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/BasicProfile')),
},
'/profile/advanced': {
component: dynamicWrapper(app, ['profile'], () =>
import('../routes/Profile/AdvancedProfile')
),
},
'/result/success': {
component: dynamicWrapper(app, [], () => import('../routes/Result/Success')),
},
'/result/fail': {
component: dynamicWrapper(app, [], () => import('../routes/Result/Error')),
},
'/exception/403': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/403')),
},
'/exception/404': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/404')),
},
'/exception/500': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/500')),
},
'/exception/trigger': {
component: dynamicWrapper(app, ['error'], () =>
import('../routes/Exception/triggerException')
),
},
'/user': {
component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')),
},
'/user/login': {
component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')),
},
'/user/register': {
component: dynamicWrapper(app, ['register'], () => import('../routes/User/Register')),
},
'/user/register-result': {
component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')),
},
// '/user/:id': {
// component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')),
// },
};
// Get name from ./menu.js or just set it in the router data.
const menuData = getFlatMenuData(getMenuData());
// Route configuration data
// eg. {name,authority ...routerConfig }
const routerData = {};
// The route matches the menu
Object.keys(routerConfig).forEach(path => {
// Regular match item name
// eg. router /user/:id === /user/chen
let menuKey = Object.keys(menuData).find(key => pathToRegexp(path).test(`${key}`));
const inherited = menuKey == null;
if (menuKey == null) {
menuKey = findMenuKey(menuData, path);
}
let menuItem = {};
// If menuKey is not empty
if (menuKey) {
menuItem = menuData[menuKey];
}
let router = routerConfig[path];
// If you need to configure complex parameter routing,
// https://github.com/ant-design/ant-design-pro-site/blob/master/docs/router-and-nav.md#%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E8%B7%AF%E7%94%B1%E8%8F%9C%E5%8D%95
// eg . /list/:type/user/info/:id
router = {
...router,
name: router.name || menuItem.name,
authority: router.authority || menuItem.authority,
hideInBreadcrumb: router.hideInBreadcrumb || menuItem.hideInBreadcrumb,
inherited,
};
routerData[path] = router;
});
return routerData;
};
import './polyfill';
import 'moment/locale/zh-cn';
import './rollbar';
html, html,
body, body,
:global(#root) { #root {
height: 100%; height: 100%;
} }
:global(.ant-layout) { .ant-layout {
min-height: 100%; min-height: 100%;
} }
...@@ -18,14 +18,11 @@ body { ...@@ -18,14 +18,11 @@ body {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
// temp fix for https://github.com/ant-design/ant-design/commit/a1fafb5b727b62cb0be29ce6e9eca8f579d4f8b7 .ant-spin-container {
:global { overflow: visible !important;
.ant-spin-container { }
overflow: visible !important;
}
.global-spin { .global-spin {
width: 100%; width: 100%;
margin: 40px 0 !important; margin: 40px 0 !important;
}
} }
import './polyfill';
import dva from 'dva';
import createHistory from 'history/createHashHistory';
// user BrowserHistory
// import createHistory from 'history/createBrowserHistory';
import createLoading from 'dva-loading';
import 'moment/locale/zh-cn';
import './rollbar';
import './index.less';
// 1. Initialize
const app = dva({
history: createHistory(),
});
// 2. Plugins
app.use(createLoading());
// 3. Register global model
app.model(require('./models/global').default);
// 4. Router
app.router(require('./router').default);
// 5. Start
app.start('#root');
export default app._store; // eslint-disable-line
...@@ -3,22 +3,22 @@ import PropTypes from 'prop-types'; ...@@ -3,22 +3,22 @@ import PropTypes from 'prop-types';
import { Layout, Icon, message } from 'antd'; import { Layout, Icon, message } from 'antd';
import DocumentTitle from 'react-document-title'; import DocumentTitle from 'react-document-title';
import { connect } from 'dva'; import { connect } from 'dva';
import { Route, Redirect, Switch, routerRedux } from 'dva/router'; import { routerRedux } from 'dva/router';
import { ContainerQuery } from 'react-container-query'; import { ContainerQuery } from 'react-container-query';
import classNames from 'classnames'; import classNames from 'classnames';
import pathToRegexp from 'path-to-regexp'; import pathToRegexp from 'path-to-regexp';
import { enquireScreen, unenquireScreen } from 'enquire-js'; import { enquireScreen, unenquireScreen } from 'enquire-js';
import memoizeOne from 'memoize-one';
import deepEqual from 'lodash.isequal';
import GlobalHeader from '../components/GlobalHeader'; import GlobalHeader from '../components/GlobalHeader';
import GlobalFooter from '../components/GlobalFooter'; import GlobalFooter from '../components/GlobalFooter';
import SiderMenu from '../components/SiderMenu'; import SiderMenu from '../components/SiderMenu';
import NotFound from '../routes/Exception/404';
import { getRoutes } from '../utils/utils';
import Authorized from '../utils/Authorized'; import Authorized from '../utils/Authorized';
import { getMenuData } from '../common/menu'; import { getMenuData } from '../common/menu';
import logo from '../assets/logo.svg'; import logo from '../assets/logo.svg';
const { Content, Header, Footer } = Layout; const { Content, Header, Footer } = Layout;
const { AuthorizedRoute, check } = Authorized; const { check } = Authorized;
/** /**
* 根据菜单取得重定向地址. * 根据菜单取得重定向地址.
...@@ -42,21 +42,21 @@ getMenuData().forEach(getRedirect); ...@@ -42,21 +42,21 @@ getMenuData().forEach(getRedirect);
/** /**
* 获取面包屑映射 * 获取面包屑映射
* @param {Object} menuData 菜单配置 * @param {Object} menuData 菜单配置
* @param {Object} routerData 路由配置
*/ */
const getBreadcrumbNameMap = (menuData, routerData) => { const getBreadcrumbNameMap = memoizeOne(meun => {
const result = {}; const routerMap = {};
const childResult = {}; const mergeMeunAndRouter = meunData => {
for (const i of menuData) { meunData.forEach(meunItem => {
if (!routerData[i.path]) { if (meunItem.children) {
result[i.path] = i; mergeMeunAndRouter(meunItem.children);
} }
if (i.children) { // Reduce memory usage
Object.assign(childResult, getBreadcrumbNameMap(i.children, routerData)); routerMap[meunItem.path] = meunItem;
} });
} };
return Object.assign({}, routerData, result, childResult); mergeMeunAndRouter(meun);
}; return routerMap;
}, deepEqual);
const query = { const query = {
'screen-xs': { 'screen-xs': {
...@@ -104,11 +104,17 @@ export default class BasicLayout extends React.PureComponent { ...@@ -104,11 +104,17 @@ export default class BasicLayout extends React.PureComponent {
isMobile, isMobile,
}; };
constructor(props) {
super(props);
this.getPageTitle = memoizeOne(this.getPageTitle);
this.breadcrumbNameMap = getBreadcrumbNameMap(getMenuData());
}
getChildContext() { getChildContext() {
const { location, routerData } = this.props; const { location } = this.props;
return { return {
location, location,
breadcrumbNameMap: getBreadcrumbNameMap(getMenuData(), routerData), breadcrumbNameMap: this.breadcrumbNameMap,
}; };
} }
...@@ -128,23 +134,19 @@ export default class BasicLayout extends React.PureComponent { ...@@ -128,23 +134,19 @@ export default class BasicLayout extends React.PureComponent {
unenquireScreen(this.enquireHandler); unenquireScreen(this.enquireHandler);
} }
getPageTitle() { getPageTitle = pathname => {
const { routerData, location } = this.props;
const { pathname } = location;
let title = 'Ant Design Pro';
let currRouterData = null; let currRouterData = null;
// match params path // match params path
for (const key in routerData) { Object.keys(this.breadcrumbNameMap).forEach(key => {
if (pathToRegexp(key).test(pathname)) { if (pathToRegexp(key).test(pathname)) {
currRouterData = routerData[key]; currRouterData = this.breadcrumbNameMap[key];
break;
} }
});
if (!currRouterData) {
return 'Ant Design Pro';
} }
if (currRouterData && currRouterData.name) { return `${currRouterData.name} - Ant Design Pro`;
title = `${currRouterData.name} - Ant Design Pro`; };
}
return title;
}
getBaseRedirect = () => { getBaseRedirect = () => {
// According to the url parameter to redirect // According to the url parameter to redirect
...@@ -212,12 +214,11 @@ export default class BasicLayout extends React.PureComponent { ...@@ -212,12 +214,11 @@ export default class BasicLayout extends React.PureComponent {
collapsed, collapsed,
fetchingNotices, fetchingNotices,
notices, notices,
routerData, children,
match, location: { pathname },
location,
} = this.props; } = this.props;
const { isMobile: mb } = this.state; const { isMobile: mb } = this.state;
const baseRedirect = this.getBaseRedirect(); // const baseRedirect = this.getBaseRedirect();
const layout = ( const layout = (
<Layout> <Layout>
<SiderMenu <SiderMenu
...@@ -247,25 +248,7 @@ export default class BasicLayout extends React.PureComponent { ...@@ -247,25 +248,7 @@ export default class BasicLayout extends React.PureComponent {
onNoticeVisibleChange={this.handleNoticeVisibleChange} onNoticeVisibleChange={this.handleNoticeVisibleChange}
/> />
</Header> </Header>
<Content style={{ margin: '24px 24px 0', height: '100%' }}> <Content style={{ margin: '24px 24px 0', height: '100%' }}>{children}</Content>
<Switch>
{redirectData.map(item => (
<Redirect key={item.from} exact from={item.from} to={item.to} />
))}
{getRoutes(match.path, routerData).map(item => (
<AuthorizedRoute
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
authority={item.authority}
redirectPath="/exception/403"
/>
))}
<Redirect exact from="/" to={baseRedirect} />
<Route render={NotFound} />
</Switch>
</Content>
<Footer style={{ padding: 0 }}> <Footer style={{ padding: 0 }}>
<GlobalFooter <GlobalFooter
links={[ links={[
...@@ -300,7 +283,7 @@ export default class BasicLayout extends React.PureComponent { ...@@ -300,7 +283,7 @@ export default class BasicLayout extends React.PureComponent {
); );
return ( return (
<DocumentTitle title={this.getPageTitle()}> <DocumentTitle title={this.getPageTitle(pathname)}>
<ContainerQuery query={query}> <ContainerQuery query={query}>
{params => <div className={classNames(params)}>{layout}</div>} {params => <div className={classNames(params)}>{layout}</div>}
</ContainerQuery> </ContainerQuery>
......
// Use require.context to require reducers automatically
// Ref: https://webpack.js.org/guides/dependency-management/#require-context
const context = require.context('./', false, /\.js$/);
export default context
.keys()
.filter(item => item !== './index.js')
.map(key => context(key));
import React from 'react'; import React from 'react';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import Exception from 'components/Exception'; import Exception from '@/components/Exception';
export default () => ( export default () => (
<Exception type="404" style={{ minHeight: 500, height: '80%' }} linkElement={Link} /> <Exception type="404" style={{ minHeight: 500, height: '80%' }} linkElement={Link} />
......
...@@ -24,9 +24,9 @@ import { ...@@ -24,9 +24,9 @@ import {
Bar, Bar,
Pie, Pie,
TimelineChart, TimelineChart,
} from 'components/Charts'; } from '@/components/Charts';
import Trend from 'components/Trend'; import Trend from '@/components/Trend';
import NumberInfo from 'components/NumberInfo'; import NumberInfo from '@/components/NumberInfo';
import { getTimeDistance } from '../../utils/utils'; import { getTimeDistance } from '../../utils/utils';
import styles from './Analysis.less'; import styles from './Analysis.less';
...@@ -208,10 +208,7 @@ export default class Analysis extends Component { ...@@ -208,10 +208,7 @@ export default class Analysis extends Component {
sorter: (a, b) => a.range - b.range, sorter: (a, b) => a.range - b.range,
render: (text, record) => ( render: (text, record) => (
<Trend flag={record.status === 1 ? 'down' : 'up'}> <Trend flag={record.status === 1 ? 'down' : 'up'}>
<span style={{ marginRight: 4 }}> <span style={{ marginRight: 4 }}>{text}%</span>
{text}
%
</span>
</Trend> </Trend>
), ),
align: 'right', align: 'right',
......
...@@ -2,10 +2,10 @@ import React, { PureComponent, Fragment } from 'react'; ...@@ -2,10 +2,10 @@ import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Row, Col, Card, Tooltip } from 'antd'; import { Row, Col, Card, Tooltip } from 'antd';
import numeral from 'numeral'; import numeral from 'numeral';
import { Pie, WaterWave, Gauge, TagCloud } from 'components/Charts'; import { Pie, WaterWave, Gauge, TagCloud } from '@/components/Charts';
import NumberInfo from 'components/NumberInfo'; import NumberInfo from '@/components/NumberInfo';
import CountDown from 'components/CountDown'; import CountDown from '@/components/CountDown';
import ActiveChart from 'components/ActiveChart'; import ActiveChart from '@/components/ActiveChart';
import Authorized from '../../utils/Authorized'; import Authorized from '../../utils/Authorized';
import styles from './Monitor.less'; import styles from './Monitor.less';
......
...@@ -4,8 +4,8 @@ import { connect } from 'dva'; ...@@ -4,8 +4,8 @@ import { connect } from 'dva';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import { Row, Col, Card, List, Avatar } from 'antd'; import { Row, Col, Card, List, Avatar } from 'antd';
import { Radar } from 'components/Charts'; import { Radar } from '@/components/Charts';
import EditableLinkGroup from 'components/EditableLinkGroup'; import EditableLinkGroup from '@/components/EditableLinkGroup';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './Workplace.less'; import styles from './Workplace.less';
...@@ -167,8 +167,7 @@ export default class Workplace extends PureComponent { ...@@ -167,8 +167,7 @@ export default class Workplace extends PureComponent {
<div className={styles.statItem}> <div className={styles.statItem}>
<p>团队内排名</p> <p>团队内排名</p>
<p> <p>
8 8<span> / 24</span>
<span> / 24</span>
</p> </p>
</div> </div>
<div className={styles.statItem}> <div className={styles.statItem}>
......
import React from 'react'; import React from 'react';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import Exception from 'components/Exception'; import Exception from '@/components/Exception';
export default () => ( export default () => (
<Exception type="403" style={{ minHeight: 500, height: '80%' }} linkElement={Link} /> <Exception type="403" style={{ minHeight: 500, height: '80%' }} linkElement={Link} />
......
import React from 'react';
import { Link } from 'dva/router';
import Exception from '@/components/Exception';
export default () => (
<Exception type="404" style={{ minHeight: 500, height: '80%' }} linkElement={Link} />
);
import React from 'react'; import React from 'react';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import Exception from 'components/Exception'; import Exception from '@/components/Exception';
export default () => ( export default () => (
<Exception type="500" style={{ minHeight: 500, height: '80%' }} linkElement={Link} /> <Exception type="500" style={{ minHeight: 500, height: '80%' }} linkElement={Link} />
......
...@@ -13,7 +13,7 @@ import { ...@@ -13,7 +13,7 @@ import {
Popover, Popover,
} from 'antd'; } from 'antd';
import { connect } from 'dva'; import { connect } from 'dva';
import FooterToolbar from 'components/FooterToolbar'; import FooterToolbar from '@/components/FooterToolbar';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import TableForm from './TableForm'; import TableForm from './TableForm';
import styles from './style.less'; import styles from './style.less';
......
...@@ -55,11 +55,7 @@ class Step2 extends React.PureComponent { ...@@ -55,11 +55,7 @@ class Step2 extends React.PureComponent {
</Form.Item> </Form.Item>
<Form.Item {...formItemLayout} className={styles.stepFormText} label="转账金额"> <Form.Item {...formItemLayout} className={styles.stepFormText} label="转账金额">
<span className={styles.money}>{data.amount}</span> <span className={styles.money}>{data.amount}</span>
<span className={styles.uppercase}> <span className={styles.uppercase}>{digitUppercase(data.amount)}</span>
{digitUppercase(data.amount)}
</span>
</Form.Item> </Form.Item>
<Divider style={{ margin: '24px 0' }} /> <Divider style={{ margin: '24px 0' }} />
<Form.Item {...formItemLayout} label="支付密码" required={false}> <Form.Item {...formItemLayout} label="支付密码" required={false}>
......
...@@ -2,7 +2,7 @@ import React, { Fragment } from 'react'; ...@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Button, Row, Col } from 'antd'; import { Button, Row, Col } from 'antd';
import { routerRedux } from 'dva/router'; import { routerRedux } from 'dva/router';
import Result from 'components/Result'; import Result from '@/components/Result';
import styles from './style.less'; import styles from './style.less';
@connect(({ form }) => ({ @connect(({ form }) => ({
......
...@@ -3,8 +3,8 @@ import numeral from 'numeral'; ...@@ -3,8 +3,8 @@ import numeral from 'numeral';
import { connect } from 'dva'; import { connect } from 'dva';
import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Dropdown, Menu } from 'antd'; import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Dropdown, Menu } from 'antd';
import TagSelect from 'components/TagSelect'; import TagSelect from '@/components/TagSelect';
import StandardFormRow from 'components/StandardFormRow'; import StandardFormRow from '@/components/StandardFormRow';
import styles from './Applications.less'; import styles from './Applications.less';
......
...@@ -3,8 +3,8 @@ import moment from 'moment'; ...@@ -3,8 +3,8 @@ import moment from 'moment';
import { connect } from 'dva'; import { connect } from 'dva';
import { Form, Card, Select, List, Tag, Icon, Avatar, Row, Col, Button } from 'antd'; import { Form, Card, Select, List, Tag, Icon, Avatar, Row, Col, Button } from 'antd';
import TagSelect from 'components/TagSelect'; import TagSelect from '@/components/TagSelect';
import StandardFormRow from 'components/StandardFormRow'; import StandardFormRow from '@/components/StandardFormRow';
import styles from './Articles.less'; import styles from './Articles.less';
const { Option } = Select; const { Option } = Select;
......
...@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; ...@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Card, Button, Icon, List } from 'antd'; import { Card, Button, Icon, List } from 'antd';
import Ellipsis from 'components/Ellipsis'; import Ellipsis from '@/components/Ellipsis';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './CardList.less'; import styles from './CardList.less';
......
...@@ -3,10 +3,10 @@ import moment from 'moment'; ...@@ -3,10 +3,10 @@ import moment from 'moment';
import { connect } from 'dva'; import { connect } from 'dva';
import { Row, Col, Form, Card, Select, List } from 'antd'; import { Row, Col, Form, Card, Select, List } from 'antd';
import TagSelect from 'components/TagSelect'; import TagSelect from '@/components/TagSelect';
import AvatarList from 'components/AvatarList'; import AvatarList from '@/components/AvatarList';
import Ellipsis from 'components/Ellipsis'; import Ellipsis from '@/components/Ellipsis';
import StandardFormRow from 'components/StandardFormRow'; import StandardFormRow from '@/components/StandardFormRow';
import styles from './Projects.less'; import styles from './Projects.less';
......
...@@ -19,7 +19,7 @@ import { ...@@ -19,7 +19,7 @@ import {
Badge, Badge,
Divider, Divider,
} from 'antd'; } from 'antd';
import StandardTable from 'components/StandardTable'; import StandardTable from '@/components/StandardTable';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './TableList.less'; import styles from './TableList.less';
......
...@@ -18,7 +18,7 @@ import { ...@@ -18,7 +18,7 @@ import {
Divider, Divider,
} from 'antd'; } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import DescriptionList from 'components/DescriptionList'; import DescriptionList from '@/components/DescriptionList';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './AdvancedProfile.less'; import styles from './AdvancedProfile.less';
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Card, Badge, Table, Divider } from 'antd'; import { Card, Badge, Table, Divider } from 'antd';
import DescriptionList from 'components/DescriptionList'; import DescriptionList from '@/components/DescriptionList';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './BasicProfile.less'; import styles from './BasicProfile.less';
......
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { Button, Icon, Card } from 'antd'; import { Button, Icon, Card } from 'antd';
import Result from 'components/Result'; import Result from '@/components/Result';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
const extra = ( const extra = (
......
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { Button, Row, Col, Icon, Steps, Card } from 'antd'; import { Button, Row, Col, Icon, Steps, Card } from 'antd';
import Result from 'components/Result'; import Result from '@/components/Result';
import PageHeaderLayout from '../../layouts/PageHeaderLayout'; import PageHeaderLayout from '../../layouts/PageHeaderLayout';
const { Step } = Steps; const { Step } = Steps;
......
...@@ -2,7 +2,7 @@ import React, { Component } from 'react'; ...@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import { Checkbox, Alert, Icon } from 'antd'; import { Checkbox, Alert, Icon } from 'antd';
import Login from 'components/Login'; import Login from '@/components/Login';
import styles from './Login.less'; import styles from './Login.less';
const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login; const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login;
......
import React from 'react'; import React from 'react';
import { Button } from 'antd'; import { Button } from 'antd';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import Result from 'components/Result'; import Result from '@/components/Result';
import styles from './RegisterResult.less'; import styles from './RegisterResult.less';
const actions = ( const actions = (
......
import React from 'react';
import { routerRedux, Route, Switch } from 'dva/router';
import { LocaleProvider } from 'antd';
import zhCN from 'antd/lib/locale-provider/zh_CN';
import { getRouterData } from './common/router';
import Authorized from './utils/Authorized';
import { getQueryPath } from './utils/utils';
const { ConnectedRouter } = routerRedux;
const { AuthorizedRoute } = Authorized;
function RouterConfig({ history, app }) {
const routerData = getRouterData(app);
const UserLayout = routerData['/user'].component;
const BasicLayout = routerData['/'].component;
return (
<LocaleProvider locale={zhCN}>
<ConnectedRouter history={history}>
<Switch>
<Route path="/user" component={UserLayout} />
<AuthorizedRoute
path="/"
render={props => <BasicLayout {...props} />}
authority={['admin', 'user']}
redirectPath={getQueryPath('/user/login', {
redirect: window.location.href,
})}
/>
</Switch>
</ConnectedRouter>
</LocaleProvider>
);
}
export default RouterConfig;
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
module.exports = {
// 'primary-color': '#10e99b',
'card-actions-background': '#f5f8fa',
};
import fetch from 'dva/fetch'; import fetch from 'dva/fetch';
import { notification } from 'antd'; import { notification } from 'antd';
import { routerRedux } from 'dva/router'; import { push } from 'umi/router';
import store from '../index';
const codeMessage = { const codeMessage = {
200: '服务器成功返回请求的数据。', 200: '服务器成功返回请求的数据。',
...@@ -77,24 +76,21 @@ export default function request(url, options) { ...@@ -77,24 +76,21 @@ export default function request(url, options) {
return response.json(); return response.json();
}) })
.catch(e => { .catch(e => {
const { dispatch } = store;
const status = e.name; const status = e.name;
if (status === 401) { if (status === 401) {
dispatch({ push('login/logout');
type: 'login/logout',
});
return; return;
} }
if (status === 403) { if (status === 403) {
dispatch(routerRedux.push('/exception/403')); push('/exception/403');
return; return;
} }
if (status <= 504 && status >= 500) { if (status <= 504 && status >= 500) {
dispatch(routerRedux.push('/exception/500')); push('/exception/500');
return; return;
} }
if (status >= 404 && status < 422) { if (status >= 404 && status < 422) {
dispatch(routerRedux.push('/exception/404')); push('/404');
} }
}); });
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment