├── src
├── scripts
│ ├── actions
│ │ ├── sysmanage
│ │ │ ├── SysUsers.js
│ │ │ ├── SysIndex.js
│ │ │ └── SysProjects.js
│ │ ├── index.js
│ │ └── myprojects
│ │ │ └── MyIndex.js
│ ├── reducers
│ │ ├── myprojects
│ │ │ ├── MyProjects.js
│ │ │ └── MyIndex.js
│ │ ├── index.js
│ │ └── sysmanage
│ │ │ ├── SysProjects.js
│ │ │ └── SysIndex.js
│ ├── services
│ │ ├── ProjectService.js
│ │ └── projects.json
│ ├── store
│ │ └── index.js
│ ├── index.js
│ ├── components
│ │ ├── common
│ │ │ ├── roles
│ │ │ │ └── Roles.js
│ │ │ ├── resources
│ │ │ │ ├── ResAPI.js
│ │ │ │ ├── ResURL.js
│ │ │ │ ├── ResInput.js
│ │ │ │ ├── ResourceList.js
│ │ │ │ └── Resources.js
│ │ │ ├── users
│ │ │ │ ├── UserInfoDialog.js
│ │ │ │ ├── UserInfo.js
│ │ │ │ ├── UserList.js
│ │ │ │ └── Users.js
│ │ │ ├── ProjectCreate.js
│ │ │ ├── ProjectList.js
│ │ │ ├── NavBar.js
│ │ │ └── projects
│ │ │ │ └── ProjectInfo.js
│ │ ├── myprojects
│ │ │ ├── MyProjects.js
│ │ │ └── MyIndex.js
│ │ ├── sysmanage
│ │ │ ├── SysProjects.js
│ │ │ └── SysIndex.js
│ │ └── header
│ │ │ └── Header.js
│ ├── constants
│ │ ├── ActionTypes.js
│ │ └── Links.js
│ ├── containers
│ │ └── App.js
│ ├── common
│ │ ├── utils
│ │ │ ├── HistoryFly.js
│ │ │ └── ReduxConnect.js
│ │ └── ui
│ │ │ ├── ToolBar.js
│ │ │ ├── DropSelect.js
│ │ │ ├── DataTable.js
│ │ │ └── Dialog.js
│ └── AppRouter.js
└── styles
│ ├── components
│ ├── projects
│ │ ├── project.css
│ │ └── projects.css
│ ├── resources
│ │ └── resource.css
│ ├── users
│ │ └── users.css
│ └── header
│ │ ├── header.css
│ │ └── navbar.css
│ ├── common
│ ├── index.css
│ ├── optsbar.css
│ ├── breadcrumb.css
│ └── toolbar.css
│ ├── containers
│ └── app.css
│ └── index.css
├── README.md
├── html
└── index.html
├── .gitignore
├── server.js
├── webpack.server.js
├── pom.xml
├── webpack.dll.js
├── package.json
├── webpack.prod.js
├── webpack.base.js
├── webpack.dev.js
└── dll
└── vendors_manifest.json
/src/scripts/actions/sysmanage/SysUsers.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scripts/reducers/myprojects/MyProjects.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/components/projects/project.css:
--------------------------------------------------------------------------------
1 | .project-wrap {
2 | flex: 1;
3 | display: flex;
4 | flex-direction: column;
5 | }
--------------------------------------------------------------------------------
/src/styles/common/index.css:
--------------------------------------------------------------------------------
1 | @charset 'utf-8';
2 |
3 | @import './toolbar.css';
4 | @import './optsbar.css';
5 | @import './breadcrumb.css';
--------------------------------------------------------------------------------
/src/styles/common/optsbar.css:
--------------------------------------------------------------------------------
1 | $proj-toolbar: 60px;
2 |
3 | .opts-bar {
4 | height: $proj-toolbar;
5 | line-height: $proj-toolbar;
6 | background: #edf1f2;
7 | border-bottom: 1px solid #dee5e7;
8 | padding-left: 20px;
9 | }
--------------------------------------------------------------------------------
/src/scripts/actions/index.js:
--------------------------------------------------------------------------------
1 | import * as SysIndex from './sysmanage/SysIndex';
2 | import * as SysProjects from './sysmanage/SysProjects';
3 | import * as MyIndex from './myprojects/MyIndex';
4 |
5 | export default {
6 | SysIndex,
7 | SysProjects,
8 | MyIndex
9 | }
--------------------------------------------------------------------------------
/src/scripts/actions/sysmanage/SysIndex.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 |
3 | /**
4 | * 系统管理 -- 切换导航
5 | * @param {[type]} curNavId 当前点击的导航的 ID
6 | * @return {[type]} [description]
7 | */
8 | export function switchNavItem (curNavId) {
9 | return {
10 | type: act.SYS_SWITCH_NAV,
11 | curNavId
12 | };
13 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ###FE project seed
2 | webpack + reactjs + redux + postcss
3 | ###local dev environment
4 | node >=4.4.7
5 | npm >=2.15.8
6 | ###project initialize
7 | npm run init
8 | ###run project
9 | open one command window and run (project root dir) : node server
10 | open another command window and run (project root dir) : npm run dev
--------------------------------------------------------------------------------
/src/scripts/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 |
3 | import SysProjects from './sysmanage/SysProjects';
4 | import SysIndex from './sysmanage/SysIndex';
5 | import MyIndex from './myprojects/MyIndex';
6 |
7 | const rootReducer = combineReducers({
8 | SysIndex,
9 | SysProjects,
10 | MyIndex
11 | });
12 |
13 | export default rootReducer;
--------------------------------------------------------------------------------
/src/scripts/actions/sysmanage/SysProjects.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 | import ProjectService from 'services/ProjectService';
3 |
4 |
5 | // 获取项目列表
6 | export function fetchProjects () {
7 | return (dispatch) => {
8 | ProjectService.getProjects().then(projects => {
9 | dispatch({
10 | type: act.SYS_FETCH_PROJECTS,
11 | projects
12 | });
13 | });
14 | };
15 | }
--------------------------------------------------------------------------------
/src/scripts/services/ProjectService.js:
--------------------------------------------------------------------------------
1 | import projectData from './projects.json';
2 |
3 | const TIMEOUT = 100;
4 |
5 | export default {
6 |
7 | // 获取所有的项目
8 | getProjects() {
9 | return new Promise((resolve) => {
10 | setTimeout(() => { resolve(projectData.data); }, TIMEOUT);
11 | });
12 | },
13 |
14 | // 新增项目
15 | addProject(data, cb) {
16 | setTimeout(() => cb(), TIMEOUT);
17 | }
18 |
19 | };
--------------------------------------------------------------------------------
/src/scripts/store/index.js:
--------------------------------------------------------------------------------
1 | const { createStore, applyMiddleware } = Redux;
2 | const thunk = ReduxThunk.default;
3 | import createLogger from 'redux-logger';
4 | import rootReducer from '../reducers';
5 |
6 | export default function configureStore(preloadedState) {
7 | const store = createStore(
8 | rootReducer,
9 | preloadedState,
10 | applyMiddleware(thunk, createLogger())
11 | );
12 |
13 | return store;
14 | }
--------------------------------------------------------------------------------
/src/styles/containers/app.css:
--------------------------------------------------------------------------------
1 | .pageframe-wrap {
2 | height: 100%;
3 | display: flex;
4 | flex-direction: column;
5 |
6 | a {
7 | color: inherit;
8 | }
9 |
10 | @import '../components/header/header.css';
11 | @import '../components/header/navbar.css';
12 | @import '../components/projects/projects.css';
13 | @import '../components/projects/project.css';
14 | @import '../components/users/users.css';
15 | }
--------------------------------------------------------------------------------
/src/scripts/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 入口文件
3 | */
4 |
5 | // 引入样式
6 | import 'styles/index.css';
7 |
8 | // 引入 provider 组件
9 | const { Provider } = ReactRedux;
10 |
11 | // redux store
12 | import configureStore from './store';
13 | import AppRouter from './AppRouter';
14 |
15 | const store = configureStore();
16 |
17 | // 渲染页面
18 | ReactDOM.render((
19 |
20 |
21 |
22 | ), document.querySelector('.main'));
--------------------------------------------------------------------------------
/src/styles/components/resources/resource.css:
--------------------------------------------------------------------------------
1 | .resource-wrap {
2 | display: flex;
3 | flex-direction: column;
4 |
5 | .reso-header {
6 | height: 49px;
7 | padding-left: 10px;
8 | background: #edf1f2;
9 | border-bottom: 1px solid #b9b9b9;
10 |
11 | .ant-menu {
12 | margin-top: 1px;
13 | background: #edf1f2;
14 | }
15 | }
16 |
17 | .reso-body {
18 | flex: 1;
19 | padding: 10px;
20 | }
21 | }
--------------------------------------------------------------------------------
/src/scripts/components/common/roles/Roles.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 |
5 | // import Component from './Component';
6 |
7 |
8 | export default class Roles extends React.Component {
9 |
10 | defaultProps = {
11 |
12 | }
13 |
14 | state = {
15 |
16 | }
17 |
18 | constructor() {
19 | super();
20 | }
21 |
22 | render() {
23 | return (
24 |
Roles
25 | );
26 | }
27 |
28 | componentDidMount() {
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | demo
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/scripts/components/common/resources/ResAPI.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 |
5 | // import Component from './Component';
6 |
7 |
8 | export default class ResAPI extends React.Component {
9 |
10 | static defaultProps = {
11 |
12 | }
13 |
14 | state = {
15 |
16 | }
17 |
18 | constructor() {
19 | super();
20 | }
21 |
22 | render() {
23 | return (
24 | ResAPI
25 | );
26 | }
27 |
28 | componentDidMount() {
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/scripts/components/common/resources/ResURL.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 |
5 | // import Component from './Component';
6 |
7 |
8 | export default class ResURL extends React.Component {
9 |
10 | static defaultProps = {
11 |
12 | }
13 |
14 | state = {
15 |
16 | }
17 |
18 | constructor() {
19 | super();
20 | }
21 |
22 | render() {
23 | return (
24 | ResURL
25 | );
26 | }
27 |
28 | componentDidMount() {
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/scripts/components/common/resources/ResInput.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 |
5 | // import Component from './Component';
6 |
7 |
8 | export default class ResInput extends React.Component {
9 |
10 | static defaultProps = {
11 |
12 | }
13 |
14 | state = {
15 |
16 | }
17 |
18 | constructor() {
19 | super();
20 | }
21 |
22 | render() {
23 | return (
24 | ResInput
25 | );
26 | }
27 |
28 | componentDidMount() {
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/scripts/constants/ActionTypes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 项目中所有的 action type
3 | * @type {String}
4 | */
5 |
6 | // SysMange action
7 | export const SYS_SWITCH_NAV = 'SYS_SWITCH_NAV'; // 切换导航按钮
8 |
9 | // SysProjects action
10 | export const SYS_FETCH_PROJECTS = 'SYS_FETCH_PROJECTS'; // 获取项目列表
11 |
12 | // MyProjects action
13 | export const MY_SWITCH_PROJECT = 'MY_SWITCH_PROJECT'; // 切换我的项目
14 | export const MY_FETCH_PROJECTS = 'MY_FETCH_PROJECTS'; // 获取我的项目列表
15 | export const MY_SWITCH_NAV = 'MY_SWITCH_NAV'; // 我的项目切换导航
16 |
17 |
--------------------------------------------------------------------------------
/src/scripts/containers/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import * as actions from 'actions';
5 | import Header from 'components/header/Header';
6 |
7 |
8 | export default class App extends React.Component {
9 |
10 | constructor() {
11 | super()
12 | }
13 |
14 | render() {
15 | return (
16 |
17 |
18 | { this.props.children }
19 |
20 | );
21 | }
22 |
23 | componentDidMount() {
24 |
25 | }
26 |
27 | }
28 |
29 | export default App;
--------------------------------------------------------------------------------
/src/scripts/common/utils/HistoryFly.js:
--------------------------------------------------------------------------------
1 | let { browserHistory } = ReactRouter;
2 |
3 |
4 | export default {
5 | /**
6 | * 跳转到指定的路径下
7 | * @param {[type]} path [description]
8 | * @param {[type]} id [description]
9 | * @return {[type]} [description]
10 | */
11 | go (path, id) {
12 | if (id) {
13 | path = path.replace(':id', id);
14 | }
15 | browserHistory.push(path);
16 | },
17 |
18 | back () {
19 | browserHistory.goBack();
20 | },
21 |
22 | forward () {
23 | browserHistory.goForward();
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /dev/
2 | /prd/
3 | /refs/
4 |
5 |
6 | # kdiff3 ignore
7 | *.orig
8 |
9 | # maven ignore
10 | target/
11 |
12 | # eclipse ignore
13 | .settings/
14 | .project
15 | .classpath
16 |
17 | # idea ignore
18 | .idea/
19 | *.ipr
20 | *.iml
21 | *.iws
22 |
23 | # temp ignore
24 | *.log
25 | *.cache
26 | *.diff
27 | *.patch
28 | *.tmp
29 |
30 | # system ignore
31 | .DS_Store
32 | Thumbs.db
33 |
34 | # package ignore (optional)
35 | # *.jar
36 | # *.war
37 | # *.zip
38 | # *.tar
39 | # *.tar.gz
40 |
41 |
42 | .sass-cache
43 | /resource/
44 | /log/
45 | /node_modules/
--------------------------------------------------------------------------------
/src/styles/common/breadcrumb.css:
--------------------------------------------------------------------------------
1 | .breadcrumb {
2 | height: $proj-breadcrumb-h;
3 | line-height: $proj-breadcrumb-h;
4 | background: $dark-bgc;
5 | padding-left: 30px;
6 | color: $light-bgc;
7 |
8 | .proj-breadcrumb {
9 | span {
10 | padding: 0 3px;
11 | }
12 | .breadcrumb-arrow .anticon {
13 | opacity: 0.5;
14 | transform: scale(0.8);
15 | }
16 | .breadcrumb-home {
17 | cursor: pointer;
18 | .anticon {
19 | font-weight: bold;
20 | cursor: pointer;
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/scripts/constants/Links.js:
--------------------------------------------------------------------------------
1 | export const MY_PROJECTS = '/page/myprojects';
2 | export const MY_PROJECT_HREF = '/page/myprojects/:id';
3 | export const MY_PROJECT_USERS = '/page/myprojects/:id/users';
4 | export const MY_PROJECT_ROLES = '/page/myprojects/:id/roles';
5 | export const MY_PROJECT_RESOURCES = '/page/myprojects/:id/resources';
6 |
7 | export const SYS_MANAGE = '/page/sysmanage';
8 | export const SYS_PROJECTS = '/page/sysmanage/projects';
9 | export const SYS_USERS = '/page/sysmanage/users';
10 | export const SYS_ROLES = '/page/sysmanage/roles';
11 | export const SYS_RESOURCES = '/page/sysmanage/resources';
12 |
--------------------------------------------------------------------------------
/src/scripts/services/projects.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": [
3 | {
4 | "key": "p001",
5 | "title": "项目一运营专题活动系统系统系同学他",
6 | "userCount": 100,
7 | "roleCount": 10,
8 | "resourceCount": 200
9 | },
10 | {
11 | "key": "p002",
12 | "title": "项目2",
13 | "userCount": 120,
14 | "roleCount": 12,
15 | "resourceCount": 220
16 | },
17 | {
18 | "key": "p003",
19 | "title": "项目3",
20 | "userCount": 130,
21 | "roleCount": 13,
22 | "resourceCount": 230
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/src/styles/components/users/users.css:
--------------------------------------------------------------------------------
1 | $user-info-w: 300px;
2 |
3 | .user-wrap {
4 | flex: 1;
5 | display: flex;
6 | flex-direction: column;
7 |
8 | .user-list-wrap {
9 | flex: 1;
10 | position: relative;
11 |
12 | .user-list {
13 | position: absolute;
14 | width: 100%;
15 | top: 0;
16 | bottom: 0;
17 | padding: 0 15px;
18 | overflow-y: scroll;
19 | background: $user-list-bgc;
20 | }
21 | }
22 | }
23 |
24 | .user-info {
25 | position: absolute;
26 | right: 0;
27 | width: $user-info-w;
28 | height: 100%;
29 | padding: 15px;
30 | background: #eee;
31 | }
--------------------------------------------------------------------------------
/src/styles/index.css:
--------------------------------------------------------------------------------
1 | @charset 'UTF-8';
2 |
3 | /*公共库*/
4 | @import './libs/antd.css';
5 |
6 | /*设置全局样式*/
7 | html, body, .main {
8 | width: 100%;
9 | height: 100%;
10 | color: #58666e;
11 | }
12 |
13 | /*主题颜色*/
14 | $dark-bgc: #1c2b36;
15 | $dark-ftc: #7793a7;
16 | $light-bgc: #edf1f2;
17 | $nav-ftc: #869fb1;
18 | $nav-hover-bgc: #16232d;
19 | $nav-active-bgc: #131e26;
20 | $proj-breadcrumb-h: 50px;
21 | $pf-toolbar-h: 60px; /*导航栏的高度*/
22 |
23 | /*自定义公共组件*/
24 | @import './common/index.css';
25 |
26 | /*容器*/
27 | @import './containers/app.css';
28 |
29 | /*设置滚动条样式*/
30 | ::-webkit-scrollbar {
31 | width: 3px;
32 | }
33 |
34 | ::-webkit-scrollbar-thumb:vertical {
35 | background-color: #bbb;
36 | }
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 | var fs = require('fs');
3 |
4 | var port = 3001;
5 |
6 |
7 | http.createServer(function (req, res) {
8 | console.log('access: ' + req.url);
9 |
10 | // will get you '/' or 'index.html' or 'css/styles.css' ...
11 | // • you need to isolate extension
12 | // • have a small mimetype lookup array/object
13 | // • only there and then reading the file
14 | // • delivering it after setting the right content type
15 | fs.readFile('./html/index.html', 'utf8', function(err, data) {
16 | res.writeHead(200, {'Content-Type': 'text/html'});
17 | res.end(data);
18 | });
19 |
20 | }).listen(port);
21 |
22 | console.log("listening on port " + port)
--------------------------------------------------------------------------------
/src/scripts/components/common/users/UserInfoDialog.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import Dialog from 'common/ui/Dialog';
5 | import UserInfo from './UserInfo';
6 |
7 | let { Button, Form } = Antd;
8 |
9 |
10 | export default class UserInfoDialog extends React.Component {
11 |
12 | static defaultProps = {
13 |
14 | }
15 |
16 | state = {
17 |
18 | }
19 |
20 | constructor() {
21 | super();
22 | }
23 |
24 | render() {
25 | let UserInfoForm = Form.create({})(UserInfo);
26 |
27 | return (
28 |
31 | );
32 | }
33 |
34 | componentDidMount() {
35 |
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/scripts/components/common/resources/ResourceList.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Table } = Antd;
5 |
6 |
7 | export default class ResourceList extends React.Component {
8 |
9 | static defaultProps = {
10 | columns: [],
11 | data: [],
12 | rowSelection: {}
13 | }
14 |
15 | state = {
16 |
17 | }
18 |
19 | constructor() {
20 | super();
21 | }
22 |
23 | render() {
24 | let columns = this.props.columns,
25 | rowSelection = this.props.rowSelection,
26 | data = this.props.data;
27 | return (
28 |
29 | );
30 | }
31 |
32 | componentDidMount() {
33 |
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/scripts/reducers/sysmanage/SysProjects.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 |
3 | const initialState = {
4 | projects: []
5 | };
6 |
7 | const Reducers = {
8 |
9 | // 获取项目列表
10 | [act.SYS_FETCH_PROJECTS] (state, action) {
11 | return Object.assign({}, state, {
12 | projects: action.projects
13 | })
14 | }
15 |
16 | };
17 |
18 | /**
19 | * 根据 actionType 调用对应的 reducer
20 | * @param {[type]} state [description]
21 | * @param {[type]} action [description]
22 | * @return {[type]} [description]
23 | */
24 | export default function SysProjects (state = initialState, action) {
25 | let reducer = Reducers[action.type];
26 | if (reducer) {
27 | return reducer(state, action);
28 | }
29 | else {
30 | return state;
31 | }
32 | }
--------------------------------------------------------------------------------
/webpack.server.js:
--------------------------------------------------------------------------------
1 | var webpackConfig = require('./webpack.dev.js');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var webpack = require('webpack');
4 | var open = require('open');
5 |
6 | var serverPath = 'http://127.0.0.1:3001';
7 | var webpackServer = 'http://127.0.0.1:3000/';
8 |
9 | new WebpackDevServer(webpack(webpackConfig), {
10 | // contentBase: serverPath,
11 | publicPath: webpackConfig.output.publicPath,
12 | hot: true,
13 | noInfo: false,
14 | historyApiFallback: true,
15 | proxy: {
16 | "\/$|\/page\/?|\/page\/.*|\/api\/.*": serverPath
17 | }
18 | }).listen(3000, 'localhost', function(err) {
19 | if (err) console.log(err);
20 | console.log('Listening at localhost:' + webpackServer);
21 | console.log('Opening your system browser...');
22 | open(webpackServer);
23 | });
--------------------------------------------------------------------------------
/src/scripts/components/myprojects/MyProjects.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import actions from 'actions'
5 | import ProjectList from 'components/common/ProjectList';
6 |
7 |
8 | class MyProjects extends React.Component {
9 |
10 | static mapToRedux = {
11 | mapStateToProps: state => ({
12 | projects: state.MyIndex.projects
13 | }),
14 | mapDispatchToProps: {
15 | fetchProjects: actions.MyIndex.fetchProjects
16 | }
17 | };
18 |
19 | static defaultProps = {
20 | projects: []
21 | }
22 |
23 | constructor() {
24 | super();
25 | }
26 |
27 | render() {
28 | const { projects } = this.props;
29 | return (
30 |
31 | );
32 | }
33 |
34 | componentDidMount() {
35 | // 执行获取项目列表的 action
36 | this.props.fetchProjects();
37 | }
38 |
39 | }
40 |
41 | export default ReduxConnect(MyProjects);
--------------------------------------------------------------------------------
/src/scripts/components/sysmanage/SysProjects.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import actions from 'actions'
5 | import ProjectList from 'components/common/ProjectList';
6 |
7 |
8 | class SysProjects extends React.Component {
9 |
10 | static mapToRedux = {
11 | mapStateToProps: state => ({
12 | projects: state.SysProjects.projects
13 | }),
14 | mapDispatchToProps: {
15 | fetchProjects: actions.SysProjects.fetchProjects
16 | }
17 | };
18 |
19 | static defaultProps = {
20 | projects: []
21 | }
22 |
23 | constructor() {
24 | super();
25 | }
26 |
27 | render() {
28 | const { projects } = this.props;
29 |
30 | return (
31 |
32 | );
33 | }
34 |
35 | componentDidMount() {
36 | // 执行获取项目列表的 action
37 | this.props.fetchProjects();
38 | }
39 |
40 | }
41 |
42 | export default ReduxConnect(SysProjects);
--------------------------------------------------------------------------------
/src/scripts/actions/myprojects/MyIndex.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 | import ProjectService from 'services/ProjectService';
3 |
4 | /**
5 | * 我的项目 - 我的项目列表
6 | * @param {[type]} curProjectId 当前选中的项目 ID
7 | * @return {[type]} [description]
8 | */
9 | export function switchProject (curProjectId) {
10 | return {
11 | type: act.MY_SWITCH_PROJECT,
12 | curProjectId
13 | };
14 | }
15 |
16 | /**
17 | * 我的项目 - 获取项目列表
18 | * @return {[type]} [description]
19 | */
20 | export function fetchProjects () {
21 | return (dispatch) => {
22 | ProjectService.getProjects().then(projects => {
23 | dispatch({
24 | type: act.MY_FETCH_PROJECTS,
25 | projects
26 | });
27 | });
28 | };
29 | }
30 |
31 | /**
32 | * 我的项目 - 切换导航
33 | * @param {[type]} curNavId 当前点击的导航的 ID
34 | * @return {[type]} [description]
35 | */
36 | export function switchNavItem (curNavId) {
37 | return {
38 | type: act.MY_SWITCH_NAV,
39 | curNavId
40 | };
41 | }
--------------------------------------------------------------------------------
/src/scripts/components/common/users/UserInfo.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Button, Form, Input } = Antd;
5 | const FormItem = Form.Item;
6 |
7 |
8 | export default class UserInfo extends React.Component {
9 |
10 | static defaultProps = {
11 |
12 | }
13 |
14 | state = {
15 |
16 | }
17 |
18 | constructor() {
19 | super();
20 | }
21 |
22 | render() {
23 | let { getFieldProps } = this.props.form;
24 |
25 | let formItemLayout = {
26 | labelCol: { span: 7 },
27 | wrapperCol: { span: 12 }
28 | };
29 |
30 | return (
31 |
39 | );
40 | }
41 |
42 | componentDidMount() {
43 |
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/src/scripts/components/sysmanage/SysIndex.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import actions from 'actions';
5 | import NavBar from 'components/common/NavBar';
6 | const { Icon } = Antd;
7 | const { Link } = ReactRouter;
8 |
9 |
10 | class SysIndex extends React.Component {
11 |
12 | static mapToRedux = {
13 | mapStateToProps: state => ({
14 | curNavId: state.SysIndex.curNavId,
15 | navList: state.SysIndex.navList
16 | }),
17 | mapDispatchToProps: {
18 | switchNavItem: actions.SysIndex.switchNavItem
19 | }
20 | };
21 |
22 | static defaultProps = {
23 | curNavId: '',
24 | navList: []
25 | }
26 |
27 | constructor() {
28 | super();
29 | }
30 |
31 | render() {
32 | const { curNavId, navList, switchNavItem } = this.props;
33 | return (
34 |
35 |
38 | { this.props.children }
39 |
40 | );
41 | }
42 |
43 | componentDidMount() {
44 | }
45 |
46 | }
47 |
48 | export default ReduxConnect(SysIndex);
--------------------------------------------------------------------------------
/src/scripts/components/common/ProjectCreate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 新建项目对话框
3 | */
4 | let { Modal, Button } = Antd;
5 |
6 |
7 | export default class ProjectCreate extends React.Component {
8 |
9 | static defaultProps = {
10 | visible: false,
11 | onSubmit: () => {},
12 | onCancel: () => {},
13 | loading: false
14 | }
15 |
16 | constructor() {
17 | super();
18 | }
19 |
20 | render() {
21 | const { handleOk, handleCancel } = this;
22 | const { visible, loading } = this.props;
23 |
24 | return (
25 | 取消,
29 |
30 | ]}
31 | >
32 | 新建项目
33 |
34 | );
35 | }
36 |
37 | componentDidMount() {
38 | }
39 |
40 | handleOk() {
41 | console.log('ok');
42 | }
43 |
44 | handleCancel() {
45 | console.log('cancel');
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | qunar.common
7 | qunar-supom-qzz
8 | 1.3.2
9 |
10 |
11 | com.qunar.qzz
12 |
13 | *****
14 |
15 | 1.0.0-SNAPSHOT
16 | pom
17 |
18 |
19 |
20 | ver
21 |
22 |
23 |
24 |
25 |
26 | com.github.goldin
27 | copy-maven-plugin
28 |
29 |
30 | org.codehaus.mojo
31 | build-helper-maven-plugin
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/styles/components/projects/projects.css:
--------------------------------------------------------------------------------
1 | $proj-toolbar: 60px;
2 | $proj-item-icon-size: 26px;
3 |
4 | .proj-wrap {
5 | flex: 1;
6 | display: flex;
7 | flex-direction: column;
8 |
9 | .proj-list-wrap {
10 | flex: 1;
11 | display: flex;
12 | flex-direction: column;
13 | }
14 |
15 | .proj-list {
16 | flex: 1;
17 | background: #eaeaea;
18 | border-right: 1px solid #dee5e7;
19 | padding: 10px 0 0 10px;
20 |
21 | .proj-item {
22 | display: inline-block;
23 | width: 260px;
24 | margin: 10px;
25 | }
26 |
27 | .proj-item-ops {
28 | display: inline-block;
29 | overflow: hidden;
30 | .anticon {
31 | width: $proj-item-icon-size;
32 | height: $proj-item-icon-size;
33 | line-height: $proj-item-icon-size;
34 | cursor: pointer;
35 | transition: all 0.3s;
36 |
37 | &:hover {
38 | font-size: 16px;
39 | font-weight: bold;
40 | }
41 | }
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/src/scripts/components/common/users/UserList.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import DataTable from 'common/ui/DataTable';
5 |
6 |
7 | const columns = [
8 | {
9 | title: '登录账号',
10 | dataIndex: 'username',
11 | key: 'username',
12 | // render: name => `${name.first} ${name.last}`,
13 | width: '20%'
14 | },
15 | {
16 | title: '姓名',
17 | sorter: true,
18 | dataIndex: 'name',
19 | key: 'name',
20 | width: '20%'
21 | },
22 | {
23 | title: '状态',
24 | dataIndex: 'status',
25 | key: 'status'
26 | },
27 | {
28 | title: '创建时间',
29 | dataIndex: 'createTime',
30 | key: 'createTime'
31 | }
32 | ];
33 |
34 |
35 | export default class UserList extends React.Component {
36 |
37 | defaultProps = {
38 |
39 | }
40 |
41 | state = {
42 |
43 | }
44 |
45 | constructor() {
46 | super();
47 | }
48 |
49 | render() {
50 | return (
51 |
52 |
53 |
54 | );
55 | }
56 |
57 | componentDidMount() {
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/src/scripts/components/common/users/Users.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Button, Icon } = Antd;
5 |
6 | import UserList from './UserList';
7 | import UserInfoDialog from './UserInfoDialog';
8 |
9 |
10 | export default class Users extends React.Component {
11 |
12 | defaultProps = {
13 |
14 | }
15 |
16 | state = {
17 | userInfoVisible: false
18 | }
19 |
20 | constructor() {
21 | super();
22 | }
23 |
24 | render() {
25 | return (
26 |
27 |
28 |
31 |
32 |
37 |
41 |
42 | );
43 | }
44 |
45 | componentDidMount() {
46 |
47 | }
48 |
49 | btnAddUserClick() {
50 | console.log('22222');
51 | }
52 |
53 | onUserInfoOkClick() {
54 |
55 | }
56 |
57 | onUserInfoCanelClick() {
58 |
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/webpack.dll.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var CleanWebpackPlugin = require('clean-webpack-plugin');
3 | var ProgressPlugin = require('webpack/lib/ProgressPlugin');
4 | var WebpackMd5Hash = require('webpack-md5-hash');
5 | var path = require('path');
6 |
7 |
8 | module.exports = {
9 |
10 | entry: {
11 | vendors: [
12 | 'isomorphic-fetch',
13 | 'react',
14 | 'react-dom',
15 | 'react-router',
16 | 'redux',
17 | 'redux-thunk',
18 | 'react-redux',
19 | 'redux-promise-middleware',
20 | 'antd'
21 | ]
22 | },
23 |
24 | output: {
25 | path: path.resolve('./dll/'),
26 | filename: '[name]@[chunkhash].js',
27 | library: '[name]_[chunkhash]'
28 | },
29 |
30 | plugins: [
31 | new CleanWebpackPlugin(['dll']),
32 | new webpack.DllPlugin({
33 | path: path.resolve('./dll/[name]_manifest.json'),
34 | name: '[name]_[chunkhash]',
35 | context: __dirname
36 | }),
37 | // 压缩 js
38 | // new webpack.optimize.UglifyJsPlugin({
39 | // compress: {
40 | // warnings: false
41 | // }
42 | // }),
43 | // 根据文件内容生成 MD5
44 | new WebpackMd5Hash(),
45 | // 显示进度
46 | new ProgressPlugin(function(percentage, msg) {
47 | console.log(parseInt(percentage * 100) + '%', msg);
48 | })
49 | ]
50 | };
51 |
--------------------------------------------------------------------------------
/src/scripts/common/ui/ToolBar.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | const { Icon } = Antd;
5 | const { Link } = ReactRouter;
6 |
7 |
8 | export default class ToolBar extends React.Component {
9 |
10 | static defaultProps = {
11 | activeKey: '',
12 | toolbarList: [],
13 | onChange: () => {}
14 | }
15 |
16 | constructor() {
17 | super();
18 | }
19 |
20 | render() {
21 | const { activeKey, toolbarList } = this.props;
22 | let className = '', itemKey = '';
23 | let toolbarItems = null;
24 | // 生成导航按钮
25 | if (toolbarList.length > 0) {
26 | toolbarItems = toolbarList.map( item => {
27 | itemKey = item.key;
28 | if (itemKey === activeKey) {
29 | className = 'active';
30 | } else {
31 | className = '';
32 | }
33 | return (
34 |
35 |
36 |
37 | {item.title}
38 |
39 |
40 | );
41 | });
42 | }
43 |
44 | return (
45 |
50 | );
51 | }
52 |
53 | componentDidMount() {
54 | }
55 |
56 | itemClick(itemKey) {
57 | this.props.onChange(itemKey);
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/styles/common/toolbar.css:
--------------------------------------------------------------------------------
1 | .pf-toolbar {
2 | height: $pf-toolbar-h;
3 | background: $dark-bgc;
4 |
5 | .pf-tlb-nav {
6 | line-height: $pf-toolbar-h;
7 |
8 | a {
9 | color: inherit;
10 | }
11 |
12 | .nav-item {
13 | display: inline-block;
14 | height: $pf-toolbar-h;
15 | padding: 0 15px;
16 | color: $nav-ftc;
17 | cursor: pointer;
18 |
19 | .icon {
20 | font-size: 16px;
21 | display: block;
22 | line-height: normal;
23 | padding: 10px;
24 | opacity: .7;
25 | transition: all .3s;
26 |
27 | &.users { color: #457fd6; }
28 | &.roles { color: #c5a42b; }
29 | &.resources { color: #8a62da; }
30 | &.projects { color: #4bbb54; }
31 | }
32 |
33 | .text {
34 | display: block;
35 | line-height: normal;
36 | text-align: center;
37 | color: $nav-ftc;
38 | transition: all .3s;
39 | }
40 |
41 | &.active {
42 | background: $nav-active-bgc;
43 | .icon { opacity: 1; }
44 | .text { color: #fff; }
45 | }
46 |
47 | &:hover {
48 | background: $nav-hover-bgc;
49 | .icon { opacity: 1; }
50 | .text { color: #fff; }
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/scripts/common/ui/DropSelect.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | const { Icon, Menu, Dropdown } = Antd;
5 | const { Link } = ReactRouter;
6 |
7 | export default class DropSelect extends React.Component {
8 |
9 | static defaultProps = {
10 | title: '请选择项目 V',
11 | selectedKey: '',
12 | items: [],
13 | onSelect: () => {}
14 | }
15 |
16 | constructor() {
17 | super();
18 | }
19 |
20 | render() {
21 | const { title, items, selectedKey, onSelect } = this.props;
22 | let selectItem = searchItem(selectedKey, items);
23 | let showTitle = title;
24 | if (selectItem) {
25 | showTitle = selectItem.title;
26 | }
27 |
28 | const menu = (
29 |
40 | );
41 |
42 | return (
43 | document.querySelector('.navbar-title-wrap')}>
44 |
45 | {showTitle}
46 |
47 |
48 | );
49 | }
50 |
51 | componentDidMount() {
52 | }
53 |
54 | }
55 |
56 |
57 | function searchItem (key, items) {
58 | for (var i = 0; i < items.length; i++) {
59 | if(items[i].key === key) {
60 | return items[i];
61 | }
62 | }
63 | return null;
64 | }
--------------------------------------------------------------------------------
/src/scripts/components/myprojects/MyIndex.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import actions from 'actions';
5 |
6 | import MyProjects from 'components/myprojects/MyProjects';
7 | import NavBar from 'components/common/NavBar';
8 | let { Button, Icon, Card } = Antd;
9 |
10 |
11 | class MyIndex extends React.Component {
12 |
13 | static mapToRedux = {
14 | mapStateToProps: state => ({
15 | curProjectId: state.MyIndex.curProjectId,
16 | curNavId: state.MyIndex.curNavId,
17 | projects: state.MyIndex.projects,
18 | navList: state.MyIndex.navList
19 | }),
20 | mapDispatchToProps: {
21 | fetchProjects: actions.MyIndex.fetchProjects,
22 | switchNavItem: actions.MyIndex.switchNavItem,
23 | switchProject: actions.MyIndex.switchProject
24 | }
25 | };
26 |
27 | static defaultProps = {
28 | curProjectId: '',
29 | projects: [],
30 | navList: [],
31 | curNavId: '',
32 | switchProject: () => {}
33 | }
34 |
35 | constructor() {
36 | super();
37 | }
38 |
39 | render() {
40 | const { projects, curProjectId, navList, curNavId, switchNavItem } = this.props;
41 | return (
42 |
43 | this.projectSelect(args)}
47 | />
48 | { this.props.children || }
49 |
50 | );
51 | }
52 |
53 | componentDidMount() {
54 | }
55 |
56 | projectSelect(params) {
57 | this.props.switchProject(params.key);
58 | }
59 |
60 | }
61 |
62 | export default ReduxConnect(MyIndex);
--------------------------------------------------------------------------------
/src/scripts/reducers/sysmanage/SysIndex.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 | import * as links from 'constants/Links';
3 |
4 | const initialState = {
5 | projectId: 'system',
6 | curNavId: 'sys-nav-1',
7 | navList: [
8 | {
9 | key: 'sys-nav-1',
10 | title: '项目管理',
11 | link: links.SYS_PROJECTS,
12 | icon: 'projects',
13 | iconType: 'github'
14 | },
15 | {
16 | key: 'sys-nav-2',
17 | title: '用户管理',
18 | link: links.SYS_USERS,
19 | icon: 'users',
20 | iconType: 'team'
21 | },
22 | {
23 | key: 'sys-nav-3',
24 | title: '角色管理',
25 | link: links.SYS_ROLES,
26 | icon: 'roles',
27 | iconType: 'solution'
28 | },
29 | {
30 | key: 'sys-nav-4',
31 | title: '资源管理',
32 | link: links.SYS_RESOURCES,
33 | icon: 'resources',
34 | iconType: 'appstore'
35 | }
36 | ]
37 | };
38 |
39 | const Reducers = {
40 |
41 | // 获取项目列表
42 | [act.SYS_FETCH_PROJECTS] (state, action) {
43 | return Object.assign({}, state, {
44 | projects: action.projects
45 | })
46 | },
47 |
48 | // 系统管理切换导航
49 | [act.SYS_SWITCH_NAV] (state, action) {
50 | return Object.assign({}, state, {
51 | curNavId: action.curNavId || initialState.curNavId
52 | })
53 | }
54 |
55 | };
56 |
57 | /**
58 | * 根据 actionType 调用对应的 reducer
59 | * @param {[type]} state [description]
60 | * @param {[type]} action [description]
61 | * @return {[type]} [description]
62 | */
63 | export default function SysIndex (state = initialState, action) {
64 | let reducer = Reducers[action.type];
65 | if (reducer) {
66 | return reducer(state, action);
67 | }
68 | else {
69 | return state;
70 | }
71 | }
--------------------------------------------------------------------------------
/src/scripts/AppRouter.js:
--------------------------------------------------------------------------------
1 | // 配置路由
2 | let { Router, Route, browserHistory, IndexRoute } = ReactRouter;
3 |
4 | // 引入页面模块
5 | import App from './containers/App';
6 | import SysIndex from './components/sysmanage/SysIndex';
7 | import SysProjects from './components/sysmanage/SysProjects';
8 |
9 | import MyIndex from './components/myprojects/MyIndex';
10 | import MyProjects from './components/myprojects/MyProjects';
11 |
12 | import Users from './components/common/users/Users';
13 | import Roles from './components/common/roles/Roles';
14 | import Resources from './components/common/resources/Resources';
15 |
16 |
17 | export default class AppRouter extends React.Component {
18 |
19 | constructor() {
20 | super();
21 | }
22 |
23 | render() {
24 | return (
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | );
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/src/scripts/components/header/Header.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 页面的头部,包括
3 | * logo
4 | * 基本操作栏
5 | */
6 | import * as links from 'constants/Links';
7 | import actions from 'actions';
8 |
9 | const { Icon } = Antd;
10 | const { Link } = ReactRouter;
11 |
12 |
13 | class Header extends React.Component {
14 |
15 | static mapToRedux = {
16 | mapStateToProps: state => ({
17 |
18 | }),
19 | mapDispatchToProps: {
20 | switchProject: actions.MyIndex.switchProject,
21 | switchNavItem: actions.SysIndex.switchNavItem
22 | }
23 | };
24 |
25 | constructor() {
26 | super()
27 | }
28 |
29 | render() {
30 | const username = window.username;
31 |
32 | return (
33 |
50 | );
51 | }
52 |
53 | componentDidMount() {
54 | }
55 |
56 | clickMyProjects() {
57 | this.props.switchProject('');
58 | }
59 |
60 | clickSysManage() {
61 | this.props.switchNavItem('');
62 | }
63 |
64 | }
65 |
66 | export default ReduxConnect(Header);
--------------------------------------------------------------------------------
/src/scripts/components/common/ProjectList.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Button, Icon, Card } = Antd;
5 | import ProjectCreate from 'components/common/ProjectCreate';
6 |
7 |
8 | export default class ProjectList extends React.Component {
9 |
10 | static defaultProps = {
11 | projects: [],
12 | projCreateVisible: false
13 | }
14 |
15 | constructor() {
16 | super();
17 | }
18 |
19 | render() {
20 | const { projects, projCreateVisible } = this.props;
21 | let projectsOperate = null;
22 | // 生成项目卡片列表
23 | let projectCardList = projects.map( item => {
24 | // 卡片上的操作按钮
25 | projectsOperate = (
26 |
27 |
28 |
29 |
30 | );
31 | // 单个卡片组件
32 | return (
33 |
36 | 用户数量: {item.userCount}
37 | 角色数量: {item.roleCount}
38 | 资源数量: {item.resourceCount}
39 |
40 | );
41 | });
42 | // 渲染卡片列表,工具栏
43 | return (
44 |
45 |
46 |
49 |
50 |
51 | {projectCardList}
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | componentDidMount() {
59 |
60 | }
61 |
62 | showAddProject() {
63 |
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/src/scripts/common/utils/ReduxConnect.js:
--------------------------------------------------------------------------------
1 | const { connect } = ReactRedux;
2 | const { bindActionCreators } = Redux;
3 |
4 | /**
5 | * 生成 mapDispatchToProps 对象
6 | * 使用 bindActionCreators 方法封装 actionCreator
7 | * @param {[type]} propsMap [description]
8 | * @param {[type]} dispatch [description]
9 | */
10 | function setMapDispatchToProps (dispatch, propsMap, ClassDefine) {
11 | let mapDispatchToProps = {}, key = '', item = null;
12 | for(key in propsMap) {
13 | item = propsMap[key];
14 | if (!item) {
15 | console.error(`mapDispatchToProps.${key} is undefined! please check your component Class: ${ClassDefine.name}`);
16 | }
17 | mapDispatchToProps[key] = bindActionCreators(item, dispatch);
18 | }
19 | return mapDispatchToProps;
20 | }
21 |
22 | /**
23 | * 封装 connect 方法, 在组件内以更简洁的方式调用 stateToProps 和 dispatchToProps
24 | * @param {[type]} ClassDefine [description]
25 | * @return {[type]} [description]
26 | */
27 | module.exports = function ReduxConnect (ClassDefine) {
28 | if (typeof ClassDefine === 'function' &&
29 | typeof ClassDefine.mapToRedux === 'object' &&
30 | typeof ClassDefine.mapToRedux.mapStateToProps === 'function' &&
31 | typeof ClassDefine.mapToRedux.mapDispatchToProps === 'object'
32 | ) {
33 | const mapToRedux = ClassDefine.mapToRedux;
34 | return connect(
35 | mapToRedux.mapStateToProps,
36 | (dispatch) => setMapDispatchToProps(dispatch, mapToRedux.mapDispatchToProps, ClassDefine)
37 | )(ClassDefine);
38 | }
39 | else {
40 | console.error(
41 | `ReduxConnect can not connect this Class,
42 | because the Class.mapToRedux is invalid,
43 | please make sure Class.mapToRedux.mapStateToProps is a function,
44 | ClassDefine.mapToRedux.mapDispatchToProps is a object`
45 | );
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/src/styles/components/header/header.css:
--------------------------------------------------------------------------------
1 | $topbar-h: 35px;
2 | $navbar-h: 60px;
3 | $ops-btn-color: #2db7f5;
4 |
5 | .pf-head {
6 | height: $topbar-h;
7 | background: $dark-bgc;
8 | color: $dark-ftc;
9 | z-index: 10;
10 |
11 | .pf-topbar {
12 | height: $topbar-h;
13 | background: $light-bgc;
14 | display: flex;
15 |
16 | .pf-logo {
17 | display: inline-block;
18 | height: $topbar-h;
19 | overflow: hidden;
20 | width: 120px;
21 | color: #1c2b36;
22 |
23 | h1 {
24 | font-size: 37px;
25 | margin-top: 5px;
26 | line-height: 35px;
27 | text-align: center;
28 | text-shadow: 0 0 3px #131e26;
29 | }
30 | }
31 |
32 | .pf-switch-proj {
33 | display: inline-block;
34 | // width: 260px;
35 | line-height: $topbar-h;
36 | margin-left: 20px;
37 | .pf-tlb-text {
38 | display: inline-block;
39 | vertical-align: middle;
40 | }
41 | .ant-select {
42 | width: 200px;
43 | }
44 | }
45 |
46 | .pf-tlb-info {
47 | display: inline-block;
48 | line-height: $topbar-h;
49 | text-align: right;
50 | flex: 1;
51 |
52 | .pf-tlb-tips {
53 | display: inline-block;
54 | padding: 0 5px;
55 | }
56 | .pf-tlb-button {
57 | padding: 0 10px;
58 | cursor: pointer;
59 | .anticon {
60 | color: $ops-btn-color;
61 | }
62 | &:hover {
63 | color: $ops-btn-color;
64 | }
65 | }
66 | }
67 | }
68 | }
69 |
70 | .pf-body {
71 | flex: 1;
72 | background: $light-bgc;
73 | }
--------------------------------------------------------------------------------
/src/scripts/common/ui/DataTable.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Table } = Antd;
5 |
6 |
7 | export default class DataTable extends React.Component {
8 |
9 | defaultProps = {
10 | columns: []
11 | }
12 |
13 | state = {
14 | data: [],
15 | pagination: {},
16 | loading: false
17 | }
18 |
19 | constructor() {
20 | super();
21 | }
22 |
23 | render() {
24 | return (
25 |
31 | );
32 | }
33 |
34 | componentDidMount() {
35 | this.fetch();
36 | }
37 |
38 | fetch() {
39 | let pagination = this.state.pagination;
40 | // Read total count from server
41 | // pagination.total = data.totalCount;
42 | let data = {
43 | results: [
44 | {
45 | key: 1,
46 | username: '123',
47 | name: '123',
48 | status: true,
49 | createTime: '123'
50 | }
51 | ]
52 | }
53 | pagination.total = 200;
54 | this.setState({
55 | loading: false,
56 | data: data.results,
57 | pagination
58 | });
59 | }
60 |
61 | handleTableChange(pagination, filters, sorter) {
62 | console.log(pagination);
63 | let pager = this.state.pagination;
64 | pager.current = pagination.current;
65 | this.setState({
66 | pagination: pager
67 | });
68 | this.fetch({
69 | results: pagination.pageSize,
70 | page: pagination.current,
71 | sortField: sorter.field,
72 | sortOrder: sorter.order,
73 | ...filters
74 | });
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/scripts/common/ui/Dialog.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | let { Modal, Button } = Antd;
5 |
6 |
7 | export default class Dialog extends React.Component {
8 |
9 | static defaultProps = {
10 | title: "用户信息",
11 | okBtnText: '提 交',
12 | cancelBtnText: '返 回',
13 | visible: false,
14 | loading: false,
15 | maskClosable: false,
16 | onOkClick: () => {},
17 | onCancelClick: null
18 | }
19 |
20 | state = {
21 | visible: false
22 | }
23 |
24 | constructor() {
25 | super();
26 | // 标记属性更新是否通过 state 执行的
27 | this.fromState = false;
28 | }
29 |
30 | render() {
31 | let handleOk = this.props.onOkClick,
32 | handleCancel = this.props.onCancelClick || this.onCancelClick.bind(this),
33 | loading = this.props.loading,
34 | visible = this.props.visible;
35 |
36 | // 如果使用 setState 方式更新 UI 则取 state 中的值
37 | // 默认从 props 中获取
38 | if (this.fromState) {
39 | visible = this.state.visible;
40 | this.fromState = false;
41 | }
42 |
43 | return (
44 |
49 | {this.props.cancelBtnText}
50 | ,
51 |
54 | ]}
55 | >
56 | { this.props.children }
57 |
58 | );
59 | }
60 |
61 | componentDidMount() {
62 |
63 | }
64 |
65 | onCancelClick() {
66 | this.fromState = true;
67 | this.setState({
68 | visible: false
69 | });
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/styles/components/header/navbar.css:
--------------------------------------------------------------------------------
1 | .navbar-wrap {
2 | display: flex;
3 | background: $dark-bgc;
4 |
5 | .nabr-item {
6 | display: inline-block;
7 | }
8 |
9 | .navbar-left {
10 | width: 120px;
11 | line-height: $pf-toolbar-h;
12 | text-align: center;
13 | color: #fff;
14 |
15 | .navbar-title-wrap {
16 | display: inline-block;
17 | vertical-align: top;
18 | height: $pf-toolbar-h;
19 | line-height: $pf-toolbar-h;
20 |
21 | .ant-dropdown-menu {
22 | background: $dark-bgc;
23 |
24 | .ant-dropdown-menu-item {
25 | color: $nav-ftc;
26 |
27 | &:hover {
28 | background: $nav-hover-bgc;
29 | color: #fff;
30 | }
31 | }
32 | }
33 | }
34 |
35 | .navbar-title {
36 | color: #fff;
37 | }
38 |
39 | .ant-dropdown-link {
40 | display: inline-block;
41 | width: 97px;
42 | white-space: nowrap;
43 | overflow: hidden;
44 | text-overflow: ellipsis;
45 | }
46 |
47 | .anticon.anticon-down {
48 | margin-left: 10px;
49 | vertical-align: top;
50 | line-height: $pf-toolbar-h;
51 | }
52 | }
53 |
54 | .navbar-arr {
55 | width: 35px;
56 | height: $pf-toolbar-h;
57 | overflow: hidden;
58 |
59 | .box-arrow-scale {
60 | transform: scale(0.5, 1);
61 | .box-arrow {
62 | width: 100px;
63 | height: 100px;
64 | transform: rotateZ(45deg) translate3d(-81px, 52px, 0);
65 | background: $dark-bgc;
66 | box-shadow: 2px 0px 10px #000;
67 | }
68 | }
69 | }
70 |
71 | .navbar-right {
72 | flex: 1;
73 | }
74 |
75 | .breadcrumb-arrow .anticon {
76 | opacity: 0.5;
77 | transform: scale(0.8);
78 | }
79 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dzs-upms",
3 | "version": "1.0.0",
4 | "description": "",
5 | "scripts": {
6 | "init": "npm install --registry https://registry.npm.taobao.org",
7 | "dev": "node webpack.server.js",
8 | "publish": "webpack --config webpack.prod.js --colors --profile --display-modules",
9 | "dll": "webpack --config webpack.dll.js --colors --profile --display-modules"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git@github.com:functions/webpack-react.git"
14 | },
15 | "jshintConfig": {
16 | "esnext": true
17 | },
18 | "author": "functions",
19 | "license": "ISC",
20 | "dependencies": {
21 | "antd": "^1.10.0",
22 | "isomorphic-fetch": "^2.2.1",
23 | "promise": "^7.1.1",
24 | "react": "^15.3.1",
25 | "react-dom": "^15.3.1",
26 | "react-redux": "^4.4.5",
27 | "react-router": "^2.0.1",
28 | "redux": "^3.5.2",
29 | "redux-logger": "^2.6.1",
30 | "redux-promise-middleware": "^4.0.0",
31 | "redux-thunk": "^2.1.0"
32 | },
33 | "devDependencies": {
34 | "autoprefixer": "^6.3.7",
35 | "babel-core": "^6.7.2",
36 | "babel-loader": "^6.2.4",
37 | "babel-preset-es2015": "^6.6.0",
38 | "babel-preset-react": "^6.5.0",
39 | "babel-preset-stage-0": "^6.5.0",
40 | "clean-webpack-plugin": "^0.1.10",
41 | "copy-webpack-plugin": "^3.0.1",
42 | "css-loader": "^0.23.1",
43 | "css-mqpacker": "^5.0.1",
44 | "del": "^2.2.1",
45 | "extract-text-webpack-plugin": "^1.0.1",
46 | "file-loader": "^0.8.5",
47 | "html-webpack-plugin": "^2.22.0",
48 | "json-loader": "^0.5.4",
49 | "jsx-loader": "^0.13.2",
50 | "open": "0.0.5",
51 | "postcss-assets": "^4.1.0",
52 | "postcss-cssnext": "^2.7.0",
53 | "postcss-font-grabber": "^1.0.7",
54 | "postcss-import": "^8.1.2",
55 | "postcss-loader": "^0.9.1",
56 | "postcss-scss": "^0.1.9",
57 | "postcss-strip-inline-comments": "^0.1.5",
58 | "precss": "^1.4.0",
59 | "react-hot-loader": "^1.3.0",
60 | "style-loader": "^0.13.1",
61 | "url-loader": "^0.5.7",
62 | "webpack": "^1.12.14",
63 | "webpack-dev-server": "^1.14.1",
64 | "webpack-md5-hash": "0.0.5"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/scripts/components/common/NavBar.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import DropSelect from 'common/ui/DropSelect';
5 | import ToolBar from 'common/ui/ToolBar';
6 | const { Icon } = Antd;
7 |
8 |
9 | export default class NavBar extends React.Component {
10 |
11 | static defaultProps = {
12 | type: 'DROPDOWN',
13 | // dropdown 模式下的属性
14 | dropSelectData: [],
15 | activeSelect: '',
16 | onSelect: () => {},
17 | // 导航相关的属性和事件
18 | navItems: [],
19 | activeNav: '',
20 | onNavChange: () => {}, // 导航切换的事件处理
21 | // 标题模式下的属性
22 | title: '',
23 | icon: ''
24 | }
25 |
26 | constructor() {
27 | super();
28 | }
29 |
30 | render() {
31 | const { type, dropSelectData, onSelect, activeSelect,
32 | navItems, activeNav, title, icon, onNavChange } = this.props;
33 |
34 | let navbarLeft = '';
35 | switch(type){
36 | case 'DROPDOWN':
37 | navbarLeft = ;
40 | break;
41 | case 'TITLE':
42 | navbarLeft = (
43 |
44 | {title}
45 |
46 |
47 | );
48 | break;
49 | default:
50 | navbarLeft = ;
53 | }
54 |
55 | return (
56 |
57 |
58 | { navbarLeft }
59 |
60 |
65 |
66 |
67 |
68 |
69 | );
70 | }
71 |
72 | componentDidMount() {
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/scripts/components/common/projects/ProjectInfo.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import Dialog from 'common/ui/Dialog';
5 | let { Button, Input, Select } = Antd;
6 | let Option = Select.Option;
7 |
8 |
9 | export default class ProjectInfo extends React.Component {
10 |
11 | static defaultProps = {
12 | value: '',
13 | managers: [],
14 | onFinish: () => {}
15 | }
16 |
17 | state = {
18 | visible: false
19 | }
20 |
21 | constructor() {
22 | super();
23 | }
24 |
25 | render() {
26 | let selectedManagers = [];
27 | let managersOption = this.props.managers.map(function(item) {
28 | if (item.selected) {
29 | selectedManagers.push(item.text);
30 | }
31 | return (
32 |
33 | );
34 | });
35 | const { visible, value } = this.props;
36 |
37 | return (
38 |
58 | );
59 | }
60 |
61 | componentDidMount() {
62 |
63 | }
64 |
65 | show() {
66 | this.setState({
67 | visible: true
68 | });
69 | setTimeout(function () {
70 | this.refs.projNameInput.refs.input.focus();
71 | }, 300);
72 | }
73 |
74 | handleManageSelect() {
75 |
76 | }
77 |
78 | submitProject() {
79 | let projectName = this.refs.projNameInput.refs.input.value;
80 | console.log(projectName);
81 | this.setState({
82 | visible: false
83 | });
84 |
85 | // 处理完成
86 | this.props.onFinish();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/webpack.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * configuration description
3 | * https://github.com/webpack/docs/wiki/configuration#configuration-object-content
4 | * webpack document
5 | * http://webpack.github.io/docs/
6 | */
7 | 'use strict'
8 | var webpack = require('webpack');
9 | var ProgressPlugin = require('webpack/lib/ProgressPlugin');
10 | var HtmlWebpackPlugin = require('html-webpack-plugin');
11 | var CleanWebpackPlugin = require('clean-webpack-plugin');
12 | var WebpackMd5Hash = require('webpack-md5-hash');
13 |
14 | // 引入基础配置
15 | var baseConfig = require('./webpack.base.js');
16 | // 引入第三方库的 dll 文件
17 | var vendorsManifest = require('./dll/vendors_manifest.json');
18 |
19 | //提取css独立成文件
20 | var ExtractTextPlugin = require("extract-text-webpack-plugin");
21 | var extractSCSS = new ExtractTextPlugin('[name]@[chunkhash].css');
22 |
23 |
24 |
25 | module.exports = {
26 | //获取项目入口js文件
27 | entry: baseConfig.entry,
28 | output: baseConfig.prodOutput,
29 | resolve: baseConfig.resolve,
30 | //各种加载器,即让各种文件格式可用require引用
31 | module: {
32 | loaders: baseConfig.module.loaders.concat(
33 | // js 类型资源的处理
34 | {
35 | test: /\.jsx?$/,
36 | include: /src\/scripts\//,
37 | loaders: ['babel-loader?presets[]=react,presets[]=es2015,presets[]=stage-0']
38 | },
39 | {
40 | test: /\.css$/,
41 | include: /src\/styles\//,
42 | loader: extractSCSS.extract('css-loader?sourceMap&minimize!postcss-loader?parser=postcss-scss')
43 | }
44 | )
45 | },
46 | plugins: [
47 | // 清空编译后的目录
48 | new CleanWebpackPlugin(['prd']),
49 | // 引用打包好的第三方库
50 | new webpack.DllReferencePlugin({
51 | context: __dirname,
52 | manifest: vendorsManifest
53 | }),
54 | // 把第三方库的依赖注入到代码中
55 | new webpack.ProvidePlugin(baseConfig.provideLibs),
56 | extractSCSS,
57 | //js文件的压缩
58 | new webpack.optimize.UglifyJsPlugin({
59 | compress: {
60 | warnings: false
61 | }
62 | }),
63 | // 根据文件内容生成 MD5
64 | new WebpackMd5Hash(),
65 | new ProgressPlugin(function(percentage, msg) {
66 | console.log(parseInt(percentage * 100) + '%', msg);
67 | })
68 | ],
69 | postcss: baseConfig.postcss
70 | };
--------------------------------------------------------------------------------
/webpack.base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack 基础的配置
3 | */
4 | var path = require('path');
5 |
6 |
7 | module.exports = {
8 | entry: {
9 | index: './src/scripts/index.js'
10 | },
11 |
12 | devOutput: {
13 | //文件输出目录
14 | path: path.join(__dirname, 'prd'),
15 | //用于配置文件发布路径,如CDN或本地服务器
16 | publicPath: '/prd/',
17 | //根据入口文件输出的对应多个文件名
18 | filename: '[name].js'
19 | },
20 |
21 | prodOutput: {
22 | //文件输出目录
23 | path: path.join(__dirname, 'prd'),
24 | //用于配置文件发布路径,如CDN或本地服务器
25 | publicPath: '/prd/',
26 | //根据入口文件输出的对应多个文件名
27 | filename: '[name]@[chunkhash].js'
28 | },
29 |
30 | resolve: {
31 | alias: {
32 | styles: path.join(__dirname, 'src', 'styles'),
33 | common: path.join(__dirname, 'src', 'scripts', 'common'),
34 | components: path.join(__dirname, 'src', 'scripts', 'components'),
35 | actions: path.join(__dirname, 'src', 'scripts', 'actions'),
36 | constants: path.join(__dirname, 'src', 'scripts', 'constants'),
37 | services: path.join(__dirname, 'src', 'scripts', 'services')
38 | },
39 | extensions: ['', '.js', '.css']
40 | },
41 |
42 | module: {
43 | loaders: [
44 | //图片文件使用 url-loader 来处理,小于8kb的直接转为base64
45 | {
46 | test: /.(png|jpg|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/,
47 | loader: 'url-loader?limit=50000'
48 | },
49 | {
50 | test: /\.(png|jpg|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/,
51 | loader: 'file-loader'
52 | },
53 | //.json 文件使用json-loader 来编译处理
54 | {
55 | test: /\.json$/,
56 | loader: 'json-loader'
57 | }
58 | ]
59 | },
60 |
61 | provideLibs: {
62 | Antd: 'antd',
63 | React: 'react',
64 | ReactDOM: 'react-dom',
65 | ReactRouter: 'react-router',
66 | Redux: 'redux',
67 | ReactRedux: 'react-redux',
68 | ReduxThunk: 'redux-thunk',
69 | ReduxConnect: 'common/utils/ReduxConnect.js'
70 | },
71 |
72 | postcss: function () {
73 | return [
74 | require('precss'),
75 | require('postcss-strip-inline-comments'),
76 | require('postcss-cssnext')()
77 | ];
78 | }
79 | };
--------------------------------------------------------------------------------
/src/scripts/reducers/myprojects/MyIndex.js:
--------------------------------------------------------------------------------
1 | import * as act from 'constants/ActionTypes';
2 | import * as links from 'constants/Links';
3 |
4 | // 默认选中项目
5 | const EMPTY_PROJ = '请选择项目';
6 |
7 | // 单个项目的导航列表
8 | const NAV_LIST = [
9 | {
10 | key: 'nav-2',
11 | title: '用户管理',
12 | link: links.MY_PROJECT_USERS,
13 | icon: 'users',
14 | iconType: 'team'
15 | },
16 | {
17 | key: 'nav-3',
18 | title: '角色管理',
19 | link: links.MY_PROJECT_ROLES,
20 | icon: 'roles',
21 | iconType: 'solution'
22 | },
23 | {
24 | key: 'nav-4',
25 | title: '资源管理',
26 | link: links.MY_PROJECT_RESOURCES,
27 | icon: 'resources',
28 | iconType: 'appstore'
29 | }
30 | ];
31 |
32 | const initialState = {
33 | curProjectId: EMPTY_PROJ,
34 | projects: [],
35 | curNavId: 'nav-2',
36 | navList: []
37 | };
38 |
39 | const Reducers = {
40 |
41 | /**
42 | * 获取我的项目列表
43 | */
44 | [act.MY_FETCH_PROJECTS] (state, action) {
45 | // 遍历每个项目的信息并为其添加 href 属性
46 | let href = '';
47 | let projects = [].concat(action.projects).map( item => {
48 | href = links.MY_PROJECT_HREF.replace(':id', item.key);
49 | return Object.assign({}, item, { href });
50 | });
51 | return Object.assign({}, state, { projects });
52 | },
53 |
54 | /**
55 | * 切换项目
56 | */
57 | [act.MY_SWITCH_PROJECT] (state, action) {
58 | const curProjectId = action.curProjectId || EMPTY_PROJ;
59 | let navList = [];
60 | // 如果没有选择任何项目
61 | if (curProjectId === EMPTY_PROJ) {
62 | navList = [];
63 | }
64 | // 如果选择了一个项目
65 | else {
66 | let link = '';
67 | // 修改导航按钮的链接为当前项目的链接
68 | navList = [].concat(NAV_LIST).map( item => {
69 | link = item.link.replace(':id', curProjectId);
70 | return Object.assign({}, item, { link });
71 | });
72 | }
73 | // 返回切换后的结果
74 | return Object.assign({}, state, {
75 | curProjectId,
76 | navList,
77 | curNavId: initialState.curNavId
78 | });
79 | },
80 |
81 | /**
82 | * 切换导航
83 | */
84 | [act.MY_SWITCH_NAV] (state, action) {
85 | return Object.assign({}, state, {
86 | curNavId: action.curNavId
87 | })
88 | }
89 |
90 | };
91 |
92 | /**
93 | * 根据 actionType 调用对应的 reducer
94 | * @param {[type]} state [description]
95 | * @param {[type]} action [description]
96 | * @return {[type]} [description]
97 | */
98 | export default function MyProjects (state = initialState, action) {
99 | let reducer = Reducers[action.type];
100 | if (reducer) {
101 | return reducer(state, action);
102 | }
103 | else {
104 | return state;
105 | }
106 | }
--------------------------------------------------------------------------------
/webpack.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * configuration description
3 | * https://github.com/webpack/docs/wiki/configuration#configuration-object-content
4 | * webpack document
5 | * http://webpack.github.io/docs/
6 | */
7 | 'use strict'
8 | var webpack = require('webpack');
9 | var ProgressPlugin = require('webpack/lib/ProgressPlugin');
10 | var HtmlWebpackPlugin = require('html-webpack-plugin');
11 | var CleanWebpackPlugin = require('clean-webpack-plugin');
12 | var CopyWebpackPlugin = require('copy-webpack-plugin');
13 | // 引入基础配置
14 | var baseConfig = require('./webpack.base.js');
15 | // 引入第三方库的 dll 文件
16 | var vendorsManifest = require('./dll/vendors_manifest.json');
17 | var vendorsFileName = vendorsManifest.name.replace('_', '@') + '.js';
18 |
19 |
20 |
21 | module.exports = {
22 | // 获取项目入口js文件
23 | entry: genEntry(),
24 | output: baseConfig.devOutput,
25 | resolve: baseConfig.resolve,
26 | // 生成sourcemap,便于开发调试
27 | devtool: "cheap-source-map",
28 | //各种加载器,即让各种文件格式可用require引用
29 | module: {
30 | loaders: baseConfig.module.loaders.concat(
31 | // js 类型资源的处理
32 | {
33 | test: /\.jsx?$/,
34 | include: /src\/scripts\//,
35 | loaders: ['react-hot', 'babel-loader?presets[]=react,presets[]=es2015,presets[]=stage-0']
36 | },
37 | // css 类型资源的处理
38 | {
39 | test: /\.css$/,
40 | include: /src\/styles\//,
41 | loader: 'style-loader!css-loader?importLoaders=2&sourceMap!postcss-loader?parser=postcss-scss'
42 | }
43 | )
44 | },
45 | plugins: [
46 | // 引用打包好的第三方库
47 | new webpack.DllReferencePlugin({
48 | context: __dirname,
49 | manifest: vendorsManifest
50 | }),
51 | // 把第三方库DLL文件拷贝到 prd 目录下
52 | new CopyWebpackPlugin([
53 | { from: './dll/' + vendorsFileName, to: vendorsFileName }
54 | ]),
55 | // 把第三方库的依赖注入到代码中
56 | new webpack.ProvidePlugin(baseConfig.provideLibs),
57 | new HtmlWebpackPlugin({
58 | filename: 'index.html',
59 | template: './html/index.html',
60 | vendors: vendorsFileName
61 | }),
62 | //增加HMR(模块热插拔)
63 | new webpack.HotModuleReplacementPlugin(),
64 | new webpack.NoErrorsPlugin(),
65 | // 构建时展示进度
66 | new ProgressPlugin(function(percentage, msg) {
67 | console.log(parseInt(percentage * 100) + '%', msg);
68 | })
69 | ],
70 | postcss: baseConfig.postcss
71 |
72 | };
73 |
74 |
75 | /**
76 | * 生成 dev 环境的主文件入口
77 | * @return {[type]} [description]
78 | */
79 | function genEntry () {
80 | var webpackHMR = [
81 | 'webpack-dev-server/client?http://127.0.0.1:3000',
82 | 'webpack/hot/only-dev-server'
83 | ];
84 | var entry = {};
85 | var baseEntry = baseConfig.entry;
86 | for(var key in baseEntry) {
87 | entry[key] = webpackHMR.concat(baseEntry[key])
88 | }
89 | return entry;
90 | }
--------------------------------------------------------------------------------
/src/scripts/components/common/resources/Resources.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | import ResourceList from './ResourceList';
5 | let { Button, Icon } = Antd;
6 | let ButtonGroup = Button.Group;
7 |
8 | let columns = [
9 | {
10 | title: '资源名称',
11 | dataIndex: 'resourceName',
12 | key: 'resourceName',
13 | width: '40%'
14 | },
15 | {
16 | title: '资源标示',
17 | dataIndex: 'resourceId',
18 | key: 'resourceId',
19 | width: '40%'
20 | },
21 | {
22 | title: '操作',
23 | dataIndex: '',
24 | key: 'operate',
25 | width: '20%',
26 | render: () => {
27 | return (
28 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 | }
36 | ];
37 |
38 | let rowSelection = {
39 | onChange(selectedRowKeys, selectedRows) {
40 | console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
41 | },
42 | onSelect(record, selected, selectedRows) {
43 | console.log(record, selected, selectedRows);
44 | },
45 | onSelectAll(selected, selectedRows, changeRows) {
46 | console.log(selected, selectedRows, changeRows);
47 | }
48 | };
49 |
50 | let menuData = [
51 | {
52 | key: 'type-url',
53 | title: 'URL资源',
54 | link: '/page/projects/resource/url'
55 | },
56 | {
57 | key: 'type-data',
58 | title: '录入资源',
59 | link: '/page/projects/resource/input'
60 | },
61 | {
62 | key: 'type-api',
63 | title: '接口提供资源',
64 | link: '/page/projects/resource/api'
65 | }
66 | ];
67 |
68 |
69 | export default class Resources extends React.Component {
70 |
71 | static defaultProps = {
72 |
73 | }
74 |
75 | state = {
76 | data: []
77 | }
78 |
79 | constructor() {
80 | super();
81 | }
82 |
83 | render() {
84 | return (
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | );
93 | }
94 |
95 | componentDidMount() {
96 | this.setState({
97 | data: [
98 | {
99 | key: 1,
100 | resourceId: '/bnb/list',
101 | resourceName: '列表页',
102 | children: [
103 | {
104 | key: 2,
105 | resourceId: '/bnb/subList',
106 | resourceName: '子列表'
107 | },
108 | {
109 | key: 3,
110 | resourceId: '/bnb/attcheList',
111 | resourceName: '附列表'
112 | }
113 | ]
114 | },
115 | {
116 | key: 4,
117 | resourceId: '/bnb/detail',
118 | resourceName: '详情页'
119 | },
120 | {
121 | key: 5,
122 | resourceId: '/bnb/booking',
123 | resourceName: '报价页'
124 | }
125 | ]
126 | });
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/dll/vendors_manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vendors_b277224caea92e299ac1",
3 | "content": {
4 | "./node_modules/react/lib/ReactServerRenderingTransaction.js": 131,
5 | "./node_modules/isomorphic-fetch/node_modules/whatwg-fetch/fetch.js": 2,
6 | "./node_modules/react/react.js": 3,
7 | "./node_modules/react/lib/React.js": 4,
8 | "./node_modules/process/browser.js": 5,
9 | "./node_modules/react/node_modules/object-assign/index.js": 6,
10 | "./node_modules/react/lib/ReactChildren.js": 7,
11 | "./node_modules/react/lib/PooledClass.js": 8,
12 | "./node_modules/react/lib/reactProdInvariant.js": 9,
13 | "./node_modules/fbjs/lib/invariant.js": 10,
14 | "./node_modules/react/lib/ReactElement.js": 11,
15 | "./node_modules/react/lib/ReactCurrentOwner.js": 12,
16 | "./node_modules/fbjs/lib/warning.js": 13,
17 | "./node_modules/fbjs/lib/emptyFunction.js": 14,
18 | "./node_modules/react/lib/canDefineProperty.js": 15,
19 | "./node_modules/react/lib/traverseAllChildren.js": 16,
20 | "./node_modules/react/lib/getIteratorFn.js": 17,
21 | "./node_modules/react/lib/KeyEscapeUtils.js": 18,
22 | "./node_modules/react/lib/ReactComponent.js": 19,
23 | "./node_modules/react/lib/ReactNoopUpdateQueue.js": 20,
24 | "./node_modules/fbjs/lib/emptyObject.js": 21,
25 | "./node_modules/react/lib/ReactPureComponent.js": 22,
26 | "./node_modules/react/lib/ReactClass.js": 23,
27 | "./node_modules/react/lib/ReactPropTypeLocations.js": 24,
28 | "./node_modules/fbjs/lib/keyMirror.js": 25,
29 | "./node_modules/react/lib/ReactPropTypeLocationNames.js": 26,
30 | "./node_modules/fbjs/lib/keyOf.js": 27,
31 | "./node_modules/react/lib/ReactDOMFactories.js": 28,
32 | "./node_modules/react/lib/ReactElementValidator.js": 29,
33 | "./node_modules/react/lib/ReactComponentTreeHook.js": 30,
34 | "./node_modules/react/lib/checkReactTypeSpec.js": 31,
35 | "./node_modules/react/lib/ReactPropTypesSecret.js": 32,
36 | "./node_modules/react/lib/ReactPropTypes.js": 33,
37 | "./node_modules/react/lib/ReactVersion.js": 34,
38 | "./node_modules/react/lib/onlyChild.js": 35,
39 | "./node_modules/react-dom/index.js": 36,
40 | "./node_modules/react/lib/ReactDOM.js": 37,
41 | "./node_modules/react/lib/ReactDOMComponentTree.js": 38,
42 | "./node_modules/react/lib/DOMProperty.js": 39,
43 | "./node_modules/react/lib/ReactDOMComponentFlags.js": 40,
44 | "./node_modules/react/lib/ReactDefaultInjection.js": 41,
45 | "./node_modules/react/lib/BeforeInputEventPlugin.js": 42,
46 | "./node_modules/react/lib/EventConstants.js": 43,
47 | "./node_modules/react/lib/EventPropagators.js": 44,
48 | "./node_modules/react/lib/EventPluginHub.js": 45,
49 | "./node_modules/react/lib/EventPluginRegistry.js": 46,
50 | "./node_modules/react/lib/EventPluginUtils.js": 47,
51 | "./node_modules/react/lib/ReactErrorUtils.js": 48,
52 | "./node_modules/react/lib/accumulateInto.js": 49,
53 | "./node_modules/react/lib/forEachAccumulated.js": 50,
54 | "./node_modules/fbjs/lib/ExecutionEnvironment.js": 51,
55 | "./node_modules/react/lib/FallbackCompositionState.js": 52,
56 | "./node_modules/react/lib/getTextContentAccessor.js": 53,
57 | "./node_modules/react/lib/SyntheticCompositionEvent.js": 54,
58 | "./node_modules/react/lib/SyntheticEvent.js": 55,
59 | "./node_modules/react/lib/SyntheticInputEvent.js": 56,
60 | "./node_modules/react/lib/ChangeEventPlugin.js": 57,
61 | "./node_modules/react/lib/ReactUpdates.js": 58,
62 | "./node_modules/react/lib/CallbackQueue.js": 59,
63 | "./node_modules/react/lib/ReactFeatureFlags.js": 60,
64 | "./node_modules/react/lib/ReactReconciler.js": 61,
65 | "./node_modules/react/lib/ReactRef.js": 62,
66 | "./node_modules/react/lib/ReactOwner.js": 63,
67 | "./node_modules/react/lib/ReactInstrumentation.js": 64,
68 | "./node_modules/react/lib/ReactDebugTool.js": 65,
69 | "./node_modules/react/lib/ReactInvalidSetStateWarningHook.js": 66,
70 | "./node_modules/react/lib/ReactHostOperationHistoryHook.js": 67,
71 | "./node_modules/react/lib/ReactChildrenMutationWarningHook.js": 68,
72 | "./node_modules/fbjs/lib/performanceNow.js": 69,
73 | "./node_modules/fbjs/lib/performance.js": 70,
74 | "./node_modules/react/lib/Transaction.js": 71,
75 | "./node_modules/react/lib/getEventTarget.js": 72,
76 | "./node_modules/react/lib/isEventSupported.js": 73,
77 | "./node_modules/react/lib/isTextInputElement.js": 74,
78 | "./node_modules/react/lib/DefaultEventPluginOrder.js": 75,
79 | "./node_modules/react/lib/EnterLeaveEventPlugin.js": 76,
80 | "./node_modules/react/lib/SyntheticMouseEvent.js": 77,
81 | "./node_modules/react/lib/SyntheticUIEvent.js": 78,
82 | "./node_modules/react/lib/ViewportMetrics.js": 79,
83 | "./node_modules/react/lib/getEventModifierState.js": 80,
84 | "./node_modules/react/lib/HTMLDOMPropertyConfig.js": 81,
85 | "./node_modules/react/lib/ReactComponentBrowserEnvironment.js": 82,
86 | "./node_modules/react/lib/DOMChildrenOperations.js": 83,
87 | "./node_modules/react/lib/DOMLazyTree.js": 84,
88 | "./node_modules/react/lib/DOMNamespaces.js": 85,
89 | "./node_modules/react/lib/setInnerHTML.js": 86,
90 | "./node_modules/react/lib/createMicrosoftUnsafeLocalFunction.js": 87,
91 | "./node_modules/react/lib/setTextContent.js": 88,
92 | "./node_modules/react/lib/escapeTextContentForBrowser.js": 89,
93 | "./node_modules/react/lib/Danger.js": 90,
94 | "./node_modules/fbjs/lib/createNodesFromMarkup.js": 91,
95 | "./node_modules/fbjs/lib/createArrayFromMixed.js": 92,
96 | "./node_modules/fbjs/lib/getMarkupWrap.js": 93,
97 | "./node_modules/react/lib/ReactMultiChildUpdateTypes.js": 94,
98 | "./node_modules/react/lib/ReactDOMIDOperations.js": 95,
99 | "./node_modules/react/lib/ReactDOMComponent.js": 96,
100 | "./node_modules/react/lib/AutoFocusUtils.js": 97,
101 | "./node_modules/fbjs/lib/focusNode.js": 98,
102 | "./node_modules/react/lib/CSSPropertyOperations.js": 99,
103 | "./node_modules/react/lib/CSSProperty.js": 100,
104 | "./node_modules/fbjs/lib/camelizeStyleName.js": 101,
105 | "./node_modules/fbjs/lib/camelize.js": 102,
106 | "./node_modules/react/lib/dangerousStyleValue.js": 103,
107 | "./node_modules/fbjs/lib/hyphenateStyleName.js": 104,
108 | "./node_modules/fbjs/lib/hyphenate.js": 105,
109 | "./node_modules/fbjs/lib/memoizeStringOnly.js": 106,
110 | "./node_modules/react/lib/DOMPropertyOperations.js": 107,
111 | "./node_modules/react/lib/quoteAttributeValueForBrowser.js": 108,
112 | "./node_modules/react/lib/ReactBrowserEventEmitter.js": 109,
113 | "./node_modules/react/lib/ReactEventEmitterMixin.js": 110,
114 | "./node_modules/react/lib/getVendorPrefixedEventName.js": 111,
115 | "./node_modules/react/lib/ReactDOMButton.js": 112,
116 | "./node_modules/react/lib/DisabledInputUtils.js": 113,
117 | "./node_modules/react/lib/ReactDOMInput.js": 114,
118 | "./node_modules/react/lib/LinkedValueUtils.js": 115,
119 | "./node_modules/react/lib/ReactDOMOption.js": 116,
120 | "./node_modules/react/lib/ReactDOMSelect.js": 117,
121 | "./node_modules/react/lib/ReactDOMTextarea.js": 118,
122 | "./node_modules/react/lib/ReactMultiChild.js": 119,
123 | "./node_modules/react/lib/ReactComponentEnvironment.js": 120,
124 | "./node_modules/react/lib/ReactInstanceMap.js": 121,
125 | "./node_modules/react/lib/ReactChildReconciler.js": 122,
126 | "./node_modules/react/lib/instantiateReactComponent.js": 123,
127 | "./node_modules/react/lib/ReactCompositeComponent.js": 124,
128 | "./node_modules/react/lib/ReactNodeTypes.js": 125,
129 | "./node_modules/fbjs/lib/shallowEqual.js": 126,
130 | "./node_modules/react/lib/shouldUpdateReactComponent.js": 127,
131 | "./node_modules/react/lib/ReactEmptyComponent.js": 128,
132 | "./node_modules/react/lib/ReactHostComponent.js": 129,
133 | "./node_modules/react/lib/flattenChildren.js": 130,
134 | "./node_modules/isomorphic-fetch/fetch-npm-browserify.js": 1,
135 | "./node_modules/react/lib/ReactServerUpdateQueue.js": 132,
136 | "./node_modules/react/lib/ReactUpdateQueue.js": 133,
137 | "./node_modules/react/lib/validateDOMNesting.js": 134,
138 | "./node_modules/react/lib/ReactDOMEmptyComponent.js": 135,
139 | "./node_modules/react/lib/ReactDOMTreeTraversal.js": 136,
140 | "./node_modules/react/lib/ReactDOMTextComponent.js": 137,
141 | "./node_modules/react/lib/ReactDefaultBatchingStrategy.js": 138,
142 | "./node_modules/react/lib/ReactEventListener.js": 139,
143 | "./node_modules/fbjs/lib/EventListener.js": 140,
144 | "./node_modules/fbjs/lib/getUnboundedScrollPosition.js": 141,
145 | "./node_modules/react/lib/ReactInjection.js": 142,
146 | "./node_modules/react/lib/ReactReconcileTransaction.js": 143,
147 | "./node_modules/react/lib/ReactInputSelection.js": 144,
148 | "./node_modules/react/lib/ReactDOMSelection.js": 145,
149 | "./node_modules/react/lib/getNodeForCharacterOffset.js": 146,
150 | "./node_modules/fbjs/lib/containsNode.js": 147,
151 | "./node_modules/fbjs/lib/isTextNode.js": 148,
152 | "./node_modules/fbjs/lib/isNode.js": 149,
153 | "./node_modules/fbjs/lib/getActiveElement.js": 150,
154 | "./node_modules/react/lib/SVGDOMPropertyConfig.js": 151,
155 | "./node_modules/react/lib/SelectEventPlugin.js": 152,
156 | "./node_modules/react/lib/SimpleEventPlugin.js": 153,
157 | "./node_modules/react/lib/SyntheticAnimationEvent.js": 154,
158 | "./node_modules/react/lib/SyntheticClipboardEvent.js": 155,
159 | "./node_modules/react/lib/SyntheticFocusEvent.js": 156,
160 | "./node_modules/react/lib/SyntheticKeyboardEvent.js": 157,
161 | "./node_modules/react/lib/getEventCharCode.js": 158,
162 | "./node_modules/react/lib/getEventKey.js": 159,
163 | "./node_modules/react/lib/SyntheticDragEvent.js": 160,
164 | "./node_modules/react/lib/SyntheticTouchEvent.js": 161,
165 | "./node_modules/react/lib/SyntheticTransitionEvent.js": 162,
166 | "./node_modules/react/lib/SyntheticWheelEvent.js": 163,
167 | "./node_modules/react/lib/ReactMount.js": 164,
168 | "./node_modules/react/lib/ReactDOMContainerInfo.js": 165,
169 | "./node_modules/react/lib/ReactDOMFeatureFlags.js": 166,
170 | "./node_modules/react/lib/ReactMarkupChecksum.js": 167,
171 | "./node_modules/react/lib/adler32.js": 168,
172 | "./node_modules/react/lib/findDOMNode.js": 169,
173 | "./node_modules/react/lib/getHostComponentFromComposite.js": 170,
174 | "./node_modules/react/lib/renderSubtreeIntoContainer.js": 171,
175 | "./node_modules/react/lib/ReactDOMUnknownPropertyHook.js": 172,
176 | "./node_modules/react/lib/ReactDOMNullInputValuePropHook.js": 173,
177 | "./node_modules/react-router/lib/index.js": 174,
178 | "./node_modules/react-router/lib/RouteUtils.js": 175,
179 | "./node_modules/react-router/lib/PropTypes.js": 176,
180 | "./node_modules/react-router/lib/deprecateObjectProperties.js": 177,
181 | "./node_modules/react-router/lib/routerWarning.js": 178,
182 | "./node_modules/react-router/node_modules/warning/browser.js": 179,
183 | "./node_modules/react-router/lib/InternalPropTypes.js": 180,
184 | "./node_modules/react-router/lib/PatternUtils.js": 181,
185 | "./node_modules/invariant/browser.js": 182,
186 | "./node_modules/react-router/lib/Router.js": 183,
187 | "./node_modules/history/lib/createHashHistory.js": 184,
188 | "./node_modules/warning/browser.js": 185,
189 | "./node_modules/history/lib/Actions.js": 186,
190 | "./node_modules/history/lib/PathUtils.js": 187,
191 | "./node_modules/history/lib/ExecutionEnvironment.js": 188,
192 | "./node_modules/history/lib/DOMUtils.js": 189,
193 | "./node_modules/history/lib/DOMStateStorage.js": 190,
194 | "./node_modules/history/lib/createDOMHistory.js": 191,
195 | "./node_modules/history/lib/createHistory.js": 192,
196 | "./node_modules/deep-equal/index.js": 193,
197 | "./node_modules/deep-equal/lib/keys.js": 194,
198 | "./node_modules/deep-equal/lib/is_arguments.js": 195,
199 | "./node_modules/history/lib/AsyncUtils.js": 196,
200 | "./node_modules/history/lib/createLocation.js": 197,
201 | "./node_modules/history/lib/runTransitionHook.js": 198,
202 | "./node_modules/history/lib/deprecate.js": 199,
203 | "./node_modules/history/lib/useQueries.js": 200,
204 | "./node_modules/query-string/index.js": 201,
205 | "./node_modules/strict-uri-encode/index.js": 202,
206 | "./node_modules/react-router/lib/createTransitionManager.js": 203,
207 | "./node_modules/react-router/lib/computeChangedRoutes.js": 204,
208 | "./node_modules/react-router/lib/TransitionUtils.js": 205,
209 | "./node_modules/react-router/lib/AsyncUtils.js": 206,
210 | "./node_modules/react-router/lib/isActive.js": 207,
211 | "./node_modules/react-router/lib/getComponents.js": 208,
212 | "./node_modules/react-router/lib/makeStateWithLocation.js": 209,
213 | "./node_modules/react-router/lib/matchRoutes.js": 210,
214 | "./node_modules/react-router/lib/RouterContext.js": 211,
215 | "./node_modules/react-router/lib/getRouteParams.js": 212,
216 | "./node_modules/react-router/lib/RouterUtils.js": 213,
217 | "./node_modules/react-router/lib/Link.js": 214,
218 | "./node_modules/react-router/lib/IndexLink.js": 215,
219 | "./node_modules/react-router/lib/withRouter.js": 216,
220 | "./node_modules/hoist-non-react-statics/index.js": 217,
221 | "./node_modules/react-router/lib/IndexRedirect.js": 218,
222 | "./node_modules/react-router/lib/Redirect.js": 219,
223 | "./node_modules/react-router/lib/IndexRoute.js": 220,
224 | "./node_modules/react-router/lib/Route.js": 221,
225 | "./node_modules/react-router/lib/History.js": 222,
226 | "./node_modules/react-router/lib/Lifecycle.js": 223,
227 | "./node_modules/react-router/lib/RouteContext.js": 224,
228 | "./node_modules/react-router/lib/useRoutes.js": 225,
229 | "./node_modules/react-router/lib/RoutingContext.js": 226,
230 | "./node_modules/react-router/lib/match.js": 227,
231 | "./node_modules/react-router/lib/createMemoryHistory.js": 228,
232 | "./node_modules/history/lib/useBasename.js": 229,
233 | "./node_modules/history/lib/createMemoryHistory.js": 230,
234 | "./node_modules/react-router/lib/useRouterHistory.js": 231,
235 | "./node_modules/react-router/lib/applyRouterMiddleware.js": 232,
236 | "./node_modules/react-router/lib/browserHistory.js": 233,
237 | "./node_modules/history/lib/createBrowserHistory.js": 234,
238 | "./node_modules/react-router/lib/createRouterHistory.js": 235,
239 | "./node_modules/react-router/lib/hashHistory.js": 236,
240 | "./node_modules/redux/lib/index.js": 237,
241 | "./node_modules/redux/lib/createStore.js": 238,
242 | "./node_modules/lodash/isPlainObject.js": 239,
243 | "./node_modules/lodash/_getPrototype.js": 240,
244 | "./node_modules/lodash/_overArg.js": 241,
245 | "./node_modules/lodash/_isHostObject.js": 242,
246 | "./node_modules/lodash/isObjectLike.js": 243,
247 | "./node_modules/symbol-observable/index.js": 244,
248 | "./node_modules/symbol-observable/ponyfill.js": 245,
249 | "./node_modules/redux/lib/combineReducers.js": 246,
250 | "./node_modules/redux/lib/utils/warning.js": 247,
251 | "./node_modules/redux/lib/bindActionCreators.js": 248,
252 | "./node_modules/redux/lib/applyMiddleware.js": 249,
253 | "./node_modules/redux/lib/compose.js": 250,
254 | "./node_modules/redux-thunk/lib/index.js": 251,
255 | "./node_modules/react-redux/lib/index.js": 252,
256 | "./node_modules/react-redux/lib/components/Provider.js": 253,
257 | "./node_modules/react-redux/lib/utils/storeShape.js": 254,
258 | "./node_modules/react-redux/lib/utils/warning.js": 255,
259 | "./node_modules/react-redux/lib/components/connect.js": 256,
260 | "./node_modules/react-redux/lib/utils/shallowEqual.js": 257,
261 | "./node_modules/react-redux/lib/utils/wrapActionCreators.js": 258,
262 | "./node_modules/redux-promise-middleware/dist/index.js": 259,
263 | "./node_modules/redux-promise-middleware/dist/isPromise.js": 260,
264 | "./node_modules/antd/dist/antd.js": 261
265 | }
266 | }
--------------------------------------------------------------------------------