Compare commits

...
48 Commits
Author SHA1 Message Date
zuiidea 2de1e81661 Merge pull request #711 from zuiidea/develop
Develop
2017-12-27 15:41:00 +08:00
zuiidea cea60c5683 update Readme 2017-12-27 15:39:45 +08:00
zuiidea f16e104f73 fix all echarts example 2017-12-26 14:14:52 +08:00
zuiidea c397f552c3 fix some style 2017-12-26 11:31:05 +08:00
zuiidea 11c4ac803e fix users pagination 2017-12-25 20:39:48 +08:00
zuiidea 09b9a100de fix header style 2017-12-25 19:54:48 +08:00
zuiidea 0e59df39ee Compatibility upgrade 2017-12-25 18:08:25 +08:00
zuiidea 30254a2ec7 upgrade package 2017-12-25 10:51:36 +08:00
zuiidea cd796a6db9 fix Search style 2017-11-24 11:27:00 +08:00
zuiidea 6ba75de576 add backTop 2017-11-24 11:02:52 +08:00
zuiidea a3637b3a99 user search 2017-11-24 10:32:12 +08:00
zuiidea 85ec09ec9a Merge branch 'weishijun14-patch-1' into develop 2017-11-24 10:28:25 +08:00
zuiidea eb683b98e7 Merge branch 'patch-1' of https://github.com/weishijun14/antd-admin into weishijun14-patch-1 2017-11-24 10:28:17 +08:00
zuiidea 9221173309 Merge branch 'silentred-master' into develop 2017-11-24 10:26:15 +08:00
zuiidea 55a96f41c6 Merge branch 'master' of https://github.com/silentred/antd-admin into silentred-master 2017-11-24 10:25:42 +08:00
zuiidea ce510e79c7 Merge branch 'nazarlitvin-pagination' into develop 2017-11-24 10:24:56 +08:00
zuiidea 3d4f2a8814 Merge branch 'pagination' of https://github.com/nazarlitvin/antd-admin into nazarlitvin-pagination 2017-11-24 10:24:22 +08:00
nazarlitvin 38e24edd7b fix incorrect pagination property 2017-11-22 16:01:49 +02:00
Jason W 841c987a1a Update package.json
update package.json
2017-11-03 04:21:16 -05:00
shijun Wei dc26f7d25e update query to search
history 的 location 属性上不再包含 query。
2017-11-02 13:19:09 +08:00
zuiidea bc754e683e assets 2017-10-30 14:07:09 +08:00
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
dongyulei 00582e70ff 修复 4.3.5 中用户画面翻页无效的问题 2017-09-10 00:02:10 +08:00
eric 6077d74f10 .gitignore 增加排除项 2017-09-07 11:00:00 +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
89 changed files with 4566 additions and 697 deletions
+2
View File
@@ -1,2 +1,4 @@
src/**/*-test.js
src/public
src/routes/chart/ECharts/theme
src/routes/chart/highCharts/mapdata
+22 -15
View File
@@ -1,42 +1,49 @@
{
"extends": "airbnb",
"rules": {
"semi": [2, "never"],
"no-console": 0,
"arrow-body-style": [0, "never"],
"comma-dangle": [2, "always-multiline"],
"global-require": 0,
"func-names": 0,
"prefer-const": 0,
"import/no-unresolved": 0,
"import/extensions": 0,
"max-len": 0,
"react/jsx-first-prop-new-line": 0,
"react/jsx-filename-extension": 0,
"space-before-function-paren": [2, "always"],
"no-unused-expressions": [0, {
"allowShortCircuit": true,
"allowTernary": true
}],
"arrow-body-style": [0, "never"],
"func-names": 0,
"prefer-const": 0,
"no-console": 0,
"no-extend-native": 0,
"no-param-reassign": 0,
"no-restricted-syntax": 0,
"no-eval": 0,
"no-continue": 0,
"react/jsx-no-bind": 0,
"no-mixed-operators": 0,
"no-plusplus": 0,
"no-unused-vars": [2, { "ignoreRestSiblings": true }],
"no-underscore-dangle": 0,
"global-require": 0,
"import/no-unresolved": 0,
"import/extensions": 0,
"space-before-function-paren": [2, "always"],
"semi": [2, "never"],
"import/no-extraneous-dependencies": 0,
"import/prefer-default-export": 0,
"jsx-a11y/no-static-element-interactions": 0,
"jsx-a11y/click-events-have-key-events": 0,
"jsx-a11y/href-no-hash": 0,
"jsx-a11y/anchor-is-valid": 0,
"jsx-a11y/label-has-for": 0,
"react/no-array-index-key": 0,
"react/require-default-props": 0,
"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/jsx-closing-tag-location": 0,
"react/sort-comp": 0,
"react/jsx-no-bind": 0,
"react/no-danger": 0,
"jsx-a11y/no-static-element-interactions": 0,
"react/jsx-first-prop-new-line": 0,
"react/jsx-filename-extension": 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
+16 -3
View File
@@ -1,8 +1,8 @@
# Antd Admin
[![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-^2.0.1-orange.svg?style=flat-square)](https://github.com/dvajs/dva)
[![React](https://img.shields.io/badge/react-^16.2.0-brightgreen.svg?style=flat-square)](https://github.com/facebook/react)
[![Ant Design](https://img.shields.io/badge/ant--design-^3.0.3-yellowgreen.svg?style=flat-square)](https://github.com/ant-design/ant-design)
[![dva](https://img.shields.io/badge/dva-^2.1.0-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.9
`2017-12-27`
-   更新`antd`至`3.0.3`,以及其它主要库,并解决升级带来的兼容问题。
- 尽可能的保持`antd`的设计语言。
### 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
+24 -16
View File
@@ -1,18 +1,24 @@
{
"private": true,
"name": "antd-admin",
"version": "4.3.6",
"version": "4.3.9",
"dependencies": {
"antd": "^2.11.2",
"axios": "^0.16.2",
"antd": "3.0.3",
"axios": "^0.17.1",
"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": "^2.0.1",
"dva-loading": "^0.2.0",
"draftjs-to-markdown": "^0.5.0",
"dva": "2.1.0",
"dva-loading": "^1.0.4",
"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",
@@ -20,30 +26,31 @@
"lodash": "^4.17.4",
"mockjs": "^1.0.1-beta3",
"nprogress": "^0.2.0",
"path-to-regexp": "^1.7.0",
"path-to-regexp": "^2.1.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": "^16.2.0",
"react-countup": "^3.0.2",
"react-dom": "^16.2.0",
"react-draft-wysiwyg": "^1.10.0",
"react-helmet": "^5.1.3",
"recharts": "^0.22.4"
"react-highcharts": "^15.0.0",
"recharts": "^1.0.0-beta.0"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-eslint": "^8.1.0",
"babel-plugin-dev-expression": "^0.2.1",
"babel-plugin-dva-hmr": "^0.3.2",
"babel-plugin-dva-hmr": "^0.4.0",
"babel-plugin-import": "^1.1.1",
"babel-plugin-transform-runtime": "^6.9.0",
"babel-runtime": "^6.9.2",
"copy-webpack-plugin": "^4.0.1",
"draftjs-to-html": "^0.7.0",
"draftjs-to-html": "^0.8.1",
"dva-model-extend": "^0.1.1",
"eslint": "^4.1.1",
"eslint-config-airbnb": "^15.0.2",
"eslint-config-airbnb": "^16.1.0",
"eslint-import-resolver-node": "^0.3.1",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "^2.6.1",
@@ -51,11 +58,12 @@
"eslint-plugin-react": "^7.1.0",
"html-webpack-plugin": "^2.29.0",
"redbox-react": "^1.2.10",
"roadhog": "^1.2.2"
"roadhog": "1.3.1"
},
"pre-commit": ["lint"],
"scripts": {
"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 -10
View File
@@ -8,12 +8,14 @@ import './DataTable.less'
class DataTable extends React.Component {
constructor (props) {
super(props)
const { dataSource, pagination = {
showSizeChanger: true,
showQuickJumper: true,
showTotal: total => `共 ${total} 条`,
current: 1,
total: 100 },
const {
dataSource, pagination = {
showSizeChanger: true,
showQuickJumper: true,
showTotal: total => `共 ${total} 条`,
current: 1,
total: 100,
},
} = props
this.state = {
loading: false,
@@ -97,13 +99,12 @@ class DataTable extends React.Component {
}
}
DataTable.propTypes = {
fetch: PropTypes.object,
rowKey: PropTypes.string,
pagination: React.PropTypes.oneOfType([
React.PropTypes.bool,
React.PropTypes.object,
pagination: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.object,
]),
columns: PropTypes.array,
dataSource: PropTypes.array,
+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
@@ -4,7 +4,7 @@ import { Breadcrumb, Icon } from 'antd'
import { Link } from 'react-router-dom'
import pathToRegexp from 'path-to-regexp'
import { queryArray } from 'utils'
import styles from './Bread.less'
import styles from './Layout.less'
const Bread = ({ menu, location }) => {
// 匹配当前路由
@@ -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}
-8
View File
@@ -1,8 +0,0 @@
@import "~themes/vars";
.bread {
height: 64px;
line-height: 64px;
padding: 0 24px;
margin-bottom: -24px;
}
-9
View File
@@ -1,9 +0,0 @@
import React from 'react'
import { config } from 'utils'
import styles from './Footer.less'
const Footer = () => (<div className={styles.footer}>
{config.footerText}
</div>)
export default Footer
-12
View File
@@ -1,12 +0,0 @@
@import "~themes/vars";
.footer {
height: 48px;
line-height: 48px;
text-align: center;
font-size: 12px;
color: #999;
background: #fff;
box-shadow: @shadow-2;
width: 100%;
}
+7 -5
View File
@@ -1,13 +1,15 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Menu, Icon, Popover } from 'antd'
import { Menu, Icon, Popover, Layout } from 'antd'
import classnames from 'classnames'
import styles from './Header.less'
import Menus from './Menu'
const SubMenu = Menu.SubMenu
const { SubMenu } = Menu
const Header = ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys, menu }) => {
const Header = ({
user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys, menu,
}) => {
let handleClickMenu = e => e.key === 'logout' && logout()
const menusProps = {
menu,
@@ -20,7 +22,7 @@ const Header = ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVis
changeOpenKeys,
}
return (
<div className={styles.header}>
<Layout.Header className={styles.header}>
{isNavbar
? <Popover placement="bottomLeft" onVisibleChange={switchMenuPopover} visible={menuPopoverVisible} overlayClassName={styles.popovermenu} trigger="click" content={<Menus {...menusProps} />}>
<div className={styles.button}>
@@ -53,7 +55,7 @@ const Header = ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVis
</SubMenu>
</Menu>
</div>
</div>
</Layout.Header>
)
}
+45 -12
View File
@@ -1,20 +1,55 @@
@import "~themes/vars";
.header {
:global .ant-menu-horizontal {
& > .ant-menu-submenu {
float: right;
:global {
.ant-menu-submenu-title {
height: 56px;
}
.ant-menu-horizontal {
line-height: 56px;
& > .ant-menu-submenu:hover {
color: #1890ff;
background-color: rgba(24, 144, 255, 0.15);
}
}
.ant-menu {
border-bottom: none;
height: 56px;
}
.ant-menu-horizontal > .ant-menu-submenu {
top: 0;
margin-top: 0;
}
.ant-menu-horizontal > .ant-menu-item,
.ant-menu-horizontal > .ant-menu-submenu {
border-bottom: none;
}
.ant-menu-horizontal > .ant-menu-item-active,
.ant-menu-horizontal > .ant-menu-item-open,
.ant-menu-horizontal > .ant-menu-item-selected,
.ant-menu-horizontal > .ant-menu-item:hover,
.ant-menu-horizontal > .ant-menu-submenu-active,
.ant-menu-horizontal > .ant-menu-submenu-open,
.ant-menu-horizontal > .ant-menu-submenu-selected,
.ant-menu-horizontal > .ant-menu-submenu:hover {
border-bottom: none;
}
border: none;
display: inline-block;
}
box-shadow: @shadow-2;
position: relative;
display: flex;
justify-content: space-between;
height: 47px;
height: 56px;
z-index: 9;
display: flex;
align-items: center;
background-color: #fff;
z-index: 999;
.rightWarpper {
display: flex;
@@ -22,9 +57,9 @@
}
.button {
width: 47px;
height: 47px;
line-height: 47px;
width: 56px;
height: 56px;
line-height: 56px;
text-align: center;
font-size: 18px;
cursor: pointer;
@@ -47,8 +82,6 @@
.ant-menu-inline .ant-menu-item,
.ant-menu-vertical .ant-menu-item {
border-right: 0;
height: 48px;
line-height: 48px;
}
.ant-menu-inline .ant-menu-item-selected,
+132 -255
View File
@@ -1,292 +1,169 @@
@import "~themes/vars";
.layout {
position: relative;
height: 100vh;
&.withnavbar {
.main {
margin-left: 0;
}
:global {
.ant-layout-header {
padding: 0;
}
&.fold {
.sider {
width: 42px;
.ant-layout-sider {
transition: all 0.3s;
.logo {
img {
width: 28px;
margin: 6px 7px;
}
.ant-menu-root {
height: ~"calc(100vh - 144px)";
overflow-x: hidden;
border-right: none;
&::-webkit-scrollbar-thumb {
background-color: transparent;
}
:global {
.ant-menu-root {
width: 100%;
overflow: visible;
& > .ant-menu-item {
padding: 0;
text-align: center;
.anticon {
font-size: 14px;
margin-right: 0;
}
}
& > .ant-menu-submenu {
& > .ant-menu-submenu-title {
padding: 0;
text-align: center;
.anticon {
font-size: 14px;
margin-right: 0;
}
&::after {
display: none;
}
}
}
}
}
}
.main {
margin-left: 42px;
}
}
.sider {
width: 224px;
background: #3e3e3e;
position: absolute;
overflow: visible;
padding-bottom: 24px;
height: 100vh;
transition: @transition-ease-out;
box-shadow: @shadow-1;
color: #999;
&.light {
background: #fff;
.switchtheme {
background: #fff;
border-top: solid 1px #f8f8f8;
}
}
.logo {
text-align: center;
height: 40px;
line-height: 40px;
cursor: pointer;
margin: 28px 0;
transition: @transition-ease-out;
overflow: hidden;
img {
width: 40px;
margin-right: 8px;
transition: @transition-ease-out;
}
span {
vertical-align: text-bottom;
font-size: 16px;
text-transform: uppercase;
display: inline-block;
}
.anticon {
transition: @transition-ease-out;
}
}
.switchtheme {
width: 100%;
position: absolute;
bottom: 0;
height: 48px;
background-color: @dark-half;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px 0 24px;
overflow: hidden;
z-index: 1000;
span {
white-space: nowrap;
overflow: hidden;
}
:global {
.anticon {
min-width: 14px;
margin-right: 8px;
font-size: 14px;
}
}
}
:global {
.ant-menu-dark,
.ant-menu-dark .ant-menu-sub {
color: #999;
}
.ant-menu-root {
height: ~"calc(100vh - 144px)";
overflow-x: hidden;
border-right: none;
&:hover {
&::-webkit-scrollbar-thumb {
background-color: transparent;
}
&:hover {
&::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
}
}
&.ant-menu-vertical {
.ant-menu-sub {
height: 0;
opacity: 0;
transition: none;
}
.ant-menu-submenu-active {
.ant-menu-sub {
height: auto;
opacity: 1;
}
}
background-color: rgba(0, 0, 0, 0.2);
}
}
}
.ant-menu {
transition: @transition-ease-out;
.ant-menu-item,
.ant-menu-submenu-title {
overflow: hidden;
white-space: normal;
}
.ant-menu {
.ant-menu-item,
.ant-menu-submenu-title {
overflow: hidden;
white-space: normal;
}
}
}
.main {
margin-left: 224px;
overflow: auto;
height: 100vh;
transition: @transition-ease-out;
.ant-layout-content {
padding: 24px;
}
:global {
.content-inner {
background: #fff;
padding: 24px;
box-shadow: @shadow-1;
min-height: e("calc(100vh - 184px)");
}
.ant-layout-footer {
text-align: center;
padding: 0 24px;
height: 40px;
font-size: 12px;
line-height: 40px;
}
.ant-back-top {
right: 50px;
}
.ant-switch.ant-switch-large {
line-height: 24px;
height: 26px;
&:after,
&:before {
width: 22px;
height: 22px;
}
.container {
margin: 24px;
&.ant-switch-checked:after,
&.ant-switch-checked:before {
margin-left: -23px;
}
}
.content {
min-height: e("calc(100vh - 184px)");
position: relative;
.flex-vertical-center {
display: flex;
align-items: center;
}
.ant-form-item {
margin-bottom: 12px;
}
}
.logo {
height: 96px;
display: flex;
align-items: center;
justify-content: center;
img {
width: 40px;
margin-right: 8px;
}
span {
vertical-align: text-bottom;
font-size: 16px;
text-transform: uppercase;
display: inline-block;
font-weight: 700;
color: @primary-color;
}
}
.switchtheme {
width: 100%;
position: absolute;
bottom: 0;
height: 48px;
background-color: #fff;
border-top: solid 1px #f8f8f8;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px;
overflow: hidden;
z-index: 9;
transition: all 0.3s;
span {
white-space: nowrap;
overflow: hidden;
font-size: 12px;
}
:global {
.anticon {
min-width: 14px;
margin-right: 4px;
font-size: 14px;
}
}
}
:global .ant-menu-dark {
color: #999;
background-color: #3e3e3e;
.bread {
margin-bottom: 24px;
.ant-menu-submenu-title:hover,
.ant-menu-submenu:hover {
color: @primary-color;
}
.ant-menu-sub {
color: #999;
}
.ant-menu-submenu-selected {
color: @primary-color;
&:not(.ant-menu-submenu-open) {
background-color: @dark-half;
}
}
.ant-menu-item,
.ant-menu-submenu-title {
& > a {
color: #999;
}
&:hover > a {
color: @primary-color;
}
}
&.ant-menu-inline {
.ant-menu-item-selected {
background-color: @dark-half;
}
}
.ant-menu-item-selected {
color: @primary-color;
background-color: @dark-half;
& > a {
color: @primary-color;
}
&:hover {
background-color: @dark-half;
:global {
.ant-breadcrumb {
display: flex;
align-items: center;
}
}
}
.spin {
:global .ant-spin-container {
height: 100vh;
.dark {
.switchtheme {
background-color: #000d18;
border-color: #001629;
}
}
.light {
:global {
.ant-layout-sider {
background: #fff;
}
}
}
@media (max-width: 767px) {
.layout {
.main {
.container {
margin: 12px;
}
.bread {
margin-bottom: 12px;
}
.bread {
padding: 0 12px;
}
:global {
.ant-layout-content {
padding: 12px;
}
.content {
min-height: e("calc(100vh - 160px)");
}
:global {
.content-inner {
padding: 12px;
min-height: e("calc(100vh - 160px)");
}
}
.ant-back-top {
right: 20px;
bottom: 20px;
}
}
}
+1 -3
View File
@@ -5,7 +5,7 @@ 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 = {}
@@ -111,7 +111,6 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
{...menuProps}
mode={siderFold ? 'vertical' : 'inline'}
theme={darkTheme ? 'dark' : 'light'}
onClick={handleClickNavMenu}
selectedKeys={defaultSelectedKeys}
>
{menuItems}
@@ -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,
+4 -2
View File
@@ -5,7 +5,9 @@ import { config } from 'utils'
import styles from './Layout.less'
import Menus from './Menu'
const Sider = ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys, menu }) => {
const Sider = ({
siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys, menu,
}) => {
const menusProps = {
menu,
siderFold,
@@ -17,7 +19,7 @@ const Sider = ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, chang
return (
<div>
<div className={styles.logo}>
<img alt={'logo'} src={config.logo} />
<img alt="logo" src={config.logo} />
{siderFold ? '' : <span>{config.name}</span>}
</div>
<Menus {...menusProps} />
-1
View File
@@ -1 +0,0 @@
@import "~themes/vars";
+1 -2
View File
@@ -2,7 +2,6 @@ import Header from './Header'
import Menu from './Menu'
import Bread from './Bread'
import Sider from './Sider'
import Footer from './Footer'
import styles from './Layout.less'
export { Header, Menu, Bread, Sider, Footer, styles }
export { Header, Menu, Bread, Sider, styles }
+2 -2
View File
@@ -26,8 +26,8 @@
}
.inner {
width: 48px;
height: 48px;
width: 40px;
height: 40px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
+4 -2
View File
@@ -4,11 +4,13 @@
background: #fff;
padding: 24px;
box-shadow: @shadow-1;
min-height: e("calc(100vh - 184px)");
min-height: ~"calc(100vh - 198px)";
position: relative;
}
@media (max-width: 767px) {
.contentInner {
padding: 12px;
min-height: e("calc(100vh - 160px)");
min-height: ~"calc(100vh - 160px)";
}
}
+54 -55
View File
@@ -1,55 +1,54 @@
.no-highlight() {
border-color: #e5e5e5;
box-shadow: none;
}
.search {
display: flex;
width: 100%;
position: relative;
:global {
.anticon-cross {
position: absolute;
width: 18px;
height: 18px;
right: 84px;
cursor: pointer;
color: #fff;
line-height: 18px;
border-radius: 50%!important;
background-color: rgba(0, 0, 0, .16);
top: 7px;
// opacity:
}
.ant-select {
width: 80px;
flex-shrink: 0;
flex-grow: 0;
&.ant-select-focused .ant-select-selection,
&.ant-select-open .ant-select-selection,
.ant-select-selection:active,
.ant-select-selection:focus,
.ant-select-selection:hover {
.no-highlight();
}
}
.ant-input {
&:focus,
&:hover {
.no-highlight();
}
flex-shrink: 1;
flex-grow: 1;
}
.ant-btn {
width: 80px;
flex-shrink: 0;
flex-grow: 0;
}
}
}
.no-highlight() {
border-color: #e5e5e5;
box-shadow: none;
}
.search {
display: flex !important;
width: 100%;
position: relative;
:global {
.anticon-cross {
position: absolute;
width: 18px;
height: 18px;
right: 84px;
cursor: pointer;
color: #fff;
line-height: 18px;
border-radius: 50%!important;
background-color: rgba(0, 0, 0, .16);
top: 7px;
}
.ant-select {
width: 80px;
flex-shrink: 0;
flex-grow: 0;
&.ant-select-focused .ant-select-selection,
&.ant-select-open .ant-select-selection,
.ant-select-selection:active,
.ant-select-selection:focus,
.ant-select-selection:hover {
.no-highlight();
}
}
.ant-input {
&:focus,
&:hover {
.no-highlight();
}
flex-shrink: 1;
flex-grow: 1;
}
.ant-btn {
width: 80px;
flex-shrink: 0;
flex-grow: 0;
}
}
}
+2 -2
View File
@@ -5,13 +5,13 @@ import Search from './Search'
import Editor from './Editor'
import FilterItem from './FilterItem'
import Loader from './Loader'
import * as Layout from './Layout/index.js'
import * as MyLayout from './Layout/index.js'
import Page from './Page'
import layer from './layer'
export {
Layout,
MyLayout,
DataTable,
DropOption,
Iconfont,
+32 -32
View File
@@ -4,7 +4,7 @@ const { apiPrefix } = config
let database = [
{
id: '1',
icon: 'laptop',
icon: 'dashboard',
name: 'Dashboard',
route: '/dashboard',
},
@@ -50,14 +50,14 @@ let database = [
icon: 'heart-o',
route: '/UIElement/iconfont',
},
{
id: '42',
bpid: '4',
mpid: '4',
name: 'DataTable',
icon: 'database',
route: '/UIElement/dataTable',
},
// {
// id: '42',
// bpid: '4',
// mpid: '4',
// name: 'DataTable',
// icon: 'database',
// route: '/UIElement/dataTable',
// },
{
id: '43',
bpid: '4',
@@ -74,51 +74,51 @@ let database = [
icon: 'search',
route: '/UIElement/search',
},
{
id: '45',
bpid: '4',
mpid: '4',
name: 'Editor',
icon: 'edit',
route: '/UIElement/editor',
},
{
id: '46',
bpid: '4',
mpid: '4',
name: 'layer (Function)',
icon: 'credit-card',
route: '/UIElement/layer',
},
// {
// id: '45',
// bpid: '4',
// mpid: '4',
// name: '56pxor',
// icon: 'edit',
// route: '/UIElement/editor',
// },
// {
// id: '46',
// bpid: '4',
// mpid: '4',
// name: 'layer (Function)',
// icon: 'credit-card',
// route: '/UIElement/layer',
// },
{
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',
+4 -2
View File
@@ -11,11 +11,13 @@ export default modelExtend(pageModel, {
setup ({ dispatch, history }) {
history.listen((location) => {
if (location.pathname === '/post') {
dispatch({ type: 'query',
dispatch({
type: 'query',
payload: {
status: 2,
...queryString.parse(location.search),
} })
},
})
}
})
},
+3 -2
View File
@@ -1,9 +1,9 @@
/* global window */
import modelExtend from 'dva-model-extend'
import queryString from 'query-string'
import { config } from 'utils'
import { create, remove, update } from 'services/user'
import * as usersService from 'services/users'
import queryString from 'query-string'
import { pageModel } from './common'
const { query } = usersService
@@ -24,9 +24,10 @@ export default modelExtend(pageModel, {
setup ({ dispatch, history }) {
history.listen((location) => {
if (location.pathname === '/user') {
const payload = queryString.parse(location.search) || { page: 1, pageSize: 10 }
dispatch({
type: 'query',
payload: queryString.parse(location.search),
payload,
})
}
})
Binary file not shown.

After

Width:  |  Height:  |  Size: 901 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

+43
View File
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<title>Group 28 Copy 5</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="62.1023273%" y1="0%" x2="108.19718%" y2="37.8635764%" id="linearGradient-1">
<stop stop-color="#4285EB" offset="0%"></stop>
<stop stop-color="#2EC7FF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="69.644116%" y1="0%" x2="54.0428975%" y2="108.456714%" id="linearGradient-2">
<stop stop-color="#29CDFF" offset="0%"></stop>
<stop stop-color="#148EFF" offset="37.8600687%"></stop>
<stop stop-color="#0A60FF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="69.6908165%" y1="-12.9743587%" x2="16.7228981%" y2="117.391248%" id="linearGradient-3">
<stop stop-color="#FA816E" offset="0%"></stop>
<stop stop-color="#F74A5C" offset="41.472606%"></stop>
<stop stop-color="#F51D2C" offset="100%"></stop>
</linearGradient>
<linearGradient x1="68.1279872%" y1="-35.6905737%" x2="30.4400914%" y2="114.942679%" id="linearGradient-4">
<stop stop-color="#FA8E7D" offset="0%"></stop>
<stop stop-color="#F74A5C" offset="51.2635191%"></stop>
<stop stop-color="#F51D2C" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="logo" transform="translate(-20.000000, -20.000000)">
<g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)">
<g id="Group-27-Copy-3">
<g id="Group-25" fill-rule="nonzero">
<g id="2">
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-1)"></path>
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-2)"></path>
</g>
<path d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z" id="Shape" fill="url(#linearGradient-3)"></path>
</g>
<ellipse id="Combined-Shape" fill="url(#linearGradient-4)" cx="100.519339" cy="100.436681" rx="23.6001926" ry="23.580786"></ellipse>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

+6 -6
View File
@@ -50,14 +50,14 @@ const Routers = function ({ history, app }) {
path: '/UIElement/editor',
component: () => import('./routes/UIElement/editor/'),
}, {
path: '/chart/lineChart',
component: () => import('./routes/chart/lineChart/'),
path: '/chart/ECharts',
component: () => import('./routes/chart/ECharts/'),
}, {
path: '/chart/barChart',
component: () => import('./routes/chart/barChart/'),
path: '/chart/highCharts',
component: () => import('./routes/chart/highCharts/'),
}, {
path: '/chart/areaChart',
component: () => import('./routes/chart/areaChart/'),
path: '/chart/Recharts',
component: () => import('./routes/chart/Recharts/'),
}, {
path: '/post',
models: () => [import('./models/post')],
+3 -3
View File
@@ -1,8 +1,8 @@
import React from 'react'
import { DropOption } from 'components'
import { DropOption, Page } from 'components'
import { Table, Row, Col, Card, message } from 'antd'
const DropOptionPage = () => (<div className="content-inner">
const DropOptionPage = () => (<Page inner>
<Row gutter={32}>
<Col lg={8} md={12}>
<Card title="默认">
@@ -90,6 +90,6 @@ const DropOptionPage = () => (<div className="content-inner">
/>
</Col>
</Row>
</div>)
</Page>)
export default DropOptionPage
+3 -3
View File
@@ -1,5 +1,5 @@
import React from 'react'
import { Iconfont } from 'components'
import { Iconfont, Page } from 'components'
import { Table, Row, Col, Icon } from 'antd'
import styles from './index.less'
import './emoji'
@@ -24,7 +24,7 @@ const localRequireSVGIcons = [
require('../../../svg/cute/think.svg'),
]
const IcoPage = () => (<div className="content-inner">
const IcoPage = () => (<Page inner>
<Icon type="star-oo" />
<h2 style={{ margin: '16px 0' }}>Colorful Icon</h2>
<ul className={styles.list}>
@@ -111,6 +111,6 @@ const IcoPage = () => (<div className="content-inner">
<a href="http://www.iconfont.cn/collections/detail?cid=4268" target="_blank" rel="noopener noreferrer"> http://www.iconfont.cn/collections/detail?cid=4268</a>
</p>
</div>
</div>)
</Page>)
export default IcoPage
+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;
}
}
}
+4 -4
View File
@@ -1,8 +1,8 @@
import React from 'react'
import { Search } from 'components'
import { Search, Page } from 'components'
import { Table, Row, Col, Card } from 'antd'
const SearchPage = () => (<div className="content-inner">
const SearchPage = () => (<Page inner>
<Row gutter={32}>
<Col lg={8} md={12}>
<Card title="默认">
@@ -27,7 +27,7 @@ const SearchPage = () => (<div className="content-inner">
</Col>
<Col lg={8} md={12}>
<Card title="大小">
<Search size="large" style={{ marginBottom: 16 }} />
<Search style={{ marginBottom: 16 }} />
<Search size="small" />
</Card>
</Col>
@@ -93,6 +93,6 @@ const SearchPage = () => (<div className="content-inner">
/>
</Col>
</Row>
</div>)
</Page>)
export default SearchPage
+35 -20
View File
@@ -1,30 +1,37 @@
/* global window */
/* global document */
import React from 'react'
import NProgress from 'nprogress'
import PropTypes from 'prop-types'
import pathToRegexp from 'path-to-regexp'
import { connect } from 'dva'
import { Layout, Loader } from 'components'
import { Loader, MyLayout } from 'components'
import { BackTop, Layout } from 'antd'
import { classnames, config } from 'utils'
import { Helmet } from 'react-helmet'
import { withRouter } from 'dva/router'
import Error from './error'
import '../themes/index.less'
import './app.less'
import Error from './error'
const { Content, Footer, Sider } = Layout
const { Header, Bread, styles } = MyLayout
const { prefix, openPages } = config
const { Header, Bread, Footer, Sider, styles } = Layout
let lastHref
const App = ({ children, dispatch, app, loading, location }) => {
const { user, siderFold, darkTheme, isNavbar, menuPopoverVisible, navOpenKeys, menu, permissions } = app
const App = ({
children, dispatch, app, loading, location,
}) => {
const {
user, siderFold, darkTheme, isNavbar, menuPopoverVisible, navOpenKeys, menu, permissions,
} = app
let { pathname } = location
pathname = pathname.startsWith('/') ? pathname : `/${pathname}`
const { iconFontJS, iconFontCSS, logo } = config
const current = menu.filter(item => pathToRegexp(item.route || '').exec(pathname))
const hasPermission = current.length ? permissions.visit.includes(current[0].id) : false
const href = window.location.href
const { href } = window.location
if (lastHref !== href) {
NProgress.start()
@@ -75,12 +82,14 @@ const App = ({ children, dispatch, app, loading, location }) => {
menu,
location,
}
if (openPages && openPages.includes(pathname)) {
return (<div>
<Loader fullScreen spinning={loading.effects['app/query']} />
{children}
</div>)
}
return (
<div>
<Loader fullScreen spinning={loading.effects['app/query']} />
@@ -91,21 +100,27 @@ const App = ({ children, dispatch, app, loading, location }) => {
{iconFontJS && <script src={iconFontJS} />}
{iconFontCSS && <link rel="stylesheet" href={iconFontCSS} />}
</Helmet>
<div className={classnames(styles.layout, { [styles.fold]: isNavbar ? false : siderFold }, { [styles.withnavbar]: isNavbar })}>
{!isNavbar ? <aside className={classnames(styles.sider, { [styles.light]: !darkTheme })}>
{siderProps.menu.length === 0 ? null : <Sider {...siderProps} />}
</aside> : ''}
<div className={styles.main}>
<Layout className={classnames({ [styles.dark]: darkTheme, [styles.light]: !darkTheme })}>
{!isNavbar && <Sider
trigger={null}
collapsible
collapsed={siderFold}
>
{siderProps.menu.length === 0 ? null : <MyLayout.Sider {...siderProps} />}
</Sider>}
<Layout style={{ height: '100vh', overflow: 'scroll' }} id="mainContainer">
<BackTop target={() => document.getElementById('mainContainer')} />
<Header {...headerProps} />
<Bread {...breadProps} />
<div className={styles.container}>
<div className={styles.content}>
{hasPermission ? children : <Error />}
</div>
</div>
<Footer />
</div>
</div>
<Content>
<Bread {...breadProps} />
{hasPermission ? children : <Error />}
</Content>
<Footer >
{config.footerText}
</Footer>
</Layout>
</Layout>
</div>
)
}
@@ -0,0 +1,321 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts/map/js/china.js')
const AirportCoordComponent = () => {
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 (
<div className="examples">
<div className="parent">
<label> render a airport chart. </label>
<ReactEcharts
option={option}
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,197 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const CalendarComponent = () => {
const 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
}
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: getVirtulData(2017),
}, {
type: 'effectScatter',
coordinateSystem: 'calendar',
calendarIndex: 1,
symbolSize (val) {
return val[1] / 40
},
data: getVirtulData(2017),
}, {
type: 'scatter',
coordinateSystem: 'calendar',
calendarIndex: 2,
symbolSize (val) {
return val[1] / 60
},
data: getVirtulData(2017),
}, {
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 3,
data: getVirtulData(2017),
}],
}
return (
<div className="examples">
<div className="parent">
<label> render a calendar-charts </label>
<ReactEcharts
option={option}
style={{ height: '700px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
}
export default CalendarComponent
@@ -0,0 +1,117 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
class ChartAPIComponent extends React.Component {
render () {
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: '展现' },
],
},
],
}
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={option}
/>
<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,97 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
class ChartShowLoadingComponent extends React.Component {
constructor () {
super()
this._t = null
this.onChartReady = this.onChartReady.bind(this)
}
componentWillUnmount () {
clearTimeout(this._t)
}
onChartReady (chart) {
this._t = setTimeout(() => {
chart.hideLoading()
}, 3000)
}
render () {
const getOtion = () => {
const option = {
title: {
text: '基础雷达图',
},
tooltip: {},
legend: {
data: ['预算分配(Allocated Budget)', '实际开销(Actual Spending)'],
},
radar: {
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',
data: [
{
value: [4300, 10000, 28000, 35000, 50000, 19000],
name: '预算分配(Allocated Budget)',
},
{
value: [5000, 14000, 28000, 31000, 42000, 21000],
name: '实际开销(Actual Spending)',
},
],
}],
}
return option
}
const getLoadingOption = () => {
const option = {
text: '加载中...',
color: '#4413c2',
textColor: '#270240',
maskColor: 'rgba(194, 88, 86, 0.3)',
zlevel: 0,
}
return option
}
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={getOtion()}
onChartReady={this.onChartReady}
loadingOption={getLoadingOption()}
showLoading
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
}
}
export default ChartShowLoadingComponent
@@ -0,0 +1,89 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const ChartWithEventComponent = () => {
const onChartReady = (echart) => {
console.log('echart is ready', echart)
}
const onChartLegendselectchanged = (param, echart) => {
console.log(param, echart)
}
const onChartClick = (param, echart) => {
console.log(param, echart)
}
const 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
}
let onEvents = {
click: onChartClick,
legendselectchanged: onChartLegendselectchanged,
}
let code = 'let onEvents = {\n' +
" 'click': onChartClick,\n" +
" 'legendselectchanged': onChartLegendselectchanged\n" +
'}\n\n' +
'<ReactEcharts \n' +
' option={getOtion()} \n' +
' style={{height: 300}} \n' +
' onChartReady={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={getOtion()}
style={{ height: 300 }}
onChartReady={onChartReady}
onEvents={onEvents}
/>
<label> code below: </label>
<pre>
<code>{code}</code>
</pre>
</div>
</div>
)
}
export default ChartWithEventComponent
@@ -0,0 +1,195 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
class DynamicChartComponent extends React.Component {
constructor (props) {
super(props)
this.timeTicket = null
this.count = 51
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
}()),
},
],
}
this.state = {
option,
}
this.fetchNewDate = this.fetchNewDate.bind(this)
}
fetchNewDate () {
let axisData = (new Date()).toLocaleTimeString().replace(/^\D*/, '')
let { option } = this.state
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)
}
}
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,70 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const GCalendarComponent = () => {
const 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
}
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: getVirtulData(2017),
}, {
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 1,
data: getVirtulData(2016),
}],
}
return (
<div className="examples">
<div className="parent">
<label> render a calendar like github commit history. </label>
<ReactEcharts
option={option}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
}
export default GCalendarComponent
+328
View File
@@ -0,0 +1,328 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
class GaugeComponent extends React.Component {
constructor () {
super()
const 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' }],
},
],
}
this.state = {
option,
}
}
componentDidMount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
this.timeTicket = setInterval(() => {
let { option } = this.state
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)
}
}
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,31 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts-liquidfill')
const LiquidfillComponent = () => {
const option = {
series: [
{
type: 'liquidFill',
data: [0.6],
},
],
}
return (<div className="examples">
<div className="parent">
<label>
render a Liquidfill chart:
</label>
<ReactEcharts option={option}
style={{
height: '400px',
width: '100%',
}}
className="react_for_echarts"
/>
</div>
</div>)
}
export default LiquidfillComponent
@@ -0,0 +1,492 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const LunarCalendarComponent = () => {
const 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
}
return (
<div className="examples">
<div className="parent">
<label> render a lunar calendar chart. </label>
<ReactEcharts
option={getOtion()}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
}
export default LunarCalendarComponent
@@ -0,0 +1,44 @@
import React from 'react'
import AdSense from 'react-adsense'
import { Link } from 'react-router'
import DynamicChartComponent from './DynamicChartComponent.js'
const MainPageComponent = () => {
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,205 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
require('echarts/map/js/china.js')
class MapChartComponent extends React.Component {
constructor () {
super()
this.timeTicket = null
const randomData = () => {
return Math.round(Math.random() * 1000)
}
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: randomData() },
{ name: '天津', value: randomData() },
{ name: '上海', value: randomData() },
{ name: '重庆', value: randomData() },
{ name: '河北', value: randomData() },
{ name: '河南', value: randomData() },
{ name: '云南', value: randomData() },
{ name: '辽宁', value: randomData() },
{ name: '黑龙江', value: randomData() },
{ name: '湖南', value: randomData() },
{ name: '安徽', value: randomData() },
{ name: '山东', value: randomData() },
{ name: '新疆', value: randomData() },
{ name: '江苏', value: randomData() },
{ name: '浙江', value: randomData() },
{ name: '江西', value: randomData() },
{ name: '湖北', value: randomData() },
{ name: '广西', value: randomData() },
{ name: '甘肃', value: randomData() },
{ name: '山西', value: randomData() },
{ name: '内蒙古', value: randomData() },
{ name: '陕西', value: randomData() },
{ name: '吉林', value: randomData() },
{ name: '福建', value: randomData() },
{ name: '贵州', value: randomData() },
{ name: '广东', value: randomData() },
{ name: '青海', value: randomData() },
{ name: '西藏', value: randomData() },
{ name: '四川', value: randomData() },
{ name: '宁夏', value: randomData() },
{ name: '海南', value: randomData() },
{ name: '台湾', value: randomData() },
{ name: '香港', value: randomData() },
{ name: '澳门', value: randomData() },
],
},
{
name: 'iphone4',
type: 'map',
mapType: 'china',
label: {
normal: {
show: true,
},
emphasis: {
show: true,
},
},
data: [
{ name: '北京', value: randomData() },
{ name: '天津', value: randomData() },
{ name: '上海', value: randomData() },
{ name: '重庆', value: randomData() },
{ name: '河北', value: randomData() },
{ name: '安徽', value: randomData() },
{ name: '新疆', value: randomData() },
{ name: '浙江', value: randomData() },
{ name: '江西', value: randomData() },
{ name: '山西', value: randomData() },
{ name: '内蒙古', value: randomData() },
{ name: '吉林', value: randomData() },
{ name: '福建', value: randomData() },
{ name: '广东', value: randomData() },
{ name: '西藏', value: randomData() },
{ name: '四川', value: randomData() },
{ name: '宁夏', value: randomData() },
{ name: '香港', value: randomData() },
{ name: '澳门', value: randomData() },
],
},
{
name: 'iphone5',
type: 'map',
mapType: 'china',
label: {
normal: {
show: true,
},
emphasis: {
show: true,
},
},
data: [
{ name: '北京', value: randomData() },
{ name: '天津', value: randomData() },
{ name: '上海', value: randomData() },
{ name: '广东', value: randomData() },
{ name: '台湾', value: randomData() },
{ name: '香港', value: randomData() },
{ name: '澳门', value: randomData() },
],
},
],
}
this.state = {
option,
}
}
componentDidMount () {
if (this.timeTicket) {
clearInterval(this.timeTicket)
}
this.timeTicket = setInterval(() => {
const { option } = this.state
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)
}
}
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,43 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
const ModuleLoadChartComponent = () => {
const option = {
title: { text: 'ECharts 入门示例' },
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
}],
}
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={option}
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: '/assets/data-1493804606544-r1PBU7D1W.jpg',
heightTexture: '/assets/data-1493804610896-SJoBIXPkW.jpg',
displacementScale: 0.05,
displacementQuality: 'medium',
environment: '/assets/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,87 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import './theme/macarons.js'
const SimpleChartComponent = () => {
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],
},
],
}
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={option}
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,108 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const ThemeChartComponent = () => {
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],
},
],
}
echarts.registerTheme('my_theme', {
backgroundColor: '#f4cccc',
})
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={option}
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,261 @@
import React from 'react'
import ReactEcharts from 'echarts-for-react'
import echarts from 'echarts'
const TreemapComponent = () => {
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, treePathInfo } = info
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 (
<div className="examples">
<div className="parent">
<label> render a disk usage treemap. </label>
<ReactEcharts
option={option}
style={{ height: '500px', width: '100%' }}
className="react_for_echarts"
/>
</div>
</div>
)
}
export default TreemapComponent
+111
View File
@@ -0,0 +1,111 @@
import React from 'react'
import { Radio } from 'antd'
import { Page } from 'components'
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 (<Page 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>
</Page>)
}
}
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)
}))
@@ -1,6 +1,6 @@
import React from 'react'
import * as d3 from 'd3-shape'
import { Row, Col, Card, Button } from 'antd'
import * as d3 from 'd3-shape'
import {
AreaChart,
Area,
@@ -9,7 +9,8 @@ import {
CartesianGrid,
Tooltip,
} from 'recharts'
import Container from '../Container'
import Container from './Container'
const data = [
{
@@ -253,10 +254,9 @@ const CardinalAreaChart = () => (
</Container>
)
const EditorPage = () => (
const AreaChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
@@ -290,4 +290,4 @@ const EditorPage = () => (
</div>
)
export default EditorPage
export default AreaChartPage
@@ -10,7 +10,8 @@ import {
Tooltip,
Legend,
} from 'recharts'
import Container from '../Container'
import Container from './Container'
const data = [
{
@@ -161,13 +162,15 @@ const MixBarChart = () => (
// 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}
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
const {
fill, x, y, width, height,
} = props
return <path d={getPath(x, y, width, height)} stroke="none" fill={fill} />
}
@@ -197,10 +200,9 @@ const CustomShapeBarChart = () => (
</Container>
)
const EditorPage = () => (
const BarChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
@@ -234,4 +236,4 @@ const EditorPage = () => (
</div>
)
export default EditorPage
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;
}
@@ -10,7 +10,7 @@ import {
Tooltip,
Legend,
} from 'recharts'
import Container from '../Container'
import Container from './Container'
const data = [
{
@@ -176,10 +176,9 @@ const CustomizedDotLineChart = () => (
</Container>
)
const EditorPage = () => (
const LineChartPage = () => (
<div className="content-inner">
<Button type="primary"
size="large"
style={{
position: 'absolute',
right: 0,
@@ -213,4 +212,4 @@ const EditorPage = () => (
</div>
)
export default EditorPage
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
+48
View File
@@ -0,0 +1,48 @@
import React from 'react'
import { Radio } from 'antd'
import { Page } from 'components'
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 (<Page inner>
<RadioGroup options={chartList} defaultValue="lineChart" onChange={this.handleRadioGroupChange} />
<div className={styles.chart}>
<ReChartsComponent type={this.state.type} />
</div>
</Page>)
}
}
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
+48
View File
@@ -0,0 +1,48 @@
import React from 'react'
import { Radio } from 'antd'
import { Page } from 'components'
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 (<Page inner>
<RadioGroup options={chartList} defaultValue="Highstock" onChange={this.handleRadioGroupChange} />
<div className={styles.chart}>
<HighChartsComponent type={this.state.type} />
</div>
</Page>)
}
}
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
@@ -4,7 +4,9 @@ import { Icon, Card } from 'antd'
import CountUp from 'react-countup'
import styles from './numberCard.less'
function NumberCard ({ icon, color, title, number, countUp }) {
function NumberCard ({
icon, color, title, number, countUp,
}) {
return (
<Card className={styles.numberCard} bordered={false} bodyStyle={{ padding: 0 }}>
<Icon className={styles.iconWarp} style={{ color }} type={icon} />
@@ -27,6 +27,7 @@
font-size: 24px;
height: 32px;
.text-overflow();
margin-bottom: 0;
}
}
}
+4 -2
View File
@@ -15,13 +15,15 @@ const bodyStyle = {
}
function Dashboard ({ dashboard, loading }) {
const { weather, sales, quote, numbers, recentSales, comments, completed, browser, cpu, user } = dashboard
const {
weather, sales, quote, numbers, recentSales, comments, completed, browser, cpu, user,
} = dashboard
const numberCards = numbers.map((item, key) => (<Col key={key} lg={6} md={12}>
<NumberCard {...item} />
</Col>))
return (
<Page loading={loading.models.dashboard && sales.length === 0}>
<Page loading={loading.models.dashboard && sales.length === 0} className={styles.dashboard}>
<Row gutter={24}>
{numberCards}
<Col lg={18} md={24}>
+22 -12
View File
@@ -1,18 +1,28 @@
:global {
.ant-card {
border-radius: 0;
margin-bottom: 24px;
.dashboard{
position: relative;
:global {
.ant-card {
border-radius: 0;
margin-bottom: 24px;
&:hover{
box-shadow: 4px 4px 40px rgba(0,0,0,.05);
}
}
.ant-card-body{
overflow-y: scroll;
overflow-x: hidden;
}
}
}
.weather {
&:hover {
box-shadow: 4px 4px 40px rgba(143,201,251,.6);
.weather {
&:hover {
box-shadow: 4px 4px 40px rgba(143,201,251,.6);
}
}
}
.quote {
&:hover {
box-shadow: 4px 4px 40px rgba(246,152,153,.6);
.quote {
&:hover {
box-shadow: 4px 4px 40px rgba(246,152,153,.6);
}
}
}
+3 -2
View File
@@ -1,12 +1,13 @@
import React from 'react'
import { Icon } from 'antd'
import styles from './index.less'
import { Page } from 'components'
const Error = () => (<div className="content-inner">
const Error = () => (<Page inner>
<div className={styles.error}>
<Icon type="frown-o" />
<h1>404 Not Found</h1>
</div>
</div>)
</Page>)
export default Error
+4 -4
View File
@@ -27,7 +27,7 @@ const Login = ({
return (
<div className={styles.form}>
<div className={styles.logo}>
<img alt={'logo'} src={config.logo} />
<img alt="logo" src={config.logo} />
<span>{config.name}</span>
</div>
<form>
@@ -38,7 +38,7 @@ const Login = ({
required: true,
},
],
})(<Input size="large" onPressEnter={handleOk} placeholder="Username" />)}
})(<Input onPressEnter={handleOk} placeholder="Username" />)}
</FormItem>
<FormItem hasFeedback>
{getFieldDecorator('password', {
@@ -47,10 +47,10 @@ const Login = ({
required: true,
},
],
})(<Input size="large" type="password" onPressEnter={handleOk} placeholder="Password" />)}
})(<Input type="password" onPressEnter={handleOk} placeholder="Password" />)}
</FormItem>
<Row>
<Button type="primary" size="large" onClick={handleOk} loading={loading.effects.login}>
<Button type="primary" onClick={handleOk} loading={loading.effects.login}>
Sign in
</Button>
<p>
+53 -51
View File
@@ -1,51 +1,53 @@
.form {
position: absolute;
top: 50%;
left: 50%;
margin: -160px 0 0 -160px;
width: 320px;
height: 320px;
padding: 36px;
box-shadow: 0 0 100px rgba(0,0,0,.08);
button {
width: 100%;
}
p {
color: rgb(204, 204, 204);
text-align: center;
margin-top: 16px;
span {
&:first-child {
margin-right: 16px;
}
}
}
}
.logo {
text-align: center;
height: 40px;
line-height: 40px;
cursor: pointer;
margin-bottom: 24px;
img {
width: 40px;
margin-right: 8px;
}
span {
vertical-align: text-bottom;
font-size: 16px;
text-transform: uppercase;
display: inline-block;
}
}
.ant-spin-container,
.ant-spin-nested-loading {
height: 100%;
}
@import "~themes/vars";
.form {
position: absolute;
top: 50%;
left: 50%;
margin: -160px 0 0 -160px;
width: 320px;
height: 320px;
padding: 36px;
box-shadow: 0 0 100px rgba(0,0,0,.08);
button {
width: 100%;
}
p {
color: rgb(204, 204, 204);
text-align: center;
margin-top: 16px;
font-size: 12px;
display: flex;
justify-content: space-between;
}
}
.logo {
text-align: center;
cursor: pointer;
margin-bottom: 24px;
display: flex;
justify-content: center;
align-items: center;
img {
width: 40px;
margin-right: 8px;
}
span {
vertical-align: text-bottom;
font-size: 16px;
text-transform: uppercase;
display: inline-block;
font-weight: 700;
color: @primary-color;
}
}
.ant-spin-container,
.ant-spin-nested-loading {
height: 100%;
}
+9 -5
View File
@@ -4,9 +4,10 @@ import { connect } from 'dva'
import { Tabs } from 'antd'
import { routerRedux } from 'dva/router'
import queryString from 'query-string'
import { Page } from 'components'
import List from './List'
const TabPane = Tabs.TabPane
const { TabPane } = Tabs
const EnumPostStatus = {
UNPUBLISH: 1,
@@ -14,9 +15,12 @@ const EnumPostStatus = {
}
const Index = ({ post, dispatch, loading, location }) => {
const Index = ({
post, dispatch, loading, location,
}) => {
const { list, pagination } = post
const { query = {}, pathname } = location
location.query = queryString.parse(location.search)
const { query, pathname } = location
const listProps = {
pagination,
@@ -44,7 +48,7 @@ const Index = ({ post, dispatch, loading, location }) => {
}
return (<div className="content-inner">
return (<Page inner>
<Tabs activeKey={query.status === String(EnumPostStatus.UNPUBLISH) ? String(EnumPostStatus.UNPUBLISH) : String(EnumPostStatus.PUBLISHED)} onTabClick={handleTabClick}>
<TabPane tab="Publised" key={String(EnumPostStatus.PUBLISHED)}>
<List {...listProps} />
@@ -53,7 +57,7 @@ const Index = ({ post, dispatch, loading, location }) => {
<List {...listProps} />
</TabPane>
</Tabs>
</div>)
</Page>)
}
Index.propTypes = {
+15 -19
View File
@@ -5,7 +5,7 @@ import { FilterItem } from 'components'
import { Form, Button, Row, Col, DatePicker, Input, Cascader, Switch } from 'antd'
import city from '../../utils/city'
const Search = Input.Search
const { Search } = Input
const { RangePicker } = DatePicker
const ColProps = {
@@ -81,34 +81,30 @@ const Filter = ({
return (
<Row gutter={24}>
<Col {...ColProps} xl={{ span: 4 }} md={{ span: 8 }}>
{getFieldDecorator('name', { initialValue: name })(<Search placeholder="Search Name" size="large" onSearch={handleSubmit} />)}
{getFieldDecorator('name', { initialValue: name })(<Search placeholder="Search Name" onSearch={handleSubmit} />)}
</Col>
<Col {...ColProps} xl={{ span: 4 }} md={{ span: 8 }}>
{getFieldDecorator('address', { initialValue: address })(
<Cascader
size="large"
style={{ width: '100%' }}
options={city}
placeholder="Please pick an address"
onChange={handleChange.bind(null, 'address')}
/>)}
{getFieldDecorator('address', { initialValue: address })(<Cascader
style={{ width: '100%' }}
options={city}
placeholder="Please pick an address"
onChange={handleChange.bind(null, 'address')}
/>)}
</Col>
<Col {...ColProps} xl={{ span: 6 }} md={{ span: 8 }} sm={{ span: 12 }}>
<FilterItem label="Createtime">
{getFieldDecorator('createTime', { initialValue: initialCreateTime })(
<RangePicker style={{ width: '100%' }} size="large" onChange={handleChange.bind(null, 'createTime')} />
)}
{getFieldDecorator('createTime', { initialValue: initialCreateTime })(<RangePicker style={{ width: '100%' }} onChange={handleChange.bind(null, 'createTime')} />)}
</FilterItem>
</Col>
<Col {...TwoColProps} xl={{ span: 10 }} md={{ span: 24 }} sm={{ span: 24 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap' }}>
<div >
<Button type="primary" size="large" className="margin-right" onClick={handleSubmit}>Search</Button>
<Button size="large" onClick={handleReset}>Reset</Button>
</div>
<div>
<Switch style={{ marginRight: 16 }} size="large" defaultChecked={isMotion} onChange={switchIsMotion} checkedChildren={'Motion'} unCheckedChildren={'Motion'} />
<Button size="large" type="ghost" onClick={onAdd}>Create</Button>
<Button type="primary" className="margin-right" onClick={handleSubmit}>Search</Button>
<Button onClick={handleReset}>Reset</Button>
</div>
<div className="flex-vertical-center">
<Switch className="ant-switch-large" style={{ marginRight: 16 }} defaultChecked={isMotion} onChange={switchIsMotion} checkedChildren="Motion" unCheckedChildren="Motion" />
<Button type="ghost" onClick={onAdd}>Create</Button>
</div>
</div>
</Col>
+4 -7
View File
@@ -75,12 +75,10 @@ const modal = ({
type: 'boolean',
},
],
})(
<Radio.Group>
<Radio value>Male</Radio>
<Radio value={false}>Female</Radio>
</Radio.Group>
)}
})(<Radio.Group>
<Radio value>Male</Radio>
<Radio value={false}>Female</Radio>
</Radio.Group>)}
</FormItem>
<FormItem label="Age" hasFeedback {...formItemLayout}>
{getFieldDecorator('age', {
@@ -126,7 +124,6 @@ const modal = ({
},
],
})(<Cascader
size="large"
style={{ width: '100%' }}
options={city}
placeholder="Pick an address"
+12 -8
View File
@@ -10,9 +10,14 @@ import Filter from './Filter'
import Modal from './Modal'
const User = ({ location, dispatch, user, loading }) => {
const User = ({
location, dispatch, user, loading,
}) => {
location.query = queryString.parse(location.search)
const { list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys } = user
const { query, pathname } = location
const {
list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys,
} = user
const { pageSize } = pagination
const modalProps = {
@@ -42,7 +47,6 @@ const User = ({ location, dispatch, user, loading }) => {
location,
isMotion,
onChange (page) {
const { query, pathname } = location
dispatch(routerRedux.push({
pathname,
search: queryString.stringify({
@@ -83,7 +87,7 @@ const User = ({ location, dispatch, user, loading }) => {
const filterProps = {
isMotion,
filter: {
...location.query,
...query,
},
onFilterChange (value) {
dispatch(routerRedux.push({
@@ -98,10 +102,10 @@ const User = ({ location, dispatch, user, loading }) => {
onSearch (fieldsValue) {
fieldsValue.keyword.length ? dispatch(routerRedux.push({
pathname: '/user',
search: queryString.stringify({
query: {
field: fieldsValue.field,
keyword: fieldsValue.keyword,
}),
},
})) : dispatch(routerRedux.push({
pathname: '/user',
}))
@@ -136,8 +140,8 @@ const User = ({ location, dispatch, user, loading }) => {
<Row style={{ marginBottom: 24, textAlign: 'right', fontSize: 13 }}>
<Col>
{`Selected ${selectedRowKeys.length} items `}
<Popconfirm title={'Are you sure delete these items?'} placement="left" onConfirm={handleDeleteItems}>
<Button type="primary" size="large" style={{ marginLeft: 8 }}>Remove</Button>
<Popconfirm title="Are you sure delete these items?" placement="left" onConfirm={handleDeleteItems}>
<Button type="primary" style={{ marginLeft: 8 }}>Remove</Button>
</Popconfirm>
</Col>
</Row>
+15 -16
View File
@@ -1,16 +1,15 @@
// 本文件是对 ant-design:
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
// 相应变量值的覆盖
// 注意:只需写出要覆盖的变量即可(不需要覆盖的变量不要写)
// http://www.iconfont.cn/collections/detail?cid=790
@import "../../node_modules/antd/lib/style/themes/default.less";
@border-radius-base: 3px;
@border-radius-sm: 2px;
@shadow-color: rgba(0,0,0,0.05);
@shadow-1-down: 4px 4px 40px @shadow-color;
@border-color-split: #f4f4f4;
@border-color-base: #e5e5e5;
@menu-dark-bg: #3e3e3e;
@text-color: #666;
@font-family: "AvenirNext-Regular", "Helvetica Neue", "lucida grande", "PingFangHK-Light", "STHeiti", "Heiti SC", "Hiragino Sans GB", "Microsoft JhengHei", "Microsoft Yahei", SimHei, "WenQuanYi Micro Hei", "Droid Sans", "Roboto", Helvetica, Tahoma, Arial, "sans-serif";
@icon-url: "/antd/iconfont";
// 本文件是对 ant-design:
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
// 相应变量值的覆盖
// 注意:只需写出要覆盖的变量即可(不需要覆盖的变量不要写)
// http://www.iconfont.cn/collections/detail?cid=790
@import "../../node_modules/antd/lib/style/themes/default.less";
@border-radius-base: 3px;
@border-radius-sm: 2px;
@shadow-color: rgba(0,0,0,0.05);
@shadow-1-down: 4px 4px 40px @shadow-color;
@border-color-split: #f4f4f4;
@border-color-base: #e5e5e5;
@font-size-base: 13px;
@text-color: #666;
+1 -1
View File
@@ -5,7 +5,7 @@ module.exports = {
name: 'AntD Admin',
prefix: 'antdAdmin',
footerText: 'Ant Design Admin © 2017 zuiidea',
logo: '/logo.png',
logo: '/logo.svg',
iconFontCSS: '/iconfont.css',
iconFontJS: '/iconfont.js',
CORS: [],