mirror of
https://github.com/zuiidea/antd-admin.git
synced 2026-10-20 08:16:39 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2de1e81661 | ||
|
|
cea60c5683 | ||
|
|
f16e104f73 | ||
|
|
c397f552c3 | ||
|
|
11c4ac803e | ||
|
|
09b9a100de | ||
|
|
0e59df39ee | ||
|
|
30254a2ec7 | ||
|
|
cd796a6db9 | ||
|
|
6ba75de576 | ||
|
|
a3637b3a99 | ||
|
|
85ec09ec9a | ||
|
|
eb683b98e7 | ||
|
|
9221173309 | ||
|
|
55a96f41c6 | ||
|
|
ce510e79c7 | ||
|
|
3d4f2a8814 | ||
|
|
38e24edd7b | ||
|
|
841c987a1a | ||
|
|
dc26f7d25e | ||
|
|
bc754e683e | ||
|
|
c7acc8db4b | ||
|
|
057acc514f | ||
|
|
53ce7d08fb | ||
|
|
8ffd68a4e2 | ||
|
|
766653ee7a | ||
|
|
9dedcc68c3 | ||
|
|
5ea2b3c9b8 | ||
|
|
d2ac91839a | ||
|
|
bfca2746d8 | ||
|
|
b417065ac3 | ||
|
|
abdc97f087 | ||
|
|
07016c6c26 | ||
|
|
b8162060cd | ||
|
|
36fb5d293c | ||
|
|
429280a97a | ||
|
|
7ac36c779e | ||
|
|
d2e7b464e3 | ||
|
|
25839ea99f | ||
|
|
9c99581aa6 | ||
|
|
e42c21f0eb | ||
|
|
782bf214e5 | ||
|
|
a8a4496c7a | ||
|
|
f5f013ff23 | ||
|
|
8cff3af897 | ||
|
|
322d5a6d0e | ||
|
|
2ee26f51a7 | ||
|
|
e670ed2f96 | ||
|
|
601a03b5b4 | ||
|
|
00582e70ff | ||
|
|
fa4385055b | ||
|
|
01f4de55df | ||
|
|
dedd34e8e8 | ||
|
|
d1b373201e | ||
|
|
dbcc90e7ad | ||
|
|
87fce74d5b | ||
|
|
5c51679ad7 | ||
|
|
6d17b5b876 | ||
|
|
1288853112 | ||
|
|
d3e7e17789 | ||
|
|
6077d74f10 | ||
|
|
7bf031699a | ||
|
|
a6eb693636 | ||
|
|
39c377e0e2 | ||
|
|
67b90c4df0 | ||
|
|
0e2727f9c8 | ||
|
|
0cf02e7324 | ||
|
|
68c9f2b65f | ||
|
|
587b1f6b9d | ||
|
|
d94580a253 | ||
|
|
531e3c0fcc | ||
|
|
d68de7a30c | ||
|
|
45cb70f006 | ||
|
|
af85384f11 | ||
|
|
208539134f | ||
|
|
a3f41e3d64 | ||
|
|
3855c402c9 | ||
|
|
6a58d8434b | ||
|
|
d26a92ce79 | ||
|
|
0d20717c3c | ||
|
|
a0d81dcda9 | ||
|
|
4490af8553 | ||
|
|
6ae39bfd55 | ||
|
|
d86f0ebd78 | ||
|
|
a320c77ecb | ||
|
|
7f091d7642 | ||
|
|
d8f222f312 | ||
|
|
38637ef167 | ||
|
|
fe8527e72e | ||
|
|
da64cac414 | ||
|
|
f6021cbaa4 |
@@ -1 +1,4 @@
|
||||
src/**/*-test.js
|
||||
src/public
|
||||
src/routes/chart/ECharts/theme
|
||||
src/routes/chart/highCharts/mapdata
|
||||
|
||||
@@ -1,41 +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,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"react/prefer-stateless-function": 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
@@ -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
|
||||
|
||||
+20
-20
@@ -7,25 +7,25 @@ const svgSpriteDirs = [
|
||||
]
|
||||
|
||||
export default {
|
||||
entry : 'src/index.js',
|
||||
svgSpriteLoaderDirs : svgSpriteDirs,
|
||||
theme : "./theme.config.js",
|
||||
publicPath : `/${version}/`,
|
||||
outputPath : `./dist/${version}`,
|
||||
entry: 'src/index.js',
|
||||
svgSpriteLoaderDirs: svgSpriteDirs,
|
||||
theme: "./theme.config.js",
|
||||
publicPath: `/${version}/`,
|
||||
outputPath: `./dist/${version}`,
|
||||
// 接口代理示例
|
||||
// "proxy": {
|
||||
// "/api/v1": {
|
||||
// "target": "http://api.zuiidea.com",
|
||||
// "changeOrigin": true,
|
||||
// "pathRewrite": { "^/api/v1" : "/v1" }
|
||||
// },
|
||||
// "/api/v2": {
|
||||
// "target": "http://192.168.0.110",
|
||||
// "changeOrigin": true,
|
||||
// "pathRewrite": { "^/api/v2" : "/api/v2" }
|
||||
// }
|
||||
// },
|
||||
env : {
|
||||
proxy: {
|
||||
"/api/v1/weather": {
|
||||
"target": "https://api.seniverse.com/",
|
||||
"changeOrigin": true,
|
||||
"pathRewrite": { "^/api/v1/weather": "/v3/weather" }
|
||||
},
|
||||
// "/api/v2": {
|
||||
// "target": "http://192.168.0.110",
|
||||
// "changeOrigin": true,
|
||||
// "pathRewrite": { "^/api/v2" : "/api/v2" }
|
||||
// }
|
||||
},
|
||||
env: {
|
||||
development: {
|
||||
extraBabelPlugins: [
|
||||
"dva-hmr",
|
||||
@@ -50,8 +50,8 @@ export default {
|
||||
]
|
||||
}
|
||||
},
|
||||
dllPlugin : {
|
||||
exclude: ["babel-runtime"],
|
||||
dllPlugin: {
|
||||
exclude: ["babel-runtime", "roadhog", "cross-env"],
|
||||
include: ["dva/router", "dva/saga", "dva/fetch"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# Antd Admin
|
||||
|
||||
[](https://github.com/facebook/react)
|
||||
[](https://github.com/ant-design/ant-design)
|
||||
[](https://github.com/dvajs/dva)
|
||||
[](https://github.com/facebook/react)
|
||||
[](https://github.com/ant-design/ant-design)
|
||||
[](https://github.com/dvajs/dva)
|
||||
|
||||
[](https://github.com/zuiidea/antd-admin)
|
||||
[](https://github.com/zuiidea/antd-admin/pulls)
|
||||
[](http://opensource.org/licenses/MIT)
|
||||
[](http://standardjs.com)
|
||||
|
||||
演示地址 <http://zuiidea.github.io/antd-admin> \| [备用地址](http://47.92.30.98:8000)
|
||||
演示地址 <http://antd-admin.zuiidea.com>
|
||||
|
||||
## 特性
|
||||
|
||||
@@ -21,6 +21,34 @@
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 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
|
||||
|
||||
`2017-09-04`
|
||||
|
||||
- 更新[dva](https://github.com/dvajs/dva)至`2.0.1`,感谢[@yangbin1994](https://github.com/yangbin1994)的[PR](https://github.com/zuiidea/antd-admin/pull/567)。
|
||||
|
||||
### 4.3.4
|
||||
|
||||
`2017-09-04`
|
||||
|
||||
- 更新[roadhog](https://github.com/sorrycc/roadhog)至`1.2.1`,修复闪屏问题。
|
||||
- 修复build css未压缩[#529](https://github.com/zuiidea/antd-admin/issues/529),classname未Hash[#477](https://github.com/zuiidea/antd-admin/issues/477)。
|
||||
- 更新登录成功使用router跳转[#479](https://github.com/zuiidea/antd-admin/issues/479)。
|
||||
|
||||
### 4.3.0
|
||||
|
||||
`2017-07-30`
|
||||
@@ -30,34 +58,8 @@
|
||||
- 新增打包时按项目版本号生成文件目录。[#449](https://github.com/zuiidea/antd-admin/issues/449)
|
||||
- 更新`eslint`,并适当修改了`.eslintrc`。
|
||||
|
||||
### 4.2.3
|
||||
|
||||
`2017-07-07`
|
||||
|
||||
- 新增用户按权限访问。[#384](https://github.com/zuiidea/antd-admin/issues/384)
|
||||
|
||||
### 4.2.2
|
||||
|
||||
`2017-06-01`
|
||||
|
||||
- 新增用户管理批量删除。[#320](https://github.com/zuiidea/antd-admin/issues/320)
|
||||
|
||||
### 4.2.1
|
||||
|
||||
`2017-05-12`
|
||||
|
||||
- 新增IconFont扩展方案,本地使用方案。[#270](https://github.com/zuiidea/antd-admin/issues/270) [Live](http://47.92.30.98:666/UIElement/iconfont)
|
||||
- 新增常见场景使用loading。 [dva-loading](https://github.com/dvajs/dva-loading)
|
||||
|
||||
### 4.2
|
||||
|
||||
`2017-04-28`
|
||||
|
||||
- 修改user相关API使用`Restful`风格。
|
||||
- 增加user页面多条件查询。[#266](https://github.com/zuiidea/antd-admin/issues/226)
|
||||
- 修复菜单默认高亮。[#201](https://github.com/zuiidea/antd-admin/issues/201)
|
||||
|
||||
[More Change Log](https://github.com/zuiidea/antd-admin/wiki/Change-Log)
|
||||
[More Change Log](https://github.com/zuiidea/antd-admin/wiki/Change-Log)
|
||||
|
||||
## 开发构建
|
||||
|
||||
@@ -99,11 +101,16 @@
|
||||
|
||||
克隆项目文件:
|
||||
|
||||
git clone https://github.com/zuiidea/antd-admin.git
|
||||
```bash
|
||||
git clone https://github.com/zuiidea/antd-admin.git
|
||||
```
|
||||
|
||||
进入目录安装依赖:
|
||||
|
||||
npm i 或者 yarn install
|
||||
```bash
|
||||
#开始前请确保没有安装roadhog、webpack到NPM全局目录
|
||||
npm i 或者 yarn install
|
||||
```
|
||||
|
||||
开发:
|
||||
|
||||
@@ -141,7 +148,9 @@ npm run lint
|
||||
- 怎么按版本打包,上线时不影响正在访问的用户? [#449](https://github.com/zuiidea/antd-admin/issues/449)
|
||||
- windows处理CRLF?[参考](http://blog.csdn.net/lysc_forever/article/details/42835203)
|
||||
|
||||
git config --global core.autocrlf false
|
||||
```bash
|
||||
git config --global core.autocrlf false
|
||||
```
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
+28
-18
@@ -1,59 +1,69 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "antd-admin",
|
||||
"version": "4.3.2",
|
||||
"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": "^1.2.0",
|
||||
"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",
|
||||
"less-vars-to-js": "^1.1.2",
|
||||
"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",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"html-webpack-plugin": "^2.29.0",
|
||||
"html-webpack-template": "^5.6.0",
|
||||
"redbox-react": "^1.2.10",
|
||||
"roadhog": "1.0.0-beta.7"
|
||||
"roadhog": "1.3.1"
|
||||
},
|
||||
"pre-commit": ["lint"],
|
||||
"scripts": {
|
||||
"dev": "set BROWSER=none&&set HOST=0.0.0.0&&roadhog server",
|
||||
"dev": "cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
|
||||
"start": "roadhog buildDll && cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
|
||||
"lint": "eslint --fix --ext .js src",
|
||||
"build": "roadhog build",
|
||||
"build:dll": "roadhog buildDll",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/* global location */
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Breadcrumb, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import { Link } from 'react-router-dom'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
import { queryArray } from 'utils'
|
||||
import styles from './Bread.less'
|
||||
import styles from './Layout.less'
|
||||
|
||||
const Bread = ({ menu }) => {
|
||||
const Bread = ({ menu, location }) => {
|
||||
// 匹配当前路由
|
||||
let pathArray = []
|
||||
let current
|
||||
@@ -25,6 +24,7 @@ const Bread = ({ menu }) => {
|
||||
}
|
||||
}
|
||||
|
||||
let paramMap = {}
|
||||
if (!current) {
|
||||
pathArray.push(menu[0] || {
|
||||
id: 1,
|
||||
@@ -37,6 +37,17 @@ const Bread = ({ menu }) => {
|
||||
})
|
||||
} 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]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 递归查找父级
|
||||
@@ -49,7 +60,7 @@ const Bread = ({ menu }) => {
|
||||
return (
|
||||
<Breadcrumb.Item key={key}>
|
||||
{((pathArray.length - 1) !== key)
|
||||
? <Link to={item.route}>
|
||||
? <Link to={pathToRegexp.compile(item.route || '')(paramMap) || '#'}>
|
||||
{content}
|
||||
</Link>
|
||||
: content}
|
||||
@@ -68,6 +79,7 @@ const Bread = ({ menu }) => {
|
||||
|
||||
Bread.propTypes = {
|
||||
menu: PropTypes.array,
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Bread
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.bread {
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
padding: 0 24px;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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%;
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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,12 +1,11 @@
|
||||
/* global location */
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { arrayToTree, queryArray } from 'utils'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOpenKeys, menu }) => {
|
||||
const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, location }) => {
|
||||
// 生成树状
|
||||
const menuTree = arrayToTree(menu.filter(_ => _.mpid !== '-1'), 'id', 'mpid')
|
||||
const levelMap = {}
|
||||
@@ -32,7 +31,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={item.id}>
|
||||
<Link to={item.route}>
|
||||
<Link to={item.route || '#'}>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
{(!siderFoldN || !menuTree.includes(item)) && item.name}
|
||||
</Link>
|
||||
@@ -103,13 +102,16 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
defaultSelectedKeys = getPathArray(menu, currentMenu, 'mpid', 'id')
|
||||
}
|
||||
|
||||
if (!defaultSelectedKeys) {
|
||||
defaultSelectedKeys = ['1']
|
||||
}
|
||||
|
||||
return (
|
||||
<Menu
|
||||
{...menuProps}
|
||||
mode={siderFold ? 'vertical' : 'inline'}
|
||||
theme={darkTheme ? 'dark' : 'light'}
|
||||
onClick={handleClickNavMenu}
|
||||
defaultSelectedKeys={defaultSelectedKeys}
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
@@ -120,9 +122,9 @@ Menus.propTypes = {
|
||||
menu: PropTypes.array,
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
handleClickNavMenu: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Menus
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
@import "~themes/vars";
|
||||
@@ -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 }
|
||||
|
||||
@@ -3,8 +3,12 @@ import PropTypes from 'prop-types'
|
||||
import classNames from 'classnames'
|
||||
import styles from './Loader.less'
|
||||
|
||||
const Loader = ({ spinning }) => {
|
||||
return (<div className={classNames(styles.loader, { [styles.hidden]: !spinning })}>
|
||||
const Loader = ({ spinning, fullScreen }) => {
|
||||
return (<div className={classNames(styles.loader, {
|
||||
[styles.hidden]: !spinning,
|
||||
[styles.fullScreen]: fullScreen,
|
||||
})}
|
||||
>
|
||||
<div className={styles.warpper}>
|
||||
<div className={styles.inner} />
|
||||
<div className={styles.text} >LOADING</div>
|
||||
@@ -15,6 +19,7 @@ const Loader = ({ spinning }) => {
|
||||
|
||||
Loader.propTypes = {
|
||||
spinning: PropTypes.bool,
|
||||
fullScreen: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default Loader
|
||||
|
||||
@@ -1,64 +1,68 @@
|
||||
.loader {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
|
||||
.warpper {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 0 auto;
|
||||
text-indent: -12345px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.7);
|
||||
border-radius: 50%;
|
||||
z-index: 100001;
|
||||
|
||||
:local {
|
||||
animation: spinner 600ms infinite linear;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
letter-spacing: 4px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
|
||||
}
|
||||
}
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.loader {
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
|
||||
&.fullScreen {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.warpper {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 auto;
|
||||
text-indent: -12345px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.7);
|
||||
border-radius: 50%;
|
||||
z-index: 100001;
|
||||
|
||||
:local {
|
||||
animation: spinner 600ms infinite linear;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
letter-spacing: 4px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
|
||||
}
|
||||
}
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import Loader from '../Loader'
|
||||
import styles from './Page.less'
|
||||
|
||||
export default class Page extends Component {
|
||||
render () {
|
||||
const { className, children, loading = false, inner = false } = this.props
|
||||
const loadingStyle = {
|
||||
height: 'calc(100vh - 184px)',
|
||||
overflow: 'hidden',
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={classnames(className, {
|
||||
[styles.contentInner]: inner,
|
||||
})}
|
||||
style={loading ? loadingStyle : null}
|
||||
>
|
||||
{loading ? <Loader spinning /> : ''}
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Page.propTypes = {
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
loading: PropTypes.bool,
|
||||
inner: PropTypes.bool,
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.contentInner{
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: ~"calc(100vh - 198px)";
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.contentInner {
|
||||
padding: 12px;
|
||||
min-height: ~"calc(100vh - 160px)";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Page",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./Page.js"
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +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,
|
||||
@@ -19,4 +20,5 @@ export {
|
||||
FilterItem,
|
||||
Loader,
|
||||
layer,
|
||||
Page,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<% htmlWebpackPlugin.options.headScripts = htmlWebpackPlugin.options.headScripts || [] %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="description" content="A admin dashboard application demo built upon Ant Design and Dva.js">
|
||||
<title>antd admin</title>
|
||||
<!--[if lte IE 10]>
|
||||
<script
|
||||
src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]-->
|
||||
<% for (item of htmlWebpackPlugin.options.headScripts) { %>
|
||||
<script src="<%= item %>"></script>
|
||||
<% } %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { message } from 'antd'
|
||||
import dva from 'dva'
|
||||
import createLoading from 'dva-loading'
|
||||
import { browserHistory } from 'dva/router'
|
||||
import createHistory from 'history/createBrowserHistory'
|
||||
import 'babel-polyfill'
|
||||
|
||||
// 1. Initialize
|
||||
@@ -9,7 +9,7 @@ const app = dva({
|
||||
...createLoading({
|
||||
effects: true,
|
||||
}),
|
||||
history: browserHistory,
|
||||
history: createHistory(),
|
||||
onError (error) {
|
||||
message.error(error.message)
|
||||
},
|
||||
|
||||
+32
-32
@@ -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',
|
||||
|
||||
+174
-152
@@ -1,152 +1,174 @@
|
||||
/* global window */
|
||||
/* global document */
|
||||
/* global location */
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { parse } from 'qs'
|
||||
import config from 'config'
|
||||
import { EnumRoleType } from 'enums'
|
||||
import { query, logout } from 'services/app'
|
||||
import * as menusService from 'services/menus'
|
||||
|
||||
const { prefix } = config
|
||||
|
||||
export default {
|
||||
namespace: 'app',
|
||||
state: {
|
||||
user: {},
|
||||
permissions: {
|
||||
visit: [],
|
||||
},
|
||||
menu: [
|
||||
{
|
||||
id: 1,
|
||||
icon: 'laptop',
|
||||
name: 'Dashboard',
|
||||
router: '/dashboard',
|
||||
},
|
||||
],
|
||||
menuPopoverVisible: false,
|
||||
siderFold: window.localStorage.getItem(`${prefix}siderFold`) === 'true',
|
||||
darkTheme: window.localStorage.getItem(`${prefix}darkTheme`) === 'true',
|
||||
isNavbar: document.body.clientWidth < 769,
|
||||
navOpenKeys: JSON.parse(window.localStorage.getItem(`${prefix}navOpenKeys`)) || [],
|
||||
},
|
||||
subscriptions: {
|
||||
|
||||
setup ({ dispatch }) {
|
||||
dispatch({ type: 'query' })
|
||||
let tid
|
||||
window.onresize = () => {
|
||||
clearTimeout(tid)
|
||||
tid = setTimeout(() => {
|
||||
dispatch({ type: 'changeNavbar' })
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
effects: {
|
||||
|
||||
* query ({
|
||||
payload,
|
||||
}, { call, put }) {
|
||||
const { success, user } = yield call(query, payload)
|
||||
if (success && user) {
|
||||
const { list } = yield call(menusService.query)
|
||||
const { permissions } = user
|
||||
let menu = list
|
||||
if (permissions.role === EnumRoleType.ADMIN || permissions.role === EnumRoleType.DEVELOPER) {
|
||||
permissions.visit = list.map(item => item.id)
|
||||
} else {
|
||||
menu = list.filter((item) => {
|
||||
const cases = [
|
||||
permissions.visit.includes(item.id),
|
||||
item.mpid ? permissions.visit.includes(item.mpid) || item.mpid === '-1' : true,
|
||||
item.bpid ? permissions.visit.includes(item.bpid) : true,
|
||||
]
|
||||
return cases.every(_ => _)
|
||||
})
|
||||
}
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
user,
|
||||
permissions,
|
||||
menu,
|
||||
},
|
||||
})
|
||||
if (location.pathname === '/login') {
|
||||
yield put(routerRedux.push('/dashboard'))
|
||||
}
|
||||
} else if (config.openPages && config.openPages.indexOf(location.pathname) < 0) {
|
||||
let from = location.pathname
|
||||
window.location = `${location.origin}/login?from=${from}`
|
||||
}
|
||||
},
|
||||
|
||||
* logout ({
|
||||
payload,
|
||||
}, { call, put }) {
|
||||
const data = yield call(logout, parse(payload))
|
||||
if (data.success) {
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw (data)
|
||||
}
|
||||
},
|
||||
|
||||
* changeNavbar (action, { put, select }) {
|
||||
const { app } = yield (select(_ => _))
|
||||
const isNavbar = document.body.clientWidth < 769
|
||||
if (isNavbar !== app.isNavbar) {
|
||||
yield put({ type: 'handleNavbar', payload: isNavbar })
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
reducers: {
|
||||
updateState (state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
}
|
||||
},
|
||||
|
||||
switchSider (state) {
|
||||
window.localStorage.setItem(`${prefix}siderFold`, !state.siderFold)
|
||||
return {
|
||||
...state,
|
||||
siderFold: !state.siderFold,
|
||||
}
|
||||
},
|
||||
|
||||
switchTheme (state) {
|
||||
window.localStorage.setItem(`${prefix}darkTheme`, !state.darkTheme)
|
||||
return {
|
||||
...state,
|
||||
darkTheme: !state.darkTheme,
|
||||
}
|
||||
},
|
||||
|
||||
switchMenuPopver (state) {
|
||||
return {
|
||||
...state,
|
||||
menuPopoverVisible: !state.menuPopoverVisible,
|
||||
}
|
||||
},
|
||||
|
||||
handleNavbar (state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
isNavbar: payload,
|
||||
}
|
||||
},
|
||||
|
||||
handleNavOpenKeys (state, { payload: navOpenKeys }) {
|
||||
return {
|
||||
...state,
|
||||
...navOpenKeys,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
/* global window */
|
||||
/* global document */
|
||||
/* global location */
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { parse } from 'qs'
|
||||
import config from 'config'
|
||||
import { EnumRoleType } from 'enums'
|
||||
import { query, logout } from 'services/app'
|
||||
import * as menusService from 'services/menus'
|
||||
import queryString from 'query-string'
|
||||
|
||||
const { prefix } = config
|
||||
|
||||
export default {
|
||||
namespace: 'app',
|
||||
state: {
|
||||
user: {},
|
||||
permissions: {
|
||||
visit: [],
|
||||
},
|
||||
menu: [
|
||||
{
|
||||
id: 1,
|
||||
icon: 'laptop',
|
||||
name: 'Dashboard',
|
||||
router: '/dashboard',
|
||||
},
|
||||
],
|
||||
menuPopoverVisible: false,
|
||||
siderFold: window.localStorage.getItem(`${prefix}siderFold`) === 'true',
|
||||
darkTheme: window.localStorage.getItem(`${prefix}darkTheme`) === 'true',
|
||||
isNavbar: document.body.clientWidth < 769,
|
||||
navOpenKeys: JSON.parse(window.localStorage.getItem(`${prefix}navOpenKeys`)) || [],
|
||||
locationPathname: '',
|
||||
locationQuery: {},
|
||||
},
|
||||
subscriptions: {
|
||||
|
||||
setupHistory ({ dispatch, history }) {
|
||||
history.listen((location) => {
|
||||
dispatch({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
locationPathname: location.pathname,
|
||||
locationQuery: queryString.parse(location.search),
|
||||
},
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
setup ({ dispatch }) {
|
||||
dispatch({ type: 'query' })
|
||||
let tid
|
||||
window.onresize = () => {
|
||||
clearTimeout(tid)
|
||||
tid = setTimeout(() => {
|
||||
dispatch({ type: 'changeNavbar' })
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
effects: {
|
||||
|
||||
* query ({
|
||||
payload,
|
||||
}, { call, put, select }) {
|
||||
const { success, user } = yield call(query, payload)
|
||||
const { locationPathname } = yield select(_ => _.app)
|
||||
if (success && user) {
|
||||
const { list } = yield call(menusService.query)
|
||||
const { permissions } = user
|
||||
let menu = list
|
||||
if (permissions.role === EnumRoleType.ADMIN || permissions.role === EnumRoleType.DEVELOPER) {
|
||||
permissions.visit = list.map(item => item.id)
|
||||
} else {
|
||||
menu = list.filter((item) => {
|
||||
const cases = [
|
||||
permissions.visit.includes(item.id),
|
||||
item.mpid ? permissions.visit.includes(item.mpid) || item.mpid === '-1' : true,
|
||||
item.bpid ? permissions.visit.includes(item.bpid) : true,
|
||||
]
|
||||
return cases.every(_ => _)
|
||||
})
|
||||
}
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
user,
|
||||
permissions,
|
||||
menu,
|
||||
},
|
||||
})
|
||||
if (location.pathname === '/login') {
|
||||
yield put(routerRedux.push({
|
||||
pathname: '/dashboard',
|
||||
}))
|
||||
}
|
||||
} else if (config.openPages && config.openPages.indexOf(locationPathname) < 0) {
|
||||
yield put(routerRedux.push({
|
||||
pathname: '/login',
|
||||
search: queryString.stringify({
|
||||
from: locationPathname,
|
||||
}),
|
||||
}))
|
||||
}
|
||||
},
|
||||
|
||||
* logout ({
|
||||
payload,
|
||||
}, { call, put }) {
|
||||
const data = yield call(logout, parse(payload))
|
||||
if (data.success) {
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw (data)
|
||||
}
|
||||
},
|
||||
|
||||
* changeNavbar (action, { put, select }) {
|
||||
const { app } = yield (select(_ => _))
|
||||
const isNavbar = document.body.clientWidth < 769
|
||||
if (isNavbar !== app.isNavbar) {
|
||||
yield put({ type: 'handleNavbar', payload: isNavbar })
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
reducers: {
|
||||
updateState (state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
}
|
||||
},
|
||||
|
||||
switchSider (state) {
|
||||
window.localStorage.setItem(`${prefix}siderFold`, !state.siderFold)
|
||||
return {
|
||||
...state,
|
||||
siderFold: !state.siderFold,
|
||||
}
|
||||
},
|
||||
|
||||
switchTheme (state) {
|
||||
window.localStorage.setItem(`${prefix}darkTheme`, !state.darkTheme)
|
||||
return {
|
||||
...state,
|
||||
darkTheme: !state.darkTheme,
|
||||
}
|
||||
},
|
||||
|
||||
switchMenuPopver (state) {
|
||||
return {
|
||||
...state,
|
||||
menuPopoverVisible: !state.menuPopoverVisible,
|
||||
}
|
||||
},
|
||||
|
||||
handleNavbar (state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
isNavbar: payload,
|
||||
}
|
||||
},
|
||||
|
||||
handleNavOpenKeys (state, { payload: navOpenKeys }) {
|
||||
return {
|
||||
...state,
|
||||
...navOpenKeys,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+73
-227
@@ -1,227 +1,73 @@
|
||||
import { parse } from 'qs'
|
||||
import { myCity, queryWeather, query } from 'services/dashboard'
|
||||
|
||||
// zuimei 摘自 http://www.zuimeitianqi.com/res/js/index.js
|
||||
let zuimei = {
|
||||
parseActualData (actual) {
|
||||
let weather = {
|
||||
icon: `http://www.zuimeitianqi.com/res/icon/${zuimei.getIconName(actual.wea, 'big')}`,
|
||||
name: zuimei.getWeatherName(actual.wea),
|
||||
temperature: actual.tmp,
|
||||
dateTime: new Date(actual.PTm).format('MM-dd hh:mm'),
|
||||
}
|
||||
return weather
|
||||
},
|
||||
|
||||
getIconName (wea, flg) {
|
||||
let myDate = new Date()
|
||||
let hour = myDate.getHours()
|
||||
let num = 0
|
||||
if (wea.indexOf('/') !== -1) {
|
||||
let weas = wea.split('/')
|
||||
if (hour < 12) {
|
||||
num = zuimei.replaceIcon(weas[0])
|
||||
if (num < 6) {
|
||||
num = `${num}_${flg}_night.png`
|
||||
} else {
|
||||
num = `${num}_${flg}.png`
|
||||
}
|
||||
} else if (hour >= 12) {
|
||||
num = zuimei.replaceIcon(weas[1])
|
||||
if (hour >= 18) {
|
||||
num = `${num}_${flg}_night.png`
|
||||
} else {
|
||||
num = `${num}_${flg}.png`
|
||||
}
|
||||
}
|
||||
} else if ((hour >= 18 && hour <= 23) || (hour >= 0 && hour <= 6)) {
|
||||
num = `${num}_${flg}_night.png`
|
||||
} else {
|
||||
num = `${num}_${flg}.png`
|
||||
}
|
||||
|
||||
return num
|
||||
},
|
||||
|
||||
replaceIcon (num) {
|
||||
if (num === 21) {
|
||||
num = 7
|
||||
} else if (num === 22) {
|
||||
num = 8
|
||||
} else if (num === 10 || num === 11 || num === 12 || num === 23 || num === 24 || num === 25) {
|
||||
num = 9
|
||||
} else if (num === 13 || num === 15 || num === 26 || num === 27 || num === 34) {
|
||||
num = 14
|
||||
} else if (num === 17 || num === 28) {
|
||||
num = 16
|
||||
} else if (num === 35) {
|
||||
num = 18
|
||||
} else if (num === 31 || num === 32 || num === 33) {
|
||||
num = 20
|
||||
} else if (num === 30) {
|
||||
num = 29
|
||||
}
|
||||
|
||||
return num
|
||||
},
|
||||
|
||||
getWeatherName (wea) {
|
||||
let name = ''
|
||||
if (wea.indexOf('/') !== -1) {
|
||||
let weas = wea.split('/')
|
||||
name = `${zuimei.getWeatherByCode(weas[0])}转${zuimei.getWeatherByCode(weas[1])}`
|
||||
} else {
|
||||
name = zuimei.getWeatherByCode(wea)
|
||||
}
|
||||
|
||||
return name
|
||||
},
|
||||
|
||||
getWeatherByCode (number) {
|
||||
let wea = ''
|
||||
let num = Number(number)
|
||||
if (num === 0) {
|
||||
wea = '晴'
|
||||
} else if (num === 1) {
|
||||
wea = '多云'
|
||||
} else if (num === 2) {
|
||||
wea = '阴'
|
||||
} else if (num === 3) {
|
||||
wea = '阵雨'
|
||||
} else if (num === 4) {
|
||||
wea = '雷阵雨'
|
||||
} else if (num === 5) {
|
||||
wea = '雷阵雨并伴有冰雹'
|
||||
} else if (num === 6) {
|
||||
wea = '雨夹雪'
|
||||
} else if (num === 7) {
|
||||
wea = '小雨'
|
||||
} else if (num === 8) {
|
||||
wea = '中雨'
|
||||
} else if (num === 9) {
|
||||
wea = '大雨'
|
||||
} else if (num === 10) {
|
||||
wea = '暴雨'
|
||||
} else if (num === 11) {
|
||||
wea = '大暴雨'
|
||||
} else if (num === 12) {
|
||||
wea = '特大暴雨'
|
||||
} else if (num === 13) {
|
||||
wea = '阵雪'
|
||||
} else if (num === 14) {
|
||||
wea = '小雪'
|
||||
} else if (num === 15) {
|
||||
wea = '中雪'
|
||||
} else if (num === 16) {
|
||||
wea = '大雪'
|
||||
} else if (num === 17) {
|
||||
wea = '暴雪'
|
||||
} else if (num === 18) {
|
||||
wea = '雾'
|
||||
} else if (num === 19) {
|
||||
wea = '冻雨'
|
||||
} else if (num === 20) {
|
||||
wea = '沙尘暴'
|
||||
} else if (num === 21) {
|
||||
wea = '小雨-中雨'
|
||||
} else if (num === 22) {
|
||||
wea = '中雨-大雨'
|
||||
} else if (num === 23) {
|
||||
wea = '大雨-暴雨'
|
||||
} else if (num === 24) {
|
||||
wea = '暴雨-大暴雨'
|
||||
} else if (num === 25) {
|
||||
wea = '大暴雨-特大暴雨'
|
||||
} else if (num === 26) {
|
||||
wea = '小雪-中雪'
|
||||
} else if (num === 27) {
|
||||
wea = '中雪-大雪'
|
||||
} else if (num === 28) {
|
||||
wea = '大雪-暴雪'
|
||||
} else if (num === 29) {
|
||||
wea = '浮沉'
|
||||
} else if (num === 30) {
|
||||
wea = '扬沙'
|
||||
} else if (num === 31) {
|
||||
wea = '强沙尘暴'
|
||||
} else if (num === 32) {
|
||||
wea = '飑'
|
||||
} else if (num === 33) {
|
||||
wea = '龙卷风'
|
||||
} else if (num === 34) {
|
||||
wea = '若高吹雪'
|
||||
} else if (num === 35) {
|
||||
wea = '轻雾'
|
||||
} else if (num === 53) {
|
||||
wea = '霾'
|
||||
} else if (num === 99) {
|
||||
wea = '未知'
|
||||
}
|
||||
|
||||
return wea
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
namespace: 'dashboard',
|
||||
state: {
|
||||
weather: {
|
||||
city: '成都',
|
||||
temperature: '5',
|
||||
name: '晴',
|
||||
icon: 'http://www.zuimeitianqi.com/res/icon/0_big.png',
|
||||
dateTime: new Date().format('MM-dd hh:mm'),
|
||||
},
|
||||
sales: [],
|
||||
quote: {
|
||||
avatar: 'http://img.hb.aicdn.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236',
|
||||
},
|
||||
numbers: [],
|
||||
recentSales: [],
|
||||
comments: [],
|
||||
completed: [],
|
||||
browser: [],
|
||||
cpu: {},
|
||||
user: {
|
||||
avatar: 'http://img.hb.aicdn.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236',
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
setup ({ dispatch }) {
|
||||
dispatch({ type: 'query' })
|
||||
dispatch({ type: 'queryWeather' })
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
* query ({
|
||||
payload,
|
||||
}, { call, put }) {
|
||||
const data = yield call(query, parse(payload))
|
||||
yield put({ type: 'queryWeather', payload: { ...data } })
|
||||
},
|
||||
* queryWeather (action, { call, put }) {
|
||||
const myCityResult = yield call(myCity, { flg: 0 })
|
||||
const result = yield call(queryWeather, { cityCode: myCityResult.selectCityCode })
|
||||
const weather = zuimei.parseActualData(result.data.actual)
|
||||
weather.city = myCityResult.selectCityName
|
||||
yield put({ type: 'queryWeatherSuccess',
|
||||
payload: {
|
||||
weather,
|
||||
} })
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
queryWeatherSuccess (state, action) {
|
||||
return {
|
||||
...state,
|
||||
...action.payload,
|
||||
}
|
||||
},
|
||||
queryWeather (state, action) {
|
||||
return {
|
||||
...state,
|
||||
...action.payload,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
import { parse } from 'qs'
|
||||
import modelExtend from 'dva-model-extend'
|
||||
import { query } from 'services/dashboard'
|
||||
import { model } from 'models/common'
|
||||
import * as weatherService from 'services/weather'
|
||||
|
||||
export default modelExtend(model, {
|
||||
namespace: 'dashboard',
|
||||
state: {
|
||||
weather: {
|
||||
city: '深圳',
|
||||
temperature: '30',
|
||||
name: '晴',
|
||||
icon: '//s5.sencdn.com/web/icons/3d_50/2.png',
|
||||
},
|
||||
sales: [],
|
||||
quote: {
|
||||
avatar: 'http://img.hb.aicdn.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236',
|
||||
},
|
||||
numbers: [],
|
||||
recentSales: [],
|
||||
comments: [],
|
||||
completed: [],
|
||||
browser: [],
|
||||
cpu: {},
|
||||
user: {
|
||||
avatar: 'http://img.hb.aicdn.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236',
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
setup ({ dispatch, history }) {
|
||||
history.listen(({ pathname }) => {
|
||||
if (pathname === '/dashboard' || pathname === '/') {
|
||||
dispatch({ type: 'query' })
|
||||
dispatch({ type: 'queryWeather' })
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
* query ({
|
||||
payload,
|
||||
}, { call, put }) {
|
||||
const data = yield call(query, parse(payload))
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: data,
|
||||
})
|
||||
},
|
||||
* queryWeather ({
|
||||
payload = {},
|
||||
}, { call, put }) {
|
||||
payload.location = 'shenzhen'
|
||||
const result = yield call(weatherService.query, payload)
|
||||
const { success } = result
|
||||
if (success) {
|
||||
const data = result.results[0]
|
||||
const weather = {
|
||||
city: data.location.name,
|
||||
temperature: data.now.temperature,
|
||||
name: data.now.text,
|
||||
icon: `//s5.sencdn.com/web/icons/3d_50/${data.now.code}.png`,
|
||||
}
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
weather,
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
+29
-45
@@ -1,45 +1,29 @@
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { queryURL } from 'utils'
|
||||
import { login } from 'services/login'
|
||||
|
||||
export default {
|
||||
namespace: 'login',
|
||||
state: {
|
||||
loginLoading: false,
|
||||
},
|
||||
|
||||
effects: {
|
||||
* login ({
|
||||
payload,
|
||||
}, { put, call }) {
|
||||
yield put({ type: 'showLoginLoading' })
|
||||
const data = yield call(login, payload)
|
||||
yield put({ type: 'hideLoginLoading' })
|
||||
if (data.success) {
|
||||
const from = queryURL('from')
|
||||
yield put({ type: 'app/query' })
|
||||
if (from) {
|
||||
yield put(routerRedux.push(from))
|
||||
} else {
|
||||
yield put(routerRedux.push('/dashboard'))
|
||||
}
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
showLoginLoading (state) {
|
||||
return {
|
||||
...state,
|
||||
loginLoading: true,
|
||||
}
|
||||
},
|
||||
hideLoginLoading (state) {
|
||||
return {
|
||||
...state,
|
||||
loginLoading: false,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { login } from 'services/login'
|
||||
|
||||
export default {
|
||||
namespace: 'login',
|
||||
|
||||
state: {},
|
||||
|
||||
effects: {
|
||||
* login ({
|
||||
payload,
|
||||
}, { put, call, select }) {
|
||||
const data = yield call(login, payload)
|
||||
const { locationQuery } = yield select(_ => _.app)
|
||||
if (data.success) {
|
||||
const { from } = locationQuery
|
||||
yield put({ type: 'app/query' })
|
||||
if (from && from !== '/login') {
|
||||
yield put(routerRedux.push(from))
|
||||
} else {
|
||||
yield put(routerRedux.push('/dashboard'))
|
||||
}
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
+6
-3
@@ -1,6 +1,7 @@
|
||||
import modelExtend from 'dva-model-extend'
|
||||
import { query } from 'services/posts'
|
||||
import { pageModel } from 'models/common'
|
||||
import queryString from 'query-string'
|
||||
|
||||
export default modelExtend(pageModel, {
|
||||
|
||||
@@ -10,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,
|
||||
...location.query,
|
||||
} })
|
||||
...queryString.parse(location.search),
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
+117
-115
@@ -1,115 +1,117 @@
|
||||
/* global window */
|
||||
import modelExtend from 'dva-model-extend'
|
||||
import { config } from 'utils'
|
||||
import { create, remove, update } from 'services/user'
|
||||
import * as usersService from 'services/users'
|
||||
import { pageModel } from './common'
|
||||
|
||||
const { query } = usersService
|
||||
const { prefix } = config
|
||||
|
||||
export default modelExtend(pageModel, {
|
||||
namespace: 'user',
|
||||
|
||||
state: {
|
||||
currentItem: {},
|
||||
modalVisible: false,
|
||||
modalType: 'create',
|
||||
selectedRowKeys: [],
|
||||
isMotion: window.localStorage.getItem(`${prefix}userIsMotion`) === 'true',
|
||||
},
|
||||
|
||||
subscriptions: {
|
||||
setup ({ dispatch, history }) {
|
||||
history.listen((location) => {
|
||||
if (location.pathname === '/user') {
|
||||
dispatch({
|
||||
type: 'query',
|
||||
payload: location.query,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
effects: {
|
||||
|
||||
* query ({ payload = {} }, { call, put }) {
|
||||
const data = yield call(query, payload)
|
||||
if (data) {
|
||||
yield put({
|
||||
type: 'querySuccess',
|
||||
payload: {
|
||||
list: data.data,
|
||||
pagination: {
|
||||
current: Number(payload.page) || 1,
|
||||
pageSize: Number(payload.pageSize) || 10,
|
||||
total: data.total,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
* delete ({ payload }, { call, put, select }) {
|
||||
const data = yield call(remove, { id: payload })
|
||||
const { selectedRowKeys } = yield select(_ => _.user)
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: { selectedRowKeys: selectedRowKeys.filter(_ => _ !== payload) } })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* multiDelete ({ payload }, { call, put }) {
|
||||
const data = yield call(usersService.remove, payload)
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: { selectedRowKeys: [] } })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* create ({ payload }, { call, put }) {
|
||||
const data = yield call(create, payload)
|
||||
if (data.success) {
|
||||
yield put({ type: 'hideModal' })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* update ({ payload }, { select, call, put }) {
|
||||
const id = yield select(({ user }) => user.currentItem.id)
|
||||
const newUser = { ...payload, id }
|
||||
const data = yield call(update, newUser)
|
||||
if (data.success) {
|
||||
yield put({ type: 'hideModal' })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
reducers: {
|
||||
|
||||
showModal (state, { payload }) {
|
||||
return { ...state, ...payload, modalVisible: true }
|
||||
},
|
||||
|
||||
hideModal (state) {
|
||||
return { ...state, modalVisible: false }
|
||||
},
|
||||
|
||||
switchIsMotion (state) {
|
||||
window.localStorage.setItem(`${prefix}userIsMotion`, !state.isMotion)
|
||||
return { ...state, isMotion: !state.isMotion }
|
||||
},
|
||||
|
||||
},
|
||||
})
|
||||
/* 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 { pageModel } from './common'
|
||||
|
||||
const { query } = usersService
|
||||
const { prefix } = config
|
||||
|
||||
export default modelExtend(pageModel, {
|
||||
namespace: 'user',
|
||||
|
||||
state: {
|
||||
currentItem: {},
|
||||
modalVisible: false,
|
||||
modalType: 'create',
|
||||
selectedRowKeys: [],
|
||||
isMotion: window.localStorage.getItem(`${prefix}userIsMotion`) === 'true',
|
||||
},
|
||||
|
||||
subscriptions: {
|
||||
setup ({ dispatch, history }) {
|
||||
history.listen((location) => {
|
||||
if (location.pathname === '/user') {
|
||||
const payload = queryString.parse(location.search) || { page: 1, pageSize: 10 }
|
||||
dispatch({
|
||||
type: 'query',
|
||||
payload,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
effects: {
|
||||
|
||||
* query ({ payload = {} }, { call, put }) {
|
||||
const data = yield call(query, payload)
|
||||
if (data) {
|
||||
yield put({
|
||||
type: 'querySuccess',
|
||||
payload: {
|
||||
list: data.data,
|
||||
pagination: {
|
||||
current: Number(payload.page) || 1,
|
||||
pageSize: Number(payload.pageSize) || 10,
|
||||
total: data.total,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
* delete ({ payload }, { call, put, select }) {
|
||||
const data = yield call(remove, { id: payload })
|
||||
const { selectedRowKeys } = yield select(_ => _.user)
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: { selectedRowKeys: selectedRowKeys.filter(_ => _ !== payload) } })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* multiDelete ({ payload }, { call, put }) {
|
||||
const data = yield call(usersService.remove, payload)
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: { selectedRowKeys: [] } })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* create ({ payload }, { call, put }) {
|
||||
const data = yield call(create, payload)
|
||||
if (data.success) {
|
||||
yield put({ type: 'hideModal' })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
* update ({ payload }, { select, call, put }) {
|
||||
const id = yield select(({ user }) => user.currentItem.id)
|
||||
const newUser = { ...payload, id }
|
||||
const data = yield call(update, newUser)
|
||||
if (data.success) {
|
||||
yield put({ type: 'hideModal' })
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
reducers: {
|
||||
|
||||
showModal (state, { payload }) {
|
||||
return { ...state, ...payload, modalVisible: true }
|
||||
},
|
||||
|
||||
hideModal (state) {
|
||||
return { ...state, modalVisible: false }
|
||||
},
|
||||
|
||||
switchIsMotion (state) {
|
||||
window.localStorage.setItem(`${prefix}userIsMotion`, !state.isMotion)
|
||||
return { ...state, isMotion: !state.isMotion }
|
||||
},
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* global location */
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
import { query } from '../../services/user'
|
||||
|
||||
@@ -12,8 +11,8 @@ export default {
|
||||
|
||||
subscriptions: {
|
||||
setup ({ dispatch, history }) {
|
||||
history.listen(() => {
|
||||
const match = pathToRegexp('/user/:id').exec(location.pathname)
|
||||
history.listen(({ pathname }) => {
|
||||
const match = pathToRegexp('/user/:id').exec(pathname)
|
||||
if (match) {
|
||||
dispatch({ type: 'query', payload: { id: match[1] } })
|
||||
}
|
||||
|
||||
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 |
@@ -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 |
+78
-135
@@ -1,149 +1,92 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Router } from 'dva/router'
|
||||
import { Switch, Route, Redirect, routerRedux } from 'dva/router'
|
||||
import dynamic from 'dva/dynamic'
|
||||
import App from 'routes/app'
|
||||
|
||||
const registerModel = (app, model) => {
|
||||
if (!(app._models.filter(m => m.namespace === model.namespace).length === 1)) {
|
||||
app.model(model)
|
||||
}
|
||||
}
|
||||
const { ConnectedRouter } = routerRedux
|
||||
|
||||
const Routers = function ({ history, app }) {
|
||||
const error = dynamic({
|
||||
app,
|
||||
component: () => import('./routes/error'),
|
||||
})
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: App,
|
||||
getIndexRoute (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/dashboard'))
|
||||
cb(null, { component: require('routes/dashboard/') })
|
||||
}, 'dashboard')
|
||||
},
|
||||
childRoutes: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/dashboard'))
|
||||
cb(null, require('routes/dashboard/'))
|
||||
}, 'dashboard')
|
||||
},
|
||||
}, {
|
||||
path: 'user',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/user'))
|
||||
cb(null, require('routes/user/'))
|
||||
}, 'user')
|
||||
},
|
||||
}, {
|
||||
path: 'user/:id',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/user/detail'))
|
||||
cb(null, require('routes/user/detail/'))
|
||||
}, 'user-detail')
|
||||
},
|
||||
}, {
|
||||
path: 'login',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/login'))
|
||||
cb(null, require('routes/login/'))
|
||||
}, 'login')
|
||||
},
|
||||
}, {
|
||||
path: 'request',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/request/'))
|
||||
}, 'request')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/iconfont',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/iconfont/'))
|
||||
}, 'UIElement-iconfont')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/search',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/search/'))
|
||||
}, 'UIElement-search')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/dropOption',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/dropOption/'))
|
||||
}, 'UIElement-dropOption')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/layer',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/layer/'))
|
||||
}, 'UIElement-layer')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/dataTable',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/dataTable/'))
|
||||
}, 'UIElement-dataTable')
|
||||
},
|
||||
}, {
|
||||
path: 'UIElement/editor',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/UIElement/editor/'))
|
||||
}, 'UIElement-editor')
|
||||
},
|
||||
}, {
|
||||
path: 'chart/lineChart',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/chart/lineChart/'))
|
||||
}, 'chart-lineChart')
|
||||
},
|
||||
}, {
|
||||
path: 'chart/barChart',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/chart/barChart/'))
|
||||
}, 'chart-barChart')
|
||||
},
|
||||
}, {
|
||||
path: 'chart/areaChart',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/chart/areaChart/'))
|
||||
}, 'chart-areaChart')
|
||||
},
|
||||
}, {
|
||||
path: 'post',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
registerModel(app, require('models/post'))
|
||||
cb(null, require('routes/post/'))
|
||||
}, 'post')
|
||||
},
|
||||
}, {
|
||||
path: '*',
|
||||
getComponent (nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('routes/error/'))
|
||||
}, 'error')
|
||||
},
|
||||
},
|
||||
],
|
||||
path: '/dashboard',
|
||||
models: () => [import('./models/dashboard')],
|
||||
component: () => import('./routes/dashboard/'),
|
||||
}, {
|
||||
path: '/user',
|
||||
models: () => [import('./models/user')],
|
||||
component: () => import('./routes/user/'),
|
||||
}, {
|
||||
path: '/user/:id',
|
||||
models: () => [import('./models/user/detail')],
|
||||
component: () => import('./routes/user/detail/'),
|
||||
}, {
|
||||
path: '/login',
|
||||
models: () => [import('./models/login')],
|
||||
component: () => import('./routes/login/'),
|
||||
}, {
|
||||
path: '/request',
|
||||
component: () => import('./routes/request/'),
|
||||
}, {
|
||||
path: '/UIElement/iconfont',
|
||||
component: () => import('./routes/UIElement/iconfont/'),
|
||||
}, {
|
||||
path: '/UIElement/search',
|
||||
component: () => import('./routes/UIElement/search/'),
|
||||
}, {
|
||||
path: '/UIElement/dropOption',
|
||||
component: () => import('./routes/UIElement/dropOption/'),
|
||||
}, {
|
||||
path: '/UIElement/layer',
|
||||
component: () => import('./routes/UIElement/layer/'),
|
||||
}, {
|
||||
path: '/UIElement/dataTable',
|
||||
component: () => import('./routes/UIElement/dataTable/'),
|
||||
}, {
|
||||
path: '/UIElement/editor',
|
||||
component: () => import('./routes/UIElement/editor/'),
|
||||
}, {
|
||||
path: '/chart/ECharts',
|
||||
component: () => import('./routes/chart/ECharts/'),
|
||||
}, {
|
||||
path: '/chart/highCharts',
|
||||
component: () => import('./routes/chart/highCharts/'),
|
||||
}, {
|
||||
path: '/chart/Recharts',
|
||||
component: () => import('./routes/chart/Recharts/'),
|
||||
}, {
|
||||
path: '/post',
|
||||
models: () => [import('./models/post')],
|
||||
component: () => import('./routes/post/'),
|
||||
},
|
||||
]
|
||||
|
||||
return <Router history={history} routes={routes} />
|
||||
return (
|
||||
<ConnectedRouter history={history}>
|
||||
<App>
|
||||
<Switch>
|
||||
<Route exact path="/" render={() => (<Redirect to="/dashboard" />)} />
|
||||
{
|
||||
routes.map(({ path, ...dynamics }, key) => (
|
||||
<Route key={key}
|
||||
exact
|
||||
path={path}
|
||||
component={dynamic({
|
||||
app,
|
||||
...dynamics,
|
||||
})}
|
||||
/>
|
||||
))
|
||||
}
|
||||
<Route component={error} />
|
||||
</Switch>
|
||||
</App>
|
||||
</ConnectedRouter>
|
||||
)
|
||||
}
|
||||
|
||||
Routers.propTypes = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+42
-22
@@ -1,29 +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()
|
||||
@@ -36,6 +44,7 @@ const App = ({ children, dispatch, app, loading, location }) => {
|
||||
const headerProps = {
|
||||
menu,
|
||||
user,
|
||||
location,
|
||||
siderFold,
|
||||
isNavbar,
|
||||
menuPopoverVisible,
|
||||
@@ -56,6 +65,7 @@ const App = ({ children, dispatch, app, loading, location }) => {
|
||||
|
||||
const siderProps = {
|
||||
menu,
|
||||
location,
|
||||
siderFold,
|
||||
darkTheme,
|
||||
navOpenKeys,
|
||||
@@ -70,15 +80,19 @@ const App = ({ children, dispatch, app, loading, location }) => {
|
||||
|
||||
const breadProps = {
|
||||
menu,
|
||||
location,
|
||||
}
|
||||
|
||||
if (openPages && openPages.includes(pathname)) {
|
||||
return (<div>
|
||||
<Loader spinning={loading.effects['app/query']} />
|
||||
<Loader fullScreen spinning={loading.effects['app/query']} />
|
||||
{children}
|
||||
</div>)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Loader fullScreen spinning={loading.effects['app/query']} />
|
||||
<Helmet>
|
||||
<title>ANTD ADMIN</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
@@ -86,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 })}>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
@@ -113,4 +133,4 @@ App.propTypes = {
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default connect(({ app, loading }) => ({ app, loading }))(App)
|
||||
export default withRouter(connect(({ app, loading }) => ({ app, loading }))(App))
|
||||
|
||||
@@ -0,0 +1,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
|
||||
@@ -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>:
|
||||
<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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}))
|
||||
@@ -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)
|
||||
}))
|
||||
+5
-5
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
+3
-4
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Spin } from 'antd'
|
||||
import styles from './weather.less'
|
||||
|
||||
function Weather ({ city, icon, dateTime, temperature, name }) {
|
||||
return (<div className={styles.weather}>
|
||||
<div className={styles.left}>
|
||||
<div className={styles.icon}
|
||||
style={{
|
||||
backgroundImage: `url(${icon})`,
|
||||
}}
|
||||
/>
|
||||
<p>{name}</p>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
<h1 className={styles.temperature}>{`${temperature}°`}</h1>
|
||||
<p className={styles.description}>{city},{dateTime}</p>
|
||||
</div>
|
||||
</div>)
|
||||
function Weather ({ city, icon, dateTime, temperature, name, loading }) {
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<div className={styles.weather}>
|
||||
<div className={styles.left}>
|
||||
<div className={styles.icon}
|
||||
style={{
|
||||
backgroundImage: `url(${icon})`,
|
||||
}}
|
||||
/>
|
||||
<p>{name}</p>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
<h1 className={styles.temperature}>{`${temperature}°`}</h1>
|
||||
<p className={styles.description}>{city},{dateTime}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>)
|
||||
}
|
||||
|
||||
Weather.propTypes = {
|
||||
@@ -25,6 +29,7 @@ Weather.propTypes = {
|
||||
dateTime: PropTypes.string,
|
||||
temperature: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
loading: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default Weather
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
||||
import { connect } from 'dva'
|
||||
import { Row, Col, Card } from 'antd'
|
||||
import { color } from 'utils'
|
||||
import { Page } from 'components'
|
||||
import { NumberCard, Quote, Sales, Weather, RecentSales, Comments, Completed, Browser, Cpu, User } from './components'
|
||||
import styles from './index.less'
|
||||
|
||||
@@ -13,92 +14,97 @@ const bodyStyle = {
|
||||
},
|
||||
}
|
||||
|
||||
function Dashboard ({ dashboard }) {
|
||||
const { weather, sales, quote, numbers, recentSales, comments, completed, browser, cpu, user } = dashboard
|
||||
function Dashboard ({ dashboard, loading }) {
|
||||
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 (
|
||||
<Row gutter={24}>
|
||||
{numberCards}
|
||||
<Col lg={18} md={24}>
|
||||
<Card bordered={false}
|
||||
bodyStyle={{
|
||||
padding: '24px 36px 24px 0',
|
||||
}}
|
||||
>
|
||||
<Sales data={sales} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={6} md={24}>
|
||||
<Row gutter={24}>
|
||||
<Col lg={24} md={12}>
|
||||
<Card bordered={false}
|
||||
className={styles.weather}
|
||||
bodyStyle={{
|
||||
padding: 0,
|
||||
height: 204,
|
||||
background: color.blue,
|
||||
}}
|
||||
>
|
||||
<Weather {...weather} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={24} md={12}>
|
||||
<Card bordered={false}
|
||||
className={styles.quote}
|
||||
bodyStyle={{
|
||||
padding: 0,
|
||||
height: 204,
|
||||
background: color.peach,
|
||||
}}
|
||||
>
|
||||
<Quote {...quote} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col lg={12} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<RecentSales data={recentSales} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={12} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Comments data={comments} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={24} md={24}>
|
||||
<Card bordered={false}
|
||||
bodyStyle={{
|
||||
padding: '24px 36px 24px 0',
|
||||
}}
|
||||
>
|
||||
<Completed data={completed} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Browser data={browser} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Cpu {...cpu} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} bodyStyle={{ ...bodyStyle.bodyStyle, padding: 0 }}>
|
||||
<User {...user} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Page loading={loading.models.dashboard && sales.length === 0} className={styles.dashboard}>
|
||||
<Row gutter={24}>
|
||||
{numberCards}
|
||||
<Col lg={18} md={24}>
|
||||
<Card bordered={false}
|
||||
bodyStyle={{
|
||||
padding: '24px 36px 24px 0',
|
||||
}}
|
||||
>
|
||||
<Sales data={sales} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={6} md={24}>
|
||||
<Row gutter={24}>
|
||||
<Col lg={24} md={12}>
|
||||
<Card bordered={false}
|
||||
className={styles.weather}
|
||||
bodyStyle={{
|
||||
padding: 0,
|
||||
height: 204,
|
||||
background: color.blue,
|
||||
}}
|
||||
>
|
||||
<Weather {...weather} loading={loading.effects['dashboard/queryWeather']} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={24} md={12}>
|
||||
<Card bordered={false}
|
||||
className={styles.quote}
|
||||
bodyStyle={{
|
||||
padding: 0,
|
||||
height: 204,
|
||||
background: color.peach,
|
||||
}}
|
||||
>
|
||||
<Quote {...quote} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col lg={12} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<RecentSales data={recentSales} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={12} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Comments data={comments} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={24} md={24}>
|
||||
<Card bordered={false}
|
||||
bodyStyle={{
|
||||
padding: '24px 36px 24px 0',
|
||||
}}
|
||||
>
|
||||
<Completed data={completed} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Browser data={browser} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} {...bodyStyle}>
|
||||
<Cpu {...cpu} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col lg={8} md={24}>
|
||||
<Card bordered={false} bodyStyle={{ ...bodyStyle.bodyStyle, padding: 0 }}>
|
||||
<User {...user} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
Dashboard.propTypes = {
|
||||
dashboard: PropTypes.object,
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default connect(({ dashboard }) => ({ dashboard }))(Dashboard)
|
||||
export default connect(({ dashboard, loading }) => ({ dashboard, loading }))(Dashboard)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,15 +8,13 @@ import styles from './index.less'
|
||||
const FormItem = Form.Item
|
||||
|
||||
const Login = ({
|
||||
login,
|
||||
loading,
|
||||
dispatch,
|
||||
form: {
|
||||
getFieldDecorator,
|
||||
validateFieldsAndScroll,
|
||||
},
|
||||
}) => {
|
||||
const { loginLoading } = login
|
||||
|
||||
function handleOk () {
|
||||
validateFieldsAndScroll((errors, values) => {
|
||||
if (errors) {
|
||||
@@ -29,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>
|
||||
@@ -40,7 +38,7 @@ const Login = ({
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
})(<Input size="large" onPressEnter={handleOk} placeholder="Username" />)}
|
||||
})(<Input onPressEnter={handleOk} placeholder="Username" />)}
|
||||
</FormItem>
|
||||
<FormItem hasFeedback>
|
||||
{getFieldDecorator('password', {
|
||||
@@ -49,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={loginLoading}>
|
||||
<Button type="primary" onClick={handleOk} loading={loading.effects.login}>
|
||||
Sign in
|
||||
</Button>
|
||||
<p>
|
||||
@@ -68,8 +66,8 @@ const Login = ({
|
||||
|
||||
Login.propTypes = {
|
||||
form: PropTypes.object,
|
||||
login: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default connect(({ login }) => ({ login }))(Form.create()(Login))
|
||||
export default connect(({ loading }) => ({ loading }))(Form.create()(Login))
|
||||
|
||||
+53
-51
@@ -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%;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import PropTypes from 'prop-types'
|
||||
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,
|
||||
@@ -13,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,
|
||||
@@ -24,11 +29,11 @@ const Index = ({ post, dispatch, loading, location }) => {
|
||||
onChange (page) {
|
||||
dispatch(routerRedux.push({
|
||||
pathname,
|
||||
query: {
|
||||
search: queryString.stringify({
|
||||
...query,
|
||||
page: page.current,
|
||||
pageSize: page.pageSize,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
},
|
||||
}
|
||||
@@ -36,14 +41,14 @@ const Index = ({ post, dispatch, loading, location }) => {
|
||||
const handleTabClick = (key) => {
|
||||
dispatch(routerRedux.push({
|
||||
pathname,
|
||||
query: {
|
||||
search: queryString.stringify({
|
||||
status: key,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
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} />
|
||||
@@ -52,7 +57,7 @@ const Index = ({ post, dispatch, loading, location }) => {
|
||||
<List {...listProps} />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>)
|
||||
</Page>)
|
||||
}
|
||||
|
||||
Index.propTypes = {
|
||||
|
||||
+15
-19
@@ -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>
|
||||
|
||||
@@ -3,13 +3,16 @@ import PropTypes from 'prop-types'
|
||||
import { Table, Modal } from 'antd'
|
||||
import classnames from 'classnames'
|
||||
import { DropOption } from 'components'
|
||||
import { Link } from 'dva/router'
|
||||
import AnimTableBody from '../../components/DataTable/AnimTableBody'
|
||||
import { Link } from 'react-router-dom'
|
||||
import queryString from 'query-string'
|
||||
import AnimTableBody from 'components/DataTable/AnimTableBody'
|
||||
import styles from './List.less'
|
||||
|
||||
const confirm = Modal.confirm
|
||||
|
||||
const List = ({ onDeleteItem, onEditItem, isMotion, location, ...tableProps }) => {
|
||||
location.query = queryString.parse(location.search)
|
||||
|
||||
const handleMenuClick = (record, e) => {
|
||||
if (e.key === '1') {
|
||||
onEditItem(record)
|
||||
|
||||
@@ -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"
|
||||
|
||||
+20
-12
@@ -3,12 +3,21 @@ import PropTypes from 'prop-types'
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { connect } from 'dva'
|
||||
import { Row, Col, Button, Popconfirm } from 'antd'
|
||||
import { Page } from 'components'
|
||||
import queryString from 'query-string'
|
||||
import List from './List'
|
||||
import Filter from './Filter'
|
||||
import Modal from './Modal'
|
||||
|
||||
const User = ({ location, dispatch, user, loading }) => {
|
||||
const { list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys } = user
|
||||
|
||||
const User = ({
|
||||
location, dispatch, user, loading,
|
||||
}) => {
|
||||
location.query = queryString.parse(location.search)
|
||||
const { query, pathname } = location
|
||||
const {
|
||||
list, pagination, currentItem, modalVisible, modalType, isMotion, selectedRowKeys,
|
||||
} = user
|
||||
const { pageSize } = pagination
|
||||
|
||||
const modalProps = {
|
||||
@@ -38,14 +47,13 @@ const User = ({ location, dispatch, user, loading }) => {
|
||||
location,
|
||||
isMotion,
|
||||
onChange (page) {
|
||||
const { query, pathname } = location
|
||||
dispatch(routerRedux.push({
|
||||
pathname,
|
||||
query: {
|
||||
search: queryString.stringify({
|
||||
...query,
|
||||
page: page.current,
|
||||
pageSize: page.pageSize,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
},
|
||||
onDeleteItem (id) {
|
||||
@@ -79,16 +87,16 @@ const User = ({ location, dispatch, user, loading }) => {
|
||||
const filterProps = {
|
||||
isMotion,
|
||||
filter: {
|
||||
...location.query,
|
||||
...query,
|
||||
},
|
||||
onFilterChange (value) {
|
||||
dispatch(routerRedux.push({
|
||||
pathname: location.pathname,
|
||||
query: {
|
||||
search: queryString.stringify({
|
||||
...value,
|
||||
page: 1,
|
||||
pageSize,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
},
|
||||
onSearch (fieldsValue) {
|
||||
@@ -125,22 +133,22 @@ const User = ({ location, dispatch, user, loading }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="content-inner">
|
||||
<Page inner>
|
||||
<Filter {...filterProps} />
|
||||
{
|
||||
selectedRowKeys.length > 0 &&
|
||||
<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>
|
||||
}
|
||||
<List {...listProps} />
|
||||
{modalVisible && <Modal {...modalProps} />}
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user