Compare commits

..
49 Commits
Author SHA1 Message Date
zuiidea c7acc8db4b Merge pull request #649 from zuiidea/develop
Develop
2017-10-30 11:56:42 +08:00
zuiidea 057acc514f Merge branch 'smackgg-master' into develop 2017-10-30 11:52:52 +08:00
zuiidea 53ce7d08fb Merge branch 'xx1595140265-patch-1' into develop 2017-10-30 11:51:27 +08:00
zuiidea 8ffd68a4e2 Merge branch 'dkvirus-patch-1' into develop 2017-10-30 11:50:18 +08:00
zuiidea 766653ee7a merge #640 2017-10-30 11:49:27 +08:00
zuiidea 9dedcc68c3 Merge branch 'the-wang-master' into develop 2017-10-30 11:28:23 +08:00
zuiidea 5ea2b3c9b8 extend chart 2017-10-30 11:25:53 +08:00
汪亚辉 d2ac91839a 面包屑导航支持多级参数
例:
当前router为/:appkey/:packageId
父级router为/:appkey
当前pathname为/com.mock.ly/58

可以看出appkey=com.mock.ly, packageId=58
目前这种场景下,面包屑中父级连接直接展示为/:appkey,没有解析

本次commit支持根据当前多param去填充面包屑中父级页面连接
2017-10-24 18:55:06 +08:00
the-wang bfca2746d8 Merge pull request #1 from zuiidea/master
up
2017-10-24 18:54:10 +08:00
dkvirus b417065ac3 Update Menu.js
在 Slider.js 中调用 Menu 组件,并没有传入 handleClickNavMenu 属性的值,代码优化。
2017-10-12 16:27:52 +08:00
xuxue abdc97f087 Update index.js
取错值,修正
2017-10-10 04:23:34 -05:00
smackxu 07016c6c26 Fixed dark theme menu bug 2017-09-12 16:27:22 +08:00
zuiidea b8162060cd Merge pull request #581 from zuiidea/develop
Develop
2017-09-11 10:27:01 +08:00
zuiidea 36fb5d293c delete extra code 2017-09-11 10:19:43 +08:00
zuiidea 429280a97a Merge branch 'DiroKate-master' into develop 2017-09-11 10:18:37 +08:00
zuiidea 7ac36c779e merge #332 2017-09-11 10:18:20 +08:00
zuiidea d2e7b464e3 megre #563 2017-09-11 10:00:25 +08:00
zuiidea 25839ea99f Merge branch 'akliyiping-develop' into develop 2017-09-11 09:55:27 +08:00
zuiidea 9c99581aa6 Merge branch 'develop' of https://github.com/akliyiping/antd-admin into akliyiping-develop 2017-09-11 09:55:05 +08:00
zuiidea e42c21f0eb fix #574 2017-09-11 09:53:22 +08:00
zuiidea 782bf214e5 Merge branch 'dong894-master' into develop 2017-09-11 09:47:45 +08:00
zuiidea a8a4496c7a Merge branch 'master' of https://github.com/dong894/antd-admin into dong894-master 2017-09-11 09:47:29 +08:00
zuiidea f5f013ff23 Merge branch 'develop' 2017-09-11 09:35:39 +08:00
zuiidea 8cff3af897 Merge branch 'master' of https://github.com/zuiidea/antd-admin 2017-09-11 09:35:32 +08:00
zuiidea 322d5a6d0e merge #576 2017-09-11 09:35:09 +08:00
zuiidea 2ee26f51a7 Merge branch 'yangbin1994-bug575' into develop 2017-09-11 09:27:00 +08:00
zuiidea e670ed2f96 Merge branch 'bug575' of https://github.com/yangbin1994/antd-admin into yangbin1994-bug575 2017-09-11 09:26:36 +08:00
杨斌 601a03b5b4 fix bug#575 2017-09-10 02:26:27 +08:00
dongyulei 00582e70ff 修复 4.3.5 中用户画面翻页无效的问题 2017-09-10 00:02:10 +08:00
zuiidea fa4385055b Update README.md 2017-09-09 14:54:18 +08:00
zuiidea 01f4de55df Merge pull request #571 from zuiidea/develop
Develop
2017-09-09 14:52:50 +08:00
zuiidea dedd34e8e8 4.3.5 2017-09-09 14:50:47 +08:00
zuiidea d1b373201e fix some grammar and details 2017-09-09 14:20:51 +08:00
zuiidea dbcc90e7ad 出去吃烧烤,回来接着看 2017-09-08 16:41:05 +08:00
zuiidea 87fce74d5b Update app.js
fix mobile Header menu
2017-09-08 15:45:38 +08:00
zuiidea 5c51679ad7 Merge branch 'yangbin1994-dva2.0' into develop 2017-09-08 14:56:35 +08:00
zuiidea 6d17b5b876 Merge branch 'yangbin1994-dva2.0' 2017-09-08 14:51:51 +08:00
杨斌 1288853112 解决冲突 2017-09-08 14:19:40 +08:00
杨斌 d3e7e17789 query-string 2017-09-08 13:27:07 +08:00
eric 6077d74f10 .gitignore 增加排除项 2017-09-07 11:00:00 +08:00
杨斌 7bf031699a add LoadingComponent 2017-09-06 20:36:14 +08:00
杨斌 a6eb693636 dva@2.0 2017-09-06 11:13:26 +08:00
zuiidea 39c377e0e2 Merge pull request #552 from zuiidea/develop
add entry.ejs and add lte IE10 polyfill
2017-09-06 09:56:25 +08:00
zuiidea 67b90c4df0 add entry.ejs and add lte IE10 polyfill 2017-09-06 09:55:41 +08:00
zuiidea 0e2727f9c8 Merge pull request #542 from zuiidea/develop
4.3.4
2017-09-04 11:48:32 +08:00
zuiidea 68c9f2b65f Merge pull request #540 from zuiidea/develop
fix login success redirect;fix css load delay
2017-09-04 11:03:13 +08:00
diro 38637ef167 Example for the ”custom className iconfont” 2017-06-06 21:10:45 +08:00
diro fe8527e72e enable the custom ClassName 2017-06-06 21:08:42 +08:00
diro da64cac414 fix the wrong iconName 2017-06-06 20:45:56 +08:00
70 changed files with 5065 additions and 368 deletions
+2
View File
@@ -1,2 +1,4 @@
src/**/*-test.js
src/public
src/routes/chart/ECharts/theme
src/routes/chart/highCharts/mapdata
+4
View File
@@ -32,10 +32,14 @@
"react/forbid-prop-types": 0,
"react/no-string-refs": 0,
"react/no-find-dom-node": 0,
"react/prefer-stateless-function": 0,
"import/no-extraneous-dependencies": 0,
"import/prefer-default-export": 0,
"react/no-danger": 0,
"jsx-a11y/no-static-element-interactions": 0,
"no-mixed-operators": 0,
"jsx-a11y/label-has-for": 0,
"no-plusplus": 0
},
"parser": "babel-eslint",
"parserOptions": {
+11 -4
View File
@@ -1,4 +1,11 @@
dist
node_modules
yarn.lock
npm-debug.log
dist
node_modules
yarn.lock
npm-debug.log
# ide
.idea
# Mac General
.DS_Store
.AppleDouble
.LSOverride
+9 -9
View File
@@ -7,17 +7,17 @@ const svgSpriteDirs = [
]
export default {
entry : 'src/index.js',
svgSpriteLoaderDirs : svgSpriteDirs,
theme : "./theme.config.js",
publicPath : `/${version}/`,
outputPath : `./dist/${version}`,
entry: 'src/index.js',
svgSpriteLoaderDirs: svgSpriteDirs,
theme: "./theme.config.js",
publicPath: `/${version}/`,
outputPath: `./dist/${version}`,
// 接口代理示例
proxy: {
"/api/v1/weather": {
"target": "https://api.seniverse.com/",
"changeOrigin": true,
"pathRewrite": { "^/api/v1/weather" : "/v3/weather" }
"pathRewrite": { "^/api/v1/weather": "/v3/weather" }
},
// "/api/v2": {
// "target": "http://192.168.0.110",
@@ -25,7 +25,7 @@ export default {
// "pathRewrite": { "^/api/v2" : "/api/v2" }
// }
},
env : {
env: {
development: {
extraBabelPlugins: [
"dva-hmr",
@@ -50,8 +50,8 @@ export default {
]
}
},
dllPlugin : {
exclude: ["babel-runtime"],
dllPlugin: {
exclude: ["babel-runtime", "roadhog", "cross-env"],
include: ["dva/router", "dva/saga", "dva/fetch"]
}
}
+15 -28
View File
@@ -2,7 +2,7 @@
[![React](https://img.shields.io/badge/react-^15.6.1-brightgreen.svg?style=flat-square)](https://github.com/facebook/react)
[![Ant Design](https://img.shields.io/badge/ant--design-^2.11.2-yellowgreen.svg?style=flat-square)](https://github.com/ant-design/ant-design)
[![dva](https://img.shields.io/badge/dva-^1.2.0-orange.svg?style=flat-square)](https://github.com/dvajs/dva)
[![dva](https://img.shields.io/badge/dva-^2.0.1-orange.svg?style=flat-square)](https://github.com/dvajs/dva)
[![GitHub issues](https://img.shields.io/github/issues/zuiidea/antd-admin.svg?style=flat-square)](https://github.com/zuiidea/antd-admin)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/zuiidea/antd-admin/pulls)
@@ -21,6 +21,19 @@
## 更新日志
### 4.3.7
`2017-10-30`
-   更新`chart`,新增[ECharts](https://github.com/ecomfe/echarts),[highCharts](https://github.com/highcharts/highcharts),[Recharts](https://github.com/recharts/recharts)演示。
### 4.3.5
`2017-09-04`
-   更新[dva](https://github.com/dvajs/dva)至`2.0.1`,感谢[@yangbin1994](https://github.com/yangbin1994)的[PR](https://github.com/zuiidea/antd-admin/pull/567)。
### 4.3.4
`2017-09-04`
@@ -38,34 +51,8 @@
-   新增打包时按项目版本号生成文件目录。[#449](https://github.com/zuiidea/antd-admin/issues/449)
-   更新`eslint`,并适当修改了`.eslintrc`。
### 4.2.3
`2017-07-07`
-   新增用户按权限访问。[#384](https://github.com/zuiidea/antd-admin/issues/384)
### 4.2.2
`2017-06-01`
-   新增用户管理批量删除。[#320](https://github.com/zuiidea/antd-admin/issues/320)
### 4.2.1
`2017-05-12`
-   新增IconFont扩展方案,本地使用方案。[#270](https://github.com/zuiidea/antd-admin/issues/270) [Live](http://47.92.30.98:666/UIElement/iconfont)
-   新增常见场景使用loading。 [dva-loading](https://github.com/dvajs/dva-loading)
### 4.2
`2017-04-28`
- 修改user相关API使用`Restful`风格。
- 增加user页面多条件查询。[#266](https://github.com/zuiidea/antd-admin/issues/226)
- 修复菜单默认高亮。[#201](https://github.com/zuiidea/antd-admin/issues/201)
[More Change Log](https://github.com/zuiidea/antd-admin/wiki/Change-Log)
[More Change Log](https://github.com/zuiidea/antd-admin/wiki/Change-Log)
## 开发构建
+17 -8
View File
@@ -1,17 +1,25 @@
{
"private": true,
"name": "antd-admin",
"version": "4.3.4",
"version": "4.3.7",
"dependencies": {
"antd": "^2.11.2",
"antd": "^2.13.8",
"axios": "^0.16.2",
"babel-polyfill": "^6.23.0",
"classnames": "^2.2.5",
"cross-env": "^5.0.5",
"d3-shape": "^1.2.0",
"draftjs-to-markdown": "^0.4.0",
"dva": "^1.2.0",
"dva": "^2.0.1",
"dva-loading": "^0.2.0",
"echarts": "^3.7.2",
"echarts-for-react": "^2.0.0",
"echarts-gl": "^1.0.0-beta.5",
"echarts-liquidfill": "^1.1.0",
"ejs-loader": "^0.3.0",
"highcharts-exporting": "^0.1.2",
"highcharts-more": "^0.1.2",
"history": "^4.7.2",
"js-beautify": "^1.6.14",
"jsonp": "^0.2.1",
"less-vars-to-js": "^1.1.2",
@@ -21,14 +29,15 @@
"path-to-regexp": "^1.7.0",
"prop-types": "^15.5.10",
"qs": "^6.5.0",
"query-string": "^5.0.0",
"rc-tween-one": "^1.3.1",
"react": "^15.6.1",
"react-countup": "^2.1.1",
"react-dom": "^15.6.1",
"react-draft-wysiwyg": "^1.10.0",
"react-helmet": "^5.1.3",
"recharts": "^0.22.4",
"roadhog": "^1.2.1"
"react-highcharts": "^13.0.0",
"recharts": "^1.0.0-beta.0"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
@@ -48,13 +57,13 @@
"eslint-plugin-jsx-a11y": "^6.0.2",
"eslint-plugin-react": "^7.1.0",
"html-webpack-plugin": "^2.29.0",
"html-webpack-template": "^5.6.0",
"redbox-react": "^1.2.10",
"roadhog": "1.0.0-beta.7"
"roadhog": "^1.2.2"
},
"pre-commit": ["lint"],
"scripts": {
"dev": "set BROWSER=none&&set HOST=0.0.0.0&&roadhog server",
"dev": "cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
"start": "roadhog buildDll & cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
"lint": "eslint --fix --ext .js src",
"build": "roadhog build",
"build:dll": "roadhog buildDll",
+11 -8
View File
@@ -1,21 +1,24 @@
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import './iconfont.less'
const Iconfont = ({ type, colorful }) => {
const Iconfont = ({ type, colorful = false, className }) => {
if (colorful) {
return (<span
dangerouslySetInnerHTML={{
__html: `<svg class="colorful-icon" aria-hidden="true"><use xlink:href="#${type.startsWith('#') ? type.replace(/#/, '') : type}"></use></svg>`,
}}
/>)
return (
<svg className={classnames('colorful-icon', className)} aria-hidden="true">
<use xlinkHref={`#${type.startsWith('#') ? type.replace(/#/, '') : type}`} />
</svg>
)
}
return <i className={`antdadmin icon-${type}`} />
return <i className={classnames('antdadmin', [`icon-${type}`], className)} />
}
Iconfont.propTypes = {
type: PropTypes.string,
type: PropTypes.string.isRequired,
colorful: PropTypes.bool,
className: PropTypes.string,
}
export default Iconfont
+14 -2
View File
@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Breadcrumb, Icon } from 'antd'
import { Link } from 'dva/router'
import { Link } from 'react-router-dom'
import pathToRegexp from 'path-to-regexp'
import { queryArray } from 'utils'
import styles from './Bread.less'
@@ -24,6 +24,7 @@ const Bread = ({ menu, location }) => {
}
}
let paramMap = {}
if (!current) {
pathArray.push(menu[0] || {
id: 1,
@@ -36,6 +37,17 @@ const Bread = ({ menu, location }) => {
})
} else {
getPathArray(current)
let keys = []
let values = pathToRegexp(current.route, keys).exec(location.pathname.replace('#', ''))
if (keys.length) {
keys.forEach((currentValue, index) => {
if (typeof currentValue.name !== 'string') {
return
}
paramMap[currentValue.name] = values[index + 1]
})
}
}
// 递归查找父级
@@ -48,7 +60,7 @@ const Bread = ({ menu, location }) => {
return (
<Breadcrumb.Item key={key}>
{((pathArray.length - 1) !== key)
? <Link to={item.route}>
? <Link to={pathToRegexp.compile(item.route || '')(paramMap) || '#'}>
{content}
</Link>
: content}
+4 -1
View File
@@ -249,7 +249,10 @@
.ant-menu-item-selected {
color: @primary-color;
background-color: @dark-half;
&.ant-menu-item {
background: @dark-half;
}
& > a {
color: @primary-color;
+4 -6
View File
@@ -1,11 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Menu, Icon } from 'antd'
import { Link } from 'dva/router'
import { Link } from 'react-router-dom'
import { arrayToTree, queryArray } from 'utils'
import pathToRegexp from 'path-to-regexp'
const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOpenKeys, menu, location }) => {
const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, location }) => {
// 生成树状
const menuTree = arrayToTree(menu.filter(_ => _.mpid !== '-1'), 'id', 'mpid')
const levelMap = {}
@@ -31,7 +31,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
}
return (
<Menu.Item key={item.id}>
<Link to={item.route}>
<Link to={item.route || '#'}>
{item.icon && <Icon type={item.icon} />}
{(!siderFoldN || !menuTree.includes(item)) && item.name}
</Link>
@@ -111,8 +111,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
{...menuProps}
mode={siderFold ? 'vertical' : 'inline'}
theme={darkTheme ? 'dark' : 'light'}
onClick={handleClickNavMenu}
defaultSelectedKeys={defaultSelectedKeys}
selectedKeys={defaultSelectedKeys}
>
{menuItems}
</Menu>
@@ -123,7 +122,6 @@ Menus.propTypes = {
menu: PropTypes.array,
siderFold: PropTypes.bool,
darkTheme: PropTypes.bool,
handleClickNavMenu: PropTypes.func,
navOpenKeys: PropTypes.array,
changeOpenKeys: PropTypes.func,
location: PropTypes.object,
+7 -2
View File
@@ -3,8 +3,12 @@ import PropTypes from 'prop-types'
import classNames from 'classnames'
import styles from './Loader.less'
const Loader = ({ spinning }) => {
return (<div className={classNames(styles.loader, { [styles.hidden]: !spinning })}>
const Loader = ({ spinning, fullScreen }) => {
return (<div className={classNames(styles.loader, {
[styles.hidden]: !spinning,
[styles.fullScreen]: fullScreen,
})}
>
<div className={styles.warpper}>
<div className={styles.inner} />
<div className={styles.text} >LOADING</div>
@@ -15,6 +19,7 @@ const Loader = ({ spinning }) => {
Loader.propTypes = {
spinning: PropTypes.bool,
fullScreen: PropTypes.bool,
}
export default Loader
+68 -64
View File
@@ -1,64 +1,68 @@
.loader {
display: block;
background-color: #fff;
width: 100%;
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 100000;
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
text-align: center;
.warpper {
width: 100px;
height: 100px;
display: inline-flex;
flex-direction: column;
justify-content: space-around;
}
.inner {
width: 48px;
height: 48px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
border-right: 1px solid rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
border-left: 1px solid rgba(0, 0, 0, 0.7);
border-radius: 50%;
z-index: 100001;
:local {
animation: spinner 600ms infinite linear;
}
}
.text {
width: 100px;
height: 20px;
text-align: center;
font-size: 12px;
letter-spacing: 4px;
color: #000;
}
&.hidden {
z-index: -1;
opacity: 0;
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loader {
display: block;
background-color: #fff;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 100000;
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
text-align: center;
&.fullScreen {
position: fixed;
}
.warpper {
width: 100px;
height: 100px;
display: inline-flex;
flex-direction: column;
justify-content: space-around;
}
.inner {
width: 48px;
height: 48px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
border-right: 1px solid rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
border-left: 1px solid rgba(0, 0, 0, 0.7);
border-radius: 50%;
z-index: 100001;
:local {
animation: spinner 600ms infinite linear;
}
}
.text {
width: 100px;
height: 20px;
text-align: center;
font-size: 12px;
letter-spacing: 4px;
color: #000;
}
&.hidden {
z-index: -1;
opacity: 0;
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
+34
View File
@@ -0,0 +1,34 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import Loader from '../Loader'
import styles from './Page.less'
export default class Page extends Component {
render () {
const { className, children, loading = false, inner = false } = this.props
const loadingStyle = {
height: 'calc(100vh - 184px)',
overflow: 'hidden',
}
return (
<div
className={classnames(className, {
[styles.contentInner]: inner,
})}
style={loading ? loadingStyle : null}
>
{loading ? <Loader spinning /> : ''}
{children}
</div>
)
}
}
Page.propTypes = {
className: PropTypes.string,
children: PropTypes.node,
loading: PropTypes.bool,
inner: PropTypes.bool,
}
+14
View File
@@ -0,0 +1,14 @@
@import "~themes/vars";
.contentInner{
background: #fff;
padding: 24px;
box-shadow: @shadow-1;
min-height: e("calc(100vh - 184px)");
}
@media (max-width: 767px) {
.contentInner {
padding: 12px;
min-height: e("calc(100vh - 160px)");
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"name": "Page",
"version": "0.0.0",
"private": true,
"main": "./Page.js"
}
+2
View File
@@ -6,6 +6,7 @@ import Editor from './Editor'
import FilterItem from './FilterItem'
import Loader from './Loader'
import * as Layout from './Layout/index.js'
import Page from './Page'
import layer from './layer'
@@ -19,4 +20,5 @@ export {
FilterItem,
Loader,
layer,
Page,
}
+25
View File
@@ -0,0 +1,25 @@
<% htmlWebpackPlugin.options.headScripts = htmlWebpackPlugin.options.headScripts || [] %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="A admin dashboard application demo built upon Ant Design and Dva.js">
<title>antd admin</title>
<!--[if lte IE 10]>
<script
src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,media-match/2.0.2/media.match.min.js"></script>
<![endif]-->
<% for (item of htmlWebpackPlugin.options.headScripts) { %>
<script src="<%= item %>"></script>
<% } %>
</head>
<body>
<div id="root"></div>
</body>
</html>
+2 -2
View File
@@ -1,7 +1,7 @@
import { message } from 'antd'
import dva from 'dva'
import createLoading from 'dva-loading'
import { browserHistory } from 'dva/router'
import createHistory from 'history/createBrowserHistory'
import 'babel-polyfill'
// 1. Initialize
@@ -9,7 +9,7 @@ const app = dva({
...createLoading({
effects: true,
}),
history: browserHistory,
history: createHistory(),
onError (error) {
message.error(error.message)
},
+7 -7
View File
@@ -93,32 +93,32 @@ let database = [
{
id: '5',
bpid: '1',
name: 'Recharts',
name: 'Charts',
icon: 'code-o',
},
{
id: '51',
bpid: '5',
mpid: '5',
name: 'LineChart',
name: 'ECharts',
icon: 'line-chart',
route: '/chart/lineChart',
route: '/chart/ECharts',
},
{
id: '52',
bpid: '5',
mpid: '5',
name: 'BarChart',
name: 'highCharts',
icon: 'bar-chart',
route: '/chart/barChart',
route: '/chart/highCharts',
},
{
id: '53',
bpid: '5',
mpid: '5',
name: 'AreaChart',
name: 'Rechartst',
icon: 'area-chart',
route: '/chart/areaChart',
route: '/chart/Recharts',
},
{
id: '6',
+5 -4
View File
@@ -7,6 +7,7 @@ import config from 'config'
import { EnumRoleType } from 'enums'
import { query, logout } from 'services/app'
import * as menusService from 'services/menus'
import queryString from 'query-string'
const { prefix } = config
@@ -41,7 +42,7 @@ export default {
type: 'updateState',
payload: {
locationPathname: location.pathname,
locationQuery: location.query,
locationQuery: queryString.parse(location.search),
},
})
})
@@ -97,10 +98,10 @@ export default {
}
} else if (config.openPages && config.openPages.indexOf(locationPathname) < 0) {
yield put(routerRedux.push({
pathname: 'login',
query: {
pathname: '/login',
search: queryString.stringify({
from: locationPathname,
},
}),
}))
}
},
+2 -1
View File
@@ -1,6 +1,7 @@
import modelExtend from 'dva-model-extend'
import { query } from 'services/posts'
import { pageModel } from 'models/common'
import queryString from 'query-string'
export default modelExtend(pageModel, {
@@ -13,7 +14,7 @@ export default modelExtend(pageModel, {
dispatch({ type: 'query',
payload: {
status: 2,
...location.query,
...queryString.parse(location.search),
} })
}
})
+2 -1
View File
@@ -23,9 +23,10 @@ export default modelExtend(pageModel, {
setup ({ dispatch, history }) {
history.listen((location) => {
if (location.pathname === '/user') {
const payload = location.query || { current: 1, pageSize: 10 }
dispatch({
type: 'query',
payload: location.query,
payload,
})
}
})
+78 -135
View File
@@ -1,149 +1,92 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Router } from 'dva/router'
import { Switch, Route, Redirect, routerRedux } from 'dva/router'
import dynamic from 'dva/dynamic'
import App from 'routes/app'
const registerModel = (app, model) => {
if (!(app._models.filter(m => m.namespace === model.namespace).length === 1)) {
app.model(model)
}
}
const { ConnectedRouter } = routerRedux
const Routers = function ({ history, app }) {
const error = dynamic({
app,
component: () => import('./routes/error'),
})
const routes = [
{
path: '/',
component: App,
getIndexRoute (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/dashboard'))
cb(null, { component: require('routes/dashboard/') })
}, 'dashboard')
},
childRoutes: [
{
path: 'dashboard',
getComponent (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/dashboard'))
cb(null, require('routes/dashboard/'))
}, 'dashboard')
},
}, {
path: 'user',
getComponent (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/user'))
cb(null, require('routes/user/'))
}, 'user')
},
}, {
path: 'user/:id',
getComponent (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/user/detail'))
cb(null, require('routes/user/detail/'))
}, 'user-detail')
},
}, {
path: 'login',
getComponent (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/login'))
cb(null, require('routes/login/'))
}, 'login')
},
}, {
path: 'request',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/request/'))
}, 'request')
},
}, {
path: 'UIElement/iconfont',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/iconfont/'))
}, 'UIElement-iconfont')
},
}, {
path: 'UIElement/search',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/search/'))
}, 'UIElement-search')
},
}, {
path: 'UIElement/dropOption',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/dropOption/'))
}, 'UIElement-dropOption')
},
}, {
path: 'UIElement/layer',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/layer/'))
}, 'UIElement-layer')
},
}, {
path: 'UIElement/dataTable',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/dataTable/'))
}, 'UIElement-dataTable')
},
}, {
path: 'UIElement/editor',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/UIElement/editor/'))
}, 'UIElement-editor')
},
}, {
path: 'chart/lineChart',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/chart/lineChart/'))
}, 'chart-lineChart')
},
}, {
path: 'chart/barChart',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/chart/barChart/'))
}, 'chart-barChart')
},
}, {
path: 'chart/areaChart',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/chart/areaChart/'))
}, 'chart-areaChart')
},
}, {
path: 'post',
getComponent (nextState, cb) {
require.ensure([], (require) => {
registerModel(app, require('models/post'))
cb(null, require('routes/post/'))
}, 'post')
},
}, {
path: '*',
getComponent (nextState, cb) {
require.ensure([], (require) => {
cb(null, require('routes/error/'))
}, 'error')
},
},
],
path: '/dashboard',
models: () => [import('./models/dashboard')],
component: () => import('./routes/dashboard/'),
}, {
path: '/user',
models: () => [import('./models/user')],
component: () => import('./routes/user/'),
}, {
path: '/user/:id',
models: () => [import('./models/user/detail')],
component: () => import('./routes/user/detail/'),
}, {
path: '/login',
models: () => [import('./models/login')],
component: () => import('./routes/login/'),
}, {
path: '/request',
component: () => import('./routes/request/'),
}, {
path: '/UIElement/iconfont',
component: () => import('./routes/UIElement/iconfont/'),
}, {
path: '/UIElement/search',
component: () => import('./routes/UIElement/search/'),
}, {
path: '/UIElement/dropOption',
component: () => import('./routes/UIElement/dropOption/'),
}, {
path: '/UIElement/layer',
component: () => import('./routes/UIElement/layer/'),
}, {
path: '/UIElement/dataTable',
component: () => import('./routes/UIElement/dataTable/'),
}, {
path: '/UIElement/editor',
component: () => import('./routes/UIElement/editor/'),
}, {
path: '/chart/ECharts',
component: () => import('./routes/chart/ECharts/'),
}, {
path: '/chart/highCharts',
component: () => import('./routes/chart/highCharts/'),
}, {
path: '/chart/Recharts',
component: () => import('./routes/chart/Recharts/'),
}, {
path: '/post',
models: () => [import('./models/post')],
component: () => import('./routes/post/'),
},
]
return <Router history={history} routes={routes} />
return (
<ConnectedRouter history={history}>
<App>
<Switch>
<Route exact path="/" render={() => (<Redirect to="/dashboard" />)} />
{
routes.map(({ path, ...dynamics }, key) => (
<Route key={key}
exact
path={path}
component={dynamic({
app,
...dynamics,
})}
/>
))
}
<Route component={error} />
</Switch>
</App>
</ConnectedRouter>
)
}
Routers.propTypes = {
+47 -53
View File
@@ -1,53 +1,47 @@
.list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
li {
width: 120px;
text-align: center;
cursor: pointer;
height: 100px;
transition: all 0.5s ease;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 24px;
box-sizing: border-box;
border: solid 1px transparent;
justify-content: center;
&:hover {
border: solid 1px #f5f5f5;
}
}
.name {
margin-top: 8px;
}
:global {
.colorful-icon {
font-size: 36px;
}
.antdadmin {
font-size: 32px;
line-height: 1;
}
}
}
@media (min-width: 1600px) {
.list {
li {
width: 160px;
}
}
}
@media (max-width: 767px) {
.list {
li {
width: 100px;
}
}
}
.list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
li {
width: 120px;
text-align: center;
cursor: pointer;
height: 100px;
transition: all 0.5s ease;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 24px;
box-sizing: border-box;
border: solid 1px transparent;
justify-content: center;
&:hover {
border: solid 1px #f5f5f5;
}
}
.name {
margin-top: 8px;
}
.icon {
font-size: 32px;
line-height: 1;
}
}
@media (min-width: 1600px) {
.list {
li {
width: 160px;
}
}
}
@media (max-width: 767px) {
.list {
li {
width: 100px;
}
}
}
+5 -3
View File
@@ -7,6 +7,7 @@ import { connect } from 'dva'
import { Layout, Loader } from 'components'
import { classnames, config } from 'utils'
import { Helmet } from 'react-helmet'
import { withRouter } from 'dva/router'
import '../themes/index.less'
import './app.less'
import Error from './error'
@@ -36,6 +37,7 @@ const App = ({ children, dispatch, app, loading, location }) => {
const headerProps = {
menu,
user,
location,
siderFold,
isNavbar,
menuPopoverVisible,
@@ -75,13 +77,13 @@ const App = ({ children, dispatch, app, loading, location }) => {
}
if (openPages && openPages.includes(pathname)) {
return (<div>
<Loader spinning={loading.effects['app/query']} />
<Loader fullScreen spinning={loading.effects['app/query']} />
{children}
</div>)
}
return (
<div>
<Loader spinning={loading.effects['app/query']} />
<Loader fullScreen spinning={loading.effects['app/query']} />
<Helmet>
<title>ANTD ADMIN</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -116,4 +118,4 @@ App.propTypes = {
loading: PropTypes.object,
}
export default connect(({ app, loading }) => ({ app, loading }))(App)
export default withRouter(connect(({ app, loading }) => ({ app, loading }))(App))
@@ -0,0 +1,322 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts/map/js/china.js')
const AirportCoordComponent = React.createClass({
getOtion () {
let geoCoordMap = {
上海: [121.4648, 31.2891],
东莞: [113.8953, 22.901],
东营: [118.7073, 37.5513],
中山: [113.4229, 22.478],
临汾: [111.4783, 36.1615],
临沂: [118.3118, 35.2936],
丹东: [124.541, 40.4242],
丽水: [119.5642, 28.1854],
乌鲁木齐: [87.9236, 43.5883],
佛山: [112.8955, 23.1097],
保定: [115.0488, 39.0948],
兰州: [103.5901, 36.3043],
包头: [110.3467, 41.4899],
北京: [116.4551, 40.2539],
北海: [109.314, 21.6211],
南京: [118.8062, 31.9208],
南宁: [108.479, 23.1152],
南昌: [116.0046, 28.6633],
南通: [121.1023, 32.1625],
厦门: [118.1689, 24.6478],
台州: [121.1353, 28.6688],
合肥: [117.29, 32.0581],
呼和浩特: [111.4124, 40.4901],
咸阳: [108.4131, 34.8706],
哈尔滨: [127.9688, 45.368],
唐山: [118.4766, 39.6826],
嘉兴: [120.9155, 30.6354],
大同: [113.7854, 39.8035],
大连: [122.2229, 39.4409],
天津: [117.4219, 39.4189],
太原: [112.3352, 37.9413],
威海: [121.9482, 37.1393],
宁波: [121.5967, 29.6466],
宝鸡: [107.1826, 34.3433],
宿迁: [118.5535, 33.7775],
常州: [119.4543, 31.5582],
广州: [113.5107, 23.2196],
廊坊: [116.521, 39.0509],
延安: [109.1052, 36.4252],
张家口: [115.1477, 40.8527],
徐州: [117.5208, 34.3268],
德州: [116.6858, 37.2107],
惠州: [114.6204, 23.1647],
成都: [103.9526, 30.7617],
扬州: [119.4653, 32.8162],
承德: [117.5757, 41.4075],
拉萨: [91.1865, 30.1465],
无锡: [120.3442, 31.5527],
日照: [119.2786, 35.5023],
昆明: [102.9199, 25.4663],
杭州: [119.5313, 29.8773],
枣庄: [117.323, 34.8926],
柳州: [109.3799, 24.9774],
株洲: [113.5327, 27.0319],
武汉: [114.3896, 30.6628],
汕头: [117.1692, 23.3405],
江门: [112.6318, 22.1484],
沈阳: [123.1238, 42.1216],
沧州: [116.8286, 38.2104],
河源: [114.917, 23.9722],
泉州: [118.3228, 25.1147],
泰安: [117.0264, 36.0516],
泰州: [120.0586, 32.5525],
济南: [117.1582, 36.8701],
济宁: [116.8286, 35.3375],
海口: [110.3893, 19.8516],
淄博: [118.0371, 36.6064],
淮安: [118.927, 33.4039],
深圳: [114.5435, 22.5439],
清远: [112.9175, 24.3292],
温州: [120.498, 27.8119],
渭南: [109.7864, 35.0299],
湖州: [119.8608, 30.7782],
湘潭: [112.5439, 27.7075],
滨州: [117.8174, 37.4963],
潍坊: [119.0918, 36.524],
烟台: [120.7397, 37.5128],
玉溪: [101.9312, 23.8898],
珠海: [113.7305, 22.1155],
盐城: [120.2234, 33.5577],
盘锦: [121.9482, 41.0449],
石家庄: [114.4995, 38.1006],
福州: [119.4543, 25.9222],
秦皇岛: [119.2126, 40.0232],
绍兴: [120.564, 29.7565],
聊城: [115.9167, 36.4032],
肇庆: [112.1265, 23.5822],
舟山: [122.2559, 30.2234],
苏州: [120.6519, 31.3989],
莱芜: [117.6526, 36.2714],
菏泽: [115.6201, 35.2057],
营口: [122.4316, 40.4297],
葫芦岛: [120.1575, 40.578],
衡水: [115.8838, 37.7161],
衢州: [118.6853, 28.8666],
西宁: [101.4038, 36.8207],
西安: [109.1162, 34.2004],
贵阳: [106.6992, 26.7682],
连云港: [119.1248, 34.552],
邢台: [114.8071, 37.2821],
邯郸: [114.4775, 36.535],
郑州: [113.4668, 34.6234],
鄂尔多斯: [108.9734, 39.2487],
重庆: [107.7539, 30.1904],
金华: [120.0037, 29.1028],
铜川: [109.0393, 35.1947],
银川: [106.3586, 38.1775],
镇江: [119.4763, 31.9702],
长春: [125.8154, 44.2584],
长沙: [113.0823, 28.2568],
长治: [112.8625, 36.4746],
阳泉: [113.4778, 38.0951],
青岛: [120.4651, 36.3373],
韶关: [113.7964, 24.7028],
}
let BJData = [
[{ name: '北京' }, { name: '上海', value: 95 }],
[{ name: '北京' }, { name: '广州', value: 90 }],
[{ name: '北京' }, { name: '大连', value: 80 }],
[{ name: '北京' }, { name: '南宁', value: 70 }],
[{ name: '北京' }, { name: '南昌', value: 60 }],
[{ name: '北京' }, { name: '拉萨', value: 50 }],
[{ name: '北京' }, { name: '长春', value: 40 }],
[{ name: '北京' }, { name: '包头', value: 30 }],
[{ name: '北京' }, { name: '重庆', value: 20 }],
[{ name: '北京' }, { name: '常州', value: 10 }],
]
let SHData = [
[{ name: '上海' }, { name: '包头', value: 95 }],
[{ name: '上海' }, { name: '昆明', value: 90 }],
[{ name: '上海' }, { name: '广州', value: 80 }],
[{ name: '上海' }, { name: '郑州', value: 70 }],
[{ name: '上海' }, { name: '长春', value: 60 }],
[{ name: '上海' }, { name: '重庆', value: 50 }],
[{ name: '上海' }, { name: '长沙', value: 40 }],
[{ name: '上海' }, { name: '北京', value: 30 }],
[{ name: '上海' }, { name: '丹东', value: 20 }],
[{ name: '上海' }, { name: '大连', value: 10 }],
]
let GZData = [
[{ name: '广州' }, { name: '福州', value: 95 }],
[{ name: '广州' }, { name: '太原', value: 90 }],
[{ name: '广州' }, { name: '长春', value: 80 }],
[{ name: '广州' }, { name: '重庆', value: 70 }],
[{ name: '广州' }, { name: '西安', value: 60 }],
[{ name: '广州' }, { name: '成都', value: 50 }],
[{ name: '广州' }, { name: '常州', value: 40 }],
[{ name: '广州' }, { name: '北京', value: 30 }],
[{ name: '广州' }, { name: '北海', value: 20 }],
[{ name: '广州' }, { name: '海口', value: 10 }],
]
let planePath = 'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z'
let convertData = function (data) {
let res = []
for (let i = 0; i < data.length; i += 1) {
let dataItem = data[i]
let fromCoord = geoCoordMap[dataItem[0].name]
let toCoord = geoCoordMap[dataItem[1].name]
if (fromCoord && toCoord) {
res.push({
fromName: dataItem[0].name,
toName: dataItem[1].name,
coords: [fromCoord, toCoord],
})
}
}
return res
}
let color = ['#a6c84c', '#ffa022', '#46bee9']
let series = [];
[['北京', BJData], ['上海', SHData], ['广州', GZData]].forEach((item, i) => {
series.push({
name: `${item[0]} Top10`,
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 6,
trailLength: 0.7,
color: '#fff',
symbolSize: 3,
},
lineStyle: {
normal: {
color: color[i],
width: 0,
curveness: 0.2,
},
},
data: convertData(item[1]),
},
{
name: `${item[0]} Top10`,
type: 'lines',
zlevel: 2,
symbol: ['none', 'arrow'],
symbolSize: 10,
effect: {
show: true,
period: 6,
trailLength: 0,
symbol: planePath,
symbolSize: 15,
},
lineStyle: {
normal: {
color: color[i],
width: 1,
opacity: 0.6,
curveness: 0.2,
},
},
data: convertData(item[1]),
},
{
name: `${item[0]} Top10`,
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
brushType: 'stroke',
},
label: {
normal: {
show: true,
position: 'right',
formatter: '{b}',
},
},
symbolSize (val) {
return val[2] / 8
},
itemStyle: {
normal: {
color: color[i],
},
},
data: item[1].map((dataItem) => {
return {
name: dataItem[1].name,
value: geoCoordMap[dataItem[1].name].concat([dataItem[1].value]),
}
}),
})
})
let option = {
backgroundColor: '#404a59',
title: {
text: '模拟迁徙',
subtext: '数据纯属虚构',
left: 'center',
textStyle: {
color: '#fff',
},
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
top: 'bottom',
left: 'right',
data: ['北京 Top10', '上海 Top10', '广州 Top10'],
textStyle: {
color: '#fff',
},
selectedMode: 'single',
},
geo: {
map: 'china',
label: {
emphasis: {
show: false,
},
},
roam: true,
itemStyle: {
normal: {
areaColor: '#323c48',
borderColor: '#404a59',
},
emphasis: {
areaColor: '#2a333d',
},
},
},
series,
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a airport chart. </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default AirportCoordComponent
@@ -0,0 +1,111 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const currentData = [
[[28604, 77, 17096869, 'Australia', 1990], [31163, 77.4, 27662440, 'Canada', 1990], [1516, 68, 1154605773, 'China', 1990], [13670, 74.7, 10582082, 'Cuba', 1990], [28599, 75, 4986705, 'Finland', 1990], [29476, 77.1, 56943299, 'France', 1990], [31476, 75.4, 78958237, 'Germany', 1990], [28666, 78.1, 254830, 'Iceland', 1990], [1777, 57.7, 870601776, 'India', 1990], [29550, 79.1, 122249285, 'Japan', 1990], [2076, 67.9, 20194354, 'North Korea', 1990], [12087, 72, 42972254, 'South Korea', 1990], [24021, 75.4, 3397534, 'New Zealand', 1990], [43296, 76.8, 4240375, 'Norway', 1990], [10088, 70.8, 38195258, 'Poland', 1990], [19349, 69.6, 147568552, 'Russia', 1990], [10670, 67.3, 53994605, 'Turkey', 1990], [26424, 75.7, 57110117, 'United Kingdom', 1990], [37062, 75.4, 252847810, 'United States', 1990]],
[[44056, 81.8, 23968973, 'Australia', 2015], [43294, 81.7, 35939927, 'Canada', 2015], [13334, 76.9, 1376048943, 'China', 2015], [21291, 78.5, 11389562, 'Cuba', 2015], [38923, 80.8, 5503457, 'Finland', 2015], [37599, 81.9, 64395345, 'France', 2015], [44053, 81.1, 80688545, 'Germany', 2015], [42182, 82.8, 329425, 'Iceland', 2015], [5903, 66.8, 1311050527, 'India', 2015], [36162, 83.5, 126573481, 'Japan', 2015], [1390, 71.4, 25155317, 'North Korea', 2015], [34644, 80.7, 50293439, 'South Korea', 2015], [34186, 80.6, 4528526, 'New Zealand', 2015], [64304, 81.6, 5210967, 'Norway', 2015], [24787, 77.3, 38611794, 'Poland', 2015], [23038, 73.13, 143456918, 'Russia', 2015], [19360, 76.5, 78665830, 'Turkey', 2015], [38225, 81.4, 64715810, 'United Kingdom', 2015], [53354, 79.1, 321773631, 'United States', 2015]],
]
const option = {
backgroundColor: new echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [{
offset: 0,
color: '#f7f8fa',
}, {
offset: 1,
color: '#cdd0d5',
}]),
title: {
text: '1990 与 2015 年各国家人均寿命与 GDP',
},
legend: {
right: 10,
data: ['1990', '2015'],
},
xAxis: {
splitLine: {
lineStyle: {
type: 'dashed',
},
},
},
yAxis: {
splitLine: {
lineStyle: {
type: 'dashed',
},
},
scale: true,
},
series: [{
name: '1990',
data: currentData[0],
type: 'scatter',
symbolSize (data) {
return Math.sqrt(data[2]) / 5e2
},
label: {
emphasis: {
show: true,
formatter (param) {
return param.data[3]
},
position: 'top',
},
},
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(120, 36, 50, 0.5)',
shadowOffsetY: 5,
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{
offset: 0,
color: 'rgb(251, 118, 123)',
}, {
offset: 1,
color: 'rgb(204, 46, 72)',
}]),
},
},
}, {
name: '2015',
data: currentData[1],
type: 'scatter',
symbolSize (data) {
return Math.sqrt(data[2]) / 5e2
},
label: {
emphasis: {
show: true,
formatter (param) {
return param.data[3]
},
position: 'top',
},
},
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(25, 100, 150, 0.5)',
shadowOffsetY: 5,
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{
offset: 0,
color: 'rgb(129, 227, 238)',
}, {
offset: 1,
color: 'rgb(25, 183, 207)',
}]),
},
},
}],
}
const BubbleGradientComponent = () => {
return (<ReactEcharts
option={option}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>)
}
export default BubbleGradientComponent
@@ -0,0 +1,200 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const CalendarComponent = React.createClass({
getVirtulData (year) {
year = year || '2017'
let date = +echarts.number.parseDate(`${year}-01-01`)
let end = +echarts.number.parseDate(`${+year + 1}-01-01`)
let dayTime = 3600 * 24 * 1000
let data = []
for (let time = date; time < end; time += dayTime) {
data.push([
echarts.format.formatTime('yyyy-MM-dd', time),
Math.floor(Math.random() * 1000),
])
}
return data
},
getOtion () {
let graphData = [[
1485878400000,
260,
], [
1486137600000,
200,
], [
1486569600000,
279,
], [
1486915200000,
847,
], [
1487347200000,
241,
], [
1487779200000,
411,
], [
1488124800000,
985,
],
]
let links = graphData.map((item, idx) => {
return {
source: idx,
target: idx + 1,
}
})
links.pop()
const option = {
tooltip: {
position: 'top',
},
visualMap: [{
min: 0,
max: 1000,
calculable: true,
seriesIndex: [2, 3, 4],
orient: 'horizontal',
left: '55%',
bottom: 20,
}, {
min: 0,
max: 1000,
inRange: {
color: ['grey'],
opacity: [0, 0.3],
},
controller: {
inRange: {
opacity: [0.3, 0.6],
},
outOfRange: {
color: '#ccc',
},
},
calculable: true,
seriesIndex: [1],
orient: 'horizontal',
left: '10%',
bottom: 20,
}],
calendar: [
{
orient: 'vertical',
yearLabel: {
margin: 40,
},
monthLabel: {
nameMap: 'cn',
margin: 20,
},
dayLabel: {
firstDay: 1,
nameMap: 'cn',
},
cellSize: 40,
range: '2017-02',
},
{
orient: 'vertical',
yearLabel: {
margin: 40,
},
monthLabel: {
margin: 20,
},
cellSize: 40,
left: 460,
range: '2017-01',
},
{
orient: 'vertical',
yearLabel: {
margin: 40,
},
monthLabel: {
margin: 20,
},
cellSize: 40,
top: 350,
range: '2017-03',
},
{
orient: 'vertical',
yearLabel: {
margin: 40,
},
dayLabel: {
firstDay: 1,
nameMap: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
},
monthLabel: {
nameMap: 'cn',
margin: 20,
},
cellSize: 40,
top: 350,
left: 460,
range: '2017-04',
}],
series: [{
type: 'graph',
edgeSymbol: ['none', 'arrow'],
coordinateSystem: 'calendar',
links,
symbolSize: 10,
calendarIndex: 0,
data: graphData,
}, {
type: 'heatmap',
coordinateSystem: 'calendar',
data: this.getVirtulData(2017),
}, {
type: 'effectScatter',
coordinateSystem: 'calendar',
calendarIndex: 1,
symbolSize (val) {
return val[1] / 40
},
data: this.getVirtulData(2017),
}, {
type: 'scatter',
coordinateSystem: 'calendar',
calendarIndex: 2,
symbolSize (val) {
return val[1] / 60
},
data: this.getVirtulData(2017),
}, {
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 3,
data: this.getVirtulData(2017),
}],
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a calendar-charts </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default CalendarComponent
@@ -0,0 +1,122 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const ChartAPIComponent = React.createClass({
propTypes: {
},
getOtion () {
const option = {
title: {
text: '漏斗图',
subtext: '纯属虚构',
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%',
},
toolbox: {
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {},
},
},
legend: {
data: ['展现', '点击', '访问', '咨询', '订单'],
},
series: [
{
name: '预期',
type: 'funnel',
left: '10%',
width: '80%',
label: {
normal: {
formatter: '{b}预期',
},
emphasis: {
position: 'inside',
formatter: '{b}预期: {c}%',
},
},
labelLine: {
normal: {
show: false,
},
},
itemStyle: {
normal: {
opacity: 0.7,
},
},
data: [
{ value: 60, name: '访问' },
{ value: 40, name: '咨询' },
{ value: 20, name: '订单' },
{ value: 80, name: '点击' },
{ value: 100, name: '展现' },
],
},
{
name: '实际',
type: 'funnel',
left: '10%',
width: '80%',
maxSize: '80%',
label: {
normal: {
position: 'inside',
formatter: '{c}%',
textStyle: {
color: '#fff',
},
},
emphasis: {
position: 'inside',
formatter: '{b}实际: {c}%',
},
},
itemStyle: {
normal: {
opacity: 0.5,
borderColor: '#fff',
borderWidth: 2,
},
},
data: [
{ value: 30, name: '访问' },
{ value: 10, name: '咨询' },
{ value: 5, name: '订单' },
{ value: 50, name: '点击' },
{ value: 80, name: '展现' },
],
},
],
}
return option
},
render () {
let code = '<ReactEcharts ref={(e) => { this.echarts_react = e; }} \n' +
' option={this.getOtion()} /> \n' +
'\n' +
'// use echarts API: http://echarts.baidu.com/api.html#echartsInstance' +
'this.echarts_react.getEchartsInstance().getDataURL();'
return (
<div className="examples">
<div className="parent">
<label> use echarts API With <strong> getEchartsInstance() </strong>: (the API will return the echarts instance, then you can use any API of echarts.)</label>
<ReactEcharts ref={(e) => { this.echarts_react = e }}
option={this.getOtion()}
/>
<label> code below: (echarts API list see: http://echarts.baidu.com/api.html#echartsInstance)</label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default ChartAPIComponent
@@ -0,0 +1,94 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const ChartShowLoadingComponent = React.createClass({
propTypes: {
},
componentWillUnmount () {
clearTimeout(this._t)
},
onChartReady (chart) {
this._t = setTimeout(() => {
chart.hideLoading()
}, 3000)
},
getOtion () {
const option = {
title: {
text: '基础雷达图',
},
tooltip: {},
legend: {
data: ['预算分配(Allocated Budget)', '实际开销(Actual Spending)'],
},
radar: {
// shape: 'circle',
indicator: [
{ name: '销售(sales)', max: 6500 },
{ name: '管理(Administration)', max: 16000 },
{ name: '信息技术(Information Techology)', max: 30000 },
{ name: '客服(Customer Support)', max: 38000 },
{ name: '研发(Development)', max: 52000 },
{ name: '市场(Marketing)', max: 25000 },
],
},
series: [{
name: '预算 vs 开销(Budget vs spending)',
type: 'radar',
// areaStyle: {normal: {}},
data: [
{
value: [4300, 10000, 28000, 35000, 50000, 19000],
name: '预算分配(Allocated Budget)',
},
{
value: [5000, 14000, 28000, 31000, 42000, 21000],
name: '实际开销(Actual Spending)',
},
],
}],
}
return option
},
getLoadingOption () {
const option = {
text: '加载中...',
color: '#4413c2',
textColor: '#270240',
maskColor: 'rgba(194, 88, 86, 0.3)',
zlevel: 0,
}
return option
},
_t: null,
render () {
let code = 'onChartReady: function(chart) {\n' +
" 'chart.hideLoading();\n" +
'}\n\n' +
'<ReactEcharts \n' +
' option={this.getOtion()} \n' +
' onChartReady={this.onChartReady} \n' +
' loadingOption={this.getLoadingOption()} \n' +
' showLoading={true} />'
return (
<div className="examples">
<div className="parent">
<label> Chart loading With <strong> showLoading </strong>: (when chart ready, hide the loading mask.)</label>
<ReactEcharts
option={this.getOtion()}
onChartReady={this.onChartReady}
loadingOption={this.getLoadingOption()}
showLoading
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default ChartShowLoadingComponent
@@ -0,0 +1,92 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const ChartWithEventComponent = React.createClass({
propTypes: {
},
onChartReady (echart) {
console.log('echart is ready', echart)
},
onChartLegendselectchanged (param, echart) {
console.log(param, echart)
},
onChartClick (param, echart) {
console.log(param, echart)
},
getOtion () {
const option = {
title: {
text: '某站点用户访问来源',
subtext: '纯属虚构',
x: 'center',
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)',
},
legend: {
orient: 'vertical',
left: 'left',
data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'],
},
series: [
{
name: '访问来源',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [
{ value: 335, name: '直接访问' },
{ value: 310, name: '邮件营销' },
{ value: 234, name: '联盟广告' },
{ value: 135, name: '视频广告' },
{ value: 1548, name: '搜索引擎' },
],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
}
return option
},
render () {
let onEvents = {
click: this.onChartClick,
legendselectchanged: this.onChartLegendselectchanged,
}
let code = 'let onEvents = {\n' +
" 'click': this.onChartClick,\n" +
" 'legendselectchanged': this.onChartLegendselectchanged\n" +
'}\n\n' +
'<ReactEcharts \n' +
' option={this.getOtion()} \n' +
' style={{height: 300}} \n' +
' onChartReady={this.onChartReady} \n' +
' onEvents={onEvents} />'
return (
<div className="examples">
<div className="parent">
<label> Chart With event <strong> onEvents </strong>: (Click the chart, and watch the console)</label>
<ReactEcharts
option={this.getOtion()}
style={{ height: 300 }}
onChartReady={this.onChartReady}
onEvents={onEvents}
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default ChartWithEventComponent
@@ -0,0 +1,190 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const DynamicChartComponent = React.createClass({
propTypes: {
},
timeTicket: null,
count: 51,
getInitialState () {
return { option: this.getOption() }
},
fetchNewDate () {
let axisData = (new Date()).toLocaleTimeString().replace(/^\D*/, '')
let option = this.state.option
option.title.text = `Hello Echarts-for-react.${new Date().getSeconds()}`
let data0 = option.series[0].data
let data1 = option.series[1].data
data0.shift()
data0.push(Math.round(Math.random() * 1000))
data1.shift()
data1.push((Math.random() * 10 + 5).toFixed(1) - 0)
option.xAxis[0].data.shift()
option.xAxis[0].data.push(axisData)
option.xAxis[1].data.shift()
option.xAxis[1].data.push(this.count += 1)
this.setState({ option })
},
componentDidMount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
this.timeTicket = setInterval(this.fetchNewDate, 1000)
},
componentWillUnmount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
},
getOption () {
const option = {
title: {
text: 'Hello Echarts-for-react.',
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['最新成交价', '预购队列'],
},
toolbox: {
show: true,
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {},
},
},
grid: {
top: 60,
left: 30,
right: 60,
bottom: 30,
},
dataZoom: {
show: false,
start: 0,
end: 100,
},
visualMap: {
show: false,
min: 0,
max: 1000,
color: ['#BE002F', '#F20C00', '#F00056', '#FF2D51', '#FF2121', '#FF4C00', '#FF7500',
'#FF8936', '#FFA400', '#F0C239', '#FFF143', '#FAFF72', '#C9DD22', '#AFDD22',
'#9ED900', '#00E500', '#0EB83A', '#0AA344', '#0C8918', '#057748', '#177CB0'],
},
xAxis: [
{
type: 'category',
boundaryGap: true,
data: (function () {
let now = new Date()
let res = []
let len = 50
while (len--) {
res.unshift(now.toLocaleTimeString().replace(/^\D*/, ''))
now = new Date(now - 2000)
}
return res
}()),
},
{
type: 'category',
boundaryGap: true,
data: (function () {
let res = []
let len = 50
while (len--) {
res.push(50 - len + 1)
}
return res
}()),
},
],
yAxis: [
{
type: 'value',
scale: true,
name: '价格',
max: 20,
min: 0,
boundaryGap: [0.2, 0.2],
},
{
type: 'value',
scale: true,
name: '预购量',
max: 1200,
min: 0,
boundaryGap: [0.2, 0.2],
},
],
series: [
{
name: '预购队列',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
itemStyle: {
normal: {
barBorderRadius: 4,
},
},
animationEasing: 'elasticOut',
animationDelay (idx) {
return idx * 10
},
animationDelayUpdate (idx) {
return idx * 10
},
data: (function () {
let res = []
let len = 50
while (len--) {
res.push(Math.round(Math.random() * 1000))
}
return res
}()),
},
{
name: '最新成交价',
type: 'line',
data: (function () {
let res = []
let len = 0
while (len < 50) {
res.push((Math.random() * 10 + 5).toFixed(1) - 0)
len++
}
return res
}()),
},
],
}
return option
},
render () {
let code = "<ReactEcharts ref='echartsInstance' \n" +
' option={this.state.option} />\n'
return (
<div className="examples">
<div className="parent">
<label> use React state to render dynamic chart</label>
<ReactEcharts ref="echarts_react"
option={this.state.option}
style={{ height: 400 }}
/>
<label> code below: use state of react to render dynamic chart</label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default DynamicChartComponent
@@ -0,0 +1,51 @@
import React from 'react'
import PropTypes from 'prop-types'
import SimpleChartComponent from './SimpleChartComponent'
import ChartWithEventComponent from './ChartWithEventComponent'
import ThemeChartComponent from './ThemeChartComponent'
import ChartShowLoadingComponent from './ChartShowLoadingComponent'
import ChartAPIComponent from './ChartAPIComponent'
import DynamicChartComponent from './DynamicChartComponent'
import MapChartComponent from './MapChartComponent'
// v1.2.0 add 7 demo.
import AirportCoordComponent from './AirportCoordComponent'
import CalendarComponent from './CalendarComponent'
import GaugeComponent from './GaugeComponent'
import GCalendarComponent from './GCalendarComponent'
import GraphComponent from './GraphComponent'
import LunarCalendarComponent from './LunarCalendarComponent'
import TreemapComponent from './TreemapComponent'
import LiquidfillComponent from './LiquidfillComponent'
import BubbleGradientComponent from './BubbleGradientComponent'
import TransparentBar3DComPonent from './TransparentBar3DComPonent'
import MoonComponent from './MoonComponent'
const EchartsComponent = ({ type }) => {
if (type === 'simple') return (<SimpleChartComponent />)
if (type === 'loading') return (<ChartShowLoadingComponent />)
if (type === 'api') return (<ChartAPIComponent />)
if (type === 'events') return (<ChartWithEventComponent />)
if (type === 'theme') return (<ThemeChartComponent />)
if (type === 'dynamic') return (<DynamicChartComponent />)
if (type === 'map') return (<MapChartComponent />)
if (type === 'airport') return (<AirportCoordComponent />)
if (type === 'graph') return (<GraphComponent />)
if (type === 'calendar') return (<CalendarComponent />)
if (type === 'treemap') return (<TreemapComponent />)
if (type === 'gauge') return (<GaugeComponent />)
if (type === 'gcalendar') return (<GCalendarComponent />)
if (type === 'lunar') return (<LunarCalendarComponent />)
if (type === 'liquid') return (<LiquidfillComponent />)
if (type === 'BubbleGradientComponent') return (<BubbleGradientComponent />)
if (type === 'TransparentBar3DComPonent') return (<TransparentBar3DComPonent />)
if (type === 'MoonComponent') return (<MoonComponent />)
return (<DynamicChartComponent />)
}
EchartsComponent.propTypes = {
type: PropTypes.string,
}
export default EchartsComponent
@@ -0,0 +1,73 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const GCalendarComponent = React.createClass({
getVirtulData (year) {
year = year || '2017'
let date = +echarts.number.parseDate(`${year}-01-01`)
let end = +echarts.number.parseDate(`${+year + 1}-01-01`)
let dayTime = 3600 * 24 * 1000
let data = []
for (let time = date; time < end; time += dayTime) {
data.push([
echarts.format.formatTime('yyyy-MM-dd', time),
Math.floor(Math.random() * 1000),
])
}
return data
},
getOtion () {
const option = {
tooltip: {
position: 'top',
},
visualMap: {
min: 0,
max: 1000,
calculable: true,
orient: 'horizontal',
left: 'center',
top: 'top',
},
calendar: [{
range: '2017',
cellSize: ['auto', 20],
}, {
top: 260,
range: '2016',
cellSize: ['auto', 20],
}],
series: [{
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 0,
data: this.getVirtulData(2017),
}, {
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 1,
data: this.getVirtulData(2016),
}],
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a calendar like github commit history. </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default GCalendarComponent
+326
View File
@@ -0,0 +1,326 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const GaugeComponent = React.createClass({
getInitialState () {
return { option: this.getOtion() }
},
componentDidMount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
this.timeTicket = setInterval(() => {
let option = this.state.option
option.series[0].data[0].value = (Math.random() * 100).toFixed(2) - 0
option.series[1].data[0].value = (Math.random() * 7).toFixed(2) - 0
option.series[2].data[0].value = (Math.random() * 2).toFixed(2) - 0
option.series[3].data[0].value = (Math.random() * 2).toFixed(2) - 0
this.setState({ option })
}, 1000)
},
componentWillUnmount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
},
getOtion () {
let option = {
backgroundColor: '#1b1b1b',
tooltip: {
formatter: '{a} <br/>{c} {b}',
},
toolbox: {
show: true,
feature: {
mark: { show: true },
restore: { show: true },
saveAsImage: { show: true },
},
},
series: [
{
name: '速度',
type: 'gauge',
min: 0,
max: 220,
splitNumber: 11,
radius: '50%',
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [[0.09, 'lime'], [0.82, '#1e90ff'], [1, '#ff4500']],
width: 3,
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisLabel: { // 坐标轴小标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisTick: { // 坐标轴小标记
length: 15, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
splitLine: { // 分隔线
length: 25, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 3,
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
pointer: { // 分隔线
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
},
title: {
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
fontWeight: 'bolder',
fontSize: 20,
fontStyle: 'italic',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
detail: {
backgroundColor: 'rgba(30,144,255,0.8)',
borderWidth: 1,
borderColor: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
offsetCenter: [0, '50%'], // x, y,单位px
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
fontWeight: 'bolder',
color: '#fff',
},
},
data: [{ value: 40, name: 'km/h' }],
},
{
name: '转速',
type: 'gauge',
center: ['25%', '55%'], // 默认全局居中
radius: '30%',
min: 0,
max: 7,
endAngle: 45,
splitNumber: 7,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [[0.29, 'lime'], [0.86, '#1e90ff'], [1, '#ff4500']],
width: 2,
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisLabel: { // 坐标轴小标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisTick: { // 坐标轴小标记
length: 12, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
splitLine: { // 分隔线
length: 20, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 3,
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
pointer: {
width: 5,
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
},
title: {
offsetCenter: [0, '-30%'], // x, y,单位px
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
fontWeight: 'bolder',
fontStyle: 'italic',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
detail: {
// backgroundColor: 'rgba(30,144,255,0.8)',
// borderWidth: 1,
borderColor: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
width: 80,
height: 30,
offsetCenter: [25, '20%'], // x, y,单位px
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
fontWeight: 'bolder',
color: '#fff',
},
},
data: [{ value: 1.5, name: 'x1000 r/min' }],
},
{
name: '油表',
type: 'gauge',
center: ['75%', '50%'], // 默认全局居中
radius: '30%',
min: 0,
max: 2,
startAngle: 135,
endAngle: 45,
splitNumber: 2,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [[0.2, 'lime'], [0.8, '#1e90ff'], [1, '#ff4500']],
width: 2,
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisTick: { // 坐标轴小标记
length: 12, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisLabel: {
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
formatter (v) {
switch (`${v}`) {
case '0' : return 'E'
case '1' : return 'Gas'
case '2' : return 'F'
default : return null
}
},
},
splitLine: { // 分隔线
length: 15, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 3,
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
pointer: {
width: 2,
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
},
title: {
show: false,
},
detail: {
show: false,
},
data: [{ value: 0.5, name: 'gas' }],
},
{
name: '水表',
type: 'gauge',
center: ['75%', '50%'], // 默认全局居中
radius: '30%',
min: 0,
max: 2,
startAngle: 315,
endAngle: 225,
splitNumber: 2,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [[0.2, 'lime'], [0.8, '#1e90ff'], [1, '#ff4500']],
width: 2,
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
axisTick: { // 坐标轴小标记
show: false,
},
axisLabel: {
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
formatter (v) {
switch (`${v}`) {
case '0' : return 'H'
case '1' : return 'Water'
case '2' : return 'C'
default : return null
}
},
},
splitLine: { // 分隔线
length: 15, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 3,
color: '#fff',
shadowColor: '#fff', // 默认透明
shadowBlur: 10,
},
},
pointer: {
width: 2,
shadowColor: '#fff', // 默认透明
shadowBlur: 5,
},
title: {
show: false,
},
detail: {
show: false,
},
data: [{ value: 0.5, name: 'gas' }],
},
],
}
return option
},
timeTicket: null,
render () {
return (
<div className="examples">
<div className="parent">
<label> render a car gauge chart. </label>
<ReactEcharts
option={this.state.option}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default GaugeComponent
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts-liquidfill')
const LiquidfillComponent = React.createClass({
propTypes: {
},
getOption () {
let option = {
series: [{
type: 'liquidFill',
data: [0.6],
}],
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a Liquidfill chart: </label>
<ReactEcharts
option={this.getOption()}
style={{ height: '400px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default LiquidfillComponent
@@ -0,0 +1,493 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const LunarCalendarComponent = React.createClass({
getOtion () {
let dateList = [
['2017-1-1', '初四'],
['2017-1-2', '初五'],
['2017-1-3', '初六'],
['2017-1-4', '初七'],
['2017-1-5', '初八', '小寒'],
['2017-1-6', '初九'],
['2017-1-7', '初十'],
['2017-1-8', '十一'],
['2017-1-9', '十二'],
['2017-1-10', '十三'],
['2017-1-11', '十四'],
['2017-1-12', '十五'],
['2017-1-13', '十六'],
['2017-1-14', '十七'],
['2017-1-15', '十八'],
['2017-1-16', '十九'],
['2017-1-17', '二十'],
['2017-1-18', '廿一'],
['2017-1-19', '廿二'],
['2017-1-20', '廿三', '大寒'],
['2017-1-21', '廿四'],
['2017-1-22', '廿五'],
['2017-1-23', '廿六'],
['2017-1-24', '廿七'],
['2017-1-25', '廿八'],
['2017-1-26', '廿九'],
['2017-1-27', '三十'],
['2017-1-28', '正月'],
['2017-1-29', '初二'],
['2017-1-30', '初三'],
['2017-1-31', '初四'],
['2017-2-1', '初五'],
['2017-2-2', '初六'],
['2017-2-3', '初七', '立春'],
['2017-2-4', '初八'],
['2017-2-5', '初九'],
['2017-2-6', '初十'],
['2017-2-7', '十一'],
['2017-2-8', '十二'],
['2017-2-9', '十三'],
['2017-2-10', '十四'],
['2017-2-11', '十五'],
['2017-2-12', '十六'],
['2017-2-13', '十七'],
['2017-2-14', '十八'],
['2017-2-15', '十九'],
['2017-2-16', '二十'],
['2017-2-17', '廿一'],
['2017-2-18', '廿二', '雨水'],
['2017-2-19', '廿三'],
['2017-2-20', '廿四'],
['2017-2-21', '廿五'],
['2017-2-22', '廿六'],
['2017-2-23', '廿七'],
['2017-2-24', '廿八'],
['2017-2-25', '廿九'],
['2017-2-26', '二月'],
['2017-2-27', '初二'],
['2017-2-28', '初三'],
['2017-3-1', '初四'],
['2017-3-2', '初五'],
['2017-3-3', '初六'],
['2017-3-4', '初七'],
['2017-3-5', '初八', '驚蟄'],
['2017-3-6', '初九'],
['2017-3-7', '初十'],
['2017-3-8', '十一'],
['2017-3-9', '十二'],
['2017-3-10', '十三'],
['2017-3-11', '十四'],
['2017-3-12', '十五'],
['2017-3-13', '十六'],
['2017-3-14', '十七'],
['2017-3-15', '十八'],
['2017-3-16', '十九'],
['2017-3-17', '二十'],
['2017-3-18', '廿一'],
['2017-3-19', '廿二'],
['2017-3-20', '廿三', '春分'],
['2017-3-21', '廿四'],
['2017-3-22', '廿五'],
['2017-3-23', '廿六'],
['2017-3-24', '廿七'],
['2017-3-25', '廿八'],
['2017-3-26', '廿九'],
['2017-3-27', '三十'],
['2017-3-28', '三月'],
['2017-3-29', '初二'],
['2017-3-30', '初三'],
['2017-3-31', '初四'],
['2017-4-1', '初五'],
['2017-4-2', '初六'],
['2017-4-3', '初七'],
['2017-4-4', '初八', '清明'],
['2017-4-5', '初九'],
['2017-4-6', '初十'],
['2017-4-7', '十一'],
['2017-4-8', '十二'],
['2017-4-9', '十三'],
['2017-4-10', '十四'],
['2017-4-11', '十五'],
['2017-4-12', '十六'],
['2017-4-13', '十七'],
['2017-4-14', '十八'],
['2017-4-15', '十九'],
['2017-4-16', '二十'],
['2017-4-17', '廿一'],
['2017-4-18', '廿二'],
['2017-4-19', '廿三'],
['2017-4-20', '廿四', '穀雨'],
['2017-4-21', '廿五'],
['2017-4-22', '廿六'],
['2017-4-23', '廿七'],
['2017-4-24', '廿八'],
['2017-4-25', '廿九'],
['2017-4-26', '四月'],
['2017-4-27', '初二'],
['2017-4-28', '初三'],
['2017-4-29', '初四'],
['2017-4-30', '初五'],
['2017-5-1', '初六'],
['2017-5-2', '初七'],
['2017-5-3', '初八'],
['2017-5-4', '初九'],
['2017-5-5', '初十', '立夏'],
['2017-5-6', '十一'],
['2017-5-7', '十二'],
['2017-5-8', '十三'],
['2017-5-9', '十四'],
['2017-5-10', '十五'],
['2017-5-11', '十六'],
['2017-5-12', '十七'],
['2017-5-13', '十八'],
['2017-5-14', '十九'],
['2017-5-15', '二十'],
['2017-5-16', '廿一'],
['2017-5-17', '廿二'],
['2017-5-18', '廿三'],
['2017-5-19', '廿四'],
['2017-5-20', '廿五'],
['2017-5-21', '廿六', '小滿'],
['2017-5-22', '廿七'],
['2017-5-23', '廿八'],
['2017-5-24', '廿九'],
['2017-5-25', '三十'],
['2017-5-26', '五月'],
['2017-5-27', '初二'],
['2017-5-28', '初三'],
['2017-5-29', '初四'],
['2017-5-30', '初五'],
['2017-5-31', '初六'],
['2017-6-1', '初七'],
['2017-6-2', '初八'],
['2017-6-3', '初九'],
['2017-6-4', '初十'],
['2017-6-5', '十一', '芒種'],
['2017-6-6', '十二'],
['2017-6-7', '十三'],
['2017-6-8', '十四'],
['2017-6-9', '十五'],
['2017-6-10', '十六'],
['2017-6-11', '十七'],
['2017-6-12', '十八'],
['2017-6-13', '十九'],
['2017-6-14', '二十'],
['2017-6-15', '廿一'],
['2017-6-16', '廿二'],
['2017-6-17', '廿三'],
['2017-6-18', '廿四'],
['2017-6-19', '廿五'],
['2017-6-20', '廿六'],
['2017-6-21', '廿七', '夏至'],
['2017-6-22', '廿八'],
['2017-6-23', '廿九'],
['2017-6-24', '六月'],
['2017-6-25', '初二'],
['2017-6-26', '初三'],
['2017-6-27', '初四'],
['2017-6-28', '初五'],
['2017-6-29', '初六'],
['2017-6-30', '初七'],
['2017-7-1', '初八'],
['2017-7-2', '初九'],
['2017-7-3', '初十'],
['2017-7-4', '十一'],
['2017-7-5', '十二'],
['2017-7-6', '十三'],
['2017-7-7', '十四', '小暑'],
['2017-7-8', '十五'],
['2017-7-9', '十六'],
['2017-7-10', '十七'],
['2017-7-11', '十八'],
['2017-7-12', '十九'],
['2017-7-13', '二十'],
['2017-7-14', '廿一'],
['2017-7-15', '廿二'],
['2017-7-16', '廿三'],
['2017-7-17', '廿四'],
['2017-7-18', '廿五'],
['2017-7-19', '廿六'],
['2017-7-20', '廿七'],
['2017-7-21', '廿八'],
['2017-7-22', '廿九', '大暑'],
['2017-7-23', '閏六'],
['2017-7-24', '初二'],
['2017-7-25', '初三'],
['2017-7-26', '初四'],
['2017-7-27', '初五'],
['2017-7-28', '初六'],
['2017-7-29', '初七'],
['2017-7-30', '初八'],
['2017-7-31', '初九'],
['2017-8-1', '初十'],
['2017-8-2', '十一'],
['2017-8-3', '十二'],
['2017-8-4', '十三'],
['2017-8-5', '十四'],
['2017-8-6', '十五'],
['2017-8-7', '十六', '立秋'],
['2017-8-8', '十七'],
['2017-8-9', '十八'],
['2017-8-10', '十九'],
['2017-8-11', '二十'],
['2017-8-12', '廿一'],
['2017-8-13', '廿二'],
['2017-8-14', '廿三'],
['2017-8-15', '廿四'],
['2017-8-16', '廿五'],
['2017-8-17', '廿六'],
['2017-8-18', '廿七'],
['2017-8-19', '廿八'],
['2017-8-20', '廿九'],
['2017-8-21', '三十'],
['2017-8-22', '七月'],
['2017-8-23', '初二', '處暑'],
['2017-8-24', '初三'],
['2017-8-25', '初四'],
['2017-8-26', '初五'],
['2017-8-27', '初六'],
['2017-8-28', '初七'],
['2017-8-29', '初八'],
['2017-8-30', '初九'],
['2017-8-31', '初十'],
['2017-9-1', '十一'],
['2017-9-2', '十二'],
['2017-9-3', '十三'],
['2017-9-4', '十四'],
['2017-9-5', '十五'],
['2017-9-6', '十六'],
['2017-9-7', '十七', '白露'],
['2017-9-8', '十八'],
['2017-9-9', '十九'],
['2017-9-10', '二十'],
['2017-9-11', '廿一'],
['2017-9-12', '廿二'],
['2017-9-13', '廿三'],
['2017-9-14', '廿四'],
['2017-9-15', '廿五'],
['2017-9-16', '廿六'],
['2017-9-17', '廿七'],
['2017-9-18', '廿八'],
['2017-9-19', '廿九'],
['2017-9-20', '八月'],
['2017-9-21', '初二'],
['2017-9-22', '初三'],
['2017-9-23', '初四', '秋分'],
['2017-9-24', '初五'],
['2017-9-25', '初六'],
['2017-9-26', '初七'],
['2017-9-27', '初八'],
['2017-9-28', '初九'],
['2017-9-29', '初十'],
['2017-9-30', '十一'],
['2017-10-1', '十二'],
['2017-10-2', '十三'],
['2017-10-3', '十四'],
['2017-10-4', '十五'],
['2017-10-5', '十六'],
['2017-10-6', '十七'],
['2017-10-7', '十八'],
['2017-10-8', '十九', '寒露'],
['2017-10-9', '二十'],
['2017-10-10', '廿一'],
['2017-10-11', '廿二'],
['2017-10-12', '廿三'],
['2017-10-13', '廿四'],
['2017-10-14', '廿五'],
['2017-10-15', '廿六'],
['2017-10-16', '廿七'],
['2017-10-17', '廿八'],
['2017-10-18', '廿九'],
['2017-10-19', '三十'],
['2017-10-20', '九月'],
['2017-10-21', '初二'],
['2017-10-22', '初三'],
['2017-10-23', '初四', '霜降'],
['2017-10-24', '初五'],
['2017-10-25', '初六'],
['2017-10-26', '初七'],
['2017-10-27', '初八'],
['2017-10-28', '初九'],
['2017-10-29', '初十'],
['2017-10-30', '十一'],
['2017-10-31', '十二'],
['2017-11-1', '十三'],
['2017-11-2', '十四'],
['2017-11-3', '十五'],
['2017-11-4', '十六'],
['2017-11-5', '十七'],
['2017-11-6', '十八'],
['2017-11-7', '十九', '立冬'],
['2017-11-8', '二十'],
['2017-11-9', '廿一'],
['2017-11-10', '廿二'],
['2017-11-11', '廿三'],
['2017-11-12', '廿四'],
['2017-11-13', '廿五'],
['2017-11-14', '廿六'],
['2017-11-15', '廿七'],
['2017-11-16', '廿八'],
['2017-11-17', '廿九'],
['2017-11-18', '十月'],
['2017-11-19', '初二'],
['2017-11-20', '初三'],
['2017-11-21', '初四'],
['2017-11-22', '初五', '小雪'],
['2017-11-23', '初六'],
['2017-11-24', '初七'],
['2017-11-25', '初八'],
['2017-11-26', '初九'],
['2017-11-27', '初十'],
['2017-11-28', '十一'],
['2017-11-29', '十二'],
['2017-11-30', '十三'],
['2017-12-1', '十四'],
['2017-12-2', '十五'],
['2017-12-3', '十六'],
['2017-12-4', '十七'],
['2017-12-5', '十八'],
['2017-12-6', '十九'],
['2017-12-7', '二十', '大雪'],
['2017-12-8', '廿一'],
['2017-12-9', '廿二'],
['2017-12-10', '廿三'],
['2017-12-11', '廿四'],
['2017-12-12', '廿五'],
['2017-12-13', '廿六'],
['2017-12-14', '廿七'],
['2017-12-15', '廿八'],
['2017-12-16', '廿九'],
['2017-12-17', '三十'],
['2017-12-18', '十一月'],
['2017-12-19', '初二'],
['2017-12-20', '初三'],
['2017-12-21', '初四'],
['2017-12-22', '初五', '冬至'],
['2017-12-23', '初六'],
['2017-12-24', '初七'],
['2017-12-25', '初八'],
['2017-12-26', '初九'],
['2017-12-27', '初十'],
['2017-12-28', '十一'],
['2017-12-29', '十二'],
['2017-12-30', '十三'],
['2017-12-31', '十四'],
]
let heatmapData = []
let lunarData = []
for (let i = 0; i < dateList.length; i++) {
heatmapData.push([
dateList[i][0],
Math.random() * 300,
])
lunarData.push([
dateList[i][0],
1,
dateList[i][1],
dateList[i][2],
])
}
const option = {
tooltip: {
formatter (params) {
return `降雨量: ${params.value[1].toFixed(2)}`
},
},
visualMap: {
show: false,
min: 0,
max: 300,
calculable: true,
seriesIndex: [2],
orient: 'horizontal',
left: 'center',
bottom: 20,
inRange: {
color: ['#e0ffff', '#006edd'],
opacity: 0.3,
},
controller: {
inRange: {
opacity: 0.5,
},
},
},
calendar: [{
left: 'center',
top: 'middle',
cellSize: [70, 70],
yearLabel: { show: false },
orient: 'vertical',
dayLabel: {
firstDay: 1,
nameMap: 'cn',
},
monthLabel: {
show: false,
},
range: '2017-03',
}],
series: [{
type: 'scatter',
coordinateSystem: 'calendar',
symbolSize: 1,
label: {
normal: {
show: true,
formatter (params) {
let d = echarts.number.parseDate(params.value[0])
return `${d.getDate()}\n\n${params.value[2]}\n\n`
},
textStyle: {
color: '#000',
},
},
},
data: lunarData,
}, {
type: 'scatter',
coordinateSystem: 'calendar',
symbolSize: 1,
label: {
normal: {
show: true,
formatter (params) {
return `\n\n\n${params.value[3] || ''}`
},
textStyle: {
fontSize: 14,
fontWeight: 700,
color: '#a00',
},
},
},
data: lunarData,
}, {
name: '降雨量',
type: 'heatmap',
coordinateSystem: 'calendar',
data: heatmapData,
}],
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a lunar calendar chart. </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default LunarCalendarComponent
@@ -0,0 +1,48 @@
import React from 'react'
import AdSense from 'react-adsense'
import { Link } from 'react-router'
import DynamicChartComponent from './DynamicChartComponent.js'
const MainPageComponent = React.createClass({
propTypes: {
},
render () {
return (
<div>
<h1> echarts-for-react {this.props.params.type} </h1>
<h3> A very simple echarts(v3.0) wrapper for React. <a href="https://github.com/hustcc/echarts-for-react">hustcc/echarts-for-react</a></h3>
<AdSense.Google client="ca-pub-7292810486004926"
slot="7806394673"
/>
<h4>
<Link to="/echarts/simple">Simple demo</Link> |
<Link to="/echarts/loading">Echarts loading</Link> |
<Link to="/echarts/api">Echarts API</Link> |
<Link to="/echarts/events">Echarts events</Link> |
<Link to="/echarts/theme">Echarts theme</Link> |
<Link to="/echarts/dynamic">Dynamic chart</Link> |
<Link to="/echarts/map">Map chart</Link>
</h4>
<h4>
<span style={{ color: 'red' }}>New</span>:&nbsp;&nbsp;
<Link to="/echarts/airport">Airport</Link> |
<Link to="/echarts/graph">Graph</Link> |
<Link to="/echarts/calendar">Calendar</Link> |
<Link to="/echarts/treemap">Treemap</Link> |
<Link to="/echarts/gauge">Gauge</Link> |
<Link to="/echarts/gcalendar">GCalendar</Link> |
<Link to="/echarts/lunar">Lunar</Link> |
<Link to="/echarts/liquid">Liquidfill</Link>
</h4>
{this.props.children || <DynamicChartComponent />}
<h3>Get it on GitHub! <a href="https://github.com/hustcc/echarts-for-react">hustcc/echarts-for-react</a></h3>
</div>
)
},
})
export default MainPageComponent
@@ -0,0 +1,204 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts/map/js/china.js')
const MapChartComponent = React.createClass({
propTypes: {
},
getInitialState () {
return { option: this.getOtion() }
},
componentDidMount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
this.timeTicket = setInterval(() => {
const option = this.state.option
const r = new Date().getSeconds()
option.title.text = `iphone销量${r}`
option.series[0].name = `iphone销量${r}`
option.legend.data[0] = `iphone销量${r}`
this.setState({ option })
}, 1000)
},
componentWillUnmount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
},
getOtion () {
const option = {
title: {
text: 'iphone销量',
subtext: '纯属虚构',
left: 'center',
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
data: ['iphone3', 'iphone4', 'iphone5'],
},
visualMap: {
min: 0,
max: 2500,
left: 'left',
top: 'bottom',
text: ['高', '低'], // 文本,默认为数值文本
calculable: true,
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {},
},
},
series: [
{
name: 'iphone3',
type: 'map',
mapType: 'china',
roam: false,
label: {
normal: {
show: true,
},
emphasis: {
show: true,
},
},
data: [
{ name: '北京', value: this.randomData() },
{ name: '天津', value: this.randomData() },
{ name: '上海', value: this.randomData() },
{ name: '重庆', value: this.randomData() },
{ name: '河北', value: this.randomData() },
{ name: '河南', value: this.randomData() },
{ name: '云南', value: this.randomData() },
{ name: '辽宁', value: this.randomData() },
{ name: '黑龙江', value: this.randomData() },
{ name: '湖南', value: this.randomData() },
{ name: '安徽', value: this.randomData() },
{ name: '山东', value: this.randomData() },
{ name: '新疆', value: this.randomData() },
{ name: '江苏', value: this.randomData() },
{ name: '浙江', value: this.randomData() },
{ name: '江西', value: this.randomData() },
{ name: '湖北', value: this.randomData() },
{ name: '广西', value: this.randomData() },
{ name: '甘肃', value: this.randomData() },
{ name: '山西', value: this.randomData() },
{ name: '内蒙古', value: this.randomData() },
{ name: '陕西', value: this.randomData() },
{ name: '吉林', value: this.randomData() },
{ name: '福建', value: this.randomData() },
{ name: '贵州', value: this.randomData() },
{ name: '广东', value: this.randomData() },
{ name: '青海', value: this.randomData() },
{ name: '西藏', value: this.randomData() },
{ name: '四川', value: this.randomData() },
{ name: '宁夏', value: this.randomData() },
{ name: '海南', value: this.randomData() },
{ name: '台湾', value: this.randomData() },
{ name: '香港', value: this.randomData() },
{ name: '澳门', value: this.randomData() },
],
},
{
name: 'iphone4',
type: 'map',
mapType: 'china',
label: {
normal: {
show: true,
},
emphasis: {
show: true,
},
},
data: [
{ name: '北京', value: this.randomData() },
{ name: '天津', value: this.randomData() },
{ name: '上海', value: this.randomData() },
{ name: '重庆', value: this.randomData() },
{ name: '河北', value: this.randomData() },
{ name: '安徽', value: this.randomData() },
{ name: '新疆', value: this.randomData() },
{ name: '浙江', value: this.randomData() },
{ name: '江西', value: this.randomData() },
{ name: '山西', value: this.randomData() },
{ name: '内蒙古', value: this.randomData() },
{ name: '吉林', value: this.randomData() },
{ name: '福建', value: this.randomData() },
{ name: '广东', value: this.randomData() },
{ name: '西藏', value: this.randomData() },
{ name: '四川', value: this.randomData() },
{ name: '宁夏', value: this.randomData() },
{ name: '香港', value: this.randomData() },
{ name: '澳门', value: this.randomData() },
],
},
{
name: 'iphone5',
type: 'map',
mapType: 'china',
label: {
normal: {
show: true,
},
emphasis: {
show: true,
},
},
data: [
{ name: '北京', value: this.randomData() },
{ name: '天津', value: this.randomData() },
{ name: '上海', value: this.randomData() },
{ name: '广东', value: this.randomData() },
{ name: '台湾', value: this.randomData() },
{ name: '香港', value: this.randomData() },
{ name: '澳门', value: this.randomData() },
],
},
],
}
return option
},
randomData () {
return Math.round(Math.random() * 1000)
},
timeTicket: null,
render () {
let code = "require('echarts/map/js/china.js'); \n" +
'<ReactEcharts \n' +
' option={this.state.option || {}} \n' +
" style={{height: '350px', width: '100%'}} \n" +
" className='react_for_echarts' />"
return (
<div className="examples">
<div className="parent">
<label> render a china map. <strong>MAP charts</strong>: </label>
<ReactEcharts
option={this.state.option}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default MapChartComponent
@@ -0,0 +1,55 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
// require.config({
// paths: {
// echarts:'../node_modules/echarts',
// }
// });
const ModuleLoadChartComponent = React.createClass({
propTypes: {
},
getOtion () {
const option = {
title: { text: 'ECharts 入门示例' },
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
}],
}
return option
},
render () {
let code = '<ReactEcharts \n' +
' option={this.getOtion()} \n' +
" style={{height: '350px', width: '100%'}} \n" +
" modules={['echarts/lib/chart/bar', 'echarts/lib/component/tooltip', 'echarts/lib/component/title']} \n" +
" className='react_for_echarts' />"
return (
<div className="examples">
<div className="parent">
<label> load echarts module as you wish <strong>reduce the file size</strong>: </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '350px', width: '100%' }}
modules={['echarts/lib/chart/bar', 'echarts/lib/component/tooltip', 'echarts/lib/component/title']}
className="react_for_echarts"
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default ModuleLoadChartComponent
+62
View File
@@ -0,0 +1,62 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import 'echarts-gl'
const option = {
globe: {
baseTexture: '/asset/data-1493804606544-r1PBU7D1W.jpg',
heightTexture: '/asset/data-1493804610896-SJoBIXPkW.jpg',
displacementScale: 0.05,
displacementQuality: 'medium',
environment: '/asset/data-1491837999815-H1_44Qtal.jpg',
shading: 'realistic',
realisticMaterial: {
roughness: 0.8,
metalness: 0,
},
postEffect: {
enable: true,
SSAO: {
enable: true,
radius: 2,
intensity: 1,
quality: 'high',
},
},
temporalSuperSampling: {
enable: true,
},
light: {
ambient: {
intensity: 0,
},
main: {
intensity: 2,
shadow: true,
},
ambientCubemap: {
texture: '/asset/data-1491838644249-ry33I7YTe.hdr',
exposure: 0,
diffuseIntensity: 0.02,
},
},
viewControl: {
autoRotate: false,
},
},
series: [],
}
const MoonComponent = () => {
return (<ReactEcharts
option={option}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>)
}
export default MoonComponent
@@ -0,0 +1,93 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import './theme/macarons.js'
const SimpleChartComponent = React.createClass({
propTypes: {
},
getOtion () {
const option = {
title: {
text: '堆叠区域图',
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['邮件营销', '联盟广告', '视频广告'],
},
toolbox: {
feature: {
saveAsImage: {},
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: '邮件营销',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [120, 132, 101, 134, 90, 230, 210],
},
{
name: '联盟广告',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [220, 182, 191, 234, 290, 330, 310],
},
{
name: '视频广告',
type: 'line',
stack: '总量',
areaStyle: { normal: {} },
data: [150, 232, 201, 154, 190, 330, 410],
},
],
}
return option
},
render () {
let code = '<ReactEcharts \n' +
' option={this.getOtion()} \n' +
" style={{height: '350px', width: '100%'}} \n" +
" className='react_for_echarts' />"
return (
<div className="examples">
<div className="parent">
<label> render a Simple echart With <strong>option and height</strong>: </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '350px', width: '100%' }}
className="react_for_echarts"
theme="macarons"
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default SimpleChartComponent
@@ -0,0 +1,115 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const ThemeChartComponent = React.createClass({
propTypes: {
},
getOtion () {
const option = {
title: {
text: '阶梯瀑布图',
subtext: 'From ExcelHome',
sublink: 'http://e.weibo.com/1341556070/Aj1J2x5a5',
},
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
},
},
legend: {
data: ['支出', '收入'],
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'category',
splitLine: { show: false },
data: ['11月1日', '11月2日', '11月3日', '11月4日', '11月5日', '11月6日', '11月7日', '11月8日', '11月9日', '11月10日', '11月11日'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '辅助',
type: 'bar',
stack: '总量',
itemStyle: {
normal: {
barBorderColor: 'rgba(0,0,0,0)',
color: 'rgba(0,0,0,0)',
},
emphasis: {
barBorderColor: 'rgba(0,0,0,0)',
color: 'rgba(0,0,0,0)',
},
},
data: [0, 900, 1245, 1530, 1376, 1376, 1511, 1689, 1856, 1495, 1292],
},
{
name: '收入',
type: 'bar',
stack: '总量',
label: {
normal: {
show: true,
position: 'top',
},
},
data: [900, 345, 393, '-', '-', 135, 178, 286, '-', '-', '-'],
},
{
name: '支出',
type: 'bar',
stack: '总量',
label: {
normal: {
show: true,
position: 'bottom',
},
},
data: ['-', '-', '-', 108, 154, '-', '-', '-', 119, 361, 203],
},
],
}
return option
},
registerTheme () {
echarts.registerTheme('my_theme', {
backgroundColor: '#f4cccc',
})
},
render () {
this.registerTheme()
let code = "echarts.registerTheme('my_theme', {\n" +
" backgroundColor: '#f4cccc'\n" +
'});\n\n' +
'<ReactEcharts \n' +
' option={this.getOtion()} \n' +
" theme='my_theme' />"
return (
<div className="examples">
<div className="parent">
<label> render a echart With <strong>theme</strong>, should <strong>echarts.registerTheme(themeName, themeObj)</strong> before use.</label>
<ReactEcharts
option={this.getOtion()}
theme="my_theme"
/>
<label> the theme object format: https://github.com/ecomfe/echarts/blob/master/theme/dark.js</label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
},
})
export default ThemeChartComponent
@@ -0,0 +1,88 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import 'echarts-gl'
const hours = ['12a', '1a', '2a', '3a', '4a', '5a', '6a',
'7a', '8a', '9a', '10a', '11a',
'12p', '1p', '2p', '3p', '4p', '5p',
'6p', '7p', '8p', '9p', '10p', '11p']
const days = ['Saturday', 'Friday', 'Thursday',
'Wednesday', 'Tuesday', 'Monday', 'Sunday']
const data = [[0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2], [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0], [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2], [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7], [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2], [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0], [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2], [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5], [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4], [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4], [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5], [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1], [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1], [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4], [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1], [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0], [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0], [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1], [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6], [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0], [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0], [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0], [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0], [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]]
const option = {
tooltip: {},
visualMap: {
max: 20,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026'],
},
},
xAxis3D: {
type: 'category',
data: hours,
},
yAxis3D: {
type: 'category',
data: days,
},
zAxis3D: {
type: 'value',
},
grid3D: {
boxWidth: 200,
boxDepth: 80,
light: {
main: {
intensity: 1.2,
},
ambient: {
intensity: 0.3,
},
},
},
series: [{
type: 'bar3D',
data: data.map((item) => {
return {
value: [item[1], item[0], item[2]],
}
}),
shading: 'color',
label: {
show: false,
textStyle: {
fontSize: 16,
borderWidth: 1,
},
},
itemStyle: {
opacity: 0.4,
},
emphasis: {
label: {
textStyle: {
fontSize: 20,
color: '#900',
},
},
itemStyle: {
color: '#900',
},
},
}],
}
const TransparentBar3DComPonent = () => {
return (<ReactEcharts
option={option}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>)
}
export default TransparentBar3DComPonent
@@ -0,0 +1,266 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const TreemapComponent = React.createClass({
getOtion () {
let diskData = [
{
value: 180,
name: 'Accounts',
path: 'Accounts',
children: [
{
value: 76,
name: 'Access',
path: 'Accounts/Access',
children: [
{
value: 12,
name: 'DefaultAccessPlugin.bundle',
path: 'Accounts/Access/DefaultAccessPlugin.bundle',
},
{
value: 28,
name: 'FacebookAccessPlugin.bundle',
path: 'Accounts/Access/FacebookAccessPlugin.bundle',
},
{
value: 20,
name: 'LinkedInAccessPlugin.bundle',
path: 'Accounts/Access/LinkedInAccessPlugin.bundle',
},
{
value: 16,
name: 'TencentWeiboAccessPlugin.bundle',
path: 'Accounts/Access/TencentWeiboAccessPlugin.bundle',
},
],
},
{
value: 92,
name: 'Authentication',
path: 'Accounts/Authentication',
children: [
{
value: 24,
name: 'FacebookAuthenticationPlugin.bundle',
path: 'Accounts/Authentication/FacebookAuthenticationPlugin.bundle',
},
{
value: 16,
name: 'LinkedInAuthenticationPlugin.bundle',
path: 'Accounts/Authentication/LinkedInAuthenticationPlugin.bundle',
},
{
value: 20,
name: 'TencentWeiboAuthenticationPlugin.bundle',
path: 'Accounts/Authentication/TencentWeiboAuthenticationPlugin.bundle',
},
{
value: 16,
name: 'TwitterAuthenticationPlugin.bundle',
path: 'Accounts/Authentication/TwitterAuthenticationPlugin.bundle',
},
{
value: 16,
name: 'WeiboAuthenticationPlugin.bundle',
path: 'Accounts/Authentication/WeiboAuthenticationPlugin.bundle',
},
],
},
{
value: 12,
name: 'Notification',
path: 'Accounts/Notification',
children: [
{
value: 12,
name: 'SPAAccountsNotificationPlugin.bundle',
path: 'Accounts/Notification/SPAAccountsNotificationPlugin.bundle',
},
],
},
],
},
{
value: 1904,
name: 'AddressBook Plug-Ins',
path: 'AddressBook Plug-Ins',
children: [
{
value: 744,
name: 'CardDAVPlugin.sourcebundle',
path: 'AddressBook Plug-Ins/CardDAVPlugin.sourcebundle',
children: [
{
value: 744,
name: 'Contents',
path: 'AddressBook Plug-Ins/CardDAVPlugin.sourcebundle/Contents',
},
],
},
{
value: 28,
name: 'DirectoryServices.sourcebundle',
path: 'AddressBook Plug-Ins/DirectoryServices.sourcebundle',
children: [
{
value: 28,
name: 'Contents',
path: 'AddressBook Plug-Ins/DirectoryServices.sourcebundle/Contents',
},
],
},
{
value: 680,
name: 'Exchange.sourcebundle',
path: 'AddressBook Plug-Ins/Exchange.sourcebundle',
children: [
{
value: 680,
name: 'Contents',
path: 'AddressBook Plug-Ins/Exchange.sourcebundle/Contents',
},
],
},
{
value: 432,
name: 'LDAP.sourcebundle',
path: 'AddressBook Plug-Ins/LDAP.sourcebundle',
children: [
{
value: 432,
name: 'Contents',
path: 'AddressBook Plug-Ins/LDAP.sourcebundle/Contents',
},
],
},
{
value: 20,
name: 'LocalSource.sourcebundle',
path: 'AddressBook Plug-Ins/LocalSource.sourcebundle',
children: [
{
value: 20,
name: 'Contents',
path: 'AddressBook Plug-Ins/LocalSource.sourcebundle/Contents',
},
],
},
],
},
{
value: 36,
name: 'Assistant',
path: 'Assistant',
children: [
{
value: 36,
name: 'Plugins',
path: 'Assistant/Plugins',
children: [
{
value: 36,
name: 'AddressBook.assistantBundle',
path: 'Assistant/Plugins/AddressBook.assistantBundle',
},
{
value: 8,
name: 'GenericAddressHandler.addresshandler',
path: 'Recents/Plugins/GenericAddressHandler.addresshandler',
},
{
value: 12,
name: 'MapsRecents.addresshandler',
path: 'Recents/Plugins/MapsRecents.addresshandler',
},
],
},
],
},
]
let formatUtil = echarts.format
function getLevelOption () {
return [{
itemStyle: {
normal: {
borderWidth: 0,
gapWidth: 5,
},
},
}, {
itemStyle: {
normal: {
gapWidth: 1,
},
},
}, {
colorSaturation: [0.35, 0.5],
itemStyle: {
normal: {
gapWidth: 1,
borderColorSaturation: 0.6,
},
},
}]
}
const option = {
title: {
text: 'Disk Usage',
left: 'center',
},
tooltip: {
formatter (info) {
let value = info.value
let treePathInfo = info.treePathInfo
let treePath = []
for (let i = 1; i < treePathInfo.length; i++) {
treePath.push(treePathInfo[i].name)
}
return [
`<div class="tooltip-title">${formatUtil.encodeHTML(treePath.join('/'))}</div>`,
`Disk Usage: ${formatUtil.addCommas(value)} KB`,
].join('')
},
},
series: [{
name: 'Disk Usage',
type: 'treemap',
visibleMin: 300,
label: {
show: true,
formatter: '{b}',
},
itemStyle: {
normal: {
borderColor: '#fff',
},
},
levels: getLevelOption(),
data: diskData,
}],
}
return option
},
render () {
return (
<div className="examples">
<div className="parent">
<label> render a disk usage treemap. </label>
<ReactEcharts
option={this.getOtion()}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
},
})
export default TreemapComponent
+110
View File
@@ -0,0 +1,110 @@
import React from 'react'
import { Radio } from 'antd'
import EchartsComponent from './EchartsComponent'
import styles from './index.less'
const RadioGroup = Radio.Group
const chartList = [
{
label: 'SimpleChart',
value: 'simple',
},
{
label: 'ChartShowLoading',
value: 'loading',
},
{
label: 'ChartAPI',
value: 'api',
},
{
label: 'ChartWithEvent',
value: 'events',
},
{
label: 'ThemeChart',
value: 'theme',
},
{
label: 'DynamicChart',
value: 'dynamic',
},
{
label: 'MapChart',
value: 'map',
},
{
label: 'AirportCoord',
value: 'airport',
},
{
label: 'Graph',
value: 'graph',
},
{
label: 'Calendar',
value: 'calendar',
},
{
label: 'Treemap',
value: 'treemap',
},
{
label: 'Gauge',
value: 'gauge',
},
{
label: 'GCalendar',
value: 'gcalendar',
},
{
label: 'LunarCalendar',
value: 'lunar',
},
{
label: 'Liquidfill',
value: 'liquid',
},
{
label: 'BubbleGradient',
value: 'BubbleGradientComponent',
},
{
label: 'TransparentBar3D',
value: 'TransparentBar3DComPonent',
},
{
label: 'MoonComponent',
value: 'MoonComponent',
},
]
class Chart extends React.Component {
constructor () {
super()
this.state = {
type: '',
}
this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this)
}
handleRadioGroupChange (e) {
this.setState({
type: e.target.value,
})
}
render () {
return (<div className="content-inner" id="EChartsMain">
<RadioGroup options={chartList} defaultValue="dynamic" onChange={this.handleRadioGroupChange} />
<div className={styles.chart}>
<EchartsComponent type={this.state.type} />
</div>
<div style={{ pading: 24, marginTop: 24 }}>
All demos from <a href="https://github.com/hustcc/echarts-for-react">https://github.com/hustcc/echarts-for-react</a>
</div>
</div>)
}
}
export default Chart
+34
View File
@@ -0,0 +1,34 @@
.chart {
label {
margin: 24px 0;
display: block;
font-size: 14px;
}
pre {
padding: 16px;
overflow: auto;
font-size: 12px;
line-height: 2;
background-color: #f6f8fa;
border-radius: 3px;
code {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
}
}
:global {
.ant-radio-wrapper {
margin-bottom: 16px;
}
}
+198
View File
@@ -0,0 +1,198 @@
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory)
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'))
} else {
// Browser globals
factory({}, root.echarts)
}
}(this, (exports, echarts) => {
let log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg)
}
}
if (!echarts) {
log('ECharts is not Loaded')
return
}
let colorPalette = [
'#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80',
'#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa',
'#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050',
'#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089',
]
let theme = {
color: colorPalette,
title: {
textStyle: {
fontWeight: 'normal',
color: '#008acd',
},
},
visualMap: {
itemWidth: 15,
color: ['#5ab1ef', '#e0ffff'],
},
toolbox: {
iconStyle: {
normal: {
borderColor: colorPalette[0],
},
},
},
tooltip: {
backgroundColor: 'rgba(50,50,50,0.5)',
axisPointer: {
type: 'line',
lineStyle: {
color: '#008acd',
},
crossStyle: {
color: '#008acd',
},
shadowStyle: {
color: 'rgba(200,200,200,0.2)',
},
},
},
dataZoom: {
dataBackgroundColor: '#efefff',
fillerColor: 'rgba(182,162,222,0.2)',
handleColor: '#008acd',
},
grid: {
borderColor: '#eee',
},
categoryAxis: {
axisLine: {
lineStyle: {
color: '#008acd',
},
},
splitLine: {
lineStyle: {
color: ['#eee'],
},
},
},
valueAxis: {
axisLine: {
lineStyle: {
color: '#008acd',
},
},
splitArea: {
show: true,
areaStyle: {
color: ['rgba(250,250,250,0.1)', 'rgba(200,200,200,0.1)'],
},
},
splitLine: {
lineStyle: {
color: ['#eee'],
},
},
},
timeline: {
lineStyle: {
color: '#008acd',
},
controlStyle: {
normal: { color: '#008acd' },
emphasis: { color: '#008acd' },
},
symbol: 'emptyCircle',
symbolSize: 3,
},
line: {
smooth: true,
symbol: 'emptyCircle',
symbolSize: 3,
},
candlestick: {
itemStyle: {
normal: {
color: '#d87a80',
color0: '#2ec7c9',
lineStyle: {
color: '#d87a80',
color0: '#2ec7c9',
},
},
},
},
scatter: {
symbol: 'circle',
symbolSize: 4,
},
map: {
label: {
normal: {
textStyle: {
color: '#d87a80',
},
},
},
itemStyle: {
normal: {
borderColor: '#eee',
areaColor: '#ddd',
},
emphasis: {
areaColor: '#fe994e',
},
},
},
graph: {
color: colorPalette,
},
gauge: {
axisLine: {
lineStyle: {
color: [[0.2, '#2ec7c9'], [0.8, '#5ab1ef'], [1, '#d87a80']],
width: 10,
},
},
axisTick: {
splitNumber: 10,
length: 15,
lineStyle: {
color: 'auto',
},
},
splitLine: {
length: 22,
lineStyle: {
color: 'auto',
},
},
pointer: {
width: 5,
},
},
}
echarts.registerTheme('macarons', theme)
}))
+158
View File
@@ -0,0 +1,158 @@
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory)
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'))
} else {
// Browser globals
factory({}, root.echarts)
}
}(this, (exports, echarts) => {
let log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg)
}
}
if (!echarts) {
log('ECharts is not Loaded')
return
}
let colorPalette = [
'#c12e34', '#e6b600', '#0098d9', '#2b821d',
'#005eaa', '#339ca8', '#cda819', '#32a487',
]
let theme = {
color: colorPalette,
title: {
textStyle: {
fontWeight: 'normal',
},
},
visualMap: {
color: ['#1790cf', '#a2d4e6'],
},
toolbox: {
iconStyle: {
normal: {
borderColor: '#06467c',
},
},
},
tooltip: {
backgroundColor: 'rgba(0,0,0,0.6)',
},
dataZoom: {
dataBackgroundColor: '#dedede',
fillerColor: 'rgba(154,217,247,0.2)',
handleColor: '#005eaa',
},
timeline: {
lineStyle: {
color: '#005eaa',
},
controlStyle: {
normal: {
color: '#005eaa',
borderColor: '#005eaa',
},
},
},
candlestick: {
itemStyle: {
normal: {
color: '#c12e34',
color0: '#2b821d',
lineStyle: {
width: 1,
color: '#c12e34',
color0: '#2b821d',
},
},
},
},
graph: {
color: colorPalette,
},
map: {
label: {
normal: {
textStyle: {
color: '#c12e34',
},
},
emphasis: {
textStyle: {
color: '#c12e34',
},
},
},
itemStyle: {
normal: {
borderColor: '#eee',
areaColor: '#ddd',
},
emphasis: {
areaColor: '#e6b600',
},
},
},
gauge: {
axisLine: {
show: true,
lineStyle: {
color: [[0.2, '#2b821d'], [0.8, '#005eaa'], [1, '#c12e34']],
width: 5,
},
},
axisTick: {
splitNumber: 10,
length: 8,
lineStyle: {
color: 'auto',
},
},
axisLabel: {
textStyle: {
color: 'auto',
},
},
splitLine: {
length: 12,
lineStyle: {
color: 'auto',
},
},
pointer: {
length: '90%',
width: 3,
color: 'auto',
},
title: {
textStyle: {
color: '#333',
},
},
detail: {
textStyle: {
color: 'auto',
},
},
},
}
echarts.registerTheme('shine', theme)
}))
@@ -0,0 +1,294 @@
import React from 'react'
import { Row, Col, Card, Button } from 'antd'
import * as d3 from 'd3-shape'
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
} from 'recharts'
import Container from './Container'
const data = [
{
name: 'Page A',
uv: 4000,
pv: 2400,
amt: 2400,
}, {
name: 'Page B',
uv: 3000,
pv: 1398,
amt: 2210,
}, {
name: 'Page C',
uv: 2000,
pv: 9800,
amt: 2290,
}, {
name: 'Page D',
uv: 2780,
pv: 3908,
amt: 2000,
}, {
name: 'Page E',
uv: 1890,
pv: 4800,
amt: 2181,
}, {
name: 'Page F',
uv: 2390,
pv: 3800,
amt: 2500,
}, {
name: 'Page G',
uv: 3490,
pv: 4300,
amt: 2100,
},
]
const mixData = [
{
name: 'Page A',
uv: 4000,
pv: 2400,
amt: 2400,
}, {
name: 'Page B',
uv: 3000,
pv: 1398,
amt: 2210,
}, {
name: 'Page C',
uv: 2000,
pv: 9800,
amt: 2290,
}, {
name: 'Page D',
uv: 2780,
pv: 3908,
amt: 2000,
}, {
name: 'Page E',
uv: 1890,
pv: 4800,
amt: 2181,
}, {
name: 'Page F',
uv: 2390,
pv: 3800,
amt: 2500,
}, {
name: 'Page G',
uv: 3490,
pv: 4300,
amt: 2100,
},
]
const percentData = [
{
month: '2015.01',
a: 4000,
b: 2400,
c: 2400,
}, {
month: '2015.02',
a: 3000,
b: 1398,
c: 2210,
}, {
month: '2015.03',
a: 2000,
b: 9800,
c: 2290,
}, {
month: '2015.04',
a: 2780,
b: 3908,
c: 2000,
}, {
month: '2015.05',
a: 1890,
b: 4800,
c: 2181,
}, {
month: '2015.06',
a: 2390,
b: 3800,
c: 2500,
}, {
month: '2015.07',
a: 3490,
b: 4300,
c: 2100,
},
]
const colProps = {
lg: 12,
md: 24,
}
const SimpleAreaChart = () => (
<Container>
<AreaChart data={data}
margin={{
top: 10,
right: 30,
left: 0,
bottom: 0,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Area type="monotone" dataKey="uv" stroke="#8884d8" fill="#8884d8" />
</AreaChart>
</Container>
)
const StackedAreaChart = () => (
<Container>
<AreaChart data={mixData}
margin={{
top: 10,
right: 30,
left: 0,
bottom: 0,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Area type="monotone" dataKey="uv" stackId="1" stroke="#8884d8" fill="#8884d8" />
<Area type="monotone" dataKey="pv" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
<Area type="monotone" dataKey="amt" stackId="1" stroke="#ffc658" fill="#ffc658" />
</AreaChart>
</Container>
)
// StackedAreaChart
const toPercent = (decimal, fixed = 0) => {
return `${(decimal * 100).toFixed(fixed)}%`
}
const getPercent = (value, total) => {
const ratio = total > 0
? value / total
: 0
return toPercent(ratio, 2)
}
const renderTooltipContent = (o) => {
const { payload, label } = o
const total = payload.reduce((result, entry) => (result + entry.value), 0)
return (
<div className="customized-tooltip-content">
<p className="total">{`${label} (Total: ${total})`}</p>
<ul className="list">
{payload.map((entry, index) => (
<li key={`item-${index}`}
style={{
color: entry.color,
}}
>
{`${entry.name}: ${entry.value}(${getPercent(entry.value, total)})`}
</li>
))}
</ul>
</div>
)
}
const PercentAreaChart = () => (
<Container>
<AreaChart data={percentData}
stackOffset="expand"
margin={{
top: 10,
right: 30,
left: 0,
bottom: 0,
}}
>
<XAxis dataKey="month" />
<YAxis tickFormatter={toPercent} />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip content={renderTooltipContent} />
<Area type="monotone" dataKey="a" stackId="1" stroke="#8884d8" fill="#8884d8" />
<Area type="monotone" dataKey="b" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
<Area type="monotone" dataKey="c" stackId="1" stroke="#ffc658" fill="#ffc658" />
</AreaChart>
</Container>
)
// CardinalAreaChart
const cardinal = d3.curveCardinal.tension(0.2)
const CardinalAreaChart = () => (
<Container>
<AreaChart data={mixData}
margin={{
top: 10,
right: 30,
left: 0,
bottom: 0,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Area type="monotone" dataKey="uv" stroke="#8884d8" fill="#8884d8" fillOpacity={0.3} />
<Area type={cardinal} dataKey="pv" stroke="#82ca9d" fill="#82ca9d" fillOpacity={0.3} />
</AreaChart>
</Container>
)
const AreaChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
top: -48,
}}
>
<a href="http://recharts.org/#/en-US/examples/TinyBarChart" target="blank">Show More</a>
</Button>
<Row gutter={32}>
<Col {...colProps}>
<Card title="SimpleAreaChart">
<SimpleAreaChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="StackedAreaChart">
<StackedAreaChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="PercentAreaChart">
<PercentAreaChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="CardinalAreaChart">
<CardinalAreaChart />
</Card>
</Col>
</Row>
</div>
)
export default AreaChartPage
@@ -0,0 +1,238 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Row, Col, Card, Button } from 'antd'
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from 'recharts'
import Container from './Container'
const data = [
{
name: 'Page A',
uv: 4000,
pv: 2400,
amt: 2400,
}, {
name: 'Page B',
uv: 3000,
pv: 1398,
amt: 2210,
}, {
name: 'Page C',
uv: 2000,
pv: 9800,
amt: 2290,
}, {
name: 'Page D',
uv: 2780,
pv: 3908,
amt: 2000,
}, {
name: 'Page E',
uv: 1890,
pv: 4800,
amt: 2181,
}, {
name: 'Page F',
uv: 2390,
pv: 3800,
amt: 2500,
}, {
name: 'Page G',
uv: 3490,
pv: 4300,
amt: 2100,
},
]
const mixData = [
{
name: 'Page A',
uv: 4000,
female: 2400,
male: 2400,
}, {
name: 'Page B',
uv: 3000,
female: 1398,
male: 2210,
}, {
name: 'Page C',
uv: 2000,
female: 9800,
male: 2290,
}, {
name: 'Page D',
uv: 2780,
female: 3908,
male: 2000,
}, {
name: 'Page E',
uv: 1890,
female: 4800,
male: 2181,
}, {
name: 'Page F',
uv: 2390,
female: 3800,
male: 2500,
}, {
name: 'Page G',
uv: 3490,
female: 4300,
male: 2100,
},
]
const colProps = {
lg: 12,
md: 24,
}
const SimpleBarChart = () => (
<Container>
<BarChart data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Bar dataKey="pv" fill="#8884d8" />
<Bar dataKey="uv" fill="#82ca9d" />
</BarChart>
</Container>
)
const StackedBarChart = () => (
<Container>
<BarChart data={data}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Bar dataKey="pv" stackId="a" fill="#8884d8" />
<Bar dataKey="uv" stackId="a" fill="#82ca9d" />
</BarChart>
</Container>
)
const MixBarChart = () => (
<Container>
<BarChart data={mixData}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Bar dataKey="female" stackId="a" fill="#8884d8" />
<Bar dataKey="male" stackId="a" fill="#82ca9d" />
<Bar dataKey="uv" fill="#ffc658" />
</BarChart>
</Container>
)
// CustomShapeBarChart
const getPath = (x, y, width, height) => {
return `M${x},${y + height}
C${x + width / 3},${y + height} ${x + width / 2},${y + height / 3} ${x + width / 2}, ${y}
C${x + width / 2},${y + height / 3} ${x + 2 * width / 3},${y + height} ${x + width}, ${y + height}
Z`
}
const TriangleBar = (props) => {
const { fill, x, y, width, height } = props
return <path d={getPath(x, y, width, height)} stroke="none" fill={fill} />
}
TriangleBar.propTypes = {
fill: PropTypes.string,
x: PropTypes.number,
y: PropTypes.number,
width: PropTypes.number,
height: PropTypes.number,
}
const CustomShapeBarChart = () => (
<Container>
<BarChart data={mixData}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Bar dataKey="female" fill="#8884d8" shape={<TriangleBar />} label />
</BarChart>
</Container>
)
const BarChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
top: -48,
}}
>
<a href="http://recharts.org/#/en-US/examples/TinyBarChart" target="blank">Show More</a>
</Button>
<Row gutter={32}>
<Col {...colProps}>
<Card title="SimpleBarChart">
<SimpleBarChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="StackedBarChart">
<StackedBarChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="MixBarChart">
<MixBarChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="CustomShapeBarChart">
<CustomShapeBarChart />
</Card>
</Col>
</Row>
</div>
)
export default BarChartPage
+22
View File
@@ -0,0 +1,22 @@
import React from 'react'
import PropTypes from 'prop-types'
import { ResponsiveContainer } from 'recharts'
import styles from './Container.less'
const Container = ({ children, ratio = 5 / 2, minHeight = 250, maxHeight = 350 }) => (<div className={styles.container} style={{ minHeight, maxHeight }}>
<div style={{ marginTop: `${100 / ratio}%` || '100%' }} />
<div className={styles.content} style={{ minHeight, maxHeight }}>
<ResponsiveContainer>
{children}
</ResponsiveContainer>
</div>
</div>)
Container.propTypes = {
children: PropTypes.element.isRequired,
ratio: PropTypes.number,
minHeight: PropTypes.number,
maxHeight: PropTypes.number,
}
export default Container
+20
View File
@@ -0,0 +1,20 @@
.container {
width: 100%;
position: relative;
display: inline-block;
:global {
.recharts-responsive-container {
width: e("calc(100% + 56px)")!important;
margin-left: -32px;
}
}
}
.content {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
@@ -0,0 +1,216 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Row, Col, Card, Button } from 'antd'
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from 'recharts'
import Container from './Container'
const data = [
{
name: 'Page A',
uv: 4000,
pv: 2400,
amt: 2400,
}, {
name: 'Page B',
uv: 3000,
pv: 1398,
amt: 2210,
}, {
name: 'Page C',
uv: 2000,
pv: 9800,
amt: 2290,
}, {
name: 'Page D',
uv: 2780,
pv: 3908,
amt: 2000,
}, {
name: 'Page E',
uv: 1890,
pv: 4800,
amt: 2181,
}, {
name: 'Page F',
uv: 2390,
pv: 3800,
amt: 2500,
}, {
name: 'Page G',
uv: 3490,
pv: 4300,
amt: 2100,
},
]
const colProps = {
lg: 12,
md: 24,
}
const SimpleLineChart = () => (
<Container>
<LineChart data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Line type="monotone"
dataKey="pv"
stroke="#8884d8"
activeDot={{
r: 8,
}}
/>
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
</Container>
)
const VerticalLineChart = () => (
<Container>
<LineChart layout="vertical"
width={600}
height={300}
data={data}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis type="number" />
<YAxis dataKey="name" type="category" />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Line dataKey="pv" stroke="#8884d8" />
<Line dataKey="uv" stroke="#82ca9d" />
</LineChart>
</Container>
)
const DashedLineChart = () => (
<Container>
<LineChart width={600}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" strokeDasharray="5 5" />
<Line type="monotone" dataKey="uv" stroke="#82ca9d" strokeDasharray="3 4 5 2" />
</LineChart>
</Container>
)
// CustomizedDotLineChart
const CustomizedDot = ({ cx, cy, payload }) => {
if (payload.value > 2500) {
return (
<svg x={cx - 10} y={cy - 10} width={20} height={20} fill="red" viewBox="0 0 1024 1024">
<path d="M512 1009.984c-274.912 0-497.76-222.848-497.76-497.76s222.848-497.76 497.76-497.76c274.912 0 497.76 222.848 497.76 497.76s-222.848 497.76-497.76 497.76zM340.768 295.936c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM686.176 296.704c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM772.928 555.392c-18.752-8.864-40.928-0.576-49.632 18.528-40.224 88.576-120.256 143.552-208.832 143.552-85.952 0-164.864-52.64-205.952-137.376-9.184-18.912-31.648-26.592-50.08-17.28-18.464 9.408-21.216 21.472-15.936 32.64 52.8 111.424 155.232 186.784 269.76 186.784 117.984 0 217.12-70.944 269.76-186.784 8.672-19.136 9.568-31.2-9.12-40.096z" />
</svg>
)
}
return (
<svg x={cx - 10} y={cy - 10} width={20} height={20} fill="green" viewBox="0 0 1024 1024">
<path d="M517.12 53.248q95.232 0 179.2 36.352t145.92 98.304 98.304 145.92 36.352 179.2-36.352 179.2-98.304 145.92-145.92 98.304-179.2 36.352-179.2-36.352-145.92-98.304-98.304-145.92-36.352-179.2 36.352-179.2 98.304-145.92 145.92-98.304 179.2-36.352zM663.552 261.12q-15.36 0-28.16 6.656t-23.04 18.432-15.872 27.648-5.632 33.28q0 35.84 21.504 61.44t51.2 25.6 51.2-25.6 21.504-61.44q0-17.408-5.632-33.28t-15.872-27.648-23.04-18.432-28.16-6.656zM373.76 261.12q-29.696 0-50.688 25.088t-20.992 60.928 20.992 61.44 50.688 25.6 50.176-25.6 20.48-61.44-20.48-60.928-50.176-25.088zM520.192 602.112q-51.2 0-97.28 9.728t-82.944 27.648-62.464 41.472-35.84 51.2q-1.024 1.024-1.024 2.048-1.024 3.072-1.024 8.704t2.56 11.776 7.168 11.264 12.8 6.144q25.6-27.648 62.464-50.176 31.744-19.456 79.36-35.328t114.176-15.872q67.584 0 116.736 15.872t81.92 35.328q37.888 22.528 63.488 50.176 17.408-5.12 19.968-18.944t0.512-18.944-3.072-7.168-1.024-3.072q-26.624-55.296-100.352-88.576t-176.128-33.28z" />
</svg>
)
}
CustomizedDot.propTypes = {
cx: PropTypes.number,
cy: PropTypes.number,
payload: PropTypes.object,
}
const CustomizedDotLineChart = () => (
<Container>
<LineChart width={600}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<XAxis dataKey="name" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" dot={<CustomizedDot />} />
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
</Container>
)
const LineChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
top: -48,
}}
>
<a href="http://recharts.org/#/en-US/examples/TinyBarChart" target="blank">Show More</a>
</Button>
<Row gutter={32}>
<Col {...colProps}>
<Card title="SimpleLineChart">
<SimpleLineChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="DashedLineChart">
<DashedLineChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="CustomizedDotLineChart">
<CustomizedDotLineChart />
</Card>
</Col>
<Col {...colProps}>
<Card title="VerticalLineChart">
<VerticalLineChart />
</Card>
</Col>
</Row>
</div>
)
export default LineChartPage
@@ -0,0 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
import AreaChartComponent from './AreaChartComponent'
import BarChartComponent from './BarChartComponent'
import LineChartComponent from './LineChartComponent'
const ReChartsComponent = ({ type }) => {
if (type === 'areaChart') return (<AreaChartComponent />)
if (type === 'barChart') return (<BarChartComponent />)
return (<LineChartComponent />)
}
ReChartsComponent.propTypes = {
type: PropTypes.string,
}
export default ReChartsComponent
+47
View File
@@ -0,0 +1,47 @@
import React from 'react'
import { Radio } from 'antd'
import ReChartsComponent from './ReChartsComponent'
import styles from './index.less'
const RadioGroup = Radio.Group
const chartList = [
{
label: 'lineChart',
value: 'lineChart',
},
{
label: 'barChart',
value: 'barChart',
},
{
label: 'areaChart',
value: 'areaChart',
},
]
class Chart extends React.Component {
constructor () {
super()
this.state = {
type: '',
}
this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this)
}
handleRadioGroupChange (e) {
this.setState({
type: e.target.value,
})
}
render () {
return (<div className="content-inner">
<RadioGroup options={chartList} defaultValue="lineChart" onChange={this.handleRadioGroupChange} />
<div className={styles.chart}>
<ReChartsComponent type={this.state.type} />
</div>
</div>)
}
}
export default Chart
+8
View File
@@ -0,0 +1,8 @@
.chart {
:global {
.ant-card {
overflow: hidden;
margin-bottom: 24px;
}
}
}
@@ -0,0 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
import HighstockComponent from './HighstockComponent'
import HighmapsComponent from './HighmapsComponent'
import HighMoreComponent from './HighMoreComponent'
const HighChartsComponent = ({ type }) => {
if (type === 'Highmaps') return (<HighmapsComponent />)
if (type === 'HighMore') return (<HighMoreComponent />)
return (<HighstockComponent />)
}
HighChartsComponent.propTypes = {
type: PropTypes.string,
}
export default HighChartsComponent
@@ -0,0 +1,25 @@
import React from 'react'
import ReactHighcharts from 'react-highcharts'
import highchartsMore from 'highcharts-more'
import highchartsExporting from 'highcharts-exporting'
highchartsMore(ReactHighcharts.Highcharts)
highchartsExporting(ReactHighcharts.Highcharts)
const config = {
chart: {
polar: true,
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
}],
}
const HighMoreComponent = () => {
return <ReactHighcharts config={config} />
}
export default HighMoreComponent
@@ -0,0 +1,54 @@
import React from 'react'
import ReactHighmaps from 'react-highcharts/ReactHighmaps.src'
import maps from './mapdata/europe'
const config = {
chart: {
spacingBottom: 20,
},
title: {
text: 'Europe time zones',
},
legend: {
enabled: true,
},
plotOptions: {
map: {
allAreas: false,
joinBy: ['iso-a2', 'code'],
dataLabels: {
enabled: true,
color: 'white',
style: {
fontWeight: 'bold',
},
},
mapData: maps,
tooltip: {
headerFormat: '',
pointFormat: '{point.name}: <b>{series.name}</b>',
},
},
},
series: [{
name: 'UTC',
data: ['IE', 'IS', 'GB', 'PT'].map((code) => {
return { code }
}),
}, {
name: 'UTC + 1',
data: ['NO', 'SE', 'DK', 'DE', 'NL', 'BE', 'LU', 'ES', 'FR', 'PL', 'CZ', 'AT', 'CH', 'LI', 'SK', 'HU',
'SI', 'IT', 'SM', 'HR', 'BA', 'YF', 'ME', 'AL', 'MK'].map((code) => {
return { code }
}),
}],
}
const HighmapsComponent = () => {
return <ReactHighmaps config={config} />
}
export default HighmapsComponent
@@ -0,0 +1,28 @@
import React from 'react'
import ReactHighstock from 'react-highcharts/ReactHighstock.src'
const data = [
[1220832000000, 22.56], [1220918400000, 21.67], [1221004800000, 21.66], [1221091200000, 21.81], [1221177600000, 21.28], [1221436800000, 20.05], [1221523200000, 19.98], [1221609600000, 18.26], [1221696000000, 19.16], [1221782400000, 20.13], [1222041600000, 18.72], [1222128000000, 18.12], [1222214400000, 18.39], [1222300800000, 18.85], [1222387200000, 18.32], [1222646400000, 15.04], [1222732800000, 16.24], [1222819200000, 15.59], [1222905600000, 14.3], [1222992000000, 13.87], [1223251200000, 14.02], [1223337600000, 12.74], [1223424000000, 12.83], [1223510400000, 12.68], [1223596800000, 13.8], [1223856000000, 15.75], [1223942400000, 14.87], [1224028800000, 13.99], [1224115200000, 14.56], [1224201600000, 13.91], [1224460800000, 14.06], [1224547200000, 13.07], [1224633600000, 13.84], [1224720000000, 14.03], [1224806400000, 13.77], [1225065600000, 13.16], [1225152000000, 14.27], [1225238400000, 14.94], [1225324800000, 15.86], [1225411200000, 15.37], [1225670400000, 15.28], [1225756800000, 15.86], [1225843200000, 14.76], [1225929600000, 14.16], [1226016000000, 14.03], [1226275200000, 13.7], [1226361600000, 13.54], [1226448000000, 12.87], [1226534400000, 13.78], [1226620800000, 12.89], [1226880000000, 12.59], [1226966400000, 12.84], [1227052800000, 12.33], [1227139200000, 11.5], [1227225600000, 11.8], [1227484800000, 13.28], [1227571200000, 12.97], [1227657600000, 13.57], [1227830400000, 13.24], [1228089600000, 12.7], [1228176000000, 13.21], [1228262400000, 13.7], [1228348800000, 13.06], [1228435200000, 13.43], [1228694400000, 14.25], [1228780800000, 14.29], [1228867200000, 14.03], [1228953600000, 13.57], [1229040000000, 14.04], [1229299200000, 13.54],
]
const config = {
rangeSelector: {
selected: 1,
},
title: {
text: 'AAPL Stock Price',
},
series: [{
name: 'AAPL',
data,
tooltip: {
valueDecimals: 2,
},
}],
}
const HighstockComponent = () => {
return <ReactHighstock config={config} />
}
export default HighstockComponent
+47
View File
@@ -0,0 +1,47 @@
import React from 'react'
import { Radio } from 'antd'
import HighChartsComponent from './HighChartsComponent'
import styles from './index.less'
const RadioGroup = Radio.Group
const chartList = [
{
label: 'Highstock',
value: 'Highstock',
},
{
label: 'Highmaps',
value: 'Highmaps',
},
{
label: 'HighMore',
value: 'HighMore',
},
]
class Chart extends React.Component {
constructor () {
super()
this.state = {
type: '',
}
this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this)
}
handleRadioGroupChange (e) {
this.setState({
type: e.target.value,
})
}
render () {
return (<div className="content-inner">
<RadioGroup options={chartList} defaultValue="Highstock" onChange={this.handleRadioGroupChange} />
<div className={styles.chart}>
<HighChartsComponent type={this.state.type} />
</div>
</div>)
}
}
export default Chart
+7
View File
@@ -0,0 +1,7 @@
.chart {
:global {
.ant-radio-wrapper {
margin-bottom: 16px;
}
}
}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -132,7 +132,7 @@ const DashedLineChart = () => (
// CustomizedDotLineChart
const CustomizedDot = ({ cx, cy, payload }) => {
if (payload.value > 2500) {
if (payload.pv > 2500) {
return (
<svg x={cx - 10} y={cy - 10} width={20} height={20} fill="red" viewBox="0 0 1024 1024">
<path d="M512 1009.984c-274.912 0-497.76-222.848-497.76-497.76s222.848-497.76 497.76-497.76c274.912 0 497.76 222.848 497.76 497.76s-222.848 497.76-497.76 497.76zM340.768 295.936c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM686.176 296.704c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM772.928 555.392c-18.752-8.864-40.928-0.576-49.632 18.528-40.224 88.576-120.256 143.552-208.832 143.552-85.952 0-164.864-52.64-205.952-137.376-9.184-18.912-31.648-26.592-50.08-17.28-18.464 9.408-21.216 21.472-15.936 32.64 52.8 111.424 155.232 186.784 269.76 186.784 117.984 0 217.12-70.944 269.76-186.784 8.672-19.136 9.568-31.2-9.12-40.096z" />
+3 -4
View File
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { connect } from 'dva'
import { Row, Col, Card } from 'antd'
import { color } from 'utils'
import { Loader } from 'components'
import { Page } from 'components'
import { NumberCard, Quote, Sales, Weather, RecentSales, Comments, Completed, Browser, Cpu, User } from './components'
import styles from './index.less'
@@ -21,8 +21,7 @@ function Dashboard ({ dashboard, loading }) {
</Col>))
return (
<div>
<Loader spinning={loading.models.dashboard && sales.length === 0} />
<Page loading={loading.models.dashboard && sales.length === 0}>
<Row gutter={24}>
{numberCards}
<Col lg={18} md={24}>
@@ -97,7 +96,7 @@ function Dashboard ({ dashboard, loading }) {
</Card>
</Col>
</Row>
</div>
</Page>
)
}
+5 -2
View File
@@ -3,13 +3,16 @@ import PropTypes from 'prop-types'
import { Table, Modal } from 'antd'
import classnames from 'classnames'
import { DropOption } from 'components'
import { Link } from 'dva/router'
import AnimTableBody from '../../components/DataTable/AnimTableBody'
import { Link } from 'react-router-dom'
import queryString from 'query-string'
import AnimTableBody from 'components/DataTable/AnimTableBody'
import styles from './List.less'
const confirm = Modal.confirm
const List = ({ onDeleteItem, onEditItem, isMotion, location, ...tableProps }) => {
location.query = queryString.parse(location.search)
const handleMenuClick = (record, e) => {
if (e.key === '1') {
onEditItem(record)
+6 -2
View File
@@ -3,11 +3,15 @@ import PropTypes from 'prop-types'
import { routerRedux } from 'dva/router'
import { connect } from 'dva'
import { Row, Col, Button, Popconfirm } from 'antd'
import { Page } from 'components'
import queryString from 'query-string'
import List from './List'
import Filter from './Filter'
import Modal from './Modal'
const User = ({ location, dispatch, user, loading }) => {
location.query = queryString.parse(location.search)
const { list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys } = user
const { pageSize } = pagination
@@ -125,7 +129,7 @@ const User = ({ location, dispatch, user, loading }) => {
}
return (
<div className="content-inner">
<Page inner>
<Filter {...filterProps} />
{
selectedRowKeys.length > 0 &&
@@ -140,7 +144,7 @@ const User = ({ location, dispatch, user, loading }) => {
}
<List {...listProps} />
{modalVisible && <Modal {...modalProps} />}
</div>
</Page>
)
}
+7 -21
View File
@@ -1,18 +1,17 @@
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackTemplate = require('html-webpack-template')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')
module.exports = (webpackConfig, env) => {
const production = env === 'production'
// FilenameHash
webpackConfig.output.chunkFilename = '[name].[hash].js'
webpackConfig.output.chunkFilename = '[name].[chunkhash].js'
if (production) {
if (webpackConfig.module) {
// ClassnameHash
webpackConfig.module.rules.map((item) => {
if (String(item.test) === '/\\.less$/' || item.test === '/\\.css/') {
if (String(item.test) === '/\\.less$/' || String(item.test) === '/\\.css/') {
item.use.filter(iitem => iitem.loader === 'css')[0].options.localIdentName = '[hash:base64:5]'
}
return item
@@ -34,26 +33,13 @@ module.exports = (webpackConfig, env) => {
},
]),
new HtmlWebpackPlugin({
hash: true,
mobile: true,
title: 'antd-admin',
inject: false,
appMountId: 'root',
template: `!!ejs-loader!${HtmlWebpackTemplate}`,
template: `${__dirname}/src/entry.ejs`,
filename: production ? '../index.html' : 'index.html',
minify: {
minify: production ? {
collapseWhitespace: true,
},
scripts: production ? null : ['/roadhog.dll.js'],
meta: [
{
name: 'description',
content: 'A admin dashboard application demo built upon Ant Design and Dva.js',
}, {
name: 'viewport',
content: 'width=device-width, initial-scale=1.0',
},
],
} : null,
hash: true,
headScripts: production ? null : ['/roadhog.dll.js'],
}),
])