├── .env ├── src ├── style │ ├── button.less │ ├── utils-border.less │ ├── imgs │ │ ├── b1.jpg │ │ ├── 404.png │ │ ├── beauty.jpg │ │ └── mobile.gif │ ├── theme │ │ ├── theme-danger.json │ │ ├── theme-grey.json │ │ ├── theme-info.json │ │ ├── theme-warn.json │ │ └── index.js │ ├── scroll.less │ ├── img.less │ ├── table.less │ ├── icons.less │ ├── modal.less │ ├── utils-spacing.less │ ├── login.less │ ├── utils-color.less │ ├── utils-text.less │ ├── utils-size.less │ ├── card.less │ ├── global.less │ ├── index.less │ ├── variables.less │ ├── menu.less │ └── banner.less ├── index.css ├── action │ ├── type.js │ └── index.js ├── App.test.js ├── components │ ├── Page.jsx │ ├── widget │ │ └── AuthWidget.js │ ├── pages │ │ ├── NotFound.jsx │ │ └── Login.jsx │ ├── ui │ │ ├── emoji │ │ │ └── index.jsx │ │ ├── banners │ │ │ ├── index.jsx │ │ │ ├── AutoPlay.jsx │ │ │ ├── Basic.jsx │ │ │ └── Custom.jsx │ │ ├── Spins.jsx │ │ ├── Icons.jsx │ │ ├── Draggable.jsx │ │ ├── Notifications.jsx │ │ ├── Buttons.jsx │ │ └── Wysiwyg.jsx │ ├── auth │ │ ├── RouterEnter.js │ │ └── Basic.js │ ├── tables │ │ ├── ExpandedTable.jsx │ │ ├── BasicTable.jsx │ │ ├── FixedTable.jsx │ │ ├── AdvancedTables.jsx │ │ ├── BasicTables.jsx │ │ ├── SelectTable.jsx │ │ ├── AsynchronousTable.jsx │ │ ├── SortTable.jsx │ │ ├── SearchTable.jsx │ │ └── EditableTable.jsx │ ├── charts │ │ ├── RechartsRadialBarChart.jsx │ │ ├── RechartsBarChart.jsx │ │ ├── RechartsRadarChart.jsx │ │ ├── RechartsSimpleLineChart.jsx │ │ ├── Echarts.jsx │ │ ├── Recharts.jsx │ │ ├── EchartsPie.jsx │ │ ├── EchartsGraphnpm.jsx │ │ ├── EchartsArea.jsx │ │ ├── EchartsScatter.jsx │ │ └── EchartsForce.js │ ├── forms │ │ ├── LoginForm.jsx │ │ ├── HorizontalForm.jsx │ │ └── ModalForm.jsx │ ├── dashboard │ │ ├── EchartsProjects.jsx │ │ └── EchartsViews.jsx │ ├── animation │ │ ├── BasicAnimations.jsx │ │ └── ExampleAnimations.jsx │ ├── BreadcrumbCustom.jsx │ ├── HeaderCustom.jsx │ └── SiderCustom.jsx ├── axios │ ├── config.js │ ├── tools.js │ └── index.js ├── App.css ├── index.js ├── utils │ └── index.jsx ├── reducer │ └── index.js ├── logo.svg ├── App.js ├── registerServiceWorker.js └── routes │ └── index.js ├── public ├── favicon.ico └── index.html ├── config ├── vendor.config.js ├── jest │ ├── fileTransform.js │ └── cssTransform.js ├── polyfills.js ├── paths.js ├── env.js └── webpackDevServer.config.js ├── .gitignore ├── .eslintrc ├── scripts ├── test.js ├── start.js └── build.js └── package.json /.env: -------------------------------------------------------------------------------- 1 | PORT=3006 -------------------------------------------------------------------------------- /src/style/button.less: -------------------------------------------------------------------------------- 1 | .ant-btn+.ant-btn { 2 | margin-left: 10px; 3 | } -------------------------------------------------------------------------------- /src/style/utils-border.less: -------------------------------------------------------------------------------- 1 | .b-a { 2 | border: 1px solid @border-color; 3 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/react-admin/master/public/favicon.ico -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /src/style/imgs/b1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/react-admin/master/src/style/imgs/b1.jpg -------------------------------------------------------------------------------- /src/style/theme/theme-danger.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "background": "#f44455" 4 | } 5 | } -------------------------------------------------------------------------------- /src/style/theme/theme-grey.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "background": "#424242" 4 | } 5 | } -------------------------------------------------------------------------------- /src/style/theme/theme-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "background": "#6887ff" 4 | } 5 | } -------------------------------------------------------------------------------- /src/style/theme/theme-warn.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "background": "#fcc100" 4 | } 5 | } -------------------------------------------------------------------------------- /src/style/imgs/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/react-admin/master/src/style/imgs/404.png -------------------------------------------------------------------------------- /src/style/imgs/beauty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/react-admin/master/src/style/imgs/beauty.jpg -------------------------------------------------------------------------------- /src/style/imgs/mobile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/react-admin/master/src/style/imgs/mobile.gif -------------------------------------------------------------------------------- /src/action/type.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/30. 3 | */ 4 | export const REQUEST_DATA = 'REQUEST_DATA'; 5 | 6 | export const RECEIVE_DATA = 'RECEIVE_DATA'; 7 | -------------------------------------------------------------------------------- /src/style/scroll.less: -------------------------------------------------------------------------------- 1 | //美化webkit内核滚动条 2 | ::-webkit-scrollbar { 3 | width: 8px; 4 | height: 8px; 5 | } 6 | ::-webkit-scrollbar-thumb { 7 | background-color: #777; 8 | } -------------------------------------------------------------------------------- /src/style/img.less: -------------------------------------------------------------------------------- 1 | img { 2 | vertical-align: middle; 3 | } 4 | .img-responsive{ 5 | width: 100%; 6 | height: auto; 7 | } 8 | .img-circle { 9 | border-radius: 50%; 10 | } -------------------------------------------------------------------------------- /config/vendor.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/9/24. 3 | */ 4 | module.exports = { 5 | entry: { 6 | vendor: ['antd'], // 需要分离的库 7 | charts: ['echarts-for-react'] 8 | } 9 | }; -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /src/style/table.less: -------------------------------------------------------------------------------- 1 | .table-operations { 2 | margin-bottom: 16px; 3 | > button { 4 | margin-right: 8px; 5 | } 6 | } 7 | 8 | .editable-row-text { 9 | padding: 5px; 10 | } 11 | 12 | .editable-row-operations a { 13 | margin-right: 8px; 14 | } -------------------------------------------------------------------------------- /src/style/theme/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/5/6. 3 | */ 4 | import themeinfo from './theme-info.json'; 5 | import themegrey from './theme-grey.json'; 6 | import themedanger from './theme-danger.json'; 7 | import themewarn from './theme-warn.json'; 8 | 9 | export default { themeinfo, themegrey, themedanger, themewarn}; -------------------------------------------------------------------------------- /src/components/Page.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/16. 3 | */ 4 | import React from 'react'; 5 | 6 | class Page extends React.Component { 7 | render() { 8 | return ( 9 |
10 | {this.props.children} 11 |
12 | ) 13 | 14 | } 15 | } 16 | 17 | export default Page; -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | // This is a custom Jest transformer turning file imports into filenames. 6 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 7 | 8 | module.exports = { 9 | process(src, filename) { 10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/axios/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/30. 3 | * 接口地址配置文件 4 | */ 5 | 6 | //easy-mock模拟数据接口地址 7 | const EASY_MOCK = 'https://www.easy-mock.com/mock'; 8 | const MOCK_AUTH = EASY_MOCK + '/597b5ed9a1d30433d8411456/auth'; // 权限接口地址 9 | export const MOCK_AUTH_ADMIN = MOCK_AUTH + '/admin'; // 管理员权限接口 10 | export const MOCK_AUTH_VISITOR = MOCK_AUTH + '/visitor'; // 访问权限接口 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | */node_modules 6 | client/node_modules 7 | server/node_modules 8 | mqtt/node_modules 9 | 10 | # testing 11 | /coverage 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | .idea 28 | -------------------------------------------------------------------------------- /src/components/widget/AuthWidget.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/31. 3 | */ 4 | import { Component } from 'react'; 5 | import { connect } from 'react-redux'; 6 | 7 | class AuthWidget extends Component { 8 | render() { 9 | return this.props.children(this.props.auth.data || {}); 10 | } 11 | } 12 | 13 | const mapStateToProps = state => { 14 | const { auth = {data: {}} } = state.httpData; 15 | return { auth }; 16 | }; 17 | 18 | export default connect(mapStateToProps)(AuthWidget); -------------------------------------------------------------------------------- /src/style/icons.less: -------------------------------------------------------------------------------- 1 | ul.icons-list{ 2 | list-style: none; 3 | overflow: hidden; 4 | li{ 5 | float: left; 6 | width: 10%; 7 | text-align: center; 8 | list-style: none; 9 | cursor: pointer; 10 | height: 100px; 11 | transition: all .3s; 12 | background-color: #fff; 13 | &:hover{ 14 | background-color: #cccccc; 15 | color: #fff; 16 | } 17 | i{ 18 | margin: 16px 0 10px; 19 | } 20 | span{ 21 | display: block; 22 | text-align: center; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app", 3 | "rules": { 4 | "no-multi-spaces": 1, 5 | "react/jsx-tag-spacing": 1, // 总是在自动关闭的标签前加一个空格,正常情况下也不需要换行 6 | "jsx-quotes": 1, 7 | "react/jsx-closing-bracket-location": 1, // 遵循JSX语法缩进/格式 8 | "react/jsx-boolean-value": 1, // 如果属性值为 true, 可以直接省略 9 | "react/no-string-refs": 1, // 总是在Refs里使用回调函数 10 | "react/self-closing-comp": 1, // 对于没有子元素的标签来说总是自己关闭标签 11 | "react/sort-comp": 1, // 按照具体规范的React.createClass 的生命周期函数书写代码 12 | "react/jsx-pascal-case": 1 // React模块名使用帕斯卡命名,实例使用骆驼式命名 13 | } 14 | } -------------------------------------------------------------------------------- /src/style/modal.less: -------------------------------------------------------------------------------- 1 | .vertical-center-modal { 2 | text-align: center; 3 | white-space: nowrap; 4 | &:before { 5 | content: ''; 6 | display: inline-block; 7 | height: 100%; 8 | vertical-align: middle; 9 | width: 0; 10 | } 11 | .ant-modal { 12 | display: inline-block; 13 | vertical-align: middle; 14 | top: 0; 15 | text-align: left; 16 | } 17 | } 18 | /* 19 | // Use flex which not working in IE 20 | .vertical-center-modal { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | } 25 | 26 | .vertical-center-modal .ant-modal { 27 | top: 0; 28 | } 29 | */ -------------------------------------------------------------------------------- /src/style/utils-spacing.less: -------------------------------------------------------------------------------- 1 | .pb-s { padding-bottom: @spacer * 0.5 !important; } 2 | .pb-m { padding-bottom: @spacer * 1 !important; } 3 | .pb-l { padding-bottom: @spacer * 2 !important; } 4 | .pa-s { padding: @spacer * 0.5 !important; } 5 | .pa-m { padding: @spacer * 1 !important; } 6 | .pa-l { padding: @spacer * 2 !important; } 7 | 8 | .mr-s { margin-right: @spacer * 0.5 !important; } 9 | .mr-m { margin-right: @spacer * 1 !important; } 10 | .mr-l { margin-right: @spacer * 2 !important; } 11 | .mb-s { margin-bottom: @spacer * 0.5 !important; } 12 | .mb-m { margin-bottom: @spacer * 1 !important; } 13 | .mb-l { margin-bottom: @spacer * 2 !important; } 14 | -------------------------------------------------------------------------------- /src/style/login.less: -------------------------------------------------------------------------------- 1 | .login{ 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | height: 100%; 6 | background: #f3f3f3; 7 | .login-form{ 8 | width: 320px; 9 | height: 340px; 10 | padding: 36px; 11 | box-shadow: 0 0 100px rgba(0,0,0,.08); 12 | background: #fff; 13 | .login-logo{ 14 | text-align: center; 15 | height: 40px; 16 | line-height: 40px; 17 | cursor: pointer; 18 | margin-bottom: 24px; 19 | span { 20 | vertical-align: text-bottom; 21 | font-size: 16px; 22 | text-transform: uppercase; 23 | display: inline-block; 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /config/polyfills.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (typeof Promise === 'undefined') { 4 | // Rejection tracking prevents a common issue where React gets into an 5 | // inconsistent state due to an error, but it gets swallowed by a Promise, 6 | // and the user has no idea what causes React's erratic future behavior. 7 | require('promise/lib/rejection-tracking').enable(); 8 | window.Promise = require('promise/lib/es6-extensions.js'); 9 | } 10 | 11 | // fetch() polyfill for making API calls. 12 | require('whatwg-fetch'); 13 | 14 | // Object.assign() is commonly used with React. 15 | // It will use the native implementation if it's present and isn't buggy. 16 | Object.assign = require('object-assign'); 17 | -------------------------------------------------------------------------------- /src/components/pages/NotFound.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/5/7. 3 | */ 4 | import React from 'react'; 5 | import img from '../../style/imgs/404.png'; 6 | 7 | 8 | class NotFound extends React.Component { 9 | state = { 10 | animated: '' 11 | }; 12 | enter = () => { 13 | this.setState({animated: 'hinge'}) 14 | }; 15 | render() { 16 | return ( 17 |
18 | 404 19 |
20 | ) 21 | } 22 | } 23 | 24 | export default NotFound; -------------------------------------------------------------------------------- /src/style/utils-color.less: -------------------------------------------------------------------------------- 1 | .color-variant(@bg, @color) { 2 | color: @color; 3 | background-color: @bg; 4 | } 5 | .dark-white { 6 | color: @dark; 7 | background-color: @white; 8 | } 9 | .min-black { 10 | .color-variant(@min-black, @black-color) 11 | } 12 | .black { 13 | .color-variant(@black, @black-color); 14 | } 15 | 16 | .dark { 17 | .color-variant(@dark, @dark-color); 18 | } 19 | 20 | .grey { 21 | .color-variant(@grey, @grey-color); 22 | } 23 | 24 | .primary { 25 | .color-variant(@primary, @primary-color); 26 | } 27 | 28 | .info { 29 | .color-variant(@info, @info-color); 30 | } 31 | .warn { 32 | .color-variant(@warn, @warn-color); 33 | } 34 | .danger { 35 | .color-variant(@danger, @danger-color) 36 | } -------------------------------------------------------------------------------- /src/action/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/30. 3 | */ 4 | import * as type from './type'; 5 | import * as http from '../axios/index'; 6 | 7 | const requestData = category => ({ 8 | type: type.REQUEST_DATA, 9 | category 10 | }); 11 | export const receiveData = (data, category) => ({ 12 | type: type.RECEIVE_DATA, 13 | data, 14 | category 15 | }); 16 | /** 17 | * 请求数据调用方法 18 | * @param funcName 请求接口的函数名 19 | * @param params 请求接口的参数 20 | */ 21 | export const fetchData = ({funcName, params, stateName}) => dispatch => { 22 | !stateName && (stateName = funcName); 23 | dispatch(requestData(stateName)); 24 | return http[funcName](params).then(res => dispatch(receiveData(res, stateName))); 25 | }; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import './style/lib/animate.css'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | import { Provider } from 'react-redux'; 7 | import thunk from 'redux-thunk'; 8 | import { createStore, applyMiddleware } from 'redux'; 9 | import reducer from './reducer'; 10 | 11 | import CRouter from './routes'; 12 | 13 | 14 | // redux 注入操作 15 | const middleware = [thunk]; 16 | const store = createStore(reducer, applyMiddleware(...middleware)); 17 | console.log(store.getState()); 18 | 19 | ReactDOM.render( 20 | 21 | 22 | 23 | , 24 | document.getElementById('root') 25 | ); 26 | registerServiceWorker(); -------------------------------------------------------------------------------- /src/style/utils-text.less: -------------------------------------------------------------------------------- 1 | .text{ 2 | font-size: 1rem; 3 | } 4 | .text-2x{ 5 | font-size: 2rem; 6 | } 7 | .text-3x{ 8 | font-size: 3rem; 9 | } 10 | .text-4x{ 11 | font-size: 4rem; 12 | } 13 | 14 | .text-center { 15 | text-align: center; 16 | } 17 | 18 | .text-left { 19 | text-align: left; 20 | } 21 | 22 | .text-right { 23 | text-align: right; 24 | } 25 | 26 | .text-danger, 27 | .text-danger-hover a:hover { 28 | color: #f44455 !important; 29 | } 30 | .text-dark, 31 | .text-dark-hover a:hover { 32 | color: #2e3e4e !important; 33 | } 34 | .text-info, 35 | .text-info-hover a:hover { 36 | color: #6887ff !important; 37 | } 38 | .text-success, 39 | .text-success-hover a:hover { 40 | color: #6cc788 !important; 41 | } 42 | .text-blue, 43 | .text-blue-hover a:hover { 44 | color: #2196f3 !important; } 45 | -------------------------------------------------------------------------------- /src/utils/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/28. 3 | */ 4 | // 获取url的参数 5 | export const queryString = () => { 6 | let _queryString = {}; 7 | const _query = window.location.search.substr(1); 8 | const _vars = _query.split('&'); 9 | _vars.forEach((v, i) => { 10 | const _pair = v.split('='); 11 | if (!_queryString.hasOwnProperty(_pair[0])) { 12 | _queryString[_pair[0]] = decodeURIComponent(_pair[1]); 13 | } else if (typeof _queryString[_pair[0]] === 'string') { 14 | const _arr = [ _queryString[_pair[0]], decodeURIComponent(_pair[1])]; 15 | _queryString[_pair[0]] = _arr; 16 | } else { 17 | _queryString[_pair[0]].push(decodeURIComponent(_pair[1])); 18 | } 19 | }); 20 | return _queryString; 21 | }; -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | const jest = require('jest'); 19 | const argv = process.argv.slice(2); 20 | 21 | // Watch unless on CI or in coverage mode 22 | if (!process.env.CI && argv.indexOf('--coverage') < 0) { 23 | argv.push('--watch'); 24 | } 25 | 26 | 27 | jest.run(argv); 28 | -------------------------------------------------------------------------------- /src/axios/tools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/30. 3 | * http通用工具函数 4 | */ 5 | import axios from 'axios'; 6 | import { message } from 'antd'; 7 | 8 | /** 9 | * 公用get请求 10 | * @param url 接口地址 11 | * @param msg 接口异常提示 12 | * @param headers 接口所需header配置 13 | */ 14 | export const get = ({url, msg = '接口异常', headers}) => 15 | axios.get(url, headers).then(res => res.data).catch(err => { 16 | console.log(err); 17 | message.warn(msg); 18 | }); 19 | 20 | /** 21 | * 公用post请求 22 | * @param url 接口地址 23 | * @param data 接口参数 24 | * @param msg 接口异常提示 25 | * @param headers 接口所需header配置 26 | */ 27 | export const post = ({url, data, msg = '接口异常', headers}) => 28 | axios.post(url, data, headers).then(res => res.data).catch(err => { 29 | console.log(err); 30 | message.warn(msg); 31 | }); 32 | -------------------------------------------------------------------------------- /src/style/utils-size.less: -------------------------------------------------------------------------------- 1 | .w-8{ 2 | width: 8px; 3 | height: 8px; 4 | display: inline-block; 5 | } 6 | .w-16{ 7 | width: 16px; 8 | height: 16px; 9 | display: inline-block; 10 | } 11 | .w-20{ 12 | width: 20px; 13 | height: 20px; 14 | display: inline-block; 15 | } 16 | .w-24{ 17 | width: 24px; 18 | height: 24px; 19 | display: inline-block; 20 | text-align: center; 21 | } 22 | .w-32{ 23 | width: 32px; 24 | height: 32px; 25 | line-height: 32px; 26 | display: inline-block; 27 | text-align: center; 28 | } 29 | .w-40{ 30 | width: 40px; 31 | height: 40px; 32 | line-height: 40px; 33 | display: inline-block; 34 | text-align: center; 35 | } 36 | .w-48{ 37 | width: 48px; 38 | height: 48px; 39 | line-height: 48px; 40 | display: inline-block; 41 | text-align: center; 42 | } 43 | .w-56{ 44 | width: 56px; 45 | height: 56px; 46 | line-height: 56px; 47 | display: inline-block; 48 | text-align: center; 49 | } -------------------------------------------------------------------------------- /src/style/card.less: -------------------------------------------------------------------------------- 1 | .react-draggable, .cursor-move{ 2 | cursor: move; 3 | strong { 4 | background: #ddd; 5 | border: 1px solid #999; 6 | border-radius: 3px; 7 | display: block; 8 | margin-bottom: 10px; 9 | padding: 3px 5px; 10 | text-align: center; 11 | } 12 | } 13 | .no-cursor { 14 | cursor: auto; 15 | } 16 | .card-tool { 17 | position: absolute; 18 | right: 24px; 19 | top: 24px; 20 | } 21 | 22 | .list-group { 23 | .list-group-item { 24 | position: relative; 25 | display: block; 26 | margin-bottom: -1px; 27 | padding: 12px 16px; 28 | background: transparent; 29 | border: 1px solid #ddd; 30 | border-color: rgba(120, 130, 140, 0.065); 31 | border-width: 1px 0; 32 | &:first-child { 33 | border-top-width: 0; 34 | } 35 | &:last-child { 36 | border-bottom-width: 0; 37 | } 38 | } 39 | } 40 | .no-padding { 41 | .ant-card-body { 42 | padding: 0 !important; 43 | } 44 | } -------------------------------------------------------------------------------- /src/components/ui/emoji/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/22. 3 | */ 4 | import React from 'react'; 5 | import PropTypes from 'prop-types'; 6 | import './iconfont'; 7 | 8 | const Emoji = ({type}) => { 9 | const useTag = ``; 10 | return ( 11 | 12 | 13 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | Emoji.propTypes = { 32 | type: PropTypes.string.isRequired 33 | }; 34 | 35 | export default Emoji; -------------------------------------------------------------------------------- /src/reducer/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/30. 3 | */ 4 | import { combineReducers } from 'redux'; 5 | import * as type from '../action/type'; 6 | 7 | const handleData = (state = {isFetching: true, data: {}}, action) => { 8 | switch (action.type) { 9 | case type.REQUEST_DATA: 10 | return {...state, isFetching: true}; 11 | case type.RECEIVE_DATA: 12 | return {...state, isFetching: false, data: action.data}; 13 | default: 14 | return {...state}; 15 | } 16 | }; 17 | const httpData = (state = {}, action) => { 18 | switch (action.type) { 19 | case type.RECEIVE_DATA: 20 | case type.REQUEST_DATA: 21 | return { 22 | ...state, 23 | [action.category]: handleData(state[action.category], action) 24 | }; 25 | default: 26 | return {...state}; 27 | } 28 | }; 29 | 30 | export default combineReducers({ 31 | httpData 32 | }); 33 | -------------------------------------------------------------------------------- /src/style/global.less: -------------------------------------------------------------------------------- 1 | small { 2 | opacity: .6; 3 | } 4 | .text-muted{ 5 | opacity: .6; 6 | } 7 | .clear{ 8 | display: block; 9 | overflow: hidden; 10 | } 11 | .center { 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | } 16 | .y-center{ 17 | display: flex; 18 | align-items: center; 19 | } 20 | .block{ 21 | display: block; 22 | } 23 | .inline { 24 | display: inline; 25 | } 26 | .none{ 27 | display: none; 28 | } 29 | .b-white { 30 | border-color: #ffffff; 31 | } 32 | .w-full { 33 | width: 100%; 34 | } 35 | 36 | .w-auto { 37 | width: auto; 38 | } 39 | 40 | .h-auto { 41 | height: auto; 42 | } 43 | 44 | .h-full { 45 | height: 100%; 46 | } 47 | 48 | .h-v { 49 | height: 100vh; 50 | } 51 | 52 | .h-v-5 { 53 | height: 50vh; 54 | } 55 | 56 | 57 | .pull-left { 58 | float: left; 59 | } 60 | 61 | .pull-right { 62 | float: right; 63 | } 64 | 65 | .w-40 { 66 | width: 40px; 67 | height: 40px; 68 | line-height: 40px; 69 | display: inline-block; 70 | text-align: center; 71 | } -------------------------------------------------------------------------------- /src/components/auth/RouterEnter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/8/1. 3 | */ 4 | /** 5 | * Created by 叶子 on 2017/7/31. 6 | */ 7 | import React, { Component } from 'react'; 8 | import { Row, Col, Card } from 'antd'; 9 | import BreadcrumbCustom from '@/components/BreadcrumbCustom'; 10 | import AuthWidget from '@/components/widget/AuthWidget'; 11 | 12 | class RouterEnter extends Component { 13 | render() { 14 | return ( 15 |
16 | 17 | ( 19 | 20 | 21 | 22 |

只有管理员登录才能看到该页面,否则跳转到404页面

23 |
24 | 25 |
26 | )} 27 | /> 28 |
29 | ) 30 | } 31 | } 32 | 33 | export default RouterEnter; -------------------------------------------------------------------------------- /src/style/index.less: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | @import "global"; 3 | @import "scroll"; 4 | @import "table"; 5 | @import "login"; 6 | @import "icons"; 7 | @import "button"; 8 | @import "modal"; 9 | @import "menu"; 10 | @import "banner"; 11 | @import "card"; 12 | @import "img"; 13 | @import "utils-text"; 14 | @import "utils-color"; 15 | @import "utils-size"; 16 | @import "utils-border"; 17 | @import "utils-spacing"; 18 | #root{ 19 | height: 100%; 20 | } 21 | .ant-layout{ 22 | height: 100%; 23 | .logo{ 24 | height: 32px; 25 | background: #333; 26 | border-radius: 6px; 27 | margin: 16px; 28 | } 29 | .ant-layout-sider-collapsed{ 30 | .anticon{ 31 | font-size: 16px; 32 | margin-left: 8px; 33 | } 34 | .nav-text{ 35 | display: none; 36 | } 37 | .ant-menu-submenu-vertical > .ant-menu-submenu-title:after{ 38 | display: none; 39 | } 40 | } 41 | p { 42 | margin: 10px 0 10px 0; 43 | } 44 | } 45 | .gutter-example{ 46 | .ant-row{ 47 | //margin-left: 0 !important; 48 | //margin-right: 0 !important; 49 | >div{ 50 | background: transparent; 51 | border: 0; 52 | } 53 | } 54 | } 55 | .gutter-box { 56 | padding: 5px 0; 57 | } -------------------------------------------------------------------------------- /src/style/variables.less: -------------------------------------------------------------------------------- 1 | @full-black: rgba(0, 0, 0, 1); 2 | @dark-black: rgba(0, 0, 0, 0.87); 3 | @light-black: rgba(0, 0, 0, 0.54); 4 | @min-black: rgba(0, 0, 0, 0.065); 5 | 6 | @full-white: rgba(255, 255, 255, 1); 7 | @dark-white: rgba(255, 255, 255, 0.87); 8 | @light-white: rgba(255, 255, 255, 0.54); 9 | @min-white: rgba(255, 255, 255, 0.1); 10 | 11 | @primary: #0cc2aa; 12 | @accent: #a88add; 13 | @warn: #fcc100; 14 | 15 | @info: #6887ff; 16 | @success: #6cc788; 17 | @warning: #f77a99; 18 | @danger: #f44455; 19 | 20 | @light: #f8f8f8; 21 | @grey: #424242; 22 | @dark: #2e3e4e; 23 | @black: #2a2b3c; 24 | @white: #ffffff; 25 | 26 | @primary-color: @dark-white; 27 | @accent-color: @dark-white; 28 | @warn-color: @dark-white; 29 | @success-color: @dark-white; 30 | @info-color: @dark-white; 31 | @warning-color: @dark-white; 32 | @danger-color: @dark-white; 33 | @light-color: @dark-black; 34 | @grey-color: @dark-white; 35 | @dark-color: @dark-white; 36 | @black-color: @dark-white; 37 | 38 | @border-color: rgba(120, 130, 140, 0.13); 39 | 40 | @spacer: 1rem; -------------------------------------------------------------------------------- /src/components/tables/ExpandedTable.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/16. 3 | */ 4 | import React from 'react'; 5 | import { Table } from 'antd'; 6 | 7 | const columns = [ 8 | { title: 'Name', dataIndex: 'name', key: 'name' }, 9 | { title: 'Age', dataIndex: 'age', key: 'age' }, 10 | { title: 'Address', dataIndex: 'address', key: 'address' }, 11 | { title: 'Action', dataIndex: '', key: 'x', render: () => Delete }, 12 | ]; 13 | 14 | const data = [ 15 | { key: 1, name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.' }, 16 | { key: 2, name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.' }, 17 | { key: 3, name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.' }, 18 | ]; 19 | 20 | const ExpandedTable = () => ( 21 |

{record.description}

} 24 | dataSource={data} 25 | /> 26 | ); 27 | 28 | export default ExpandedTable; -------------------------------------------------------------------------------- /src/components/charts/RechartsRadialBarChart.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/22. 3 | */ 4 | import React from 'react'; 5 | import { RadialBarChart, RadialBar, Legend, Tooltip, ResponsiveContainer } from 'recharts'; 6 | 7 | const data = [ 8 | {name: '18-24', uv: 31.47, pv: 2400, fill: '#8884d8'}, 9 | {name: '25-29', uv: 26.69, pv: 4567, fill: '#83a6ed'}, 10 | {name: '30-34', uv: 15.69, pv: 1398, fill: '#8dd1e1'}, 11 | {name: '35-39', uv: 8.22, pv: 9800, fill: '#82ca9d'}, 12 | {name: '40-49', uv: 8.63, pv: 3908, fill: '#a4de6c'}, 13 | {name: '50+', uv: 2.63, pv: 4800, fill: '#d0ed57'}, 14 | {name: 'unknow', uv: 6.67, pv: 4800, fill: '#ffc658'} 15 | ]; 16 | 17 | const RechartsRadialBarChart = () => ( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | 27 | export default RechartsRadialBarChart; -------------------------------------------------------------------------------- /src/components/charts/RechartsBarChart.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/21. 3 | */ 4 | import React from 'react'; 5 | import {BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts'; 6 | 7 | const data = [ 8 | {name: 'Page A', uv: 4000, pv: 2400, amt: 2400}, 9 | {name: 'Page B', uv: 3000, pv: 1398, amt: 2210}, 10 | {name: 'Page C', uv: 2000, pv: 9800, amt: 2290}, 11 | {name: 'Page D', uv: 2780, pv: 3908, amt: 2000}, 12 | {name: 'Page E', uv: 1890, pv: 4800, amt: 2181}, 13 | {name: 'Page F', uv: 2390, pv: 3800, amt: 2500}, 14 | {name: 'Page G', uv: 3490, pv: 4300, amt: 2100}, 15 | ]; 16 | 17 | const RechartsBarChart = () => ( 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | 34 | export default RechartsBarChart; -------------------------------------------------------------------------------- /src/components/charts/RechartsRadarChart.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/22. 3 | */ 4 | import React from 'react'; 5 | import {Radar, RadarChart, PolarGrid, Legend, 6 | PolarAngleAxis, PolarRadiusAxis, ResponsiveContainer} from 'recharts'; 7 | 8 | const data = [ 9 | { subject: 'Math', A: 120, B: 110, fullMark: 150 }, 10 | { subject: 'Chinese', A: 98, B: 130, fullMark: 150 }, 11 | { subject: 'English', A: 86, B: 130, fullMark: 150 }, 12 | { subject: 'Geography', A: 99, B: 100, fullMark: 150 }, 13 | { subject: 'Physics', A: 85, B: 90, fullMark: 150 }, 14 | { subject: 'History', A: 65, B: 85, fullMark: 150 }, 15 | ]; 16 | 17 | const RechartsRadarChart = () => ( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | 30 | export default RechartsRadarChart; -------------------------------------------------------------------------------- /src/components/charts/RechartsSimpleLineChart.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/21. 3 | */ 4 | import React from 'react'; 5 | import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts'; 6 | 7 | 8 | const data = [ 9 | {name: 'Page A', uv: 4000, pv: 2400, amt: 2400}, 10 | {name: 'Page B', uv: 3000, pv: 1398, amt: 2210}, 11 | {name: 'Page C', uv: 2000, pv: 9800, amt: 2290}, 12 | {name: 'Page D', uv: 2780, pv: 3908, amt: 2000}, 13 | {name: 'Page E', uv: 1890, pv: 4800, amt: 2181}, 14 | {name: 'Page F', uv: 2390, pv: 3800, amt: 2500}, 15 | {name: 'Page G', uv: 3490, pv: 4300, amt: 2100}, 16 | ]; 17 | 18 | const RechartsSimpleLineChart = () => ( 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | 36 | export default RechartsSimpleLineChart; -------------------------------------------------------------------------------- /src/components/tables/BasicTable.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/15. 3 | */ 4 | import React from 'react'; 5 | import { Table, Icon } from 'antd'; 6 | 7 | const columns = [{ 8 | title: 'Name', 9 | dataIndex: 'name', 10 | key: 'name', 11 | render: text => {text}, 12 | }, { 13 | title: 'Age', 14 | dataIndex: 'age', 15 | key: 'age', 16 | }, { 17 | title: 'Address', 18 | dataIndex: 'address', 19 | key: 'address', 20 | }, { 21 | title: 'Action', 22 | key: 'action', 23 | render: (text, record) => ( 24 | 25 | Action 一 {record.name} 26 | 27 | Delete 28 | 29 | 30 | More actions 31 | 32 | 33 | ), 34 | }]; 35 | 36 | const data = [{ 37 | key: '1', 38 | name: 'John Brown', 39 | age: 32, 40 | address: 'New York No. 1 Lake Park', 41 | }, { 42 | key: '2', 43 | name: 'Jim Green', 44 | age: 42, 45 | address: 'London No. 1 Lake Park', 46 | }, { 47 | key: '3', 48 | name: 'Joe Black', 49 | age: 32, 50 | address: 'Sidney No. 1 Lake Park', 51 | }]; 52 | 53 | const BasicTable = () => ( 54 |
55 | ); 56 | 57 | export default BasicTable; -------------------------------------------------------------------------------- /src/components/tables/FixedTable.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/16. 3 | */ 4 | import React from 'react'; 5 | import { Table } from 'antd'; 6 | 7 | const columns = [ 8 | { title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' }, 9 | { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' }, 10 | { title: 'Column 1', dataIndex: 'address', key: '1' }, 11 | { title: 'Column 2', dataIndex: 'address', key: '2' }, 12 | { title: 'Column 3', dataIndex: 'address', key: '3' }, 13 | { title: 'Column 4', dataIndex: 'address', key: '4' }, 14 | { title: 'Column 5', dataIndex: 'address', key: '5' }, 15 | { title: 'Column 6', dataIndex: 'address', key: '6' }, 16 | { title: 'Column 7', dataIndex: 'address', key: '7' }, 17 | { title: 'Column 8', dataIndex: 'address', key: '8' }, 18 | { 19 | title: 'Action', 20 | key: 'operation', 21 | fixed: 'right', 22 | width: 100, 23 | render: () => action, 24 | }, 25 | ]; 26 | 27 | const data = [{ 28 | key: '1', 29 | name: 'John Brown', 30 | age: 32, 31 | address: 'New York Park', 32 | }, { 33 | key: '2', 34 | name: 'Jim Green', 35 | age: 40, 36 | address: 'London Park', 37 | }]; 38 | 39 | const FixedTable = () => ( 40 |
41 | ); 42 | 43 | export default FixedTable; -------------------------------------------------------------------------------- /src/style/menu.less: -------------------------------------------------------------------------------- 1 | .ant-menu-dark { 2 | &.ant-menu-inline { 3 | .ant-menu-item-selected { 4 | background-color: #5f5f5f !important; 5 | } 6 | } 7 | } 8 | .custom-trigger { 9 | font-size: 18px; 10 | line-height: 64px; 11 | padding: 0 16px; 12 | cursor: pointer; 13 | transition: color .3s; 14 | } 15 | .ant-layout-sider-collapsed { 16 | overflow-y: initial !important; 17 | } 18 | .avatar { 19 | position: relative; 20 | display: inline-block; 21 | width: 40px; 22 | line-height: 1; 23 | border-radius: 500px; 24 | white-space: nowrap; 25 | font-weight: bold; 26 | i { 27 | position: absolute; 28 | left: 0; 29 | top: 0; 30 | width: 10px; 31 | height: 10px; 32 | margin: 1px; 33 | border-width: 2px; 34 | border-style: solid; 35 | border-radius: 100%; 36 | &.bottom { 37 | left: auto; 38 | top: auto; 39 | bottom: 0; 40 | right: 0; 41 | } 42 | &.on { 43 | background-color: #6cc788; 44 | } 45 | } 46 | img { 47 | border-radius: 500px; 48 | width: 100%; 49 | } 50 | } 51 | .switcher { 52 | z-index: 1050; 53 | position: fixed; 54 | top: 78px; 55 | right: -240px; 56 | width: 240px; 57 | transition: right 0.2s ease; 58 | border: 1px solid rgba(120, 120, 120, 0.1); 59 | background-clip: padding-box; 60 | &.active { 61 | right: -2px; 62 | } 63 | .sw-btn { 64 | position: absolute; 65 | left: -43px; 66 | top: -1px; 67 | padding: 10px 15px; 68 | z-index: 1045; 69 | border: 1px solid rgba(120, 120, 120, 0.1); 70 | border-right-width: 0; 71 | background-clip: padding-box; 72 | } 73 | } -------------------------------------------------------------------------------- /src/components/ui/banners/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/26. 3 | */ 4 | import React from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import BreadcrumbCustom from '../../BreadcrumbCustom'; 7 | import Basic from './Basic'; 8 | import AutoPlay from './AutoPlay'; 9 | import Custom from './Custom'; 10 | 11 | class Banners extends React.Component { 12 | render() { 13 | return ( 14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 | 25 |
26 | 27 | 28 | 29 |
30 | 31 | 32 |
33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | ) 41 | } 42 | } 43 | 44 | export default Banners; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/axios/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/16. 3 | */ 4 | import axios from 'axios'; 5 | import { get } from './tools'; 6 | import * as config from './config'; 7 | 8 | export const getPros = () => axios.post('http://api.xitu.io/resources/github', { 9 | category: "trending", 10 | period: "day", 11 | lang: "javascript", 12 | offset: 0, 13 | limit: 30 14 | }).then(function (response) { 15 | return response.data; 16 | }).catch(function (error) { 17 | console.log(error); 18 | }); 19 | 20 | export const npmDependencies = () => axios.get('./npm.json').then(res => res.data).catch(err => console.log(err)); 21 | 22 | export const weibo = () => axios.get('./weibo.json').then(res => res.data).catch(err => console.log(err)); 23 | 24 | const GIT_OAUTH = 'https://github.com/login/oauth'; 25 | export const gitOauthLogin = () => axios.get(`${GIT_OAUTH}/authorize?client_id=792cdcd244e98dcd2dee&redirect_uri=http://localhost:3006/&scope=user&state=reactAdmin`); 26 | export const gitOauthToken = code => axios.post('https://cors-anywhere.herokuapp.com/' + GIT_OAUTH + '/access_token', {...{client_id: '792cdcd244e98dcd2dee', 27 | client_secret: '81c4ff9df390d482b7c8b214a55cf24bf1f53059', redirect_uri: 'http://localhost:3006/', state: 'reactAdmin'}, code: code}, {headers: {Accept: 'application/json'}}) 28 | .then(res => res.data).catch(err => console.log(err)); 29 | export const gitOauthInfo = access_token => axios({ 30 | method: 'get', 31 | url: 'https://api.github.com/user?access_token=' + access_token, 32 | }).then(res => res.data).catch(err => console.log(err)); 33 | 34 | // easy-mock数据交互 35 | // 管理员权限获取 36 | export const admin = () => get({url: config.MOCK_AUTH_ADMIN}); 37 | 38 | // 访问权限获取 39 | export const guest = () => get({url: config.MOCK_AUTH_VISITOR}); -------------------------------------------------------------------------------- /src/components/tables/AdvancedTables.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/16. 3 | */ 4 | import React from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import FixedTable from './FixedTable'; 7 | import ExpandedTable from './ExpandedTable'; 8 | import EditableTable from './EditableTable'; 9 | import BreadcrumbCustom from '../BreadcrumbCustom'; 10 | 11 | class AdvancedTables extends React.Component { 12 | render() { 13 | return ( 14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
32 | 33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 | ); 43 | } 44 | } 45 | 46 | export default AdvancedTables; -------------------------------------------------------------------------------- /src/components/tables/BasicTables.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/15. 3 | */ 4 | import React from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import BasicTable from './BasicTable'; 7 | import SelectTable from './SelectTable'; 8 | import SortTable from './SortTable'; 9 | import SearchTable from './SearchTable'; 10 | import BreadcrumbCustom from '../BreadcrumbCustom'; 11 | 12 | const BasicTables = () => ( 13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 | 24 | {/**/} 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 | 51 | 52 | 53 |
54 | 55 | 56 | 57 | ); 58 | 59 | export default BasicTables; -------------------------------------------------------------------------------- /src/components/auth/Basic.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 叶子 on 2017/7/31. 3 | */ 4 | import React, { Component } from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import BreadcrumbCustom from '@/components/BreadcrumbCustom'; 7 | import AuthWidget from '@/components/widget/AuthWidget'; 8 | import beauty from '@/style/imgs/beauty.jpg'; 9 | 10 | class Basic extends Component { 11 | render() { 12 | return ( 13 |
14 | 15 | ( 17 | 18 |
19 | 20 | {!auth.uid &&

登录之后你将看到一张美女图

} 21 | { 22 | auth.permissions && auth.permissions.includes('auth/authPage/visit') && 23 |
24 | 25 | {(auth.permissions.includes('auth/authPage/edit') && 26 |
27 |

看啥子美女,看点美景就行啦~😄😄

28 |

管理员身份登录才能看到这两段话

29 |
) || 30 |
31 |

管理员登录将看到不一样的效果

32 |
33 | } 34 |
35 | 36 | } 37 |
38 | 39 | 40 | )} 41 | /> 42 | 43 | 44 | ) 45 | } 46 | } 47 | 48 | export default Basic; -------------------------------------------------------------------------------- /src/components/charts/Echarts.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/17. 3 | */ 4 | import React from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import EchartsArea from './EchartsArea'; 7 | import EchartsPie from './EchartsPie'; 8 | import EchartsEffectScatter from './EchartsEffectScatter'; 9 | import EchartsForce from './EchartsForce'; 10 | 11 | class Echarts extends React.Component { 12 | render() { 13 | return ( 14 |
15 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 | 24 | 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 | 51 | ) 52 | } 53 | } 54 | 55 | export default Echarts; -------------------------------------------------------------------------------- /src/components/charts/Recharts.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hao.cheng on 2017/4/21. 3 | */ 4 | import React from 'react'; 5 | import { Row, Col, Card } from 'antd'; 6 | import RechartsSimpleLineChart from './RechartsSimpleLineChart'; 7 | import RechartsBarChart from './RechartsBarChart'; 8 | import RechartsRadialBarChart from './RechartsRadialBarChart'; 9 | import RechartsRadarChart from './RechartsRadarChart'; 10 | 11 | class Recharts extends React.Component { 12 | render() { 13 | return ( 14 |
15 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 | 24 | 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 | ) 51 | } 52 | } 53 | 54 | export default Recharts; -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebookincubator/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(path, needsSlash) { 15 | const hasSlash = path.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return path.substr(path, path.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${path}/`; 20 | } else { 21 | return path; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right