├── 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 | [](https://github.com/facebook/react)
4 | [](https://github.com/ant-design/ant-design)
5 | [](http://opensource.org/licenses/MIT)
6 |
7 | [](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 | 
35 |
36 | ### Baidu Map
37 | 
38 |
39 | ### Echarts
40 | 
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