Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02d39ace0 | ||
|
|
4d32829445 | ||
|
|
5438e04fc5 | ||
|
|
54bbe4d70a | ||
|
|
78ece0c9fb | ||
|
|
3407f9a0c1 | ||
|
|
f1b78e8d1f | ||
|
|
df2fc9c32e | ||
|
|
cc5c319332 | ||
|
|
43ef09dfed | ||
|
|
0c95751b8d | ||
|
|
843bd1a088 | ||
|
|
a0db71e571 | ||
|
|
7fc14eddd9 | ||
|
|
7f2fdc383b | ||
|
|
ff2caecb3a | ||
|
|
d01df1ef13 | ||
|
|
cd55df3a15 | ||
|
|
ce59f3e7b2 | ||
|
|
4d722f103a | ||
|
|
c1bc6f27b1 | ||
|
|
ed88c087bf | ||
|
|
4e337caa07 | ||
|
|
ea3929b4c2 | ||
|
|
9eff4ca129 | ||
|
|
d6d94e2121 | ||
|
|
737c0236d6 | ||
|
|
69571f2916 | ||
|
|
6dffa7378c | ||
|
|
c2a7bc7106 | ||
|
|
e752750c9e | ||
|
|
32bde8f69e | ||
|
|
b5f9ef51f1 | ||
|
|
8c10be6ee6 | ||
|
|
c1e3872792 | ||
|
|
c3eef53e4d | ||
|
|
a1b9c0c33d | ||
|
|
c49b0edbe9 | ||
|
|
0fd8824ad7 | ||
|
|
973199135f | ||
|
|
43b7b21ad3 | ||
|
|
ba96ebb874 | ||
|
|
c66f086f42 | ||
|
|
07b2175e92 | ||
|
|
d245a1eabc | ||
|
|
f1e2fd3b18 | ||
|
|
a6b3dba92e | ||
|
|
9fd0abe6ea | ||
|
|
d06ee20c47 | ||
|
|
2ef1fa0367 | ||
|
|
9d459106c1 | ||
|
|
cd5a52a8fc | ||
|
|
d89320f578 | ||
|
|
df5ce2991e | ||
|
|
668c9c7dfe | ||
|
|
9bd13055c0 | ||
|
|
9f3adda59d | ||
|
|
bfa7aaecb8 | ||
|
|
9d4310d8e0 | ||
|
|
b3555b01f3 | ||
|
|
74895fbb0d | ||
|
|
5f04d19d2d | ||
|
|
0fef06e0c6 | ||
|
|
89d22451c5 | ||
|
|
fb49056c73 | ||
|
|
a3071819c4 | ||
|
|
d4e10ad5c2 | ||
|
|
59e9a1053e | ||
|
|
308fc09b33 | ||
|
|
99ec9facd3 | ||
|
|
2a96d7a5f6 | ||
|
|
195e1d17f8 | ||
|
|
580ff59b3d | ||
|
|
cfa5aae5da | ||
|
|
761125735a | ||
|
|
d1b12ff0e1 | ||
|
|
a47176a4e5 | ||
|
|
bc3d7fb39a | ||
|
|
458548150c | ||
|
|
f6e11bb464 | ||
|
|
479fc647c3 | ||
|
|
9a4c63390d | ||
|
|
42cd1221fa | ||
|
|
98b773fdc3 | ||
|
|
cd54fcbf52 | ||
|
|
bd68f8c631 | ||
|
|
3fde5aaa3c | ||
|
|
2f34de5602 | ||
|
|
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 | ||
|
|
38637ef167 | ||
|
|
fe8527e72e | ||
|
|
da64cac414 |
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"presets": [
|
||||
"umi/babel"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"babel-plugin-module-resolver",
|
||||
{
|
||||
"alias": {
|
||||
"components": "./src/components",
|
||||
"utils": "./src/utils",
|
||||
"config": "./src/utils/config",
|
||||
"enums": "./src/utils/enums",
|
||||
"services": "./src/services",
|
||||
"models": "./src/models",
|
||||
"routes": "./src/routes",
|
||||
"themes": "./src/themes"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
src/**/*-test.js
|
||||
src/public
|
||||
src/routes/chart/ECharts/theme
|
||||
src/routes/chart/highCharts/mapdata
|
||||
|
||||
@@ -1,52 +1,48 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"extends": "umi",
|
||||
"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,
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 8,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": "node"
|
||||
}
|
||||
"react/jsx-first-prop-new-line": 0,
|
||||
"react/jsx-filename-extension": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
> 请酌情提供细节,并保持issue精简便于查阅
|
||||
> 1. 功能需求 => 详细说明
|
||||
> 2. Bug反馈
|
||||
> 2.1 简单描述下报错
|
||||
> 2.2 你期望什么结果
|
||||
> 2.3 如何操作导致的
|
||||
> 2.4 可提供运行环境信息
|
||||
> 3. 代码求助 => 可以提,未必及时答复
|
||||
@@ -1,4 +1,16 @@
|
||||
dist
|
||||
node_modules
|
||||
yarn.lock
|
||||
npm-debug.log
|
||||
dist
|
||||
node_modules
|
||||
yarn.lock
|
||||
npm-debug.log
|
||||
|
||||
# ide
|
||||
.idea
|
||||
|
||||
# Mac General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# umi
|
||||
.umi
|
||||
.umi-production
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
const path = require('path')
|
||||
const { version } = require('./package.json')
|
||||
|
||||
const svgSpriteDirs = [
|
||||
path.resolve(__dirname, 'src/svg/'),
|
||||
require.resolve('antd').replace(/index\.js$/, '')
|
||||
]
|
||||
|
||||
export default {
|
||||
entry : 'src/index.js',
|
||||
svgSpriteLoaderDirs : svgSpriteDirs,
|
||||
theme : "./theme.config.js",
|
||||
publicPath : `/${version}/`,
|
||||
outputPath : `./dist/${version}`,
|
||||
// 接口代理示例
|
||||
proxy: {
|
||||
"/api/v1/weather": {
|
||||
"target": "https://api.seniverse.com/",
|
||||
"changeOrigin": true,
|
||||
"pathRewrite": { "^/api/v1/weather" : "/v3/weather" }
|
||||
},
|
||||
// "/api/v2": {
|
||||
// "target": "http://192.168.0.110",
|
||||
// "changeOrigin": true,
|
||||
// "pathRewrite": { "^/api/v2" : "/api/v2" }
|
||||
// }
|
||||
},
|
||||
env : {
|
||||
development: {
|
||||
extraBabelPlugins: [
|
||||
"dva-hmr",
|
||||
"transform-runtime",
|
||||
[
|
||||
"import", {
|
||||
"libraryName": "antd",
|
||||
"style": true
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
production: {
|
||||
extraBabelPlugins: [
|
||||
"transform-runtime",
|
||||
[
|
||||
"import", {
|
||||
"libraryName": "antd",
|
||||
"style": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
dllPlugin : {
|
||||
exclude: ["babel-runtime"],
|
||||
include: ["dva/router", "dva/saga", "dva/fetch"]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
const mock = {}
|
||||
require('fs').readdirSync(require('path').join(__dirname + '/src/mock')).forEach(function(file) {
|
||||
Object.assign(mock, require('./src/mock/' + file))
|
||||
})
|
||||
module.exports = mock
|
||||
@@ -0,0 +1,71 @@
|
||||
import {resolve} from "path";
|
||||
|
||||
export default {
|
||||
// for query-string@6 https://github.com/sorrycc/blog/issues/68
|
||||
es5ImcompatibleVersions: true,
|
||||
plugins: [
|
||||
[
|
||||
'umi-plugin-react',
|
||||
{
|
||||
dva: true,
|
||||
antd: true,
|
||||
routes: {
|
||||
exclude: [
|
||||
/model\.(j|t)sx?$/,
|
||||
/service\.(j|t)sx?$/,
|
||||
/models\//,
|
||||
/components\//,
|
||||
/services\//,
|
||||
/chart\/Container\.js$/,
|
||||
/chart\/ECharts\/.+Component\.js$/,
|
||||
/chart\/ECharts\/.+ComPonent\.js$/,
|
||||
/chart\/ECharts\/theme\/.+\.js$/,
|
||||
/chart\/highCharts\/.+Component\.js$/,
|
||||
/chart\/highCharts\/mapdata\/.+\.js$/,
|
||||
/chart\/Recharts\/.+Component\.js$/,
|
||||
/chart\/Recharts\/Container\.js$/,
|
||||
],
|
||||
},
|
||||
dll: {
|
||||
exclude: [],
|
||||
include: ["dva", "dva/router", "dva/saga", "dva/fetch", "antd/es"],
|
||||
},
|
||||
hardSource: /* isMac */process.platform === 'darwin',
|
||||
},
|
||||
],
|
||||
],
|
||||
theme: "./theme.config.js",
|
||||
// 接口代理示例
|
||||
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" }
|
||||
// }
|
||||
},
|
||||
alias: {
|
||||
themes: resolve(__dirname, './src/themes'),
|
||||
components: resolve(__dirname,"./src/components"),
|
||||
utils: resolve(__dirname,"./src/utils"),
|
||||
config: resolve(__dirname,"./src/utils/config"),
|
||||
enums: resolve(__dirname,"./src/utils/enums"),
|
||||
services: resolve(__dirname,"./src/services"),
|
||||
models: resolve(__dirname,"./src/models"),
|
||||
routes: resolve(__dirname,"./src/routes"),
|
||||
},
|
||||
urlLoaderExcludes: [
|
||||
/\.svg$/,
|
||||
],
|
||||
ignoreMomentLocale: true,
|
||||
chainWebpack(config) {
|
||||
config.module.rule('svg')
|
||||
.test(/\.svg$/i)
|
||||
.use('svg-sprite-loader')
|
||||
.loader(require.resolve('svg-sprite-loader'));
|
||||
},
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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)
|
||||
@@ -13,87 +13,99 @@
|
||||
|
||||
## 特性
|
||||
|
||||
- 基于[react](https://github.com/facebook/react),[ant-design](https://github.com/ant-design/ant-design),[dva](https://github.com/dvajs/dva),[Mock](https://github.com/nuysoft/Mock) 企业级后台管理系统最佳实践。
|
||||
- 基于Antd UI 设计语言,提供后台管理系统常见使用场景。
|
||||
- 基于[dva](https://github.com/dvajs/dva)动态加载 Model 和路由,按需加载。
|
||||
- 使用[roadhog](https://github.com/sorrycc/roadhog)本地调试和构建,其中Mock功能实现脱离后端独立开发。
|
||||
- 浅度响应式设计。
|
||||
* 基于[react](https://github.com/facebook/react),[ant-design](https://github.com/ant-design/ant-design),[dva](https://github.com/dvajs/dva),[Mock](https://github.com/nuysoft/Mock) 企业级后台管理系统最佳实践。
|
||||
* 基于 Antd UI 设计语言,提供后台管理系统常见使用场景。
|
||||
* 基于[dva](https://github.com/dvajs/dva)动态加载 Model 和路由,按需加载。
|
||||
* 使用[umi](https://github.com/umijs/umi)本地调试和构建,其中 Mock 功能实现脱离后端独立开发。
|
||||
* 浅度响应式设计。
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 5.0.0-beta
|
||||
|
||||
`2018-6-20`
|
||||
|
||||
* 感谢@sorrycc、@xiaohuoni [PR](https://github.com/zuiidea/antd-admin/pull/770)
|
||||
|
||||
* 更新`roadhog`至`umi`
|
||||
详见 [使用 umi 改进 dva 项目开发](https://github.com/sorrycc/blog/issues/66#issuecomment-408596579) | [umi model 用法](https://github.com/umijs/umi/issues/171)
|
||||
|
||||
### 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`
|
||||
|
||||
- 更新[roadhog](https://github.com/sorrycc/roadhog)至`1.0.0-beta.7`,得益于`webpack@3.4`,编译速度不减。
|
||||
- 基于使用roadhog的dll插件,开发时编译耗时减半。
|
||||
- 新增打包时按项目版本号生成文件目录。[#449](https://github.com/zuiidea/antd-admin/issues/449)
|
||||
- 更新`eslint`,并适当修改了`.eslintrc`。
|
||||
* 更新[roadhog](https://github.com/sorrycc/roadhog)至`1.0.0-beta.7`,得益于`webpack@3.4`,编译速度不减。
|
||||
* 基于使用 roadhog 的 dll 插件,开发时编译耗时减半。
|
||||
* 新增打包时按项目版本号生成文件目录。[#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)
|
||||
|
||||
## 开发构建
|
||||
|
||||
### 目录结构
|
||||
### 目录结构
|
||||
|
||||
```bash
|
||||
├── /dist/ # 项目输出目录
|
||||
├── /mock/ # 数据mock
|
||||
├── /public/ # 公共文件,编译时copy至dist目录
|
||||
├── /src/ # 项目源码目录
|
||||
│ ├── /public/ # 公共文件,编译时copy至dist目录
|
||||
│ ├── /components/ # UI组件及UI相关方法
|
||||
│ │ ├── skin.less # 全局样式
|
||||
│ │ └── vars.less # 全局样式变量
|
||||
│ ├── /routes/ # 路由组件
|
||||
│ │ └── app.js # 路由入口
|
||||
│ ├── /layouts/ # 全局组件
|
||||
│ │ └── app.js # 页面入口
|
||||
│ │ └── index.js # 入口文件
|
||||
│ ├── /models/ # 数据模型
|
||||
│ ├── /pages/ # 页面组件
|
||||
│ │ └── document.ejs # html模版
|
||||
│ ├── /services/ # 数据接口
|
||||
│ ├── /themes/ # 项目样式
|
||||
│ ├── /mock/ # 数据mock
|
||||
│ │ ├── default.less # 全局样式
|
||||
│ │ └── vars.less # 全局样式变量
|
||||
│ ├── /utils/ # 工具函数
|
||||
│ │ ├── config.js # 项目常规配置
|
||||
│ │ ├── menu.js # 菜单及面包屑配置
|
||||
│ │ ├── config.js # 项目常规配置
|
||||
│ │ ├── request.js # 异步请求函数
|
||||
│ │ ├── request.js # 异步请求函数(axios)
|
||||
│ │ └── theme.js # 项目需要在js中使用到样式变量
|
||||
│ ├── route.js # 路由配置
|
||||
│ ├── index.js # 入口文件
|
||||
│ └── index.html
|
||||
├── package.json # 项目信息
|
||||
├── .eslintrc # Eslint配置
|
||||
└── .roadhogrc.js # roadhog配置
|
||||
└── .umirc.js # umi配置
|
||||
└── .umirc.mock.js # mock配置
|
||||
└── .theme.config.js # 主题less编译配置
|
||||
```
|
||||
pages中可参考 [duck 模式](https://medium.freecodecamp.org/scaling-your-redux-app-with-ducks-6115955638be)
|
||||
|
||||
文件夹命名说明:
|
||||
|
||||
- components:组件(方法)为单位以文件夹保存,文件夹名组件首字母大写(如`DataTable`),方法首字母小写(如`layer`),文件夹内主文件与文件夹同名,多文件以`index.js`导出对象(如`./src/components/Layout`)。
|
||||
- routes:页面为单位以文件夹保存,文件夹名首字母小写(特殊除外,如`UIElement`),文件夹内主文件以`index.js`导出,多文件时可建立`components`文件夹(如`./src/routes/dashboard`),如果有子路由,依次按照路由层次建立文件夹(如`./src/routes/UIElement`)。
|
||||
* components:组件(方法)为单位以文件夹保存,文件夹名组件首字母大写(如`DataTable`),方法首字母小写(如`layer`),文件夹内主文件与文件夹同名,多文件以`index.js`导出对象(如`./src/components/Layout`)。
|
||||
* routes:页面为单位以文件夹保存,文件夹名首字母小写(特殊除外,如`UIElement`),文件夹内主文件以`index.js`导出,多文件时可建立`components`文件夹(如`./src/routes/dashboard`),如果有子路由,依次按照路由层次建立文件夹(如`./src/routes/UIElement`)。
|
||||
|
||||
### 快速开始
|
||||
|
||||
@@ -106,31 +118,20 @@ git clone https://github.com/zuiidea/antd-admin.git
|
||||
进入目录安装依赖:
|
||||
|
||||
```bash
|
||||
#开始前请确保没有安装roadhog、webpack到NPM全局目录
|
||||
#开始前请确保没有安装roadhog、webpack到NPM全局目录, 国内用户推荐yarn或者cnpm
|
||||
npm i 或者 yarn install
|
||||
```
|
||||
|
||||
开发:
|
||||
|
||||
```bash
|
||||
npm run build:dll #第一次npm run dev时需运行此命令,使开发时编译更快
|
||||
npm run dev
|
||||
打开 http://localhost:8000
|
||||
npm run start
|
||||
打开 http://localhost:8000 #端口在package.json中cross-env后加上 PORT=8000指定
|
||||
```
|
||||
|
||||
构建:
|
||||
[详情](https://github.com/zuiidea/antd-admin/issues/269)
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
|
||||
将会打包至dist/{version}目录 #package.json里version字段
|
||||
|
||||
npm run build:new
|
||||
|
||||
将会打包至dist/{version增加1}目录 #package.json里version字段
|
||||
```
|
||||
|
||||
代码检测:
|
||||
|
||||
```bash
|
||||
@@ -139,29 +140,33 @@ npm run lint
|
||||
|
||||
## FAQ
|
||||
|
||||
- 项目打包后如何部署? [#269](https://github.com/zuiidea/antd-admin/issues/269)
|
||||
- 如何做权限管理? [#384](https://github.com/zuiidea/antd-admin/issues/384)
|
||||
- 如何使用mock.js模拟接口,怎么使用线上接口? [#348](https://github.com/zuiidea/antd-admin/issues/348)
|
||||
- 如何使用Iconfont,如何使用本地的svg图标? [#270](https://github.com/zuiidea/antd-admin/issues/270)
|
||||
- 怎么按版本打包,上线时不影响正在访问的用户? [#449](https://github.com/zuiidea/antd-admin/issues/449)
|
||||
- windows处理CRLF?[参考](http://blog.csdn.net/lysc_forever/article/details/42835203)
|
||||
* 项目打包后如何部署? [#269](https://github.com/zuiidea/antd-admin/issues/269)
|
||||
* 如何做权限管理? [#384](https://github.com/zuiidea/antd-admin/issues/384)
|
||||
* 如何使用 mock.js 模拟接口,怎么使用线上接口? [#348](https://github.com/zuiidea/antd-admin/issues/348)
|
||||
* 如何使用 Iconfont,如何使用本地的 svg 图标? [#270](https://github.com/zuiidea/antd-admin/issues/270)
|
||||
* 怎么按版本打包,上线时不影响正在访问的用户? [#449](https://github.com/zuiidea/antd-admin/issues/449)
|
||||
* windows 处理 CRLF?[参考](http://blog.csdn.net/lysc_forever/article/details/42835203)
|
||||
|
||||
```bash
|
||||
git config --global core.autocrlf false
|
||||
```
|
||||
```bash
|
||||
git config --global core.autocrlf false
|
||||
```
|
||||
|
||||
## 参考
|
||||
|
||||
用户列表:<https://github.com/dvajs/dva/tree/master/examples/user-dashboard>
|
||||
|
||||
dashboard设计稿:<https://dribbble.com/shots/3108122-Dashboard-Admin> (已征得作者同意)
|
||||
dashboard 设计稿:<https://dribbble.com/shots/3108122-Dashboard-Admin> (已征得作者同意)
|
||||
|
||||
## 截屏
|
||||
|
||||
web
|
||||
|
||||

|
||||

|
||||
|
||||
移动
|
||||
|
||||

|
||||

|
||||
|
||||
效果图
|
||||
|
||||

|
||||
|
||||
|
Before Width: | Height: | Size: 3.7 MiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 645 KiB |
@@ -1,5 +1,5 @@
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const queryArray = (array, key, keyAlias = 'key') => {
|
||||
if (!(array instanceof Array)) {
|
||||
@@ -1,7 +1,7 @@
|
||||
import { color } from '../utils/theme'
|
||||
import { color } from '../src/utils/theme'
|
||||
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const { apiPrefix } = config
|
||||
|
||||
@@ -4,7 +4,7 @@ const { apiPrefix } = config
|
||||
let database = [
|
||||
{
|
||||
id: '1',
|
||||
icon: 'laptop',
|
||||
icon: 'dashboard',
|
||||
name: 'Dashboard',
|
||||
route: '/dashboard',
|
||||
},
|
||||
@@ -78,7 +78,7 @@ let database = [
|
||||
id: '45',
|
||||
bpid: '4',
|
||||
mpid: '4',
|
||||
name: 'Editor',
|
||||
name: '56pxor',
|
||||
icon: 'edit',
|
||||
route: '/UIElement/editor',
|
||||
},
|
||||
@@ -93,32 +93,32 @@ let database = [
|
||||
{
|
||||
id: '5',
|
||||
bpid: '1',
|
||||
name: 'Recharts',
|
||||
name: 'Charts',
|
||||
icon: 'code-o',
|
||||
},
|
||||
{
|
||||
id: '51',
|
||||
bpid: '5',
|
||||
mpid: '5',
|
||||
name: 'LineChart',
|
||||
name: 'ECharts',
|
||||
icon: 'line-chart',
|
||||
route: '/chart/lineChart',
|
||||
route: '/chart/ECharts',
|
||||
},
|
||||
{
|
||||
id: '52',
|
||||
bpid: '5',
|
||||
mpid: '5',
|
||||
name: 'BarChart',
|
||||
name: 'highCharts',
|
||||
icon: 'bar-chart',
|
||||
route: '/chart/barChart',
|
||||
route: '/chart/highCharts',
|
||||
},
|
||||
{
|
||||
id: '53',
|
||||
bpid: '5',
|
||||
mpid: '5',
|
||||
name: 'AreaChart',
|
||||
name: 'Rechartst',
|
||||
icon: 'area-chart',
|
||||
route: '/chart/areaChart',
|
||||
route: '/chart/Recharts',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
@@ -1,6 +1,6 @@
|
||||
const qs = require('qs')
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const { apiPrefix } = config
|
||||
|
||||
@@ -173,7 +173,7 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
|
||||
[`DELETE ${apiPrefix}/users`] (req, res) {
|
||||
[`POST ${apiPrefix}/users/delete`] (req, res) {
|
||||
const { ids } = req.body
|
||||
database = database.filter(item => !ids.some(_ => _ === item.id))
|
||||
res.status(204).end()
|
||||
@@ -1,63 +1,63 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "antd-admin",
|
||||
"version": "4.3.3",
|
||||
"version": "5.0.0-beta",
|
||||
"dependencies": {
|
||||
"antd": "^2.11.2",
|
||||
"axios": "^0.16.2",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"classnames": "^2.2.5",
|
||||
"d3-shape": "^1.2.0",
|
||||
"draftjs-to-markdown": "^0.4.0",
|
||||
"dva": "^1.2.0",
|
||||
"dva-loading": "^0.2.0",
|
||||
"ejs-loader": "^0.3.0",
|
||||
"js-beautify": "^1.6.14",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"antd": "^3.9.0",
|
||||
"axios": "^0.18.0",
|
||||
"classnames": "^2.2.6",
|
||||
"d3-shape": "^1.2.2",
|
||||
"draftjs-to-html": "^0.8.4",
|
||||
"draftjs-to-markdown": "^0.5.1",
|
||||
"dva-model-extend": "^0.1.2",
|
||||
"echarts": "^4.1.0",
|
||||
"echarts-for-react": "^2.0.14",
|
||||
"echarts-gl": "^1.1.1",
|
||||
"echarts-liquidfill": "^2.0.2",
|
||||
"highcharts-exporting": "^0.1.7",
|
||||
"highcharts-more": "^0.1.7",
|
||||
"jsonp": "^0.2.1",
|
||||
"less-vars-to-js": "^1.1.2",
|
||||
"lodash": "^4.17.4",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"qs": "^6.5.0",
|
||||
"rc-tween-one": "^1.3.1",
|
||||
"react": "^15.6.1",
|
||||
"react-countup": "^2.1.1",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-draft-wysiwyg": "^1.10.0",
|
||||
"react-helmet": "^5.1.3",
|
||||
"recharts": "^0.22.4",
|
||||
"roadhog": "^1.2.1"
|
||||
"path-to-regexp": "^2.4.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"qs": "^6.5.2",
|
||||
"query-string": "^6.1.0",
|
||||
"rc-tween-one": "^2.2.3",
|
||||
"react-adsense": "^0.0.6",
|
||||
"react-countup": "^4.0.0-alpha.6",
|
||||
"react-draft-wysiwyg": "^1.12.13",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-highcharts": "^16.0.2",
|
||||
"recharts": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-plugin-dev-expression": "^0.2.1",
|
||||
"babel-plugin-dva-hmr": "^0.3.2",
|
||||
"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",
|
||||
"dva-model-extend": "^0.1.1",
|
||||
"eslint": "^4.1.1",
|
||||
"eslint-config-airbnb": "^15.0.2",
|
||||
"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"
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "^5.5.0",
|
||||
"eslint-config-umi": "^0.1.5",
|
||||
"eslint-plugin-flowtype": "^2.50.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"js-beautify": "^1.8.1",
|
||||
"less-vars-to-js": "^1.3.0",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"svg-sprite-loader": "^3.9.2",
|
||||
"umi": "^2.0.0",
|
||||
"umi-plugin-react": "^1.0.0"
|
||||
},
|
||||
"pre-commit": ["lint"],
|
||||
"pre-commit": [
|
||||
"lint"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "set BROWSER=none&&set HOST=0.0.0.0&&roadhog server",
|
||||
"analyze": "cross-env ANALYZE=1 umi build",
|
||||
"start": "umi dev",
|
||||
"lint": "eslint --fix --ext .js src",
|
||||
"build": "roadhog build",
|
||||
"build:dll": "roadhog buildDll",
|
||||
"build:new": "node version && roadhog build"
|
||||
"build": "umi build",
|
||||
"test": "umi test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 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 |
@@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { TweenOneGroup } from 'rc-tween-one'
|
||||
|
||||
const enterAnim = [
|
||||
@@ -40,28 +39,12 @@ const leaveAnim = [
|
||||
},
|
||||
]
|
||||
|
||||
const AnimTableBody = ({ body, page = 1, current }) => {
|
||||
if (current !== +page) {
|
||||
return body
|
||||
}
|
||||
|
||||
return (
|
||||
<TweenOneGroup
|
||||
component="tbody"
|
||||
className={body.props.className}
|
||||
enter={enterAnim}
|
||||
leave={leaveAnim}
|
||||
appear={false}
|
||||
>
|
||||
{body.props.children}
|
||||
</TweenOneGroup>
|
||||
)
|
||||
}
|
||||
|
||||
AnimTableBody.propTypes = {
|
||||
body: PropTypes.element,
|
||||
page: PropTypes.any,
|
||||
current: PropTypes.number.isRequired,
|
||||
}
|
||||
const AnimTableBody = props => (<TweenOneGroup
|
||||
component="tbody"
|
||||
{...props}
|
||||
enter={enterAnim}
|
||||
leave={leaveAnim}
|
||||
appear={false}
|
||||
/>)
|
||||
|
||||
export default AnimTableBody
|
||||
|
||||
@@ -2,18 +2,21 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Table } from 'antd'
|
||||
import { request } from 'utils'
|
||||
import lodash from 'lodash'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import isEqual from 'lodash.isequal'
|
||||
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,
|
||||
@@ -29,12 +32,12 @@ class DataTable extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const staticNextProps = lodash.cloneDeep(nextProps)
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
const staticNextProps = cloneDeep(nextProps)
|
||||
delete staticNextProps.columns
|
||||
const { columns, ...otherProps } = this.props
|
||||
|
||||
if (!lodash.isEqual(staticNextProps, otherProps)) {
|
||||
if (!isEqual(staticNextProps, otherProps)) {
|
||||
this.props = nextProps
|
||||
this.fetch()
|
||||
}
|
||||
@@ -97,13 +100,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,
|
||||
|
||||
@@ -2,7 +2,9 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dropdown, Button, Icon, Menu } from 'antd'
|
||||
|
||||
const DropOption = ({ onMenuClick, menuOptions = [], buttonStyle, dropdownProps }) => {
|
||||
const DropOption = ({
|
||||
onMenuClick, menuOptions = [], buttonStyle, dropdownProps,
|
||||
}) => {
|
||||
const menu = menuOptions.map(item => <Menu.Item key={item.key}>{item.name}</Menu.Item>)
|
||||
return (<Dropdown
|
||||
overlay={<Menu onClick={onMenuClick}>{menu}</Menu>}
|
||||
|
||||
@@ -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,10 +1,10 @@
|
||||
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, location }) => {
|
||||
// 匹配当前路由
|
||||
@@ -24,6 +24,7 @@ const Bread = ({ menu, location }) => {
|
||||
}
|
||||
}
|
||||
|
||||
let paramMap = {}
|
||||
if (!current) {
|
||||
pathArray.push(menu[0] || {
|
||||
id: 1,
|
||||
@@ -36,6 +37,17 @@ const Bread = ({ menu, location }) => {
|
||||
})
|
||||
} else {
|
||||
getPathArray(current)
|
||||
|
||||
let keys = []
|
||||
let values = pathToRegexp(current.route, keys).exec(location.pathname.replace('#', ''))
|
||||
if (keys.length) {
|
||||
keys.forEach((currentValue, index) => {
|
||||
if (typeof currentValue.name !== 'string') {
|
||||
return
|
||||
}
|
||||
paramMap[currentValue.name] = values[index + 1]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 递归查找父级
|
||||
@@ -48,7 +60,7 @@ const Bread = ({ menu, location }) => {
|
||||
return (
|
||||
<Breadcrumb.Item key={key}>
|
||||
{((pathArray.length - 1) !== key)
|
||||
? <Link to={item.route}>
|
||||
? <Link to={pathToRegexp.compile(item.route || '')(paramMap) || '#'}>
|
||||
{content}
|
||||
</Link>
|
||||
: content}
|
||||
|
||||
@@ -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,59 +1,92 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.header {
|
||||
:global .ant-menu-horizontal {
|
||||
& > .ant-menu-submenu {
|
||||
float: right;
|
||||
}
|
||||
border: none;
|
||||
display: inline-block;
|
||||
}
|
||||
box-shadow: @shadow-2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 47px;
|
||||
background-color: #fff;
|
||||
z-index: 999;
|
||||
|
||||
.rightWarpper {
|
||||
display: flex;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 47px;
|
||||
height: 47px;
|
||||
line-height: 47px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: fade(@primary-color, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu {
|
||||
width: 280px;
|
||||
margin-left: 6px;
|
||||
|
||||
:global .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
|
||||
.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,
|
||||
.ant-menu-inline .ant-menu-selected {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
.header {
|
||||
: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;
|
||||
}
|
||||
}
|
||||
box-shadow: @shadow-2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
|
||||
.rightWarpper {
|
||||
display: flex;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: fade(@primary-color, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu {
|
||||
width: 280px;
|
||||
margin-left: 6px;
|
||||
|
||||
:global .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
|
||||
.ant-menu-inline .ant-menu-item,
|
||||
.ant-menu-vertical .ant-menu-item {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.ant-menu-inline .ant-menu-item-selected,
|
||||
.ant-menu-inline .ant-menu-selected {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,292 +1,191 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.layout {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
|
||||
&.withnavbar {
|
||||
.main {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.fold {
|
||||
.sider {
|
||||
width: 42px;
|
||||
|
||||
.logo {
|
||||
img {
|
||||
width: 28px;
|
||||
margin: 6px 7px;
|
||||
}
|
||||
}
|
||||
|
||||
: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;
|
||||
|
||||
&::-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
transition: @transition-ease-out;
|
||||
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 224px;
|
||||
overflow: auto;
|
||||
height: 100vh;
|
||||
transition: @transition-ease-out;
|
||||
|
||||
:global {
|
||||
.content-inner {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: e("calc(100vh - 184px)");
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 24px;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: e("calc(100vh - 184px)");
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global .ant-menu-dark {
|
||||
color: #999;
|
||||
background-color: #3e3e3e;
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spin {
|
||||
:global .ant-spin-container {
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.layout {
|
||||
.main {
|
||||
.container {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.bread {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: e("calc(100vh - 160px)");
|
||||
}
|
||||
|
||||
:global {
|
||||
.content-inner {
|
||||
padding: 12px;
|
||||
min-height: e("calc(100vh - 160px)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
:global {
|
||||
.ant-layout-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
transition: all 0.3s;
|
||||
|
||||
.ant-menu-root {
|
||||
height: ~"calc(100vh - 144px)";
|
||||
overflow-x: hidden;
|
||||
border-right: none;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-content {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
white-space: nowrap;
|
||||
:local {
|
||||
animation: fadeLeftIn 500ms linear;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidemenu {
|
||||
:global{
|
||||
.ant-menu-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bread {
|
||||
margin-bottom: 24px;
|
||||
|
||||
:global {
|
||||
.ant-breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.switchtheme {
|
||||
background-color: #000d18;
|
||||
border-color: #001629;
|
||||
}
|
||||
}
|
||||
|
||||
.light {
|
||||
:global {
|
||||
.ant-layout-sider {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.bread {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-layout-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-back-top {
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeLeftIn {
|
||||
0% {
|
||||
transform: translateX(5px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
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'
|
||||
import styles from './Layout.less'
|
||||
|
||||
const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOpenKeys, menu, location }) => {
|
||||
const { SubMenu } = Menu
|
||||
let openKeysFlag = false
|
||||
|
||||
const Menus = ({
|
||||
siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, location,
|
||||
}) => {
|
||||
// 生成树状
|
||||
const menuTree = arrayToTree(menu.filter(_ => _.mpid !== '-1'), 'id', 'mpid')
|
||||
const levelMap = {}
|
||||
@@ -18,7 +24,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
levelMap[item.id] = item.mpid
|
||||
}
|
||||
return (
|
||||
<Menu.SubMenu
|
||||
<SubMenu
|
||||
key={item.id}
|
||||
title={<span>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
@@ -26,14 +32,14 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
</span>}
|
||||
>
|
||||
{getMenus(item.children, siderFoldN)}
|
||||
</Menu.SubMenu>
|
||||
</SubMenu>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={item.id}>
|
||||
<Link to={item.route}>
|
||||
<Link to={item.route || '#'} style={siderFoldN ? { width: 10 } : {}}>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
{(!siderFoldN || !menuTree.includes(item)) && item.name}
|
||||
{item.name}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)
|
||||
@@ -60,6 +66,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
}
|
||||
|
||||
const onOpenChange = (openKeys) => {
|
||||
if (navOpenKeys.length) changeOpenKeys([]), openKeysFlag = true
|
||||
const latestOpenKey = openKeys.find(key => !navOpenKeys.includes(key))
|
||||
const latestCloseKey = navOpenKeys.find(key => !openKeys.includes(key))
|
||||
let nextOpenKeys = []
|
||||
@@ -83,6 +90,7 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
let defaultSelectedKeys
|
||||
for (let item of menu) {
|
||||
if (item.route && pathToRegexp(item.route).exec(location.pathname)) {
|
||||
if (!navOpenKeys.length && item.mpid && !openKeysFlag) changeOpenKeys([String(item.mpid)])
|
||||
currentMenu = item
|
||||
break
|
||||
}
|
||||
@@ -91,8 +99,12 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
let result = [String(current[id])]
|
||||
const getPath = (item) => {
|
||||
if (item && item[pid]) {
|
||||
result.unshift(String(item[pid]))
|
||||
getPath(queryArray(array, item[pid], id))
|
||||
if (item[pid] === '-1') {
|
||||
result.unshift(String(item['bpid']))
|
||||
} else {
|
||||
result.unshift(String(item[pid]))
|
||||
getPath(queryArray(array, item[pid], id))
|
||||
}
|
||||
}
|
||||
}
|
||||
getPath(current)
|
||||
@@ -111,8 +123,8 @@ const Menus = ({ siderFold, darkTheme, handleClickNavMenu, navOpenKeys, changeOp
|
||||
{...menuProps}
|
||||
mode={siderFold ? 'vertical' : 'inline'}
|
||||
theme={darkTheme ? 'dark' : 'light'}
|
||||
onClick={handleClickNavMenu}
|
||||
defaultSelectedKeys={defaultSelectedKeys}
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
className={styles.sidemenu}
|
||||
>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
@@ -123,7 +135,6 @@ Menus.propTypes = {
|
||||
menu: PropTypes.array,
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
handleClickNavMenu: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
location: PropTypes.object,
|
||||
|
||||
@@ -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,36 @@
|
||||
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.less";
|
||||
|
||||
.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"
|
||||
}
|
||||
@@ -38,7 +38,9 @@ class Search extends React.Component {
|
||||
this.handleSearch()
|
||||
}
|
||||
render () {
|
||||
const { size, select, selectOptions, selectProps, style, keyword } = this.props
|
||||
const {
|
||||
size, select, selectOptions, selectProps, style, keyword,
|
||||
} = this.props
|
||||
const { clearVisible } = this.state
|
||||
return (
|
||||
<Input.Group compact size={size} className={styles.search} style={style}>
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ import ReactDOM from 'react-dom'
|
||||
import classnames from 'classnames'
|
||||
import styles from './layer.less'
|
||||
|
||||
const { info, success, error, warning, confirm } = Modal
|
||||
const {
|
||||
info, success, error, warning, confirm,
|
||||
} = Modal
|
||||
|
||||
const layer = {
|
||||
prefixCls: 'ant-layer',
|
||||
@@ -53,32 +55,31 @@ layer.open = (config) => {
|
||||
const { className, wrapClassName = '', verticalCenter = true } = modalProps
|
||||
const { prefixCls } = layer
|
||||
layer.index += 1
|
||||
const index = layer.index
|
||||
const { index } = layer
|
||||
let div = document.createElement('div')
|
||||
div.id = `${prefixCls}-reference-${index}`
|
||||
div.className = `${prefixCls}-reference`
|
||||
document.body.appendChild(div)
|
||||
|
||||
ReactDOM.render(
|
||||
<Modal
|
||||
visible
|
||||
title="Title"
|
||||
transitionName="zoom"
|
||||
maskTransitionName="fade"
|
||||
onCancel={() => {
|
||||
ReactDOM.render(<Modal
|
||||
visible
|
||||
title="Title"
|
||||
transitionName="zoom"
|
||||
maskTransitionName="fade"
|
||||
onCancel={() => {
|
||||
layer.close(index)
|
||||
}}
|
||||
onOk={() => {
|
||||
onOk={() => {
|
||||
layer.close(index)
|
||||
}}
|
||||
{...modalProps}
|
||||
wrapClassName={classnames({ [styles.verticalCenter]: verticalCenter, [wrapClassName]: true })}
|
||||
className={classnames(prefixCls, className, [`${prefixCls}-${index}`])}
|
||||
>
|
||||
<div className={`${prefixCls}-body-wrapper`} style={{ maxHeight: document.body.clientHeight - 256 }}>
|
||||
{content}
|
||||
</div>
|
||||
</Modal>, div)
|
||||
{...modalProps}
|
||||
wrapClassName={classnames({ [styles.verticalCenter]: verticalCenter, [wrapClassName]: true })}
|
||||
className={classnames(prefixCls, className, [`${prefixCls}-${index}`])}
|
||||
>
|
||||
<div className={`${prefixCls}-body-wrapper`} style={{ maxHeight: document.body.clientHeight - 256 }}>
|
||||
{content}
|
||||
</div>
|
||||
</Modal>, div)
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import '@babel/polyfill'
|
||||
@@ -1,25 +0,0 @@
|
||||
import { message } from 'antd'
|
||||
import dva from 'dva'
|
||||
import createLoading from 'dva-loading'
|
||||
import { browserHistory } from 'dva/router'
|
||||
import 'babel-polyfill'
|
||||
|
||||
// 1. Initialize
|
||||
const app = dva({
|
||||
...createLoading({
|
||||
effects: true,
|
||||
}),
|
||||
history: browserHistory,
|
||||
onError (error) {
|
||||
message.error(error.message)
|
||||
},
|
||||
})
|
||||
|
||||
// 2. Model
|
||||
app.model(require('./models/app'))
|
||||
|
||||
// 3. Router
|
||||
app.router(require('./router'))
|
||||
|
||||
// 4. Start
|
||||
app.start('#root')
|
||||
@@ -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 '../pages/404'
|
||||
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,
|
||||
@@ -73,15 +82,17 @@ const App = ({ children, dispatch, app, loading, location }) => {
|
||||
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 spinning={loading.effects['app/query']} />
|
||||
<Loader fullScreen spinning={loading.effects['app/query']} />
|
||||
<Helmet>
|
||||
<title>ANTD ADMIN</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
@@ -89,21 +100,27 @@ const App = ({ children, dispatch, app, loading, location }) => {
|
||||
{iconFontJS && <script src={iconFontJS} />}
|
||||
{iconFontCSS && <link rel="stylesheet" href={iconFontCSS} />}
|
||||
</Helmet>
|
||||
<div className={classnames(styles.layout, { [styles.fold]: isNavbar ? false : siderFold }, { [styles.withnavbar]: isNavbar })}>
|
||||
{!isNavbar ? <aside className={classnames(styles.sider, { [styles.light]: !darkTheme })}>
|
||||
{siderProps.menu.length === 0 ? null : <Sider {...siderProps} />}
|
||||
</aside> : ''}
|
||||
<div className={styles.main}>
|
||||
|
||||
<Layout className={classnames({ [styles.dark]: darkTheme, [styles.light]: !darkTheme })}>
|
||||
{!isNavbar && <Sider
|
||||
trigger={null}
|
||||
collapsible
|
||||
collapsed={siderFold}
|
||||
>
|
||||
{siderProps.menu.length === 0 ? null : <MyLayout.Sider {...siderProps} />}
|
||||
</Sider>}
|
||||
<Layout style={{ height: '100vh', overflow: 'scroll' }} id="mainContainer">
|
||||
<BackTop target={() => document.getElementById('mainContainer')} />
|
||||
<Header {...headerProps} />
|
||||
<Bread {...breadProps} />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
{hasPermission ? children : <Error />}
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
<Content>
|
||||
<Bread {...breadProps} />
|
||||
{hasPermission ? children : <Error />}
|
||||
</Content>
|
||||
<Footer >
|
||||
{config.footerText}
|
||||
</Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -116,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))
|
||||
@@ -1,72 +1,72 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
:global {
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
|
||||
.bar {
|
||||
background: @primary-color;
|
||||
position: fixed;
|
||||
z-index: 1024;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px @primary-color,0 0 5px @primary-color;
|
||||
opacity: 1.0;
|
||||
transform: rotate(3deg) translate(0px,-4px);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
border-top-color: @primary-color;
|
||||
border-left-color: @primary-color;
|
||||
border-radius: 50%;
|
||||
|
||||
:local {
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
#nprogress {
|
||||
.bar,
|
||||
.spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
:global {
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
|
||||
.bar {
|
||||
background: @primary-color;
|
||||
position: fixed;
|
||||
z-index: 1024;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px @primary-color,0 0 5px @primary-color;
|
||||
opacity: 1.0;
|
||||
transform: rotate(3deg) translate(0px,-4px);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
border-top-color: @primary-color;
|
||||
border-left-color: @primary-color;
|
||||
border-radius: 50%;
|
||||
|
||||
:local {
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
#nprogress {
|
||||
.bar,
|
||||
.spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { LocaleProvider } from 'antd'
|
||||
import enUS from 'antd/lib/locale-provider/en_US'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import App from './app'
|
||||
|
||||
export default withRouter((props) => {
|
||||
return (
|
||||
<LocaleProvider locale={enUS}>
|
||||
<App>
|
||||
{ props.children }
|
||||
</App>
|
||||
</LocaleProvider>
|
||||
)
|
||||
})
|
||||
@@ -1,12 +1,15 @@
|
||||
/* global window */
|
||||
/* global document */
|
||||
/* global location */
|
||||
/* eslint no-restricted-globals: ["error", "event"] */
|
||||
|
||||
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
|
||||
|
||||
@@ -97,10 +100,10 @@ export default {
|
||||
}
|
||||
} else if (config.openPages && config.openPages.indexOf(locationPathname) < 0) {
|
||||
yield put(routerRedux.push({
|
||||
pathname: 'login',
|
||||
query: {
|
||||
pathname: '/login',
|
||||
search: queryString.stringify({
|
||||
from: locationPathname,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
}
|
||||
},
|
||||
@@ -110,6 +113,16 @@ export default {
|
||||
}, { call, put }) {
|
||||
const data = yield call(logout, parse(payload))
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: {
|
||||
user: {},
|
||||
permissions: { visit: [] },
|
||||
menu: [{
|
||||
id: 1,
|
||||
icon: 'laptop',
|
||||
name: 'Dashboard',
|
||||
router: '/dashboard',
|
||||
}],
|
||||
}})
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw (data)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React from 'react'
|
||||
import { Icon } from 'antd'
|
||||
import styles from './index.less'
|
||||
import { Page } from 'components'
|
||||
import styles from './404.less'
|
||||
|
||||
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
|
||||
@@ -5,9 +5,11 @@ import { Table, Row, Col, Card, Select } from 'antd'
|
||||
class DataTablePage extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = { filterCase: {
|
||||
gender: '',
|
||||
} }
|
||||
this.state = {
|
||||
filterCase: {
|
||||
gender: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectChange = (gender) => {
|
||||
@@ -20,7 +22,11 @@ class DataTablePage extends React.Component {
|
||||
render () {
|
||||
const { filterCase } = this.state
|
||||
const staticDataTableProps = {
|
||||
dataSource: [{ key: '1', name: 'John Brown', age: 24, address: 'New York' }, { key: '2', name: 'Jim Green', age: 23, address: 'London' }],
|
||||
dataSource: [{
|
||||
key: '1', name: 'John Brown', age: 24, address: 'New York',
|
||||
}, {
|
||||
key: '2', name: 'Jim Green', age: 23, address: 'London',
|
||||
}],
|
||||
columns: [{ title: 'name', dataIndex: 'name' }, { title: 'Age', dataIndex: 'age' }, { title: 'Address', dataIndex: 'address' }],
|
||||
pagination: false,
|
||||
}
|
||||
@@ -39,7 +45,7 @@ class DataTablePage extends React.Component {
|
||||
{ title: 'Phone', dataIndex: 'phone' },
|
||||
{ title: 'Gender', dataIndex: 'gender' },
|
||||
],
|
||||
rowKey: 'registered',
|
||||
rowKey: 'email',
|
||||
}
|
||||
|
||||
const caseChangeDataTableProps = {
|
||||
@@ -57,7 +63,7 @@ class DataTablePage extends React.Component {
|
||||
{ title: 'Phone', dataIndex: 'phone' },
|
||||
{ title: 'Gender', dataIndex: 'gender' },
|
||||
],
|
||||
rowKey: 'registered',
|
||||
rowKey: 'email',
|
||||
}
|
||||
|
||||
return (<div className="content-inner">
|
||||
@@ -125,6 +131,7 @@ class DataTablePage extends React.Component {
|
||||
desciption: '远程获取数据的参数',
|
||||
type: 'Object',
|
||||
default: '后面有空加上',
|
||||
key: 'basetable'
|
||||
}]}
|
||||
/>
|
||||
</Col>
|
||||
@@ -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
|
||||
@@ -4,7 +4,6 @@ import { convertToRaw } from 'draft-js'
|
||||
import { Row, Col, Card } from 'antd'
|
||||
import draftToHtml from 'draftjs-to-html'
|
||||
import draftToMarkdown from 'draftjs-to-markdown'
|
||||
// https://github.com/jpuri/react-draft-wysiwyg/blob/master/docs/src/components/Demo/index.js
|
||||
|
||||
export default class EditorPage extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -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
|
||||
@@ -3,7 +3,9 @@ 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 }}>
|
||||
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>
|
||||
@@ -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
|
||||
@@ -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) { // eslint-disable-line
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory) // eslint-disable-line
|
||||
} 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) { // eslint-disable-line
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory) // eslint-disable-line
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports, require('echarts'))
|
||||
} else {
|
||||
// Browser globals
|
||||
factory({}, root.echarts)
|
||||
}
|
||||
}(this, (exports, echarts) => {
|
||||
let log = function (msg) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console && console.error && console.error(msg)
|
||||
}
|
||||
}
|
||||
if (!echarts) {
|
||||
log('ECharts is not Loaded')
|
||||
return
|
||||
}
|
||||
|
||||
let colorPalette = [
|
||||
'#c12e34', '#e6b600', '#0098d9', '#2b821d',
|
||||
'#005eaa', '#339ca8', '#cda819', '#32a487',
|
||||
]
|
||||
|
||||
let theme = {
|
||||
|
||||
color: colorPalette,
|
||||
|
||||
title: {
|
||||
textStyle: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
},
|
||||
|
||||
visualMap: {
|
||||
color: ['#1790cf', '#a2d4e6'],
|
||||
},
|
||||
|
||||
toolbox: {
|
||||
iconStyle: {
|
||||
normal: {
|
||||
borderColor: '#06467c',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(0,0,0,0.6)',
|
||||
},
|
||||
|
||||
dataZoom: {
|
||||
dataBackgroundColor: '#dedede',
|
||||
fillerColor: 'rgba(154,217,247,0.2)',
|
||||
handleColor: '#005eaa',
|
||||
},
|
||||
|
||||
timeline: {
|
||||
lineStyle: {
|
||||
color: '#005eaa',
|
||||
},
|
||||
controlStyle: {
|
||||
normal: {
|
||||
color: '#005eaa',
|
||||
borderColor: '#005eaa',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
candlestick: {
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#c12e34',
|
||||
color0: '#2b821d',
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#c12e34',
|
||||
color0: '#2b821d',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
graph: {
|
||||
color: colorPalette,
|
||||
},
|
||||
|
||||
map: {
|
||||
label: {
|
||||
normal: {
|
||||
textStyle: {
|
||||
color: '#c12e34',
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
textStyle: {
|
||||
color: '#c12e34',
|
||||
},
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
borderColor: '#eee',
|
||||
areaColor: '#ddd',
|
||||
},
|
||||
emphasis: {
|
||||
areaColor: '#e6b600',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
gauge: {
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: [[0.2, '#2b821d'], [0.8, '#005eaa'], [1, '#c12e34']],
|
||||
width: 5,
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
splitNumber: 10,
|
||||
length: 8,
|
||||
lineStyle: {
|
||||
color: 'auto',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: 'auto',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
length: 12,
|
||||
lineStyle: {
|
||||
color: 'auto',
|
||||
},
|
||||
},
|
||||
pointer: {
|
||||
length: '90%',
|
||||
width: 3,
|
||||
color: 'auto',
|
||||
},
|
||||
title: {
|
||||
textStyle: {
|
||||
color: '#333',
|
||||
},
|
||||
},
|
||||
detail: {
|
||||
textStyle: {
|
||||
color: 'auto',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
echarts.registerTheme('shine', theme)
|
||||
}))
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import * as d3 from 'd3-shape'
|
||||
import { Row, Col, Card, Button } from 'antd'
|
||||
import * as d3 from 'd3-shape'
|
||||
import {
|
||||
AreaChart,
|
||||
Area,
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
} from 'recharts'
|
||||
import Container from '../Container'
|
||||
import Container from './Container'
|
||||
|
||||
|
||||
const data = [
|
||||
{
|
||||
@@ -253,10 +254,9 @@ const CardinalAreaChart = () => (
|
||||
</Container>
|
||||
)
|
||||
|
||||
const EditorPage = () => (
|
||||
const AreaChartPage = () => (
|
||||
<div className="content-inner">
|
||||
<Button type="primary"
|
||||
size="large"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
@@ -290,4 +290,4 @@ const EditorPage = () => (
|
||||
</div>
|
||||
)
|
||||
|
||||
export default EditorPage
|
||||
export default AreaChartPage
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
Tooltip,
|
||||
Legend,
|
||||
} from 'recharts'
|
||||
import Container from '../Container'
|
||||
import Container from './Container'
|
||||
|
||||
|
||||
const data = [
|
||||
{
|
||||
@@ -161,13 +162,15 @@ const MixBarChart = () => (
|
||||
// CustomShapeBarChart
|
||||
const getPath = (x, y, width, height) => {
|
||||
return `M${x},${y + height}
|
||||
C${x + (width / 3)},${y + height} ${x + (width / 2)},${y + (height / 3)} ${x + (width / 2)}, ${y}
|
||||
C${x + (width / 2)},${y + (height / 3)} ${x + (2 * (width / 3))},${y + height} ${x + width}, ${y + height}
|
||||
C${x + width / 3},${y + height} ${x + width / 2},${y + height / 3} ${x + width / 2}, ${y}
|
||||
C${x + width / 2},${y + height / 3} ${x + 2 * width / 3},${y + height} ${x + width}, ${y + height}
|
||||
Z`
|
||||
}
|
||||
|
||||
const TriangleBar = (props) => {
|
||||
const { fill, x, y, width, height } = props
|
||||
const {
|
||||
fill, x, y, width, height,
|
||||
} = props
|
||||
return <path d={getPath(x, y, width, height)} stroke="none" fill={fill} />
|
||||
}
|
||||
|
||||
@@ -197,10 +200,9 @@ const CustomShapeBarChart = () => (
|
||||
</Container>
|
||||
)
|
||||
|
||||
const EditorPage = () => (
|
||||
const BarChartPage = () => (
|
||||
<div className="content-inner">
|
||||
<Button type="primary"
|
||||
size="large"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
@@ -234,4 +236,4 @@ const EditorPage = () => (
|
||||
</div>
|
||||
)
|
||||
|
||||
export default EditorPage
|
||||
export default BarChartPage
|
||||
@@ -0,0 +1,24 @@
|
||||
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
|
||||