├── src ├── components │ ├── setting │ │ └── SettingContainer.js │ ├── user │ │ └── UserContainer.js │ ├── map │ │ ├── GoogleContainer.js │ │ └── BaiduContainer.js │ ├── dashboard │ │ ├── Week.js │ │ ├── Summary.js │ │ ├── Views.jsx │ │ ├── Day.js │ │ ├── Calendar.js │ │ ├── China.js │ │ ├── Trend.js │ │ └── ChinaJson.js │ ├── IndexContainer.js │ ├── echarts │ │ ├── charts │ │ │ ├── Pie.jsx │ │ │ ├── Radar.jsx │ │ │ ├── Bar.jsx │ │ │ └── Line.jsx │ │ └── SamplesContainer.js │ └── list │ │ └── ListContainer.js ├── redux │ ├── saga │ │ ├── User.js │ │ ├── index.js │ │ └── List.js │ ├── store │ │ └── index.js │ ├── actions │ │ ├── Common.js │ │ ├── List.js │ │ └── User.js │ └── reducers │ │ ├── index.js │ │ ├── List.js │ │ ├── Common.js │ │ └── User.js ├── styles │ └── imgs │ │ └── logo.png ├── utils │ └── ConstantUtil.js ├── App.test.js ├── index.css ├── App.css ├── index.js ├── registerServiceWorker.js └── App.js ├── .travis.yml ├── public ├── favicon.ico ├── manifest.json └── index.html ├── config ├── jest │ ├── fileTransform.js │ └── cssTransform.js ├── polyfills.js ├── paths.js ├── env.js ├── webpackDevServer.config.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── .gitignore ├── scripts ├── test.js ├── start.js └── build.js ├── LICENSE ├── README.md └── package.json /src/components/setting/SettingContainer.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: javascript 2 | script: true -------------------------------------------------------------------------------- /src/redux/saga/User.js: -------------------------------------------------------------------------------- 1 | import { put, call } from 'redux-saga/effects'; 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aarhub/react-ame-admin/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/styles/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aarhub/react-ame-admin/HEAD/src/styles/imgs/logo.png -------------------------------------------------------------------------------- /src/utils/ConstantUtil.js: -------------------------------------------------------------------------------- 1 | export let baseUrl = 'http://localhost:8080' 2 | 3 | if (process.env.NODE_ENV !== 'development') { 4 | baseUrl = ''; 5 | } 6 | 7 | export const URL_POST_PLATFORM_LOGOUT = `${baseUrl}/quit` 8 | -------------------------------------------------------------------------------- /src/components/user/UserContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class UserContainer extends React.Component { 4 | render() { 5 | return ( 6 |
User Data
7 | ) 8 | } 9 | } -------------------------------------------------------------------------------- /src/components/map/GoogleContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class MapvContainer extends React.Component { 4 | render() { 5 | return ( 6 |
Google Map Visual
7 | ) 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/redux/saga/index.js: -------------------------------------------------------------------------------- 1 | import { takeLatest } from 'redux-saga/effects'; 2 | import { LIST_GET, LIST_DELETE_ITEM } from '../actions/List'; 3 | import { getList, deleteListItem } from './List'; 4 | 5 | export default function* index() { 6 | yield [ 7 | takeLatest(LIST_GET, getList), 8 | takeLatest(LIST_DELETE_ITEM, deleteListItem) 9 | ] 10 | } -------------------------------------------------------------------------------- /src/components/dashboard/Week.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Week extends React.Component { 4 | render() { 5 | return ( 6 |
7 | {this.props.children} 8 |
9 | ) 10 | } 11 | 12 | 13 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /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/redux/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import createSagaMiddleware from 'redux-saga'; 3 | import reducer from '../reducers'; 4 | import root from '../saga'; 5 | 6 | const sagaMiddleware = createSagaMiddleware(); 7 | 8 | const store = createStore( 9 | reducer, 10 | applyMiddleware(sagaMiddleware) 11 | ) 12 | 13 | sagaMiddleware.run(root); 14 | 15 | export default store; -------------------------------------------------------------------------------- /src/redux/actions/Common.js: -------------------------------------------------------------------------------- 1 | export const CURRENT_BREAD_CRUMB_DATA = "CURRENT_BREAD_CRUMB_DATA"; 2 | export const CHANGE_BREAD_CRUMB_DATA = "CHANGE_BREAD_CRUMB_DATA"; 3 | 4 | export function getCurrentBreadCrumbData() { 5 | return { 6 | type: CURRENT_BREAD_CRUMB_DATA 7 | } 8 | } 9 | 10 | export function changeBreadCrumbData(currentCrumb) { 11 | return { 12 | type: CHANGE_BREAD_CRUMB_DATA, 13 | currentCrumb: currentCrumb 14 | } 15 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | .box { 8 | box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.15); 9 | } 10 | 11 | ul li { 12 | list-style: none; 13 | } 14 | 15 | .week-info { 16 | width: 100%; 17 | display: flex; 18 | justify-content: space-between; 19 | } 20 | 21 | .week-info .week-day { 22 | width: 14%; 23 | text-align: right; 24 | font-size: 12px; 25 | padding-right: 5px; 26 | } -------------------------------------------------------------------------------- /src/redux/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { requestUser, requestUserChangeAdmin, requestUserPermissions, requestUserPermissionsUpdate, requestUserInfo } from './User'; 3 | import { handleBreadCrumb } from './Common'; 4 | import { handleList } from "./List"; 5 | 6 | export default combineReducers({ 7 | requestUser, 8 | requestUserChangeAdmin, 9 | requestUserPermissions, 10 | requestUserPermissionsUpdate, 11 | requestUserInfo, 12 | handleBreadCrumb, 13 | handleList 14 | }); -------------------------------------------------------------------------------- /src/redux/reducers/List.js: -------------------------------------------------------------------------------- 1 | import { LIST_GET_DONE, LIST_GET_ERROR, LIST_DELETE_ITEM_DONE, LIST_DELETE_ITEM_ERROR } from "../actions/List"; 2 | 3 | export function handleList(state = {}, action) { 4 | switch (action.type) { 5 | case LIST_GET_DONE: 6 | return Object.assign({}, state, { results: action.results }); 7 | case LIST_GET_ERROR: 8 | return Object.assign({}, state, action.msg); 9 | case LIST_DELETE_ITEM_DONE: 10 | return Object.assign({}, state, { result: action.result }); 11 | case LIST_DELETE_ITEM_ERROR: 12 | return Object.assign({}, state, { msg: action.msg }); 13 | default: 14 | return state; 15 | } 16 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | .idea/ 23 | # See https://help.github.com/ignore-files/ for more about ignoring files. 24 | 25 | # dependencies 26 | /node_modules 27 | 28 | # testing 29 | /coverage 30 | 31 | # production 32 | /build 33 | 34 | # misc 35 | .DS_Store 36 | .env.local 37 | .env.development.local 38 | .env.test.local 39 | .env.production.local 40 | 41 | npm-debug.log* 42 | yarn-debug.log* 43 | yarn-error.log* 44 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 18 | // In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet. 19 | // We don't polyfill it in the browser--this is user's responsibility. 20 | if (process.env.NODE_ENV === 'test') { 21 | require('raf').polyfill(global); 22 | } 23 | -------------------------------------------------------------------------------- /src/redux/reducers/Common.js: -------------------------------------------------------------------------------- 1 | import {CHANGE_BREAD_CRUMB_DATA, CURRENT_BREAD_CRUMB_DATA} from "../actions/Common"; 2 | 3 | const globalState = { 4 | currentCrumb: null 5 | } 6 | 7 | export function handleBreadCrumb(state = globalState, action) { 8 | switch (action.type) { 9 | case CHANGE_BREAD_CRUMB_DATA: 10 | sessionStorage.setItem("currentCrumb", JSON.stringify(action.currentCrumb)); 11 | 12 | return Object.assign({}, state, { 13 | currentCrumb: action.currentCrumb 14 | }); 15 | 16 | case CURRENT_BREAD_CRUMB_DATA: 17 | let obj = sessionStorage.getItem("currentCrumb"); 18 | 19 | try { 20 | obj = (obj && JSON.parse(obj)) 21 | } catch (e) { 22 | console.log(e); 23 | obj = null; 24 | } 25 | 26 | return Object.assign({}, state, { 27 | currentCrumb: obj 28 | }); 29 | 30 | default: 31 | return state; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 F.Achilles 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/dashboard/Summary.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Row, Col, Icon } from 'antd'; 3 | 4 | export default class Summary extends React.PureComponent { 5 | render() { 6 | return ( 7 | 8 |
 Tasks
9 |
 Orders
10 |
 Messages
11 |
Weather
12 |
13 | ) 14 | } 15 | } 16 | 17 | const styles = { 18 | container: { 19 | marginBottom: '16px', 20 | textAlign: 'center', 21 | height: '40px', 22 | lineHeight: '40px' 23 | }, 24 | item: { 25 | background: '#FFFFFF', 26 | height: '40px', 27 | lineHeight: '40px' 28 | } 29 | } -------------------------------------------------------------------------------- /src/redux/actions/List.js: -------------------------------------------------------------------------------- 1 | export const LIST_GET = "LIST_GET"; 2 | export const LIST_GET_DONE = "LIST_GET_DONE"; 3 | export const LIST_GET_ERROR = "LIST_GET_ERROR"; 4 | 5 | export const LIST_DELETE_ITEM = "LIST_DELETE_ITEM"; 6 | export const LIST_DELETE_ITEM_DONE = "LIST_DELETE_ITEM_DONE"; 7 | export const LIST_DELETE_ITEM_ERROR = "LIST_DELETE_ITEM_ERROR"; 8 | 9 | export function getList(params) { 10 | return { 11 | type: LIST_GET, 12 | params 13 | } 14 | } 15 | 16 | export function getListDone(results) { 17 | return { 18 | type: LIST_GET_DONE, 19 | results 20 | } 21 | } 22 | 23 | export function getListError(msg) { 24 | return { 25 | type: LIST_GET_ERROR, 26 | msg 27 | } 28 | } 29 | 30 | export function deleteListItem(params, callback) { 31 | return { 32 | type: LIST_DELETE_ITEM, 33 | params, 34 | callback 35 | } 36 | } 37 | 38 | export function deleteListItemDone(result) { 39 | return { 40 | type: LIST_DELETE_ITEM_DONE, 41 | result 42 | } 43 | } 44 | 45 | export function deleteListItemError(msg) { 46 | return { 47 | type: LIST_DELETE_ITEM_ERROR, 48 | msg 49 | } 50 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | React AME Admin 2 | ======== 3 | [![React](https://img.shields.io/badge/react-^16.2.0-brightgreen.svg?style=flat-square)](https://github.com/facebook/react) 4 | [![Ant Design](https://img.shields.io/badge/ant--design-^3.0.3-yellowgreen.svg?style=flat-square)](https://github.com/ant-design/ant-design) 5 | [![MIT](https://img.shields.io/dub/l/vibe-d.svg?style=flat-square)](http://opensource.org/licenses/MIT) 6 | 7 | [![Build Status](https://travis-ci.org/fachilles/react-ame-admin.svg?branch=master)](https://travis-ci.org/fachilles/react-ame-admin) 8 | 9 | 10 | 11 | A frontend Framework for building admin applications on top of Restful API, using React, Antd, Map, Echarts. 12 | 13 | ## Features 14 | * Based on the actual project. 15 | * To provide background admin system with common scenarios, based Antd UI design language. 16 | * To provide the Baidu Map visual demo that depends on the react-bmap component. 17 | * Include actual Charts, Calendar and so on. 18 | 19 | ## Installation 20 | 1.Download or clone code. 21 | 22 | 2.Install dependency modules. 23 | ```js 24 | npm install 25 | ``` 26 | 27 | 3.Start project. 28 | ```js 29 | npm start 30 | ``` 31 | 32 | ## Screen Shot 33 | ### Dashboard 34 | ![shot](https://raw.githubusercontent.com/fachilles/fachilles.github.io/master/static/imgs/react-admin/react-admin-1.png) 35 | 36 | ### Baidu Map 37 | ![shot](https://raw.githubusercontent.com/fachilles/fachilles.github.io/master/static/imgs/react-admin/react-admin-2.png) 38 | 39 | ### Echarts 40 | ![shot](https://raw.githubusercontent.com/fachilles/fachilles.github.io/master/static/imgs/react-admin/react-admin-3.png) 41 | 42 | 43 | 44 | ## License 45 | React Admin is licensed under the [MIT Licence](https://github.com/marmelab/admin-on-rest/blob/master/LICENSE.md). 46 | 47 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | @import '~antd/dist/antd.css'; 2 | .App { 3 | text-align: center; 4 | } 5 | 6 | .App-logo { 7 | animation: App-logo-spin infinite 20s linear; 8 | height: 80px; 9 | } 10 | 11 | .App-header { 12 | background-color: #222; 13 | height: 150px; 14 | padding: 20px; 15 | color: white; 16 | } 17 | 18 | .App-title { 19 | font-size: 1.5em; 20 | } 21 | 22 | .App-intro { 23 | font-size: large; 24 | } 25 | 26 | .container { 27 | position: absolute; 28 | width: 100%; 29 | top: 0; 30 | bottom: 0; 31 | } 32 | 33 | .container .logo { 34 | height: 32px; 35 | line-height: 32px; 36 | border-radius: 6px; 37 | margin: 16px; 38 | white-space: nowrap; 39 | overflow: hidden; 40 | } 41 | 42 | .container .logo img { 43 | vertical-align: middle; 44 | width: 32px; 45 | } 46 | 47 | .container .logo .title { 48 | vertical-align: middle; 49 | line-height: 32px; 50 | color: #FFFFFF; 51 | padding-left: 5px; 52 | font-size: 18px; 53 | -webkit-transition: opacity .3s ease-in-out, width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); 54 | transition: opacity .3s ease-in-out, width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); 55 | } 56 | 57 | .container .logo .logo_collapsed { 58 | max-width: 0; 59 | display: inline-block; 60 | opacity: 0; 61 | } 62 | 63 | .container .trigger { 64 | font-size: 18px; 65 | line-height: 64px; 66 | padding: 0 16px; 67 | cursor: pointer; 68 | -webkit-transition: color .3s; 69 | transition: color .3s; 70 | } 71 | 72 | .container .trigger:hover { 73 | color: #108ee9; 74 | } 75 | 76 | @keyframes App-logo-spin { 77 | from { 78 | transform: rotate(0deg); 79 | } 80 | to { 81 | transform: rotate(360deg); 82 | } 83 | } -------------------------------------------------------------------------------- /src/components/IndexContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import China from './dashboard/China'; 3 | import Views from './dashboard/Views'; 4 | import Summary from './dashboard/Summary'; 5 | import Trend from './dashboard/Trend'; 6 | import { Row, Col } from 'antd'; 7 | 8 | export default class IndexContainer extends React.Component { 9 | constructVisitors = () => { 10 | let items = [{ 11 | name: 'Bei Jing', value: 1234 12 | }, { 13 | name: 'Shang Hai', value: 324 14 | }, { 15 | name: 'Shen Zhen', value: 345 16 | }, { 17 | name: 'Guang Zhou', value: 345 18 | }, { 19 | name: 'Hang Zhou', value: 345 20 | }, , { 21 | name: 'Guang Xi', value: 345 22 | }]; 23 | 24 | return items.map((item) => { 25 | return
  • {item.name} {item.value}
  • 26 | }) 27 | } 28 | 29 | render() { 30 | return ( 31 |
    32 | 33 | 34 |
    35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
    44 |
    45 | ) 46 | } 47 | } 48 | 49 | const styles = { 50 | main: { 51 | }, 52 | map: { 53 | width: '100%', 54 | height: 'auto', 55 | margin: '5px 0' 56 | } 57 | } -------------------------------------------------------------------------------- /src/components/dashboard/Views.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import echarts from 'echarts'; 3 | 4 | export default class Views extends React.PureComponent { 5 | render() { 6 | return ( 7 |
    8 | ) 9 | } 10 | 11 | componentDidMount() { 12 | this.views = echarts.init(document.getElementById('views')) 13 | this.initViews(); 14 | } 15 | 16 | initViews = () => { 17 | const option = { 18 | backgroundColor: '#FFFFFF', 19 | tooltip: { 20 | trigger: 'axis', 21 | axisPointer: { 22 | type: 'shadow' 23 | } 24 | }, 25 | grid: { 26 | left: '3%', 27 | right: '3%', 28 | top: '3%', 29 | bottom: '3%', 30 | containLabel: true 31 | }, 32 | xAxis: { 33 | type: 'value' 34 | }, 35 | yAxis: { 36 | type: 'category', 37 | data: ['Bei Jing', 'Guang Zhou', 'Hang Zhou', 'Shang Hai', 'Shen Zhen', 'Guang Xi', 'Chong Qing'] 38 | }, 39 | series: [ 40 | { 41 | name: '视频广告', 42 | type: 'bar', 43 | stack: '总量', 44 | label: { 45 | normal: { 46 | show: true, 47 | position: 'insideRight' 48 | } 49 | }, 50 | data: [150, 212, 201, 154, 190, 330, 410] 51 | } 52 | ] 53 | }; 54 | 55 | this.views.setOption(option); 56 | } 57 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React Admin 23 | 24 | 25 | 26 | 29 |
    30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/components/echarts/charts/Pie.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Pie extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.echarts = this.props.echarts; 8 | } 9 | 10 | render() { 11 | return ( 12 |
    13 | ) 14 | } 15 | 16 | componentDidMount() { 17 | this.chartPie = this.echarts.init(document.getElementById('chartPie')); 18 | this.constructOption(); 19 | } 20 | 21 | constructOption = () => { 22 | let option = { 23 | title: { 24 | text: '某站点用户访问来源', 25 | subtext: 'Demo Digital', 26 | x: 'center' 27 | }, 28 | tooltip: { 29 | trigger: 'item', 30 | formatter: "{a}
    {b} : {c} ({d}%)" 31 | }, 32 | legend: { 33 | orient: 'vertical', 34 | left: 'left', 35 | data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'] 36 | }, 37 | series: [ 38 | { 39 | name: '访问来源', 40 | type: 'pie', 41 | radius: '55%', 42 | center: ['50%', '60%'], 43 | data: [ 44 | { value: 335, name: '直接访问' }, 45 | { value: 310, name: '邮件营销' }, 46 | { value: 234, name: '联盟广告' }, 47 | { value: 135, name: '视频广告' }, 48 | { value: 1548, name: '搜索引擎' } 49 | ], 50 | itemStyle: { 51 | emphasis: { 52 | shadowBlur: 10, 53 | shadowOffsetX: 0, 54 | shadowColor: 'rgba(0, 0, 0, 0.5)' 55 | } 56 | } 57 | } 58 | ] 59 | }; 60 | 61 | this.chartPie.setOption(option); 62 | } 63 | } -------------------------------------------------------------------------------- /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