diff --git a/.roadhogrc.js b/.roadhogrc.js index 1f65c6a..9b76d6f 100644 --- a/.roadhogrc.js +++ b/.roadhogrc.js @@ -7,17 +7,17 @@ const svgSpriteDirs = [ ] export default { - entry : 'src/index.js', - svgSpriteLoaderDirs : svgSpriteDirs, - theme : "./theme.config.js", - publicPath : `/${version}/`, - outputPath : `./dist/${version}`, + entry: 'src/index.js', + svgSpriteLoaderDirs: svgSpriteDirs, + theme: "./theme.config.js", + publicPath: `/${version}/`, + outputPath: `./dist/${version}`, // 接口代理示例 proxy: { "/api/v1/weather": { "target": "https://api.seniverse.com/", "changeOrigin": true, - "pathRewrite": { "^/api/v1/weather" : "/v3/weather" } + "pathRewrite": { "^/api/v1/weather": "/v3/weather" } }, // "/api/v2": { // "target": "http://192.168.0.110", @@ -25,7 +25,7 @@ export default { // "pathRewrite": { "^/api/v2" : "/api/v2" } // } }, - env : { + env: { development: { extraBabelPlugins: [ "dva-hmr", @@ -50,8 +50,8 @@ export default { ] } }, - dllPlugin : { - exclude: ["babel-runtime"], + dllPlugin: { + exclude: ["babel-runtime", "roadhog", "cross-env"], include: ["dva/router", "dva/saga", "dva/fetch"] } } diff --git a/package.json b/package.json index 46f0232..653f5c6 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,13 @@ "axios": "^0.16.2", "babel-polyfill": "^6.23.0", "classnames": "^2.2.5", + "cross-env": "^5.0.5", "d3-shape": "^1.2.0", "draftjs-to-markdown": "^0.4.0", - "dva": "^1.2.0", + "dva": "^2.0.1", "dva-loading": "^0.2.0", "ejs-loader": "^0.3.0", + "history": "^4.7.2", "js-beautify": "^1.6.14", "jsonp": "^0.2.1", "less-vars-to-js": "^1.1.2", @@ -21,6 +23,7 @@ "path-to-regexp": "^1.7.0", "prop-types": "^15.5.10", "qs": "^6.5.0", + "query-string": "^5.0.0", "rc-tween-one": "^1.3.1", "react": "^15.6.1", "react-countup": "^2.1.1", @@ -48,11 +51,13 @@ "eslint-plugin-react": "^7.1.0", "html-webpack-plugin": "^2.29.0", "redbox-react": "^1.2.10", - "roadhog": "^1.2.1" + "roadhog": "^1.2.2" }, - "pre-commit": ["lint"], + "pre-commit": [ + "lint" + ], "scripts": { - "dev": "set BROWSER=none&&set HOST=0.0.0.0&&roadhog server", + "dev": "cross-env BROWSER=none HOST=0.0.0.0 roadhog server", "lint": "eslint --fix --ext .js src", "build": "roadhog build", "build:dll": "roadhog buildDll", diff --git a/src/components/Layout/Bread.js b/src/components/Layout/Bread.js index ad4d5b5..be05ef4 100644 --- a/src/components/Layout/Bread.js +++ b/src/components/Layout/Bread.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Breadcrumb, Icon } from 'antd' -import { Link } from 'dva/router' +import { LinkWrapper } from 'components' import pathToRegexp from 'path-to-regexp' import { queryArray } from 'utils' import styles from './Bread.less' @@ -48,9 +48,9 @@ const Bread = ({ menu, location }) => { return ( {((pathArray.length - 1) !== key) - ? + ? {content} - + : content} ) diff --git a/src/components/Layout/Menu.js b/src/components/Layout/Menu.js index 3662b87..60e42ff 100644 --- a/src/components/Layout/Menu.js +++ b/src/components/Layout/Menu.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Menu, Icon } from 'antd' -import { Link } from 'dva/router' +import { LinkWrapper } from 'components' import { arrayToTree, queryArray } from 'utils' import pathToRegexp from 'path-to-regexp' @@ -31,10 +31,10 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp } return ( - + {item.icon && } {(!siderFoldN || !menuTree.includes(item)) && item.name} - + ) }) diff --git a/src/components/LinkWrapper/index.js b/src/components/LinkWrapper/index.js new file mode 100644 index 0000000..320e315 --- /dev/null +++ b/src/components/LinkWrapper/index.js @@ -0,0 +1,10 @@ +import { Link } from 'react-router-dom' + +export default (props) => { + const Component = props.to ? Link : 'a' + return ( + + {props.children} + + ) +} diff --git a/src/components/Loader/Loader.js b/src/components/Loader/Loader.js index fe24a19..2d2943f 100644 --- a/src/components/Loader/Loader.js +++ b/src/components/Loader/Loader.js @@ -3,8 +3,11 @@ import PropTypes from 'prop-types' import classNames from 'classnames' import styles from './Loader.less' -const Loader = ({ spinning }) => { - return (
+const Loader = ({ spinning, fullScreen }) => { + return (
LOADING
@@ -15,6 +18,7 @@ const Loader = ({ spinning }) => { Loader.propTypes = { spinning: PropTypes.bool, + fullScreen: PropTypes.bool, } export default Loader diff --git a/src/components/Loader/Loader.less b/src/components/Loader/Loader.less index ba3685a..723402d 100644 --- a/src/components/Loader/Loader.less +++ b/src/components/Loader/Loader.less @@ -1,8 +1,12 @@ +.loader_fullScreen { + position: fixed !important; +} + .loader { display: block; background-color: #fff; width: 100%; - position: fixed; + position: absolute; top: 0; bottom: 0; left: 0; diff --git a/src/components/index.js b/src/components/index.js index 6694a34..2c8a0d6 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -6,6 +6,7 @@ import Editor from './Editor' import FilterItem from './FilterItem' import Loader from './Loader' import * as Layout from './Layout/index.js' +import LinkWrapper from './LinkWrapper' import layer from './layer' @@ -19,4 +20,5 @@ export { FilterItem, Loader, layer, + LinkWrapper, } diff --git a/src/index.js b/src/index.js index 3be2c3c..e880e17 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import { message } from 'antd' import dva from 'dva' import createLoading from 'dva-loading' -import { browserHistory } from 'dva/router' +import createHistory from 'history/createBrowserHistory' import 'babel-polyfill' // 1. Initialize @@ -9,7 +9,7 @@ const app = dva({ ...createLoading({ effects: true, }), - history: browserHistory, + history: createHistory(), onError (error) { message.error(error.message) }, diff --git a/src/models/app.js b/src/models/app.js index c5d0a34..5e2f7a0 100644 --- a/src/models/app.js +++ b/src/models/app.js @@ -7,6 +7,7 @@ import config from 'config' import { EnumRoleType } from 'enums' import { query, logout } from 'services/app' import * as menusService from 'services/menus' +import queryString from 'query-string' const { prefix } = config @@ -41,7 +42,7 @@ export default { type: 'updateState', payload: { locationPathname: location.pathname, - locationQuery: location.query, + locationQuery: queryString.parse(location.search), }, }) }) diff --git a/src/models/post.js b/src/models/post.js index 6ed99a8..1e3c7a1 100644 --- a/src/models/post.js +++ b/src/models/post.js @@ -1,6 +1,7 @@ import modelExtend from 'dva-model-extend' import { query } from 'services/posts' import { pageModel } from 'models/common' +import queryString from 'query-string' export default modelExtend(pageModel, { @@ -13,7 +14,7 @@ export default modelExtend(pageModel, { dispatch({ type: 'query', payload: { status: 2, - ...location.query, + ...queryString.parse(location.search), } }) } }) diff --git a/src/models/user.js b/src/models/user.js index 0a789e7..cfaf1fa 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -4,6 +4,7 @@ import { config } from 'utils' import { create, remove, update } from 'services/user' import * as usersService from 'services/users' import { pageModel } from './common' +import queryString from 'query-string' const { query } = usersService const { prefix } = config @@ -25,7 +26,7 @@ export default modelExtend(pageModel, { if (location.pathname === '/user') { dispatch({ type: 'query', - payload: location.query, + payload: queryString.parse(location.search), }) } }) diff --git a/src/router.js b/src/router.js index ec8f046..4aef55a 100644 --- a/src/router.js +++ b/src/router.js @@ -1,149 +1,90 @@ import React from 'react' import PropTypes from 'prop-types' -import { Router } from 'dva/router' +import { Router, Switch, Route, Redirect, routerRedux } from 'dva/router' +import dynamic from 'dva/dynamic' import App from 'routes/app' +import { Loader } from 'components' -const registerModel = (app, model) => { - if (!(app._models.filter(m => m.namespace === model.namespace).length === 1)) { - app.model(model) - } -} +const { ConnectedRouter } = routerRedux const Routers = function ({ history, app }) { + const error = dynamic({ + app, + component: () => import('./routes/error'), + }) const routes = [ { - path: '/', - component: App, - getIndexRoute (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/dashboard')) - cb(null, { component: require('routes/dashboard/') }) - }, 'dashboard') - }, - childRoutes: [ - { - path: 'dashboard', - getComponent (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/dashboard')) - cb(null, require('routes/dashboard/')) - }, 'dashboard') - }, - }, { - path: 'user', - getComponent (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/user')) - cb(null, require('routes/user/')) - }, 'user') - }, - }, { - path: 'user/:id', - getComponent (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/user/detail')) - cb(null, require('routes/user/detail/')) - }, 'user-detail') - }, - }, { - path: 'login', - getComponent (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/login')) - cb(null, require('routes/login/')) - }, 'login') - }, - }, { - path: 'request', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/request/')) - }, 'request') - }, - }, { - path: 'UIElement/iconfont', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/iconfont/')) - }, 'UIElement-iconfont') - }, - }, { - path: 'UIElement/search', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/search/')) - }, 'UIElement-search') - }, - }, { - path: 'UIElement/dropOption', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/dropOption/')) - }, 'UIElement-dropOption') - }, - }, { - path: 'UIElement/layer', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/layer/')) - }, 'UIElement-layer') - }, - }, { - path: 'UIElement/dataTable', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/dataTable/')) - }, 'UIElement-dataTable') - }, - }, { - path: 'UIElement/editor', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/UIElement/editor/')) - }, 'UIElement-editor') - }, - }, { - path: 'chart/lineChart', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/chart/lineChart/')) - }, 'chart-lineChart') - }, - }, { - path: 'chart/barChart', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/chart/barChart/')) - }, 'chart-barChart') - }, - }, { - path: 'chart/areaChart', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/chart/areaChart/')) - }, 'chart-areaChart') - }, - }, { - path: 'post', - getComponent (nextState, cb) { - require.ensure([], (require) => { - registerModel(app, require('models/post')) - cb(null, require('routes/post/')) - }, 'post') - }, - }, { - path: '*', - getComponent (nextState, cb) { - require.ensure([], (require) => { - cb(null, require('routes/error/')) - }, 'error') - }, - }, - ], + path: '/dashboard', + models: () => [import('./models/dashboard')], + component: () => import('./routes/dashboard/'), + }, { + path: '/user', + models: () => [import('./models/user')], + component: () => import('./routes/user/'), + }, { + path: '/user/:id', + models: () => [import('./models/user/detail')], + component: () => import('./routes/user/detail/'), + }, { + path: '/login', + models: () => [import('./models/login')], + component: () => import('./routes/login/'), + }, { + path: '/request', + component: () => import('./routes/request/'), + }, { + path: '/UIElement/iconfont', + component: () => import('./routes/UIElement/iconfont/'), + }, { + path: '/UIElement/search', + component: () => import('./routes/UIElement/search/'), + }, { + path: '/UIElement/dropOption', + component: () => import('./routes/UIElement/dropOption/'), + }, { + path: '/UIElement/layer', + component: () => import('./routes/UIElement/layer/'), + }, { + path: '/UIElement/dataTable', + component: () => import('./routes/UIElement/dataTable/'), + }, { + path: '/UIElement/editor', + component: () => import('./routes/UIElement/editor/'), + }, { + path: '/chart/lineChart', + component: () => import('./routes/chart/lineChart/'), + }, { + path: '/chart/barChart', + component: () => import('./routes/chart/barChart/'), + }, { + path: '/chart/areaChart', + component: () => import('./routes/chart/areaChart/'), + }, { + path: '/post', + models: () => [import('./models/post')], + component: () => import('./routes/post/'), }, ] - return + return ( + + + + ()} /> + { + routes.map(({ path, ...dynamics }, key) => ( + (), + ...dynamics + })} /> + )) + } + + + + + ) } Routers.propTypes = { diff --git a/src/routes/app.js b/src/routes/app.js index 9e75aad..5569caa 100644 --- a/src/routes/app.js +++ b/src/routes/app.js @@ -10,6 +10,7 @@ import { Helmet } from 'react-helmet' import '../themes/index.less' import './app.less' import Error from './error' +import { withRouter } from 'dva/router' const { prefix, openPages } = config @@ -40,16 +41,16 @@ const App = ({ children, dispatch, app, loading, location }) => { isNavbar, menuPopoverVisible, navOpenKeys, - switchMenuPopover () { + switchMenuPopover() { dispatch({ type: 'app/switchMenuPopver' }) }, - logout () { + logout() { dispatch({ type: 'app/logout' }) }, - switchSider () { + switchSider() { dispatch({ type: 'app/switchSider' }) }, - changeOpenKeys (openKeys) { + changeOpenKeys(openKeys) { dispatch({ type: 'app/handleNavOpenKeys', payload: { navOpenKeys: openKeys } }) }, } @@ -60,10 +61,10 @@ const App = ({ children, dispatch, app, loading, location }) => { siderFold, darkTheme, navOpenKeys, - changeTheme () { + changeTheme() { dispatch({ type: 'app/switchTheme' }) }, - changeOpenKeys (openKeys) { + changeOpenKeys(openKeys) { window.localStorage.setItem(`${prefix}navOpenKeys`, JSON.stringify(openKeys)) dispatch({ type: 'app/handleNavOpenKeys', payload: { navOpenKeys: openKeys } }) }, @@ -75,13 +76,13 @@ const App = ({ children, dispatch, app, loading, location }) => { } if (openPages && openPages.includes(pathname)) { return (
- + {children}
) } return (
- + ANTD ADMIN @@ -116,4 +117,4 @@ App.propTypes = { loading: PropTypes.object, } -export default connect(({ app, loading }) => ({ app, loading }))(App) +export default withRouter(connect(({ app, loading }) => ({ app, loading }))(App)) diff --git a/src/routes/user/List.js b/src/routes/user/List.js index e80c2b5..8f43f5d 100644 --- a/src/routes/user/List.js +++ b/src/routes/user/List.js @@ -3,13 +3,16 @@ import PropTypes from 'prop-types' import { Table, Modal } from 'antd' import classnames from 'classnames' import { DropOption } from 'components' -import { Link } from 'dva/router' +import { LinkWrapper } from 'components' import AnimTableBody from '../../components/DataTable/AnimTableBody' +import queryString from 'query-string' import styles from './List.less' const confirm = Modal.confirm const List = ({ onDeleteItem, onEditItem, isMotion, location, ...tableProps }) => { + location.query = queryString.parse(location.search) + const handleMenuClick = (record, e) => { if (e.key === '1') { onEditItem(record) @@ -35,7 +38,7 @@ const List = ({ onDeleteItem, onEditItem, isMotion, location, ...tableProps }) = title: 'Name', dataIndex: 'name', key: 'name', - render: (text, record) => {text}, + render: (text, record) => {text}, }, { title: 'NickName', dataIndex: 'nickName', diff --git a/src/routes/user/index.js b/src/routes/user/index.js index df64acd..258899d 100644 --- a/src/routes/user/index.js +++ b/src/routes/user/index.js @@ -6,8 +6,10 @@ import { Row, Col, Button, Popconfirm } from 'antd' import List from './List' import Filter from './Filter' import Modal from './Modal' +import queryString from 'query-string' const User = ({ location, dispatch, user, loading }) => { + location.query = queryString.parse(location.search) const { list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys } = user const { pageSize } = pagination