diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..7e3649a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab
diff --git a/.env b/.env
new file mode 100644
index 0000000..904cfb0
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+BROWSER=none
+HOST=0.0.0.0
+PORT=7001
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..96a82df
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,7 @@
+src/**/*-test.js
+src/public
+src/routes/chart/ECharts/theme
+src/routes/chart/highCharts/mapdata
+src/locales/_build/
+src/locales/**/*.js
+docs/**/*.js
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..e71ebc8
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,8 @@
+{
+ "extends": "react-app",
+ "rules": {
+ "jsx-a11y/href-no-hash": "off",
+ "no-console": "warn",
+ "valid-jsdoc": "warn"
+ }
+}
diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 0000000..1f0ad65
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,8 @@
+> 请酌情提供细节,并保持issue精简便于查阅
+> 1. 功能需求 => 详细说明
+> 2. Bug反馈
+> 2.1 简单描述下报错
+> 2.2 你期望什么结果
+> 2.3 如何操作导致的
+> 2.4 可提供运行环境信息
+> 3. 代码求助 => 可以提,未必及时答复
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..75b78a8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+coverage
+dist
+node_modules
+npm-debug.log
+yarn-error.log
+yarn.lock
+package-lock.json
+
+# ide
+.idea
+
+# Mac General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# umi
+.umi
+.umi-production
+
+# jslingui
+src/locales/_build
+src/locales/**/*.js
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..1e879f7
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+*.svg
+*.ejs
+.DS_Store
+.umi
+.umi-production
+src/locales/**/*.json
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..36301bc
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "es5"
+}
diff --git a/.stylelintrc.json b/.stylelintrc.json
new file mode 100644
index 0000000..b533bdd
--- /dev/null
+++ b/.stylelintrc.json
@@ -0,0 +1,9 @@
+{
+ "extends": ["stylelint-config-standard", "stylelint-config-prettier"],
+ "rules": {
+ "declaration-empty-line-before": null,
+ "no-descending-specificity": null,
+ "selector-pseudo-class-no-unknown": null,
+ "selector-pseudo-element-colon-notation": null
+ }
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..66de02f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+language: node_js
+node_js:
+ - node
+script:
+ - npm run build
+before_install:
+ - yarn global add now
+after_script:
+ - |
+ if [[ $TRAVIS_BRANCH == 'master' ]]; then
+ echo $PROD_SITE_NOW_CONFIG >> dist/vercel.json && echo $PROD_DOC_NOW_CONFIG >> docs/vercel.json;
+ else
+ echo $DEV_SITE_NOW_CONFIG >> dist/vercel.json && echo $DEV_DOC_NOW_CONFIG >> docs/vercel.json;
+ fi
+ - cd ./dist
+ - now -A vercel.json -t $NOW_TOKEN --prod -c
+ - cd ../docs
+ - now -A vercel.json -t $NOW_TOKEN --prod -c
diff --git a/.umirc.js b/.umirc.js
new file mode 100644
index 0000000..1a0cbc5
--- /dev/null
+++ b/.umirc.js
@@ -0,0 +1,135 @@
+// https://umijs.org/config/
+import { resolve } from 'path'
+const fs = require('fs')
+const path = require('path')
+const lessToJs = require('less-vars-to-js')
+const isDevelopment = process.env.NODE_ENV === 'development'
+
+// how to speed compile: https://umijs.org/guide/boost-compile-speed
+export default {
+ // IMPORTANT! change next line to yours or delete. And hide in dev
+ publicPath: isDevelopment ? '/' : 'http://140.249.182.90:7000/',
+ alias: {
+ api: resolve(__dirname, './src/services/'),
+ components: resolve(__dirname, './src/components'),
+ config: resolve(__dirname, './src/utils/config'),
+ themes: resolve(__dirname, './src/themes'),
+ utils: resolve(__dirname, './src/utils'),
+ },
+ antd: {},
+ // a lower cost way to genereate sourcemap, default is cheap-module-source-map, could save 60% time in dev hotload
+ devtool: 'eval',
+ dva: { immer: true },
+ dynamicImport: {
+ loading: 'components/Loader/Loader',
+ },
+ extraBabelPlugins: [
+ [
+ 'import',
+ {
+ libraryName: 'lodash',
+ libraryDirectory: '',
+ camel2DashComponentName: false,
+ },
+ 'lodash',
+ ],
+ [
+ 'import',
+ {
+ libraryName: '@ant-design/icons',
+ libraryDirectory: 'es/icons',
+ camel2DashComponentName: false,
+ },
+ 'ant-design-icons',
+ ],
+ [
+ 'macros'
+ ]
+ ],
+ hash: true,
+ ignoreMomentLocale: true,
+ // umi3 comple node_modules by default, could be disable
+ nodeModulesTransform: {
+ type: 'none',
+ exclude: [],
+ },
+ // Webpack Configuration
+ proxy: {
+ '/api/v1/weather': {
+ target: 'https://api.seniverse.com/',
+ changeOrigin: true,
+ pathRewrite: { '^/api/v1/weather': '/v3/weather' },
+ },
+ },
+ // Theme for antd
+ // https://ant.design/docs/react/customize-theme
+ theme: lessToJs(
+ fs.readFileSync(path.join(__dirname, './src/themes/default.less'), 'utf8')
+ ),
+ webpack5: {},
+ mfsu: {},
+ chainWebpack: function (config, { webpack }) {
+ !isDevelopment && config.merge({
+ optimization: {
+ minimize: false,
+ splitChunks: {
+ chunks: 'all',
+ minSize: 30000,
+ minChunks: 3,
+ automaticNameDelimiter: '.',
+ cacheGroups: {
+ react: {
+ name: 'react',
+ priority: 20,
+ test: /[\\/]node_modules[\\/](react|react-dom|react-dom-router)[\\/]/,
+ },
+ antd: {
+ name: 'antd',
+ priority: 20,
+ test: /[\\/]node_modules[\\/](antd|@ant-design\/icons)[\\/]/,
+ },
+ 'echarts-gl': {
+ name: 'echarts-gl',
+ priority: 30,
+ test: /[\\/]node_modules[\\/]echarts-gl[\\/]/,
+ },
+ zrender: {
+ name: 'zrender',
+ priority: 30,
+ test: /[\\/]node_modules[\\/]zrender[\\/]/,
+ },
+ echarts: {
+ name: 'echarts',
+ priority: 20,
+ test: /[\\/]node_modules[\\/](echarts|echarts-for-react|echarts-liquidfill)[\\/]/,
+ },
+ highcharts: {
+ name: 'highcharts',
+ priority: 20,
+ test: /[\\/]node_modules[\\/]highcharts[\\/]/,
+ },
+ recharts: {
+ name: 'recharts',
+ priority: 20,
+ test: /[\\/]node_modules[\\/]recharts[\\/]/,
+ },
+ draftjs: {
+ name: 'draftjs',
+ priority: 30,
+ test: /[\\/]node_modules[\\/](draft-js|react-draft-wysiwyg|draftjs-to-html|draftjs-to-markdown)[\\/]/,
+ },
+ async: {
+ chunks: 'async',
+ minChunks: 2,
+ name: 'async',
+ maxInitialRequests: 1,
+ minSize: 0,
+ priority: 5,
+ reuseExistingChunk: true,
+ },
+ },
+ },
+ },
+ })
+ },
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..58dfaa4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "json.schemas": [
+
+ ],
+ "js/ts.implicitProjectConfig.experimentalDecorators": true
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fb8f0c2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+MIT LICENSE
+
+Copyright (c) 2016 zuiidea (zuiiidea@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README-zh_CN.md b/README-zh_CN.md
new file mode 100644
index 0000000..5c2468e
--- /dev/null
+++ b/README-zh_CN.md
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+AntD Admin
+
+
+
+一套优秀的中后台前端解决方案
+
+[](https://github.com/ant-design/ant-design)
+[](https://github.com/umijs/umi)
+[](https://github.com/zuiidea/antd-admin/issues)
+[](http://opensource.org/licenses/MIT)
+
+[](https://github.com/zuiidea/antd-admin/pulls)
+[](https://gitter.im/antd-admin/antd-admin)
+
+
+
+- 在线演示 - [https://antd-admin.zuiidea.com](https://antd-admin.zuiidea.com)
+- 使用文档 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/](https://doc.antd-admin.zuiidea.com/#/zh-cn/)
+- 常见问题 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/faq](https://doc.antd-admin.zuiidea.com/#/zh-cn/faq)
+- 更新日志 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/change-log](https://doc.antd-admin.zuiidea.com/#/zh-cn/change-log)
+
+[English](./README.md) | 简体中文
+
+## 特性
+
+- 国际化,源码中抽离翻译字段,按需加载语言包
+- 动态权限,不同权限对应不同菜单
+- 优雅美观,Ant Design 设计体系
+- Mock 数据,本地数据调试
+
+
+## 使用
+
+1. 下载项目代码。
+
+```bash
+git clone https://github.com/zuiidea/antd-admin.git my-project
+cd my-project
+```
+
+2. 进入目录安装依赖,国内用户推荐使用 [cnpm](https://cnpmjs.org) 进行加速。
+
+```bash
+yarn install
+```
+
+或者
+
+```bash
+npm install
+```
+
+3. 启动本地服务器。
+
+```bash
+npm run start
+```
+
+4. 启动完成后打开浏览器访问 [http://localhost:7000](http://localhost:7000),如果需要更改启动端口,可在 `.env` 文件中配置。
+
+5. 登录账号有2个,一个账号admin 密码admin;另一个账号guest 密码guest
+
+> 更多信息请参考 [使用文档](https://doc.antd-admin.zuiidea.com/#/zh-cn/)。
+
+
+## 支持环境
+
+现代浏览器。
+
+| [ ](http://godban.github.io/browsers-support-badges/)IE / Edge | [ ](http://godban.github.io/browsers-support-badges/)Firefox | [ ](http://godban.github.io/browsers-support-badges/)Chrome | [ ](http://godban.github.io/browsers-support-badges/)Safari | [ ](http://godban.github.io/browsers-support-badges/)Opera |
+| --------- | --------- | --------- | --------- | --------- |
+|IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions
+
+## 参与贡献
+
+我们非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :smiley:
+- 在你的公司或个人项目中使用 AntD Admin。
+- 通过 [Issue](http://github.com/zuiidea/antd-admin/issues) 报告 bug 或进行咨询。
+- 提交 [Pull Request](http://github.com/zuiidea/antd-admin/pulls) 改进代码。
+
+> 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。
diff --git a/assets/standard.md b/assets/standard.md
new file mode 100644
index 0000000..f8cd8ce
--- /dev/null
+++ b/assets/standard.md
@@ -0,0 +1,35 @@
+### 开发环境
+
+- OS:Windows
+- 编辑器:Atom
+- cmd:Cmder
+
+### Atom 插件
+
+- [atom-beautify](https://atom.io/packages/atom-beautify)
+
+ #### Less
+
+ - [x] Beautify On Save
+
+ #### Javascript
+
+ - [ ] Disable Beautifying Language
+
+ #### Markdown
+
+ - [x] Beautify On Save
+ - [x] Default Beautifier:Remark
+
+ #### HTML
+
+ - [x] Beautify On Save
+
+- [linter](https://atom.io/packages/linter)
+ - [ ] Lint on Change
+- [linter-eslint](https://atom.io/packages/linter-eslint)
+ - [x] Fix errors on save
+
+### Cmder 主题
+
+- [Panda-Theme-Cmder](https://github.com/HamidFaraji/Panda-Theme-Cmder)
diff --git a/docs/.nojekyll b/docs/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/docs/API-configuration.md b/docs/API-configuration.md
new file mode 100644
index 0000000..73ee148
--- /dev/null
+++ b/docs/API-configuration.md
@@ -0,0 +1,86 @@
+# API configuration
+
+## Why
+
+In the use of `redux` or `dva` projects, we often write functions like the following `service` layer to make the code structure clearer, but it is easy to see that we will write a lot of similar code in `antd -admin@5.0`, using the more concise configuration method to achieve the same function.
+
+```javascript
+export async function login(data) {
+ return request({
+ url: '/api/v1/user/login',
+ method: 'post',
+ data,
+ })
+}
+```
+
+## Configuration and use
+
+In the `src/services/api.js` file, you will see the following configuration object, the object's key is used to call the function name, the object's value is the requested `url`, the default request method is `GET`, The format of the value of the other request mode object is `'method url'`.
+
+```javascript
+export default {
+ ...
+ queryUser: '/user/:id',
+ queryUserList: '/users',
+ updateUser: 'Patch /user/:id',
+ createUser: 'POST /user/:id',
+ removeUser: 'DELETE /user/:id',
+ removeUserList: 'POST /users/delete',
+ ...
+}
+```
+
+Used in other files
+
+```javascript
+import { queryUser } from 'api'
+
+// in the general file
+...
+queryUser(option).then(data => console.log(data))
+...
+
+/ / Model file
+...
+yield call(queryUser, option)
+...
+```
+
+## Method to realize
+
+Refer to the `src/services/index.js` file to traverse the api configuration. Each property returns the corresponding encapsulated request function.
+
+```javascript
+import request from 'utils/request'
+import { apiPrefix } from 'utils/config'
+
+import api from './api'
+
+const gen = params => {
+ let url = apiPrefix + params
+ let method = 'GET'
+
+ const paramsArray = params.split(' ')
+ if (paramsArray.length === 2) {
+ method = paramsArray[0]
+ url = apiPrefix + paramsArray[1]
+ }
+
+ return function(data) {
+ return request({
+ url,
+ data,
+ method,
+ })
+ }
+}
+
+const APIFunction = {}
+for (const key in api) {
+ APIFunction[key] = gen(api[key])
+}
+
+module.exports = APIFunction
+
+```
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..41f72da
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+AntD Admin
+
+
+
+An excellent front-end solution for enterprise applications.
+
+[](https://github.com/ant-design/ant-design)
+[](https://github.com/umijs/umi)
+[](https://github.com/zuiidea/antd-admin/issues)
+[](http://opensource.org/licenses/MIT)
+
+[](https://github.com/zuiidea/antd-admin/pulls)
+[](https://gitter.im/antd-admin/antd-admin)
+
+
+
+- Preview - [https://antd-admin.zuiidea.com](https://antd-admin.zuiidea.com)
+- Documentation - [https://doc.antd-admin.zuiidea.com](https://doc.antd-admin.zuiidea.com)
+- FAQ - [https://doc.antd-admin.zuiidea.com/#/faq](https://doc.antd-admin.zuiidea.com/#/faq)
+- ChangeLog - [https://doc.antd-admin.zuiidea.com/#/change-log](https://doc.antd-admin.zuiidea.com/#/change-log)
+
+## Features
+
+- Internationalization, extracting translation fields from source code, loading language packs on demand
+- Dynamic permissions, different permissions for different menus
+- Elegant and beautiful, Ant Design system
+- Mock data, local data debugging
+
+
+## Usage
+
+1. Clone project code.
+
+```bash
+git clone https://github.com/zuiidea/antd-admin.git my-project
+cd my-project
+```
+
+2. Installation dependence.
+
+```bash
+yarn install
+```
+
+Or
+
+```bash
+npm install
+```
+
+3. Start local server.
+
+```bash
+npm run start
+```
+
+4. After the startup is complete, open a browser and visit [http://localhost:7000](http://localhost:7000), If you need to change the startup port, you can configure it in the `.env` file.
+
+
+> More instructions at [documentation](https://doc.antd-admin.zuiidea.com)。
+
+
+## Browsers support
+
+Modern browsers.
+
+| [ ](http://godban.github.io/browsers-support-badges/)IE / Edge | [ ](http://godban.github.io/browsers-support-badges/)Firefox | [ ](http://godban.github.io/browsers-support-badges/)Chrome | [ ](http://godban.github.io/browsers-support-badges/)Safari | [ ](http://godban.github.io/browsers-support-badges/)Opera |
+| --------- | --------- | --------- | --------- | --------- |
+|IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions
+
+## Contributing
+
+We very much welcome your contribution, you can build together with us in the following ways :smiley:
+
+- Use Ant Design Pro in your daily work.
+- Submit [GitHub issues](http://github.com/zuiidea/antd-admin/issues)s to report bugs or ask questions.
+- Propose [Pull Request](http://github.com/zuiidea/antd-admin/pulls) to improve our code.
diff --git a/docs/_media/favicon.ico b/docs/_media/favicon.ico
new file mode 100644
index 0000000..7ca2170
Binary files /dev/null and b/docs/_media/favicon.ico differ
diff --git a/docs/_media/logo.svg b/docs/_media/logo.svg
new file mode 100644
index 0000000..ce7afe5
--- /dev/null
+++ b/docs/_media/logo.svg
@@ -0,0 +1,24 @@
+
+
+
+ Created with Sketch.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_media/term_build.svg b/docs/_media/term_build.svg
new file mode 100644
index 0000000..5b1a6ea
--- /dev/null
+++ b/docs/_media/term_build.svg
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➜ antd-admin git:( master ) ✗ ➜ antd-admin git:( master ) ✗ n ➜ antd-admin git:( master ) ✗ np ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm r ➜ antd-admin git:( master ) ✗ npm ru ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run b ➜ antd-admin git:( master ) ✗ npm run bu ➜ antd-admin git:( master ) ✗ npm run bui ➜ antd-admin git:( master ) ✗ npm run buil ➜ antd-admin git:( master ) ✗ npm run build Compiling ● webpack █████████████████████████ compiling (0%) Compiling ● webpack ███ ██████████████████████ building modules (10%) 2/2 modules 0 active Compiling ● webpack ███ ██████████████████████ building modules (11%) 11/13 modules 2 activ e node_modules/umi/lib/createHistory.js ● webpack ███ ██████████████████████ building modules (12%) 18/21 modules 3 activ node_modules/webpack/buildin/global.js ● webpack ██████ ███████████████████ building modules (23%) 110/112 modules 2 act ive node_modules/react-dom/cjs/react-dom.production.min.js ● webpack ██████ ███████████████████ building modules (23%) 115/118 modules 3 act node_modules/util/support/isBufferBrowser.js ● webpack ██████ ███████████████████ building modules (23%) 116/141 modules 25 ac tive node_modules/core-js/modules/_global.js ● webpack ███████ ██████████████████ building modules (25%) 130/142 modules 12 ac node_modules/path-browserify/index.js ● webpack ███████ ██████████████████ building modules (27%) 147/191 modules 44 ac node_modules/core-js/modules/_bind.js ● webpack █████████ ████████████████ building modules (35%) 215/256 modules 41 ac node_modules/core-js/modules/_inherit-if-required.js ● webpack ██████████ ███████████████ building modules (39%) 249/266 modules 17 ac node_modules/core-js/modules/web.dom.iterable.js ● webpack ███████████ ██████████████ building modules (42%) 267/307 modules 40 ac ...4m › postcss-loader › less-loader › src/pages/404.less ● webpack ████████████ █████████████ building modules (47%) 313/320 modules 7 act node_modules/prop-types/index.js ● webpack █████████████ ████████████ building modules (49%) 328/351 modules 23 ac node_modules/react-router-dom/es/index.js ● webpack █████████████ ████████████ building modules (51%) 343/354 modules 11 ac babel-loader › src/pages/chart/highCharts/HighChartsComponent.js ● webpack █████████████ ████████████ building modules (52%) 354/372 modules 18 ac src/locales/en/messages.json ● webpack ██████████████ ███████████ building modules (54%) 372/394 modules 22 ac babel-loader › src/utils/theme.js ● webpack ███████████████ ██████████ building modules (57%) 395/422 modules 27 ac node_modules/@babel/runtime/helpers/arrayWithoutHoles.js ● webpack ███████████████ ██████████ building modules (60%) 424/455 modules 31 ac node_modules/antd/es/card/Meta.js ● webpack ████████████████ █████████ building modules (61%) 427/463 modules 36 ac node_modules/antd/es/_util/throttleByAnimationFrame.js ● webpack ████████████████ █████████ building modules (64%) 458/477 modules 19 ac node_modules/antd/es/radio/group.js ● webpack █████████████████ ████████ building modules (67%) 476/497 modules 21 ac babel-loader › src/pages/chart/highCharts/mapdata/europe.js ● webpack █████████████████ ████████ building modules (66%) 488/514 modules 26 ac node_modules/react-router-dom/node_modules/warning/warning.js ● webpack █████████████████ ████████ building modules (67%) 493/518 modules 25 ac ...der › less-loader › src/pages/chart/Recharts/Container.less ● webpack █████████████████ ████████ building modules (67%) 505/525 modules 20 ac node_modules/omit.js/es/index.js ● webpack █████████████████ ████████ building modules (67%) 532/559 modules 27 ac node_modules/highcharts-exporting/exporting.js ● webpack █████████████████ ████████ building modules (67%) 574/598 modules 24 ac node_modules/antd/es/date-picker/locale/en_US.js ● webpack █████████████████ ████████ building modules (68%) 589/608 modules 19 ac node_modules/draft-js/lib/ContentState.js ● webpack █████████████████ ████████ building modules (67%) 616/641 modules 25 ac node_modules/react-router/es/matchPath.js ● webpack █████████████████ ████████ building modules (67%) 656/679 modules 23 ac node_modules/draft-js/lib/DraftEntityInstance.js ● webpack █████████████████ ████████ building modules (67%) 665/690 modules 25 ac node_modules/axios/lib/utils.js ● webpack █████████████████ ████████ building modules (67%) 685/712 modules 27 ac node_modules/add-dom-event-listener/lib/index.js ● webpack █████████████████ ████████ building modules (68%) 735/756 modules 21 ac node_modules/lodash/_objectToString.js ● webpack █████████████████ ████████ building modules (68%) 737/758 modules 21 ac node_modules/lodash/_getRawTag.js ● webpack █████████████████ ████████ building modules (67%) 756/787 modules 31 ac node_modules/add-dom-event-listener/lib/EventObject.js ● webpack █████████████████ ████████ building modules (67%) 771/800 modules 29 ac node_modules/core-js/library/modules/_add-to-unscopables.js ● webpack █████████████████ ████████ building modules (67%) 781/808 modules 27 ac node_modules/core-js/library/modules/_object-dp.js ● webpack █████████████████ ████████ building modules (68%) 817/836 modules 19 ac node_modules/size-sensor/lib/index.js ● webpack █████████████████ ████████ building modules (68%) 845/870 modules 25 ac node_modules/is-buffer/index.js ● webpack █████████████████ ████████ building modules (68%) 892/913 modules 21 ac node_modules/echarts/lib/util/model.js ● webpack █████████████████ ████████ building modules (68%) 933/963 modules 30 ac node_modules/echarts-liquidfill/node_modules/echarts/lib/model/Series.js ● webpack █████████████████ ████████ building modules (68%) 978/996 modules 18 ac node_modules/lodash/_baseFor.js ● webpack █████████████████ ████████ building modules (68%) 1000/1029 modules 29 active node_modules/zrender/lib/contain/text.js ● webpack █████████████████ ████████ building modules (68%) 1029/1056 modules 27 ...e_modules/echarts-liquidfill/node_modules/echarts/lib/model/mixin/dataFormat. js ● webpack █████████████████ ████████ building modules (68%) 1059/1077 modules 18 node_modules/lodash/_createBaseFor.js ● webpack █████████████████ ████████ building modules (68%) 1101/1133 modules 32 node_modules/zrender/lib/graphic/helper/image.js ● webpack █████████████████ ████████ building modules (68%) 1155/1175 modules 20 node_modules/lodash/_baseGetAllKeys.js ● webpack ██████████████████ ███████ building modules (69%) 1212/1231 modules 19 node_modules/size-sensor/lib/sensors/resizeObserver.js ● webpack █████████████████ ████████ building modules (68%) 1266/1296 modules 30 node_modules/d3-shape/src/curve/cardinalClosed.js ● webpack █████████████████ ████████ building modules (68%) 1329/1357 modules 28 ...ules/echarts-liquidfill/node_modules/echarts/lib/data/helper/dataStackHelper. ● webpack ██████████████████ ███████ building modules (69%) 1392/1409 modules 17 node_modules/d3-collection/src/set.js ● webpack ██████████████████ ███████ building modules (69%) 1449/1467 modules 18 node_modules/component-classes/index.js ● webpack █████████████████ ████████ building modules (68%) 1481/1507 modules 26 node_modules/d3-time/src/second.js ● webpack ██████████████████ ███████ building modules (69%) 1534/1551 modules 17 node_modules/echarts-liquidfill/src/liquidFillView.js ● webpack ██████████████████ ███████ building modules (69%) 1594/1607 modules 13 node_modules/rc-animate/es/CSSMotion.js ● webpack █████████████████ ████████ building modules (68%) 1651/1691 modules 40 node_modules/echarts/lib/component/gridSimple.js ● webpack ██████████████████ ███████ building modules (69%) 1700/1713 modules 13 node_modules/echarts/lib/coord/calendar/prepareCustom.js ● webpack █████████████████ ████████ building modules (68%) 1739/1771 modules 32 node_modules/echarts/lib/component/tooltip/TooltipContent.js ● webpack ██████████████████ ███████ building modules (69%) 1780/1807 modules 27 node_modules/echarts/lib/chart/scatter/ScatterView.js ● webpack ██████████████████ ███████ building modules (69%) 1781/1808 modules 27 node_modules/echarts/lib/chart/scatter/ScatterSeries.js ● webpack █████████████████ ████████ building modules (68%) 1819/1852 modules 33 node_modules/echarts/lib/chart/graph/categoryFilter.js ● webpack ██████████████████ ███████ building modules (69%) 1867/1880 modules 13 node_modules/echarts/lib/chart/sankey/SankeySeries.js ● webpack ██████████████████ ███████ building modules (69%) 1916/1944 modules 28 node_modules/echarts/lib/component/dataZoom/DataZoomView.js ● webpack ██████████████████ ███████ building modules (69%) 1966/1993 modules 27 node_modules/echarts/lib/chart/sunburst/SunburstPiece.js ● webpack ██████████████████ ███████ building modules (69%) 2002/2030 modules 28 node_modules/draft-js/lib/CompositeDraftDecorator.js ● webpack ██████████████████ ███████ building modules (69%) 2010/2034 modules 24 node_modules/echarts/lib/component/marker/MarkerModel.js ● webpack ██████████████████ ███████ building modules (69%) 2031/2047 modules 16 babel-loader › src/pages/dashboard/components/browser.js ● webpack ██████████████████ ███████ building modules (69%) 2081/2100 modules 19 node_modules/array-tree-filter/lib/index.js ● webpack ██████████████████ ███████ building modules (69%) 2105/2122 modules 17 node_modules/echarts/lib/component/dataZoom/SelectZoomModel.js ● webpack ██████████████████ ███████ building modules (69%) 2108/2123 modules 15 ● webpack ██████████████████ ███████ building modules (69%) 2117/2127 modules 10 node_modules/react-router-redux/es/middleware.js ● webpack ██████████████████ ███████ building modules (69%) 2122/2130 modules 8 a ctive node_modules/react-router-redux/es/actions.js ● webpack ██████████████████ ███████ building modules (69%) 2143/2167 modules 24 node_modules/react-redux/es/connect/connect.js ● webpack ██████████████████ ███████ building modules (69%) 2185/2203 modules 18 node_modules/rc-dialog/es/DialogWrap.js ● webpack ██████████████████ ███████ building modules (69%) 2237/2265 modules 28 node_modules/antd/es/tag/index.js ● webpack ██████████████████ ███████ building modules (69%) 2283/2301 modules 18 babel-loader › src/pages/user/components/Filter.js ● webpack ██████████████████ ███████ building modules (69%) 2327/2338 modules 11 node_modules/rc-util/es/getScrollBarSize.js ● webpack ██████████████████ ███████ building modules (69%) 2339/2357 modules 18 node_modules/async-validator/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2347/2363 modules 16 node_modules/lodash/_createCurry.js ● webpack ██████████████████ ███████ building modules (69%) 2384/2400 modules 16 node_modules/rmc-feedback/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2402/2422 modules 20 node_modules/dom-align/es/getAlignOffset.js ● webpack ██████████████████ ███████ building modules (69%) 2426/2438 modules 12 node_modules/dva-core/lib/prefixType.js ● webpack ██████████████████ ███████ building modules (69%) 2430/2438 modules 8 a ● webpack ██████████████████ ███████ building modules (69%) 2451/2471 modules 20 node_modules/antd/es/badge/index.js ● webpack ██████████████████ ███████ building modules (69%) 2485/2494 modules 9 a node_modules/fbjs/lib/emptyObject.js ● webpack ██████████████████ ███████ building modules (69%) 2490/2520 modules 30 node_modules/antd/es/date-picker/WeekPicker.js ● webpack ██████████████████ ███████ building modules (69%) 2512/2524 modules 12 node_modules/react-side-effect/lib/index.js ● webpack ██████████████████ ███████ building modules (69%) 2519/2529 modules 10 node_modules/redux-saga/lib/internal/runSaga.js ● webpack ██████████████████ ███████ building modules (69%) 2524/2532 modules 8 a node_modules/antd/es/layout/Sider.js ● webpack ██████████████████ ███████ building modules (69%) 2540/2549 modules 9 a node_modules/antd/es/_util/getDataOrAriaProps.js ● webpack ██████████████████ ███████ building modules (69%) 2554/2561 modules 7 a node_modules/redux-saga/lib/internal/sagaHelpers/index.js ● webpack ██████████████████ ███████ building modules (69%) 2577/2581 modules 4 a node_modules/rc-switch/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2581/2589 modules 8 a node_modules/rc-drawer/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2604/2610 modules 6 a node_modules/rc-calendar/es/date/DateInput.js ● webpack ██████████████████ ███████ finish module graph (70%) ● webpack ███████████████████ ██████ optimizing (73%) ● webpack ████████████████████ █████ advanced chunk modules optimization (79%) ● webpack ██████████████████████ ███ after hashing (88%) ● webpack ███████████████████████ ██ additional chunk assets processing (90%) ● webpack ███████████████████████ ██ chunk asset optimization (92%) UglifyJSPlugi n ● webpack ███████████████████████ ██ after chunk asset optimization (92%) ➜ antd-admin git:( master ) ✗ npm run build > antd-admin@5.0.0-beta build /Users/zuiidea/web/antd-admin > umi build [12:40:22] webpack compiled in 15s 56ms DONE Compiled successfully in 15062ms 12:40:22 File sizes after gzip: 887 B dist/ p__dashboard__model.js.async.js 877 B dist/ precache-manifest.6d2a703c437c4f28b5f6e072817bbe6e.js 786 B dist/ p__UIElement__editor__index.async.js 764 B dist/ i18n-0.async.js 652 B dist/ p__login__index.chunk.css 614 B dist/ p__user__$id__models__detail.js.async.js 599 B dist/ p__post__model.js.async.js 589 B dist/ p__user__$id__index.async.js 569 B dist/ service-worker.js 530 B dist/ p__request__index.chunk.css 515 B dist/ p__login__model.js.async.js 419 B dist/ p__index.async.js 245 B dist/ p__chart__ECharts__index.chunk.css 230 B dist/ p__chart__Recharts__index.chunk.css 138 B dist/ p__user__$id__index.chunk.css 74 B dist/ p__chart__highCharts__index.chunk.css 66 B dist/ p__user__index.chunk.css 66 B dist/ p__post__index.chunk.css The bundle size is significantly larger than recommended. Consider reducing it with code splitting: https://goo.gl/9VhYWB You can also analyze the project dependencies: https://goo.gl/LeUzfb ➜ antd-admin git:( master ) ✗
+
\ No newline at end of file
diff --git a/docs/_media/term_i18n.svg b/docs/_media/term_i18n.svg
new file mode 100644
index 0000000..a287916
--- /dev/null
+++ b/docs/_media/term_i18n.svg
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➜ antd-admin git:( master ) ✗ ➜ antd-admin git:( master ) ✗ n ➜ antd-admin git:( master ) ✗ np ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm r ➜ antd-admin git:( master ) ✗ npm ru ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run a ➜ antd-admin git:( master ) ✗ npm run ad ➜ antd-admin git:( master ) ✗ npm run add ➜ antd-admin git:( master ) ✗ npm run add- ➜ antd-admin git:( master ) ✗ npm run add-l ➜ antd-admin git:( master ) ✗ npm run add-lo ➜ antd-admin git:( master ) ✗ npm run add-loc ➜ antd-admin git:( master ) ✗ npm run add-loca ➜ antd-admin git:( master ) ✗ npm run add-local ➜ antd-admin git:( master ) ✗ npm run add-locale ➜ antd-admin git:( master ) ✗ npm run add-locale ➜ antd-admin git:( master ) ✗ npm run add-locale j ➜ antd-admin git:( master ) ✗ npm run add-locale ja ➜ antd-admin git:( master ) ✗ npm run e ➜ antd-admin git:( master ) ✗ npm run ex ➜ antd-admin git:( master ) ✗ npm run ext ➜ antd-admin git:( master ) ✗ npm run extr ➜ antd-admin git:( master ) ✗ npm run extra ➜ antd-admin git:( master ) ✗ npm run extrac ➜ antd-admin git:( master ) ✗ npm run extract ➜ antd-admin git:( master ) ✗ npm run add-locale ja > antd-admin@5.0.0-beta add-locale /Users/zuiidea/web/antd-admin > lingui add-locale "ja" Added locale ja . (use " lingui extract " to extract messages) ➜ antd-admin git:( master ) ✗ npm run extract > antd-admin@5.0.0-beta extract /Users/zuiidea/web/antd-admin > lingui extract ➜ antd-admin git:( master ) ✗ npm run t ➜ antd-admin git:( master ) ✗ npm run tr ➜ antd-admin git:( master ) ✗ npm run tra ➜ antd-admin git:( master ) ✗ npm run tran ➜ antd-admin git:( master ) ✗ npm run trans ➜ antd-admin git:( master ) ✗ npm run trans: ➜ antd-admin git:( master ) ✗ npm run trans:o ➜ antd-admin git:( master ) ✗ npm run trans:on ➜ antd-admin git:( master ) ✗ npm run trans:onl Catalog statistics: ┌─────────────┬─────────────┬─────────┐ │ Language │ Total count │ Missing │ ├─────────────┼─────────────┼─────────┤ │ en (source) │ 52 │ - │ │ ja │ 52 │ 52 │ │ zh │ 52 │ 0 │ └─────────────┴─────────────┴─────────┘ (use " lingui add-locale <language> " to add more locales) (use " lingui extract " to update catalogs with new messages) (use " lingui compile " to compile catalogs for production) ➜ antd-admin git:( master ) ✗ npm run trans:only ➜ antd-admin git:( master ) ✗ npm run trans:only > antd-admin@5.0.0-beta trans:only /Users/zuiidea/web/antd-admin > node ./scripts/translate.js add to skip: Publish Date add to skip: Reset add to skip: Search add to skip: Search Name add to skip: Send add to skip: Sign in add to skip: Sign out add to skip: Switch Theme add to skip: Tags add to skip: The input is not valid E-mail! add to skip: The input is not valid phone! add to skip: Title add to skip: Total {total} Items add to skip: Unpublished add to skip: Update add to skip: Update User add to skip: Username add to skip: Views add to skip: Visibility add to skip: You have viewed all notifications. completed: en -> zh start: en -> ja link: en -> ja: /dashboard -> /ja/dashboard youdao: en -> ja: Add Param -> Param の追加 youdao: en -> ja: Address -> アドレス youdao: en -> ja: Age -> 年齢 youdao: en -> ja: Are you sure delete this record? -> このレコードを削除してもよ ろしいですか? youdao: en -> ja: Author -> 著者 youdao: en -> ja: Avatar -> アバター youdao: en -> ja: Categories -> カテゴリ youdao: en -> ja: Clear notifications -> 通知のクリア youdao: en -> ja: Comments -> コメント youdao: en -> ja: Create -> 作成 youdao: en -> ja: Create User -> ユーザーの作成 same: en -> ja: CreateTime youdao: en -> ja: Dark -> 暗い youdao: en -> ja: Delete -> 削除 youdao: en -> ja: Email -> 電子メール youdao: en -> ja: Female -> 女性 youdao: en -> ja: Gender -> 性別 youdao: en -> ja: Hi, -> こんにちは youdao: en -> ja: Image -> イメージ youdao: en -> ja: Light -> 光 youdao: en -> ja: Male -> 男性 youdao: en -> ja: Name -> 名前 youdao: en -> ja: NickName -> ニックネーム youdao: en -> ja: Not Found -> 見つからない youdao: en -> ja: Operation -> 操作 same: en -> ja: Params youdao: en -> ja: Password -> パスワード youdao: en -> ja: Phone -> 電話 youdao: en -> ja: Pick an address -> 住所の選択 youdao: en -> ja: Please pick an address -> 住所を選択してください same: en -> ja: Publised youdao: en -> ja: Publish Date -> 発行日 youdao: en -> ja: Reset -> リセット youdao: en -> ja: Search -> 検索 youdao: en -> ja: Search Name -> 検索名 youdao: en -> ja: Send -> 送信 youdao: en -> ja: Sign in -> サインイン youdao: en -> ja: Sign out -> サインアウト youdao: en -> ja: Switch Theme -> テーマを切り替える youdao: en -> ja: Tags -> タグ youdao: en -> ja: The input is not valid E-mail! -> 入力が有効な電子メールではあ りません! youdao: en -> ja: The input is not valid phone! -> 入力は有効な電話ではありません ! youdao: en -> ja: Title -> タイトル youdao: en -> ja: Total {total} Items -> 合計{total}項目 youdao: en -> ja: Unpublished -> 未発表 youdao: en -> ja: Update -> 更新 youdao: en -> ja: Update User -> ユーザーの更新 youdao: en -> ja: Username -> 名 youdao: en -> ja: Views -> 表示モード youdao: en -> ja: Visibility -> 可視 性 youdao: en -> ja: You have viewed all notifications. -> すべての通知を表示しまし た。 completed: en -> ja All translations have been completed. ➜ antd-admin git:( master ) ✗
+
\ No newline at end of file
diff --git a/docs/_media/term_js_build.svg b/docs/_media/term_js_build.svg
new file mode 100644
index 0000000..ff7489f
--- /dev/null
+++ b/docs/_media/term_js_build.svg
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➜ antd-admin git:( master ) ✗ ➜ antd-admin git:( master ) ✗ n ➜ antd-admin git:( master ) ✗ np ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm r ➜ antd-admin git:( master ) ✗ npm ru ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run b ➜ antd-admin git:( master ) ✗ npm run bu ➜ antd-admin git:( master ) ✗ npm run bui ➜ antd-admin git:( master ) ✗ npm run buil ➜ antd-admin git:( master ) ✗ npm run build Compiling ● webpack █████████████████████████ compiling (0%) Compiling ● webpack ███ ██████████████████████ building modules (10%) 2/2 modules 0 active Compiling ● webpack ███ ██████████████████████ building modules (11%) 11/13 modules 2 activ e node_modules/umi/lib/createHistory.js ● webpack ███ ██████████████████████ building modules (12%) 18/21 modules 3 activ node_modules/webpack/buildin/global.js ● webpack ██████ ███████████████████ building modules (23%) 110/112 modules 2 act ive node_modules/react-dom/cjs/react-dom.production.min.js ● webpack ██████ ███████████████████ building modules (23%) 115/118 modules 3 act node_modules/util/support/isBufferBrowser.js ● webpack ██████ ███████████████████ building modules (23%) 116/141 modules 25 ac tive node_modules/core-js/modules/_global.js ● webpack ███████ ██████████████████ building modules (25%) 130/142 modules 12 ac node_modules/path-browserify/index.js ● webpack ███████ ██████████████████ building modules (27%) 147/191 modules 44 ac node_modules/core-js/modules/_bind.js ● webpack █████████ ████████████████ building modules (35%) 215/256 modules 41 ac node_modules/core-js/modules/_inherit-if-required.js ● webpack ██████████ ███████████████ building modules (39%) 249/266 modules 17 ac node_modules/core-js/modules/web.dom.iterable.js ● webpack ███████████ ██████████████ building modules (42%) 267/307 modules 40 ac ...4m › postcss-loader › less-loader › src/pages/404.less ● webpack ████████████ █████████████ building modules (47%) 313/320 modules 7 act node_modules/prop-types/index.js ● webpack █████████████ ████████████ building modules (49%) 328/351 modules 23 ac node_modules/react-router-dom/es/index.js ● webpack █████████████ ████████████ building modules (51%) 343/354 modules 11 ac babel-loader › src/pages/chart/highCharts/HighChartsComponent.js ● webpack █████████████ ████████████ building modules (52%) 354/372 modules 18 ac src/locales/en/messages.json ● webpack ██████████████ ███████████ building modules (54%) 372/394 modules 22 ac babel-loader › src/utils/theme.js ● webpack ███████████████ ██████████ building modules (57%) 395/422 modules 27 ac node_modules/@babel/runtime/helpers/arrayWithoutHoles.js ● webpack ███████████████ ██████████ building modules (60%) 424/455 modules 31 ac node_modules/antd/es/card/Meta.js ● webpack ████████████████ █████████ building modules (61%) 427/463 modules 36 ac node_modules/antd/es/_util/throttleByAnimationFrame.js ● webpack ████████████████ █████████ building modules (64%) 458/477 modules 19 ac node_modules/antd/es/radio/group.js ● webpack █████████████████ ████████ building modules (67%) 476/497 modules 21 ac babel-loader › src/pages/chart/highCharts/mapdata/europe.js ● webpack █████████████████ ████████ building modules (66%) 488/514 modules 26 ac node_modules/react-router-dom/node_modules/warning/warning.js ● webpack █████████████████ ████████ building modules (67%) 493/518 modules 25 ac ...der › less-loader › src/pages/chart/Recharts/Container.less ● webpack █████████████████ ████████ building modules (67%) 505/525 modules 20 ac node_modules/omit.js/es/index.js ● webpack █████████████████ ████████ building modules (67%) 532/559 modules 27 ac node_modules/highcharts-exporting/exporting.js ● webpack █████████████████ ████████ building modules (67%) 574/598 modules 24 ac node_modules/antd/es/date-picker/locale/en_US.js ● webpack █████████████████ ████████ building modules (68%) 589/608 modules 19 ac node_modules/draft-js/lib/ContentState.js ● webpack █████████████████ ████████ building modules (67%) 616/641 modules 25 ac node_modules/react-router/es/matchPath.js ● webpack █████████████████ ████████ building modules (67%) 656/679 modules 23 ac node_modules/draft-js/lib/DraftEntityInstance.js ● webpack █████████████████ ████████ building modules (67%) 665/690 modules 25 ac node_modules/axios/lib/utils.js ● webpack █████████████████ ████████ building modules (67%) 685/712 modules 27 ac node_modules/add-dom-event-listener/lib/index.js ● webpack █████████████████ ████████ building modules (68%) 735/756 modules 21 ac node_modules/lodash/_objectToString.js ● webpack █████████████████ ████████ building modules (68%) 737/758 modules 21 ac node_modules/lodash/_getRawTag.js ● webpack █████████████████ ████████ building modules (67%) 756/787 modules 31 ac node_modules/add-dom-event-listener/lib/EventObject.js ● webpack █████████████████ ████████ building modules (67%) 771/800 modules 29 ac node_modules/core-js/library/modules/_add-to-unscopables.js ● webpack █████████████████ ████████ building modules (67%) 781/808 modules 27 ac node_modules/core-js/library/modules/_object-dp.js ● webpack █████████████████ ████████ building modules (68%) 817/836 modules 19 ac node_modules/size-sensor/lib/index.js ● webpack █████████████████ ████████ building modules (68%) 845/870 modules 25 ac node_modules/is-buffer/index.js ● webpack █████████████████ ████████ building modules (68%) 892/913 modules 21 ac node_modules/echarts/lib/util/model.js ● webpack █████████████████ ████████ building modules (68%) 933/963 modules 30 ac node_modules/echarts-liquidfill/node_modules/echarts/lib/model/Series.js ● webpack █████████████████ ████████ building modules (68%) 978/996 modules 18 ac node_modules/lodash/_baseFor.js ● webpack █████████████████ ████████ building modules (68%) 1000/1029 modules 29 active node_modules/zrender/lib/contain/text.js ● webpack █████████████████ ████████ building modules (68%) 1029/1056 modules 27 ...e_modules/echarts-liquidfill/node_modules/echarts/lib/model/mixin/dataFormat. js ● webpack █████████████████ ████████ building modules (68%) 1059/1077 modules 18 node_modules/lodash/_createBaseFor.js ● webpack █████████████████ ████████ building modules (68%) 1101/1133 modules 32 node_modules/zrender/lib/graphic/helper/image.js ● webpack █████████████████ ████████ building modules (68%) 1155/1175 modules 20 node_modules/lodash/_baseGetAllKeys.js ● webpack ██████████████████ ███████ building modules (69%) 1212/1231 modules 19 node_modules/size-sensor/lib/sensors/resizeObserver.js ● webpack █████████████████ ████████ building modules (68%) 1266/1296 modules 30 node_modules/d3-shape/src/curve/cardinalClosed.js ● webpack █████████████████ ████████ building modules (68%) 1329/1357 modules 28 ...ules/echarts-liquidfill/node_modules/echarts/lib/data/helper/dataStackHelper. ● webpack ██████████████████ ███████ building modules (69%) 1392/1409 modules 17 node_modules/d3-collection/src/set.js ● webpack ██████████████████ ███████ building modules (69%) 1449/1467 modules 18 node_modules/component-classes/index.js ● webpack █████████████████ ████████ building modules (68%) 1481/1507 modules 26 node_modules/d3-time/src/second.js ● webpack ██████████████████ ███████ building modules (69%) 1534/1551 modules 17 node_modules/echarts-liquidfill/src/liquidFillView.js ● webpack ██████████████████ ███████ building modules (69%) 1594/1607 modules 13 node_modules/rc-animate/es/CSSMotion.js ● webpack █████████████████ ████████ building modules (68%) 1651/1691 modules 40 node_modules/echarts/lib/component/gridSimple.js ● webpack ██████████████████ ███████ building modules (69%) 1700/1713 modules 13 node_modules/echarts/lib/coord/calendar/prepareCustom.js ● webpack █████████████████ ████████ building modules (68%) 1739/1771 modules 32 node_modules/echarts/lib/component/tooltip/TooltipContent.js ● webpack ██████████████████ ███████ building modules (69%) 1780/1807 modules 27 node_modules/echarts/lib/chart/scatter/ScatterView.js ● webpack ██████████████████ ███████ building modules (69%) 1781/1808 modules 27 node_modules/echarts/lib/chart/scatter/ScatterSeries.js ● webpack █████████████████ ████████ building modules (68%) 1819/1852 modules 33 node_modules/echarts/lib/chart/graph/categoryFilter.js ● webpack ██████████████████ ███████ building modules (69%) 1867/1880 modules 13 node_modules/echarts/lib/chart/sankey/SankeySeries.js ● webpack ██████████████████ ███████ building modules (69%) 1916/1944 modules 28 node_modules/echarts/lib/component/dataZoom/DataZoomView.js ● webpack ██████████████████ ███████ building modules (69%) 1966/1993 modules 27 node_modules/echarts/lib/chart/sunburst/SunburstPiece.js ● webpack ██████████████████ ███████ building modules (69%) 2002/2030 modules 28 node_modules/draft-js/lib/CompositeDraftDecorator.js ● webpack ██████████████████ ███████ building modules (69%) 2010/2034 modules 24 node_modules/echarts/lib/component/marker/MarkerModel.js ● webpack ██████████████████ ███████ building modules (69%) 2031/2047 modules 16 babel-loader › src/pages/dashboard/components/browser.js ● webpack ██████████████████ ███████ building modules (69%) 2081/2100 modules 19 node_modules/array-tree-filter/lib/index.js ● webpack ██████████████████ ███████ building modules (69%) 2105/2122 modules 17 node_modules/echarts/lib/component/dataZoom/SelectZoomModel.js ● webpack ██████████████████ ███████ building modules (69%) 2108/2123 modules 15 ● webpack ██████████████████ ███████ building modules (69%) 2117/2127 modules 10 node_modules/react-router-redux/es/middleware.js ● webpack ██████████████████ ███████ building modules (69%) 2122/2130 modules 8 a ctive node_modules/react-router-redux/es/actions.js ● webpack ██████████████████ ███████ building modules (69%) 2143/2167 modules 24 node_modules/react-redux/es/connect/connect.js ● webpack ██████████████████ ███████ building modules (69%) 2185/2203 modules 18 node_modules/rc-dialog/es/DialogWrap.js ● webpack ██████████████████ ███████ building modules (69%) 2237/2265 modules 28 node_modules/antd/es/tag/index.js ● webpack ██████████████████ ███████ building modules (69%) 2283/2301 modules 18 babel-loader › src/pages/user/components/Filter.js ● webpack ██████████████████ ███████ building modules (69%) 2327/2338 modules 11 node_modules/rc-util/es/getScrollBarSize.js ● webpack ██████████████████ ███████ building modules (69%) 2339/2357 modules 18 node_modules/async-validator/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2347/2363 modules 16 node_modules/lodash/_createCurry.js ● webpack ██████████████████ ███████ building modules (69%) 2384/2400 modules 16 node_modules/rmc-feedback/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2402/2422 modules 20 node_modules/dom-align/es/getAlignOffset.js ● webpack ██████████████████ ███████ building modules (69%) 2426/2438 modules 12 node_modules/dva-core/lib/prefixType.js ● webpack ██████████████████ ███████ building modules (69%) 2430/2438 modules 8 a ● webpack ██████████████████ ███████ building modules (69%) 2451/2471 modules 20 node_modules/antd/es/badge/index.js ● webpack ██████████████████ ███████ building modules (69%) 2485/2494 modules 9 a node_modules/fbjs/lib/emptyObject.js ● webpack ██████████████████ ███████ building modules (69%) 2490/2520 modules 30 node_modules/antd/es/date-picker/WeekPicker.js ● webpack ██████████████████ ███████ building modules (69%) 2512/2524 modules 12 node_modules/react-side-effect/lib/index.js ● webpack ██████████████████ ███████ building modules (69%) 2519/2529 modules 10 node_modules/redux-saga/lib/internal/runSaga.js ● webpack ██████████████████ ███████ building modules (69%) 2524/2532 modules 8 a node_modules/antd/es/layout/Sider.js ● webpack ██████████████████ ███████ building modules (69%) 2540/2549 modules 9 a node_modules/antd/es/_util/getDataOrAriaProps.js ● webpack ██████████████████ ███████ building modules (69%) 2554/2561 modules 7 a node_modules/redux-saga/lib/internal/sagaHelpers/index.js ● webpack ██████████████████ ███████ building modules (69%) 2577/2581 modules 4 a node_modules/rc-switch/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2581/2589 modules 8 a node_modules/rc-drawer/es/index.js ● webpack ██████████████████ ███████ building modules (69%) 2604/2610 modules 6 a node_modules/rc-calendar/es/date/DateInput.js ● webpack ██████████████████ ███████ finish module graph (70%) ● webpack ███████████████████ ██████ optimizing (73%) ● webpack ████████████████████ █████ advanced chunk modules optimization (79%) ● webpack ██████████████████████ ███ after hashing (88%) ● webpack ███████████████████████ ██ additional chunk assets processing (90%) ● webpack ███████████████████████ ██ chunk asset optimization (92%) UglifyJSPlugi n ● webpack ███████████████████████ ██ after chunk asset optimization (92%) ➜ antd-admin git:( master ) ✗ npm run build > antd-admin@5.0.0-beta build /Users/zuiidea/web/antd-admin > umi build [12:40:22] webpack compiled in 15s 56ms DONE Compiled successfully in 15062ms 12:40:22 File sizes after gzip: 887 B dist/ p__dashboard__model.js.async.js 877 B dist/ precache-manifest.6d2a703c437c4f28b5f6e072817bbe6e.js 786 B dist/ p__UIElement__editor__index.async.js 764 B dist/ i18n-0.async.js 652 B dist/ p__login__index.chunk.css 614 B dist/ p__user__$id__models__detail.js.async.js 599 B dist/ p__post__model.js.async.js 589 B dist/ p__user__$id__index.async.js 569 B dist/ service-worker.js 530 B dist/ p__request__index.chunk.css 515 B dist/ p__login__model.js.async.js 419 B dist/ p__index.async.js 245 B dist/ p__chart__ECharts__index.chunk.css 230 B dist/ p__chart__Recharts__index.chunk.css 138 B dist/ p__user__$id__index.chunk.css 74 B dist/ p__chart__highCharts__index.chunk.css 66 B dist/ p__user__index.chunk.css 66 B dist/ p__post__index.chunk.css The bundle size is significantly larger than recommended. Consider reducing it with code splitting: https://goo.gl/9VhYWB You can also analyze the project dependencies: https://goo.gl/LeUzfb ➜ antd-admin git:( master ) ✗
+ 0:00/0:00
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_media/term_js_i18n.svg b/docs/_media/term_js_i18n.svg
new file mode 100644
index 0000000..f985604
--- /dev/null
+++ b/docs/_media/term_js_i18n.svg
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➜ antd-admin git:( master ) ✗ ➜ antd-admin git:( master ) ✗ n ➜ antd-admin git:( master ) ✗ np ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm ➜ antd-admin git:( master ) ✗ npm r ➜ antd-admin git:( master ) ✗ npm ru ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run ➜ antd-admin git:( master ) ✗ npm run a ➜ antd-admin git:( master ) ✗ npm run ad ➜ antd-admin git:( master ) ✗ npm run add ➜ antd-admin git:( master ) ✗ npm run add- ➜ antd-admin git:( master ) ✗ npm run add-l ➜ antd-admin git:( master ) ✗ npm run add-lo ➜ antd-admin git:( master ) ✗ npm run add-loc ➜ antd-admin git:( master ) ✗ npm run add-loca ➜ antd-admin git:( master ) ✗ npm run add-local ➜ antd-admin git:( master ) ✗ npm run add-locale ➜ antd-admin git:( master ) ✗ npm run add-locale ➜ antd-admin git:( master ) ✗ npm run add-locale j ➜ antd-admin git:( master ) ✗ npm run add-locale ja ➜ antd-admin git:( master ) ✗ npm run e ➜ antd-admin git:( master ) ✗ npm run ex ➜ antd-admin git:( master ) ✗ npm run ext ➜ antd-admin git:( master ) ✗ npm run extr ➜ antd-admin git:( master ) ✗ npm run extra ➜ antd-admin git:( master ) ✗ npm run extrac ➜ antd-admin git:( master ) ✗ npm run extract ➜ antd-admin git:( master ) ✗ npm run add-locale ja > antd-admin@5.0.0-beta add-locale /Users/zuiidea/web/antd-admin > lingui add-locale "ja" Added locale ja . (use " lingui extract " to extract messages) ➜ antd-admin git:( master ) ✗ npm run extract > antd-admin@5.0.0-beta extract /Users/zuiidea/web/antd-admin > lingui extract ➜ antd-admin git:( master ) ✗ npm run t ➜ antd-admin git:( master ) ✗ npm run tr ➜ antd-admin git:( master ) ✗ npm run tra ➜ antd-admin git:( master ) ✗ npm run tran ➜ antd-admin git:( master ) ✗ npm run trans ➜ antd-admin git:( master ) ✗ npm run trans: ➜ antd-admin git:( master ) ✗ npm run trans:o ➜ antd-admin git:( master ) ✗ npm run trans:on ➜ antd-admin git:( master ) ✗ npm run trans:onl Catalog statistics: ┌─────────────┬─────────────┬─────────┐ │ Language │ Total count │ Missing │ ├─────────────┼─────────────┼─────────┤ │ en (source) │ 52 │ - │ │ ja │ 52 │ 52 │ │ zh │ 52 │ 0 │ └─────────────┴─────────────┴─────────┘ (use " lingui add-locale <language> " to add more locales) (use " lingui extract " to update catalogs with new messages) (use " lingui compile " to compile catalogs for production) ➜ antd-admin git:( master ) ✗ npm run trans:only ➜ antd-admin git:( master ) ✗ npm run trans:only > antd-admin@5.0.0-beta trans:only /Users/zuiidea/web/antd-admin > node ./scripts/translate.js add to skip: Publish Date add to skip: Reset add to skip: Search add to skip: Search Name add to skip: Send add to skip: Sign in add to skip: Sign out add to skip: Switch Theme add to skip: Tags add to skip: The input is not valid E-mail! add to skip: The input is not valid phone! add to skip: Title add to skip: Total {total} Items add to skip: Unpublished add to skip: Update add to skip: Update User add to skip: Username add to skip: Views add to skip: Visibility add to skip: You have viewed all notifications. completed: en -> zh start: en -> ja link: en -> ja: /dashboard -> /ja/dashboard youdao: en -> ja: Add Param -> Param の追加 youdao: en -> ja: Address -> アドレス youdao: en -> ja: Age -> 年齢 youdao: en -> ja: Are you sure delete this record? -> このレコードを削除してもよ ろしいですか? youdao: en -> ja: Author -> 著者 youdao: en -> ja: Avatar -> アバター youdao: en -> ja: Categories -> カテゴリ youdao: en -> ja: Clear notifications -> 通知のクリア youdao: en -> ja: Comments -> コメント youdao: en -> ja: Create -> 作成 youdao: en -> ja: Create User -> ユーザーの作成 same: en -> ja: CreateTime youdao: en -> ja: Dark -> 暗い youdao: en -> ja: Delete -> 削除 youdao: en -> ja: Email -> 電子メール youdao: en -> ja: Female -> 女性 youdao: en -> ja: Gender -> 性別 youdao: en -> ja: Hi, -> こんにちは youdao: en -> ja: Image -> イメージ youdao: en -> ja: Light -> 光 youdao: en -> ja: Male -> 男性 youdao: en -> ja: Name -> 名前 youdao: en -> ja: NickName -> ニックネーム youdao: en -> ja: Not Found -> 見つからない youdao: en -> ja: Operation -> 操作 same: en -> ja: Params youdao: en -> ja: Password -> パスワード youdao: en -> ja: Phone -> 電話 youdao: en -> ja: Pick an address -> 住所の選択 youdao: en -> ja: Please pick an address -> 住所を選択してください same: en -> ja: Publised youdao: en -> ja: Publish Date -> 発行日 youdao: en -> ja: Reset -> リセット youdao: en -> ja: Search -> 検索 youdao: en -> ja: Search Name -> 検索名 youdao: en -> ja: Send -> 送信 youdao: en -> ja: Sign in -> サインイン youdao: en -> ja: Sign out -> サインアウト youdao: en -> ja: Switch Theme -> テーマを切り替える youdao: en -> ja: Tags -> タグ youdao: en -> ja: The input is not valid E-mail! -> 入力が有効な電子メールではあ りません! youdao: en -> ja: The input is not valid phone! -> 入力は有効な電話ではありません ! youdao: en -> ja: Title -> タイトル youdao: en -> ja: Total {total} Items -> 合計{total}項目 youdao: en -> ja: Unpublished -> 未発表 youdao: en -> ja: Update -> 更新 youdao: en -> ja: Update User -> ユーザーの更新 youdao: en -> ja: Username -> 名 youdao: en -> ja: Views -> 表示モード youdao: en -> ja: Visibility -> 可視 性 youdao: en -> ja: You have viewed all notifications. -> すべての通知を表示しまし た。 completed: en -> ja All translations have been completed. ➜ antd-admin git:( master ) ✗
+ 0:00/0:00
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
new file mode 100644
index 0000000..3d6d176
--- /dev/null
+++ b/docs/_sidebar.md
@@ -0,0 +1,12 @@
+- Getting started
+ - [Quick Start](getting-started.md)
+- Customization
+ - [Configuration](configuration.md)
+ - [API Configuration](API-configuration.md)
+ - [I18n](i18n.md)
+ - [Layout](layout.md)
+ - [Request](request.md)
+- Guide
+ - [Deploy](deploy.md)
+- [Change Log](change-log.md)
+- [FAQ](faq.md)
diff --git a/docs/change-log.md b/docs/change-log.md
new file mode 100644
index 0000000..3465321
--- /dev/null
+++ b/docs/change-log.md
@@ -0,0 +1,50 @@
+## 5.0.0
+
+#### Optimization
+
+- Try to use decorators to simplify code writing and improve code readability.
+
+- API configurization to simplify the way data is obtained.
+
+- The files in `utils` are split and each has its own role.
+
+- Simplify the `utils/request` file without special handling.
+
+#### Specification
+
+- Functions add comments, parameters, return values, etc., ambiguous code adds comments, canonical reference [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html#appendices-jsdoc-tag-reference).
+
+- Semantic version number, specification participation [semantic version 2.0.0](https://semver.org/lang/zh-CN/).
+
+- Static code checking, unified code style, will use `prettier`, `stylelint`, `eslint` specification code before code submission.
+
+- Git submits information normalization, [git-commit-emoji-cn](https://github.com/liuchengxu/git-commit-emoji-cn).
+
+- Based on the pre-defined routing of `Umi`, there is no need to write a routing configuration file.
+
+- Use `React 16` new features such as `Fragment`, `Context`, `PureComponent`, etc.
+
+#### Features
+
+- Support internationalization, extract source fields from source code, load language packs on demand, and automatically translate online.
+
+- Support for the introduction `lodash` functions on demand.
+
+- Support multiple layouts, which rules can be used according to the rules.
+
+- Support Antd Admin to automatically compile and deploy on Travis.
+
+- Generate a documentation website using `Docsify`.
+
+
+#### Style
+
+- Added Antd Admin standalone Logo.
+
+- Rewrite the overall layout component, optimize the menu, automatic breadcrumb navigation, menu auto-expansion and other logic.
+
+- The mobile menu is changed to drawer.
+
+#### Other
+
+- Discard components such as `IconFont`, `Search`, `DataTable` because they are well supported and replaceable in `Antd`.
\ No newline at end of file
diff --git a/docs/configuration.md b/docs/configuration.md
new file mode 100644
index 0000000..54acff7
--- /dev/null
+++ b/docs/configuration.md
@@ -0,0 +1,102 @@
+# Configuration
+
+You can do some custom configuration in `/src/utils/config.js`:
+
+## siteName
+
+- Type `String`
+
+ Configure the site name, apply it to the login box, and display the title text at the top of the sidebar.
+
+## copyright
+
+- Type: `String`
+
+ Configure the copyright notice to apply to the login page, at the bottom of the `Primary` layout.
+
+## logoPath
+
+- Type: `String`
+
+ Configure the site logo to apply to the login box and the Logo display at the top of the sidebar.
+
+## apiPrefix
+
+- Type: `String`
+
+ Configure the prefix of the interface in the project. The interface related documents can be viewed [API configuration](API-configuration.md)
+
+## fixedHeader
+
+- Type: `String`
+
+ Under the `Primary` layout, whether the top of the page is fixed when scrolling。
+
+## layouts
+
+- Type: `Array`
+
+ Configuration? Which routes use which layout, unspecified route uses the default layout `Public`, the project currently has `Primary` and `Public` layouts,
+ The default configuration is as follows:
+
+ ```javascript
+ layouts: [
+ {
+ name: 'primary',
+ include: [/.*/],
+ exclude: [/(\/(en|zh))*\/login/],
+ },
+ ],
+ ```
+
+ The object properties for each layout are as follows:
+
+ - `name` - The name of the layout;
+
+ - `include` - Specifies a list of routing rules that use this layout, which can be a regular expression or a string;
+
+ - `exclude` - Specifies a list of routing rules that do not use this layout, which can be a regular expression or a string.
+
+ > Note: `exclude` takes precedence over `include`, and the layout previous it has a higher priority than the behind layout. The development process may need to be combined with the layout in the `src/layouts` directory. For details, see [Using Layout](./layout.md).
+
+## i18n
+
+- Type: `Object`
+
+ Configure internationalization, the default configuration is as follows:
+
+ ```javascript
+ i18n: {
+ languages: [
+ {
+ key: 'en',
+ title: 'English',
+ flag: '/america.svg',
+ },
+ {
+ key: 'zh',
+ title: '中文',
+ flag: '/china.svg',
+ },
+ ],
+ defaultLanguage: 'en',
+ }
+ ```
+
+ ### i18n.languages
+
+ - Type: `Array`
+
+ Specify which languages the app supports, and the object properties for each language are as follows:
+
+ - `key` - The `key` of the language is applied to the page url to distinguish the language, and also corresponds to the language package folder name in the `src/locales` directory;
+
+ - `title` - The name of the language, at the bottom of the login page, at the top of the `Primary` layout, the language switch is displayed;
+
+ - `flag` - The path of the flag icon of the language, the language switching display at the top of the `Primary` layout.
+
+ ### i18n.defaultLanguage
+
+ - Type: `String`
+
+ Configure the default language.
diff --git a/docs/deploy.md b/docs/deploy.md
new file mode 100644
index 0000000..3cc157f
--- /dev/null
+++ b/docs/deploy.md
@@ -0,0 +1,113 @@
+# Deploy
+
+After the development is completed and verified in the development environment, it needs to be deployed to our users.
+
+
+
+## Build
+
+First execute the following command,
+
+```bash
+npm run build
+```
+
+After a few seconds, the output should look like this:
+
+```bash
+> antd-admin@5.0.0-beta build /Users/zuiidea/web/antd-admin
+> umi build
+
+[21:13:17] webpack compiled in 43s 868ms
+ DONE Compiled successfully in 43877ms 21:13:17
+
+File sizes after gzip:
+
+ 1.3 MB dist/vendors.async.js
+ 308.21 KB dist/umi.js
+ 45.49 KB dist/vendors.chunk.css
+ 36.08 KB dist/p__chart__highCharts__index.async.js
+ 33.53 KB dist/p__user__index.async.js
+ 22.36 KB dist/p__chart__ECharts__index.async.js
+ 4.21 KB dist/p__dashboard__index.async.js
+ 4.06 KB dist/umi.css
+ ...
+```
+
+The `build` command will package all resources, including JavaScript, CSS, web fonts, images, html, and more. You can find these files in the `dist/` directory.
+
+> If you have requirements for using HashHistory , deploying html to non-root directories, statics, etc., check out [Umi Deployment] (https://umijs.org/en/guide/deploy.html).
+
+## Local verification
+
+
+Local verification can be done via `serve` before publishing.
+
+```
+$ yarn global add serve
+$ serve ./dist
+
+Serving!
+
+- Local: http://localhost:5000
+- On Your Network: http://{Your IP}:5000
+
+Copied local address to clipboard!
+
+```
+
+Access [http://localhost:5000](http://localhost:5000), under normal circumstances, it should be consistent with `npm start` (The API may not get the correct data).
+
+
+## Deploy
+
+Next, we can upload the static file to the server. If you use Nginx as the Web server, you can configure it in `ngnix.conf`:
+```
+server
+ {
+ listen 80;
+ # Specify an accessible domain name
+ server_name antd-admin.zuiidea.com;
+ # The directory where the compiled files are stored
+ root /home/www/antd-admin/dist;
+
+ # Proxy server interface to avoid cross-domain
+ location /api {
+ proxy_pass http://localhost:7000/api;
+ }
+
+ Because the front end uses BrowserHistory, it will route backback to index.html
+ location / {
+ index index.html;
+ try_files $uri $uri/ /index.html;
+ }
+ }
+```
+
+Restart the web server and access [http://antd-admin.zuiidea.com](http://antd-admin.zuiidea.com) , You will see the correct page.
+
+```bash
+nginx -s reload
+```
+
+Similarly, if you use Caddy as a web server, you can do this in `Caddyfile`:
+
+```
+antd-admin.zuiidea.com {
+ gzip
+ root /home/www/antd-admin/dist
+ proxy /api http://localhost:7000
+
+ rewrite {
+ if {path} not_match ^/api
+ to {path} {path}/ /
+ }
+}
+
+
+antd-admin.zuiidea.com/public {
+ gzip
+ root /home/www/antd-admin/dist/static/public
+}
+
+```
diff --git a/docs/faq.md b/docs/faq.md
new file mode 100644
index 0000000..2c6409d
--- /dev/null
+++ b/docs/faq.md
@@ -0,0 +1,9 @@
+# FAQ
+
+Most asked
+
+## create new page
+
+ 1. just copy a page in /src/pages (route here auto generated by [umi](https://umijs.org/guide/router.html#basic-routing))
+ 2. modify namespace/pathToRegexp in model.js
+ 3. modify mock route.js to add a route
\ No newline at end of file
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 0000000..9a9c90f
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,73 @@
+# Quick Start
+
+> Before delving into Ant Design React, a good knowledge base of [React](http://facebook.github.io/react/) 、 [ES2015+](http://es6.ruanyifeng.com/) 、 [Antd Design](https://ant.design/docs/react/introduce-cn) . Learn about [UmiJS](https://umijs.org/) , [Dva](http://github.com/dvajs/dva) . And properly installed and configured [Node.js](https://nodejs.org/) v8 or above, [Git](https://git-scm.com/). It would be helpful if you have pre-existing knowledge on those.
+
+## Installation
+
+```bash
+git clone https://github.com/zuiidea/antd-admin.git my-project
+cd my-project
+```
+
+## Scaffolding
+
+The project layout is as follows:
+
+```bash
+├── dist/ # Default build output directory
+├── mock/ # Mock files
+├── public/ # Static resource
+├── src/ # Source code
+│ ├── components/ # Components
+│ ├── e2e/ # Integrated Test Case
+│ ├── layouts/ # Common Layouts
+│ ├── locales/ # i18n resources
+│ ├── models/ # Global dva Model
+│ ├── pages/ # Sub-pages and templates
+│ ├── services/ # Backend Services
+│ │ ├── api.js # API configuration
+│ │ └── index.js # API export
+│ ├── themes/ # Themes
+│ │ ├── default.less # Less variable
+│ │ ├── index.less # Global style
+│ │ ├── mixin.less # Less mixin
+│ │ └── vars.less # Less variable and mixin
+│ ├── utils/ # Utility
+│ │ ├── config.js # Application configuration
+│ │ ├── constant.js # Static constant
+│ │ ├── index.js # Utility methods
+│ │ ├── request.js # Request function(axios)
+│ │ └── theme.js # Style variables used in js
+├── .editorconfig
+├── .env
+├── .eslintrc
+├── .gitignore
+├── .prettierignore
+├── .prettierrc
+├── .stylelintrc.json
+├── .travis.yml
+└── .umirc.js
+└── package.json
+```
+
+## Development
+
+1. Install Dependencies.
+
+```bash
+yarn install
+```
+
+Or
+
+```bash
+npm install
+```
+
+2. Start local server.
+
+```bash
+npm run start
+```
+
+3. After the startup is complete, open a browser and visit [http://localhost:7000](http://localhost:7000), If you need to change the startup port, you can configure it in the `.env` file.
diff --git a/docs/i18n.md b/docs/i18n.md
new file mode 100644
index 0000000..33bf011
--- /dev/null
+++ b/docs/i18n.md
@@ -0,0 +1,75 @@
+# globalization
+
+## Add language
+
+Take Japanese as an example.
+
+
+
+1. Add a language pack local file, `ja` is the Japanese language code, and a list of languages that support translation [有道智云](http://ai.youdao.com/docs/doc-trans-api.s#p05), the `src/locales/ja/messages.json` file will be generated after running the following command.
+
+ ```bash
+ npm run add-locale ja
+ ```
+
+2. Extract the fields in the code that need to be translated, ie `?message `, `` t`message `` in the `message` field, run the following command after `src/locales/ja /messages.json` will appear after the extracted field configuration.
+
+ ```bash
+ npm run extract
+ ```
+
+ You will see the following information:
+
+ ```bash
+ Catalog statistics:
+ ┌─────────────┬─────────────┬─────────┐
+ │ Language │ Total count │ Missing │
+ ├─────────────┼─────────────┼─────────┤
+ │ en (source) │ 52 │ - │
+ │ ja │ 52 │ 52 │
+ │ zh │ 52 │ 0 │
+ └─────────────┴─────────────┴─────────┘
+ ```
+
+3. At the same time, we have added the relevant configuration in `src/utils/config.js`.
+
+ ```javascript
+ {
+ ...
+ i18n: {
+ languages: [
+ ...
+ {
+ key:'ja',
+ title: '日本語',
+ flag: '/japanese.svg',
+ },
+ ],
+ },
+ }
+ ```
+
+ > Routing related effects, after the configuration `npm run start` takes effect after restart.
+
+4. Use the built-in commands for automatic translation. You will see the translated configuration in `src/locales/ja/messages.json`.
+
+ ```bash
+ npm run trans:only
+ ```
+
+ You will see the following information:
+
+ ```bash
+ start: en -> ja
+ ...
+ youdao: en -> ja: Unpublished -> 未発表
+ youdao: en -> ja: Update -> 更新
+ youdao: en -> ja: Update User -> ユーザーの更新
+ youdao: en -> ja: Username -> 名
+ ...
+ All translations have been completed.
+ ```
+
+ > `npm run trans` will execute `npm run extract` and `npm run trans:only` in order.
+
+5. Finally, you can adjust the inaccurate fields in `src/locales/ja/messages.json`. Start the development mode `npm run start`, open [http://localhost:7000/ja/login](http://localhost:7000/ja/login) and you will see the Japanese version of the app.
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..e981d4c
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ antd-admin - An admin dashboard application demo built upon Ant Design and UmiJS
+
+
+
+
+
+
+
+
+
+ En
+ 中文
+
+ Loading...
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/layout.md b/docs/layout.md
new file mode 100644
index 0000000..22223ad
--- /dev/null
+++ b/docs/layout.md
@@ -0,0 +1,60 @@
+# Layout
+
+## Add a new layout
+
+Take a new layout named `secondary` as an example to make the route starting with `secondary` use this layout.
+
+1. Add related configuration in `src/utils/config.js`. For details, please refer to [layouts](/configuration?id=layouts).
+
+```javascript
+ layouts: [
+ {
+ name: 'primary',
+ include: [/.*/],
+ exclude: [/(\/(en|zh))*\/login/, /(\/(en|zh))*\/secondary\/(.*)/],
+ },
+ {
+ name: 'secondary',
+ include: [/(\/(en|zh))*\/secondary\/(.*)/],
+ },
+ ],
+```
+
+2. Add the `secondary` layout component to the `src/layouts/BaseLayout.js` file.
+
+```javascript
+ import SecondaryLayout from './SecondaryLayout'
+
+ const LayoutMap = {
+ primary: PrimaryLayout,
+ public: PublicLayout,
+ secondary: SecondaryLayout,
+ }
+```
+
+3. Add the `SecondaryLayout.js` file to the `src/layouts/` directory.
+
+```javascript
+ import React from 'react'
+
+ export default ({ children }) => {
+ return (
+
+
Secondary
+ {children}
+
+ )
+ }
+```
+
+4. Add a `secondary/index.js` file to the `src/pages/` directory.
+
+```javascript
+ import React from 'react'
+
+ export default ({ children }) => {
+ Return Secondary page Content
+ }
+```
+
+5. Finally, start the development mode `npm run start`, open [http://localhost:7000/secondary/](http://localhost:7000/secondary/) and you will see the page for the `secondary` layout.
diff --git a/docs/request.md b/docs/request.md
new file mode 100644
index 0000000..69d6607
--- /dev/null
+++ b/docs/request.md
@@ -0,0 +1,22 @@
+# HTTP request
+
+this project use axios for http service, file located in src/utils/request.js
+
+## Custom Header
+
+As for privilege access or modify cookie, you could add header param by yourself
+
+```
+axios.defaults.headers.common['Authorization'] = 'token'
+```
+
+Or
+
+```
+axios.interceptors.request.use(function (config) {
+ config.headers.token = window.localStorage.getItem('token');
+ return config;
+}, function (error) {
+ return Promise.reject(error);
+});
+```
\ No newline at end of file
diff --git a/docs/sw.js b/docs/sw.js
new file mode 100644
index 0000000..cf6295c
--- /dev/null
+++ b/docs/sw.js
@@ -0,0 +1,83 @@
+/* ===========================================================
+ * docsify sw.js
+ * ===========================================================
+ * Copyright 2016 @huxpro
+ * Licensed under Apache 2.0
+ * Register service worker.
+ * ========================================================== */
+
+const RUNTIME = 'docsify'
+const HOSTNAME_WHITELIST = [
+ self.location.hostname,
+ 'fonts.gstatic.com',
+ 'fonts.googleapis.com',
+ 'unpkg.com'
+]
+
+// The Util Function to hack URLs of intercepted requests
+const getFixedUrl = (req) => {
+ var now = Date.now()
+ var url = new URL(req.url)
+
+ // 1. fixed http URL
+ // Just keep syncing with location.protocol
+ // fetch(httpURL) belongs to active mixed content.
+ // And fetch(httpRequest) is not supported yet.
+ url.protocol = self.location.protocol
+
+ // 2. add query for caching-busting.
+ // Github Pages served with Cache-Control: max-age=600
+ // max-age on mutable content is error-prone, with SW life of bugs can even extend.
+ // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
+ // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
+ if (url.hostname === self.location.hostname) {
+ url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
+ }
+ return url.href
+}
+
+/**
+ * @Lifecycle Activate
+ * New one activated when old isnt being used.
+ *
+ * waitUntil(): activating ====> activated
+ */
+self.addEventListener('activate', event => {
+ event.waitUntil(self.clients.claim())
+})
+
+/**
+ * @Functional Fetch
+ * All network requests are being intercepted here.
+ *
+ * void respondWith(Promise r)
+ */
+self.addEventListener('fetch', event => {
+ // Skip some of cross-origin requests, like those for Google Analytics.
+ if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
+ // Stale-while-revalidate
+ // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
+ // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
+ const cached = caches.match(event.request)
+ const fixedUrl = getFixedUrl(event.request)
+ const fetched = fetch(fixedUrl, { cache: 'no-store' })
+ const fetchedCopy = fetched.then(resp => resp.clone())
+
+ // Call respondWith() with whatever we get first.
+ // If the fetch fails (e.g disconnected), wait for the cache.
+ // If there’s nothing in cache, wait for the fetch.
+ // If neither yields a response, return offline pages.
+ event.respondWith(
+ Promise.race([fetched.catch(_ => cached), cached])
+ .then(resp => resp || fetched)
+ .catch(_ => { /* eat any errors */ })
+ )
+
+ // Update the cache with the version we fetched (only for ok status)
+ event.waitUntil(
+ Promise.all([fetchedCopy, caches.open(RUNTIME)])
+ .then(([response, cache]) => response.ok && cache.put(event.request, response))
+ .catch(_ => { /* eat any errors */ })
+ )
+ }
+})
\ No newline at end of file
diff --git a/docs/zh-cn/API-configuration.md b/docs/zh-cn/API-configuration.md
new file mode 100644
index 0000000..19913ac
--- /dev/null
+++ b/docs/zh-cn/API-configuration.md
@@ -0,0 +1,86 @@
+# 接口配置
+
+## 为什么
+
+在使用了`redux`或者`dva`项目中,我们经常会写类似下面的`service`层的函数,使代码结构更清晰,但是很容易看出,我们会写很多相似的代码,在`antd-admin@5.0`中,使用了更加简洁的配置方式实现了相同的功能。
+
+```javascript
+export async function login(data) {
+ return request({
+ url: '/api/v1/user/login',
+ method: 'post',
+ data,
+ })
+}
+```
+
+## 配置和使用
+
+在`src/services/api.js`文件中,你会看到如下配置对象,对象的键用于调用时的函数名称,对象的值为请求的`url`,默认请求方式为`GET`,如果是其他请求方式对象的值的格式则为`'method url'`。
+
+```javascript
+export default {
+ ...
+ queryUser: '/user/:id',
+ queryUserList: '/users',
+ updateUser: 'Patch /user/:id',
+ createUser: 'POST /user/:id',
+ removeUser: 'DELETE /user/:id',
+ removeUserList: 'POST /users/delete',
+ ...
+}
+```
+
+在其他文件中使用
+
+```javascript
+import { queryUser } from 'api'
+
+// 一般文件中
+...
+queryUser(option).then(data => console.log(data))
+...
+
+// model文件中
+...
+yield call(queryUser, option)
+...
+```
+
+## 实现方式
+
+参考`src/services/index.js`文件,对api配置进行遍历,每个属性都返回对应的封装后的request函数。
+
+```javascript
+import request from 'utils/request'
+import { apiPrefix } from 'utils/config'
+
+import api from './api'
+
+const gen = params => {
+ let url = apiPrefix + params
+ let method = 'GET'
+
+ const paramsArray = params.split(' ')
+ if (paramsArray.length === 2) {
+ method = paramsArray[0]
+ url = apiPrefix + paramsArray[1]
+ }
+
+ return function(data) {
+ return request({
+ url,
+ data,
+ method,
+ })
+ }
+}
+
+const APIFunction = {}
+for (const key in api) {
+ APIFunction[key] = gen(api[key])
+}
+
+module.exports = APIFunction
+
+```
\ No newline at end of file
diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md
new file mode 100644
index 0000000..61799bb
--- /dev/null
+++ b/docs/zh-cn/README.md
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+AntD Admin
+
+
+
+一套优秀的中后台前端解决方案
+
+[](https://github.com/ant-design/ant-design)
+[](https://github.com/umijs/umi)
+[](https://github.com/zuiidea/antd-admin/issues)
+[](http://opensource.org/licenses/MIT)
+
+[](https://github.com/zuiidea/antd-admin/pulls)
+[](https://gitter.im/antd-admin/antd-admin)
+
+
+
+- 在线演示 - [https://antd-admin.zuiidea.com](https://antd-admin.zuiidea.com)
+- 使用文档 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/](https://doc.antd-admin.zuiidea.com/#/zh-cn/)
+- 常见问题 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/faq](https://doc.antd-admin.zuiidea.com/#/zh-cn/faq)
+- 更新日志 - [https://doc.antd-admin.zuiidea.com/#/zh-cn/change-log](https://doc.antd-admin.zuiidea.com/#/zh-cn/change-log)
+
+## 特性
+
+- 国际化,源码中抽离翻译字段,按需加载语言包
+- 动态权限,不同权限对应不同菜单
+- 优雅美观,Ant Design 设计体系
+- Mock 数据,本地数据调试
+
+
+## 使用
+
+1. 下载项目代码。
+
+```bash
+git clone https://github.com/zuiidea/antd-admin.git my-project
+cd my-project
+```
+
+2. 进入目录安装依赖,国内用户推荐使用 [cnpm](https://cnpmjs.org) 进行加速。
+
+```bash
+yarn install
+```
+
+或者
+
+```bash
+npm install
+```
+
+3. 启动本地服务器。
+
+```bash
+npm run start
+```
+
+4. 启动完成后打开浏览器访问 [http://localhost:7000](http://localhost:7000),如果需要更改启动端口,可在 `.env` 文件中配置。
+
+
+> 更多信息请参考 [使用文档](https://doc.antd-admin.zuiidea.com/#/zh-cn/)。
+
+
+## 支持环境
+
+现代浏览器。
+
+| [ ](http://godban.github.io/browsers-support-badges/)IE / Edge | [ ](http://godban.github.io/browsers-support-badges/)Firefox | [ ](http://godban.github.io/browsers-support-badges/)Chrome | [ ](http://godban.github.io/browsers-support-badges/)Safari | [ ](http://godban.github.io/browsers-support-badges/)Opera |
+| --------- | --------- | --------- | --------- | --------- |
+|IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions
+
+## 参与贡献
+
+我们非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :smiley:
+- 在你的公司或个人项目中使用 AntD Admin。
+- 通过 [Issue](http://github.com/zuiidea/antd-admin/issues) 报告 bug 或进行咨询。
+- 提交 [Pull Request](http://github.com/zuiidea/antd-admin/pulls) 改进代码。
+
+> 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。
\ No newline at end of file
diff --git a/docs/zh-cn/_sidebar.md b/docs/zh-cn/_sidebar.md
new file mode 100644
index 0000000..68dc92e
--- /dev/null
+++ b/docs/zh-cn/_sidebar.md
@@ -0,0 +1,11 @@
+- 入门
+ - [快速上手](zh-cn/getting-started.md)
+- 定制化
+ - [配置项](zh-cn/configuration.md)
+ - [接口配置](zh-cn/API-configuration.md)
+ - [国际化](zh-cn/i18n.md)
+ - [布局](zh-cn/layout.md)
+ - [http 请求](zh-cn/request.md)
+- 指南
+ - [部署](zh-cn/deploy.md)
+- [更新日志](zh-cn/change-log.md)
diff --git a/docs/zh-cn/change-log.md b/docs/zh-cn/change-log.md
new file mode 100644
index 0000000..54b0ec6
--- /dev/null
+++ b/docs/zh-cn/change-log.md
@@ -0,0 +1,52 @@
+## 5.0.0
+
+#### 优化
+
+- 尽量使用修饰器,简化代码编写,提高代码可读性。
+
+- API 配置化,简化获取数据方式。
+
+- `utils` 内文件拆分,各司其职。
+
+- 简化`utils/request`文件,不做特殊处理。
+
+#### 规范
+
+- 函数添加描述、参数、返回值等注释,含糊不清的代码增加注释,规范参考 [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html#appendices-jsdoc-tag-reference)。
+
+- 语义化版本号,规范参加 [语义化版本 2.0.0](https://semver.org/lang/zh-CN/)。
+
+- 静态代码检查,统一代码风格,代码提交前将会使用 `prettier`、`stylelint`、`eslint` 规范代码。
+
+- Git 提交信息规范化,[git-commit-emoji-cn](https://github.com/liuchengxu/git-commit-emoji-cn)。
+
+- 基于 `Umi` 的约定式路由,无需再写路由配置文件。
+
+- 使用 `React 16` 新特性,如 `Fragment`、`Context`、 `PureComponent`等。
+
+#### 功能
+
+- 支持国际化,源码中抽离翻译字段,按需加载语言包,自动在线翻译。
+
+- 支持按需引入 `lodash` 函数。
+
+- 支持多布局,可根据规则规定哪些路由使用哪种布局。
+
+- 支持 Antd Admin 在 Travis 上自动编译和部署。
+
+- 使用 `Docsify` 生成文档网站。
+
+
+#### 样式
+
+- 新增 Antd Admin 独立 Logo。
+
+- 重写整体布局组件,优化菜单、面包屑导航自动高亮,菜单自动展开等逻辑。
+
+- 移动端菜单更改为抽屉式。
+
+#### 其他
+
+- 废弃 `IconFont`、 `Search`、`DataTable`等组件,因为在 `Antd` 中有很好的支持和可替代的。
+
+
diff --git a/docs/zh-cn/configuration.md b/docs/zh-cn/configuration.md
new file mode 100644
index 0000000..70f517f
--- /dev/null
+++ b/docs/zh-cn/configuration.md
@@ -0,0 +1,102 @@
+# 配置项
+
+你可以在 `/src/utils/config.js` 里做一些自定义配置:
+
+## siteName
+
+- 类型: `String`
+
+ 配置站点名称,应用到登录框,侧边栏顶部的标题文字显示。
+
+## copyright
+
+- 类型: `String`
+
+ 配置版权声明,应用到登录页、`Primay`布局底部。
+
+## logoPath
+
+- 类型: `String`
+
+ 配置站点 Logo,应用到登录框,侧边栏顶部的 Logo 显示。
+
+## apiPrefix
+
+- 类型: `String`
+
+ 配置项目中接口的前缀,接口相关文档可查看 [接口配置](API-configuration.md)
+
+## fixedHeader
+
+- 类型: `String`
+
+ 在`Primary`布局下,页面滚动时是否固定顶部。
+
+## layouts
+
+- 类型: `Array`
+
+ 配置哪些路由使用哪种布局,未指定路由使用默认布局 `Public`,项目中目前有 `Primary` 和 `Public` 两种布局,
+ 默认配置如下:
+
+ ```javascript
+ layouts: [
+ {
+ name: 'primary',
+ include: [/.*/],
+ exclude: [/(\/(en|zh))*\/login/],
+ },
+ ],
+ ```
+
+ 每种布局的对象属性如下:
+
+ - `name` - 布局的名称;
+
+ - `include` - 指定使用该布局的路由规则列表,规则可为正则表达式或者字符串;
+
+ - `exclude` - 指定不使用该布局的路由规则列表,规则可为正则表达式或者字符串。
+
+ > 注意:`exclude` 优先级高于 `include`,前面的布局优先级高于后面的布局。开发过程中可能需要结合`src/layouts`目录下的布局使用,具体方法可查看 [使用布局](./layout.md)。
+
+## i18n
+
+- 类型: `Object`
+
+ 配置国际化,默认配置如下:
+
+ ```javascript
+ i18n: {
+ languages: [
+ {
+ key: 'en',
+ title: 'English',
+ flag: '/america.svg',
+ },
+ {
+ key: 'zh',
+ title: '中文',
+ flag: '/china.svg',
+ },
+ ],
+ defaultLanguage: 'en',
+ }
+ ```
+
+ ### i18n.languages
+
+ - 类型: `Array`
+
+ 指定应用支持哪些语言,每种语言的对象属性如下:
+
+ - `key` - 语言的`key`,应用到页面 url 上以区分语言,也对应 `src/locales` 目录下的语言包文件夹名;
+
+ - `title` - 语言名称,在登录页底部、`Primay` 布局顶部语言切换显示;
+
+ - `flag` - 语言的国旗图标的路径,在 `Primay` 布局顶部语言切换显示。
+
+ ### i18n.defaultLanguage
+
+ - 类型: `String`
+
+ 配置默认语言。
diff --git a/docs/zh-cn/deploy.md b/docs/zh-cn/deploy.md
new file mode 100644
index 0000000..cdbac06
--- /dev/null
+++ b/docs/zh-cn/deploy.md
@@ -0,0 +1,114 @@
+# 部署
+
+完成开发并且在开发环境验证之后,就需要部署给我们的用户了。
+
+
+
+## 构建
+
+先执行下面的命令,
+
+```bash
+npm run build
+```
+
+几秒后,输出应该如下:
+
+```bash
+> antd-admin@5.0.0-beta build /Users/zuiidea/web/antd-admin
+> umi build
+
+[21:13:17] webpack compiled in 43s 868ms
+ DONE Compiled successfully in 43877ms 21:13:17
+
+File sizes after gzip:
+
+ 1.3 MB dist/vendors.async.js
+ 308.21 KB dist/umi.js
+ 45.49 KB dist/vendors.chunk.css
+ 36.08 KB dist/p__chart__highCharts__index.async.js
+ 33.53 KB dist/p__user__index.async.js
+ 22.36 KB dist/p__chart__ECharts__index.async.js
+ 4.21 KB dist/p__dashboard__index.async.js
+ 4.06 KB dist/umi.css
+ ...
+```
+
+`build` 命令会打包所有的资源,包含 JavaScript, CSS, web fonts, images, html 等。你可以在 `dist/` 目录下找到这些文件。
+
+> 如果有使用 HashHistory 、 部署 html 到非根目录、静态化等需求,请查看[Umi 部署](https://umijs.org/zh/guide/deploy.html)。
+
+## 本地验证
+
+
+发布之前,可以通过 `serve` 做本地验证,
+
+```
+$ yarn global add serve
+$ serve ./dist
+
+Serving!
+
+- Local: http://localhost:5000
+- On Your Network: http://{Your IP}:5000
+
+Copied local address to clipboard!
+
+```
+
+访问 [http://localhost:5000](http://localhost:5000),正常情况下法应该是和 `npm start` 一致的(接口可能无法获取到正确数据)。
+
+
+## 部署
+
+接下来,我们可以把静态文件上传到服务器,如果使用 Nginx 作为 Web server,你可以在 `ngnix.conf` 中这样配置:
+
+```
+server
+ {
+ listen 80;
+ # 指定可访问的域名
+ server_name antd-admin.zuiidea.com;
+ # 编译后的文件存放的目录
+ root /home/www/antd-admin/dist;
+
+ # 代理服务端接口,避免跨域
+ location /api {
+ proxy_pass http://localhost:7000/api;
+ }
+
+ # 因为前端使用了BrowserHistory,所以将路由 fallback 到 index.html
+ location / {
+ index index.html;
+ try_files $uri $uri/ /index.html;
+ }
+ }
+```
+
+重启 Web server,访问 [http://antd-admin.zuiidea.com](http://antd-admin.zuiidea.com) ,你将看到正确的页面。
+
+```bash
+nginx -s reload
+```
+
+类似的,如果你使用 Caddy 作为 Web server,你可以在 `Caddyfile` 中这样配置:
+
+```
+antd-admin.zuiidea.com {
+ gzip
+ root /home/www/antd-admin/dist
+ proxy /api http://localhost:7000
+
+ rewrite {
+ if {path} not_match ^/api
+ to {path} {path}/ /
+ }
+}
+
+
+antd-admin.zuiidea.com/public {
+ gzip
+ root /home/www/antd-admin/dist/static/public
+}
+
+```
diff --git a/docs/zh-cn/faq.md b/docs/zh-cn/faq.md
new file mode 100644
index 0000000..bf5f1bd
--- /dev/null
+++ b/docs/zh-cn/faq.md
@@ -0,0 +1,7 @@
+# 问题集锦
+
+## 新建页面
+
+ 1. 直接从/src/pages复制一个page (会自动创建路由[umi](https://umijs.org/zh/guide/router.html#%E7%BA%A6%E5%AE%9A%E5%BC%8F%E8%B7%AF%E7%94%B1))
+ 2. 修改 namespace/pathToRegexp 在 model.js
+ 3. 修改 mock中route.js增加一条route
\ No newline at end of file
diff --git a/docs/zh-cn/getting-started.md b/docs/zh-cn/getting-started.md
new file mode 100644
index 0000000..b9d1183
--- /dev/null
+++ b/docs/zh-cn/getting-started.md
@@ -0,0 +1,73 @@
+# 快速上手
+
+> 在开始之前,推荐先学习 [React](http://facebook.github.io/react/) 、 [ES2015+](http://es6.ruanyifeng.com/) 、 [Antd Design](https://ant.design/docs/react/introduce-cn) , 了解 [UmiJS](https://umijs.org/) 、[Dva](http://github.com/dvajs/dva) ,并正确安装和配置了 [Node.js](https://nodejs.org/) v8 或以上 、[Git](https://git-scm.com/)。提前了解和学习这些知识会非常有帮助。
+
+## 安装
+
+```bash
+git clone https://github.com/zuiidea/antd-admin.git my-project
+cd my-project
+```
+
+## 目录结构
+
+应用的目录结构如下
+
+```bash
+├── dist/ # 默认build输出目录
+├── mock/ # Mock文件目录
+├── public/ # 静态资源文件目录
+├── src/ # 源码目录
+│ ├── components/ # 组件目录
+│ ├── e2e/ # e2e目录
+│ ├── layouts/ # 布局目录
+│ ├── locales/ # 国际化文件目录
+│ ├── models/ # 数据模型目录
+│ ├── pages/ # 页面组件目录
+│ ├── services/ # 数据接口目录
+│ │ ├── api.js # 接口配置
+│ │ └── index.js # 接口输出
+│ ├── themes/ # 项目样式目录
+│ │ ├── default.less # 样式变量
+│ │ ├── index.less # 全局样式
+│ │ ├── mixin.less # 样式函数
+│ │ └── vars.less # 样式变量及函数
+│ ├── utils/ # 工具函数目录
+│ │ ├── config.js # 项目配置
+│ │ ├── constant.js # 静态常量
+│ │ ├── index.js # 工具函数
+│ │ ├── request.js # 异步请求函数(axios)
+│ │ └── theme.js # 项目需要在js中使用到样式变量
+├── .editorconfig # 编辑器配置
+├── .env # 环境变量
+├── .eslintrc # ESlint配置
+├── .gitignore # Git忽略文件配置
+├── .prettierignore # Prettier忽略文件配置
+├── .prettierrc # Prettier配置
+├── .stylelintrc.json # Stylelint配置
+├── .travis.yml # Travis配置
+└── .umirc.js # Umi配置
+└── package.json # 项目信息
+```
+
+## 本地开发
+
+1. 进入目录安装依赖,国内用户推荐使用 [cnpm](https://cnpmjs.org) 进行加速
+
+```bash
+yarn install
+```
+
+或者
+
+```bash
+npm install
+```
+
+2. 启动本地服务器
+
+```bash
+npm run start
+```
+
+3. 启动完成后打开浏览器访问 [http://localhost:7000](http://localhost:7000),如果需要更改启动端口,可在 `.env` 文件中配置。
diff --git a/docs/zh-cn/i18n.md b/docs/zh-cn/i18n.md
new file mode 100644
index 0000000..33244d6
--- /dev/null
+++ b/docs/zh-cn/i18n.md
@@ -0,0 +1,75 @@
+# 国际化
+
+## 新增应用语言
+
+以新增日语为例。
+
+
+
+1. 添加语言包本地文件,`ja` 为日语的语言代码,支持翻译的语言列表参考 [有道智云](http://ai.youdao.com/docs/doc-trans-api.s#p05),运行下面命令后会生成 `src/locales/ja/messages.json` 文件。
+
+ ```bash
+ npm run add-locale ja
+ ```
+
+2. 提取代码中需要翻译的字段,即 `message `、`` intl.formatMessage({ id: 'message `` 中 `message` 字段,运行下面命令后 `src/locales/ja/messages.json' }) 将会出现提取后的字段配置。
+
+ ```bash
+ npm run extract
+ ```
+
+ 你将看到如下信息:
+
+ ```bash
+ Catalog statistics:
+ ┌─────────────┬─────────────┬─────────┐
+ │ Language │ Total count │ Missing │
+ ├─────────────┼─────────────┼─────────┤
+ │ en (source) │ 52 │ - │
+ │ ja │ 52 │ 52 │
+ │ zh │ 52 │ 0 │
+ └─────────────┴─────────────┴─────────┘
+ ```
+
+3. 与此同时,我们在 `src/utils/config.js` 新增相关配置。
+
+ ```javascript
+ {
+ ...
+ i18n: {
+ languages: [
+ ...
+ {
+ key:'ja',
+ title: '日本語',
+ flag: '/japanese.svg',
+ },
+ ],
+ },
+ }
+ ```
+
+ > 路由相关效果,配置后 `npm run start` 重启后生效。
+
+4. 使用内置的命令进行自动翻译,在 `src/locales/ja/messages.json` 中将会看到翻译后的配置。
+
+ ```bash
+ npm run trans:only
+ ```
+
+ 你将看到如下信息:
+
+ ```bash
+ start: en -> ja
+ ...
+ youdao: en -> ja: Unpublished -> 未発表
+ youdao: en -> ja: Update -> 更新
+ youdao: en -> ja: Update User -> ユーザーの更新
+ youdao: en -> ja: Username -> 名
+ ...
+ All translations have been completed.
+ ```
+
+ > `npm run trans` 将会依次执行 `npm run extract` 和 `npm run trans:only`
+
+5. 最后,可以在 `src/locales/ja/messages.json` 中对翻译不准确的的字段进行调整。启动开发模式 `npm run start`,打开 [http://localhost:7000/ja/login](http://localhost:7000/ja/login),你将看到日语版本的应用。
diff --git a/docs/zh-cn/layout.md b/docs/zh-cn/layout.md
new file mode 100644
index 0000000..f3a39e7
--- /dev/null
+++ b/docs/zh-cn/layout.md
@@ -0,0 +1,60 @@
+# 布局
+
+## 新增布局
+
+以新增名为 `secondary` 的布局为例,使以 `secondary` 开头的路由都使用该布局。
+
+1. 在 `src/utils/config.js` 新增相关配置,参数详细请查看 [layouts](/zh-cn/configuration?id=layouts)。
+
+ ```javascript
+ layouts: [
+ {
+ name: 'primary',
+ include: [/.*/],
+ exclude: [/(\/(en|zh))*\/login/, /(\/(en|zh))*\/secondary\/(.*)/],
+ },
+ {
+ name: 'secondary',
+ include: [/(\/(en|zh))*\/secondary\/(.*)/],
+ },
+ ],
+ ```
+
+2. 在`src/layouts/BaseLayout.js` 文件中新增 `secondary` 布局组件。
+
+ ```javascript
+ import SecondaryLayout from './SecondaryLayout'
+
+ const LayoutMap = {
+ primary: PrimaryLayout,
+ public: PublicLayout,
+ secondary: SecondaryLayout,
+ }
+ ```
+
+3. 在`src/layouts/` 目录中新增 `SecondaryLayout.js` 文件。
+
+ ```javascript
+ import React from 'react'
+
+ export default ({ children }) => {
+ return (
+
+
Secondary
+ {children}
+
+ )
+ }
+ ```
+
+4. 在`src/pages/` 目录中新增 `secondary/index.js` 文件。
+
+ ```javascript
+ import React from 'react'
+
+ export default ({ children }) => {
+ return Secondary page Content
+ }
+ ```
+
+5. 最后,启动开发模式 `npm run start`,打开 [http://localhost:7000/secondary/](http://localhost:7000/secondary/),你将看到 `secondary` 布局的页面。
diff --git a/docs/zh-cn/request.md b/docs/zh-cn/request.md
new file mode 100644
index 0000000..a87022c
--- /dev/null
+++ b/docs/zh-cn/request.md
@@ -0,0 +1,24 @@
+# HTTP请求
+
+本项目使用了axios提供http请求服务,文件在src/utils/request.js
+
+## 自定义Header
+
+为了提供鉴权、修改cookie等服务,可以手动修改Header
+
+```
+axios.defaults.headers.common['Authorization'] = 'token'
+```
+
+或者
+
+```
+// 添加请求拦截器
+axios.interceptors.request.use(function (config) {
+ // 在发送请求之前做些什么
+ config.headers.token = window.localStorage.getItem('token');
+ return config;
+}, function (error) {
+ return Promise.reject(error);
+});
+```
\ No newline at end of file
diff --git a/docs/zh-cn/router.md b/docs/zh-cn/router.md
new file mode 100644
index 0000000..f511c2e
--- /dev/null
+++ b/docs/zh-cn/router.md
@@ -0,0 +1,5 @@
+# 路由
+
+本项目中采用约定式路由
+
+参考[umi 路由](https://umijs.org/zh/guide/router.html)
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..c52ac83
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ testURL: 'http://localhost:8000',
+}
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..3316983
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,36 @@
+{
+ "name": "Antd-Admin",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#fff",
+ "description": "A front-end solution for enterprise applications built upon Ant Design and UmiJS",
+ "icons": [{
+ "src": "logo/logo@96.png",
+ "sizes": "72x72"
+ },
+ {
+ "src": "logo/logo@128.png",
+ "sizes": "128x128"
+ },
+ {
+ "src": "logo/logo@144.png",
+ "sizes": "144x144"
+ },
+ {
+ "src": "logo/logo@152.png",
+ "sizes": "152x152"
+ },
+ {
+ "src": "logo/logo@192.png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "logo/logo@384.png",
+ "sizes": "384x384"
+ },
+ {
+ "src": "logo/logo@512.png",
+ "sizes": "512x512"
+ }
+ ]
+}
diff --git a/mock/_utils.js b/mock/_utils.js
new file mode 100644
index 0000000..2229c12
--- /dev/null
+++ b/mock/_utils.js
@@ -0,0 +1,59 @@
+/**
+ * Query objects that specify keys and values in an array where all values are objects.
+ * @param {array} array An array where all values are objects, like [{key:1},{key:2}].
+ * @param {string} key The key of the object that needs to be queried.
+ * @param {string} value The value of the object that needs to be queried.
+ * @return {object|undefined} Return frist object when query success.
+ */
+export function queryArray(array, key, value) {
+ if (!Array.isArray(array)) {
+ return
+ }
+ return array.filter(_ => _[key] === value)
+}
+
+export function randomNumber(min, max) {
+ return Math.floor(Math.random() * (max - min) + min)
+}
+
+export function randomAvatar() {
+ const avatarList = [
+ 'photo-1549492864-2ec7d66ffb04.jpeg',
+ 'photo-1480535339474-e083439a320d.jpeg',
+ 'photo-1523419409543-a5e549c1faa8.jpeg',
+ 'photo-1519648023493-d82b5f8d7b8a.jpeg',
+ 'photo-1523307730650-594bc63f9d67.jpeg',
+ 'photo-1522962506050-a2f0267e4895.jpeg',
+ 'photo-1489779162738-f81aed9b0a25.jpeg',
+ 'photo-1534308143481-c55f00be8bd7.jpeg',
+ 'photo-1519336555923-59661f41bb45.jpeg',
+ 'photo-1551438632-e8c7d9a5d1b7.jpeg',
+ 'photo-1525879000488-bff3b1c387cf.jpeg',
+ 'photo-1487412720507-e7ab37603c6f.jpeg',
+ 'photo-1510227272981-87123e259b17.jpeg'
+ ]
+ return `//image.zuiidea.com/${avatarList[randomNumber(0, avatarList.length - 1)]}?imageView2/1/w/200/h/200/format/webp/q/75|imageslim`
+}
+
+export const Constant = {
+ ApiPrefix: '/api/v1',
+ NotFound: {
+ message: 'Not Found',
+ documentation_url: '',
+ },
+ Color: {
+ green: '#64ea91',
+ blue: '#8fc9fb',
+ purple: '#d897eb',
+ red: '#f69899',
+ yellow: '#f8c82e',
+ peach: '#f797d6',
+ borderBase: '#e5e5e5',
+ borderSplit: '#f4f4f4',
+ grass: '#d6fbb5',
+ sky: '#c1e0fc',
+ },
+}
+
+export Mock from 'mockjs'
+export qs from 'qs'
diff --git a/mock/dashboard.js b/mock/dashboard.js
new file mode 100644
index 0000000..8758594
--- /dev/null
+++ b/mock/dashboard.js
@@ -0,0 +1,142 @@
+import { Mock, Constant } from './_utils'
+
+const { ApiPrefix, Color } = Constant
+
+const Dashboard = Mock.mock({
+ 'sales|8': [
+ {
+ 'name|+1': 2008,
+ 'Clothes|200-500': 1,
+ 'Food|180-400': 1,
+ 'Electronics|300-550': 1,
+ },
+ ],
+ cpu: {
+ 'usage|50-600': 1,
+ space: 825,
+ 'cpu|40-90': 1,
+ 'data|20': [
+ {
+ 'cpu|20-80': 1,
+ },
+ ],
+ },
+ browser: [
+ {
+ name: 'Google Chrome',
+ percent: 43.3,
+ status: 1,
+ },
+ {
+ name: 'Mozilla Firefox',
+ percent: 33.4,
+ status: 2,
+ },
+ {
+ name: 'Apple Safari',
+ percent: 34.6,
+ status: 3,
+ },
+ {
+ name: 'Internet Explorer',
+ percent: 12.3,
+ status: 4,
+ },
+ {
+ name: 'Opera Mini',
+ percent: 3.3,
+ status: 1,
+ },
+ {
+ name: 'Chromium',
+ percent: 2.53,
+ status: 1,
+ },
+ ],
+ user: {
+ name: 'github',
+ sales: 3241,
+ sold: 3556,
+ },
+ 'completed|12': [
+ {
+ 'name|+1': 2008,
+ 'Task complete|200-1000': 1,
+ 'Cards Complete|200-1000': 1,
+ },
+ ],
+ 'comments|5': [
+ {
+ name: '@last',
+ 'status|1-3': 1,
+ content: '@sentence',
+ avatar() {
+ return Mock.Random.image(
+ '48x48',
+ Mock.Random.color(),
+ '#757575',
+ 'png',
+ this.name.substr(0, 1)
+ )
+ },
+ date() {
+ return `2016-${Mock.Random.date('MM-dd')} ${Mock.Random.time(
+ 'HH:mm:ss'
+ )}`
+ },
+ },
+ ],
+ 'recentSales|36': [
+ {
+ 'id|+1': 1,
+ name: '@last',
+ 'status|1-4': 1,
+ date() {
+ return `${Mock.Random.integer(2015, 2016)}-${Mock.Random.date(
+ 'MM-dd'
+ )} ${Mock.Random.time('HH:mm:ss')}`
+ },
+ 'price|10-200.1-2': 1,
+ },
+ ],
+ quote: {
+ name: 'Joho Doe',
+ title: 'Graphic Designer',
+ content:
+ "I'm selfish, impatient and a little insecure. I make mistakes, I am out of control and at times hard to handle. But if you can't handle me at my worst, then you sure as hell don't deserve me at my best.",
+ avatar:
+ '//cdn.antd-admin.zuiidea.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236',
+ },
+ numbers: [
+ {
+ icon: 'pay-circle-o',
+ color: Color.green,
+ title: 'Online Review',
+ number: 2781,
+ },
+ {
+ icon: 'team',
+ color: Color.blue,
+ title: 'New Customers',
+ number: 3241,
+ },
+ {
+ icon: 'message',
+ color: Color.purple,
+ title: 'Active Projects',
+ number: 253,
+ },
+ {
+ icon: 'shopping-cart',
+ color: Color.red,
+ title: 'Referrals',
+ number: 4324,
+ },
+ ],
+})
+
+module.exports = {
+ [`GET ${ApiPrefix}/dashboard`](req, res) {
+ res.json(Dashboard)
+ },
+}
diff --git a/mock/post.js b/mock/post.js
new file mode 100644
index 0000000..e8e0d7c
--- /dev/null
+++ b/mock/post.js
@@ -0,0 +1,67 @@
+import { Mock, Constant } from './_utils'
+
+const { ApiPrefix } = Constant
+
+let postId = 0
+const database = Mock.mock({
+ 'data|100': [
+ {
+ id() {
+ postId += 1
+ return postId + 10000
+ },
+ 'status|1-2': 1,
+ title: '@title',
+ author: '@last',
+ categories: '@word',
+ tags: '@word',
+ 'views|10-200': 1,
+ 'comments|10-200': 1,
+ visibility: () => {
+ return Mock.mock(
+ '@pick(["Public",' + '"Password protected", ' + '"Private"])'
+ )
+ },
+ date: '@dateTime',
+ image() {
+ return Mock.Random.image(
+ '100x100',
+ Mock.Random.color(),
+ '#757575',
+ 'png',
+ this.author.substr(0, 1)
+ )
+ },
+ },
+ ],
+}).data
+
+module.exports = {
+ [`GET ${ApiPrefix}/posts`](req, res) {
+ const { query } = req
+ let { pageSize, page, ...other } = query
+ pageSize = pageSize || 10
+ page = page || 1
+
+ let newData = database
+ for (let key in other) {
+ if ({}.hasOwnProperty.call(other, key)) {
+ newData = newData.filter(item => {
+ if ({}.hasOwnProperty.call(item, key)) {
+ return (
+ String(item[key])
+ .trim()
+ .indexOf(decodeURI(other[key]).trim()) > -1
+ )
+ }
+ return true
+ })
+ }
+ }
+
+ res.status(200).json({
+ data: newData.slice((page - 1) * pageSize, page * pageSize),
+ total: newData.length,
+ })
+ },
+}
diff --git a/mock/route.js b/mock/route.js
new file mode 100644
index 0000000..fb0456b
--- /dev/null
+++ b/mock/route.js
@@ -0,0 +1,155 @@
+import { Constant } from './_utils'
+const { ApiPrefix } = Constant
+
+const database = [
+ {
+ id: '1',
+ icon: 'dashboard',
+ name: 'Dashboard',
+ zh: {
+ name: '仪表盘'
+ },
+ 'pt-br': {
+ name: 'Dashboard'
+ },
+ route: '/dashboard',
+ },
+ {
+ id: '2',
+ breadcrumbParentId: '1',
+ name: 'Users',
+ zh: {
+ name: '用户管理'
+ },
+ 'pt-br': {
+ name: 'Usuário'
+ },
+ icon: 'user',
+ route: '/user',
+ },
+ {
+ id: '7',
+ breadcrumbParentId: '1',
+ name: 'Posts',
+ zh: {
+ name: '用户管理'
+ },
+ 'pt-br': {
+ name: 'Posts'
+ },
+ icon: 'shopping-cart',
+ route: '/post',
+ },
+ {
+ id: '21',
+ menuParentId: '-1',
+ breadcrumbParentId: '2',
+ name: 'User Detail',
+ zh: {
+ name: '用户详情'
+ },
+ 'pt-br': {
+ name: 'Detalhes do usuário'
+ },
+ route: '/user/:id',
+ },
+ {
+ id: '3',
+ breadcrumbParentId: '1',
+ name: 'Request',
+ zh: {
+ name: 'Request'
+ },
+ 'pt-br': {
+ name: 'Requisição'
+ },
+ icon: 'api',
+ route: '/request',
+ },
+ {
+ id: '4',
+ breadcrumbParentId: '1',
+ name: 'UI Element',
+ zh: {
+ name: 'UI组件'
+ },
+ 'pt-br': {
+ name: 'Elementos UI'
+ },
+ icon: 'camera-o',
+ },
+ {
+ id: '45',
+ breadcrumbParentId: '4',
+ menuParentId: '4',
+ name: 'Editor',
+ zh: {
+ name: 'Editor'
+ },
+ 'pt-br': {
+ name: 'Editor'
+ },
+ icon: 'edit',
+ route: '/editor',
+ },
+ {
+ id: '5',
+ breadcrumbParentId: '1',
+ name: 'Charts',
+ zh: {
+ name: 'Charts'
+ },
+ 'pt-br': {
+ name: 'Graficos'
+ },
+ icon: 'code-o',
+ },
+ {
+ id: '51',
+ breadcrumbParentId: '5',
+ menuParentId: '5',
+ name: 'ECharts',
+ zh: {
+ name: 'ECharts'
+ },
+ 'pt-br': {
+ name: 'ECharts'
+ },
+ icon: 'line-chart',
+ route: '/chart/ECharts',
+ },
+ {
+ id: '52',
+ breadcrumbParentId: '5',
+ menuParentId: '5',
+ name: 'HighCharts',
+ zh: {
+ name: 'HighCharts'
+ },
+ 'pt-br': {
+ name: 'HighCharts'
+ },
+ icon: 'bar-chart',
+ route: '/chart/highCharts',
+ },
+ {
+ id: '53',
+ breadcrumbParentId: '5',
+ menuParentId: '5',
+ name: 'Rechartst',
+ zh: {
+ name: 'Rechartst'
+ },
+ 'pt-br': {
+ name: 'Rechartst'
+ },
+ icon: 'area-chart',
+ route: '/chart/Recharts',
+ },
+]
+
+module.exports = {
+ [`GET ${ApiPrefix}/routes`](req, res) {
+ res.status(200).json(database)
+ },
+}
diff --git a/mock/user.js b/mock/user.js
new file mode 100644
index 0000000..4ffd4d3
--- /dev/null
+++ b/mock/user.js
@@ -0,0 +1,250 @@
+import { Mock, Constant, randomAvatar } from './_utils'
+import qs from 'qs'
+
+const { ApiPrefix } = Constant
+
+let usersListData = Mock.mock({
+ 'data|80-100': [
+ {
+ id: '@id',
+ name: '@name',
+ nickName: '@last',
+ phone: /^1[34578]\d{9}$/,
+ 'age|11-99': 1,
+ address: '@county(true)',
+ isMale: '@boolean',
+ email: '@email',
+ createTime: '@datetime',
+ avatar() {
+ return randomAvatar()
+ },
+ },
+ ],
+})
+
+let database = usersListData.data
+
+const EnumRoleType = {
+ ADMIN: 'admin',
+ DEFAULT: 'guest',
+ DEVELOPER: 'developer',
+}
+
+const userPermission = {
+ DEFAULT: {
+ visit: ['1', '2', '21', '7', '5', '51', '52', '53'],
+ role: EnumRoleType.DEFAULT,
+ },
+ ADMIN: {
+ role: EnumRoleType.ADMIN,
+ },
+ DEVELOPER: {
+ role: EnumRoleType.DEVELOPER,
+ },
+}
+
+const adminUsers = [
+ {
+ id: 0,
+ username: 'admin',
+ password: 'admin',
+ permissions: userPermission.ADMIN,
+ avatar: randomAvatar(),
+ },
+ {
+ id: 1,
+ username: 'guest',
+ password: 'guest',
+ permissions: userPermission.DEFAULT,
+ avatar: randomAvatar(),
+ },
+ {
+ id: 2,
+ username: '吴彦祖',
+ password: '123456',
+ permissions: userPermission.DEVELOPER,
+ avatar: randomAvatar(),
+ },
+]
+
+const queryArray = (array, key, keyAlias = 'key') => {
+ if (!(array instanceof Array)) {
+ return null
+ }
+ let data
+
+ for (let item of array) {
+ if (item[keyAlias] === key) {
+ data = item
+ break
+ }
+ }
+
+ if (data) {
+ return data
+ }
+ return null
+}
+
+const NOTFOUND = {
+ message: 'Not Found',
+ documentation_url: 'http://localhost:8000/request',
+}
+
+module.exports = {
+ [`POST ${ApiPrefix}/user/login`](req, res) {
+ const { username, password } = req.body
+ const user = adminUsers.filter(item => item.username === username)
+
+ if (user.length > 0 && user[0].password === password) {
+ const now = new Date()
+ now.setDate(now.getDate() + 1)
+ res.cookie(
+ 'token',
+ JSON.stringify({ id: user[0].id, deadline: now.getTime() }),
+ {
+ maxAge: 900000,
+ httpOnly: true,
+ }
+ )
+ res.json({ success: true, message: 'Ok' })
+ } else {
+ res.status(400).end()
+ }
+ },
+
+ [`GET ${ApiPrefix}/user/logout`](req, res) {
+ res.clearCookie('token')
+ res.status(200).end()
+ },
+
+ [`GET ${ApiPrefix}/user`](req, res) {
+ const cookie = req.headers.cookie || ''
+ const cookies = qs.parse(cookie.replace(/\s/g, ''), { delimiter: ';' })
+ const response = {}
+ let user = {}
+ if (!cookies.token) {
+ res.status(200).send({ message: 'Not Login' })
+ return
+ }
+ const token = JSON.parse(cookies.token)
+ if (token) {
+ response.success = token.deadline > new Date().getTime()
+ }
+ if (response.success) {
+ const userItem = adminUsers.find(_ => _.id === token.id)
+ if (userItem) {
+ const { password, ...other } = userItem
+ user = other
+ }
+ }
+ response.user = user
+ res.json(response)
+ },
+
+ [`GET ${ApiPrefix}/users`](req, res) {
+ const { query } = req
+ let { pageSize, page, ...other } = query
+ pageSize = pageSize || 10
+ page = page || 1
+
+ let newData = database
+ for (let key in other) {
+ if ({}.hasOwnProperty.call(other, key)) {
+ newData = newData.filter(item => {
+ if ({}.hasOwnProperty.call(item, key)) {
+ if (key === 'address') {
+ return other[key].every(iitem => item[key].indexOf(iitem) > -1)
+ } else if (key === 'createTime') {
+ const start = new Date(other[key][0]).getTime()
+ const end = new Date(other[key][1]).getTime()
+ const now = new Date(item[key]).getTime()
+
+ if (start && end) {
+ return now >= start && now <= end
+ }
+ return true
+ }
+ return (
+ String(item[key])
+ .trim()
+ .indexOf(decodeURI(other[key]).trim()) > -1
+ )
+ }
+ return true
+ })
+ }
+ }
+
+ res.status(200).json({
+ data: newData.slice((page - 1) * pageSize, page * pageSize),
+ total: newData.length,
+ })
+ },
+
+ [`POST ${ApiPrefix}/users/delete`](req, res) {
+ const { ids=[] } = req.body
+ database = database.filter(item => !ids.some(_ => _ === item.id))
+ res.status(204).end()
+ },
+
+ [`POST ${ApiPrefix}/user`](req, res) {
+ const newData = req.body
+ newData.createTime = Mock.mock('@now')
+ newData.avatar =
+ newData.avatar ||
+ Mock.Random.image(
+ '100x100',
+ Mock.Random.color(),
+ '#757575',
+ 'png',
+ newData.nickName.substr(0, 1)
+ )
+ newData.id = Mock.mock('@id')
+
+ database.unshift(newData)
+
+ res.status(200).end()
+ },
+
+ [`GET ${ApiPrefix}/user/:id`](req, res) {
+ const { id } = req.params
+ const data = queryArray(database, id, 'id')
+ if (data) {
+ res.status(200).json(data)
+ } else {
+ res.status(200).json(NOTFOUND)
+ }
+ },
+
+ [`DELETE ${ApiPrefix}/user/:id`](req, res) {
+ const { id } = req.params
+ const data = queryArray(database, id, 'id')
+ if (data) {
+ database = database.filter(item => item.id !== id)
+ res.status(204).end()
+ } else {
+ res.status(200).json(NOTFOUND)
+ }
+ },
+
+ [`PATCH ${ApiPrefix}/user/:id`](req, res) {
+ const { id } = req.params
+ const editItem = req.body
+ let isExist = false
+
+ database = database.map(item => {
+ if (item.id === id) {
+ isExist = true
+ return Object.assign({}, item, editItem)
+ }
+ return item
+ })
+
+ if (isExist) {
+ res.status(201).end()
+ } else {
+ res.status(200).json(NOTFOUND)
+ }
+ },
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..4b1c72b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,129 @@
+{
+ "name": "antd-admin",
+ "version": "5.3.0",
+ "license": "MIT",
+ "description": "An admin dashboard application demo built upon Ant Design and UmiJS",
+ "dependencies": {
+ "@ant-design/icons": "^4.6.2",
+ "@lingui/react": "^3.8.0",
+ "antd": "^4.0.0",
+ "axios": "^0.21.0",
+ "classnames": "^2.2.6",
+ "d3-shape": "^2.1.0",
+ "draft-js": "^0.11.7",
+ "draftjs-to-html": "^0.9.0",
+ "draftjs-to-markdown": "^0.6.0",
+ "dva-model-extend": "^0.1.2",
+ "echarts": "^5.0.0",
+ "echarts-for-react": "^3.0.0",
+ "echarts-gl": "^2.0.2",
+ "echarts-liquidfill": "^3.0.0",
+ "enquire-js": "^0.2.1",
+ "highcharts-exporting": "^0.1.7",
+ "highcharts-more": "^0.1.7",
+ "json-format": "^1.0.1",
+ "lodash": "^4.17.11",
+ "md5": "^2.2.1",
+ "nprogress": "^0.2.0",
+ "path-to-regexp": "^6.1.0",
+ "prop-types": "^15.7.0",
+ "qs": "^6.10.0",
+ "react-adsense": "^0.1.0",
+ "react-countup": "^4.2.0",
+ "react-draft-wysiwyg": "^1.13.0",
+ "react-helmet": "^6.0.0",
+ "react-highcharts": "^16.1.0",
+ "react-perfect-scrollbar": "^1.5.0",
+ "recharts": "^2.0.0",
+ "store": "^2.0.0"
+ },
+ "devDependencies": {
+ "@babel/preset-react": "^7.12.13",
+ "@lingui/cli": "^3.8.0",
+ "@lingui/macro": "^3.8.0",
+ "@umijs/preset-react": "^1.8.0",
+ "babel-eslint": "^10.0.0",
+ "babel-plugin-dev-expression": "^0.2.0",
+ "babel-plugin-import": "^1.13.0",
+ "babel-plugin-macros": "^3.0.0",
+ "babel-plugin-module-resolver": "^4.0.0",
+ "cross-env": "^7.0.0",
+ "eslint": "^7.0.0",
+ "eslint-config-react-app": "^6.0.0",
+ "eslint-plugin-flowtype": "^5.1.0",
+ "eslint-plugin-import": "^2.18.0",
+ "eslint-plugin-jsx-a11y": "^6.2.1",
+ "eslint-plugin-react": "^7.23.0",
+ "eslint-plugin-react-hooks": "^4.0.0",
+ "husky": "^4.2.0",
+ "less-vars-to-js": "^1.3.0",
+ "lint-staged": "^10.0.0",
+ "mockjs": "^1.1.0",
+ "module": "^1.2.5",
+ "prettier": "^2.0.0",
+ "stylelint": "^13.2.0",
+ "stylelint-config-prettier": "^8.0.0",
+ "stylelint-config-standard": "^21.0.0",
+ "typescript": "^4.2.3",
+ "umi": "^3.4.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "lint-staged": {
+ "src/**/*.js": [
+ "eslint --ext .js --fix",
+ "npm run prettier",
+ "git add"
+ ],
+ "**/*.less": [
+ "stylelint --syntax less",
+ "npm run prettier",
+ "git add"
+ ]
+ },
+ "lingui": {
+ "fallbackLocales": {
+ "default": "en"
+ },
+ "sourceLocale": "en",
+ "locales": [
+ "en",
+ "zh",
+ "pt-br"
+ ],
+ "catalogs": [
+ {
+ "path": "src/locales/{locale}/messages",
+ "include": [
+ "src/pages",
+ "src/layouts",
+ "src/components",
+ "src/layouts"
+ ]
+ }
+ ],
+ "format": "minimal",
+ "extractBabelOptions": {
+ "presets": [
+ "@umijs/babel-preset-umi",
+ "@babel/preset-react"
+ ]
+ }
+ },
+ "scripts": {
+ "analyze": "cross-env ANALYZE=1 umi build",
+ "build": "umi build",
+ "check:model": "umi dva list model",
+ "lint:js": "eslint --ext .js src",
+ "lint:style": "stylelint \"src/**/*.less\" --syntax less",
+ "start": "umi dev",
+ "test": "cross-env BABELRC=none umi test",
+ "prettier": "prettier --write 'src/**/*.{js,less}'",
+ "precommit": "lint-staged",
+ "add-locale": "lingui add-locale",
+ "extract": "lingui extract",
+ "trans": "lingui extract --clean && node ./scripts/translate.js",
+ "doc": "docsify serve docs"
+ }
+}
diff --git a/public/america.svg b/public/america.svg
new file mode 100644
index 0000000..706cc00
--- /dev/null
+++ b/public/america.svg
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/china.svg b/public/china.svg
new file mode 100644
index 0000000..709a1fe
--- /dev/null
+++ b/public/china.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..7ca2170
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/logo.svg b/public/logo.svg
new file mode 100644
index 0000000..ce7afe5
--- /dev/null
+++ b/public/logo.svg
@@ -0,0 +1,24 @@
+
+
+
+ Created with Sketch.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/logo/logo@128.png b/public/logo/logo@128.png
new file mode 100755
index 0000000..5e218d8
Binary files /dev/null and b/public/logo/logo@128.png differ
diff --git a/public/logo/logo@144.png b/public/logo/logo@144.png
new file mode 100755
index 0000000..347e0df
Binary files /dev/null and b/public/logo/logo@144.png differ
diff --git a/public/logo/logo@152.png b/public/logo/logo@152.png
new file mode 100755
index 0000000..900dc3c
Binary files /dev/null and b/public/logo/logo@152.png differ
diff --git a/public/logo/logo@192.png b/public/logo/logo@192.png
new file mode 100755
index 0000000..342ab1e
Binary files /dev/null and b/public/logo/logo@192.png differ
diff --git a/public/logo/logo@384.png b/public/logo/logo@384.png
new file mode 100755
index 0000000..c487f36
Binary files /dev/null and b/public/logo/logo@384.png differ
diff --git a/public/logo/logo@512.png b/public/logo/logo@512.png
new file mode 100755
index 0000000..c2b44dc
Binary files /dev/null and b/public/logo/logo@512.png differ
diff --git a/public/logo/logo@72.png b/public/logo/logo@72.png
new file mode 100755
index 0000000..126e5ef
Binary files /dev/null and b/public/logo/logo@72.png differ
diff --git a/public/logo/logo@96.png b/public/logo/logo@96.png
new file mode 100755
index 0000000..de9a9fb
Binary files /dev/null and b/public/logo/logo@96.png differ
diff --git a/public/portugal.svg b/public/portugal.svg
new file mode 100644
index 0000000..1e8ffbb
--- /dev/null
+++ b/public/portugal.svg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scripts/translate.js b/scripts/translate.js
new file mode 100644
index 0000000..b2d9444
--- /dev/null
+++ b/scripts/translate.js
@@ -0,0 +1,114 @@
+/**
+ * Youdao Translate, My private account is for testing purposes only.
+ * Please go to the official account to apply for an account. Thank you for your cooperation.
+ * APP ID:055c2d71f9a05214
+ * Secret key:ZcpuQxQW3NkQeKVkqrXIKQYXH57g2KuN
+ */
+
+/* eslint-disable */
+const md5 = require('md5')
+const qs = require('qs')
+const fs = require('fs')
+const path = require('path')
+const axios = require('axios')
+const jsonFormat = require('json-format')
+const { i18n } = require('../src/utils/config')
+const { languages, defaultLanguage } = i18n
+
+const locales = {}
+
+languages.forEach(item => {
+ locales[item.key] = require(`../src/locales/${item.key}/messages.json`)
+})
+
+const youdao = ({ q, from, to }) =>
+ new Promise((resolve, reject) => {
+ {
+ const appid = '055c2d71f9a05214'
+ const appse = 'ZcpuQxQW3NkQeKVkqrXIKQYXH57g2KuN'
+ const salt = Date.now()
+
+ const sign = md5(appid + q + salt + appse)
+ const query = qs.stringify({
+ q,
+ from,
+ to,
+ appKey: appid,
+ salt,
+ sign,
+ })
+
+ axios.get(`http://openapi.youdao.com/api?${query}`).then(({ data }) => {
+ if (data.query && data.translation[0]) {
+ resolve(data.translation[0])
+ } else {
+ resolve(q)
+ }
+ })
+ }
+ })
+
+const transform = async ({ from, to, locales, outputPath }) => {
+ for (const key in locales[from]) {
+ if (locales[to][key]) {
+ console.log(`add to skip: ${key}`)
+ } else {
+ let res = key
+ let way = 'youdao'
+ if (key.indexOf('/') !== 0) {
+ const reg = '{([^{}]*)}'
+ const tasks = key
+ .match(new RegExp(`${reg}|((?<=(${reg}|^)).*?(?=(${reg}|$)))`, 'g'))
+ .map(item => {
+ if (new RegExp(reg).test(item)) {
+ return Promise.resolve(item)
+ }
+ return youdao({
+ q: item,
+ from,
+ to,
+ })
+ })
+
+ res = (await Promise.all(tasks)).join('')
+ } else {
+ res = `/${to + key}`
+ way = 'link'
+ }
+ if (res !== key) {
+ locales[to][key] = res
+ console.log(`${way}: ${from} -> ${to}: ${key} -> ${res}`)
+ } else {
+ console.log(`same: ${from} -> ${to}: ${key}`)
+ }
+ }
+ }
+ await fs.writeFileSync(
+ path.resolve(__dirname, outputPath),
+ jsonFormat(locales[to], {
+ type: 'space',
+ size: 2,
+ })
+ )
+}
+;(async () => {
+ const tasks = languages
+ .map(item => ({
+ from: defaultLanguage,
+ to: item.key,
+ }))
+ .filter(item => item.from !== item.to)
+
+ for (const item of tasks) {
+ console.log(`start: ${item.from} -> ${item.to}`)
+ await transform({
+ from: item.from,
+ to: item.to,
+ locales,
+ outputPath: `../src/locales/${item.to}/messages.json`,
+ })
+ console.log(`completed: ${item.from} -> ${item.to}`)
+ }
+
+ console.log('All translations have been completed.')
+})()
diff --git a/src/components/DropOption/DropOption.js b/src/components/DropOption/DropOption.js
new file mode 100644
index 0000000..1bb4ba2
--- /dev/null
+++ b/src/components/DropOption/DropOption.js
@@ -0,0 +1,35 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { BarsOutlined, DownOutlined } from '@ant-design/icons'
+import { Dropdown, Button, Menu } from 'antd'
+
+const DropOption = ({
+ onMenuClick,
+ menuOptions = [],
+ buttonStyle,
+ dropdownProps,
+}) => {
+ const menu = menuOptions.map(item => (
+ {item.name}
+ ))
+ return (
+ {menu}}
+ {...dropdownProps}
+ >
+
+
+
+
+
+ )
+}
+
+DropOption.propTypes = {
+ onMenuClick: PropTypes.func,
+ menuOptions: PropTypes.array.isRequired,
+ buttonStyle: PropTypes.object,
+ dropdownProps: PropTypes.object,
+}
+
+export default DropOption
diff --git a/src/components/DropOption/package.json b/src/components/DropOption/package.json
new file mode 100644
index 0000000..0a1dc40
--- /dev/null
+++ b/src/components/DropOption/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "DropOption",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./DropOption.js"
+}
diff --git a/src/components/Editor/Editor.js b/src/components/Editor/Editor.js
new file mode 100644
index 0000000..a89d167
--- /dev/null
+++ b/src/components/Editor/Editor.js
@@ -0,0 +1,17 @@
+import React from 'react'
+import { Editor } from 'react-draft-wysiwyg'
+import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
+import styles from './Editor.less'
+
+const DraftEditor = props => {
+ return (
+
+ )
+}
+
+export default DraftEditor
diff --git a/src/components/Editor/Editor.less b/src/components/Editor/Editor.less
new file mode 100644
index 0000000..2cea380
--- /dev/null
+++ b/src/components/Editor/Editor.less
@@ -0,0 +1,106 @@
+.wrapper {
+ height: 500px;
+
+ :global {
+ .rdw-dropdownoption-default {
+ padding: 6px;
+ }
+
+ .rdw-dropdown-optionwrapper {
+ box-sizing: content-box;
+ width: 100%;
+ border-radius: 0 0 2px 2px;
+ &:hover {
+ box-shadow: none;
+ }
+ }
+
+ .rdw-inline-wrapper {
+ flex-wrap: wrap;
+ margin-bottom: 0;
+
+ .rdw-option-wrapper {
+ margin-bottom: 6px;
+ }
+ }
+
+ .rdw-option-active {
+ box-shadow: 1px 1px 0 #e8e8e8 inset;
+ }
+
+ .rdw-colorpicker-option {
+ box-shadow: none;
+ }
+
+ .rdw-colorpicker-modal,
+ .rdw-embedded-modal,
+ .rdw-emoji-modal,
+ .rdw-image-modal,
+ .rdw-link-modal {
+ box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
+ }
+
+ .rdw-colorpicker-modal,
+ .rdw-embedded-modal,
+ .rdw-link-modal {
+ height: auto;
+ }
+
+ .rdw-emoji-modal {
+ width: 214px;
+ }
+
+ .rdw-colorpicker-modal {
+ width: auto;
+ }
+
+ .rdw-embedded-modal-btn,
+ .rdw-image-modal-btn,
+ .rdw-link-modal-btn {
+ height: 32px;
+ margin-top: 12px;
+ }
+
+ .rdw-embedded-modal-input,
+ .rdw-embedded-modal-size-input,
+ .rdw-link-modal-input {
+ padding: 2px 6px;
+ height: 32px;
+ }
+
+ .rdw-dropdown-selectedtext {
+ color: #000;
+ }
+
+ .rdw-dropdown-wrapper,
+ .rdw-option-wrapper {
+ min-width: 36px;
+ transition: all 0.2s ease;
+ height: 30px;
+
+ &:active {
+ box-shadow: 1px 1px 0 #e8e8e8 inset;
+ }
+
+ &:hover {
+ box-shadow: 1px 1px 0 #e8e8e8;
+ }
+ }
+
+ .rdw-dropdown-wrapper {
+ min-width: 60px;
+ }
+
+ .rdw-editor-main {
+ box-sizing: border-box;
+ }
+ }
+
+ .editor {
+ border: 1px solid #f1f1f1;
+ padding: 5px;
+ border-radius: 2px;
+ height: auto;
+ min-height: 200px;
+ }
+}
diff --git a/src/components/Editor/package.json b/src/components/Editor/package.json
new file mode 100644
index 0000000..8069626
--- /dev/null
+++ b/src/components/Editor/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Editor",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Editor.js"
+}
diff --git a/src/components/Ellipsis/index.d.ts b/src/components/Ellipsis/index.d.ts
new file mode 100644
index 0000000..075fa78
--- /dev/null
+++ b/src/components/Ellipsis/index.d.ts
@@ -0,0 +1,21 @@
+import React from 'react';
+import { TooltipProps } from 'antd/lib/tooltip';
+
+export interface EllipsisTooltipProps extends TooltipProps {
+ title?: undefined;
+ overlayStyle?: undefined;
+}
+
+export interface EllipsisProps {
+ tooltip?: boolean | EllipsisTooltipProps;
+ length?: number;
+ lines?: number;
+ style?: React.CSSProperties;
+ className?: string;
+ fullWidthRecognition?: boolean;
+}
+
+export function getStrFullLength(str: string): number;
+export function cutStrByFullLength(str: string, maxLength: number): string;
+
+export default class Ellipsis extends React.Component {}
diff --git a/src/components/Ellipsis/index.js b/src/components/Ellipsis/index.js
new file mode 100644
index 0000000..de700b7
--- /dev/null
+++ b/src/components/Ellipsis/index.js
@@ -0,0 +1,270 @@
+import React, { Component } from 'react';
+import { Tooltip } from 'antd';
+import classNames from 'classnames';
+import styles from './index.less';
+
+/* eslint react/no-did-mount-set-state: 0 */
+/* eslint no-param-reassign: 0 */
+
+const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined;
+
+const TooltipOverlayStyle = {
+ overflowWrap: 'break-word',
+ wordWrap: 'break-word',
+};
+
+export const getStrFullLength = (str = '') =>
+ str.split('').reduce((pre, cur) => {
+ const charCode = cur.charCodeAt(0);
+ if (charCode >= 0 && charCode <= 128) {
+ return pre + 1;
+ }
+ return pre + 2;
+ }, 0);
+
+export const cutStrByFullLength = (str = '', maxLength) => {
+ let showLength = 0;
+ return str.split('').reduce((pre, cur) => {
+ const charCode = cur.charCodeAt(0);
+ if (charCode >= 0 && charCode <= 128) {
+ showLength += 1;
+ } else {
+ showLength += 2;
+ }
+ if (showLength <= maxLength) {
+ return pre + cur;
+ }
+ return pre;
+ }, '');
+};
+
+const getTooltip = ({ tooltip, overlayStyle, title, children }) => {
+ if (tooltip) {
+ const props = tooltip === true ? { overlayStyle, title } : { ...tooltip, overlayStyle, title };
+ return {children} ;
+ }
+ return children;
+};
+
+const EllipsisText = ({ text, length, tooltip, fullWidthRecognition, ...other }) => {
+ if (typeof text !== 'string') {
+ throw new Error('Ellipsis children must be string.');
+ }
+ const textLength = fullWidthRecognition ? getStrFullLength(text) : text.length;
+ if (textLength <= length || length < 0) {
+ return {text} ;
+ }
+ const tail = '...';
+ let displayText;
+ if (length - tail.length <= 0) {
+ displayText = '';
+ } else {
+ displayText = fullWidthRecognition ? cutStrByFullLength(text, length) : text.slice(0, length);
+ }
+
+ const spanAttrs = tooltip ? {} : { ...other };
+ return getTooltip({
+ tooltip,
+ overlayStyle: TooltipOverlayStyle,
+ title: text,
+ children: (
+
+ {displayText}
+ {tail}
+
+ ),
+ });
+};
+
+export default class Ellipsis extends Component {
+ state = {
+ text: '',
+ targetCount: 0,
+ };
+
+ componentDidMount() {
+ if (this.node) {
+ this.computeLine();
+ }
+ }
+
+ componentDidUpdate(perProps) {
+ const { lines } = this.props;
+ if (lines !== perProps.lines) {
+ this.computeLine();
+ }
+ }
+
+ computeLine = () => {
+ const { lines } = this.props;
+ if (lines && !isSupportLineClamp) {
+ const text = this.shadowChildren.innerText || this.shadowChildren.textContent;
+ const lineHeight = parseInt(getComputedStyle(this.root).lineHeight, 10);
+ const targetHeight = lines * lineHeight;
+ this.content.style.height = `${targetHeight}px`;
+ const totalHeight = this.shadowChildren.offsetHeight;
+ const shadowNode = this.shadow.firstChild;
+
+ if (totalHeight <= targetHeight) {
+ this.setState({
+ text,
+ targetCount: text.length,
+ });
+ return;
+ }
+
+ // bisection
+ const len = text.length;
+ const mid = Math.ceil(len / 2);
+
+ const count = this.bisection(targetHeight, mid, 0, len, text, shadowNode);
+
+ this.setState({
+ text,
+ targetCount: count,
+ });
+ }
+ };
+
+ bisection = (th, m, b, e, text, shadowNode) => {
+ const suffix = '...';
+ let mid = m;
+ let end = e;
+ let begin = b;
+ shadowNode.innerHTML = text.substring(0, mid) + suffix;
+ let sh = shadowNode.offsetHeight;
+
+ if (sh <= th) {
+ shadowNode.innerHTML = text.substring(0, mid + 1) + suffix;
+ sh = shadowNode.offsetHeight;
+ if (sh > th || mid === begin) {
+ return mid;
+ }
+ begin = mid;
+ if (end - begin === 1) {
+ mid = 1 + begin;
+ } else {
+ mid = Math.floor((end - begin) / 2) + begin;
+ }
+ return this.bisection(th, mid, begin, end, text, shadowNode);
+ }
+ if (mid - 1 < 0) {
+ return mid;
+ }
+ shadowNode.innerHTML = text.substring(0, mid - 1) + suffix;
+ sh = shadowNode.offsetHeight;
+ if (sh <= th) {
+ return mid - 1;
+ }
+ end = mid;
+ mid = Math.floor((end - begin) / 2) + begin;
+ return this.bisection(th, mid, begin, end, text, shadowNode);
+ };
+
+ handleRoot = n => {
+ this.root = n;
+ };
+
+ handleContent = n => {
+ this.content = n;
+ };
+
+ handleNode = n => {
+ this.node = n;
+ };
+
+ handleShadow = n => {
+ this.shadow = n;
+ };
+
+ handleShadowChildren = n => {
+ this.shadowChildren = n;
+ };
+
+ render() {
+ const { text, targetCount } = this.state;
+ const {
+ children,
+ lines,
+ length,
+ className,
+ tooltip,
+ fullWidthRecognition,
+ ...restProps
+ } = this.props;
+
+ const cls = classNames(styles.ellipsis, className, {
+ [styles.lines]: lines && !isSupportLineClamp,
+ [styles.lineClamp]: lines && isSupportLineClamp,
+ });
+
+ if (!lines && !length) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ // length
+ if (!lines) {
+ return (
+
+ );
+ }
+
+ const id = `antd-pro-ellipsis-${`${new Date().getTime()}${Math.floor(Math.random() * 100)}`}`;
+
+ // support document.body.style.webkitLineClamp
+ if (isSupportLineClamp) {
+ const style = `#${id}{-webkit-line-clamp:${lines};-webkit-box-orient: vertical;}`;
+
+ const node = (
+
+
+ {children}
+
+ );
+
+ return getTooltip({
+ tooltip,
+ overlayStyle: TooltipOverlayStyle,
+ title: children,
+ children: node,
+ });
+ }
+
+ const childNode = (
+
+ {targetCount > 0 && text.substring(0, targetCount)}
+ {targetCount > 0 && targetCount < text.length && '...'}
+
+ );
+
+ return (
+
+
+ {getTooltip({
+ tooltip,
+ overlayStyle: TooltipOverlayStyle,
+ title: text,
+ children: childNode,
+ })}
+
+ {children}
+
+
+ {text}
+
+
+
+ );
+ }
+}
diff --git a/src/components/Ellipsis/index.less b/src/components/Ellipsis/index.less
new file mode 100644
index 0000000..3c0360c
--- /dev/null
+++ b/src/components/Ellipsis/index.less
@@ -0,0 +1,24 @@
+.ellipsis {
+ display: inline-block;
+ width: 100%;
+ overflow: hidden;
+ word-break: break-all;
+}
+
+.lines {
+ position: relative;
+ .shadow {
+ position: absolute;
+ z-index: -999;
+ display: block;
+ color: transparent;
+ opacity: 0;
+ }
+}
+
+.lineClamp {
+ position: relative;
+ display: -webkit-box;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/src/components/Ellipsis/index.md b/src/components/Ellipsis/index.md
new file mode 100644
index 0000000..1875b17
--- /dev/null
+++ b/src/components/Ellipsis/index.md
@@ -0,0 +1,17 @@
+---
+title: Ellipsis
+subtitle: 文本自动省略号
+cols: 1
+order: 10
+---
+
+文本过长自动处理省略号,支持按照文本长度和最大行数两种方式截取。
+
+## API
+
+| 参数 | 说明 | 类型 | 默认值 |
+| -------------------- | ------------------------------------------------ | ------- | ------ |
+| tooltip | 移动到文本展示完整内容的提示 | boolean | - |
+| length | 在按照长度截取下的文本最大字符数,超过则截取省略 | number | - |
+| lines | 在按照行数截取下最大的行数,超过则截取省略 | number | `1` |
+| fullWidthRecognition | 是否将全角字符的长度视为 2 来计算字符串长度 | boolean | - |
diff --git a/src/components/Ellipsis/index.test.js b/src/components/Ellipsis/index.test.js
new file mode 100644
index 0000000..4d057b2
--- /dev/null
+++ b/src/components/Ellipsis/index.test.js
@@ -0,0 +1,13 @@
+import { getStrFullLength, cutStrByFullLength } from './index';
+
+describe('test calculateShowLength', () => {
+ it('get full length', () => {
+ expect(getStrFullLength('一二,a,')).toEqual(8);
+ });
+ it('cut str by full length', () => {
+ expect(cutStrByFullLength('一二,a,', 7)).toEqual('一二,a');
+ });
+ it('cut str when length small', () => {
+ expect(cutStrByFullLength('一22三', 5)).toEqual('一22');
+ });
+});
diff --git a/src/components/FilterItem/FilterItem.js b/src/components/FilterItem/FilterItem.js
new file mode 100644
index 0000000..e701c8b
--- /dev/null
+++ b/src/components/FilterItem/FilterItem.js
@@ -0,0 +1,28 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './FilterItem.less'
+
+const FilterItem = ({ label = '', children }) => {
+ const labelArray = label.split('')
+ return (
+
+ {labelArray.length > 0 && (
+
+ {labelArray.map((item, index) => (
+
+ {item}
+
+ ))}
+
+ )}
+
{children}
+
+ )
+}
+
+FilterItem.propTypes = {
+ label: PropTypes.string,
+ children: PropTypes.element.isRequired,
+}
+
+export default FilterItem
diff --git a/src/components/FilterItem/FilterItem.less b/src/components/FilterItem/FilterItem.less
new file mode 100644
index 0000000..6fe1e7b
--- /dev/null
+++ b/src/components/FilterItem/FilterItem.less
@@ -0,0 +1,17 @@
+.filterItem {
+ display: flex;
+ justify-content: space-between;
+
+ .labelWrap {
+ width: 80px;
+ line-height: 28px;
+ margin-right: 12px;
+ justify-content: space-between;
+ display: flex;
+ overflow: hidden;
+ }
+
+ .item {
+ flex: 1;
+ }
+}
diff --git a/src/components/FilterItem/package.json b/src/components/FilterItem/package.json
new file mode 100644
index 0000000..04c7d8a
--- /dev/null
+++ b/src/components/FilterItem/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "FilterItem",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./FilterItem.js"
+}
diff --git a/src/components/GlobalFooter/index.d.ts b/src/components/GlobalFooter/index.d.ts
new file mode 100644
index 0000000..efde77d
--- /dev/null
+++ b/src/components/GlobalFooter/index.d.ts
@@ -0,0 +1,14 @@
+import React from 'react';
+export interface GlobalFooterProps {
+ links?: Array<{
+ key?: string;
+ title: React.ReactNode;
+ href: string;
+ blankTarget?: boolean;
+ }>;
+ copyright?: React.ReactNode;
+ style?: React.CSSProperties;
+ className?: string;
+}
+
+export default class GlobalFooter extends React.Component {}
diff --git a/src/components/GlobalFooter/index.js b/src/components/GlobalFooter/index.js
new file mode 100644
index 0000000..1c2fb74
--- /dev/null
+++ b/src/components/GlobalFooter/index.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import classNames from 'classnames';
+import styles from './index.less';
+
+const GlobalFooter = ({ className, links, copyright }) => {
+ const clsString = classNames(styles.globalFooter, className);
+ return (
+
+ {links && (
+
+ )}
+ {copyright && {copyright}
}
+
+ );
+};
+
+export default GlobalFooter;
diff --git a/src/components/GlobalFooter/index.less b/src/components/GlobalFooter/index.less
new file mode 100644
index 0000000..e4b3dfd
--- /dev/null
+++ b/src/components/GlobalFooter/index.less
@@ -0,0 +1,29 @@
+@import '~antd/lib/style/themes/default.less';
+
+.globalFooter {
+ margin: 48px 0 24px 0;
+ padding: 0 16px;
+ text-align: center;
+
+ .links {
+ margin-bottom: 8px;
+
+ a {
+ color: @text-color-secondary;
+ transition: all 0.3s;
+
+ &:not(:last-child) {
+ margin-right: 40px;
+ }
+
+ &:hover {
+ color: @text-color;
+ }
+ }
+ }
+
+ .copyright {
+ color: @text-color-secondary;
+ font-size: @font-size-base;
+ }
+}
diff --git a/src/components/GlobalFooter/index.md b/src/components/GlobalFooter/index.md
new file mode 100644
index 0000000..5d6058f
--- /dev/null
+++ b/src/components/GlobalFooter/index.md
@@ -0,0 +1,15 @@
+---
+title: GlobalFooter
+subtitle: 全局页脚
+cols: 1
+order: 7
+---
+
+页脚属于全局导航的一部分,作为对顶部导航的补充,通过传递数据控制展示内容。
+
+## API
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --------- | -------- | ---------------------------------------------------------------- | ------ |
+| links | 链接数据 | array<{ title: ReactNode, href: string, blankTarget?: boolean }> | - |
+| copyright | 版权信息 | ReactNode | - |
diff --git a/src/components/Layout/Bread.js b/src/components/Layout/Bread.js
new file mode 100644
index 0000000..ca86499
--- /dev/null
+++ b/src/components/Layout/Bread.js
@@ -0,0 +1,68 @@
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { Breadcrumb } from 'antd'
+import { Link, withRouter } from 'umi'
+import { t } from "@lingui/macro"
+import iconMap from 'utils/iconMap'
+const { pathToRegexp } = require('path-to-regexp')
+import { queryAncestors } from 'utils'
+import styles from './Bread.less'
+
+@withRouter
+class Bread extends PureComponent {
+ generateBreadcrumbs = (paths) => {
+ return paths.map((item, key) => {
+ const content = item && (
+
+ {item.icon && (
+ {iconMap[item.icon]}
+ )}
+ {item.name}
+
+ )
+
+ return (
+ item && (
+
+ {paths.length - 1 !== key ? (
+ {content}
+ ) : (
+ content
+ )}
+
+ )
+ )
+ })
+ }
+ render() {
+ const { routeList, location } = this.props
+
+ // Find a route that matches the pathname.
+ const currentRoute = routeList.find(
+ (_) => _.route && pathToRegexp(_.route).exec(location.pathname)
+ )
+
+ // Find the breadcrumb navigation of the current route match and all its ancestors.
+ const paths = currentRoute
+ ? queryAncestors(routeList, currentRoute, 'breadcrumbParentId').reverse()
+ : [
+ routeList[0],
+ {
+ id: 404,
+ name: t`Not Found`,
+ },
+ ]
+
+ return (
+
+ {this.generateBreadcrumbs(paths)}
+
+ )
+ }
+}
+
+Bread.propTypes = {
+ routeList: PropTypes.array,
+}
+
+export default Bread
diff --git a/src/components/Layout/Bread.less b/src/components/Layout/Bread.less
new file mode 100644
index 0000000..d30a5f1
--- /dev/null
+++ b/src/components/Layout/Bread.less
@@ -0,0 +1,16 @@
+.bread {
+ margin-bottom: 24px;
+
+ :global {
+ .ant-breadcrumb {
+ display: flex;
+ align-items: center;
+ }
+ }
+}
+
+@media (max-width: 767px) {
+ .bread {
+ margin-bottom: 12px;
+ }
+}
diff --git a/src/components/Layout/Header.js b/src/components/Layout/Header.js
new file mode 100644
index 0000000..3b37540
--- /dev/null
+++ b/src/components/Layout/Header.js
@@ -0,0 +1,169 @@
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { Menu, Layout, Avatar, Popover, Badge, List } from 'antd'
+import { Ellipsis } from 'components'
+import {
+ BellOutlined,
+ RightOutlined,
+ MenuFoldOutlined,
+ MenuUnfoldOutlined,
+} from '@ant-design/icons'
+import { Trans } from "@lingui/macro"
+import { getLocale, setLocale } from 'utils'
+import moment from 'moment'
+import classnames from 'classnames'
+import config from 'config'
+import styles from './Header.less'
+
+const { SubMenu } = Menu
+
+class Header extends PureComponent {
+ handleClickMenu = e => {
+ e.key === 'SignOut' && this.props.onSignOut()
+ }
+ render() {
+ const {
+ fixed,
+ avatar,
+ username,
+ collapsed,
+ notifications,
+ onCollapseChange,
+ onAllNotificationsRead,
+ } = this.props
+
+ const rightContent = [
+
+
+
+ Hi,
+
+ {username}
+
+
+ }
+ >
+
+ Sign out
+
+
+ ,
+ ]
+
+ if (config.i18n) {
+ const { languages } = config.i18n
+ const language = getLocale()
+ const currentLanguage = languages.find(
+ item => item.key === language
+ )
+
+ rightContent.unshift(
+ {
+ setLocale(data.key)
+ }}
+ mode="horizontal"
+ >
+ }>
+ {languages.map(item => (
+
+
+ {item.title}
+
+ ))}
+
+
+ )
+ }
+
+ rightContent.unshift(
+ document.querySelector('#primaryLayout')}
+ content={
+
+
You have viewed all notifications.,
+ }}
+ renderItem={item => (
+
+
+ {item.title}
+
+ }
+ description={moment(item.date).fromNow()}
+ />
+
+
+ )}
+ />
+ {notifications.length ? (
+
+ Clear notifications
+
+ ) : null}
+
+ }
+ >
+
+
+
+
+ )
+
+ return (
+
+ )
+ }
+}
+
+Header.propTypes = {
+ fixed: PropTypes.bool,
+ user: PropTypes.object,
+ menus: PropTypes.array,
+ collapsed: PropTypes.bool,
+ onSignOut: PropTypes.func,
+ notifications: PropTypes.array,
+ onCollapseChange: PropTypes.func,
+ onAllNotificationsRead: PropTypes.func,
+}
+
+export default Header
diff --git a/src/components/Layout/Header.less b/src/components/Layout/Header.less
new file mode 100644
index 0000000..1709b6d
--- /dev/null
+++ b/src/components/Layout/Header.less
@@ -0,0 +1,154 @@
+@import '~themes/vars.less';
+
+.header {
+ padding: 0;
+ box-shadow: @shadow-2;
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+ height: 72px;
+ z-index: 9;
+ align-items: center;
+ background-color: #fff;
+
+ &.fixed {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: ~'calc(100% - 256px)';
+ z-index: 29;
+ transition: width 0.2s;
+
+ &.collapsed {
+ width: ~'calc(100% - 80px)';
+ }
+ }
+
+ :global {
+ .ant-menu-submenu-title {
+ height: 72px;
+ }
+
+ .ant-menu-horizontal {
+ line-height: 72px;
+
+ & > .ant-menu-submenu:hover {
+ color: @primary-color;
+ background-color: @hover-color;
+ }
+ }
+
+ .ant-menu {
+ border-bottom: none;
+ height: 72px;
+ }
+
+ .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;
+ }
+ }
+
+ .rightContainer {
+ display: flex;
+ align-items: center;
+ }
+
+ .button {
+ width: 72px;
+ height: 72px;
+ line-height: 72px;
+ text-align: center;
+ font-size: 18px;
+ cursor: pointer;
+ transition: @transition-ease-in;
+
+ &:hover {
+ color: @primary-color;
+ background-color: @hover-color;
+ }
+ }
+}
+
+.iconButton {
+ width: 48px;
+ height: 48px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 24px;
+ cursor: pointer;
+ .background-hover();
+
+ &:hover {
+ .iconFont {
+ color: @primary-color;
+ }
+ }
+
+ & + .iconButton {
+ margin-left: 8px;
+ }
+
+ .iconFont {
+ color: #b2b0c7;
+ font-size: 24px;
+ }
+}
+
+.notification {
+ padding: 24px 0;
+ width: 320px;
+ .notificationItem {
+ transition: all 0.3s;
+ padding: 12px 24px;
+ cursor: pointer;
+ &:hover {
+ background-color: @hover-color;
+ }
+ }
+ .clearButton {
+ text-align: center;
+ height: 48px;
+ line-height: 48px;
+ cursor: pointer;
+ .background-hover();
+ }
+}
+
+.notificationPopover {
+ :global {
+ .ant-popover-inner-content {
+ padding: 0;
+ }
+ .ant-popover-arrow {
+ display: none;
+ }
+ .ant-list-item-content {
+ flex: 0;
+ margin-left: 16px;
+ }
+ }
+}
+
+@media (max-width: 767px) {
+ .header {
+ width: 100% !important;
+ }
+}
diff --git a/src/components/Layout/Menu.js b/src/components/Layout/Menu.js
new file mode 100644
index 0000000..8438599
--- /dev/null
+++ b/src/components/Layout/Menu.js
@@ -0,0 +1,122 @@
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { Menu } from 'antd'
+import { NavLink, withRouter } from 'umi'
+import { pathToRegexp } from 'path-to-regexp'
+import { arrayToTree, queryAncestors } from 'utils'
+import iconMap from 'utils/iconMap'
+import store from 'store'
+
+const { SubMenu } = Menu
+
+@withRouter
+class SiderMenu extends PureComponent {
+ state = {
+ openKeys: store.get('openKeys') || [],
+ }
+
+ onOpenChange = openKeys => {
+ const { menus } = this.props
+ const rootSubmenuKeys = menus.filter(_ => !_.menuParentId).map(_ => _.id)
+
+ const latestOpenKey = openKeys.find(
+ key => this.state.openKeys.indexOf(key) === -1
+ )
+
+ let newOpenKeys = openKeys
+ if (rootSubmenuKeys.indexOf(latestOpenKey) !== -1) {
+ newOpenKeys = latestOpenKey ? [latestOpenKey] : []
+ }
+
+ this.setState({
+ openKeys: newOpenKeys,
+ })
+ store.set('openKeys', newOpenKeys)
+ }
+
+ generateMenus = data => {
+ return data.map(item => {
+ if (item.children) {
+ return (
+
+ {item.icon && iconMap[item.icon]}
+ {item.name}
+
+ }
+ >
+ {this.generateMenus(item.children)}
+
+ )
+ }
+ return (
+
+
+ {item.icon && iconMap[item.icon]}
+ {item.name}
+
+
+ )
+ })
+ }
+
+ render() {
+ const {
+ collapsed,
+ theme,
+ menus,
+ location,
+ isMobile,
+ onCollapseChange,
+ } = this.props
+
+ // Generating tree-structured data for menu content.
+ const menuTree = arrayToTree(menus, 'id', 'menuParentId')
+
+ // Find a menu that matches the pathname.
+ const currentMenu = menus.find(
+ _ => _.route && pathToRegexp(_.route).exec(location.pathname)
+ )
+
+ // Find the key that should be selected according to the current menu.
+ const selectedKeys = currentMenu
+ ? queryAncestors(menus, currentMenu, 'menuParentId').map(_ => _.id)
+ : []
+
+ const menuProps = collapsed
+ ? {}
+ : {
+ openKeys: this.state.openKeys,
+ }
+
+ return (
+ {
+ onCollapseChange(true)
+ }
+ : undefined
+ }
+ {...menuProps}
+ >
+ {this.generateMenus(menuTree)}
+
+ )
+ }
+}
+
+SiderMenu.propTypes = {
+ menus: PropTypes.array,
+ theme: PropTypes.string,
+ isMobile: PropTypes.bool,
+ onCollapseChange: PropTypes.func,
+}
+
+export default SiderMenu
diff --git a/src/components/Layout/Sider.js b/src/components/Layout/Sider.js
new file mode 100644
index 0000000..575311d
--- /dev/null
+++ b/src/components/Layout/Sider.js
@@ -0,0 +1,88 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { Switch, Layout } from 'antd'
+import { t } from "@lingui/macro"
+import { Trans } from "@lingui/macro"
+import { BulbOutlined } from '@ant-design/icons'
+import ScrollBar from '../ScrollBar'
+import { config } from 'utils'
+import SiderMenu from './Menu'
+import styles from './Sider.less'
+
+class Sider extends PureComponent {
+ render() {
+ const {
+ menus,
+ theme,
+ isMobile,
+ collapsed,
+ onThemeChange,
+ onCollapseChange,
+ } = this.props
+
+ return (
+
+
+
+
+ {!collapsed &&
{config.siteName} }
+
+
+
+
+
+
+
+
+ {!collapsed && (
+
+
+
+ Switch Theme
+
+
+
+ )}
+
+ )
+ }
+}
+
+Sider.propTypes = {
+ menus: PropTypes.array,
+ theme: PropTypes.string,
+ isMobile: PropTypes.bool,
+ collapsed: PropTypes.bool,
+ onThemeChange: PropTypes.func,
+ onCollapseChange: PropTypes.func,
+}
+
+export default Sider
diff --git a/src/components/Layout/Sider.less b/src/components/Layout/Sider.less
new file mode 100644
index 0000000..9f41821
--- /dev/null
+++ b/src/components/Layout/Sider.less
@@ -0,0 +1,110 @@
+@import '~themes/vars.less';
+
+.sider {
+ box-shadow: fade(@primary-color, 10%) 0 0 28px 0;
+ z-index: 10;
+ :global {
+ .ant-layout-sider-children {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ }
+ }
+}
+
+.brand {
+ z-index: 1;
+ height: 72px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 24px;
+ box-shadow: 0 1px 9px -3px rgba(0, 0, 0, 0.2);
+ .logo {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ img {
+ width: 36px;
+ margin-right: 8px;
+ }
+
+ h1 {
+ vertical-align: text-bottom;
+ font-size: 16px;
+ text-transform: uppercase;
+ display: inline-block;
+ font-weight: 700;
+ color: @primary-color;
+ white-space: nowrap;
+ margin-bottom: 0;
+ .text-gradient();
+
+ :local {
+ animation: fadeRightIn 300ms @ease-in-out;
+ animation-fill-mode: both;
+ }
+ }
+ }
+}
+
+.menuContainer {
+ height: ~'calc(100vh - 120px)';
+ overflow-x: hidden;
+ flex: 1;
+ padding: 24px 0;
+
+ &::-webkit-scrollbar-thumb {
+ background-color: transparent;
+ }
+
+ &:hover {
+ &::-webkit-scrollbar-thumb {
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+ }
+
+ :global {
+ .ant-menu-inline {
+ border-right: none;
+ }
+ }
+}
+
+.switchTheme {
+ width: 100%;
+ height: 48px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 16px;
+ overflow: hidden;
+ transition: all 0.3s;
+
+ span {
+ white-space: nowrap;
+ overflow: hidden;
+ font-size: 12px;
+ }
+
+ :global {
+ .anticon {
+ min-width: 14px;
+ margin-right: 4px;
+ font-size: 14px;
+ }
+ }
+}
+
+@keyframes fadeLeftIn {
+ 0% {
+ transform: translateX(5px);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translateX(0);
+ opacity: 1;
+ }
+}
diff --git a/src/components/Layout/index.js b/src/components/Layout/index.js
new file mode 100644
index 0000000..3ad0894
--- /dev/null
+++ b/src/components/Layout/index.js
@@ -0,0 +1,6 @@
+import Header from './Header'
+import Menu from './Menu'
+import Bread from './Bread'
+import Sider from './Sider'
+
+export { Header, Menu, Bread, Sider }
diff --git a/src/components/Loader/Loader.js b/src/components/Loader/Loader.js
new file mode 100644
index 0000000..5a5a021
--- /dev/null
+++ b/src/components/Loader/Loader.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import classNames from 'classnames'
+import styles from './Loader.less'
+
+const Loader = ({ spinning = false, fullScreen }) => {
+ return (
+
+ )
+}
+
+Loader.propTypes = {
+ spinning: PropTypes.bool,
+ fullScreen: PropTypes.bool,
+}
+
+export default Loader
diff --git a/src/components/Loader/Loader.less b/src/components/Loader/Loader.less
new file mode 100644
index 0000000..9fa02dc
--- /dev/null
+++ b/src/components/Loader/Loader.less
@@ -0,0 +1,67 @@
+.loader {
+ 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);
+ }
+}
diff --git a/src/components/Loader/package.json b/src/components/Loader/package.json
new file mode 100644
index 0000000..15bde9a
--- /dev/null
+++ b/src/components/Loader/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Loader",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Loader.js"
+}
diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js
new file mode 100644
index 0000000..532bf31
--- /dev/null
+++ b/src/components/Page/Page.js
@@ -0,0 +1,33 @@
+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 (
+
+ {loading ? : ''}
+ {children}
+
+ )
+ }
+}
+
+Page.propTypes = {
+ className: PropTypes.string,
+ children: PropTypes.node,
+ loading: PropTypes.bool,
+ inner: PropTypes.bool,
+}
diff --git a/src/components/Page/Page.less b/src/components/Page/Page.less
new file mode 100644
index 0000000..e180131
--- /dev/null
+++ b/src/components/Page/Page.less
@@ -0,0 +1,16 @@
+@import '~themes/vars.less';
+
+.contentInner {
+ background: #fff;
+ padding: 24px;
+ box-shadow: @shadow-1;
+ min-height: ~'calc(100vh - 230px)';
+ position: relative;
+}
+
+@media (max-width: 767px) {
+ .contentInner {
+ padding: 12px;
+ min-height: ~'calc(100vh - 160px)';
+ }
+}
diff --git a/src/components/Page/package.json b/src/components/Page/package.json
new file mode 100644
index 0000000..a3811bd
--- /dev/null
+++ b/src/components/Page/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Page",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Page.js"
+}
diff --git a/src/components/ScrollBar/index.js b/src/components/ScrollBar/index.js
new file mode 100644
index 0000000..ce752b5
--- /dev/null
+++ b/src/components/ScrollBar/index.js
@@ -0,0 +1,5 @@
+import ScrollBar from 'react-perfect-scrollbar'
+import 'react-perfect-scrollbar/dist/css/styles.css'
+import './index.less'
+
+export default ScrollBar
diff --git a/src/components/ScrollBar/index.less b/src/components/ScrollBar/index.less
new file mode 100644
index 0000000..31e149b
--- /dev/null
+++ b/src/components/ScrollBar/index.less
@@ -0,0 +1,31 @@
+:global {
+ .ps--active-x > .ps__rail-x,
+ .ps--active-y > .ps__rail-y {
+ background-color: transparent;
+ }
+
+ .ps__rail-x:hover > .ps__thumb-x,
+ .ps__rail-x:focus > .ps__thumb-x {
+ height: 8px;
+ }
+
+ .ps__rail-y:hover > .ps__thumb-y,
+ .ps__rail-y:focus > .ps__thumb-y {
+ width: 8px;
+ }
+
+ .ps__rail-y,
+ .ps__rail-x {
+ z-index: 9;
+ }
+
+ .ps__thumb-y {
+ width: 4px;
+ right: 4px;
+ }
+
+ .ps__thumb-x {
+ height: 4px;
+ bottom: 4px;
+ }
+}
diff --git a/src/components/index.js b/src/components/index.js
new file mode 100644
index 0000000..d3d3750
--- /dev/null
+++ b/src/components/index.js
@@ -0,0 +1,11 @@
+import Editor from './Editor'
+import FilterItem from './FilterItem'
+import DropOption from './DropOption'
+import Loader from './Loader'
+import ScrollBar from './ScrollBar'
+import GlobalFooter from './GlobalFooter'
+import Ellipsis from './Ellipsis'
+import * as MyLayout from './Layout/index.js'
+import Page from './Page'
+
+export { MyLayout, Editor, GlobalFooter, Ellipsis, FilterItem, DropOption, Loader, Page, ScrollBar }
diff --git a/src/e2e/login.e2e.js b/src/e2e/login.e2e.js
new file mode 100644
index 0000000..7c8fd0e
--- /dev/null
+++ b/src/e2e/login.e2e.js
@@ -0,0 +1,41 @@
+import puppeteer from 'puppeteer'
+
+describe('Login', () => {
+ let browser
+ let page
+
+ beforeAll(async () => {
+ browser = await puppeteer.launch({ args: ['--no-sandbox'] })
+ })
+
+ beforeEach(async () => {
+ page = await browser.newPage()
+ await page.goto('http://localhost:8000/en/login', {
+ waitUntil: 'networkidle2',
+ })
+ })
+
+ afterEach(() => page.close())
+
+ it('should login with failure', async () => {
+ await page.waitFor(selector => !!document.querySelector('#username'), {
+ timeout: 3000,
+ })
+ await page.type('#username', 'wrong_user')
+ await page.type('#password', 'wrong_password')
+ await page.click('button[type="button"]')
+ await page.waitForSelector('.anticon-close-circle') // should display error
+ })
+
+ it('should login successfully', async () => {
+ await page.waitForSelector('#username', { timeout: 3000 })
+ await page.type('#username', 'admin')
+ await page.type('#password', 'admin')
+ await page.click('button[type="button"]')
+ await page.waitForSelector('.ant-layout-footer')
+ const text = await page.evaluate(() => document.body.innerHTML)
+ expect(text).toContain('Ant Design Admin')
+ })
+
+ afterAll(() => browser.close())
+})
diff --git a/src/layouts/BaseLayout.js b/src/layouts/BaseLayout.js
new file mode 100644
index 0000000..4e36bed
--- /dev/null
+++ b/src/layouts/BaseLayout.js
@@ -0,0 +1,55 @@
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Helmet } from 'react-helmet'
+import { Loader } from 'components'
+import { queryLayout } from 'utils'
+import NProgress from 'nprogress'
+import config from 'utils/config'
+import { withRouter } from 'umi'
+
+import PublicLayout from './PublicLayout'
+import PrimaryLayout from './PrimaryLayout'
+import './BaseLayout.less'
+
+const LayoutMap = {
+ primary: PrimaryLayout,
+ public: PublicLayout,
+}
+
+@withRouter
+@connect(({ loading }) => ({ loading }))
+class BaseLayout extends PureComponent {
+ previousPath = ''
+
+ render() {
+ const { loading, children, location } = this.props
+ const Container = LayoutMap[queryLayout(config.layouts, location.pathname)]
+
+ const currentPath = location.pathname + location.search
+ if (currentPath !== this.previousPath) {
+ NProgress.start()
+ }
+
+ if (!loading.global) {
+ NProgress.done()
+ this.previousPath = currentPath
+ }
+
+ return (
+
+
+ {config.siteName}
+
+
+ {children}
+
+ )
+ }
+}
+
+BaseLayout.propTypes = {
+ loading: PropTypes.object,
+}
+
+export default BaseLayout
diff --git a/src/layouts/BaseLayout.less b/src/layouts/BaseLayout.less
new file mode 100644
index 0000000..d958d75
--- /dev/null
+++ b/src/layouts/BaseLayout.less
@@ -0,0 +1,74 @@
+@import '~themes/vars.less';
+@import '~themes/index.less';
+
+:global {
+ #nprogress {
+ pointer-events: none;
+
+ .bar {
+ background: @primary-color;
+ position: fixed;
+ z-index: 2048;
+ 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;
+ transform: rotate(3deg) translate(0, -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);
+ }
+}
diff --git a/src/layouts/PrimaryLayout.js b/src/layouts/PrimaryLayout.js
new file mode 100644
index 0000000..b054705
--- /dev/null
+++ b/src/layouts/PrimaryLayout.js
@@ -0,0 +1,168 @@
+/* global window */
+/* global document */
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { withRouter } from 'umi'
+import { connect } from 'umi'
+import { MyLayout, GlobalFooter } from 'components'
+import { BackTop, Layout, Drawer } from 'antd'
+import { enquireScreen, unenquireScreen } from 'enquire-js'
+const { pathToRegexp } = require("path-to-regexp")
+import { config, getLocale } from 'utils'
+import Error from '../pages/404'
+import styles from './PrimaryLayout.less'
+import store from 'store'
+
+const { Content } = Layout
+const { Header, Bread, Sider } = MyLayout
+
+@withRouter
+@connect(({ app, loading }) => ({ app, loading }))
+class PrimaryLayout extends PureComponent {
+ state = {
+ isMobile: false,
+ }
+
+ componentDidMount() {
+ this.enquireHandler = enquireScreen(mobile => {
+ const { isMobile } = this.state
+ if (isMobile !== mobile) {
+ this.setState({
+ isMobile: mobile,
+ })
+ }
+ })
+ }
+
+ componentWillUnmount() {
+ unenquireScreen(this.enquireHandler)
+ }
+
+ onCollapseChange = collapsed => {
+ this.props.dispatch({
+ type: 'app/handleCollapseChange',
+ payload: collapsed,
+ })
+ }
+
+ render() {
+ const { app, location, dispatch, children } = this.props
+ const { theme, collapsed, notifications } = app
+ const user = store.get('user') || {}
+ const permissions = store.get('permissions') || {}
+ const routeList = store.get('routeList') || []
+ const { isMobile } = this.state
+ const { onCollapseChange } = this
+
+ // Localized route name.
+
+ const lang = getLocale()
+ const newRouteList =
+ lang !== 'en'
+ ? routeList.map(item => {
+ const { name, ...other } = item
+ return {
+ ...other,
+ name: (item[lang] || {}).name || name,
+ }
+ })
+ : routeList
+
+ // Find a route that matches the pathname.
+ const currentRoute = newRouteList.find(
+ _ => _.route && pathToRegexp(_.route).exec(location.pathname)
+ )
+
+ // Query whether you have permission to enter this page
+ const hasPermission = currentRoute
+ ? permissions.visit.includes(currentRoute.id)
+ : false
+
+ // MenuParentId is equal to -1 is not a available menu.
+ const menus = newRouteList.filter(_ => _.menuParentId !== '-1')
+
+ const headerProps = {
+ menus,
+ collapsed,
+ notifications,
+ onCollapseChange,
+ avatar: user.avatar,
+ username: user.username,
+ fixed: config.fixedHeader,
+ onAllNotificationsRead() {
+ dispatch({ type: 'app/allNotificationsRead' })
+ },
+ onSignOut() {
+ dispatch({ type: 'app/signOut' })
+ },
+ }
+
+ const siderProps = {
+ theme,
+ menus,
+ isMobile,
+ collapsed,
+ onCollapseChange,
+ onThemeChange(theme) {
+ dispatch({
+ type: 'app/handleThemeChange',
+ payload: theme,
+ })
+ },
+ }
+
+ return (
+
+
+ {isMobile ? (
+
+
+
+ ) : (
+
+ )}
+
+
+
+
+ {hasPermission ? children : }
+
+ document.querySelector('#primaryLayout')}
+ />
+
+
+
+
+ )
+ }
+}
+
+PrimaryLayout.propTypes = {
+ children: PropTypes.element.isRequired,
+ location: PropTypes.object,
+ dispatch: PropTypes.func,
+ app: PropTypes.object,
+ loading: PropTypes.object,
+}
+
+export default PrimaryLayout
diff --git a/src/layouts/PrimaryLayout.less b/src/layouts/PrimaryLayout.less
new file mode 100644
index 0000000..6ee60c9
--- /dev/null
+++ b/src/layouts/PrimaryLayout.less
@@ -0,0 +1,58 @@
+@import '~themes/vars.less';
+
+.backTop {
+ right: 50px;
+
+ :global {
+ .ant-back-top-content {
+ background: @primary-color;
+ opacity: 0.3;
+ transition: all 0.3s;
+ box-shadow: 0 0 15px 1px rgba(69, 65, 78, 0.1);
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+}
+
+.content {
+ padding: 24px;
+ min-height: ~'calc(100% - 72px)';
+ // overflow-y: scroll;
+}
+
+.container {
+ height: 100vh;
+ flex: 1;
+ width: ~'calc(100% - 256px)';
+ overflow-y: scroll;
+ overflow-x: hidden;
+}
+
+.footer {
+ background: #fff;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 24px;
+ padding-bottom: 24px;
+ min-height: 72px;
+}
+
+@media (max-width: 767px) {
+ .content {
+ padding: 12px;
+ }
+
+ .backTop {
+ right: 20px;
+ bottom: 20px;
+ }
+
+ .container {
+ height: 100vh;
+ flex: 1;
+ width: 100%;
+ }
+}
diff --git a/src/layouts/PublicLayout.js b/src/layouts/PublicLayout.js
new file mode 100644
index 0000000..caaaf5c
--- /dev/null
+++ b/src/layouts/PublicLayout.js
@@ -0,0 +1,3 @@
+export default ({ children }) => {
+ return children
+}
diff --git a/src/layouts/index.js b/src/layouts/index.js
new file mode 100644
index 0000000..cd45ffe
--- /dev/null
+++ b/src/layouts/index.js
@@ -0,0 +1,71 @@
+import React, { Component } from 'react'
+import { withRouter } from 'umi'
+import { ConfigProvider } from 'antd'
+import { i18n } from "@lingui/core"
+import { I18nProvider } from '@lingui/react'
+import { getLocale } from 'utils'
+import { zh, en, pt } from 'make-plural/plurals'
+import zhCN from 'antd/lib/locale-provider/zh_CN'
+import enUS from 'antd/lib/locale-provider/en_US'
+import ptBR from 'antd/lib/locale-provider/pt_BR'
+
+import BaseLayout from './BaseLayout'
+
+i18n.loadLocaleData({
+ en: { plurals: en },
+ zh: { plurals: zh },
+ 'pt-br': { plurals: pt }
+})
+
+// antd
+const languages = {
+ zh: zhCN,
+ en: enUS,
+ 'pt-br': ptBR
+}
+
+const { defaultLanguage } = i18n
+
+@withRouter
+class Layout extends Component {
+ state = {
+ }
+
+ componentDidMount() {
+ }
+
+ loadCatalog = async (lan) => {
+ const catalog = await import(
+ `../locales/${lan}/messages.json`
+ )
+
+ i18n.load(lan, catalog)
+ i18n.activate(lan)
+
+ // if (lan != i18n.locale) {
+ // i18n.load(lan, catalog)
+ // i18n.activate(lan)
+ // }
+
+ }
+
+ render() {
+ const { children } = this.props
+
+ let language = getLocale()
+
+ if (!languages[language]) language = defaultLanguage
+
+ this.loadCatalog(language)
+
+ return (
+
+
+ {children}
+
+
+ )
+ }
+}
+
+export default Layout
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
new file mode 100644
index 0000000..538126f
--- /dev/null
+++ b/src/locales/en/messages.json
@@ -0,0 +1,56 @@
+{
+ "/dashboard": "/dashboard",
+ "Add Param": "Add Param",
+ "Address": "Address",
+ "Age": "Age",
+ "Are you sure delete this record?": "Are you sure delete this record?",
+ "Author": "Author",
+ "Avatar": "Avatar",
+ "Categories": "Categories",
+ "Clear notifications": "Clear notifications",
+ "Comments": "Comments",
+ "Create": "Create",
+ "Create User": "Create User",
+ "CreateTime": "CreateTime",
+ "LastLoginTime": "LastLoginTime",
+ "Dark": "Dark",
+ "Delete": "Delete",
+ "Email": "Email",
+ "Female": "Female",
+ "Gender": "Gender",
+ "Hi,": "Hi,",
+ "Image": "Image",
+ "Light": "Light",
+ "Male": "Male",
+ "Name": "Name",
+ "NickName": "NickName",
+ "Not Found": "Not Found",
+ "Operation": "Operation",
+ "Params": "Params",
+ "Password": "Password",
+ "Phone": "Phone",
+ "Pick an address": "Pick an address",
+ "Please pick an address": "Please pick an address",
+ "Publised": "Publised",
+ "Publish Date": "Publish Date",
+ "Reset": "Reset",
+ "Search": "Search",
+ "Search Name": "Search Name",
+ "Send": "Send",
+ "Sign in": "Sign in",
+ "Sign out": "Sign out",
+ "Switch Theme": "Switch Theme",
+ "Tags": "Tags",
+ "The input is not valid E-mail!": "The input is not valid E-mail!",
+ "The input is not valid phone!": "The input is not valid phone!",
+ "Title": "Title",
+ "Total {total} Items": "Total {total} Items",
+ "Unpublished": "Unpublished",
+ "Update": "Update",
+ "Update User": "Update User",
+ "Username": "Username",
+ "Views": "Views",
+ "Visibility": "Visibility",
+ "You have viewed all notifications.": "You have viewed all notifications.",
+ "Status": "Status"
+}
\ No newline at end of file
diff --git a/src/locales/pt-br/messages.json b/src/locales/pt-br/messages.json
new file mode 100644
index 0000000..2e931da
--- /dev/null
+++ b/src/locales/pt-br/messages.json
@@ -0,0 +1,54 @@
+{
+ "/dashboard": "/dashboard",
+ "Add Param": "Add Parametro",
+ "Address": "Endereço",
+ "Age": "Ano",
+ "Are you sure delete this record?": "Tem certeza de excluir este registro?",
+ "Author": "Autor",
+ "Avatar": "Avatar",
+ "Categories": "Categorias",
+ "Clear notifications": "limpar notificações",
+ "Comments": "Comentarios",
+ "Create": "Criar",
+ "Create User": "Criar Usuário",
+ "CreateTime": "CreateTime",
+ "Dark": "Escuro",
+ "Delete": "Deletar",
+ "Email": "Email",
+ "Female": "Feminino",
+ "Gender": "Genero",
+ "Hi,": "Olá,",
+ "Image": "Imagem",
+ "Light": "Claro",
+ "Male": "masculino",
+ "Name": "Nome",
+ "NickName": "NickName",
+ "Not Found": "Não Encontrado",
+ "Operation": "Operation",
+ "Params": "Parametros",
+ "Password": "Senha",
+ "Phone": "Fone",
+ "Pick an address": "Escolha um endereço",
+ "Please pick an address": "Por favor, escolha um endereço",
+ "Publised": "Publicado",
+ "Publish Date": "Data de publicação",
+ "Reset": "Reset",
+ "Search": "procurar",
+ "Search Name": "Search Name",
+ "Send": "Enviar",
+ "Sign in": "Sign in",
+ "Sign out": "Sign out",
+ "Switch Theme": "Trocar tema",
+ "Tags": "Tags",
+ "The input is not valid E-mail!": "Não é um E-mail valido!",
+ "The input is not valid phone!": "Não é um telefone Valido!",
+ "Title": "Titulo",
+ "Total {total} Items": "Total {total} Items",
+ "Unpublished": "Não publicado",
+ "Update": "Atualizar",
+ "Update User": "Atualizar Usuário",
+ "Username": "Usuário",
+ "Views": "visualizações",
+ "Visibility": "Visibilidade",
+ "You have viewed all notifications.": "Você visualizou todas as notificações."
+}
diff --git a/src/locales/zh/messages.json b/src/locales/zh/messages.json
new file mode 100644
index 0000000..ac2df4a
--- /dev/null
+++ b/src/locales/zh/messages.json
@@ -0,0 +1,56 @@
+{
+ "/dashboard": "/zh/dashboard",
+ "Add Param": "添加参数",
+ "Address": "地址",
+ "Age": "年龄",
+ "Are you sure delete this record?": "您确定要删除这条记录吗?",
+ "Author": "作者",
+ "Avatar": "头像",
+ "Categories": "类别",
+ "Clear notifications": "清空消息",
+ "Comments": "评论数",
+ "Create": "创建",
+ "Create User": "创建用户",
+ "CreateTime": "创建时间",
+ "LastLoginTime": "上次登录时间",
+ "Dark": "暗",
+ "Delete": "删除",
+ "Email": "电子邮件",
+ "Female": "女",
+ "Gender": "性别",
+ "Hi,": "你好,",
+ "Image": "图像",
+ "Light": "明",
+ "Male": "男性",
+ "Name": "名字",
+ "NickName": "昵称",
+ "Not Found": "未找到",
+ "Operation": "操作",
+ "Params": "参数",
+ "Password": "密码",
+ "Phone": "电话",
+ "Pick an address": "选择地址",
+ "Please pick an address": "选择地址",
+ "Publised": "已发布",
+ "Publish Date": "发布日期",
+ "Reset": "重置",
+ "Search": "搜索",
+ "Search Name": "搜索名字",
+ "Send": "发送",
+ "Sign in": "登录",
+ "Sign out": "退出登录",
+ "Switch Theme": "切换主题",
+ "Tags": "标签",
+ "The input is not valid E-mail!": "输入的电子邮件无效!",
+ "The input is not valid phone!": "输入无效的手机!",
+ "Title": "标题",
+ "Total {total} Items": "总共 {total} 条记录",
+ "Unpublished": "未发布",
+ "Update": "更新",
+ "Update User": "更新用户",
+ "Username": "用户名",
+ "Views": "浏览数",
+ "Visibility": "可见性",
+ "You have viewed all notifications.": "您已查看所有通知",
+ "Status": "状态"
+}
\ No newline at end of file
diff --git a/src/models/app.js b/src/models/app.js
new file mode 100644
index 0000000..a868eca
--- /dev/null
+++ b/src/models/app.js
@@ -0,0 +1,161 @@
+/* global window */
+
+import { history } from 'umi'
+import { stringify } from 'qs'
+import store from 'store'
+const { pathToRegexp } = require("path-to-regexp")
+import { ROLE_TYPE } from 'utils/constant'
+import { queryLayout } from 'utils'
+import { CANCEL_REQUEST_MESSAGE } from 'utils/constant'
+import api from 'api'
+import config from 'config'
+
+const { queryRouteList, logoutUser, queryUserInfo } = api
+
+const goDashboard = () => {
+ if (pathToRegexp(['/', '/login']).exec(window.location.pathname)) {
+ history.push({
+ pathname: '/dashboard',
+ })
+ }
+}
+
+export default {
+ namespace: 'app',
+ state: {
+ routeList: [
+ {
+ id: '1',
+ icon: 'laptop',
+ name: 'Dashboard',
+ zhName: '仪表盘',
+ router: '/dashboard',
+ },
+ ],
+ locationPathname: '',
+ locationQuery: {},
+ theme: store.get('theme') || 'light',
+ collapsed: store.get('collapsed') || false,
+ notifications: [
+ {
+ title: 'New User is registered.',
+ date: new Date(Date.now() - 10000000),
+ },
+ {
+ title: 'Application has been approved.',
+ date: new Date(Date.now() - 50000000),
+ },
+ ],
+ },
+ subscriptions: {
+ setup({ dispatch }) {
+ dispatch({ type: 'query' })
+ },
+ setupHistory({ dispatch, history }) {
+ history.listen(location => {
+ dispatch({
+ type: 'updateState',
+ payload: {
+ locationPathname: location.pathname,
+ locationQuery: location.query,
+ },
+ })
+ })
+ },
+
+ setupRequestCancel({ history }) {
+ history.listen(() => {
+ const { cancelRequest = new Map() } = window
+
+ cancelRequest.forEach((value, key) => {
+ if (value.pathname !== window.location.pathname) {
+ value.cancel(CANCEL_REQUEST_MESSAGE)
+ cancelRequest.delete(key)
+ }
+ })
+ })
+ },
+ },
+ effects: {
+ *query({ payload }, { call, put, select }) {
+ // store isInit to prevent query trigger by refresh
+ const isInit = store.get('isInit')
+ if (isInit) {
+ goDashboard()
+ return
+ }
+ const { locationPathname } = yield select(_ => _.app)
+ const { success, user } = yield call(queryUserInfo, payload)
+ if (success && user) {
+ const { list } = yield call(queryRouteList)
+ const { permissions } = user
+ let routeList = list
+ if (
+ permissions.role === ROLE_TYPE.ADMIN ||
+ permissions.role === ROLE_TYPE.DEVELOPER
+ ) {
+ permissions.visit = list.map(item => item.id)
+ } else {
+ routeList = list.filter(item => {
+ const cases = [
+ permissions.visit.includes(item.id),
+ item.mpid
+ ? permissions.visit.includes(item.mpid) || item.mpid === '-1'
+ : true,
+ item.bpid ? permissions.visit.includes(item.bpid) : true,
+ ]
+ return cases.every(_ => _)
+ })
+ }
+ store.set('routeList', routeList)
+ store.set('permissions', permissions)
+ store.set('user', user)
+ store.set('isInit', true)
+ goDashboard()
+ } else if (queryLayout(config.layouts, locationPathname) !== 'public') {
+ history.push({
+ pathname: '/login',
+ search: stringify({
+ from: locationPathname,
+ }),
+ })
+ }
+ },
+
+ *signOut({ payload }, { call, put }) {
+ const data = yield call(logoutUser)
+ if (data.success) {
+ store.set('routeList', [])
+ store.set('permissions', { visit: [] })
+ store.set('user', {})
+ store.set('isInit', false)
+ store.set('token', false)
+ yield put({ type: 'query' })
+ } else {
+ throw data
+ }
+ },
+ },
+ reducers: {
+ updateState(state, { payload }) {
+ return {
+ ...state,
+ ...payload,
+ }
+ },
+
+ handleThemeChange(state, { payload }) {
+ store.set('theme', payload)
+ state.theme = payload
+ },
+
+ handleCollapseChange(state, { payload }) {
+ store.set('collapsed', payload)
+ state.collapsed = payload
+ },
+
+ allNotificationsRead(state) {
+ state.notifications = []
+ },
+ },
+}
diff --git a/src/pages/404.less b/src/pages/404.less
new file mode 100644
index 0000000..f5300b1
--- /dev/null
+++ b/src/pages/404.less
@@ -0,0 +1,19 @@
+.error {
+ color: black;
+ text-align: center;
+ position: absolute;
+ top: 30%;
+ margin-top: -50px;
+ left: 50%;
+ margin-left: -100px;
+ width: 200px;
+
+ :global .anticon {
+ font-size: 48px;
+ margin-bottom: 16px;
+ }
+
+ h1 {
+ font-family: cursive;
+ }
+}
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
new file mode 100644
index 0000000..cff81d3
--- /dev/null
+++ b/src/pages/404.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import { FrownOutlined } from '@ant-design/icons'
+import { Page } from 'components'
+import styles from './404.less'
+
+const Error = () => (
+
+
+
+
404 Not Found
+
+
+)
+
+export default Error
diff --git a/src/pages/chart/ECharts/AirportCoordComponent.js b/src/pages/chart/ECharts/AirportCoordComponent.js
new file mode 100644
index 0000000..6b8c2ba
--- /dev/null
+++ b/src/pages/chart/ECharts/AirportCoordComponent.js
@@ -0,0 +1,321 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+require('./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 (
+
+
+ render a airport chart.
+
+
+
+ )
+}
+
+export default AirportCoordComponent
diff --git a/src/pages/chart/ECharts/BubbleGradientComponent.js b/src/pages/chart/ECharts/BubbleGradientComponent.js
new file mode 100644
index 0000000..813f8a2
--- /dev/null
+++ b/src/pages/chart/ECharts/BubbleGradientComponent.js
@@ -0,0 +1,165 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+import * as 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 (
+
+ )
+}
+
+export default BubbleGradientComponent
diff --git a/src/pages/chart/ECharts/CalendarComponent.js b/src/pages/chart/ECharts/CalendarComponent.js
new file mode 100644
index 0000000..79dd50c
--- /dev/null
+++ b/src/pages/chart/ECharts/CalendarComponent.js
@@ -0,0 +1,193 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+import * as 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 (
+
+
+ render a calendar-charts
+
+
+
+ )
+}
+
+export default CalendarComponent
diff --git a/src/pages/chart/ECharts/ChartAPIComponent.js b/src/pages/chart/ECharts/ChartAPIComponent.js
new file mode 100644
index 0000000..35b97f7
--- /dev/null
+++ b/src/pages/chart/ECharts/ChartAPIComponent.js
@@ -0,0 +1,130 @@
+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} {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 =
+ ' { 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 (
+
+
+
+ {' '}
+ use echarts API With getEchartsInstance() : (the
+ API will return the echarts instance, then you can use any API of
+ echarts.)
+
+
{
+ this.echarts_react = e
+ }}
+ option={option}
+ />
+
+ {' '}
+ code below: (echarts API list see:
+ http://echarts.baidu.com/api.html#echartsInstance)
+
+
+ {code}
+
+
+
+ )
+ }
+}
+
+export default ChartAPIComponent
diff --git a/src/pages/chart/ECharts/ChartShowLoadingComponent.js b/src/pages/chart/ECharts/ChartShowLoadingComponent.js
new file mode 100644
index 0000000..26a83fd
--- /dev/null
+++ b/src/pages/chart/ECharts/ChartShowLoadingComponent.js
@@ -0,0 +1,104 @@
+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' +
+ ' '
+
+ return (
+
+
+
+ {' '}
+ Chart loading With showLoading : (when chart
+ ready, hide the loading mask.)
+
+
+
code below:
+
+ {code}
+
+
+
+ )
+ }
+}
+
+export default ChartShowLoadingComponent
diff --git a/src/pages/chart/ECharts/ChartWithEventComponent.js b/src/pages/chart/ECharts/ChartWithEventComponent.js
new file mode 100644
index 0000000..7103a01
--- /dev/null
+++ b/src/pages/chart/ECharts/ChartWithEventComponent.js
@@ -0,0 +1,95 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+const ChartWithEventComponent = () => {
+ const onChartReady = echart => {
+ /* eslint-disable */
+ 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} {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' +
+ ' '
+
+ return (
+
+
+
+ {' '}
+ Chart With event onEvents : (Click the chart, and
+ watch the console)
+
+
+
code below:
+
+ {code}
+
+
+
+ )
+}
+
+export default ChartWithEventComponent
diff --git a/src/pages/chart/ECharts/DynamicChartComponent.js b/src/pages/chart/ECharts/DynamicChartComponent.js
new file mode 100644
index 0000000..cce8296
--- /dev/null
+++ b/src/pages/chart/ECharts/DynamicChartComponent.js
@@ -0,0 +1,217 @@
+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 =
+ " \n'
+ return (
+
+
+
use React state to render dynamic chart
+
+
code below: use state of react to render dynamic chart
+
+ {code}
+
+
+
+ )
+ }
+}
+
+export default DynamicChartComponent
diff --git a/src/pages/chart/ECharts/EchartsComponent.js b/src/pages/chart/ECharts/EchartsComponent.js
new file mode 100644
index 0000000..b2fa38e
--- /dev/null
+++ b/src/pages/chart/ECharts/EchartsComponent.js
@@ -0,0 +1,49 @@
+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'
+
+const EchartsComponent = ({ type }) => {
+ if (type === 'simple') return
+ if (type === 'loading') return
+ if (type === 'api') return
+ if (type === 'events') return
+ if (type === 'theme') return
+ if (type === 'dynamic') return
+ if (type === 'map') return
+ if (type === 'airport') return
+ if (type === 'graph') return
+ if (type === 'calendar') return
+ if (type === 'treemap') return
+ if (type === 'gauge') return
+ if (type === 'gcalendar') return
+ if (type === 'lunar') return
+ if (type === 'liquid') return
+ if (type === 'BubbleGradientComponent') return
+ if (type === 'TransparentBar3DComPonent') return
+ return
+}
+
+EchartsComponent.propTypes = {
+ type: PropTypes.string,
+}
+
+export default EchartsComponent
diff --git a/src/pages/chart/ECharts/GCalendarComponent.js b/src/pages/chart/ECharts/GCalendarComponent.js
new file mode 100644
index 0000000..da81e14
--- /dev/null
+++ b/src/pages/chart/ECharts/GCalendarComponent.js
@@ -0,0 +1,76 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+import * as 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 (
+
+
+ render a calendar like github commit history.
+
+
+
+ )
+}
+
+export default GCalendarComponent
diff --git a/src/pages/chart/ECharts/GaugeComponent.js b/src/pages/chart/ECharts/GaugeComponent.js
new file mode 100644
index 0000000..665908b
--- /dev/null
+++ b/src/pages/chart/ECharts/GaugeComponent.js
@@ -0,0 +1,370 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+class GaugeComponent extends React.Component {
+ constructor() {
+ super()
+ const option = {
+ backgroundColor: '#1b1b1b',
+ tooltip: {
+ formatter: '{a} {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 (
+
+
+ render a car gauge chart.
+
+
+
+ )
+ }
+}
+
+export default GaugeComponent
diff --git a/src/pages/chart/ECharts/GraphComponent.js b/src/pages/chart/ECharts/GraphComponent.js
new file mode 100644
index 0000000..1621cd8
--- /dev/null
+++ b/src/pages/chart/ECharts/GraphComponent.js
@@ -0,0 +1,1365 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+const GraphComponent = () => {
+ const getOtion = () => {
+ const webkitDep = {
+ type: 'force',
+ categories: [
+ { name: 'HTMLElement', keyword: {}, base: 'HTMLElement' },
+ { name: 'WebGL', keyword: {}, base: 'WebGLRenderingContext' },
+ { name: 'SVG', keyword: {}, base: 'SVGElement' },
+ { name: 'CSS', keyword: {}, base: 'CSSRule' },
+ { name: 'Other', keyword: {} },
+ ],
+ nodes: [
+ { name: 'AnalyserNode', value: 1, category: 4 },
+ { name: 'AudioNode', value: 1, category: 4 },
+ { name: 'Uint8Array', value: 1, category: 4 },
+ { name: 'Float32Array', value: 1, category: 4 },
+ { name: 'ArrayBuffer', value: 1, category: 4 },
+ { name: 'ArrayBufferView', value: 1, category: 4 },
+ { name: 'Attr', value: 1, category: 4 },
+ { name: 'Node', value: 1, category: 4 },
+ { name: 'Element', value: 1, category: 4 },
+ { name: 'AudioBuffer', value: 1, category: 4 },
+ { name: 'AudioBufferCallback', value: 1, category: 4 },
+ { name: 'AudioBufferSourceNode', value: 1, category: 4 },
+ { name: 'AudioSourceNode', value: 1, category: 4 },
+ { name: 'AudioGain', value: 1, category: 4 },
+ { name: 'AudioParam', value: 1, category: 4 },
+ { name: 'AudioContext', value: 1, category: 4 },
+ { name: 'AudioDestinationNode', value: 1, category: 4 },
+ { name: 'AudioListener', value: 1, category: 4 },
+ { name: 'BiquadFilterNode', value: 1, category: 4 },
+ { name: 'ChannelMergerNode', value: 1, category: 4 },
+ { name: 'ChannelSplitterNode', value: 1, category: 4 },
+ { name: 'ConvolverNode', value: 1, category: 4 },
+ { name: 'DelayNode', value: 1, category: 4 },
+ { name: 'DynamicsCompressorNode', value: 1, category: 4 },
+ { name: 'GainNode', value: 1, category: 4 },
+ { name: 'MediaElementAudioSourceNode', value: 1, category: 4 },
+ { name: 'MediaStreamAudioDestinationNode', value: 1, category: 4 },
+ { name: 'MediaStreamAudioSourceNode', value: 1, category: 4 },
+ { name: 'OscillatorNode', value: 1, category: 4 },
+ { name: 'PannerNode', value: 1, category: 4 },
+ { name: 'ScriptProcessorNode', value: 1, category: 4 },
+ { name: 'WaveShaperNode', value: 1, category: 4 },
+ { name: 'WaveTable', value: 1, category: 4 },
+ { name: 'CanvasRenderingContext', value: 1, category: 4 },
+ { name: 'HTMLCanvasElement', value: 1, category: 0 },
+ { name: 'CanvasRenderingContext2D', value: 1, category: 4 },
+ { name: 'ImageData', value: 1, category: 4 },
+ { name: 'CanvasGradient', value: 1, category: 4 },
+ { name: 'CanvasPattern', value: 1, category: 4 },
+ { name: 'HTMLImageElement', value: 1, category: 0 },
+ { name: 'HTMLVideoElement', value: 1, category: 0 },
+ { name: 'TextMetrics', value: 1, category: 4 },
+ { name: 'CDATASection', value: 1, category: 4 },
+ { name: 'Text', value: 1, category: 4 },
+ { name: 'CharacterData', value: 1, category: 4 },
+ { name: 'ClientRectList', value: 1, category: 4 },
+ { name: 'ClientRect', value: 1, category: 4 },
+ { name: 'Clipboard', value: 1, category: 4 },
+ { name: 'FileList', value: 1, category: 4 },
+ { name: 'DataTransferItemList', value: 1, category: 4 },
+ { name: 'Comment', value: 1, category: 4 },
+ { name: 'Console', value: 1, category: 4 },
+ { name: 'MemoryInfo', value: 1, category: 4 },
+ { name: 'Crypto', value: 1, category: 4 },
+ { name: 'CSSCharsetRule', value: 1, category: 3 },
+ { name: 'CSSRule', value: 3, category: 3 },
+ { name: 'CSSFontFaceRule', value: 1, category: 3 },
+ { name: 'CSSStyleDeclaration', value: 1, category: 3 },
+ { name: 'CSSImportRule', value: 1, category: 3 },
+ { name: 'MediaList', value: 1, category: 4 },
+ { name: 'CSSStyleSheet', value: 1, category: 3 },
+ { name: 'CSSMediaRule', value: 1, category: 3 },
+ { name: 'CSSRuleList', value: 1, category: 3 },
+ { name: 'CSSPageRule', value: 1, category: 3 },
+ { name: 'CSSPrimitiveValue', value: 1, category: 3 },
+ { name: 'CSSValue', value: 1, category: 3 },
+ { name: 'Counter', value: 1, category: 4 },
+ { name: 'RGBColor', value: 1, category: 4 },
+ { name: 'Rect', value: 1, category: 4 },
+ { name: 'CSSStyleRule', value: 1, category: 3 },
+ { name: 'StyleSheet', value: 1, category: 4 },
+ { name: 'CSSUnknownRule', value: 1, category: 3 },
+ { name: 'CSSValueList', value: 1, category: 3 },
+ { name: 'Database', value: 1, category: 4 },
+ { name: 'SQLTransactionCallback', value: 1, category: 4 },
+ { name: 'DatabaseCallback', value: 1, category: 4 },
+ { name: 'DatabaseSync', value: 1, category: 4 },
+ { name: 'SQLTransactionSyncCallback', value: 1, category: 4 },
+ { name: 'DataTransferItem', value: 1, category: 4 },
+ { name: 'StringCallback', value: 1, category: 4 },
+ { name: 'Entry', value: 1, category: 4 },
+ { name: 'File', value: 1, category: 4 },
+ { name: 'DataView', value: 1, category: 4 },
+ { name: 'DedicatedWorkerContext', value: 1, category: 4 },
+ { name: 'WorkerContext', value: 1, category: 4 },
+ { name: 'DirectoryEntry', value: 1, category: 4 },
+ { name: 'DirectoryReader', value: 1, category: 4 },
+ { name: 'VoidCallback', value: 1, category: 4 },
+ { name: 'DirectoryEntrySync', value: 1, category: 4 },
+ { name: 'EntrySync', value: 1, category: 4 },
+ { name: 'DirectoryReaderSync', value: 1, category: 4 },
+ { name: 'FileEntrySync', value: 1, category: 4 },
+ { name: 'EntriesCallback', value: 1, category: 4 },
+ { name: 'EntryArraySync', value: 1, category: 4 },
+ { name: 'DocumentFragment', value: 1, category: 4 },
+ { name: 'NodeList', value: 1, category: 4 },
+ { name: 'DocumentType', value: 1, category: 4 },
+ { name: 'NamedNodeMap', value: 1, category: 4 },
+ { name: 'DOMFileSystem', value: 1, category: 4 },
+ { name: 'DOMFileSystemSync', value: 1, category: 4 },
+ { name: 'DOMImplementation', value: 1, category: 4 },
+ { name: 'HTMLDocument', value: 1, category: 0 },
+ { name: 'DOMMimeType', value: 1, category: 4 },
+ { name: 'DOMPlugin', value: 1, category: 4 },
+ { name: 'DOMMimeTypeArray', value: 1, category: 4 },
+ { name: 'DOMPluginArray', value: 1, category: 4 },
+ { name: 'DOMSelection', value: 1, category: 4 },
+ { name: 'Range', value: 1, category: 4 },
+ { name: 'DOMSettableTokenList', value: 1, category: 4 },
+ { name: 'DOMTokenList', value: 1, category: 4 },
+ { name: 'DOMStringMap', value: 1, category: 4 },
+ { name: 'ShadowRoot', value: 1, category: 4 },
+ { name: 'Entity', value: 1, category: 4 },
+ { name: 'EntityReference', value: 1, category: 4 },
+ { name: 'EntryArray', value: 1, category: 4 },
+ { name: 'MetadataCallback', value: 1, category: 4 },
+ { name: 'EntryCallback', value: 1, category: 4 },
+ { name: 'Metadata', value: 1, category: 4 },
+ { name: 'ErrorCallback', value: 1, category: 4 },
+ { name: 'FileError', value: 1, category: 4 },
+ { name: 'FileCallback', value: 1, category: 4 },
+ { name: 'FileEntry', value: 1, category: 4 },
+ { name: 'FileWriterCallback', value: 1, category: 4 },
+ { name: 'FileWriterSync', value: 1, category: 4 },
+ { name: 'FileReader', value: 1, category: 4 },
+ { name: 'FileReaderSync', value: 1, category: 4 },
+ { name: 'FileSystemCallback', value: 1, category: 4 },
+ { name: 'FileWriter', value: 1, category: 4 },
+ { name: 'Float64Array', value: 1, category: 4 },
+ { name: 'GamepadList', value: 1, category: 4 },
+ { name: 'Gamepad', value: 1, category: 4 },
+ { name: 'Geolocation', value: 1, category: 4 },
+ { name: 'PositionCallback', value: 1, category: 4 },
+ { name: 'Geoposition', value: 1, category: 4 },
+ { name: 'Coordinates', value: 1, category: 4 },
+ { name: 'HTMLAllCollection', value: 1, category: 0 },
+ { name: 'HTMLAnchorElement', value: 1, category: 0 },
+ { name: 'HTMLElement', value: 3, category: 0 },
+ { name: 'HTMLAppletElement', value: 1, category: 0 },
+ { name: 'HTMLAreaElement', value: 1, category: 0 },
+ { name: 'HTMLAudioElement', value: 1, category: 0 },
+ { name: 'HTMLMediaElement', value: 1, category: 0 },
+ { name: 'HTMLBaseElement', value: 1, category: 0 },
+ { name: 'HTMLBaseFontElement', value: 1, category: 0 },
+ { name: 'HTMLBodyElement', value: 1, category: 0 },
+ { name: 'HTMLBRElement', value: 1, category: 0 },
+ { name: 'HTMLButtonElement', value: 1, category: 0 },
+ { name: 'HTMLFormElement', value: 1, category: 0 },
+ { name: 'ValidityState', value: 1, category: 4 },
+ { name: 'HTMLCollection', value: 1, category: 0 },
+ { name: 'HTMLContentElement', value: 1, category: 0 },
+ { name: 'HTMLDataListElement', value: 1, category: 0 },
+ { name: 'HTMLDetailsElement', value: 1, category: 0 },
+ { name: 'HTMLDirectoryElement', value: 1, category: 0 },
+ { name: 'HTMLDivElement', value: 1, category: 0 },
+ { name: 'HTMLDListElement', value: 1, category: 0 },
+ { name: 'HTMLEmbedElement', value: 1, category: 0 },
+ { name: 'SVGDocument', value: 1, category: 2 },
+ { name: 'HTMLFieldSetElement', value: 1, category: 0 },
+ { name: 'HTMLFontElement', value: 1, category: 0 },
+ { name: 'HTMLFormControlsCollection', value: 1, category: 0 },
+ { name: 'HTMLFrameElement', value: 1, category: 0 },
+ { name: 'HTMLFrameSetElement', value: 1, category: 0 },
+ { name: 'HTMLHeadElement', value: 1, category: 0 },
+ { name: 'HTMLHeadingElement', value: 1, category: 0 },
+ { name: 'HTMLHRElement', value: 1, category: 0 },
+ { name: 'HTMLHtmlElement', value: 1, category: 0 },
+ { name: 'HTMLIFrameElement', value: 1, category: 0 },
+ { name: 'HTMLInputElement', value: 1, category: 0 },
+ { name: 'HTMLKeygenElement', value: 1, category: 0 },
+ { name: 'HTMLLabelElement', value: 1, category: 0 },
+ { name: 'HTMLLegendElement', value: 1, category: 0 },
+ { name: 'HTMLLIElement', value: 1, category: 0 },
+ { name: 'HTMLLinkElement', value: 1, category: 0 },
+ { name: 'HTMLMapElement', value: 1, category: 0 },
+ { name: 'HTMLMarqueeElement', value: 1, category: 0 },
+ { name: 'TimeRanges', value: 1, category: 4 },
+ { name: 'MediaController', value: 1, category: 4 },
+ { name: 'MediaError', value: 1, category: 4 },
+ { name: 'TextTrackList', value: 1, category: 4 },
+ { name: 'TextTrack', value: 1, category: 4 },
+ { name: 'HTMLMenuElement', value: 1, category: 0 },
+ { name: 'HTMLMetaElement', value: 1, category: 0 },
+ { name: 'HTMLMeterElement', value: 1, category: 0 },
+ { name: 'HTMLModElement', value: 1, category: 0 },
+ { name: 'HTMLObjectElement', value: 1, category: 0 },
+ { name: 'HTMLOListElement', value: 1, category: 0 },
+ { name: 'HTMLOptGroupElement', value: 1, category: 0 },
+ { name: 'HTMLOptionElement', value: 1, category: 0 },
+ { name: 'HTMLOptionsCollection', value: 1, category: 0 },
+ { name: 'HTMLOutputElement', value: 1, category: 0 },
+ { name: 'HTMLParagraphElement', value: 1, category: 0 },
+ { name: 'HTMLParamElement', value: 1, category: 0 },
+ { name: 'HTMLPreElement', value: 1, category: 0 },
+ { name: 'HTMLProgressElement', value: 1, category: 0 },
+ { name: 'HTMLQuoteElement', value: 1, category: 0 },
+ { name: 'HTMLScriptElement', value: 1, category: 0 },
+ { name: 'HTMLSelectElement', value: 1, category: 0 },
+ { name: 'HTMLShadowElement', value: 1, category: 0 },
+ { name: 'HTMLSourceElement', value: 1, category: 0 },
+ { name: 'HTMLSpanElement', value: 1, category: 0 },
+ { name: 'HTMLStyleElement', value: 1, category: 0 },
+ { name: 'HTMLTableCaptionElement', value: 1, category: 0 },
+ { name: 'HTMLTableCellElement', value: 1, category: 0 },
+ { name: 'HTMLTableColElement', value: 1, category: 0 },
+ { name: 'HTMLTableElement', value: 1, category: 0 },
+ { name: 'HTMLTableSectionElement', value: 1, category: 0 },
+ { name: 'HTMLTableRowElement', value: 1, category: 0 },
+ { name: 'HTMLTextAreaElement', value: 1, category: 0 },
+ { name: 'HTMLTitleElement', value: 1, category: 0 },
+ { name: 'HTMLTrackElement', value: 1, category: 0 },
+ { name: 'HTMLUListElement', value: 1, category: 0 },
+ { name: 'HTMLUnknownElement', value: 1, category: 0 },
+ { name: 'IDBCursor', value: 1, category: 4 },
+ { name: 'IDBAny', value: 1, category: 4 },
+ { name: 'IDBKey', value: 1, category: 4 },
+ { name: 'IDBRequest', value: 1, category: 4 },
+ { name: 'IDBCursorWithValue', value: 1, category: 4 },
+ { name: 'IDBDatabase', value: 1, category: 4 },
+ { name: 'DOMStringList', value: 1, category: 4 },
+ { name: 'IDBObjectStore', value: 1, category: 4 },
+ { name: 'IDBTransaction', value: 1, category: 4 },
+ { name: 'IDBFactory', value: 1, category: 4 },
+ { name: 'IDBVersionChangeRequest', value: 1, category: 4 },
+ { name: 'IDBOpenDBRequest', value: 1, category: 4 },
+ { name: 'IDBIndex', value: 1, category: 4 },
+ { name: 'IDBKeyRange', value: 1, category: 4 },
+ { name: 'DOMError', value: 1, category: 4 },
+ { name: 'Int16Array', value: 1, category: 4 },
+ { name: 'Int32Array', value: 1, category: 4 },
+ { name: 'Int8Array', value: 1, category: 4 },
+ { name: 'JavaScriptCallFrame', value: 1, category: 4 },
+ { name: 'LocalMediaStream', value: 1, category: 4 },
+ { name: 'MediaStream', value: 1, category: 4 },
+ { name: 'Location', value: 1, category: 4 },
+ { name: 'MediaQueryList', value: 1, category: 4 },
+ { name: 'MediaQueryListListener', value: 1, category: 4 },
+ { name: 'MediaSource', value: 1, category: 4 },
+ { name: 'SourceBufferList', value: 1, category: 4 },
+ { name: 'SourceBuffer', value: 1, category: 4 },
+ { name: 'MediaStreamTrackList', value: 1, category: 4 },
+ { name: 'MediaStreamList', value: 1, category: 4 },
+ { name: 'MediaStreamTrack', value: 1, category: 4 },
+ { name: 'MessageChannel', value: 1, category: 4 },
+ { name: 'MessagePort', value: 1, category: 4 },
+ { name: 'MutationObserver', value: 1, category: 4 },
+ { name: 'MutationRecord', value: 1, category: 4 },
+ { name: 'Navigator', value: 1, category: 4 },
+ { name: 'BatteryManager', value: 1, category: 4 },
+ { name: 'NavigatorUserMediaErrorCallback', value: 1, category: 4 },
+ { name: 'NavigatorUserMediaError', value: 1, category: 4 },
+ { name: 'NavigatorUserMediaSuccessCallback', value: 1, category: 4 },
+ { name: 'NodeFilter', value: 1, category: 4 },
+ { name: 'NodeIterator', value: 1, category: 4 },
+ { name: 'Notation', value: 1, category: 4 },
+ { name: 'Notification', value: 1, category: 4 },
+ { name: 'NotificationPermissionCallback', value: 1, category: 4 },
+ { name: 'NotificationCenter', value: 1, category: 4 },
+ { name: 'OESVertexArrayObject', value: 1, category: 4 },
+ { name: 'WebGLVertexArrayObjectOES', value: 1, category: 1 },
+ { name: 'Performance', value: 1, category: 4 },
+ { name: 'PerformanceNavigation', value: 1, category: 4 },
+ { name: 'PerformanceTiming', value: 1, category: 4 },
+ { name: 'PositionErrorCallback', value: 1, category: 4 },
+ { name: 'PositionError', value: 1, category: 4 },
+ { name: 'ProcessingInstruction', value: 1, category: 4 },
+ { name: 'RadioNodeList', value: 1, category: 4 },
+ { name: 'RTCDataChannel', value: 1, category: 4 },
+ { name: 'RTCPeerConnection', value: 1, category: 4 },
+ { name: 'RTCSessionDescription', value: 1, category: 4 },
+ { name: 'RTCIceCandidate', value: 1, category: 4 },
+ { name: 'RTCSessionDescriptionCallback', value: 1, category: 4 },
+ { name: 'RTCStatsCallback', value: 1, category: 4 },
+ { name: 'RTCStatsResponse', value: 1, category: 4 },
+ { name: 'RTCStatsReport', value: 1, category: 4 },
+ { name: 'RTCStatsElement', value: 1, category: 4 },
+ { name: 'ScriptProfile', value: 1, category: 4 },
+ { name: 'ScriptProfileNode', value: 1, category: 4 },
+ { name: 'SharedWorker', value: 1, category: 4 },
+ { name: 'AbstractWorker', value: 1, category: 4 },
+ { name: 'SharedWorkerContext', value: 1, category: 4 },
+ { name: 'SpeechGrammarList', value: 1, category: 4 },
+ { name: 'SpeechGrammar', value: 1, category: 4 },
+ { name: 'SpeechInputResultList', value: 1, category: 4 },
+ { name: 'SpeechInputResult', value: 1, category: 4 },
+ { name: 'SpeechRecognition', value: 1, category: 4 },
+ { name: 'SpeechRecognitionResult', value: 1, category: 4 },
+ { name: 'SpeechRecognitionAlternative', value: 1, category: 4 },
+ { name: 'SpeechRecognitionResultList', value: 1, category: 4 },
+ { name: 'SQLResultSet', value: 1, category: 4 },
+ { name: 'SQLResultSetRowList', value: 1, category: 4 },
+ { name: 'SQLStatementCallback', value: 1, category: 4 },
+ { name: 'SQLTransaction', value: 1, category: 4 },
+ { name: 'SQLStatementErrorCallback', value: 1, category: 4 },
+ { name: 'SQLTransactionErrorCallback', value: 1, category: 4 },
+ { name: 'SQLError', value: 1, category: 4 },
+ { name: 'SQLTransactionSync', value: 1, category: 4 },
+ { name: 'StorageInfo', value: 1, category: 4 },
+ { name: 'StorageInfoUsageCallback', value: 1, category: 4 },
+ { name: 'StorageInfoQuotaCallback', value: 1, category: 4 },
+ { name: 'StorageInfoErrorCallback', value: 1, category: 4 },
+ { name: 'DOMCoreException', value: 1, category: 4 },
+ { name: 'StyleSheetList', value: 1, category: 4 },
+ { name: 'SVGAElement', value: 1, category: 2 },
+ { name: 'SVGTransformable', value: 1, category: 2 },
+ { name: 'SVGAnimatedString', value: 1, category: 2 },
+ { name: 'SVGAltGlyphDefElement', value: 1, category: 2 },
+ { name: 'SVGElement', value: 3, category: 2 },
+ { name: 'SVGAltGlyphElement', value: 1, category: 2 },
+ { name: 'SVGURIReference', value: 1, category: 2 },
+ { name: 'SVGAltGlyphItemElement', value: 1, category: 2 },
+ { name: 'SVGAnimateColorElement', value: 1, category: 2 },
+ { name: 'SVGAnimationElement', value: 1, category: 2 },
+ { name: 'SVGAnimatedAngle', value: 1, category: 2 },
+ { name: 'SVGAngle', value: 1, category: 2 },
+ { name: 'SVGAnimatedLength', value: 1, category: 2 },
+ { name: 'SVGLength', value: 1, category: 2 },
+ { name: 'SVGAnimatedLengthList', value: 1, category: 2 },
+ { name: 'SVGLengthList', value: 1, category: 2 },
+ { name: 'SVGAnimatedNumberList', value: 1, category: 2 },
+ { name: 'SVGNumberList', value: 1, category: 2 },
+ { name: 'SVGAnimatedPreserveAspectRatio', value: 1, category: 2 },
+ { name: 'SVGPreserveAspectRatio', value: 1, category: 2 },
+ { name: 'SVGAnimatedRect', value: 1, category: 2 },
+ { name: 'SVGRect', value: 1, category: 2 },
+ { name: 'SVGAnimatedTransformList', value: 1, category: 2 },
+ { name: 'SVGTransformList', value: 1, category: 2 },
+ { name: 'SVGAnimateElement', value: 1, category: 2 },
+ { name: 'SVGAnimateMotionElement', value: 1, category: 2 },
+ { name: 'SVGAnimateTransformElement', value: 1, category: 2 },
+ { name: 'ElementTimeControl', value: 1, category: 4 },
+ { name: 'SVGCircleElement', value: 1, category: 2 },
+ { name: 'SVGClipPathElement', value: 1, category: 2 },
+ { name: 'SVGAnimatedEnumeration', value: 1, category: 2 },
+ { name: 'SVGColor', value: 1, category: 2 },
+ { name: 'SVGComponentTransferFunctionElement', value: 1, category: 2 },
+ { name: 'SVGAnimatedNumber', value: 1, category: 2 },
+ { name: 'SVGCursorElement', value: 1, category: 2 },
+ { name: 'SVGExternalResourcesRequired', value: 1, category: 2 },
+ { name: 'SVGDefsElement', value: 1, category: 2 },
+ { name: 'SVGDescElement', value: 1, category: 2 },
+ { name: 'SVGStylable', value: 1, category: 2 },
+ { name: 'SVGSVGElement', value: 1, category: 2 },
+ { name: 'SVGElementInstance', value: 1, category: 2 },
+ { name: 'EventTarget', value: 1, category: 4 },
+ { name: 'SVGElementInstanceList', value: 1, category: 2 },
+ { name: 'SVGUseElement', value: 1, category: 2 },
+ { name: 'SVGEllipseElement', value: 1, category: 2 },
+ { name: 'SVGAnimatedBoolean', value: 1, category: 2 },
+ { name: 'SVGFEBlendElement', value: 1, category: 2 },
+ { name: 'SVGFilterPrimitiveStandardAttributes', value: 1, category: 2 },
+ { name: 'SVGFEColorMatrixElement', value: 1, category: 2 },
+ { name: 'SVGFEComponentTransferElement', value: 1, category: 2 },
+ { name: 'SVGFECompositeElement', value: 1, category: 2 },
+ { name: 'SVGFEConvolveMatrixElement', value: 1, category: 2 },
+ { name: 'SVGAnimatedInteger', value: 1, category: 2 },
+ { name: 'SVGFEDiffuseLightingElement', value: 1, category: 2 },
+ { name: 'SVGFEDisplacementMapElement', value: 1, category: 2 },
+ { name: 'SVGFEDistantLightElement', value: 1, category: 2 },
+ { name: 'SVGFEDropShadowElement', value: 1, category: 2 },
+ { name: 'SVGFEFloodElement', value: 1, category: 2 },
+ { name: 'SVGFEFuncAElement', value: 1, category: 2 },
+ { name: 'SVGFEFuncBElement', value: 1, category: 2 },
+ { name: 'SVGFEFuncGElement', value: 1, category: 2 },
+ { name: 'SVGFEFuncRElement', value: 1, category: 2 },
+ { name: 'SVGFEGaussianBlurElement', value: 1, category: 2 },
+ { name: 'SVGFEImageElement', value: 1, category: 2 },
+ { name: 'SVGFEMergeElement', value: 1, category: 2 },
+ { name: 'SVGFEMergeNodeElement', value: 1, category: 2 },
+ { name: 'SVGFEMorphologyElement', value: 1, category: 2 },
+ { name: 'SVGFEOffsetElement', value: 1, category: 2 },
+ { name: 'SVGFEPointLightElement', value: 1, category: 2 },
+ { name: 'SVGFESpecularLightingElement', value: 1, category: 2 },
+ { name: 'SVGFESpotLightElement', value: 1, category: 2 },
+ { name: 'SVGFETileElement', value: 1, category: 2 },
+ { name: 'SVGFETurbulenceElement', value: 1, category: 2 },
+ { name: 'SVGFilterElement', value: 1, category: 2 },
+ { name: 'SVGFitToViewBox', value: 1, category: 2 },
+ { name: 'SVGFontElement', value: 1, category: 2 },
+ { name: 'SVGFontFaceElement', value: 1, category: 2 },
+ { name: 'SVGFontFaceFormatElement', value: 1, category: 2 },
+ { name: 'SVGFontFaceNameElement', value: 1, category: 2 },
+ { name: 'SVGFontFaceSrcElement', value: 1, category: 2 },
+ { name: 'SVGFontFaceUriElement', value: 1, category: 2 },
+ { name: 'SVGForeignObjectElement', value: 1, category: 2 },
+ { name: 'SVGGElement', value: 1, category: 2 },
+ { name: 'SVGGlyphElement', value: 1, category: 2 },
+ { name: 'SVGGlyphRefElement', value: 1, category: 2 },
+ { name: 'SVGGradientElement', value: 1, category: 2 },
+ { name: 'SVGHKernElement', value: 1, category: 2 },
+ { name: 'SVGImageElement', value: 1, category: 2 },
+ { name: 'SVGLinearGradientElement', value: 1, category: 2 },
+ { name: 'SVGLineElement', value: 1, category: 2 },
+ { name: 'SVGLocatable', value: 1, category: 2 },
+ { name: 'SVGMatrix', value: 1, category: 2 },
+ { name: 'SVGMarkerElement', value: 1, category: 2 },
+ { name: 'SVGMaskElement', value: 1, category: 2 },
+ { name: 'SVGMetadataElement', value: 1, category: 2 },
+ { name: 'SVGMissingGlyphElement', value: 1, category: 2 },
+ { name: 'SVGMPathElement', value: 1, category: 2 },
+ { name: 'SVGNumber', value: 1, category: 2 },
+ { name: 'SVGPaint', value: 1, category: 2 },
+ { name: 'SVGPathElement', value: 1, category: 2 },
+ { name: 'SVGPathSegList', value: 1, category: 2 },
+ { name: 'SVGPathSegArcAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegArcRel', value: 1, category: 2 },
+ { name: 'SVGPathSegClosePath', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoCubicAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoCubicRel', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoCubicSmoothAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoCubicSmoothRel', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoQuadraticAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoQuadraticRel', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoQuadraticSmoothAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegCurvetoQuadraticSmoothRel', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoHorizontalAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoHorizontalRel', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoRel', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoVerticalAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegLinetoVerticalRel', value: 1, category: 2 },
+ { name: 'SVGPathSegMovetoAbs', value: 1, category: 2 },
+ { name: 'SVGPathSegMovetoRel', value: 1, category: 2 },
+ { name: 'SVGPoint', value: 1, category: 2 },
+ { name: 'SVGPathSeg', value: 1, category: 2 },
+ { name: 'SVGPatternElement', value: 1, category: 2 },
+ { name: 'SVGPointList', value: 1, category: 2 },
+ { name: 'SVGPolygonElement', value: 1, category: 2 },
+ { name: 'SVGPolylineElement', value: 1, category: 2 },
+ { name: 'SVGRadialGradientElement', value: 1, category: 2 },
+ { name: 'SVGRectElement', value: 1, category: 2 },
+ { name: 'SVGScriptElement', value: 1, category: 2 },
+ { name: 'SVGSetElement', value: 1, category: 2 },
+ { name: 'SVGStopElement', value: 1, category: 2 },
+ { name: 'SVGStyleElement', value: 1, category: 2 },
+ { name: 'SVGLangSpace', value: 1, category: 2 },
+ { name: 'SVGZoomAndPan', value: 1, category: 2 },
+ { name: 'SVGViewSpec', value: 1, category: 2 },
+ { name: 'SVGTransform', value: 1, category: 2 },
+ { name: 'SVGSwitchElement', value: 1, category: 2 },
+ { name: 'SVGSymbolElement', value: 1, category: 2 },
+ { name: 'SVGTests', value: 1, category: 2 },
+ { name: 'SVGStringList', value: 1, category: 2 },
+ { name: 'SVGTextContentElement', value: 1, category: 2 },
+ { name: 'SVGTextElement', value: 1, category: 2 },
+ { name: 'SVGTextPathElement', value: 1, category: 2 },
+ { name: 'SVGTextPositioningElement', value: 1, category: 2 },
+ { name: 'SVGTitleElement', value: 1, category: 2 },
+ { name: 'SVGTRefElement', value: 1, category: 2 },
+ { name: 'SVGTSpanElement', value: 1, category: 2 },
+ { name: 'SVGViewElement', value: 1, category: 2 },
+ { name: 'SVGVKernElement', value: 1, category: 2 },
+ { name: 'TextTrackCueList', value: 1, category: 4 },
+ { name: 'TextTrackCue', value: 1, category: 4 },
+ { name: 'Touch', value: 1, category: 4 },
+ { name: 'TouchList', value: 1, category: 4 },
+ { name: 'TreeWalker', value: 1, category: 4 },
+ { name: 'Uint16Array', value: 1, category: 4 },
+ { name: 'Uint32Array', value: 1, category: 4 },
+ { name: 'Uint8ClampedArray', value: 1, category: 4 },
+ { name: 'WebGLRenderingContext', value: 3, category: 1 },
+ { name: 'WebGLProgram', value: 1, category: 1 },
+ { name: 'WebGLBuffer', value: 1, category: 1 },
+ { name: 'WebGLFramebuffer', value: 1, category: 1 },
+ { name: 'WebGLRenderbuffer', value: 1, category: 1 },
+ { name: 'WebGLTexture', value: 1, category: 1 },
+ { name: 'WebGLShader', value: 1, category: 1 },
+ { name: 'WebGLActiveInfo', value: 1, category: 1 },
+ { name: 'WebGLContextAttributes', value: 1, category: 1 },
+ { name: 'WebGLShaderPrecisionFormat', value: 1, category: 1 },
+ { name: 'WebGLUniformLocation', value: 1, category: 1 },
+ { name: 'WebKitAnimationList', value: 1, category: 4 },
+ { name: 'WebKitAnimation', value: 1, category: 4 },
+ { name: 'WebKitCSSFilterValue', value: 1, category: 4 },
+ { name: 'WebKitCSSKeyframeRule', value: 1, category: 4 },
+ { name: 'WebKitCSSKeyframesRule', value: 1, category: 4 },
+ { name: 'WebKitCSSMatrix', value: 1, category: 4 },
+ { name: 'WebKitCSSMixFunctionValue', value: 1, category: 4 },
+ { name: 'WebKitCSSTransformValue', value: 1, category: 4 },
+ { name: 'WebKitNamedFlow', value: 1, category: 4 },
+ { name: 'WebSocket', value: 1, category: 4 },
+ { name: 'Worker', value: 1, category: 4 },
+ { name: 'WorkerLocation', value: 1, category: 4 },
+ { name: 'WorkerNavigator', value: 1, category: 4 },
+ { name: 'XMLHttpRequest', value: 1, category: 4 },
+ { name: 'XMLHttpRequestUpload', value: 1, category: 4 },
+ { name: 'DOMFormData', value: 1, category: 4 },
+ { name: 'XPathEvaluator', value: 1, category: 4 },
+ { name: 'XPathExpression', value: 1, category: 4 },
+ { name: 'XPathNSResolver', value: 1, category: 4 },
+ { name: 'XPathResult', value: 1, category: 4 },
+ { name: 'XSLTProcessor', value: 1, category: 4 },
+ ],
+ links: [
+ { source: 0, target: 1 },
+ { source: 0, target: 2 },
+ { source: 0, target: 3 },
+ { source: 4, target: 4 },
+ { source: 5, target: 4 },
+ { source: 6, target: 7 },
+ { source: 6, target: 8 },
+ { source: 9, target: 3 },
+ { source: 10, target: 9 },
+ { source: 11, target: 12 },
+ { source: 11, target: 9 },
+ { source: 11, target: 13 },
+ { source: 11, target: 14 },
+ { source: 15, target: 16 },
+ { source: 15, target: 17 },
+ { source: 15, target: 0 },
+ { source: 15, target: 18 },
+ { source: 15, target: 9 },
+ { source: 15, target: 11 },
+ { source: 15, target: 19 },
+ { source: 15, target: 20 },
+ { source: 15, target: 21 },
+ { source: 15, target: 22 },
+ { source: 15, target: 23 },
+ { source: 15, target: 24 },
+ { source: 15, target: 25 },
+ { source: 15, target: 26 },
+ { source: 15, target: 27 },
+ { source: 15, target: 28 },
+ { source: 15, target: 29 },
+ { source: 15, target: 30 },
+ { source: 15, target: 31 },
+ { source: 15, target: 32 },
+ { source: 15, target: 4 },
+ { source: 16, target: 1 },
+ { source: 13, target: 14 },
+ { source: 1, target: 15 },
+ { source: 1, target: 1 },
+ { source: 1, target: 14 },
+ { source: 14, target: 3 },
+ { source: 12, target: 1 },
+ { source: 18, target: 1 },
+ { source: 18, target: 14 },
+ { source: 18, target: 3 },
+ { source: 33, target: 34 },
+ { source: 35, target: 33 },
+ { source: 35, target: 36 },
+ { source: 35, target: 37 },
+ { source: 35, target: 38 },
+ { source: 35, target: 39 },
+ { source: 35, target: 34 },
+ { source: 35, target: 40 },
+ { source: 35, target: 41 },
+ { source: 42, target: 43 },
+ { source: 19, target: 1 },
+ { source: 20, target: 1 },
+ { source: 44, target: 7 },
+ { source: 45, target: 46 },
+ { source: 47, target: 48 },
+ { source: 47, target: 49 },
+ { source: 47, target: 39 },
+ { source: 50, target: 44 },
+ { source: 51, target: 52 },
+ { source: 21, target: 1 },
+ { source: 21, target: 9 },
+ { source: 53, target: 5 },
+ { source: 54, target: 55 },
+ { source: 56, target: 55 },
+ { source: 56, target: 57 },
+ { source: 58, target: 55 },
+ { source: 58, target: 59 },
+ { source: 58, target: 60 },
+ { source: 61, target: 55 },
+ { source: 61, target: 62 },
+ { source: 61, target: 59 },
+ { source: 63, target: 55 },
+ { source: 63, target: 57 },
+ { source: 64, target: 65 },
+ { source: 64, target: 66 },
+ { source: 64, target: 67 },
+ { source: 64, target: 68 },
+ { source: 55, target: 55 },
+ { source: 55, target: 60 },
+ { source: 62, target: 55 },
+ { source: 57, target: 55 },
+ { source: 57, target: 65 },
+ { source: 69, target: 55 },
+ { source: 69, target: 57 },
+ { source: 60, target: 70 },
+ { source: 60, target: 62 },
+ { source: 60, target: 55 },
+ { source: 71, target: 55 },
+ { source: 72, target: 65 },
+ { source: 73, target: 74 },
+ { source: 75, target: 73 },
+ { source: 75, target: 76 },
+ { source: 76, target: 77 },
+ { source: 78, target: 79 },
+ { source: 78, target: 80 },
+ { source: 49, target: 81 },
+ { source: 49, target: 78 },
+ { source: 82, target: 5 },
+ { source: 83, target: 84 },
+ { source: 22, target: 1 },
+ { source: 22, target: 14 },
+ { source: 85, target: 80 },
+ { source: 85, target: 86 },
+ { source: 85, target: 87 },
+ { source: 88, target: 89 },
+ { source: 88, target: 90 },
+ { source: 88, target: 88 },
+ { source: 88, target: 91 },
+ { source: 86, target: 92 },
+ { source: 90, target: 93 },
+ { source: 94, target: 7 },
+ { source: 94, target: 8 },
+ { source: 94, target: 95 },
+ { source: 96, target: 7 },
+ { source: 96, target: 97 },
+ { source: 98, target: 85 },
+ { source: 99, target: 88 },
+ { source: 100, target: 60 },
+ { source: 100, target: 96 },
+ { source: 100, target: 101 },
+ { source: 102, target: 103 },
+ { source: 104, target: 102 },
+ { source: 103, target: 102 },
+ { source: 105, target: 103 },
+ { source: 106, target: 7 },
+ { source: 106, target: 107 },
+ { source: 108, target: 109 },
+ { source: 23, target: 1 },
+ { source: 23, target: 14 },
+ { source: 8, target: 7 },
+ { source: 8, target: 109 },
+ { source: 8, target: 110 },
+ { source: 8, target: 8 },
+ { source: 8, target: 57 },
+ { source: 8, target: 6 },
+ { source: 8, target: 46 },
+ { source: 8, target: 45 },
+ { source: 8, target: 95 },
+ { source: 8, target: 111 },
+ { source: 112, target: 7 },
+ { source: 113, target: 7 },
+ { source: 92, target: 114 },
+ { source: 80, target: 98 },
+ { source: 80, target: 85 },
+ { source: 80, target: 115 },
+ { source: 80, target: 116 },
+ { source: 80, target: 87 },
+ { source: 114, target: 80 },
+ { source: 93, target: 89 },
+ { source: 116, target: 80 },
+ { source: 89, target: 99 },
+ { source: 89, target: 89 },
+ { source: 89, target: 117 },
+ { source: 89, target: 88 },
+ { source: 118, target: 119 },
+ { source: 120, target: 81 },
+ { source: 121, target: 80 },
+ { source: 121, target: 122 },
+ { source: 121, target: 120 },
+ { source: 91, target: 89 },
+ { source: 91, target: 123 },
+ { source: 91, target: 81 },
+ { source: 48, target: 81 },
+ { source: 124, target: 119 },
+ { source: 125, target: 4 },
+ { source: 126, target: 98 },
+ { source: 127, target: 119 },
+ { source: 122, target: 127 },
+ { source: 3, target: 5 },
+ { source: 3, target: 3 },
+ { source: 128, target: 5 },
+ { source: 128, target: 128 },
+ { source: 24, target: 1 },
+ { source: 24, target: 13 },
+ { source: 129, target: 130 },
+ { source: 131, target: 132 },
+ { source: 133, target: 134 },
+ { source: 135, target: 7 },
+ { source: 135, target: 95 },
+ { source: 136, target: 137 },
+ { source: 138, target: 137 },
+ { source: 139, target: 137 },
+ { source: 140, target: 141 },
+ { source: 142, target: 137 },
+ { source: 143, target: 137 },
+ { source: 144, target: 137 },
+ { source: 145, target: 137 },
+ { source: 146, target: 137 },
+ { source: 146, target: 147 },
+ { source: 146, target: 95 },
+ { source: 146, target: 148 },
+ { source: 34, target: 137 },
+ { source: 149, target: 7 },
+ { source: 150, target: 137 },
+ { source: 150, target: 95 },
+ { source: 151, target: 137 },
+ { source: 151, target: 149 },
+ { source: 152, target: 137 },
+ { source: 153, target: 137 },
+ { source: 154, target: 137 },
+ { source: 155, target: 137 },
+ { source: 101, target: 8 },
+ { source: 101, target: 135 },
+ { source: 101, target: 149 },
+ { source: 137, target: 8 },
+ { source: 137, target: 149 },
+ { source: 156, target: 137 },
+ { source: 156, target: 157 },
+ { source: 158, target: 137 },
+ { source: 158, target: 149 },
+ { source: 158, target: 147 },
+ { source: 158, target: 148 },
+ { source: 159, target: 137 },
+ { source: 160, target: 149 },
+ { source: 160, target: 7 },
+ { source: 147, target: 137 },
+ { source: 147, target: 149 },
+ { source: 161, target: 137 },
+ { source: 161, target: 157 },
+ { source: 162, target: 137 },
+ { source: 163, target: 137 },
+ { source: 164, target: 137 },
+ { source: 165, target: 137 },
+ { source: 166, target: 137 },
+ { source: 167, target: 137 },
+ { source: 167, target: 157 },
+ { source: 39, target: 137 },
+ { source: 168, target: 137 },
+ { source: 168, target: 48 },
+ { source: 168, target: 147 },
+ { source: 168, target: 95 },
+ { source: 168, target: 148 },
+ { source: 168, target: 114 },
+ { source: 169, target: 137 },
+ { source: 169, target: 147 },
+ { source: 169, target: 95 },
+ { source: 169, target: 148 },
+ { source: 170, target: 137 },
+ { source: 170, target: 147 },
+ { source: 171, target: 137 },
+ { source: 171, target: 147 },
+ { source: 172, target: 137 },
+ { source: 173, target: 137 },
+ { source: 173, target: 70 },
+ { source: 173, target: 108 },
+ { source: 174, target: 137 },
+ { source: 174, target: 149 },
+ { source: 175, target: 137 },
+ { source: 141, target: 137 },
+ { source: 141, target: 176 },
+ { source: 141, target: 177 },
+ { source: 141, target: 178 },
+ { source: 141, target: 179 },
+ { source: 141, target: 180 },
+ { source: 181, target: 137 },
+ { source: 182, target: 137 },
+ { source: 183, target: 137 },
+ { source: 183, target: 95 },
+ { source: 184, target: 137 },
+ { source: 185, target: 137 },
+ { source: 185, target: 147 },
+ { source: 185, target: 148 },
+ { source: 185, target: 157 },
+ { source: 186, target: 137 },
+ { source: 187, target: 137 },
+ { source: 188, target: 137 },
+ { source: 188, target: 147 },
+ { source: 189, target: 149 },
+ { source: 189, target: 188 },
+ { source: 189, target: 7 },
+ { source: 190, target: 137 },
+ { source: 190, target: 147 },
+ { source: 190, target: 108 },
+ { source: 190, target: 95 },
+ { source: 190, target: 148 },
+ { source: 191, target: 137 },
+ { source: 192, target: 137 },
+ { source: 193, target: 137 },
+ { source: 194, target: 137 },
+ { source: 194, target: 95 },
+ { source: 195, target: 137 },
+ { source: 196, target: 137 },
+ { source: 197, target: 137 },
+ { source: 197, target: 147 },
+ { source: 197, target: 95 },
+ { source: 197, target: 189 },
+ { source: 197, target: 149 },
+ { source: 197, target: 148 },
+ { source: 197, target: 7 },
+ { source: 198, target: 137 },
+ { source: 199, target: 137 },
+ { source: 200, target: 137 },
+ { source: 201, target: 137 },
+ { source: 201, target: 70 },
+ { source: 202, target: 137 },
+ { source: 203, target: 137 },
+ { source: 204, target: 137 },
+ { source: 205, target: 137 },
+ { source: 205, target: 202 },
+ { source: 205, target: 149 },
+ { source: 205, target: 206 },
+ { source: 207, target: 137 },
+ { source: 207, target: 149 },
+ { source: 206, target: 137 },
+ { source: 206, target: 149 },
+ { source: 208, target: 137 },
+ { source: 208, target: 147 },
+ { source: 208, target: 95 },
+ { source: 208, target: 148 },
+ { source: 209, target: 137 },
+ { source: 210, target: 137 },
+ { source: 210, target: 180 },
+ { source: 211, target: 137 },
+ { source: 212, target: 137 },
+ { source: 40, target: 141 },
+ { source: 213, target: 214 },
+ { source: 213, target: 215 },
+ { source: 213, target: 216 },
+ { source: 217, target: 213 },
+ { source: 218, target: 219 },
+ { source: 218, target: 214 },
+ { source: 218, target: 220 },
+ { source: 218, target: 221 },
+ { source: 222, target: 215 },
+ { source: 222, target: 223 },
+ { source: 222, target: 224 },
+ { source: 222, target: 216 },
+ { source: 225, target: 214 },
+ { source: 225, target: 220 },
+ { source: 225, target: 216 },
+ { source: 226, target: 215 },
+ { source: 226, target: 226 },
+ { source: 220, target: 219 },
+ { source: 220, target: 214 },
+ { source: 220, target: 221 },
+ { source: 220, target: 216 },
+ { source: 220, target: 225 },
+ { source: 224, target: 216 },
+ { source: 216, target: 227 },
+ { source: 216, target: 214 },
+ { source: 216, target: 221 },
+ { source: 221, target: 218 },
+ { source: 221, target: 227 },
+ { source: 221, target: 220 },
+ { source: 223, target: 216 },
+ { source: 228, target: 5 },
+ { source: 228, target: 228 },
+ { source: 229, target: 5 },
+ { source: 229, target: 229 },
+ { source: 230, target: 5 },
+ { source: 230, target: 230 },
+ { source: 231, target: 231 },
+ { source: 232, target: 233 },
+ { source: 234, target: 219 },
+ { source: 177, target: 176 },
+ { source: 25, target: 12 },
+ { source: 25, target: 141 },
+ { source: 235, target: 236 },
+ { source: 236, target: 235 },
+ { source: 237, target: 238 },
+ { source: 237, target: 239 },
+ { source: 233, target: 240 },
+ { source: 26, target: 12 },
+ { source: 26, target: 233 },
+ { source: 27, target: 12 },
+ { source: 27, target: 233 },
+ { source: 241, target: 233 },
+ { source: 240, target: 242 },
+ { source: 243, target: 244 },
+ { source: 115, target: 117 },
+ { source: 245, target: 7 },
+ { source: 246, target: 95 },
+ { source: 246, target: 7 },
+ { source: 97, target: 7 },
+ { source: 247, target: 131 },
+ { source: 247, target: 104 },
+ { source: 247, target: 105 },
+ { source: 247, target: 248 },
+ { source: 247, target: 129 },
+ { source: 249, target: 250 },
+ { source: 251, target: 232 },
+ { source: 7, target: 97 },
+ { source: 7, target: 95 },
+ { source: 7, target: 7 },
+ { source: 7, target: 8 },
+ { source: 252, target: 7 },
+ { source: 253, target: 252 },
+ { source: 253, target: 7 },
+ { source: 95, target: 7 },
+ { source: 254, target: 7 },
+ { source: 255, target: 256 },
+ { source: 257, target: 255 },
+ { source: 257, target: 87 },
+ { source: 258, target: 259 },
+ { source: 28, target: 12 },
+ { source: 28, target: 14 },
+ { source: 28, target: 32 },
+ { source: 29, target: 1 },
+ { source: 260, target: 52 },
+ { source: 260, target: 261 },
+ { source: 260, target: 262 },
+ { source: 132, target: 133 },
+ { source: 263, target: 264 },
+ { source: 265, target: 7 },
+ { source: 265, target: 70 },
+ { source: 266, target: 95 },
+ { source: 107, target: 7 },
+ { source: 107, target: 94 },
+ { source: 107, target: 107 },
+ { source: 107, target: 46 },
+ { source: 107, target: 45 },
+ { source: 68, target: 64 },
+ { source: 67, target: 64 },
+ { source: 267, target: 4 },
+ { source: 267, target: 5 },
+ { source: 268, target: 269 },
+ { source: 268, target: 241 },
+ { source: 268, target: 270 },
+ { source: 268, target: 233 },
+ { source: 268, target: 271 },
+ { source: 268, target: 267 },
+ { source: 268, target: 272 },
+ { source: 271, target: 269 },
+ { source: 272, target: 273 },
+ { source: 274, target: 275 },
+ { source: 30, target: 1 },
+ { source: 276, target: 277 },
+ { source: 111, target: 94 },
+ { source: 111, target: 8 },
+ { source: 111, target: 7 },
+ { source: 111, target: 95 },
+ { source: 111, target: 106 },
+ { source: 278, target: 279 },
+ { source: 278, target: 244 },
+ { source: 280, target: 84 },
+ { source: 239, target: 176 },
+ { source: 239, target: 2 },
+ { source: 238, target: 239 },
+ { source: 281, target: 282 },
+ { source: 283, target: 284 },
+ { source: 285, target: 281 },
+ { source: 286, target: 287 },
+ { source: 288, target: 286 },
+ { source: 289, target: 290 },
+ { source: 291, target: 292 },
+ { source: 293, target: 292 },
+ { source: 74, target: 292 },
+ { source: 294, target: 295 },
+ { source: 296, target: 289 },
+ { source: 77, target: 296 },
+ { source: 297, target: 298 },
+ { source: 297, target: 299 },
+ { source: 300, target: 301 },
+ { source: 70, target: 59 },
+ { source: 70, target: 7 },
+ { source: 70, target: 70 },
+ { source: 302, target: 70 },
+ { source: 303, target: 304 },
+ { source: 303, target: 305 },
+ { source: 306, target: 307 },
+ { source: 308, target: 309 },
+ { source: 310, target: 307 },
+ { source: 311, target: 312 },
+ { source: 313, target: 314 },
+ { source: 315, target: 316 },
+ { source: 317, target: 318 },
+ { source: 319, target: 320 },
+ { source: 321, target: 322 },
+ { source: 323, target: 324 },
+ { source: 325, target: 326 },
+ { source: 327, target: 312 },
+ { source: 328, target: 312 },
+ { source: 329, target: 312 },
+ { source: 312, target: 330 },
+ { source: 312, target: 307 },
+ { source: 331, target: 304 },
+ { source: 331, target: 315 },
+ { source: 332, target: 304 },
+ { source: 332, target: 333 },
+ { source: 334, target: 65 },
+ { source: 334, target: 67 },
+ { source: 335, target: 307 },
+ { source: 335, target: 336 },
+ { source: 335, target: 319 },
+ { source: 335, target: 333 },
+ { source: 337, target: 338 },
+ { source: 337, target: 315 },
+ { source: 339, target: 304 },
+ { source: 340, target: 341 },
+ { source: 157, target: 342 },
+ { source: 307, target: 8 },
+ { source: 307, target: 342 },
+ { source: 307, target: 307 },
+ { source: 343, target: 344 },
+ { source: 343, target: 345 },
+ { source: 343, target: 307 },
+ { source: 343, target: 346 },
+ { source: 343, target: 343 },
+ { source: 345, target: 343 },
+ { source: 347, target: 304 },
+ { source: 347, target: 315 },
+ { source: 338, target: 348 },
+ { source: 349, target: 350 },
+ { source: 349, target: 305 },
+ { source: 349, target: 333 },
+ { source: 351, target: 350 },
+ { source: 351, target: 305 },
+ { source: 351, target: 333 },
+ { source: 351, target: 319 },
+ { source: 352, target: 350 },
+ { source: 352, target: 305 },
+ { source: 353, target: 350 },
+ { source: 353, target: 305 },
+ { source: 353, target: 336 },
+ { source: 353, target: 333 },
+ { source: 354, target: 350 },
+ { source: 354, target: 336 },
+ { source: 354, target: 333 },
+ { source: 354, target: 305 },
+ { source: 354, target: 319 },
+ { source: 354, target: 355 },
+ { source: 354, target: 348 },
+ { source: 356, target: 350 },
+ { source: 356, target: 336 },
+ { source: 356, target: 305 },
+ { source: 357, target: 350 },
+ { source: 357, target: 305 },
+ { source: 357, target: 336 },
+ { source: 357, target: 333 },
+ { source: 358, target: 307 },
+ { source: 358, target: 336 },
+ { source: 359, target: 350 },
+ { source: 359, target: 336 },
+ { source: 359, target: 305 },
+ { source: 360, target: 350 },
+ { source: 361, target: 335 },
+ { source: 362, target: 335 },
+ { source: 363, target: 335 },
+ { source: 364, target: 335 },
+ { source: 365, target: 350 },
+ { source: 365, target: 305 },
+ { source: 365, target: 336 },
+ { source: 366, target: 350 },
+ { source: 366, target: 321 },
+ { source: 367, target: 350 },
+ { source: 368, target: 307 },
+ { source: 368, target: 305 },
+ { source: 369, target: 350 },
+ { source: 369, target: 305 },
+ { source: 369, target: 333 },
+ { source: 369, target: 336 },
+ { source: 370, target: 350 },
+ { source: 370, target: 336 },
+ { source: 370, target: 305 },
+ { source: 371, target: 307 },
+ { source: 371, target: 336 },
+ { source: 372, target: 350 },
+ { source: 372, target: 305 },
+ { source: 372, target: 336 },
+ { source: 373, target: 307 },
+ { source: 373, target: 336 },
+ { source: 374, target: 350 },
+ { source: 374, target: 305 },
+ { source: 375, target: 350 },
+ { source: 375, target: 336 },
+ { source: 375, target: 355 },
+ { source: 375, target: 333 },
+ { source: 376, target: 341 },
+ { source: 376, target: 355 },
+ { source: 376, target: 333 },
+ { source: 376, target: 315 },
+ { source: 350, target: 341 },
+ { source: 350, target: 315 },
+ { source: 350, target: 305 },
+ { source: 377, target: 321 },
+ { source: 377, target: 323 },
+ { source: 378, target: 307 },
+ { source: 379, target: 307 },
+ { source: 380, target: 307 },
+ { source: 381, target: 307 },
+ { source: 382, target: 307 },
+ { source: 383, target: 307 },
+ { source: 384, target: 304 },
+ { source: 384, target: 315 },
+ { source: 385, target: 304 },
+ { source: 386, target: 307 },
+ { source: 387, target: 341 },
+ { source: 388, target: 341 },
+ { source: 388, target: 325 },
+ { source: 388, target: 333 },
+ { source: 389, target: 307 },
+ { source: 390, target: 304 },
+ { source: 390, target: 315 },
+ { source: 390, target: 321 },
+ { source: 318, target: 316 },
+ { source: 391, target: 388 },
+ { source: 391, target: 315 },
+ { source: 392, target: 304 },
+ { source: 392, target: 315 },
+ { source: 393, target: 307 },
+ { source: 393, target: 324 },
+ { source: 393, target: 394 },
+ { source: 395, target: 377 },
+ { source: 395, target: 315 },
+ { source: 395, target: 333 },
+ { source: 395, target: 313 },
+ { source: 395, target: 314 },
+ { source: 396, target: 341 },
+ { source: 396, target: 315 },
+ { source: 396, target: 333 },
+ { source: 394, target: 394 },
+ { source: 397, target: 307 },
+ { source: 398, target: 307 },
+ { source: 399, target: 338 },
+ { source: 320, target: 400 },
+ { source: 401, target: 334 },
+ { source: 402, target: 304 },
+ { source: 402, target: 403 },
+ { source: 402, target: 336 },
+ { source: 402, target: 404 },
+ { source: 402, target: 405 },
+ { source: 402, target: 406 },
+ { source: 402, target: 407 },
+ { source: 402, target: 408 },
+ { source: 402, target: 409 },
+ { source: 402, target: 410 },
+ { source: 402, target: 411 },
+ { source: 402, target: 412 },
+ { source: 402, target: 413 },
+ { source: 402, target: 414 },
+ { source: 402, target: 415 },
+ { source: 402, target: 416 },
+ { source: 402, target: 417 },
+ { source: 402, target: 418 },
+ { source: 402, target: 419 },
+ { source: 402, target: 420 },
+ { source: 402, target: 421 },
+ { source: 402, target: 422 },
+ { source: 402, target: 423 },
+ { source: 404, target: 424 },
+ { source: 405, target: 424 },
+ { source: 406, target: 424 },
+ { source: 407, target: 424 },
+ { source: 408, target: 424 },
+ { source: 409, target: 424 },
+ { source: 410, target: 424 },
+ { source: 411, target: 424 },
+ { source: 412, target: 424 },
+ { source: 413, target: 424 },
+ { source: 414, target: 424 },
+ { source: 415, target: 424 },
+ { source: 416, target: 424 },
+ { source: 417, target: 424 },
+ { source: 418, target: 424 },
+ { source: 419, target: 424 },
+ { source: 420, target: 424 },
+ { source: 403, target: 424 },
+ { source: 421, target: 424 },
+ { source: 422, target: 424 },
+ { source: 425, target: 377 },
+ { source: 425, target: 315 },
+ { source: 425, target: 333 },
+ { source: 425, target: 325 },
+ { source: 423, target: 423 },
+ { source: 426, target: 423 },
+ { source: 427, target: 304 },
+ { source: 427, target: 426 },
+ { source: 428, target: 304 },
+ { source: 428, target: 426 },
+ { source: 429, target: 388 },
+ { source: 429, target: 315 },
+ { source: 430, target: 304 },
+ { source: 430, target: 315 },
+ { source: 431, target: 338 },
+ { source: 432, target: 312 },
+ { source: 433, target: 341 },
+ { source: 433, target: 336 },
+ { source: 341, target: 305 },
+ { source: 341, target: 57 },
+ { source: 341, target: 65 },
+ { source: 434, target: 435 },
+ { source: 342, target: 436 },
+ { source: 342, target: 423 },
+ { source: 342, target: 437 },
+ { source: 342, target: 315 },
+ { source: 342, target: 324 },
+ { source: 342, target: 307 },
+ { source: 342, target: 314 },
+ { source: 342, target: 316 },
+ { source: 342, target: 394 },
+ { source: 342, target: 400 },
+ { source: 342, target: 438 },
+ { source: 342, target: 8 },
+ { source: 342, target: 95 },
+ { source: 439, target: 304 },
+ { source: 440, target: 377 },
+ { source: 441, target: 442 },
+ { source: 443, target: 341 },
+ { source: 443, target: 333 },
+ { source: 443, target: 315 },
+ { source: 443, target: 423 },
+ { source: 443, target: 324 },
+ { source: 444, target: 304 },
+ { source: 445, target: 309 },
+ { source: 445, target: 333 },
+ { source: 445, target: 315 },
+ { source: 446, target: 443 },
+ { source: 446, target: 317 },
+ { source: 446, target: 319 },
+ { source: 447, target: 341 },
+ { source: 438, target: 394 },
+ { source: 304, target: 393 },
+ { source: 304, target: 325 },
+ { source: 326, target: 438 },
+ { source: 448, target: 309 },
+ { source: 449, target: 446 },
+ { source: 309, target: 305 },
+ { source: 346, target: 304 },
+ { source: 346, target: 343 },
+ { source: 346, target: 315 },
+ { source: 450, target: 436 },
+ { source: 450, target: 442 },
+ { source: 437, target: 321 },
+ { source: 437, target: 326 },
+ { source: 437, target: 323 },
+ { source: 437, target: 307 },
+ { source: 451, target: 307 },
+ { source: 43, target: 44 },
+ { source: 43, target: 43 },
+ { source: 180, target: 452 },
+ { source: 180, target: 453 },
+ { source: 453, target: 180 },
+ { source: 453, target: 94 },
+ { source: 452, target: 453 },
+ { source: 179, target: 180 },
+ { source: 454, target: 344 },
+ { source: 455, target: 454 },
+ { source: 456, target: 7 },
+ { source: 456, target: 252 },
+ { source: 457, target: 5 },
+ { source: 457, target: 457 },
+ { source: 458, target: 5 },
+ { source: 458, target: 458 },
+ { source: 2, target: 5 },
+ { source: 2, target: 2 },
+ { source: 459, target: 2 },
+ { source: 459, target: 459 },
+ { source: 31, target: 1 },
+ { source: 31, target: 3 },
+ { source: 460, target: 33 },
+ { source: 460, target: 461 },
+ { source: 460, target: 462 },
+ { source: 460, target: 463 },
+ { source: 460, target: 464 },
+ { source: 460, target: 465 },
+ { source: 460, target: 4 },
+ { source: 460, target: 5 },
+ { source: 460, target: 466 },
+ { source: 460, target: 467 },
+ { source: 460, target: 468 },
+ { source: 460, target: 469 },
+ { source: 460, target: 470 },
+ { source: 460, target: 36 },
+ { source: 460, target: 39 },
+ { source: 460, target: 34 },
+ { source: 460, target: 40 },
+ { source: 460, target: 3 },
+ { source: 471, target: 472 },
+ { source: 473, target: 72 },
+ { source: 474, target: 55 },
+ { source: 474, target: 57 },
+ { source: 475, target: 55 },
+ { source: 475, target: 62 },
+ { source: 475, target: 474 },
+ { source: 476, target: 476 },
+ { source: 477, target: 72 },
+ { source: 478, target: 72 },
+ { source: 479, target: 95 },
+ { source: 480, target: 4 },
+ { source: 480, target: 5 },
+ { source: 481, target: 279 },
+ { source: 84, target: 222 },
+ { source: 84, target: 482 },
+ { source: 84, target: 483 },
+ { source: 84, target: 84 },
+ { source: 84, target: 257 },
+ { source: 84, target: 73 },
+ { source: 84, target: 76 },
+ { source: 84, target: 126 },
+ { source: 84, target: 99 },
+ { source: 84, target: 89 },
+ { source: 484, target: 485 },
+ { source: 484, target: 4 },
+ { source: 484, target: 5 },
+ { source: 484, target: 486 },
+ { source: 487, target: 488 },
+ { source: 487, target: 489 },
+ { source: 487, target: 490 },
+ { source: 488, target: 490 },
+ { source: 490, target: 7 },
+ { source: 491, target: 7 },
+ { source: 491, target: 94 },
+ ],
+ }
+ const option = {
+ legend: {
+ data: ['HTMLElement', 'WebGL', 'SVG', 'CSS', 'Other'],
+ },
+ series: [
+ {
+ type: 'graph',
+ layout: 'force',
+ animation: false,
+ label: {
+ normal: {
+ position: 'right',
+ formatter: '{b}',
+ },
+ },
+ draggable: true,
+ data: webkitDep.nodes.map((node, idx) => {
+ node.id = idx
+ return node
+ }),
+ categories: webkitDep.categories,
+ force: {
+ edgeLength: 5,
+ repulsion: 20,
+ gravity: 0.2,
+ },
+ edges: webkitDep.links,
+ },
+ ],
+ }
+ return option
+ }
+
+ return (
+
+
+ render a graph-webkit-dep.
+
+
+
+ )
+}
+
+export default GraphComponent
diff --git a/src/pages/chart/ECharts/LiquidfillComponent.js b/src/pages/chart/ECharts/LiquidfillComponent.js
new file mode 100644
index 0000000..b119217
--- /dev/null
+++ b/src/pages/chart/ECharts/LiquidfillComponent.js
@@ -0,0 +1,32 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+require('echarts-liquidfill')
+
+const LiquidfillComponent = () => {
+ const option = {
+ series: [
+ {
+ type: 'liquidFill',
+ data: [0.6],
+ },
+ ],
+ }
+ return (
+
+
+ render a Liquidfill chart:
+
+
+
+ )
+}
+
+export default LiquidfillComponent
diff --git a/src/pages/chart/ECharts/LunarCalendarComponent.js b/src/pages/chart/ECharts/LunarCalendarComponent.js
new file mode 100644
index 0000000..0d4e7c4
--- /dev/null
+++ b/src/pages/chart/ECharts/LunarCalendarComponent.js
@@ -0,0 +1,490 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+import * as 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 (
+
+
+ render a lunar calendar chart.
+
+
+
+ )
+}
+
+export default LunarCalendarComponent
diff --git a/src/pages/chart/ECharts/MainPageComponent.js b/src/pages/chart/ECharts/MainPageComponent.js
new file mode 100644
index 0000000..ed0a5cd
--- /dev/null
+++ b/src/pages/chart/ECharts/MainPageComponent.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import AdSense from 'react-adsense'
+import { Link } from 'umi'
+import DynamicChartComponent from './DynamicChartComponent.js'
+
+const MainPageComponent = () => {
+ return (
+
+
echarts-for-react {this.props.params.type}
+
+ {' '}
+ A very simple echarts(v3.0) wrapper for React.{' '}
+
+ hustcc/echarts-for-react
+
+
+
+
+
+
+ Simple demo |
+ Echarts loading |
+ Echarts API |
+ Echarts events |
+ Echarts theme |
+ Dynamic chart |
+ Map chart
+
+
+ New
+ :
+ Airport |
+ Graph |
+ Calendar |
+ Treemap |
+ Gauge |
+ GCalendar |
+ Lunar |
+ Liquidfill
+
+ {this.props.children ||
}
+
+
+
+ )
+}
+
+export default MainPageComponent
diff --git a/src/pages/chart/ECharts/MapChartComponent.js b/src/pages/chart/ECharts/MapChartComponent.js
new file mode 100644
index 0000000..d272e90
--- /dev/null
+++ b/src/pages/chart/ECharts/MapChartComponent.js
@@ -0,0 +1,209 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+require('./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" +
+ ' "
+ return (
+
+
+
+ {' '}
+ render a china map. MAP charts :{' '}
+
+
+
code below:
+
+ {code}
+
+
+
+ )
+ }
+}
+
+export default MapChartComponent
diff --git a/src/pages/chart/ECharts/ModuleLoadChartComponent.js b/src/pages/chart/ECharts/ModuleLoadChartComponent.js
new file mode 100644
index 0000000..852fcdb
--- /dev/null
+++ b/src/pages/chart/ECharts/ModuleLoadChartComponent.js
@@ -0,0 +1,55 @@
+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 =
+ ' "
+ return (
+
+
+
+ {' '}
+ load echarts module as you wish
+ reduce the file size
+ :{' '}
+
+
+
code below:
+
+ {code}
+
+
+
+ )
+}
+
+export default ModuleLoadChartComponent
diff --git a/src/pages/chart/ECharts/SimpleChartComponent.js b/src/pages/chart/ECharts/SimpleChartComponent.js
new file mode 100644
index 0000000..4028029
--- /dev/null
+++ b/src/pages/chart/ECharts/SimpleChartComponent.js
@@ -0,0 +1,90 @@
+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 =
+ ' "
+ return (
+
+
+
+ {' '}
+ render a Simple echart With option and height :{' '}
+
+
+
code below:
+
+ {code}
+
+
+
+ )
+}
+
+export default SimpleChartComponent
diff --git a/src/pages/chart/ECharts/ThemeChartComponent.js b/src/pages/chart/ECharts/ThemeChartComponent.js
new file mode 100644
index 0000000..7b81688
--- /dev/null
+++ b/src/pages/chart/ECharts/ThemeChartComponent.js
@@ -0,0 +1,127 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+
+import * as 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' +
+ ' "
+ return (
+
+
+
+ {' '}
+ render a echart With theme , should{' '}
+ echarts.registerTheme(themeName, themeObj) before
+ use.
+
+
+
+ {' '}
+ the theme object format:
+ https://github.com/ecomfe/echarts/blob/master/theme/dark.js
+
+
+ {code}
+
+
+
+ )
+}
+
+export default ThemeChartComponent
diff --git a/src/pages/chart/ECharts/TransparentBar3DComPonent.js b/src/pages/chart/ECharts/TransparentBar3DComPonent.js
new file mode 100644
index 0000000..63d0740
--- /dev/null
+++ b/src/pages/chart/ECharts/TransparentBar3DComPonent.js
@@ -0,0 +1,302 @@
+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 (
+
+ )
+}
+
+export default TransparentBar3DComPonent
diff --git a/src/pages/chart/ECharts/TreemapComponent.js b/src/pages/chart/ECharts/TreemapComponent.js
new file mode 100644
index 0000000..aec590d
--- /dev/null
+++ b/src/pages/chart/ECharts/TreemapComponent.js
@@ -0,0 +1,275 @@
+import React from 'react'
+import ReactEcharts from 'echarts-for-react'
+import * as 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 [
+ `${formatUtil.encodeHTML(
+ treePath.join('/')
+ )}
`,
+ `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 (
+
+
+ render a disk usage treemap.
+
+
+
+ )
+}
+
+export default TreemapComponent
diff --git a/src/pages/chart/ECharts/index.js b/src/pages/chart/ECharts/index.js
new file mode 100644
index 0000000..0e0a2e1
--- /dev/null
+++ b/src/pages/chart/ECharts/index.js
@@ -0,0 +1,115 @@
+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',
+ },
+]
+
+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 (
+
+
+
+
+
+
+
+ )
+ }
+}
+
+export default Chart
diff --git a/src/pages/chart/ECharts/index.less b/src/pages/chart/ECharts/index.less
new file mode 100644
index 0000000..7a42d68
--- /dev/null
+++ b/src/pages/chart/ECharts/index.less
@@ -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;
+ }
+}
diff --git a/src/pages/chart/ECharts/map/js/china.js b/src/pages/chart/ECharts/map/js/china.js
new file mode 100644
index 0000000..12dabff
--- /dev/null
+++ b/src/pages/chart/ECharts/map/js/china.js
@@ -0,0 +1,46 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['exports', 'echarts'], factory);
+ } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
+ // CommonJS
+ factory(exports, require('echarts'));
+ } else {
+ // Browser globals
+ factory({}, root.echarts);
+ }
+}(this, function (exports, echarts) {
+ var log = function (msg) {
+ if (typeof console !== 'undefined') {
+ console && console.error && console.error(msg);
+ }
+ }
+ if (!echarts) {
+ log('ECharts is not Loaded');
+ return;
+ }
+ if (!echarts.registerMap) {
+ log('ECharts Map is not loaded')
+ return;
+ }
+ echarts.registerMap('china', {"type":"FeatureCollection","features":[{"type":"Feature","id":"710000","properties":{"id":"710000","cp":[121.509062,24.044332],"name":"台湾","childNum":6},"geometry":{"type":"MultiPolygon","coordinates":[["@@°Ü¯Û"],["@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚänÜƤɊĂǀĆĴĤNJŨxĚĮǂƺòƌâÔ®ĮXŦţƸZûÐƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ¿@ăƑ¥ĘWǬÏĶŁâ"],["@@\\p|WoYG¿¥Ij@¢"],["@@
¡@V^RqBbAnTXeRz¤L«³I"],["@@ÆEEkWqë @"],["@@fced"],["@@¯ɜÄèaì¯ØǓIġĽ"],["@@çûĖëĄhòř "]],"encodeOffsets":[[[122886,24033]],[[123335,22980]],[[122375,24193]],[[122518,24117]],[[124427,22618]],[[124862,26043]],[[126259,26318]],[[127671,26683]]]}},{"type":"Feature","id":"130000","properties":{"id":"130000","cp":[114.502461,38.045474],"name":"河北","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@o~Z]ªrºc_ħ²G¼s`jΟnüsÂłNX_M`ǽÓnUK
Ĝēs¤©yrý§uģcJe"],["@@U`Ts¿mÂ"],["@@oºƋÄdeVDJj£J|ÅdzÂFt~KŨ¸IÆv|¢r}èonb}`RÎÄn°ÒdÞ²^®lnÐèĄlðÓ×]ªÆ}LiñÖ`^°Ç¶p®đDcŋ`ZÔ¶êqvFÆN®ĆTH®¦O¾IbÐã´BĐɢŴÆíȦpĐÞXR·nndO¤OÀĈƒQgµFo|gȒęSWb©osx|hYhgŃfmÖĩnºTÌSp¢dYĤ¶UĈjlǐpäìë|³kÛfw²Xjz~ÂqbTÑěŨ@|oMzv¢ZrÃVw¬ŧˏf°ÐTªqs{S¯r æÝlNd®²Ğ džiGĘJ¼lr}~K¨ŸƐÌWöÆzR¤lêmĞLÎ@¡|q]SvKÑcwpÏÏĿćènĪWlĄkT}J¤~ÈTdpddʾĬBVtEÀ¢ôPĎƗè@~kü\\rÊĔÖæW_§¼F´©òDòjYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkvGpuARhÞÆǶgĘTǼƹS£¨¡ù³ŘÍ]¿ÂyôEP xX¶¹ÜO¡gÚ¡IwÃé¦ÅBÏ|ǰ
N«úmH¯âDùyŜŲIÄuШD¸dɂFOhđ©OiÃ`ww^ÌkÑH«ƇǤŗĺtFu
{Z}Ö@U´
ʚLg®¯Oı°Ãw ^VbÉsmA
ê]]w§RRl£ȭµu¯b{ÍDěïÿȧuT£ġěŗƃĝQ¨fVƋƅna@³@ďyýIĹÊKŭfċŰóxV@tƯJ]eR¾fe|rHA|h~Ėƍl§ÏlTíb ØoÅbbx³^zÃͶSj®AyÂhðk`«P˵EFÛ¬Y¨Ļrõqi¼Wi°§Ð±´°^[À|ĠO@ÆxO\\ta\\tĕtû{ġȧXýĪÓjùÎRb^ÎfK[ÝděYfíÙTyuUSyŌŏů@Oi½éŅaVcř§ax¹XŻácWU£ôãºQ¨÷Ñws¥qEHÙ|šYQoŕÇyáĂ£MðoťÊP¡mWO¡v{ôvîēÜISpÌhp¨ jdeŔQÖjX³àĈ[n`Yp@UcM`RKhEbpŞlNut®EtqnsÁgAiúoHqCXhfgu~ÏWP½¢G^}¯ÅīGCÑ^ãziMáļMTÃƘrMc|O_¯Ŏ´|morDkO\\mĆJfl@c̬¢aĦtRıÒ¾ùƀ^juųœKUFyƝ
īÛ÷ąV×qƥV¿aȉd³BqPBmaËđŻģmÅ®V¹d^KKonYg¯XhqaLdu¥ÍpDž¡KąÅkĝęěhq}HyÃ]¹ǧ£
Í÷¿qáµ§g¤o^á¾ZE¤i`ij{nOl»WÝĔįhgF[¿¡ßkOüš_ūiDZàUtėGyl}ÓM}jpEC~¡FtoQiHkk{Ãmï"]],"encodeOffsets":[[[119712,40641]],[[121616,39981]],[[116462,37237]]]}},{"type":"Feature","id":"140000","properties":{"id":"140000","cp":[111.849248,36.857014],"name":"山西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ÞĩÒSra}ÁyWix±Üe´lèßÓǏokćiµVZģ¡coTS˹ĪmnÕńehZg{gtwªpXaĚThȑp{¶Eh®RćƑP¿£Pmc¸mQÝWďȥoÅîɡųAďä³aÏJ½¥PGąSM
EÅruµéYÓŌ_dĒCoȵ]¯_²ÕjāK~©ÅØ^ÔkïçămÏk]±cݯÑÃmQÍ~_apm
~ç¡qu{JÅŧ·Ls}EyÁÆcI{¤IiCfUcƌÃp§]ě«vD@¡SÀµMÅwuYY¡DbÑc¡h×]nkoQdaMç~eDÛtT©±@¥ù@É¡ZcW|WqOJmĩl«ħşvOÓ«IqăV¥D[mI~Ó¢cehiÍ]Ɠ~ĥqX·eƷn±}v[ěďŕ]_œ`¹§ÕōIo©bs^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs×¥ŅxÊdÒ{ºvĴÎêÌɊ²¶ü¨|ÞƸµȲLLúÉƎ¤ϊęĔV`_bªS^|dzY|dz¥pZbÆ£¶ÒK}tĦÔņƠPYznÍvX¶Ěn ĠÔzý¦ª÷ÑĸÙUȌ¸dòÜJð´ìúNM¬XZ´¤ŊǸ_tldI{¦ƀðĠȤ¥NehXnYGR° ƬDj¬¸|CĞKqºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBÊTŸʂōĖĴŞȀÆÿȄlŤĒötνî¼ĨXh|ªM¤Ðz"],"encodeOffsets":[[116874,41716]]}},{"type":"Feature","id":"150000","properties":{"id":"150000","cp":[111.670801,41.818311],"name":"内蒙古","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@¯PqFB
|S³C|kñHdiÄ¥sʼnÅ
PóÑÑE^ÅPpy_YtShQ·aHwsOnʼnÃs©iqjUSiº]ïW«gW¡ARë¥_sgÁnUI«m
]jvV¼euhwqAaW_µj
»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáGOUÛOB±XkŹ£k|e]olkVͼÕqtaÏõjgÁ£§U^RLËnX°ÇBz^~wfvypV ¯ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyxþp]ÉvïèvƀnÂĴÖ@V~Ĉv¦wĖtējyÄDXÄxGQuv_i¦aBçw˛wD©{tāmQ{EJ§KPśƘƿ¥@sCTÉ}ɃwƇy±gÑ}T[÷kÐ禫
SÒ¥¸ëBX½HáŵÀğtSÝÂa[ƣ°¯¦Pï¡]£ġÒk®G²èQ°óMq}EóƐÇ\\@áügQÍu¥FTÕ¿Jû]|mvāÎYua^WoÀa·ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶¿A[¡{d×uQAMxVvMOmăl«ct[wº_ÇÊjb£ĦS_éQZ_lwgOiýe`YYLq§IÁdz£ÙË[ÕªuƏ³ÍTs·bÁĽäė[b[ŗfãcn¥îC¿÷µ[ŏÀQōĉm¿Á^£mJVmL[{Ï_£F¥Ö{ŹA}
×Wu©ÅaųijƳhB{·TQqÙIķËZđ©Yc|M¡
LeVUóK_QWk_ĥ¿ãZ»X\\ĴuUèlG®ěłTĠğDŃOrÍdÆÍz]±
ŭ©Å]ÅÐ}UË¥©TċïxgckfWgi\\ÏĒ¥HkµEë{»ÏetcG±ahUiñiWsɁ·cCÕk]wȑ|ća}w
VaĚá G°ùnM¬¯{ÈÐÆA¥ÄêJxÙ¢hP¢ÛºµwWOóFÁz^ÀŗÎú´§¢T¤ǻƺSėǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇqZñiñC³ª
»E`¨åXēÕqÉû[l}ç@čƘóO¿¡FUsAʽīccocÇS}£IS~ălkĩXçmĈ
ŀÐoÐdxÒuL^T{r@¢ÍĝKén£kQyÅõËXŷƏL§~}kq»IHėDžjĝ»ÑÞoå°qTt|r©ÏS¯·eŨĕx«È[eM¿yupN~¹ÏyN£{©għWí»Í¾səšDž_ÃĀɗ±ąijĉʍŌŷSÉA±åǥɋ@ë£R©ąP©}ĹªƏj¹erLDĝ·{i«ƫC£µsKC
GS|úþXgp{ÁX¿ć{ƱȏñZáĔyoÁhA}ŅĆfdʼn_¹Y°ėǩÑ¡H¯¶oMQqð¡Ë|Ñ`ƭŁX½·óÛxğįÅcQs«tȋDžFù^it«Č¯[hAi©á¥ÇĚ×l|¹y¯YȵƓñǙµïċĻ|Düȭ¶¡oŽäÕG\\ÄT¿Òõr¯LguÏYęRƩɷŌO\\İТæ^Ŋ IJȶȆbÜGĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľ]ėl¥ËĭûÁėéV©±ćn©ȇÍq¯½YÃÔʼnÉNÑÅÝy¹NqáʅDǡËñƁYÅy̱os§ȋµʽǘǏƬɱàưN¢ƔÊuľýľώȪƺɂļxZĈ}ÌʼnŪĺœĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~ǼȳÐUfdIxÿ\\G zâɏÙOº·pqy£@qþ@Ǟ˽IBäƣzsÂZÁàĻdñ°ŕzéØűzșCìDȐĴĺf®Àľưø@ɜÖÞKĊŇƄ§͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФÔ¤ƌĞ̪Qʤ´¼mȠJˀƲÀɠmǐnǔĎȆÞǠN~ʢĜ¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºēĢĖćYÀŎüôQÐÂŎŞdžŞêƖoˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^ªƂ`ªt¾äƚêĦ¼ÐĔǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDÄ|ø˂˜ƮЬɚwɲFjĔ²Äw°dždÀÉ_ĸdîàŎjÊêTЪŌŜWÈ|tqĢUB~´°ÎFCU¼pĀēƄN¦¾O¶łKĊOjĚj´ĜYp{¦SĚÍ\\TתV÷Ší¨ÅDK°ßtŇĔK¨ǵÂcḷ̌ĚǣȄĽFlġUĵŇȣFʉɁMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFxúQEr´Wrh¤Ɛ \\talĈDJÜ|[Pll̚¸ƎGú´P¬W¦^¦H]prRn|or¾wLVnÇIujkmon£cX^Bh`¥V¦U¤¸}xRj[^xN[~ªxQ[`ªHÆÂExx^wN¶Ê|¨ìMrdYpoRzNyÀDs~bcfÌ`L¾n|¾T°c¨È¢ar¤`[|òDŞĔöxElÖdHÀI`Ď\\Àì~ÆR¼tf¦^¢ķ¶eÐÚMptgjɡČÅyġLûŇV®ÄÈƀϰP|ªVVªj¬ĚÒêp¬E|ŬÂc|ÀtƐK f{ĘFĒƌXƲąo½Ę\\¥o}Ûu£çkX{uĩ«āíÓUŅßŢqŤ¥lyň[oi{¦LńðFȪȖĒL¿Ìf£K£ʺoqNwğc`uetOj×°KJ±qÆġmĚŗos¬
qehqsuH{¸kH¡
ÊRǪÇƌbȆ¢´äÜ¢NìÉʖ¦â©Ġu¦öČ^â£ĂhĖMÈÄw\\fŦ°W ¢¾luŸDw\\̀ʉÌÛM
Ā[bÓEn}¶Vc
ês"]],"encodeOffsets":[[[129102,52189]]]}},{"type":"Feature","id":"210000","properties":{"id":"210000","cp":[123.429096,41.796767],"name":"辽宁","childNum":16},"geometry":{"type":"MultiPolygon","coordinates":[["@@L@@sa"],["@@MnNm"],["@@dc"],["@@eÀC@b"],["@@f
XwkbrÄ`qg"],["@@^jtWQ"],["@@~ Y]c"],["@@G`ĔN^_¿ZÃM"],["@@iX¶BY"],["@@YZ"],["@@L_{Epf"],["@@^WqCT\\"],["@@\\[§t|¤_"],["@@m`n_"],["@@Ïxnj{q_×^Giip"],["@@@é^BntaÊU]x ¯ÄPIJ°hʙK³VÕ@Y~|EvĹsǦL^pòŸÒG Ël]xxÄ_fT¤Ď¤cPC¨¸TVjbgH²sdÎdHt`B²¬GJję¶[ÐhjeXdlwhðSȦªVÊÏÆZÆŶ®²^ÎyÅÎcPqńĚDMħĜŁHkçvV[ij¼WYÀäĦ`XlR`ôLUVfK¢{NZdĒªYĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~źB|¦ÕE¤Ð`\\|KUnnI]¤ÀÂĊnŎR®Ő¿¶\\ÀøíDm¦ÎbŨabaĘ\\ľã¸atÎSƐ´©v\\ÖÚÌǴ¤Â¨JKrZ_ZfjþhPkx`YRIjJcVf~sCN¤ EhæmsHy¨SðÑÌ\\\\ĐRZk°IS§fqŒßýáĞÙÉÖ[^¯ǤŲê´\\¦¬ĆPM¯£»uïpùzExanµyoluqe¦W^£ÊL}ñrkqWňûPUP¡ôJoo·U}£[·¨@XĸDXmÛݺGUCÁª½{íĂ^cjk¶Ã[q¤LÉö³cux«zZf²BWÇ®Yß½ve±ÃCý£W{Ú^q^sÑ·¨ÍOt¹·C¥GDrí@wÕKţëV·i}xËÍ÷i©ĝɝǡ]{c±OW³Ya±_ç©HĕoƫŇqr³Lys[ñ³¯OSďOMisZ±ÅFC¥Pq{Ã[Pg}\\¿ghćO
k^ģÁFıĉĥMoEqqZûěʼn³F¦oĵhÕP{¯~TÍlªNßYÐ{Ps{ÃVUeĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀffdF~ĀeĖd`sx² ®EżĀdQÂd^~ăÔH¦\\LKpĄVez¤NP ǹÓRÆąJSha[¦´ÂghwmBШźhI|VV|p] ¼èNä¶ÜBÖ¼L`¼bØæKVpoúNZÞÒKxpw|ÊEMnzEQIZZNBčÚFÜçmĩWĪñtÞĵÇñZ«uD±|Əlij¥ãn·±PmÍada CLǑkùó¡³Ï«QaċÏOÃ¥ÕđQȥċƭy³ÃA"]],"encodeOffsets":[[[123686,41445]],[[126019,40435]],[[124393,40128]],[[126117,39963]],[[125322,40140]],[[126686,40700]],[[126041,40374]],[[125584,40168]],[[125453,40165]],[[125362,40214]],[[125280,40291]],[[125774,39997]],[[125976,40496]],[[125822,39993]],[[125509,40217]],[[122731,40949]]]}},{"type":"Feature","id":"220000","properties":{"id":"220000","cp":[125.3245,43.886841],"name":"吉林","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@pä³PClFbbÍzwBGĭZÅi»lYċ²SgkÇ£^Sqd¯R
©é£¯S\\cZ¹iűƏCuƍÓXoR}M^o£
R}oªUF
uuXHlEÅÏ©¤ÛmTþ¤D²ÄufàÀXXȱAeyYw¬dvõ´KÊ£\\rµÄlidā]|DÂVH¹Þ®ÜWnCķ W§@\\¸~¤Vp¸póIO¢VOŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúv𼤠N°ąO¥«³[éǡű_°Õ\\ÚÊĝþâőàerR¨JYlďQ[ ÏYëЧTGztnß¡gFkMāGÁ¤ia Éȹ`\\xs¬dĆkNnuNUuP@vRY¾\\¢
GªóĄ~RãÖÎĢùđŴÕhQxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp]vbÍZuĂ{n^IüÀSÖ¦EvRÎûh@â[ƏÈô~FNr¯ôçR±HÑlĢ^¤¢OðævxsŒ]ÞÁTĠs¶¿âÆGW¾ìA¦·TѬè¥ÏÐJ¨¼ÒÖ¼ƦɄxÊ~StD@Ă¼Ŵ¡jlºWvÐzƦZвCH AxiukdGgetqmcÛ£Ozy¥cE}|
¾cZ
k¿uŐã[oxGikfeäT@
SUwpiÚFM©£è^Ú`@v¶eňf heP¶täOlÃUgÞzŸU`l}ÔÆUvØ_Ō¬Öi^ĉi§²ÃB~¡ĈÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYxƘDVÇĺĿg¿cwÅ\\¹¥Yĭl¤OvLjM_a W`zļMž·\\swqÝSAqŚij¯°kRē°wx^ĐkǂÒ\\]nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°G³¼XÀ¤¹i´o¤ŃÈ`ÌDzÄUĞd\\iÖmÈBĤÜɲDEh LG¾ƀľ{WaYÍÈĢĘÔRîĐj}ÇccjoUb½{h§Ǿ{KƖµÎ÷GĀÖŠåưÎslyiē«`å§H¥Ae^§GK}iã\\c]v©ģZmÃ|[M}ģTɟĵÂÂ`ÀçmFK¥ÚíÁbX³ÌQÒHof{]ept·GŋĜYünĎųVY^ydõkÅZW«WUa~U·SbwGçǑiW^qFuNĝ·EwUtW·Ýďæ©PuqEzwAVXRãQ`©GMehccďÏd©ÑW_ÏYƅ»
é\\ɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ýL¡ýqT^rme\\PpZZbyuybQefµ]UhĿDCmûvaÙNSkCwncćfv~
YÇG"],"encodeOffsets":[[130196,42528]]}},{"type":"Feature","id":"230000","properties":{"id":"230000","cp":[128.642464,46.756967],"name":"黑龙江","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@UµNÿ¥īèçHÍøƕ¶Lǽ|g¨|a¾pVidd~ÈiíďÓQġėÇZÎXb½|ſÃH½KFgɱCģÛÇAnjÕc[VĝDZÃËÇ_ £ń³pj£º¿»WH´¯U¸đĢmtĜyzzNN|g¸÷äűѱĉā~mq^[ǁÑďlw]¯xQĔ¯l°řĴrBÞTxr[tޏĻN_yX`biNKu
P£kZĮ¦[ºxÆÀdhĹŀUÈƗCwáZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFć}¢A±Äj¨]ĊÕjŋ«×`VuÓÅ~_kŷVÝyhVkÄãPsOµfgeŇ
µf@u_Ù ÙcªNªÙEojVxT@ãSefjlwH\\pŏäÀvlY½d{F~¦dyz¤PÜndsrhfHcvlwjF£G±DÏƥYyÏu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|C˜zxAè¥bfudTrFWÁ¹Am|ĔĕsķÆF´N}ć
UÕ@Áijſmuçuð^ÊýowFzØÎĕNőǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°Uzouxe]}
AyÈW¯ÌmKQ]Īºif¸ÄX|sZt|½ÚUÎ lk^p{f¤lºlÆW A²PVÜPHÊâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi`¶bXrBgxfv»uUi^v~J¬mVp´£´VWrnP½ì¢BX¬hðX¹^TjVriªjtŊÄmtPGx¸bgRsT`ZozÆO]ÒFôÒOÆŊvÅpcGêsx´DR{AEOr°x|íb³Wm~DVjºéNNËܲɶGxŷCSt}]ûōSmtuÇÃĕNāg»íT«u}ç½BĵÞʣ¥ëÊ¡MÛ³ãȅ¡ƋaǩÈÉQG¢·lG|tvgrrf«ptęŘnÅĢrI²¯LiØsPf_vĠdxM prʹL¤¤eËÀđKïÙVY§]Ióáĥ]ķK¥j|pŇ\\kzţ¦šnņäÔVĂîά|vW®l¤èØrxm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄĄ»ƢjȦOǺ¨ìSŖÆƬyQv`cwZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨSfm ĊƀP̎ēz©ĊÄÕÊmgÇsJ¥ƔŊśæÎÑqv¿íUOµªÂnĦÁ_½ä@êí
£P}Ġ[@gġ}gɊ×ûÏWXá¢užƻÌsNͽƎÁ§čŐAēeL³àydl¦ĘVçŁpśdžĽĺſÊQíÜçÛġÔsĕ¬Ǹ¯YßċġHµ ¡eå`ļrĉŘóƢFìĎWøxÊkƈdƬv|I|·©NqńRŀ¤éeŊŀàŀU²ŕƀBQ£Ď}L¹Îk@©ĈuǰųǨÚ§ƈnTËÇéƟÊcfčŤ^XmHĊĕË«W·ċëx³ǔķÐċJāwİ_ĸȀ^ôWr°oú¬Ħ
ŨK~ȰCĐ´Ƕ£fNÎèâw¢XnŮeÂÆĶ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®ØCÔ ŬGƠƦYĜĘÜƬDJg_ͥœ@čŅĻA¶¯@wÎqC½Ĉ»NăëKďÍQÙƫ[«ÃígßÔÇOÝáWñuZ¯ĥŕā¡ÑķJu¤E 寰WKɱ_d_}}vyõu¬ï¹ÓU±½@gÏ¿rýDg
Cdµ°MFYxw¿CG£Rƛ½Õ{]L§{qqą¿BÇƻğëܭNJË|c²}Fµ}ÙRsÓpg±QNqǫŋRwŕnéÑÉK«SeYR
ŋ@{¤SJ}D Ûǖ֍]gr¡µŷjqWÛham³~S«Þ]"]],"encodeOffsets":[[[134456,44547]]]}},{"type":"Feature","id":"320000","properties":{"id":"320000","cp":[119.767413,33.041544],"name":"江苏","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@cþÅPi`ZRu¥É\\]~°Y`µÓ^phÁbnÀşúòaĬºTÖŒbe¦¦{¸ZâćNp©Hr|^mjhSEb\\afv`sz^lkljÄtg¤D¾X¿À|ĐiZȀåB·î}GL¢õcßjayBFµÏC^ĭcÙt¿sğH]j{s©HM¢QnDÀ©DaÜÞ·jgàiDbPufjDk`dPOîhw¡ĥ¥GP²ĐobºrYî¶aHŢ´ ]´rılw³r_{£DB_Ûdåuk|Ũ¯F Cºyr{XFye³Þċ¿ÂkĭB¿MvÛpm`rÚã@ƹhågËÖƿxnlč¶Åì½Ot¾dJlVJĂǀŞqvnO^JZż·Q}êÍÅmµÒ]ƍ¦Dq}¬R^èĂ´ŀĻĊIÔtIJyQŐĠMNtR®òLhĚs©»}OÓGZz¶A\\jĨFäOĤHYJvÞHNiÜaĎÉnFQlNM¤B´ĄNöɂtpŬdfå
qm¿QûùŞÚb¤uŃJŴu»¹ĄlȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Yxcitğ®jű¢KOķCoy`å®VTa_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋÄÄÍīçÛɈǥ£ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ¡RLčiXyÅNïă¡¸iĔÏNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCtOPrE^ÒogĉIµÛÅʹK
¤½phMü`oæŀ"],"encodeOffsets":[[121740,32276]]}},{"type":"Feature","id":"330000","properties":{"id":"330000","cp":[120.153576,29.287459],"name":"浙江","childNum":45},"geometry":{"type":"MultiPolygon","coordinates":[["@@E^dQ]K"],["@@jX^j"],["@@sfbU"],["@@qP\\xz[ck"],["@@R¢FX}°[s_"],["@@Cb\\}"],["@@e|v\\la{u"],["@@v~u}"],["@@QxÂF¯}"],["@@¹nvÞs¯o"],["@@rSkUEj"],["@@biZP"],["@@p[}INf"],["@@À¿"],["@@¹dnb
"],["@@rSBnR"],["@@g~h}"],["@@FlEk"],["@@OdPc"],["@@v[u\\"],["@@FjâL~wyoo~sµL\\"],["@@¬e¹aN"],["@@\\nÔ¡q]L³ë\\ÿ®QÖ"],["@@ÊA©[¬"],["@@Kxv"],["@@@hlIk]"],["@@pW{o||j"],["@@Md|_mC"],["@@¢
X£ÏylD¼XtH"],["@@hlÜ[LykAvyfw^E¤"],["@@fp¤MusR"],["@@®_ma~LÁ¬Z"],["@@iMxZ"],["@@ZcYd"],["@@Z~dOSo|A¿qZv"],["@@@`EN¡v"],["@@|TY{"],["@@@n@m"],["@@XWkCT\\"],["@@ºwZRkĕWO¢"],["@@X®±Grƪ\\ÔáXq{"],["@@ůTG°ĄLHm°UC"],["@@¤aÜx~}dtüGæţŎíĔcŖpMËÐj碷ðĄÆMzjWKĎ¢Q¶À_ê_Bıi«pZgf¤Nrq]§ĂN®«H±yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªÁŖHŗʼnåqûõi¨hÜ·ñt»¹ýv_[«¸mYL¯Qª
mĉÅdMgÇjcº«ę¬K´B«Âącoċ\\xKd¡gěŧ«®á[~ıxu·ÅKsËÉc¢Ù\\ĭƛëbf¹ģSĜkáƉÔĈZB{aMµfzʼnfåÂŧįƋǝÊĕġć£g³neą»@¦S®\\ßðChiqªĭiAuAµ_W¥ƣO\\lċĢttC¨£t`PZäuXßBsĻyekOđġĵHuXBµ]×\\°®¬F¢¾pµ¼kŘó¬Wät¸|@L¨¸µrºù³Ù~§WIZW®±Ð¨ÒÉx`²pĜrOògtÁZ}þÙ]¡FKwsPlU[}¦Rvn`hq¬\\nQ´ĘRWb_ rtČFIÖkĦPJ¶ÖÀÖJĈĄTĚòC ²@Pú
Øz©PCÈÚDZhŖl¬â~nm¨f©iļ«mntuÖZÜÄjL®EÌFª²iÊxبIÈhhst"],["@@o\\VzRZ}y"],["@@@°¡mÛGĕ¨§Ianá[ýƤjfæØLäGr"]],"encodeOffsets":[[[125592,31553]],[[125785,31436]],[[125729,31431]],[[125513,31380]],[[125223,30438]],[[125115,30114]],[[124815,29155]],[[124419,28746]],[[124095,28635]],[[124005,28609]],[[125000,30713]],[[125111,30698]],[[125078,30682]],[[125150,30684]],[[124014,28103]],[[125008,31331]],[[125411,31468]],[[125329,31479]],[[125626,30916]],[[125417,30956]],[[125254,30976]],[[125199,30997]],[[125095,31058]],[[125083,30915]],[[124885,31015]],[[125218,30798]],[[124867,30838]],[[124755,30788]],[[124802,30809]],[[125267,30657]],[[125218,30578]],[[125200,30562]],[[124968,30474]],[[125167,30396]],[[124955,29879]],[[124714,29781]],[[124762,29462]],[[124325,28754]],[[123990,28459]],[[125366,31477]],[[125115,30363]],[[125369,31139]],[[122495,31878]],[[125329,30690]],[[125192,30787]]]}},{"type":"Feature","id":"340000","properties":{"id":"340000","cp":[117.283042,31.26119],"name":"安徽","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@^iuLX^"],["@@e©Ehl"],["@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊzÖgņtÀÁĂÆáhEz|WzqD¹°Eŧl{ævÜcA`¤C`|´qxIJkq^³³GšµbíZ
¹qpa±ď OH¦Ħx¢gPícOl_iCveaOjCh߸iÝbÛªCC¿mRV§¢A|t^iĠGÀtÚsd]ĮÐDE¶zAb àiödK¡~H¸íæAǿYj{ď¿À½W®£ChÃsikkly]_teu[bFaTign{]GqªoĈMYá|·¥f¥őaSÕėNµñĞ«Im_m¿Âa]uĜp
Z_§{Cäg¤°r[_YjÆOdý[I[á·¥Q_nùgL¾mvˊBÜÆ¶ĊJhpc¹O]iŠ]¥ jtsggJǧw×jÉ©±EFËKiÛÃÕYv
sm¬njĻª§emná}k«ŕgđ²ÙDÇ¤í¡ªOy×Où±@DñSęćăÕIÕ¿IµĥOjNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆßF¶X®¿mw
RIÞfßoG³¾©uyHį{Ɓħ¯AFnuP
ÍÔzVdàôº^Ðæd´oG¤{S¬ćxã}ŧ×Kǥĩ«ÕOEзÖdÖsƘѨ[Û^Xr¢¼§xvÄÆµ`K§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē
ßúLÃÃ_ÈÏ|]ÂÏFlg`ben¾¢pUh~ƴ˶_r sĄ~cƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³
]u}f
ïQl{skloNdjäËzDvčoQďHI¦rbtHĔ~BmlRV_ħTLnñH±DL¼Lªl§Ťa¸ĚlK²\\RòvDcÎJbt[¤D@®hh~kt°ǾzÖ@¾ªdbYhüóZ ň¶vHrľ\\ÊJuxAT|dmÀO[ÃÔG·ĚąĐlŪÚpSJ¨ĸLvÞcPæķŨ®mÐálwKhïgA¢ųƩޤOÈm°K´"]],"encodeOffsets":[[[121722,32278]],[[119475,30423]],[[119168,35472]]]}},{"type":"Feature","id":"350000","properties":{"id":"350000","cp":[118.306239,26.075302],"name":"福建","childNum":18},"geometry":{"type":"MultiPolygon","coordinates":[["@@zht´]"],["@@aj^~ĆG©O"],["@@ed¨C}}i"],["@@@vPGsQ"],["@@sBzddW]Q"],["@@S¨Q{"],["@@NVucW"],["@@qptBAq"],["@@¸[mu"],["@@Q\\pD]_"],["@@jSwUadpF"],["@@eXª~"],["@@AjvFso"],["@@fT_Çí\\v|ba¦jZÆy°"],["@@IjJi"],["@@wJIx«¼AoNe{M"],["@@K±¡ÓČäeZ"],["@@k¡¹Eh~c®wBkUplÀ¡I~Māe£bN¨gZý¡a±Öcp©PhI¢Qq
ÇGj|¥U g[Ky¬ŏv@OptÉEF\\@ åA¬V{XģĐBy
cpě
¼³Ăp·¤¥ohqqÚ¡ŅLs^á§qlÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ßėuĕeûÒiÁŧSW¥Qûŗ½ùěcݧSùĩąSWó«íęACµeRåǃRCÒÇZÍ¢ź±^dlstjD¸ZpuÔâÃH¾oLUêÃÔjjēò´ĄWƛ
^Ñ¥Ħ@ÇòmOw¡õyJyD}¢ďÑÈġfZda©º²z£NjD°Ötj¶¬ZSÎ~¾c°¶ÐmxO¸¢Pl´SL|¥AȪĖMņIJg®áIJČĒü` QF¬h|ĂJ@zµ |ê³È ¸UÖŬŬÀEttĸr]ðM¤ĶIJHtÏ AĬkvsq^aÎbvdfÊòSD´Z^xPsĂrvƞŀjJd×ŘÉ ®AΦĤdxĆqAZRÀMźnĊ»İÐZ YXæJyĊ²·¶q§·K@·{sXãô«lŗ¶»o½E¡«¢±¨Y®Ø¶^AvWĶGĒĢPlzfļtàAvWYãO_¤sD§ssČġ[kƤPX¦`¶®BBvĪjv©jx[L¥àï[F
¼ÍË»ğV`«Ip}ccÅĥZEãoP
´B@D¸m±z«Ƴ¿å³BRضWlâþäą`]Z£Tc ĹGµ¶Hm@_©k¾xĨôȉðX«½đCIbćqK³ÁÄš¬OAwã»aLʼnËĥW[ÂGIÂNxij¤D¢îĎÎB§°_JGs¥E@
¤uć
PåcuMuw¢BI¿]zG¹guĮck\\_"]],"encodeOffsets":[[[123250,27563]],[[122541,27268]],[[123020,27189]],[[122916,27125]],[[122887,26845]],[[122808,26762]],[[122568,25912]],[[122778,26197]],[[122515,26757]],[[122816,26587]],[[123388,27005]],[[122450,26243]],[[122578,25962]],[[121255,25103]],[[120987,24903]],[[122339,25802]],[[121042,25093]],[[122439,26024]]]}},{"type":"Feature","id":"360000","properties":{"id":"360000","cp":[115.592151,27.676493],"name":"江西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ĢĨƐgļ¼ÂMD~ņªe^\\^§ý©j×cZبzdÒa¶lÒJìõ`oz÷@¤u޸´ôęöY¼HČƶajlÞƩ¥éZ[|h}^U ¥pĄžƦO lt¸Æ Q\\aÆ|CnÂOjtĚĤdÈF`¶@Ðë ¦ōÒ¨SêvHĢûXD®
QgÄWiØPÞìºr¤džNĠ¢lĄtZoCƞÔºCxrpĠV®Ê{f_Y`_eq®Aot`@oDXfkp¨|s¬\\DÄSfè©Hn¬
^DhÆyøJhØxĢĀLÊƠPżċĄwȠ̦G®ǒĤäTŠÆ~Ħw«|TF¡nc³Ïå¹]ĉđxe{ÎÓvOEm°BƂĨİ|Gvz½ª´HàpeJÝQxnÀWEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[r«_gmQu~¥V\\OkxtL E¢Ú^~ýêPóqoě±_Êw§ÑªåƗā¼mĉŹ¿NQ
YBąrwģcÍ¥BŗÊcØiIƝĿuqtāwO]³YCñTeÉcaubÍ]trluī
BÐGsĵıN£ï^ķqss¿FūūVÕ·´Ç{éĈýÿOER_đûIċâJhŅıNȩĕB
¦K{Tk³¡OP·wnµÏd¯}½TÍ«YiµÕsC¯iM¤¦¯P|ÿUHvhe¥oFTuõ\\OSsMòđƇiaºćXĊĵà·çhƃ÷Ç{ígu^đgm[×zkKN¶Õ»lčÓ{XSÆv©_ÈëJbVkĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B±ÌKyáV¼Ã~
`gsÙfIƋlę¹e|~udjuTlXµf`¿Jd[\\L²"],"encodeOffsets":[[116689,26234]]}},{"type":"Feature","id":"370000","properties":{"id":"370000","cp":[118.000923,36.275807],"name":"山东","childNum":13},"geometry":{"type":"MultiPolygon","coordinates":[["@@Xjd]{K"],["@@itbFHy"],["@@HlGk"],["@@TGy"],["@@K¬U"],["@@WdXc"],["@@PtOs"],["@@LnXhc"],["@@ppVu]Or"],["@@cdzAUa"],["@@udRhnCI"],["@@oIpR"],["@@Ľč{fzƤîKÎMĮ]ZF½Y]â£ph¶¨râøÀÎǨ¤^ºÄGz~grĚĜlĞÆLĆdž¢Îo¦cvKbgr°WhmZp L]LºcUÆnżĤÌĒbAnrOA´ȊcÀbƦUØrĆUÜøĬƞEzVL®öØBkŖÝĐ˹ŧ̄±ÀbÎÉnb²ĦhņBĖįĦåXćì@L¯´ywƕCéõė ƿ¸lµ¾Z|ZWyFY¨Mf~C¿`à_RÇzwƌfQnny´INoƬèôº|sTJULîVjǎ¾ĒØDz²XPn±ŴPè¸ŔLƔÜƺ_TüÃĤBBċÈöA´faM¨{«M`¶d¡ôÖ°mȰBÔjj´PM|c^d¤u¤Û´ä«ƢfPk¶Môl]Lb}su^ke{lC
MrDÇ]NÑFsmoõľHyGă{{çrnÓEƕZGª¹Fj¢ïW
uøCǷë¡ąuhÛ¡^KxC`C\\bÅxì²ĝÝ¿_NīCȽĿåB¥¢·IŖÕy\\¹kxãČ×GDyäÁçFQ¡KtŵƋ]CgÏAùSedcÚźuYfyMmhUWpSyGwMPqŀÁ¼zK¶GY§Ë@´śÇµƕBm@IogZ¯uTMx}CVKï{éƵP_K«pÛÙqċtkkù]gTğwoɁsMõ³ăAN£MRkmEÊčÛbMjÝGu
IZGPģãħE[iµBEuDPÔ~ª¼ęt]ûG§¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~ݏYI] PumŝrƿIā[xedzL¯v¯s¬ÁY
~}
ťuŁgƋpÝĄ_ņī¶ÏSR´ÁP~¿Cyċßdwk´SsX|t`Ä ÈðAªìÎT°¦Dda^lĎDĶÚY°`ĪŴǒàŠv\\ebZHŖR¬ŢƱùęOÑM³FÛWp["]],"encodeOffsets":[[[123806,39303]],[[123821,39266]],[[123742,39256]],[[123702,39203]],[[123649,39066]],[[123847,38933]],[[123580,38839]],[[123894,37288]],[[123043,36624]],[[123344,38676]],[[123522,38857]],[[123628,38858]],[[118260,36742]]]}},{"type":"Feature","id":"410000","properties":{"id":"410000","cp":[113.665412,33.757975],"name":"河南","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ýLùµP³swIÓxcŢĞð´E®ÚPtĴXØx¶@«ŕŕQGYfa[şußǩđš_X³ijÕčC]kbc¥CS¯ëÍB©÷³Si_}mYTt³xlàcČzÀD}ÂOQ³ÐTĨ¯ƗòËŖ[hłŦv~}ÂZ«¤lPÇ£ªÝŴÅR§ØnhctâknÏľŹUÓÝdKuķI§oTũÙďkęĆH¸Ó\\Ä¿PcnS{wBIvÉĽ[GqµuŇôYgûZca©@½Õǽys¯}lgg@C\\£asIdÍuCQñ[L±ęk·ţb¨©kK»KC²òGKmĨS`UQnk}AGēsqaJ¥ĐGRĎpCuÌy ã iMcplk|tRkðev~^´¦ÜSí¿_iyjI|ȑ|¿_»d}q^{Ƈdă}tqµ`Ƴĕg}V¡om½faÇo³TTj¥tĠRyK{ùÓjuµ{t}uËRivGçJFjµÍyqÎàQÂFewixGw½Yŷpµú³XU½ġyłåkÚwZX·l¢Á¢KzOÎÎjc¼htoDHr
|J½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ
Ť]MÛfaQpě±ǽ¾]uFu÷nčįADp}AjmcEÇaª³o³ÆÍSƇĈÙDIzËčľ^KLiÞñ[aA²zzÌ÷D|[íijgfÕÞd®|`Ć~oĠƑô³ŊD×°¯CsøÀ«ìUMhTº¨¸ǡîSÔDruÂÇZÖEvPZW~ØÐtĄE¢¦Ðy¸bô´oŬ¬²Ês~]®tªapŎJ¨Öº_Ŕ`Ŗ^Đ\\Ĝu~m²Ƹ¸fWĦrƔ}Î^gjdfÔ¡J}\\n C¦þWxªJRÔŠu¬ĨĨmFdM{\\d\\YÊ¢ú@@¦ª²SÜsC}fNècbpRmlØ^gd¢aÒ¢CZZxvƶN¿¢T@uC¬^ĊðÄn|lGlRjsp¢ED}Fio~ÔN~zkĘHVsDzßjŬŢ`Pûàl¢\\ÀEhİgÞē X¼Pk|m"],"encodeOffsets":[[118256,37017]]}},{"type":"Feature","id":"420000","properties":{"id":"420000","cp":[113.298572,30.684355],"name":"湖北","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@AB"],["@@lskt"],["@@¾«}{ra®pîÃ\\{øCËyyB±b\\òÝjKL ]ĎĽÌJyÚCƈćÎT´Å´pb©ÈdFin~BCo°BĎÃømv®E^vǾ½Ĝ²RobÜeN^ĺ£R¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I¾®I{GqpCgyl{£ÍÍyPL¡¡¸kWxYlÙæŁĢz¾V´W¶ùŸo¾ZHxjwfxGNÁ³Xéæl¶EièIH ujÌQ~v|sv¶Ôi|ú¢FhQsğ¦SiŠBgÐE^ÁÐ{čnOÂÈUÎóĔÊēIJ}Z³½Mŧïeyp·uk³DsѨL¶_Åuèw»¡WqÜ]\\Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟOKÉġÿ×wg÷IÅzCg]m«ªGeçÃTC«[t§{loWeC@ps_Bprf_``Z|ei¡oċMqow¹DƝÓDYpûsYkıǃ}s¥ç³[§cY§HK«Qy]¢wwö¸ïx¼ņ¾Xv®ÇÀµRĠÐHM±cÏdƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy
¿³x¯No|¹HÏÛmjúË~TuęjCöAwě¬Rđl¯ ÑbŇTĿ_[IčĄʿnM¦ğ\\É[T·k¹©oĕ@A¾wya¥Y\\¥Âaz¯ãÁ¡k¥ne£ÛwE©Êō¶˓uoj_U¡cF¹[WvP©whuÕyBF`RqJUw\\i¡{jEPïÿ½fć
QÑÀQ{°fLÔ~wXgītêݾĺHd³fJd]HJ²
EoU¥HhwQsƐ»Xmg±çve]DmÍPoCc¾_hhøYrŊU¶eD°Č_N~øĹĚ·`z]Äþp¼
äÌQv\\rCé¾TnkžŐÚÜa¼ÝƆ̶Ûo
d
ĔňТJqPb ¾|J¾fXƐîĨ_Z¯À}úƲN_ĒÄ^ĈaŐyp»CÇÄKñL³ġM²wrIÒŭxjb[n«øæà ^²h¯ÚŐªÞ¸Y²ĒVø}Ā^İ´LÚm¥ÀJÞ{JVųÞŃx×sxxƈē ģMřÚðòIfĊŒ\\Ʈ±ŒdʧĘDvČ_Àæ~Dċ´A®µ¨ØLV¦êHÒ¤"]],"encodeOffsets":[[[113712,34000]],[[115612,30507]],[[113649,34054]]]}},{"type":"Feature","id":"430000","properties":{"id":"430000","cp":[111.782279,28.09409],"name":"湖南","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@nFTs"],["@@ßÅÆá½ÔXrCO
ËRïÿĩTooQyÓ[ŅBE¬ÎÓXaį§Ã¸G °ITxpúxÚij¥Ï̾edÄ©ĸG
àGhM¤Â_U}Ċ}¢pczfþg¤ÇòAVM"],["@@©KA·³CQ±Á«³BUƑ¹AtćOwD]JiØSm¯b£ylX
HËѱH«C^õľAŧ¤É¥ïyuǙuA¢^{ÌC´¦ŷJ£^[ª¿ĕ~Ƈ
N
skóā¹¿ï]ă~÷O§@Vm¡Qđ¦¢Ĥ{ºjÔª¥nf´~Õo×ÛąMąıuZmZcÒ IJβSÊDŽŶ¨ƚCÖŎªQؼrŭ«}NÏürʬmjr@ĘrTW SsdHzƓ^ÇÂyUi¯DÅYlŹu{hT}mĉ¹¥ěDÿë©ıÓ[Oº£¥ótł¹MÕƪ`P
DiÛU¾ÅâìUñBÈ£ýhedy¡oċ`pfmjP~kZa
ZsÐd°wj§@Ĵ®w~^kÀÅKvNmX\\¨aŃqvíó¿F¤¡@ũÑVw}S@j}¾«pĂrªg àÀ²NJ¶¶Dô
K|^ª°LX¾ŴäPα£EXd^¶IJÞÜ~u¸ǔMRhsR
e`ÄofIÔ\\Ø ićymnú¨cj ¢»GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQ_EzAN¦zLU`cªxOTu RLÄ¢dVi`p˔vŎµªÉF~Ød¢ºgİàw¸Áb[¦Zb¦z½xBĖ@ªpºlS¸Ö\\Ĕ[N¥ˀmĎăJ\\ŀ`
ňSÚĖÁĐiOĜ«BxDõĚivSÌ}iùÜnкG{p°M´wÀÒzJ²ò¨ oTçüöoÛÿñőФùTz²CȆȸǎŪƑÐc°dPÎğ˶[Ƚu¯½WM¡ÉB·rínZÒ `¨GA¾\\pēXhÃRCüWGġu
Té§ŎÑ©ò³I±³}_EÃħg®ęisÁPDmÅ{b[RÅs·kPŽƥóRoOV~]{g\\êYƪ¦kÝbiċƵGZ»Ěõ
ó·³vŝ£ø@pyö_ëIkѵbcѧy
×dYتiþ¨[]f]Ņ©C}ÁN»hĻħƏĩ"]],"encodeOffsets":[[[115640,30489]],[[112543,27312]],[[116690,26230]]]}},{"type":"Feature","id":"440000","properties":{"id":"440000","cp":[113.280637,23.125178],"name":"广东","childNum":24},"geometry":{"type":"MultiPolygon","coordinates":[["@@QdAua"],["@@lxDLo"],["@@sbhNLo"],["@@Ă ā"],["@@WltO[["],["@@Kr]S"],["@@eI]y"],["@@I|Mym"],["@@Û³LS¼Y"],["@@nvºBëui©`¾"],["@@zdÛJw®"],["@@°
¯"],["@@a yAª¸ËJIxØ@ĀHAmÃV¡ofuo"],["@@sŗÃÔėAƁZÄ ~°ČPäh"],["@@¶ÝÌvmĞhıQ"],["@@HdSjĒ¢D}war
u«ZqadYM"],["@@el\\LqqU"],["@@~rMo\\"],["@@f^C"],["@@øPªoj÷ÍÝħXČx°Q¨ıXNv"],["@@gÇƳo[~tly"],["@@EÆC¿"],["@@OP"],["@@wđógĝ[³¡VÙæÅöM̳¹pÁaËýý©D©ÜJŹƕģGą¤{Ùū
ÇO²«BƱéAÒĥ¡«BhlmtÃPµyU¯ucd·w_bŝcīímGO|KPȏŹãŝIŕŭŕ@Óoo¿ē±ß}
ŭIJWÈCőâUâǙIğʼn©IijE×
Á³AówXJþ±ÌÜÓĨ£L]ĈÙƺZǾĆĖMĸĤfÎĵlŨnÈĐtFFĤêk¶^k°f¶g}®Faf`vXŲxl¦ÔÁ²¬Ð¦pqÊ̲iXØRDÎ}Ä@ZĠsx®AR~®ETtĄZƈfŠŠHâÒÐAµ\\S¸^wĖkRzalŜ|E¨ÈNĀňZTpBh£\\ĎƀuXĖtKL¶G|»ĺEļĞ~ÜĢÛĊrOÙîvd]n¬VÊĜ°RÖpMƂªFbwEÀ©\\
¤]ŸI®¥D³|Ë]CöAŤ¦
æ´¥¸Lv¼¢ĽBaôF~®²GÌÒEYzk¤°ahlVÕI^CxĈPsBƒºV¸@¾ªR²ĨN]´_eavSivc}p}Đ¼ƌkJÚe th_¸ ºx±ò_xN˲@ă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIǪ`uTÅxYĒÖ¼kÖµMjJÚwn\\hĒv]îh|ÈƄøèg¸Ķß ĉĈWb¹ƀdéĘNTtP[öSvrCZaGubo´ŖÒÇĐ~¡zCI
özx¢PnÈñ @ĥÒ¦]ƞV}³ăĔñiiÄÓVépKG½ÄÓávYoC·sitiaÀyŧΡÈYDÑům}ý|m[węõĉZÅxUO}÷N¹³ĉo_qtăqwµŁYÙǝŕ¹tïÛUïmRCº
ĭ|µÕÊK½Rē ó]GªęAx»HO£|ām¡diď×YïYWªʼnOeÚtĐ«zđ¹T
āúEá²\\ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃOj YÇ÷Qěi"]],"encodeOffsets":[[[117381,22988]],[[116552,22934]],[[116790,22617]],[[116973,22545]],[[116444,22536]],[[116931,22515]],[[116496,22490]],[[116453,22449]],[[113301,21439]],[[118726,21604]],[[118709,21486]],[[113210,20816]],[[115482,22082]],[[113171,21585]],[[113199,21590]],[[115232,22102]],[[115739,22373]],[[115134,22184]],[[113056,21175]],[[119573,21271]],[[119957,24020]],[[115859,22356]],[[116561,22649]],[[116285,22746]]]}},{"type":"Feature","id":"450000","properties":{"id":"450000","cp":[108.320004,22.82402],"name":"广西","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@H TQ§A"],["@@ĨʪLƊDÎĹĐCǦė¸zÚGn£¾rªŀÜt¬@ÖÚSx~øOŒŶÐÂæȠ\\ÈÜObĖw^oÞLf¬°bI lTØBÌF£Ć¹gñĤaYt¿¤VSñK¸¤nM¼JE±½¸ñoÜCƆæĪ^ĚQÖ¦^f´QüÜÊz¯lzUĺš@ìp¶n]sxtx¶@~ÒĂJb©gk{°~c°`Ô¬rV\\la¼¤ôá`¯¹LCÆbxEræOv[H[~|aB£ÖsºdAĐzNÂðsÞÆ
Ĥªbab`ho¡³F«èVlo¤ÔRzpp®SĪº¨ÖºN
ijd`a¦¤F³ºDÎńĀìCĜº¦Ċ~nS|gźvZkCÆj°zVÈÁƔ]LÊFZg
čPkini«qÇczÍY®¬Ů»qR×ō©DÕ§ƙǃŵTÉĩ±ıdÑnYYIJvNĆĆØÜ Öp}e³¦m©iÓ|¹ħņ|ª¦QF¢Â¬ʖovg¿em^ucà÷gÕuíÙćĝ}FϼĹ{µHKsLSđƃrč¤[AgoSŇYMÿ§Ç{FśbkylQxĕ]T·¶[B
ÑÏGáşşƇe
ăYSsFQ}BwtYğÃ@~
CÍQ ×Wj˱rÉ¥oÏ ±«ÓÂ¥kwWűmcih³K~µh¯e]lµélEģEďsmÇŧē`ãògK_ÛsUʝćğ¶höO¤Ǜn³c`¡y¦CezYwa[ďĵűMę§]XÎ_íÛ]éÛUćİÕBƣ±
dy¹T^dûÅÑŦ·PĻþÙ`K¦
¢ÍeĥR¿³£[~äu¼dltW¸oRM¢ď\\z}Æzdvň{ÎXF¶°Â_ÒÂÏL©ÖTmu¼ãlīkiqéfA·Êµ\\őDc¥ÝFyÔćcűH_hLÜêĺШc}rn`½Ì@¸¶ªVLhŒ\\Ţĺk~Ġið°|gtTĭĸ^xvKVGréAébUuMJVÃO¡
qĂXËSģãlýà_juYÛÒBG^éÖ¶§EGÅzěƯ¤EkN[kdåucé¬dnYpAyČ{`]þ¯TbÜÈk¡ĠvàhÂƄ¢Jî¶²"]],"encodeOffsets":[[[111707,21520]],[[107619,25527]]]}},{"type":"Feature","id":"460000","properties":{"id":"460000","cp":[109.83119,19.031971],"name":"海南","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@¦Ŝil¢XƦƞòïè§ŞCêɕrŧůÇąĻõ·ĉ³œ̅kÇm@ċȧŧĥĽʉƅſȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀоjNðĀÒRZdžzÐŘΰH¨Ƣb²_Ġ "],"encodeOffsets":[[112750,20508]]}},{"type":"Feature","id":"510000","properties":{"id":"510000","cp":[104.065735,30.659462],"name":"四川","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@LqKr"],["@@[ĻéV£_ţġñpG réÏ·~ąSfy×Í·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«T¤JJJyJÈ`Ohߦ¡uËhIyCjmÿw
ZG
TiSsOB²fNmsPa{M{õE^Hj}gYpaeu¯oáwHjÁ½M¡pMuåmni{fk\\oÎqCwEZ¼KĝAy{m÷LwO×SimRI¯rKõBS«sFe]fµ¢óY_ÆPRcue°Cbo×bd£ŌIHgtrnyPt¦foaXďxlBowz_{ÊéWiêEGhܸºuFĈIxf®Y½ĀǙ]¤EyF²ċw¸¿@g¢§RGv»áW`ÃĵJwi]t¥wO½a[×]`ÃiüL¦LabbTÀåc}ÍhÆh®BHî|îºÉk¤Sy£ia©taį·Ɖ`ō¥UhO
ĝLk}©Fos´JmµlŁu
ønÑJWΪYÀïAetTŅÓGË«bo{ıwodƟ½OġܵxàNÖ¾P²§HKv¾]|BÆåoZ`¡Ø`ÀmºĠ~ÌЧnÇ
¿¤]wğ@srğu~Io[é±¹ ¿ſđÓ@qg¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@áťsZÏÅĭƋěpwDóÖáŻneQËq·GCœýS]x·ýq³OÕ¶Qzßti{řáÍÇWŝŭñzÇWpç¿JXĩè½cFÂLiVjx}\\NŇĖ¥GeJA¼ÄHfÈu~¸Æ«dE³ÉMA|bÒ
ćhG¬CMõƤąAvüVéŀ_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»ÕZ³ġqDoy`L¬gdp°şp¦ėìÅĮZ°Iähzĵf²å ĚÑKpIN|Ñz]ń
·FU×é»R³MÉ»GM«kiér}Ã`¹ăÞmÈnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ
þTº·àUȞÏʦ¶I«dĽĢdĬ¿»Ĕ×h\\c¬ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvwxBèĻĒ©ĈtCĢɽŠȣ¦āæ·HĽîôNÔ~^¤Ɗu^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ®Z´ğ~Sn|ªWÚ©òzPOȸbð¢|øĞŒQìÛÐ@ĞǎRS¤Á§d
i´ezÝúØã]HqkIþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwnÆƄmÀêErĒtD®ċæcQE®³^ĭ¥©l}äQtoŖÜqÆkµªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿQPJvÄz^Đ¹Æ¯fLà´GC²dtĀRt¼¤ĦOðğfÔðDŨŁĞƘïPÈ®âbMüÀXZ ¸£@Å»»QÉ]dsÖ×_Í_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|YÔZśÎs´xº±Uñt|OĩĠºNbgþJy^dÂY Į]Řz¦gC³R`Āz¢Aj¸CL¤RÆ»@Ŏk\\Ç´£YW}z@Z}öoû¶]´^NÒ}èNªPÍy¹`S°´ATeVamdUĐwʄvĮÕ\\uÆŗ¨Yp¹àZÂmWh{á}WØǍÉüwga§áCNęÎ[ĀÕĪgÖɪXøx¬½Ů¦¦[NÎLÜUÖ´òrÙŠxR^JkijnDX{U~ET{ļº¦PZcjF²Ė@pg¨B{u¨ŦyhoÚD®¯¢ WòàFΤ¨GDäz¦kŮPġqË¥À]eâÚ´ªKxīPÖ|æ[xäJÞĥsNÖ½I¬nĨY´®ÐƐmDŝuäđđEb
ee_v¡}ìęNJē}qÉåT¯µRs¡M@}ůaa¯wvƉåZw\\Z{åû^"]],"encodeOffsets":[[[108815,30935]],[[110617,31811]]]}},{"type":"Feature","id":"520000","properties":{"id":"520000","cp":[106.713478,26.578343],"name":"贵州","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@G\\lY£in"],["@@q|mc¯tÏVSÎ"],["@@hÑ£IsNgßHHªķÃh_¹¡ĝħń¦uÙùgS¯JH|sÝÅtÁïyMDč»eÕtA¤{b\\}G®u\\åPFqwÅaD
K°ºâ_£ùbµmÁÛĹM[q|hlaªāI}ѵ@swtwm^oµD鼊yVky°ÉûÛR
³e¥]RÕěħ[ƅåÛDpJiVÂF²I
»mN·£LbÒYbWsÀbpkiTZĄă¶Hq`
ĥ_J¯ae«KpÝx]aĕÛPÇȟ[ÁåŵÏő÷Pw}TÙ@Õs«ĿÛq©½m¤ÙH·yǥĘĉBµĨÕnđ]K©œáGçş§ÕßgǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊw¶øV¤w²Ĉ]ÊKx|`ź¦ÂÈdrcÈbe¸`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pĐ`oÒh¶pa^ÓĔ}D»^Xy`d[Kv
JPhèhCrĂĚÂ^Êƌ wZLĠ£ÁbrzOIlMMĪŐžËr×ÎeŦtw|¢mKjSǘňĂStÎŦEtqFT¾E쬬ôxÌO¢ K³ŀºäYPVgŎ¦Ŋm޼VZwVlz¤
£Tl®ctĽÚó{GAÇge~Îd¿æaSba¥KKûj®_Ä^\\ؾbP®¦x^sxjĶI_Ä Xâ¼Hu¨Qh¡À@Ëô}±GNìĎlT¸
`V~R°tbÕĊ`¸úÛtÏFDu[MfqGH·¥yAztMFe|R_GkChZeÚ°tov`xbDnÐ{E}ZèxNEÞREn[Pv@{~rĆAB§EO¿|UZ~ìUf¨J²ĂÝÆsªB`s¶fvö¦Õ~dÔq¨¸º»uù[[§´sb¤¢zþF¢Æ
ÀhÂW\\ıËIÝo±ĭŠ£þÊs}¡R]ěDg´VG¢j±®èºÃmpU[Á뺰rÜbNu¸}º¼`niºÔXĄ¤¼ÔdaµÁ_Ã
ftQQgR·Ǔv}Ý×ĵ]µWc¤F²OĩųãW½¯K©
]{LóµCIµ±Mß¿h©āq¬o½~@i~TUxŪÒ¢@£ÀEîôruńb[§nWuMÆLl¿]x}ij½"]],"encodeOffsets":[[[112158,27383]],[[112105,27474]],[[112095,27476]]]}},{"type":"Feature","id":"530000","properties":{"id":"530000","cp":[101.512251,24.740609],"name":"云南","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@[ùx½}ÑRHYīĺûsÍniEoã½Ya²ė{c¬ĝgĂsAØÅwďõzFjw}«Dx¿}Uũlê@HÅF¨ÇoJ´Ónũuą¡Ã¢pÒÅØ TF²xa²ËXcÊlHîAßËŁkŻƑŷÉ©hWæßUËs¡¦}teèÆ¶StÇÇ}Fd£jĈZĆÆ¤Tč\\D}O÷£U§~ŃGåŃDĝ¸Tsd¶¶Bª¤u¢ŌĎo~t¾ÍŶÒtD¦ÚiôözØX²ghįh½Û±¯ÿm·zR¦Ɵ`ªŊÃh¢rOÔ´£Ym¼èêf¯ŪĽncÚbw\\zlvWªâ ¦gmĿBĹ£¢ƹřbĥkǫßeeZkÙIKueT»sVesbaĕ ¶®dNĄÄpªy¼³BE®lGŭCǶwêżĔÂepÍÀQƞpC¼ŲÈAÎô¶RäQ^Øu¬°_Èôc´¹ò¨P΢hlϦ´ĦÆ´sâÇŲPnÊD^¯°Upv}®BP̪jǬxSöwlfòªvqĸ|`HviļndĜĆhňem·FyÞqóSᝳX_ĞçêtryvL¤§z¦c¦¥jnŞklD¤øz½ĜàĂŧMÅ|áƆàÊcðÂFÜáŢ¥\\\\ºİøÒÐJĴîD¦zK²ǏÎEh~CDhMn^ÌöÄ©ČZÀaüfɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~ÄqêljN¬¼HÊNQ´ê¼VظE^ŃÒyM{JLoÒęæe±Ķygã¯JYÆĭĘëo¥Šo¯hcK«z_prC´ĢÖY¼ v¸¢RÅW³Â§fǸYi³xR´ďUË`êĿUûuĆBƣöNDH«ĈgÑaB{ÊNF´¬c·Åv}eÇÃGB»If¦HňĕM
~[iwjUÁKE¾dĪçWIèÀoÈXòyŞŮÈXâÎŚj|àsRyµÖPr´þ ¸^wþTDŔHr¸RÌmfżÕâCôoxĜƌÆĮÐYtâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyhr@ĒÔƀÀ²º\\êpJ}ĠvqtĠ@^xÀ£È¨mËÏğ}n¹_¿¢×Y_æpÅA^{½Lu¨GO±Õ½ßM¶wÁĢÛPƢ¼pcIJx|ap̬HÐŊSfsðBZ¿©XÏÒKk÷Eû¿S
rEFsÕūkóVǥʼniTL¡n{uxţÏhôŝ¬ğōNNJkyPaqÂğ¤K®YxÉƋÁ]āęDqçgOgILu\\_gz]W¼~CÔē]bµogpÑ_oď`´³Țkl`IªºÎȄqÔþ»E³ĎSJ»_f·adÇqÇc¥Á_Źw{L^ɱćxU£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣGË÷k°_^ý|_zċBZocmø¯hhcæ\\lMFlư£ĜÆyHF¨µêÕ]HA
àÓ^it `þßäkĤÎT~Wlÿ¨ÔPzUCNVv [jâôDôď[}z¿msSh¯{jïğl}šĹ[őgK©U·µË@¾m_~q¡f¹
ÅË^»f³ø}Q¡Ö˳gͱ^Ç
\\ëÃA_¿bWÏ[¶ƛé£F{īZgm@|kHǭƁć¦UĔť×ë}ǝeďºȡȘÏíBÉ£āĘPªij¶ʼnÿy©nď£G¹¡I±LÉĺÑdĉÜW¥}gÁ{aqÃ¥aıęÏZï`"],"encodeOffsets":[[104636,22969]]}},{"type":"Feature","id":"540000","properties":{"id":"540000","cp":[89.132212,30.860361],"name":"西藏","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ÂhľxŖxÒVºÅâAĪÝȆµę¯Ňa±r_w~uSÕňqOj]ɄQ
£Z
UDûoY»©M[L¼qãË{VÍçWVi]ë©Ä÷àyƛhÚU°adcQ~Mx¥cc¡ÙaSyFÖkuRýq¿ÔµQĽ³aG{¿FµëªéĜÿª@¬·K·àariĕĀ«V»ŶĴūgèLǴŇƶaftèBŚ£^âǐÝ®M¦ÁǞÿ¬LhJ¾óƾƺcxwf]Y
´¦|QLn°adĊ
\\¨oǀÍŎ´ĩĀd`tÊQŞŕ|¨C^©Ĉ¦¦ÎJĊ{ëĎjª²rÐl`¼Ą[t|¦Stè¾PÜK¸dƄı]s¤î_v¹ÎVòŦj£Əsc¬_Ğ´|٦Av¦w`ăaÝaa¢e¤ı²©ªSªÈMĄwÉØŔì@T¤Ę\\õª@þo´xA sÂtŎKzó´ÇĊµ¢r^nĊƬ×üG¢³ {âĊ]G~bÀgVjzlhǶfOfdªB]pjTOtĊn¤}®¦Č¥d¢¼»ddY¼t¢eȤJ¤}Ǿ¡°§¤AÐlc@ĝsªćļđAçwxUuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H
ãd«g[ؼēÀcīľġ¬cJµ
ÐʥVȝ¸ßS¹ý±ğkƁ¼ą^ɛ¤Ûÿb[}¬ōõÃ]ËNm®g@Bg}ÍF±ǐyL¥íCIijÏ÷Ñį[¹¦[âšEÛïÁÉdƅß{âNÆāŨß¾ě÷yC£k´ÓH@¹TZ¥¢į·ÌAЧ®Zc
v½Z¹|ÅWZqgW|ieZÅYVÓqdqbc²R@c¥Rã»GeeƃīQ}J[ÒK
¬Ə|oėjġĠÑN¡ð¯EBčnwôɍėª²CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛęgſ¶ҍć`ĘąŌJÞä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷f±iMÝ@ĥ°G¬ÃM¥n£Øąğ¯ß§aëbéüÑOčk£{\\eµª×MÉfm«Ƒ{Å×Gŏǩãy³©WÑăû··Qòı}¯ãIéÕÂZ¨īès¶ZÈsæĔTŘvgÌsN@îá¾ó@ÙwU±ÉT廣TđWxq¹Zobs[ׯcĩvėŧ³BM|¹kªħ¥TzNYnÝßpęrñĠĉRS~½ěVVµõ«M££µBĉ¥áºae~³AuĐh`ܳç@BÛïĿa©|z²Ý¼D£àč²ŸIûI āóK¥}rÝ_Á´éMaň¨~ªSĈ½½KÙóĿeƃÆB·¬ën×W|Uº}LJrƳlŒµ`bÔ`QÐÓ@s¬ñIÍ@ûws¡åQÑßÁ`ŋĴ{ĪTÚÅTSijYo|Ç[ǾµMW¢ĭiÕØ¿@Mh
pÕ]jéò¿OƇĆƇpêĉâlØwěsǩĵ¸c
bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB\\qTGªÇĜçPoÿfñòą¦óQīÈáPābß{ZŗĸIæÅhnszÁCËìñÏ·ąĚÝUm®óL·ăUÈíoù´Êj°ŁŤ_uµ^°ìÇ@tĶĒ¡ÆM³Ģ«İĨÅ®ğRāðggheÆ¢zÊ©Ô\\°ÝĎz~ź¤PnMĪÖB£kné§żćĆKǰ¼L¶èâz¨u¦¥LDĘz¬ýÎmĘd¾ßFzhg²Fy¦ĝ¤ċņbÎ@yĄæm°NĮZRÖíJ²öLĸÒ¨Y®ƌÐVàtt_ÚÂyĠz]ŢhzĎ{ÂĢXc|ÐqfO¢¤ögÌHNPKŖUú´xx[xvĐCûĀìÖT¬¸^}Ìsòd´_KgžLĴ
ÀBon|H@Êx¦BpŰŌ¿fµƌA¾zLjRx¶FkĄźRzŀ~¶[´HnªVƞuĒȨƎcƽÌm¸ÁÈM¦x͊ëÀxdžBú^´W£dkɾĬpw˂ØɦļĬIŚÊnŔa¸~J°îlɌxĤÊÈðhÌ®gT´øàCÀ^ªerrƘd¢İP|Ė ŸWªĦ^¶´ÂLaT±üWƜǀRÂŶUńĖ[QhlLüAÜ\\qRĄ©"],"encodeOffsets":[[90849,37210]]}},{"type":"Feature","id":"610000","properties":{"id":"610000","cp":[108.948024,34.263161],"name":"陕西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@p¢ȮµûGĦ}Ħðǚ¶òƄjɂz°{ºØkÈęâ¦jªBg\\ċ°s¬]jú EȌdž¬stRÆdĠİwܸôW¾ƮłÒ_{Ìû¼jº¹¢GǪÒ¯ĘZ`ºŊecņą~BÂgzpâēòYǠȰÌTΨÂW|fcă§uF@N¢XLRMº[ğȣſï|¥Jkc`sʼnǷY¹W@µ÷K
ãï³ÛIcñ·VȋÚÒķø©þ¥yÓğęmWµÎumZyOŅƟĥÓ~sÑL¤µaÅ
Y¦ocyZ{y c]{Ta©`U_Ěē£ωÊƍKùK¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑdìUYOuFÕÈYvÁCqÓTǢí§·S¹NgV¬ë÷Át°DدC´ʼnƒópģ}ċcEË
FéGU¥×K
§¶³BČ}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO
ÿEËߌĤNĔwƇÄńwĪo[_KÓª³ÙnKÇěÿ]ďă_d©·©Ýŏ°Ù®g]±ßå¬÷m\\iaǑkěX{¢|ZKlçhLtŇîŵœè[É@ƉĄEtƇϳħZ«mJ
×¾MtÝĦ£IwÄå\\Õ{OwĬ©LÙ³ÙgBƕŀrÌĢŭO¥lãyC§HÍ£ßEñX¡°ÙCgpťzb`wIvA|§hoĕ@E±iYd¥OϹS|}F@¾oAO²{tfÜ¢FǂÒW²°BĤh^Wx{@¬F¸¡ķn£P|ªĴ@^ĠĈæbÔc¶lYi
^MicϰÂ[ävï¶gv@ÀĬ·lJ¸sn|¼u~a]ÆÈtŌºJpþ£KKf~¦UbyäIĺãnÔ¿^ŵMThĠܤko¼Ŏìąǜh`[tRd²IJ_XPrɲlXiL§à¹H°Ȧqº®QCbAŌJ¸ĕÚ³ĺ§ `d¨YjiZvRĺ±öVKkjGȊÄePĞZmļKÀ[`ösìhïÎoĬdtKÞ{¬èÒÒBÔpIJÇĬJŊ¦±J«Y§@·pHµàåVKepWftsAÅqC·¬ko«pHÆuK@oHĆÛķhxenS³àǍrqƶRbzy¸ËÐl¼EºpĤ¼x¼½~Ğà@ÚüdK^mÌSj"],"encodeOffsets":[[110234,38774]]}},{"type":"Feature","id":"620000","properties":{"id":"620000","cp":[103.823557,36.058039],"name":"甘肃","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@VuUv"],["@@ũEĠtt~nkh`Q¦ÅÄÜdwAb×ĠąJ¤DüègĺqBqj°lI¡ĨÒ¤úSHbjÎB°aZ¢KJO[|A£Dx}NìHUnrk kp¼Y kMJn[aGáÚÏ[½rc}aQxOgsPMnUsncZ
sKúvAtÞġ£®ĀYKdnFw¢JE°Latf`¼h¬we|Æbj}GA·~W`¢MC¤tL©IJ°qdfObÞĬ¹ttu`^ZúE`[@Æsîz®¡CƳƜG²R¢RmfwĸgÜą G@pzJM½mhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬²I¥IʼnÈīoıÓÑAçÑ|«LÝcspīðÍg
të_õ\\ĉñLYnĝgRǡÁiHLlõUĹ²uQjYi§Z_c¨´ĹĖÙ·ŋI
aBDR¹ȥr¯GºßK¨jWkɱOqWij\\aQ\\sg_ĆǛōëp»£lğÛgSŶN®À]ÓämĹãJaz¥V}Le¤Lýo¹IsŋÅÇ^bz
³tmEÁ´a¹cčecÇNĊãÁ\\č¯dNj]jZµkÓdaćå]ğij@ ©O{¤ĸm¢E·®«|@Xwg]A챝XǁÑdzªcwQÚŝñsÕ³ÛV_ý¥\\ů¥©¾÷w©WÕÊĩhÿÖÁRo¸V¬âDb¨hûxÊ×nj~Zâg|XÁnßYoº§ZÅŘv[ĭÖʃuďxcVbnUSf
B¯³_TzºÎO©çMÑ~M³]µ^püµÄY~y@X~¤Z³[Èōl@®Å¼£QK·Di¡ByÿQ_´D¥hŗy^ĭÁZ]cIzýah¹MĪğPs{ò²Vw¹t³ŜË[Ñ}X\\gsF£sPAgěp×ëfYHāďÖqēŭOÏëdLü\\it^c®Rʺ¶¢H°mrY£B¹čIoľu¶uI]vģSQ{UŻÅ}QÂ|̰ƅ¤ĩŪU ęĄÌZÒ\\v²PĔ»ƢNHĂyAmƂwVm`]ÈbH`Ì¢²ILvĜH®¤Dlt_¢JJÄämèÔDëþgºƫaʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b
ð÷®üszMzÖĖQdȨýv§Tè|ªHþa¸|Ð ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v·À|\\ƁĚN´ĜçèÁz]ġ¤²¨QÒŨTIlªťØ}¼˗ƦvÄùØE«FïËIqōTvāÜŏíÛßÛVj³âwGăÂíNOPìyV³ʼnĖýZso§HÑiYw[ß\\X¦¥c]ÔƩÜ·«jÐqvÁ¦m^ċ±R¦ƈťĚgÀ»IïĨʗƮ°ƝĻþÍAƉſ±tÍEÕÞāNUÍ¡\\ſčåÒʻĘm ƭÌŹöʥëQ¤µÇcƕªoIýIÉ_mkl³ăƓ¦j¡YzŇi}Msßõīʋ }ÁVm_[n}eıUĥ¼ªI{ΧDÓƻėojqYhĹT©oūĶ£]ďxĩǑMĝq`B´ƃ˺Чç~²ņj@¥@đ´ί}ĥtPńǾV¬ufÓÉCtÓ̻
¹£G³]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼĤŊɲĖÂKq´ï¦ºĒDzņɾªǀÞĈĂD½ĄĎÌŗĞrôñnN¼â¾ʄľԆ|DŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿ĽĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY
tÁƤyAã˾J@ǝrý@¤
rz¸oP¹ɐÚyáHĀ[Jw
cVeȴÏ»ÈĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔĹŊũ~ËUă{ĻƹɁύȩþĽvĽƓÉ@ēĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶¨c~c¼īeXǚ\\đ¾JwÀďksãAfÕ¦L}waoZD½Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LFLzĈôe]gx}|KK}xklL]c¦£fRtív¦PĤoH{tK"]],"encodeOffsets":[[[108619,36299]],[[108589,36341]]]}},{"type":"Feature","id":"630000","properties":{"id":"630000","cp":[96.778916,35.623178],"name":"青海","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@InJm"],["@@CƽOŃĦsΰ~dz¦@@Ņi±è}ШƄ˹A³r_ĞǒNĪĐw¤^ŬĵªpĺSZgrpiƼĘÔ¨C|ÍJ©Ħ»®VIJ~f\\m `UnÂ~ʌĬàöNt~ňjy¢ZiƔ¥Ąk´nl`JÊJþ©pdƖ®È£¶ìRʦźõƮËnʼėæÑƀĎ[¢VÎĂMÖÝÎF²sƊƀÎBļýƞ¯ʘƭðħ¼Jh¿ŦęΌƇ¥²Q]Č¥nuÂÏri¸¬ƪÛ^Ó¦d¥[Wà
x\\ZjÒ¨GtpþYŊĕ´zUOëPîMĄÁxH´áiÜUàîÜŐĂÛSuŎrJð̬EFÁú×uÃÎkrĒ{V}İ«O_ÌËĬ©ÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u
ºµ[gt£¸OƤĿéYõ·kĀq]juw¥DĩƍõÇPéĽG©ã¤G
uȧþRcÕĕNyyûtøï»a½ē¿BMoį£Íj}éZËqbʍƬh¹ìÿÓAçãnIáI`ks£CGěUy×Cy
@¶ʡÊBnāzGơMē¼±O÷õJËĚăVĪũƆ£¯{ËL½ÌzżVR|ĠTbuvJvµhĻĖHAëáa
OÇðñęNw
œľ·LmI±íĠĩPÉ×®ÿscB³±JKßĊ«`
ađ»·QAmOVţéÿ¤¹SQt]]Çx±¯A@ĉij¢Óļ©l¶ÅÛrŕspãRk~¦ª]Į´FRådČsCqđéFn¿ÅƃmÉx{W©ºƝºįkÕƂƑ¸wWūЩÈF£\\tÈ¥ÄRÈýÌJ lGr^×äùyÞ³fjc¨£ÂZ|ǓMĝÏ@ëÜőRĝ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³ÞIňµç½©C¡į÷¯B»|St»]vųs»}MÓ ÿʪƟǭA¡fs»PY¼c¡»¦cċ¥£~msĉPSi^o©AecPeǵkgyUi¿h}aHĉ^|á´¡HØûÅ«ĉ®]m¡qĉ¶³ÈyôōLÁstB®wn±ă¥HSòė£Së@לÊăxÇN©©T±ª£IJ¡fb®Þbb_Ą¥xu¥B{łĝ³«`dƐt¤ťiñÍUuºí`£^tƃIJc·ÛLO½sç¥Ts{ă\\_»kϱq©čiìĉ|ÍI¥ć¥]ª§D{ŝŖÉR_sÿc³ĪōƿΧp[ĉc¯bKmR¥{³Ze^wx¹dƽŽôIg §Mĕ ƹĴ¿ǣÜÍ]Ý]snåA{eƭ`ǻŊĿ\\ijŬűYÂÿ¬jĖqßb¸L«¸©@ěĀ©ê¶ìÀEH|´bRľÓ¶rÀQþvl®ÕETzÜdb hw¤{LRdcb¯ÙVgƜßzÃôì®^jUèXÎ|UäÌ»rK\\ªN¼pZCüVY¤ɃRi^rPŇTÖ}|br°qňb̰ªiƶGQ¾²x¦PmlŜ[Ĥ¡ΞsĦÔÏâ\\ªÚŒU\\f
¢N²§x|¤§xĔsZPòʛ²SÐqF`ªVÞŜĶƨVZÌL`¢dŐIqr\\oäõF礻Ŷ×h¹]ClÙ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ´ÃbEÄlbʔC|CŮkƮ[ʼ¬ň´KŮÈΰÌζƶlðļATUvdTGº̼ÔsÊDÔveOg"]],"encodeOffsets":[[[105308,37219]],[[95370,40081]]]}},{"type":"Feature","id":"640000","properties":{"id":"640000","cp":[106.278179,37.26637],"name":"宁夏","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@KëÀęĞ«Oęȿȕı]ʼn¡åįÕÔ«ǴõƪĚQÐZhv K°öqÀÑS[ÃÖHƖčËnL]ûc
Ùß@ĝ¾}w»»oģF¹»kÌÏ·{zP§B¢íyÅt@@á]Yv_ssģ¼ißĻL¾ġsKD£¡N_
X¸}B~HaiÅf{«x»ge_bsKF¯¡IxmELcÿZ¤ĢÝsuBLùtYdmVtNmtOPhRw~bd
¾qÐ\\âÙH\\bImlNZ»loqlVmGā§~QCw¤{A\\PKNY¯bFkC¥sks_Ã\\ă«¢ħkJi¯rrAhĹûç£CUĕĊ_ÔBixÅÙĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~hw^ófćKyEKzuÔ¡qQ¤xZÑ¢^ļöܾEp±âbÊÑÆ^fk¬
NC¾YpxbK~¥eÖäBlt¿Đx½I[ĒǙWf»Ĭ}d§dµùEuj¨IÆ¢¥dXªƅx¿]mtÏwßRĶX¢͎vÆzƂZò®ǢÌʆCrâºMÞzÆMÒÊÓŊZľr°Î®Ȉmª²ĈUªĚîøºĮ¦ÌĘk^FłĬhĚiĀ˾iİbjÕ"],["@@mfwěwMrŢªv@G"]],"encodeOffsets":[[[109366,40242]],[[108600,36303]]]}},{"type":"Feature","id":"650000","properties":{"id":"650000","cp":[85.617733,40.792818],"name":"新疆","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@QØĔ²X¨~ǘBºjʐߨvKƔX¨vĊO÷¢i@~cĝe_«E}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX
êÎf`C¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥OéÈ¿ÖğǤǷÂFÒzÉx[]Ĥĝœ¦EP}ûƥé¿İƷTėƫœŕƅƱB»Đ±ēO
¦E}`cȺrĦáŖuÒª«IJπdƺÏØZƴwʄ¤ĖGĐǂZĶèH¶}ÚZצʥĪï|ÇĦMŔ»İĝLjì¥Βba¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»òmqóŘĝč˾ăC
ćāƿÝɽ©DZҹđ¥³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕUv£ƁQïƵkŏ½ΉÃŭdzLŇʻ«ƭ\\lŭD{ʓDkaFÃÄa³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍöůʼnT¡c_ËKYƧUśĵÝU_©rETÏʜ±OñtYwē¨{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\śnkOw¥±T»ƷFɯàĩÞáB¹Æ
ÑUwŕĽw[mG½Èå~Æ÷QyěCFmĭZīŵVÁƿQƛûXS²b½KϽĉS©ŷXĕ{ĕK·¥Ɨcqq©f¿]ßDõU³hgËÇïģÉɋwk¯í}I·œbmÉřīJɥĻˁ×xoɹīlc
¤³Xù]DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®ƝvUm©³G\\}µĿQyŹlăµEwLJQ½yƋBe¶ŋÀůo¥AÉw@{Gpm¿AijŽKLh³`ñcËtW±»ÕSëüÿďDu\\wwwù³VLŕOMËGh£õP¡erÏd{ġWÁ
č|yšg^ğyÁzÙs`s|ÉåªÇ}m¢Ń¨`x¥ù^}Ì¥H«YªƅAйn~ź¯f¤áÀzgÇDIÔ´AňĀÒ¶ûEYospõD[{ù°]uJqU|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw ÞkrťË¿XGÉbřaDü·Ē÷Aê[ÄäI®BÕĐÞ_¢āĠpÛÄȉĖġDKwbmÄNôfƫVÉvidzHQµâFùœ³¦{YGd¢ĚÜO {Ö¦ÞÍÀP^bƾl[vt×ĈÍE˨¡Đ~´î¸ùÎhuè`¸HÕŔVºwĠââWò@{ÙNÝ´ə²ȕn{¿¥{l÷eé^eďXj©î\\ªÑòÜìc\\üqÕ[Č¡xoÂċªbØø|¶ȴZdÆÂońéG\\¼C°ÌÆn´nxÊOĨŪƴĸ¢¸òTxÊǪMīĞÖŲÃɎOvʦƢ~FRěò¿ġ~åŊúN¸qĘ[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾ĄYÒ©ÊfºmÔĘcDoĬMŬS¤s²ʘÚžȂVŦ èW°ªB|IJXŔþÈJĦÆæFĚêYĂªĂ]øªŖNÞüAfɨJ¯ÎrDDĤ`mz\\§~D¬{vJ«lµĂb¤pŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMTòP÷fØĶK¢ȝ˔Sô¹òEð`Ɩ½ǒÂň×äı§ĤƝ§C~¡hlåǺŦŞkâ~}FøàIJaĞfƠ¥Ŕd®U¸źXv¢aƆúŪtŠųƠjdƺƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹\\ĜÑŚ¶ZƄ³àjĨoâȴLÊȮĐĚăÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTiƢ¾ªì°`öøu®Ê¾ãØ"],"encodeOffsets":[[88824,50096]]}},{"type":"Feature","id":"110000","properties":{"id":"110000","cp":[116.405285,39.904989],"name":"北京","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ĽOÁûtŷmiÍt_H»Ĩ±d`¹{bw
Yr³S]§§o¹qGtm_SŧoaFLgQN_dV@Zom_ć\\ßc±x¯oœRcfe
£o§ËgToÛJíĔóu
|wP¤XnO¢ÉŦ¯rNÄā¤zâŖÈRpŢZÚ{GrFt¦Òx§ø¹RóäV¤XdżâºWbwڍUd®bêņ¾jnŎGŃŶnzÚSeîĜZczî¾i]ÍQaúÍÔiþĩȨWĢü|Ėu[qb[swP@ÅğP¿{\\¥A¨ÏѨj¯X\\¯MKpA³[H
īu}}"],"encodeOffsets":[[120023,41045]]}},{"type":"Feature","id":"120000","properties":{"id":"120000","cp":[117.190182,39.125596],"name":"天津","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ŬgX§Ü«E
¶F̬O_ïlÁgz±AXeµÄĵ{¶]gitgIj·¥îakS¨ÐƎk}ĕ{gBqGf{¿aU^fIư³õ{YıëNĿk©ïËZŏR§òoY×Ógc
ĥs¡bġ«@dekąI[nlPqCnp{ō³°`{PNdƗqSÄĻNNâyj]äÒD ĬH°Æ]~¡HO¾X}ÐxgpgWrDGpù^LrzWxZ^¨´T\\|~@IzbĤjeĊªz£®ĔvěLmV¾Ô_ÈNW~zbĬvG²ZmDM~~"],"encodeOffsets":[[120237,41215]]}},{"type":"Feature","id":"310000","properties":{"id":"310000","cp":[121.472644,31.231706],"name":"上海","childNum":6},"geometry":{"type":"MultiPolygon","coordinates":[["@@ɧư¬EpƸÁxc"],["@@©ª"],["@@MA"],["@@QpİE§ÉC¾"],["@@bŝÕÕEȣÚƥêImɇǦèÜĠÚÃƌÃ͎ó"],["@@ǜûȬɋŭ×^sYɍDŋŽąñCG²«ªč@h_p¯A{oloY¬j@IJ`gQÚhr|ǀ^MIJvtbe´R¯Ô¬¨Yô¤r]ìƬį"]],"encodeOffsets":[[[124702,32062]],[[124547,32200]],[[124808,31991]],[[124726,32110]],[[124903,32376]],[[124438,32149]]]}},{"type":"Feature","id":"500000","properties":{"id":"500000","cp":[107.304962,29.533155],"name":"重庆","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êÐqHðqĖä¥^CÆIj²p
\\_ æüY|[YxƊæu°xb®
Űb@~¢NQt°¶Sæ Ê~rljĔëĚ¢~uf`faĔJåĊnÖ]jƎćÊ@£¾a®£Ű{ŶĕFègLk{Y|¡ĜWƔtƬJÑxq±ĢN´òKLÈüD|s`ŋć]Ã`đMûƱ½~Y°ħ`ƏíW½eI½{aOIrÏ¡ĕŇapµÜƅġ^ÖÛbÙŽŏml½SêqDu[RãË»ÿw`»y¸_ĺę}÷`M¯ċfCVµqʼn÷Zgg`d½pDOÎCn^uf²ènh¼WtƏxRGg¦
pVFI±G^Ic´ecGĹÞ½sëĬhxW}KÓeXsbkF¦LØgTkïƵNï¶}Gyw\\oñ¡nmĈzj@Óc£»Wă¹Ój_m»¹·~MvÛaq»ê\\ÂoVnÓØÍ²«bq¿efE Ĝ^Q~ Évýş¤²ĮpEİ}zcĺL½¿gÅ¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u_n»_At©Þűā§IVeëY}{VPÀFA¨ąB}q@|Ou\\FmQFÝ
Mwå}]|FmÏCawu_p¯sfÙgY
DHl`{QEfNysB¦zG¸rHeN\\CvEsÐùÜ_·ÖĉsaQ¯}_UxÃđqNH¬Äd^ÝŰR¬ã°wećJE·vÝ·HgéFXjÉê`|ypxkAwWĐpb¥eOsmzwqChóUQl¥F^lafanòsrEvfQdÁUVfÎvÜ^eftET¬ôA\\¢sJnQTjPØxøK|nBzĞ»LY
FDxÓvr[ehľvN¢o¾NiÂxGpâ¬zbfZo~hGi]öF||NbtOMn eA±tPTLjpYQ|SHYĀxinzDJÌg¢và¥Pg_ÇzIIII£®S¬Øsμ£N"],["@@ifjN@s"]],"encodeOffsets":[[[109628,30765]],[[111725,31320]]]}},{"type":"Feature","id":"810000","properties":{"id":"810000","cp":[114.173355,22.320048],"name":"香港","childNum":5},"geometry":{"type":"MultiPolygon","coordinates":[["@@AlBk"],["@@mn"],["@@EpFo"],["@@ea¢pl¸Eõ¹hj[]ÔCÎ@lj¡uBX
´AI¹
[yDU]W`çwZkmc
MpÅv}IoJlcafŃK°ä¬XJmÐ đhI®æÔtSHnEÒrÈc"],["@@rMUwAS®e"]],"encodeOffsets":[[[117111,23002]],[[117072,22876]],[[117045,22887]],[[116975,23082]],[[116882,22747]]]}},{"type":"Feature","id":"820000","properties":{"id":"820000","cp":[113.54909,22.198951],"name":"澳门","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@kÊd°å§s"],"encodeOffsets":[[116279,22639]]}}],"UTF8Encoding":true});
+}));
diff --git a/src/pages/chart/ECharts/theme/macarons.js b/src/pages/chart/ECharts/theme/macarons.js
new file mode 100644
index 0000000..3660c13
--- /dev/null
+++ b/src/pages/chart/ECharts/theme/macarons.js
@@ -0,0 +1,219 @@
+/* global define */
+;(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') {
+ /* eslint-disable */
+ 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)
+})
diff --git a/src/pages/chart/ECharts/theme/shine.js b/src/pages/chart/ECharts/theme/shine.js
new file mode 100644
index 0000000..bba7655
--- /dev/null
+++ b/src/pages/chart/ECharts/theme/shine.js
@@ -0,0 +1,169 @@
+/* global define */
+;(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') {
+ /* eslint-disable */
+ 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)
+})
diff --git a/src/pages/chart/Recharts/AreaChartComponent.js b/src/pages/chart/Recharts/AreaChartComponent.js
new file mode 100644
index 0000000..519a245
--- /dev/null
+++ b/src/pages/chart/Recharts/AreaChartComponent.js
@@ -0,0 +1,360 @@
+import React from 'react'
+import { Row, Col, Card, Button } from 'antd'
+import * as d3 from 'd3-shape'
+import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts'
+import Container from './Container'
+
+const data = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ pv: 2400,
+ amt: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ pv: 1398,
+ amt: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ pv: 9800,
+ amt: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ pv: 3908,
+ amt: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ pv: 4800,
+ amt: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ pv: 3800,
+ amt: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ pv: 4300,
+ amt: 2100,
+ },
+]
+
+const mixData = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ pv: 2400,
+ amt: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ pv: 1398,
+ amt: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ pv: 9800,
+ amt: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ pv: 3908,
+ amt: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ pv: 4800,
+ amt: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ pv: 3800,
+ amt: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ pv: 4300,
+ amt: 2100,
+ },
+]
+
+const percentData = [
+ {
+ month: '2015.01',
+ a: 4000,
+ b: 2400,
+ c: 2400,
+ },
+ {
+ month: '2015.02',
+ a: 3000,
+ b: 1398,
+ c: 2210,
+ },
+ {
+ month: '2015.03',
+ a: 2000,
+ b: 9800,
+ c: 2290,
+ },
+ {
+ month: '2015.04',
+ a: 2780,
+ b: 3908,
+ c: 2000,
+ },
+ {
+ month: '2015.05',
+ a: 1890,
+ b: 4800,
+ c: 2181,
+ },
+ {
+ month: '2015.06',
+ a: 2390,
+ b: 3800,
+ c: 2500,
+ },
+ {
+ month: '2015.07',
+ a: 3490,
+ b: 4300,
+ c: 2100,
+ },
+]
+
+const colProps = {
+ lg: 12,
+ md: 24,
+}
+
+const SimpleAreaChart = () => (
+
+
+
+
+
+
+
+
+
+)
+
+const StackedAreaChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+// StackedAreaChart
+
+const toPercent = (decimal, fixed = 0) => {
+ return `${(decimal * 100).toFixed(fixed)}%`
+}
+
+const getPercent = (value, total) => {
+ const ratio = total > 0 ? value / total : 0
+
+ return toPercent(ratio, 2)
+}
+
+const renderTooltipContent = o => {
+ const { payload, label } = o
+ const total = payload.reduce((result, entry) => result + entry.value, 0)
+
+ return (
+
+
{`${label} (Total: ${total})`}
+
+ {payload.map((entry, index) => (
+
+ {`${entry.name}: ${entry.value}(${getPercent(entry.value, total)})`}
+
+ ))}
+
+
+ )
+}
+
+const PercentAreaChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+// CardinalAreaChart
+const cardinal = d3.curveCardinal.tension(0.2)
+const CardinalAreaChart = () => (
+
+
+
+
+
+
+
+
+
+
+)
+
+const AreaChartPage = () => (
+
+
+
+ Show More
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default AreaChartPage
diff --git a/src/pages/chart/Recharts/BarChartComponent.js b/src/pages/chart/Recharts/BarChartComponent.js
new file mode 100644
index 0000000..e524ea7
--- /dev/null
+++ b/src/pages/chart/Recharts/BarChartComponent.js
@@ -0,0 +1,260 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Row, Col, Card, Button } from 'antd'
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+} from 'recharts'
+import Container from './Container'
+
+const data = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ pv: 2400,
+ amt: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ pv: 1398,
+ amt: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ pv: 9800,
+ amt: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ pv: 3908,
+ amt: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ pv: 4800,
+ amt: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ pv: 3800,
+ amt: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ pv: 4300,
+ amt: 2100,
+ },
+]
+
+const mixData = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ female: 2400,
+ male: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ female: 1398,
+ male: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ female: 9800,
+ male: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ female: 3908,
+ male: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ female: 4800,
+ male: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ female: 3800,
+ male: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ female: 4300,
+ male: 2100,
+ },
+]
+const colProps = {
+ lg: 12,
+ md: 24,
+}
+
+const SimpleBarChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+const StackedBarChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+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}
+ Z`
+}
+
+const TriangleBar = props => {
+ const { fill, x, y, width, height } = props
+ return
+}
+
+TriangleBar.propTypes = {
+ fill: PropTypes.string,
+ x: PropTypes.number,
+ y: PropTypes.number,
+ width: PropTypes.number,
+ height: PropTypes.number,
+}
+
+const CustomShapeBarChart = () => (
+
+
+
+
+
+ } label />
+
+
+)
+
+const BarChartPage = () => (
+
+
+
+ Show More
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default BarChartPage
diff --git a/src/pages/chart/Recharts/Container.js b/src/pages/chart/Recharts/Container.js
new file mode 100644
index 0000000..5c19608
--- /dev/null
+++ b/src/pages/chart/Recharts/Container.js
@@ -0,0 +1,27 @@
+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,
+}) => (
+
+)
+
+Container.propTypes = {
+ children: PropTypes.element.isRequired,
+ ratio: PropTypes.number,
+ minHeight: PropTypes.number,
+ maxHeight: PropTypes.number,
+}
+
+export default Container
diff --git a/src/pages/chart/Recharts/Container.less b/src/pages/chart/Recharts/Container.less
new file mode 100644
index 0000000..daa5c27
--- /dev/null
+++ b/src/pages/chart/Recharts/Container.less
@@ -0,0 +1,20 @@
+.container {
+ width: 100%;
+ position: relative;
+ display: inline-block;
+
+ :global {
+ .recharts-responsive-container {
+ width: e('calc(100% + 56px)') !important;
+ margin-left: -32px;
+ }
+ }
+}
+
+.content {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+}
diff --git a/src/pages/chart/Recharts/LineChartComponent.js b/src/pages/chart/Recharts/LineChartComponent.js
new file mode 100644
index 0000000..a249cdf
--- /dev/null
+++ b/src/pages/chart/Recharts/LineChartComponent.js
@@ -0,0 +1,261 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Row, Col, Card, Button } from 'antd'
+import {
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+} from 'recharts'
+import Container from './Container'
+
+const data = [
+ {
+ name: 'Page A',
+ uv: 4000,
+ pv: 2400,
+ amt: 2400,
+ },
+ {
+ name: 'Page B',
+ uv: 3000,
+ pv: 1398,
+ amt: 2210,
+ },
+ {
+ name: 'Page C',
+ uv: 2000,
+ pv: 9800,
+ amt: 2290,
+ },
+ {
+ name: 'Page D',
+ uv: 2780,
+ pv: 3908,
+ amt: 2000,
+ },
+ {
+ name: 'Page E',
+ uv: 1890,
+ pv: 4800,
+ amt: 2181,
+ },
+ {
+ name: 'Page F',
+ uv: 2390,
+ pv: 3800,
+ amt: 2500,
+ },
+ {
+ name: 'Page G',
+ uv: 3490,
+ pv: 4300,
+ amt: 2100,
+ },
+]
+
+const colProps = {
+ lg: 12,
+ md: 24,
+}
+
+const SimpleLineChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+const VerticalLineChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+const DashedLineChart = () => (
+
+
+
+
+
+
+
+
+
+
+
+)
+
+// CustomizedDotLineChart
+const CustomizedDot = ({ cx, cy, payload }) => {
+ if (payload.value > 2500) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ )
+}
+
+CustomizedDot.propTypes = {
+ cx: PropTypes.number,
+ cy: PropTypes.number,
+ payload: PropTypes.object,
+}
+
+const CustomizedDotLineChart = () => (
+
+
+
+
+
+
+
+ }
+ />
+
+
+
+)
+
+const LineChartPage = () => (
+
+
+
+ Show More
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
+
+export default LineChartPage
diff --git a/src/pages/chart/Recharts/ReChartsComponent.js b/src/pages/chart/Recharts/ReChartsComponent.js
new file mode 100644
index 0000000..9ed7acc
--- /dev/null
+++ b/src/pages/chart/Recharts/ReChartsComponent.js
@@ -0,0 +1,18 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import AreaChartComponent from './AreaChartComponent'
+import BarChartComponent from './BarChartComponent'
+import LineChartComponent from './LineChartComponent'
+
+const ReChartsComponent = ({ type }) => {
+ if (type === 'areaChart') return
+ if (type === 'barChart') return
+ return
+}
+
+ReChartsComponent.propTypes = {
+ type: PropTypes.string,
+}
+
+export default ReChartsComponent
diff --git a/src/pages/chart/Recharts/index.js b/src/pages/chart/Recharts/index.js
new file mode 100644
index 0000000..fec6ce2
--- /dev/null
+++ b/src/pages/chart/Recharts/index.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import { Radio } from 'antd'
+import { Page } from 'components'
+import ReChartsComponent from './ReChartsComponent'
+import styles from './index.less'
+
+const RadioGroup = Radio.Group
+
+const chartList = [
+ {
+ label: 'lineChart',
+ value: 'lineChart',
+ },
+ {
+ label: 'barChart',
+ value: 'barChart',
+ },
+ {
+ label: 'areaChart',
+ value: 'areaChart',
+ },
+]
+
+class Chart extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ type: '',
+ }
+ this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this)
+ }
+ handleRadioGroupChange(e) {
+ this.setState({
+ type: e.target.value,
+ })
+ }
+ render() {
+ return (
+
+
+
+
+
+
+ )
+ }
+}
+
+export default Chart
diff --git a/src/pages/chart/Recharts/index.less b/src/pages/chart/Recharts/index.less
new file mode 100644
index 0000000..169053a
--- /dev/null
+++ b/src/pages/chart/Recharts/index.less
@@ -0,0 +1,8 @@
+.chart {
+ :global {
+ .ant-card {
+ overflow: hidden;
+ margin-bottom: 24px;
+ }
+ }
+}
diff --git a/src/pages/chart/highCharts/HighChartsComponent.js b/src/pages/chart/highCharts/HighChartsComponent.js
new file mode 100644
index 0000000..520e08a
--- /dev/null
+++ b/src/pages/chart/highCharts/HighChartsComponent.js
@@ -0,0 +1,18 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import HighstockComponent from './HighstockComponent'
+import HighmapsComponent from './HighmapsComponent'
+import HighMoreComponent from './HighMoreComponent'
+
+const HighChartsComponent = ({ type }) => {
+ if (type === 'Highmaps') return
+ if (type === 'HighMore') return
+ return
+}
+
+HighChartsComponent.propTypes = {
+ type: PropTypes.string,
+}
+
+export default HighChartsComponent
diff --git a/src/pages/chart/highCharts/HighMoreComponent.js b/src/pages/chart/highCharts/HighMoreComponent.js
new file mode 100644
index 0000000..0c6273c
--- /dev/null
+++ b/src/pages/chart/highCharts/HighMoreComponent.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import ReactHighcharts from 'react-highcharts'
+import HighchartsExporting from 'highcharts-exporting'
+import HighchartsMore from 'highcharts-more'
+
+HighchartsMore(ReactHighcharts.Highcharts)
+HighchartsExporting(ReactHighcharts.Highcharts)
+
+const config = {
+ chart: {
+ polar: true,
+ },
+ xAxis: {
+ categories: [
+ 'Jan',
+ 'Feb',
+ 'Mar',
+ 'Apr',
+ 'May',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Oct',
+ 'Nov',
+ 'Dec',
+ ],
+ },
+ series: [
+ {
+ data: [
+ 29.9,
+ 71.5,
+ 106.4,
+ 129.2,
+ 144.0,
+ 176.0,
+ 135.6,
+ 148.5,
+ 216.4,
+ 194.1,
+ 95.6,
+ 54.4,
+ ],
+ },
+ ],
+}
+
+const HighMoreComponent = () => {
+ return
+}
+
+export default HighMoreComponent
diff --git a/src/pages/chart/highCharts/HighmapsComponent.js b/src/pages/chart/highCharts/HighmapsComponent.js
new file mode 100644
index 0000000..f74527b
--- /dev/null
+++ b/src/pages/chart/highCharts/HighmapsComponent.js
@@ -0,0 +1,81 @@
+import React from 'react'
+import ReactHighmaps from 'react-highcharts/ReactHighmaps.src'
+import maps from './mapdata/europe'
+
+const config = {
+ chart: {
+ spacingBottom: 20,
+ },
+ title: {
+ text: 'Europe time zones',
+ },
+
+ legend: {
+ enabled: true,
+ },
+
+ plotOptions: {
+ map: {
+ allAreas: false,
+ joinBy: ['iso-a2', 'code'],
+ dataLabels: {
+ enabled: true,
+ color: 'white',
+ style: {
+ fontWeight: 'bold',
+ },
+ },
+ mapData: maps,
+ tooltip: {
+ headerFormat: '',
+ pointFormat: '{point.name}: {series.name} ',
+ },
+ },
+ },
+
+ series: [
+ {
+ name: 'UTC',
+ data: ['IE', 'IS', 'GB', 'PT'].map(code => {
+ return { code }
+ }),
+ },
+ {
+ name: 'UTC + 1',
+ data: [
+ 'NO',
+ 'SE',
+ 'DK',
+ 'DE',
+ 'NL',
+ 'BE',
+ 'LU',
+ 'ES',
+ 'FR',
+ 'PL',
+ 'CZ',
+ 'AT',
+ 'CH',
+ 'LI',
+ 'SK',
+ 'HU',
+ 'SI',
+ 'IT',
+ 'SM',
+ 'HR',
+ 'BA',
+ 'YF',
+ 'ME',
+ 'AL',
+ 'MK',
+ ].map(code => {
+ return { code }
+ }),
+ },
+ ],
+}
+
+const HighmapsComponent = () => {
+ return
+}
+export default HighmapsComponent
diff --git a/src/pages/chart/highCharts/HighstockComponent.js b/src/pages/chart/highCharts/HighstockComponent.js
new file mode 100644
index 0000000..e2cd4e5
--- /dev/null
+++ b/src/pages/chart/highCharts/HighstockComponent.js
@@ -0,0 +1,99 @@
+import React from 'react'
+import ReactHighstock from 'react-highcharts/ReactHighstock.src'
+
+const data = [
+ [1220832000000, 22.56],
+ [1220918400000, 21.67],
+ [1221004800000, 21.66],
+ [1221091200000, 21.81],
+ [1221177600000, 21.28],
+ [1221436800000, 20.05],
+ [1221523200000, 19.98],
+ [1221609600000, 18.26],
+ [1221696000000, 19.16],
+ [1221782400000, 20.13],
+ [1222041600000, 18.72],
+ [1222128000000, 18.12],
+ [1222214400000, 18.39],
+ [1222300800000, 18.85],
+ [1222387200000, 18.32],
+ [1222646400000, 15.04],
+ [1222732800000, 16.24],
+ [1222819200000, 15.59],
+ [1222905600000, 14.3],
+ [1222992000000, 13.87],
+ [1223251200000, 14.02],
+ [1223337600000, 12.74],
+ [1223424000000, 12.83],
+ [1223510400000, 12.68],
+ [1223596800000, 13.8],
+ [1223856000000, 15.75],
+ [1223942400000, 14.87],
+ [1224028800000, 13.99],
+ [1224115200000, 14.56],
+ [1224201600000, 13.91],
+ [1224460800000, 14.06],
+ [1224547200000, 13.07],
+ [1224633600000, 13.84],
+ [1224720000000, 14.03],
+ [1224806400000, 13.77],
+ [1225065600000, 13.16],
+ [1225152000000, 14.27],
+ [1225238400000, 14.94],
+ [1225324800000, 15.86],
+ [1225411200000, 15.37],
+ [1225670400000, 15.28],
+ [1225756800000, 15.86],
+ [1225843200000, 14.76],
+ [1225929600000, 14.16],
+ [1226016000000, 14.03],
+ [1226275200000, 13.7],
+ [1226361600000, 13.54],
+ [1226448000000, 12.87],
+ [1226534400000, 13.78],
+ [1226620800000, 12.89],
+ [1226880000000, 12.59],
+ [1226966400000, 12.84],
+ [1227052800000, 12.33],
+ [1227139200000, 11.5],
+ [1227225600000, 11.8],
+ [1227484800000, 13.28],
+ [1227571200000, 12.97],
+ [1227657600000, 13.57],
+ [1227830400000, 13.24],
+ [1228089600000, 12.7],
+ [1228176000000, 13.21],
+ [1228262400000, 13.7],
+ [1228348800000, 13.06],
+ [1228435200000, 13.43],
+ [1228694400000, 14.25],
+ [1228780800000, 14.29],
+ [1228867200000, 14.03],
+ [1228953600000, 13.57],
+ [1229040000000, 14.04],
+ [1229299200000, 13.54],
+]
+
+const config = {
+ rangeSelector: {
+ selected: 1,
+ },
+ title: {
+ text: 'AAPL Stock Price',
+ },
+ series: [
+ {
+ name: 'AAPL',
+ data,
+ tooltip: {
+ valueDecimals: 2,
+ },
+ },
+ ],
+}
+
+const HighstockComponent = () => {
+ return
+}
+
+export default HighstockComponent
diff --git a/src/pages/chart/highCharts/index.js b/src/pages/chart/highCharts/index.js
new file mode 100644
index 0000000..44a80de
--- /dev/null
+++ b/src/pages/chart/highCharts/index.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import { Radio } from 'antd'
+import { Page } from 'components'
+import HighChartsComponent from './HighChartsComponent'
+import styles from './index.less'
+
+const RadioGroup = Radio.Group
+
+const chartList = [
+ {
+ label: 'Highstock',
+ value: 'Highstock',
+ },
+ {
+ label: 'Highmaps',
+ value: 'Highmaps',
+ },
+ {
+ label: 'HighMore',
+ value: 'HighMore',
+ },
+]
+
+class Chart extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ type: '',
+ }
+ this.handleRadioGroupChange = this.handleRadioGroupChange.bind(this)
+ }
+ handleRadioGroupChange(e) {
+ this.setState({
+ type: e.target.value,
+ })
+ }
+ render() {
+ return (
+
+
+
+
+
+
+ )
+ }
+}
+
+export default Chart
diff --git a/src/pages/chart/highCharts/index.less b/src/pages/chart/highCharts/index.less
new file mode 100644
index 0000000..2926f77
--- /dev/null
+++ b/src/pages/chart/highCharts/index.less
@@ -0,0 +1,7 @@
+.chart {
+ :global {
+ .ant-radio-wrapper {
+ margin-bottom: 16px;
+ }
+ }
+}
diff --git a/src/pages/chart/highCharts/mapdata/europe.js b/src/pages/chart/highCharts/mapdata/europe.js
new file mode 100644
index 0000000..95a13c9
--- /dev/null
+++ b/src/pages/chart/highCharts/mapdata/europe.js
@@ -0,0 +1,9162 @@
+module.exports = {
+ title: 'Europe',
+ version: '1.1.2',
+ type: 'FeatureCollection',
+ copyright: 'Copyright (c) 2015 Highsoft AS, Based on data from Natural Earth',
+ copyrightShort: 'Natural Earth',
+ copyrightUrl: 'http://www.naturalearthdata.com',
+ crs: { type: 'name', properties: { name: 'urn:ogc:def:crs:EPSG:102014' } },
+ 'hc-transform': {
+ default: {
+ crs:
+ '+proj=lcc +lat_1=43 +lat_2=62 +lat_0=30 +lon_0=10 +x_0=0 +y_0=0 +ellps=intl +units=m +no_defs',
+ scale: 0.000169255094964,
+ jsonres: 15.5,
+ jsonmarginX: -999,
+ jsonmarginY: 9851.0,
+ xoffset: -1706316.2597,
+ yoffset: 4824494.18154,
+ },
+ },
+ features: [
+ {
+ type: 'Feature',
+ id: 'DK',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.19,
+ 'hc-middle-y': 0.44,
+ 'hc-key': 'dk',
+ 'hc-a2': 'DK',
+ name: 'Denmark',
+ labelrank: '4',
+ 'country-abbrev': 'Den.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'DNK',
+ 'iso-a2': 'DK',
+ 'woe-id': '23424796',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [3686, 4530],
+ [3743, 4490],
+ [3764, 4508],
+ [3787, 4471],
+ [3773, 4443],
+ [3724, 4436],
+ [3644, 4481],
+ [3658, 4526],
+ [3686, 4530],
+ ],
+ ],
+ [
+ [
+ [3536, 4512],
+ [3564, 4499],
+ [3541, 4493],
+ [3513, 4524],
+ [3536, 4512],
+ ],
+ ],
+ [
+ [
+ [3898, 4549],
+ [3847, 4516],
+ [3831, 4533],
+ [3864, 4557],
+ [3898, 4549],
+ ],
+ ],
+ [
+ [
+ [3443, 4565],
+ [3482, 4530],
+ [3472, 4501],
+ [3447, 4513],
+ [3443, 4565],
+ ],
+ ],
+ [
+ [
+ [3616, 4524],
+ [3599, 4467],
+ [3584, 4496],
+ [3635, 4587],
+ [3616, 4524],
+ ],
+ ],
+ [
+ [
+ [4282, 4636],
+ [4328, 4610],
+ [4317, 4568],
+ [4251, 4596],
+ [4260, 4656],
+ [4282, 4636],
+ ],
+ ],
+ [
+ [
+ [3217, 4671],
+ [3225, 4667],
+ [3223, 4642],
+ [3210, 4667],
+ [3217, 4671],
+ ],
+ ],
+ [
+ [
+ [3533, 4717],
+ [3608, 4645],
+ [3599, 4563],
+ [3567, 4550],
+ [3511, 4568],
+ [3458, 4614],
+ [3459, 4642],
+ [3424, 4684],
+ [3533, 4717],
+ ],
+ ],
+ [
+ [
+ [3899, 4708],
+ [3889, 4727],
+ [3902, 4751],
+ [3914, 4724],
+ [3899, 4708],
+ ],
+ ],
+ [
+ [
+ [3578, 4795],
+ [3579, 4771],
+ [3562, 4769],
+ [3572, 4800],
+ [3578, 4795],
+ ],
+ ],
+ [
+ [
+ [3306, 5107],
+ [3300, 5063],
+ [3263, 5028],
+ [3247, 5060],
+ [3264, 5089],
+ [3306, 5107],
+ ],
+ ],
+ [
+ [
+ [3664, 5214],
+ [3644, 5204],
+ [3639, 5178],
+ [3611, 5196],
+ [3664, 5214],
+ ],
+ ],
+ [
+ [
+ [3282, 4516],
+ [3255, 4513],
+ [3260, 4582],
+ [3227, 4563],
+ [3225, 4595],
+ [3261, 4584],
+ [3251, 4670],
+ [3201, 4707],
+ [3166, 4708],
+ [3184, 4779],
+ [3216, 4802],
+ [3200, 4855],
+ [3172, 4868],
+ [3178, 4993],
+ [3188, 5027],
+ [3208, 5000],
+ [3249, 4999],
+ [3274, 4971],
+ [3277, 5015],
+ [3312, 5063],
+ [3347, 5035],
+ [3326, 5010],
+ [3362, 5013],
+ [3345, 5088],
+ [3389, 5126],
+ [3417, 5111],
+ [3444, 5148],
+ [3362, 5120],
+ [3338, 5136],
+ [3269, 5107],
+ [3237, 5058],
+ [3245, 5003],
+ [3199, 5057],
+ [3260, 5156],
+ [3385, 5166],
+ [3411, 5189],
+ [3472, 5289],
+ [3508, 5292],
+ [3570, 5336],
+ [3544, 5283],
+ [3563, 5244],
+ [3562, 5187],
+ [3548, 5172],
+ [3519, 5092],
+ [3535, 4992],
+ [3603, 4985],
+ [3632, 4960],
+ [3598, 4893],
+ [3578, 4899],
+ [3563, 4859],
+ [3558, 4910],
+ [3542, 4916],
+ [3513, 4872],
+ [3517, 4805],
+ [3460, 4782],
+ [3487, 4757],
+ [3444, 4736],
+ [3454, 4722],
+ [3395, 4683],
+ [3430, 4613],
+ [3394, 4588],
+ [3434, 4536],
+ [3435, 4494],
+ [3409, 4521],
+ [3384, 4487],
+ [3384, 4487],
+ [3282, 4516],
+ ],
+ ],
+ [
+ [
+ [3717, 4815],
+ [3747, 4806],
+ [3772, 4741],
+ [3805, 4817],
+ [3779, 4826],
+ [3839, 4872],
+ [3901, 4850],
+ [3884, 4814],
+ [3901, 4753],
+ [3845, 4704],
+ [3842, 4672],
+ [3879, 4649],
+ [3871, 4621],
+ [3837, 4612],
+ [3834, 4545],
+ [3818, 4538],
+ [3838, 4500],
+ [3805, 4457],
+ [3768, 4508],
+ [3790, 4538],
+ [3750, 4596],
+ [3685, 4601],
+ [3656, 4648],
+ [3675, 4656],
+ [3665, 4703],
+ [3634, 4751],
+ [3681, 4753],
+ [3717, 4786],
+ [3717, 4815],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'FO',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.56,
+ 'hc-middle-y': 0.16,
+ 'hc-key': 'fo',
+ 'hc-a2': 'FO',
+ name: 'Faroe Islands',
+ labelrank: '6',
+ 'country-abbrev': 'Faeroe Is.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'FRO',
+ 'iso-a2': 'FO',
+ 'woe-id': '23424816',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [1151, 6735],
+ [1169, 6717],
+ [1165, 6663],
+ [1146, 6700],
+ [1151, 6735],
+ ],
+ ],
+ [
+ [
+ [1176, 6812],
+ [1202, 6782],
+ [1190, 6763],
+ [1169, 6796],
+ [1176, 6812],
+ ],
+ ],
+ [
+ [
+ [1150, 6888],
+ [1163, 6872],
+ [1139, 6859],
+ [1115, 6902],
+ [1150, 6888],
+ ],
+ ],
+ [
+ [
+ [1158, 6940],
+ [1202, 6846],
+ [1193, 6819],
+ [1166, 6880],
+ [1143, 6903],
+ [1158, 6940],
+ ],
+ ],
+ [
+ [
+ [1199, 6933],
+ [1230, 6870],
+ [1208, 6857],
+ [1181, 6898],
+ [1172, 6936],
+ [1199, 6933],
+ ],
+ ],
+ [
+ [
+ [1236, 6908],
+ [1230, 6914],
+ [1227, 6927],
+ [1232, 6941],
+ [1236, 6908],
+ ],
+ ],
+ [
+ [
+ [1226, 6902],
+ [1222, 6904],
+ [1215, 6942],
+ [1217, 6946],
+ [1226, 6902],
+ ],
+ ],
+ [
+ [
+ [1254, 6915],
+ [1248, 6943],
+ [1254, 6940],
+ [1257, 6921],
+ [1255, 6914],
+ [1263, 6903],
+ [1246, 6901],
+ [1239, 6895],
+ [1243, 6931],
+ [1254, 6915],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'HR',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.09,
+ 'hc-middle-y': 0.39,
+ 'hc-key': 'hr',
+ 'hc-a2': 'HR',
+ name: 'Croatia',
+ labelrank: '6',
+ 'country-abbrev': 'Cro.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'HRV',
+ 'iso-a2': 'HR',
+ 'woe-id': '23424843',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [4965, 1080],
+ [4964, 1071],
+ [4945, 1066],
+ [4938, 1078],
+ [4965, 1080],
+ ],
+ ],
+ [
+ [
+ [5060, 1097],
+ [5137, 1081],
+ [5142, 1075],
+ [5062, 1089],
+ [5060, 1097],
+ ],
+ ],
+ [
+ [
+ [4924, 1135],
+ [4980, 1143],
+ [5017, 1129],
+ [4944, 1116],
+ [4924, 1135],
+ ],
+ ],
+ [
+ [
+ [4799, 1153],
+ [4804, 1142],
+ [4785, 1134],
+ [4768, 1148],
+ [4799, 1153],
+ ],
+ ],
+ [
+ [
+ [4873, 1205],
+ [4915, 1189],
+ [5010, 1189],
+ [4904, 1178],
+ [4834, 1192],
+ [4873, 1205],
+ ],
+ ],
+ [
+ [
+ [4922, 1243],
+ [4925, 1221],
+ [4841, 1228],
+ [4840, 1250],
+ [4922, 1243],
+ ],
+ ],
+ [
+ [
+ [4813, 1251],
+ [4834, 1236],
+ [4825, 1233],
+ [4794, 1244],
+ [4813, 1251],
+ ],
+ ],
+ [
+ [
+ [4621, 1380],
+ [4603, 1384],
+ [4580, 1409],
+ [4607, 1399],
+ [4621, 1380],
+ ],
+ ],
+ [
+ [
+ [4572, 1425],
+ [4565, 1419],
+ [4550, 1431],
+ [4536, 1450],
+ [4572, 1425],
+ ],
+ ],
+ [
+ [
+ [4496, 1441],
+ [4573, 1380],
+ [4557, 1376],
+ [4526, 1418],
+ [4496, 1441],
+ ],
+ ],
+ [
+ [
+ [4482, 1574],
+ [4494, 1578],
+ [4572, 1505],
+ [4495, 1543],
+ [4482, 1574],
+ ],
+ ],
+ [
+ [
+ [4392, 1569],
+ [4391, 1562],
+ [4374, 1601],
+ [4388, 1593],
+ [4392, 1569],
+ ],
+ ],
+ [
+ [
+ [4458, 1644],
+ [4474, 1623],
+ [4481, 1604],
+ [4444, 1643],
+ [4458, 1644],
+ ],
+ ],
+ [
+ [
+ [4398, 1672],
+ [4394, 1585],
+ [4363, 1666],
+ [4381, 1672],
+ [4355, 1720],
+ [4372, 1729],
+ [4398, 1672],
+ ],
+ ],
+ [
+ [
+ [4412, 1758],
+ [4435, 1713],
+ [4468, 1683],
+ [4386, 1710],
+ [4412, 1758],
+ ],
+ ],
+ [
+ [
+ [5311, 1013],
+ [5150, 1111],
+ [5070, 1120],
+ [5023, 1159],
+ [5115, 1130],
+ [5161, 1114],
+ [5293, 1053],
+ [5298, 1030],
+ [5311, 1013],
+ ],
+ ],
+ [
+ [
+ [5272, 2037],
+ [5265, 2001],
+ [5308, 1936],
+ [5313, 1878],
+ [5390, 1853],
+ [5399, 1831],
+ [5332, 1816],
+ [5333, 1734],
+ [5308, 1729],
+ [5259, 1787],
+ [5229, 1777],
+ [5164, 1799],
+ [5120, 1791],
+ [5085, 1763],
+ [5051, 1788],
+ [5030, 1773],
+ [4966, 1787],
+ [4950, 1773],
+ [4893, 1807],
+ [4867, 1774],
+ [4805, 1774],
+ [4781, 1716],
+ [4754, 1721],
+ [4705, 1771],
+ [4662, 1750],
+ [4668, 1659],
+ [4747, 1571],
+ [4775, 1482],
+ [4881, 1385],
+ [4890, 1365],
+ [4976, 1298],
+ [5010, 1291],
+ [5019, 1256],
+ [5062, 1201],
+ [5095, 1184],
+ [5098, 1143],
+ [4981, 1218],
+ [4936, 1263],
+ [4860, 1282],
+ [4742, 1274],
+ [4729, 1323],
+ [4625, 1387],
+ [4544, 1481],
+ [4583, 1510],
+ [4492, 1601],
+ [4491, 1679],
+ [4468, 1723],
+ [4415, 1769],
+ [4362, 1786],
+ [4296, 1624],
+ [4219, 1709],
+ [4192, 1822],
+ [4209, 1816],
+ [4271, 1801],
+ [4286, 1828],
+ [4369, 1822],
+ [4403, 1876],
+ [4428, 1842],
+ [4525, 1818],
+ [4570, 1837],
+ [4542, 1900],
+ [4581, 1934],
+ [4624, 1943],
+ [4625, 2002],
+ [4602, 2023],
+ [4614, 2053],
+ [4734, 2110],
+ [4722, 2143],
+ [4777, 2150],
+ [4851, 2116],
+ [4877, 2075],
+ [4924, 2054],
+ [4959, 2009],
+ [5008, 2009],
+ [5070, 1968],
+ [5138, 1979],
+ [5180, 1971],
+ [5227, 2026],
+ [5272, 2037],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'NL',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.34,
+ 'hc-middle-y': 0.59,
+ 'hc-key': 'nl',
+ 'hc-a2': 'NL',
+ name: 'Netherlands',
+ labelrank: '5',
+ 'country-abbrev': 'Neth.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'NLD',
+ 'iso-a2': 'NL',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [2408, 3636],
+ [2399, 3614],
+ [2350, 3647],
+ [2395, 3648],
+ [2408, 3636],
+ ],
+ ],
+ [
+ [
+ [2593, 4028],
+ [2574, 3998],
+ [2561, 4015],
+ [2588, 4051],
+ [2593, 4028],
+ ],
+ ],
+ [
+ [
+ [2603, 4061],
+ [2593, 4060],
+ [2613, 4079],
+ [2625, 4085],
+ [2603, 4061],
+ ],
+ ],
+ [
+ [
+ [2691, 4107],
+ [2652, 4094],
+ [2648, 4104],
+ [2719, 4119],
+ [2691, 4107],
+ ],
+ ],
+ [
+ [
+ [2776, 4121],
+ [2783, 4117],
+ [2735, 4111],
+ [2734, 4122],
+ [2776, 4121],
+ ],
+ ],
+ [
+ [
+ [2817, 4118],
+ [2812, 4122],
+ [2827, 4129],
+ [2847, 4126],
+ [2817, 4118],
+ ],
+ ],
+ [
+ [
+ [2280, 3553],
+ [2316, 3561],
+ [2371, 3536],
+ [2395, 3553],
+ [2437, 3537],
+ [2380, 3495],
+ [2330, 3523],
+ [2285, 3515],
+ [2280, 3553],
+ ],
+ ],
+ [
+ [
+ [2444, 3537],
+ [2389, 3565],
+ [2367, 3550],
+ [2316, 3574],
+ [2305, 3602],
+ [2372, 3613],
+ [2422, 3559],
+ [2444, 3580],
+ [2400, 3604],
+ [2436, 3629],
+ [2402, 3678],
+ [2414, 3716],
+ [2438, 3721],
+ [2510, 3811],
+ [2565, 3989],
+ [2593, 3969],
+ [2677, 4019],
+ [2717, 4076],
+ [2786, 4101],
+ [2916, 4110],
+ [2993, 4045],
+ [2988, 3965],
+ [2969, 3933],
+ [2959, 3874],
+ [2912, 3874],
+ [2897, 3827],
+ [2945, 3818],
+ [2952, 3754],
+ [2887, 3701],
+ [2910, 3678],
+ [2832, 3644],
+ [2788, 3666],
+ [2751, 3642],
+ [2779, 3594],
+ [2794, 3519],
+ [2766, 3475],
+ [2780, 3452],
+ [2737, 3419],
+ [2761, 3382],
+ [2746, 3338],
+ [2690, 3344],
+ [2723, 3456],
+ [2660, 3498],
+ [2614, 3492],
+ [2581, 3557],
+ [2561, 3534],
+ [2537, 3566],
+ [2511, 3546],
+ [2486, 3564],
+ [2467, 3530],
+ [2444, 3537],
+ ],
+ [
+ [2720, 3812],
+ [2735, 3822],
+ [2736, 3825],
+ [2736, 3825],
+ [2736, 3825],
+ [2750, 3836],
+ [2750, 3869],
+ [2717, 3876],
+ [2748, 3862],
+ [2736, 3825],
+ [2736, 3825],
+ [2736, 3825],
+ [2720, 3812],
+ [2720, 3812],
+ [2720, 3812],
+ [2720, 3812],
+ [2670, 3782],
+ [2621, 3817],
+ [2717, 3877],
+ [2712, 3924],
+ [2732, 3940],
+ [2678, 3949],
+ [2676, 4013],
+ [2616, 3976],
+ [2626, 3929],
+ [2657, 3907],
+ [2608, 3887],
+ [2614, 3833],
+ [2591, 3815],
+ [2674, 3776],
+ [2720, 3812],
+ [2720, 3812],
+ [2720, 3812],
+ [2720, 3812],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'EE',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.6,
+ 'hc-middle-y': 0.53,
+ 'hc-key': 'ee',
+ 'hc-a2': 'EE',
+ name: 'Estonia',
+ labelrank: '6',
+ 'country-abbrev': 'Est.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'EST',
+ 'iso-a2': 'EE',
+ 'woe-id': '23424805',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [5483, 5775],
+ [5469, 5746],
+ [5441, 5761],
+ [5452, 5784],
+ [5483, 5775],
+ ],
+ ],
+ [
+ [
+ [5440, 5891],
+ [5460, 5893],
+ [5468, 5876],
+ [5435, 5869],
+ [5440, 5891],
+ ],
+ ],
+ [
+ [
+ [5370, 5868],
+ [5403, 5866],
+ [5426, 5828],
+ [5383, 5810],
+ [5362, 5771],
+ [5337, 5813],
+ [5275, 5835],
+ [5334, 5850],
+ [5348, 5887],
+ [5370, 5868],
+ ],
+ ],
+ [
+ [
+ [6143, 6139],
+ [6134, 6134],
+ [6119, 6126],
+ [6130, 6125],
+ [6130, 6125],
+ [6131, 6125],
+ [6133, 6126],
+ [6124, 6119],
+ [6106, 6106],
+ [6108, 6072],
+ [6106, 6046],
+ [6102, 6021],
+ [6074, 6020],
+ [6012, 5988],
+ [6005, 5937],
+ [6044, 5907],
+ [6076, 5839],
+ [6106, 5812],
+ [6161, 5739],
+ [6194, 5705],
+ [6159, 5682],
+ [6151, 5595],
+ [6071, 5605],
+ [6022, 5561],
+ [5934, 5617],
+ [5926, 5637],
+ [5861, 5642],
+ [5801, 5677],
+ [5699, 5617],
+ [5669, 5588],
+ [5681, 5651],
+ [5674, 5732],
+ [5642, 5736],
+ [5618, 5688],
+ [5557, 5706],
+ [5535, 5759],
+ [5512, 5760],
+ [5504, 5815],
+ [5545, 5818],
+ [5543, 5838],
+ [5488, 5817],
+ [5479, 5858],
+ [5495, 5879],
+ [5471, 5891],
+ [5470, 5946],
+ [5555, 5992],
+ [5541, 6009],
+ [5694, 6088],
+ [5735, 6082],
+ [5770, 6142],
+ [5882, 6132],
+ [5912, 6141],
+ [5940, 6125],
+ [6095, 6143],
+ [6111, 6169],
+ [6126, 6160],
+ [6143, 6139],
+ ],
+ ],
+ [
+ [
+ [5280, 5633],
+ [5297, 5662],
+ [5272, 5700],
+ [5306, 5706],
+ [5369, 5757],
+ [5380, 5746],
+ [5417, 5762],
+ [5487, 5731],
+ [5463, 5728],
+ [5448, 5692],
+ [5403, 5642],
+ [5351, 5628],
+ [5342, 5561],
+ [5313, 5556],
+ [5336, 5608],
+ [5280, 5633],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'BG',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.54,
+ 'hc-middle-y': 0.49,
+ 'hc-key': 'bg',
+ 'hc-a2': 'BG',
+ name: 'Bulgaria',
+ labelrank: '4',
+ 'country-abbrev': 'Bulg.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'BGR',
+ 'iso-a2': 'BG',
+ 'woe-id': '23424771',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [7353, 1794],
+ [7373, 1738],
+ [7359, 1683],
+ [7291, 1678],
+ [7265, 1596],
+ [7264, 1551],
+ [7287, 1467],
+ [7255, 1461],
+ [7212, 1374],
+ [7250, 1382],
+ [7288, 1337],
+ [7352, 1291],
+ [7366, 1265],
+ [7320, 1259],
+ [7271, 1219],
+ [7200, 1259],
+ [7149, 1241],
+ [7136, 1215],
+ [7058, 1175],
+ [7060, 1145],
+ [7026, 1104],
+ [6967, 1083],
+ [7003, 1040],
+ [7004, 992],
+ [6956, 965],
+ [6884, 953],
+ [6831, 918],
+ [6735, 946],
+ [6714, 926],
+ [6671, 941],
+ [6645, 975],
+ [6547, 945],
+ [6462, 882],
+ [6390, 877],
+ [6357, 845],
+ [6313, 844],
+ [6303, 916],
+ [6313, 957],
+ [6262, 1037],
+ [6189, 1058],
+ [6140, 1104],
+ [6170, 1136],
+ [6144, 1181],
+ [6146, 1270],
+ [6192, 1283],
+ [6229, 1382],
+ [6118, 1443],
+ [6066, 1533],
+ [6067, 1588],
+ [6105, 1620],
+ [6108, 1660],
+ [6115, 1666],
+ [6116, 1666],
+ [6193, 1640],
+ [6168, 1606],
+ [6183, 1561],
+ [6264, 1592],
+ [6444, 1587],
+ [6512, 1615],
+ [6610, 1620],
+ [6698, 1611],
+ [6780, 1652],
+ [6838, 1749],
+ [7006, 1837],
+ [7055, 1833],
+ [7089, 1809],
+ [7144, 1825],
+ [7163, 1808],
+ [7199, 1830],
+ [7223, 1793],
+ [7278, 1781],
+ [7353, 1794],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'ES',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.38,
+ 'hc-middle-y': 0.53,
+ 'hc-key': 'es',
+ 'hc-a2': 'ES',
+ name: 'Spain',
+ labelrank: '2',
+ 'country-abbrev': 'Sp.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'ESP',
+ 'iso-a2': 'ES',
+ 'woe-id': '23424950',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [[[1502, -54], [1511, -71], [1486, -84], [1488, -64], [1502, -54]]],
+ [
+ [
+ [1546, 46],
+ [1554, 23],
+ [1497, -29],
+ [1456, -3],
+ [1495, 44],
+ [1546, 46],
+ ],
+ ],
+ [
+ [
+ [1936, 261],
+ [1927, 203],
+ [1997, 190],
+ [1929, 81],
+ [1890, 58],
+ [1826, 103],
+ [1806, 154],
+ [1767, 130],
+ [1740, 175],
+ [1879, 250],
+ [1936, 261],
+ ],
+ ],
+ [
+ [
+ [2150, 269],
+ [2183, 239],
+ [2186, 195],
+ [2124, 231],
+ [2082, 238],
+ [2083, 271],
+ [2150, 269],
+ ],
+ ],
+ [
+ [
+ [-240, -615],
+ [-227, -613],
+ [-212, -627],
+ [-226, -637],
+ [-240, -615],
+ ],
+ ],
+ [
+ [
+ [1743, 1010],
+ [1741, 1016],
+ [1746, 1022],
+ [1751, 1009],
+ [1743, 1010],
+ ],
+ ],
+ [
+ [
+ [-212, -550],
+ [-280, -577],
+ [-390, -461],
+ [-390, -378],
+ [-423, -351],
+ [-410, -302],
+ [-426, -252],
+ [-503, -171],
+ [-621, -134],
+ [-621, -20],
+ [-559, 40],
+ [-533, 84],
+ [-473, 83],
+ [-444, 129],
+ [-481, 131],
+ [-520, 224],
+ [-479, 302],
+ [-423, 324],
+ [-393, 365],
+ [-430, 404],
+ [-449, 478],
+ [-438, 511],
+ [-476, 588],
+ [-361, 562],
+ [-304, 645],
+ [-328, 703],
+ [-262, 740],
+ [-270, 768],
+ [-238, 881],
+ [-249, 936],
+ [-220, 941],
+ [-168, 993],
+ [-134, 993],
+ [-54, 1057],
+ [-122, 1124],
+ [-107, 1176],
+ [-226, 1223],
+ [-257, 1193],
+ [-338, 1204],
+ [-354, 1228],
+ [-457, 1228],
+ [-463, 1252],
+ [-423, 1288],
+ [-441, 1327],
+ [-534, 1320],
+ [-566, 1304],
+ [-596, 1288],
+ [-587, 1350],
+ [-515, 1391],
+ [-569, 1392],
+ [-513, 1429],
+ [-557, 1437],
+ [-523, 1496],
+ [-578, 1477],
+ [-586, 1499],
+ [-540, 1545],
+ [-582, 1564],
+ [-574, 1593],
+ [-606, 1604],
+ [-593, 1640],
+ [-553, 1673],
+ [-514, 1671],
+ [-482, 1695],
+ [-455, 1674],
+ [-372, 1686],
+ [-356, 1731],
+ [-254, 1763],
+ [-154, 1714],
+ [-134, 1675],
+ [75, 1634],
+ [238, 1587],
+ [284, 1556],
+ [443, 1491],
+ [623, 1495],
+ [629, 1468],
+ [712, 1434],
+ [786, 1445],
+ [860, 1392],
+ [909, 1376],
+ [984, 1392],
+ [989, 1363],
+ [1059, 1338],
+ [1034, 1294],
+ [1135, 1241],
+ [1182, 1231],
+ [1213, 1182],
+ [1270, 1188],
+ [1324, 1134],
+ [1370, 1139],
+ [1390, 1120],
+ [1470, 1114],
+ [1478, 1158],
+ [1615, 1104],
+ [1634, 1067],
+ [1645, 1016],
+ [1691, 1033],
+ [1760, 981],
+ [1811, 998],
+ [1848, 968],
+ [1953, 995],
+ [2005, 979],
+ [2032, 944],
+ [1994, 929],
+ [1984, 895],
+ [2004, 842],
+ [1931, 775],
+ [1785, 717],
+ [1727, 667],
+ [1609, 655],
+ [1483, 627],
+ [1414, 570],
+ [1439, 525],
+ [1381, 514],
+ [1313, 426],
+ [1239, 361],
+ [1131, 223],
+ [1138, 92],
+ [1175, 24],
+ [1224, -23],
+ [1143, -71],
+ [1081, -84],
+ [1038, -115],
+ [959, -245],
+ [961, -319],
+ [864, -330],
+ [834, -311],
+ [724, -358],
+ [683, -399],
+ [650, -471],
+ [586, -524],
+ [536, -485],
+ [484, -484],
+ [458, -514],
+ [327, -472],
+ [280, -482],
+ [239, -459],
+ [132, -437],
+ [41, -430],
+ [12, -464],
+ [-40, -480],
+ [-81, -467],
+ [-154, -480],
+ [-207, -551],
+ [-212, -550],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'IT',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.44,
+ 'hc-middle-y': 0.38,
+ 'hc-key': 'it',
+ 'hc-a2': 'IT',
+ name: 'Italy',
+ labelrank: '2',
+ 'country-abbrev': 'Italy',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'ITA',
+ 'iso-a2': 'IT',
+ 'woe-id': '23424853',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [3951, -735],
+ [3968, -746],
+ [3964, -760],
+ [3941, -747],
+ [3951, -735],
+ ],
+ ],
+ [
+ [
+ [4632, -225],
+ [4627, -220],
+ [4615, -212],
+ [4628, -199],
+ [4632, -225],
+ ],
+ ],
+ [[[3101, -59], [3124, -77], [3111, -105], [3098, -75], [3101, -59]]],
+ [[[3088, -62], [3076, -61], [3070, -47], [3089, -36], [3088, -62]]],
+ [[[4361, 430], [4336, 430], [4339, 444], [4362, 437], [4361, 430]]],
+ [[[3108, 525], [3108, 513], [3089, 508], [3096, 526], [3108, 525]]],
+ [
+ [
+ [3570, 1021],
+ [3559, 994],
+ [3500, 1004],
+ [3511, 1022],
+ [3570, 1021],
+ ],
+ ],
+ [
+ [
+ [4232, 1848],
+ [4234, 1880],
+ [4197, 1904],
+ [4172, 1883],
+ [4130, 1896],
+ [4104, 1856],
+ [3969, 1791],
+ [3987, 1831],
+ [3941, 1798],
+ [3929, 1753],
+ [3956, 1693],
+ [3999, 1657],
+ [3982, 1613],
+ [3951, 1618],
+ [3952, 1515],
+ [3972, 1447],
+ [4046, 1372],
+ [4097, 1349],
+ [4164, 1295],
+ [4243, 1249],
+ [4295, 1134],
+ [4324, 1039],
+ [4355, 983],
+ [4508, 842],
+ [4595, 804],
+ [4666, 801],
+ [4791, 822],
+ [4831, 780],
+ [4776, 731],
+ [4777, 691],
+ [4803, 671],
+ [4934, 618],
+ [5040, 591],
+ [5140, 527],
+ [5263, 487],
+ [5321, 437],
+ [5395, 344],
+ [5373, 247],
+ [5302, 273],
+ [5278, 332],
+ [5239, 378],
+ [5164, 374],
+ [5094, 397],
+ [5054, 427],
+ [5026, 402],
+ [4967, 290],
+ [4976, 256],
+ [4949, 206],
+ [4957, 172],
+ [5012, 157],
+ [5111, 103],
+ [5111, 19],
+ [5133, -6],
+ [5113, -47],
+ [5052, -47],
+ [4988, -111],
+ [5003, -197],
+ [4918, -289],
+ [4904, -348],
+ [4805, -351],
+ [4795, -270],
+ [4825, -257],
+ [4848, -197],
+ [4830, -143],
+ [4905, -111],
+ [4910, -66],
+ [4874, -17],
+ [4845, 89],
+ [4813, 123],
+ [4787, 211],
+ [4743, 268],
+ [4685, 243],
+ [4632, 288],
+ [4582, 305],
+ [4599, 352],
+ [4538, 431],
+ [4446, 398],
+ [4475, 442],
+ [4433, 472],
+ [4389, 467],
+ [4300, 585],
+ [4268, 571],
+ [4211, 594],
+ [4151, 571],
+ [4115, 620],
+ [4058, 632],
+ [4015, 684],
+ [3968, 713],
+ [3946, 762],
+ [3876, 798],
+ [3837, 869],
+ [3780, 903],
+ [3714, 902],
+ [3734, 937],
+ [3690, 992],
+ [3634, 1019],
+ [3644, 1045],
+ [3589, 1053],
+ [3594, 1118],
+ [3570, 1188],
+ [3547, 1214],
+ [3533, 1311],
+ [3500, 1371],
+ [3440, 1384],
+ [3317, 1469],
+ [3212, 1491],
+ [3157, 1458],
+ [3107, 1400],
+ [3093, 1358],
+ [3048, 1329],
+ [2951, 1315],
+ [2947, 1336],
+ [2994, 1398],
+ [2987, 1425],
+ [2929, 1412],
+ [2858, 1449],
+ [2825, 1488],
+ [2823, 1539],
+ [2868, 1577],
+ [2845, 1630],
+ [2803, 1651],
+ [2780, 1703],
+ [2830, 1708],
+ [2885, 1743],
+ [2898, 1787],
+ [2863, 1817],
+ [2860, 1855],
+ [2827, 1879],
+ [2830, 1910],
+ [2876, 1937],
+ [2908, 1923],
+ [2981, 1950],
+ [3039, 1928],
+ [3097, 1988],
+ [3091, 2025],
+ [3166, 2075],
+ [3162, 2022],
+ [3196, 1984],
+ [3243, 1967],
+ [3255, 1898],
+ [3287, 1913],
+ [3272, 1939],
+ [3331, 2036],
+ [3330, 2087],
+ [3365, 2089],
+ [3389, 2031],
+ [3470, 2049],
+ [3486, 2010],
+ [3509, 2022],
+ [3486, 2071],
+ [3495, 2121],
+ [3562, 2101],
+ [3551, 2141],
+ [3567, 2197],
+ [3676, 2170],
+ [3694, 2212],
+ [3737, 2234],
+ [3823, 2232],
+ [3913, 2265],
+ [3895, 2240],
+ [3956, 2154],
+ [4122, 2120],
+ [4216, 2116],
+ [4152, 2046],
+ [4209, 2017],
+ [4176, 1965],
+ [4209, 1955],
+ [4203, 1909],
+ [4269, 1861],
+ [4232, 1848],
+ ],
+ [
+ [3995, 1344],
+ [3998, 1370],
+ [3986, 1365],
+ [3979, 1352],
+ [3995, 1344],
+ ],
+ [[4013, 764], [4013, 764], [4013, 764], [4013, 764], [4013, 764]],
+ ],
+ [
+ [
+ [4478, -359],
+ [4561, -334],
+ [4623, -299],
+ [4666, -313],
+ [4761, -256],
+ [4763, -319],
+ [4702, -424],
+ [4681, -501],
+ [4688, -552],
+ [4748, -640],
+ [4712, -662],
+ [4694, -749],
+ [4551, -718],
+ [4496, -647],
+ [4450, -628],
+ [4404, -635],
+ [4296, -582],
+ [4228, -529],
+ [4153, -506],
+ [4105, -511],
+ [4048, -440],
+ [4064, -380],
+ [4122, -328],
+ [4157, -371],
+ [4202, -322],
+ [4252, -310],
+ [4270, -344],
+ [4366, -378],
+ [4418, -353],
+ [4478, -359],
+ ],
+ ],
+ [
+ [
+ [3266, -34],
+ [3251, -99],
+ [3213, -132],
+ [3155, -125],
+ [3146, -78],
+ [3104, -26],
+ [3106, 18],
+ [3148, 164],
+ [3115, 173],
+ [3137, 231],
+ [3132, 293],
+ [3100, 371],
+ [3066, 368],
+ [3061, 416],
+ [3084, 469],
+ [3148, 443],
+ [3203, 467],
+ [3307, 568],
+ [3353, 545],
+ [3381, 525],
+ [3369, 495],
+ [3439, 349],
+ [3393, 274],
+ [3417, 221],
+ [3396, 45],
+ [3376, -56],
+ [3315, -32],
+ [3266, -34],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'SM',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.68,
+ 'hc-middle-y': 0.41,
+ 'hc-key': 'sm',
+ 'hc-a2': 'SM',
+ name: 'San Marino',
+ labelrank: '6',
+ 'country-abbrev': 'S.M.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'SMR',
+ 'iso-a2': 'SM',
+ 'woe-id': '23424947',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [3995, 1344],
+ [3979, 1352],
+ [3986, 1365],
+ [3998, 1370],
+ [3995, 1344],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'VA',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.62,
+ 'hc-middle-y': 0.44,
+ 'hc-key': 'va',
+ 'hc-a2': 'VA',
+ name: 'Vatican',
+ labelrank: '6',
+ 'country-abbrev': 'Vat.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'VAT',
+ 'iso-a2': 'VA',
+ 'woe-id': '23424986',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [[4013, 764], [4013, 764], [4013, 764], [4013, 764], [4013, 764]],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'TR',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.62,
+ 'hc-middle-y': 0.51,
+ 'hc-key': 'tr',
+ 'hc-a2': 'TR',
+ name: 'Turkey',
+ labelrank: '2',
+ 'country-abbrev': 'Tur.',
+ subregion: 'Western Asia',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'TUR',
+ 'iso-a2': 'TR',
+ 'woe-id': '23424969',
+ continent: 'Asia',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [[[7048, 641], [7008, 614], [6984, 617], [7031, 663], [7048, 641]]],
+ [[[7377, 872], [7400, 872], [7378, 846], [7356, 860], [7377, 872]]],
+ [
+ [
+ [7026, 1104],
+ [7060, 1145],
+ [7058, 1175],
+ [7136, 1215],
+ [7149, 1241],
+ [7200, 1259],
+ [7271, 1219],
+ [7320, 1259],
+ [7366, 1265],
+ [7367, 1220],
+ [7404, 1176],
+ [7482, 1136],
+ [7608, 1115],
+ [7653, 1117],
+ [7644, 1044],
+ [7562, 1015],
+ [7478, 1025],
+ [7426, 979],
+ [7331, 959],
+ [7321, 909],
+ [7281, 839],
+ [7186, 763],
+ [7178, 732],
+ [7097, 621],
+ [7110, 666],
+ [7091, 700],
+ [7208, 812],
+ [7195, 827],
+ [7137, 795],
+ [7043, 777],
+ [7028, 811],
+ [7081, 892],
+ [7056, 973],
+ [7113, 1024],
+ [7089, 1088],
+ [7026, 1104],
+ ],
+ ],
+ [
+ [
+ [9732, 429],
+ [9709, 427],
+ [9717, 324],
+ [9732, 308],
+ [9732, 245],
+ [9709, 236],
+ [9731, 170],
+ [9699, 144],
+ [9700, 102],
+ [9638, 110],
+ [9642, 143],
+ [9568, 212],
+ [9628, 325],
+ [9607, 380],
+ [9556, 400],
+ [9498, 327],
+ [9502, 279],
+ [9445, 237],
+ [9287, 266],
+ [9243, 235],
+ [9170, 98],
+ [9163, 32],
+ [9133, 54],
+ [9107, -9],
+ [8982, -55],
+ [8915, -110],
+ [8801, -100],
+ [8689, -21],
+ [8509, 5],
+ [8352, -16],
+ [8335, -55],
+ [8356, -128],
+ [8340, -219],
+ [8301, -212],
+ [8181, -304],
+ [8158, -284],
+ [8099, -292],
+ [8040, -273],
+ [8000, -223],
+ [8004, -185],
+ [7961, -170],
+ [7948, -209],
+ [7892, -205],
+ [7879, -172],
+ [7800, -182],
+ [7811, -212],
+ [7781, -263],
+ [7741, -246],
+ [7754, -221],
+ [7682, -240],
+ [7674, -274],
+ [7600, -284],
+ [7653, -235],
+ [7752, -207],
+ [7737, -175],
+ [7792, -123],
+ [7626, -189],
+ [7594, -180],
+ [7558, -209],
+ [7560, -159],
+ [7597, -159],
+ [7617, -99],
+ [7583, -114],
+ [7568, -76],
+ [7518, -98],
+ [7500, -29],
+ [7450, -20],
+ [7499, 16],
+ [7480, 85],
+ [7391, 80],
+ [7355, 125],
+ [7323, 84],
+ [7232, 113],
+ [7280, 153],
+ [7234, 219],
+ [7268, 237],
+ [7305, 205],
+ [7329, 146],
+ [7417, 196],
+ [7380, 197],
+ [7311, 268],
+ [7348, 280],
+ [7369, 348],
+ [7329, 331],
+ [7324, 377],
+ [7249, 421],
+ [7305, 498],
+ [7291, 525],
+ [7117, 451],
+ [7123, 498],
+ [7103, 589],
+ [7133, 619],
+ [7143, 674],
+ [7201, 751],
+ [7262, 762],
+ [7321, 796],
+ [7363, 765],
+ [7436, 783],
+ [7400, 829],
+ [7479, 841],
+ [7456, 812],
+ [7644, 862],
+ [7687, 862],
+ [7724, 893],
+ [7635, 896],
+ [7672, 943],
+ [7792, 990],
+ [7866, 1032],
+ [7743, 998],
+ [7655, 1041],
+ [7651, 1092],
+ [7679, 1126],
+ [7825, 1139],
+ [7879, 1153],
+ [7902, 1180],
+ [8032, 1178],
+ [8116, 1207],
+ [8142, 1249],
+ [8133, 1281],
+ [8262, 1408],
+ [8278, 1451],
+ [8340, 1507],
+ [8402, 1540],
+ [8471, 1606],
+ [8686, 1658],
+ [8761, 1684],
+ [8797, 1744],
+ [8844, 1737],
+ [8842, 1713],
+ [8888, 1673],
+ [8964, 1661],
+ [9041, 1721],
+ [9086, 1704],
+ [9106, 1660],
+ [9194, 1625],
+ [9215, 1675],
+ [9298, 1682],
+ [9322, 1656],
+ [9449, 1661],
+ [9460, 1698],
+ [9520, 1672],
+ [9616, 1692],
+ [9691, 1735],
+ [9724, 1777],
+ [9732, 1781],
+ [9732, 429],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'MT',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.67,
+ 'hc-middle-y': 0.77,
+ 'hc-key': 'mt',
+ 'hc-a2': 'MT',
+ name: 'Malta',
+ labelrank: '5',
+ 'country-abbrev': 'Malta',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Middle East & North Africa',
+ 'iso-a3': 'MLT',
+ 'iso-a2': 'MT',
+ 'woe-id': '23424897',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [4588, -999],
+ [4533, -992],
+ [4526, -965],
+ [4572, -975],
+ [4588, -999],
+ ],
+ ],
+ [
+ [
+ [4514, -952],
+ [4492, -948],
+ [4508, -935],
+ [4528, -946],
+ [4514, -952],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'FR',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.47,
+ 'hc-middle-y': 0.47,
+ 'hc-key': 'fr',
+ 'hc-a2': 'FR',
+ name: 'France',
+ labelrank: '2',
+ 'country-abbrev': 'Fr.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'FRA',
+ 'iso-a2': 'FR',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [1209, 2125],
+ [1227, 2092],
+ [1216, 2069],
+ [1190, 2121],
+ [1209, 2125],
+ ],
+ ],
+ [
+ [
+ [1184, 2202],
+ [1214, 2184],
+ [1223, 2170],
+ [1167, 2205],
+ [1184, 2202],
+ ],
+ ],
+ [
+ [
+ [1077, 2433],
+ [1065, 2431],
+ [1059, 2452],
+ [1077, 2447],
+ [1077, 2433],
+ ],
+ ],
+ [[[915, 2566], [923, 2556], [890, 2567], [893, 2589], [915, 2566]]],
+ [
+ [
+ [2720, 2051],
+ [2736, 2073],
+ [2835, 2080],
+ [2844, 1995],
+ [2876, 1937],
+ [2830, 1910],
+ [2827, 1879],
+ [2860, 1855],
+ [2863, 1817],
+ [2898, 1787],
+ [2885, 1743],
+ [2830, 1708],
+ [2780, 1703],
+ [2803, 1651],
+ [2845, 1630],
+ [2868, 1577],
+ [2823, 1539],
+ [2825, 1488],
+ [2858, 1449],
+ [2929, 1412],
+ [2987, 1425],
+ [2994, 1398],
+ [2947, 1336],
+ [2951, 1315],
+ [2945, 1307],
+ [2937, 1301],
+ [2931, 1307],
+ [2922, 1295],
+ [2876, 1277],
+ [2872, 1248],
+ [2784, 1209],
+ [2754, 1175],
+ [2770, 1150],
+ [2592, 1113],
+ [2547, 1158],
+ [2487, 1170],
+ [2478, 1211],
+ [2429, 1206],
+ [2454, 1234],
+ [2402, 1241],
+ [2378, 1215],
+ [2324, 1226],
+ [2315, 1252],
+ [2250, 1258],
+ [2231, 1287],
+ [2195, 1284],
+ [2072, 1222],
+ [2010, 1176],
+ [1989, 1130],
+ [1981, 1017],
+ [2005, 979],
+ [1953, 995],
+ [1848, 968],
+ [1811, 998],
+ [1760, 981],
+ [1691, 1033],
+ [1697, 1064],
+ [1634, 1067],
+ [1615, 1104],
+ [1478, 1158],
+ [1470, 1114],
+ [1390, 1120],
+ [1370, 1139],
+ [1324, 1134],
+ [1270, 1188],
+ [1213, 1182],
+ [1182, 1231],
+ [1135, 1241],
+ [1034, 1294],
+ [1059, 1338],
+ [989, 1363],
+ [984, 1392],
+ [1013, 1392],
+ [1059, 1437],
+ [1169, 1739],
+ [1152, 1731],
+ [1216, 1974],
+ [1230, 1995],
+ [1284, 1915],
+ [1291, 1943],
+ [1214, 2039],
+ [1247, 2091],
+ [1256, 2193],
+ [1130, 2285],
+ [1126, 2324],
+ [1083, 2386],
+ [1119, 2448],
+ [1091, 2486],
+ [1101, 2527],
+ [1073, 2513],
+ [1026, 2561],
+ [1060, 2567],
+ [1044, 2600],
+ [981, 2603],
+ [996, 2638],
+ [936, 2634],
+ [860, 2708],
+ [799, 2726],
+ [788, 2753],
+ [700, 2747],
+ [698, 2797],
+ [656, 2833],
+ [733, 2829],
+ [736, 2855],
+ [696, 2895],
+ [737, 2918],
+ [659, 2913],
+ [664, 2956],
+ [711, 2987],
+ [760, 2981],
+ [828, 2994],
+ [845, 2960],
+ [858, 2988],
+ [901, 2967],
+ [920, 3008],
+ [1000, 3002],
+ [1059, 2885],
+ [1137, 2923],
+ [1151, 2890],
+ [1227, 2916],
+ [1224, 2890],
+ [1313, 2887],
+ [1283, 2917],
+ [1297, 2997],
+ [1296, 3054],
+ [1264, 3110],
+ [1258, 3206],
+ [1317, 3176],
+ [1357, 3187],
+ [1384, 3157],
+ [1366, 3140],
+ [1383, 3100],
+ [1447, 3071],
+ [1523, 3053],
+ [1556, 3030],
+ [1633, 3059],
+ [1681, 3063],
+ [1625, 3083],
+ [1659, 3147],
+ [1746, 3178],
+ [1841, 3190],
+ [1906, 3248],
+ [1919, 3273],
+ [1946, 3441],
+ [2022, 3473],
+ [2124, 3485],
+ [2123, 3485],
+ [2129, 3413],
+ [2161, 3376],
+ [2227, 3382],
+ [2244, 3311],
+ [2310, 3281],
+ [2310, 3245],
+ [2377, 3244],
+ [2408, 3217],
+ [2390, 3138],
+ [2443, 3122],
+ [2486, 3135],
+ [2492, 3162],
+ [2529, 3175],
+ [2510, 3129],
+ [2519, 3074],
+ [2536, 3076],
+ [2629, 2982],
+ [2688, 2991],
+ [2719, 2961],
+ [2752, 2975],
+ [2791, 2962],
+ [2819, 2954],
+ [2854, 2877],
+ [2879, 2886],
+ [2960, 2853],
+ [2984, 2871],
+ [3032, 2830],
+ [3085, 2829],
+ [3136, 2805],
+ [3116, 2766],
+ [3059, 2708],
+ [3045, 2634],
+ [3008, 2560],
+ [3016, 2533],
+ [2996, 2470],
+ [3006, 2412],
+ [2964, 2369],
+ [2892, 2392],
+ [2862, 2351],
+ [2897, 2346],
+ [2805, 2247],
+ [2773, 2237],
+ [2768, 2184],
+ [2706, 2139],
+ [2688, 2089],
+ [2704, 2071],
+ [2664, 2007],
+ [2731, 2035],
+ [2720, 2051],
+ ],
+ [
+ [1743, 1010],
+ [1751, 1009],
+ [1746, 1022],
+ [1741, 1016],
+ [1743, 1010],
+ ],
+ ],
+ [
+ [
+ [3204, 798],
+ [3163, 857],
+ [3201, 949],
+ [3285, 996],
+ [3325, 981],
+ [3337, 1073],
+ [3354, 1080],
+ [3367, 1026],
+ [3360, 972],
+ [3377, 942],
+ [3380, 816],
+ [3347, 770],
+ [3346, 698],
+ [3306, 600],
+ [3212, 657],
+ [3241, 695],
+ [3192, 706],
+ [3203, 766],
+ [3169, 777],
+ [3204, 798],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'NO',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.43,
+ 'hc-middle-y': 0.8,
+ 'hc-key': 'no',
+ 'hc-a2': 'NO',
+ name: 'Norway',
+ labelrank: '3',
+ 'country-abbrev': 'Nor.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'NOR',
+ 'iso-a2': 'NO',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [2823, 5756],
+ [2848, 5748],
+ [2843, 5737],
+ [2818, 5753],
+ [2823, 5756],
+ ],
+ ],
+ [
+ [
+ [2800, 5766],
+ [2790, 5779],
+ [2796, 5789],
+ [2803, 5778],
+ [2800, 5766],
+ ],
+ ],
+ [
+ [
+ [2884, 5781],
+ [2873, 5785],
+ [2877, 5796],
+ [2899, 5793],
+ [2884, 5781],
+ ],
+ ],
+ [
+ [
+ [2777, 5805],
+ [2777, 5769],
+ [2759, 5778],
+ [2769, 5841],
+ [2777, 5805],
+ ],
+ ],
+ [
+ [
+ [2778, 5961],
+ [2792, 5938],
+ [2757, 5944],
+ [2763, 5974],
+ [2778, 5961],
+ ],
+ ],
+ [
+ [
+ [2819, 5951],
+ [2791, 5950],
+ [2785, 5984],
+ [2810, 5991],
+ [2819, 5951],
+ ],
+ ],
+ [
+ [
+ [2847, 6026],
+ [2842, 5982],
+ [2822, 5979],
+ [2818, 6024],
+ [2847, 6026],
+ ],
+ ],
+ [
+ [
+ [2789, 6032],
+ [2789, 6009],
+ [2776, 6024],
+ [2782, 6042],
+ [2789, 6032],
+ ],
+ ],
+ [
+ [
+ [2770, 6105],
+ [2770, 6070],
+ [2748, 6098],
+ [2755, 6142],
+ [2770, 6105],
+ ],
+ ],
+ [
+ [
+ [2764, 6164],
+ [2782, 6157],
+ [2786, 6132],
+ [2759, 6160],
+ [2764, 6164],
+ ],
+ ],
+ [
+ [
+ [2744, 6285],
+ [2757, 6268],
+ [2750, 6265],
+ [2737, 6285],
+ [2744, 6285],
+ ],
+ ],
+ [
+ [
+ [2734, 6314],
+ [2729, 6303],
+ [2722, 6324],
+ [2730, 6330],
+ [2734, 6314],
+ ],
+ ],
+ [
+ [
+ [2758, 6346],
+ [2771, 6338],
+ [2743, 6323],
+ [2745, 6350],
+ [2758, 6346],
+ ],
+ ],
+ [
+ [
+ [2782, 6565],
+ [2805, 6551],
+ [2775, 6531],
+ [2760, 6550],
+ [2782, 6565],
+ ],
+ ],
+ [
+ [
+ [2800, 6596],
+ [2811, 6592],
+ [2802, 6572],
+ [2789, 6604],
+ [2800, 6596],
+ ],
+ ],
+ [
+ [
+ [2893, 6675],
+ [2901, 6648],
+ [2869, 6646],
+ [2873, 6674],
+ [2893, 6675],
+ ],
+ ],
+ [
+ [
+ [2880, 6686],
+ [2899, 6693],
+ [2896, 6683],
+ [2868, 6687],
+ [2880, 6686],
+ ],
+ ],
+ [
+ [
+ [2943, 6687],
+ [2915, 6661],
+ [2907, 6693],
+ [2927, 6711],
+ [2943, 6687],
+ ],
+ ],
+ [
+ [
+ [2964, 6713],
+ [2978, 6701],
+ [2947, 6703],
+ [2938, 6713],
+ [2964, 6713],
+ ],
+ ],
+ [
+ [
+ [3061, 6794],
+ [3062, 6784],
+ [3029, 6773],
+ [3032, 6794],
+ [3061, 6794],
+ ],
+ ],
+ [
+ [
+ [3050, 6830],
+ [3065, 6830],
+ [3059, 6806],
+ [3046, 6817],
+ [3050, 6830],
+ ],
+ ],
+ [
+ [
+ [3200, 6891],
+ [3183, 6874],
+ [3169, 6884],
+ [3176, 6896],
+ [3200, 6891],
+ ],
+ ],
+ [
+ [
+ [3168, 6874],
+ [3147, 6853],
+ [3131, 6886],
+ [3153, 6875],
+ [3168, 6874],
+ ],
+ ],
+ [
+ [
+ [3253, 6915],
+ [3238, 6915],
+ [3235, 6931],
+ [3244, 6931],
+ [3253, 6915],
+ ],
+ ],
+ [
+ [
+ [3237, 6913],
+ [3214, 6907],
+ [3203, 6920],
+ [3223, 6938],
+ [3237, 6913],
+ ],
+ ],
+ [
+ [
+ [3227, 6967],
+ [3188, 6977],
+ [3215, 7006],
+ [3238, 6981],
+ [3227, 6967],
+ ],
+ ],
+ [
+ [
+ [3321, 7101],
+ [3324, 7076],
+ [3313, 7067],
+ [3257, 7062],
+ [3321, 7101],
+ ],
+ ],
+ [
+ [
+ [3651, 7346],
+ [3663, 7333],
+ [3660, 7319],
+ [3649, 7325],
+ [3651, 7346],
+ ],
+ ],
+ [
+ [
+ [3633, 7339],
+ [3658, 7299],
+ [3628, 7308],
+ [3615, 7351],
+ [3633, 7339],
+ ],
+ ],
+ [
+ [
+ [3648, 7351],
+ [3644, 7336],
+ [3627, 7357],
+ [3642, 7363],
+ [3648, 7351],
+ ],
+ ],
+ [
+ [
+ [3629, 7427],
+ [3613, 7424],
+ [3581, 7411],
+ [3614, 7439],
+ [3629, 7427],
+ ],
+ ],
+ [
+ [
+ [3580, 7414],
+ [3570, 7409],
+ [3576, 7431],
+ [3617, 7446],
+ [3580, 7414],
+ ],
+ ],
+ [
+ [
+ [3699, 7488],
+ [3672, 7467],
+ [3667, 7471],
+ [3675, 7487],
+ [3699, 7488],
+ ],
+ ],
+ [
+ [
+ [3759, 7501],
+ [3747, 7473],
+ [3727, 7478],
+ [3750, 7520],
+ [3759, 7501],
+ ],
+ ],
+ [
+ [
+ [3773, 7608],
+ [3785, 7573],
+ [3736, 7520],
+ [3740, 7562],
+ [3773, 7608],
+ ],
+ ],
+ [
+ [
+ [3716, 7662],
+ [3713, 7631],
+ [3693, 7638],
+ [3701, 7661],
+ [3716, 7662],
+ ],
+ ],
+ [
+ [
+ [3809, 7748],
+ [3780, 7719],
+ [3765, 7722],
+ [3777, 7749],
+ [3809, 7748],
+ ],
+ ],
+ [
+ [
+ [3791, 7809],
+ [3797, 7789],
+ [3783, 7773],
+ [3755, 7758],
+ [3791, 7809],
+ ],
+ ],
+ [
+ [
+ [3814, 7846],
+ [3823, 7829],
+ [3809, 7822],
+ [3803, 7832],
+ [3814, 7846],
+ ],
+ ],
+ [
+ [
+ [3830, 7885],
+ [3824, 7862],
+ [3812, 7870],
+ [3813, 7887],
+ [3830, 7885],
+ ],
+ ],
+ [
+ [
+ [3971, 8096],
+ [3969, 8064],
+ [3943, 8083],
+ [3950, 8101],
+ [3971, 8096],
+ ],
+ ],
+ [
+ [
+ [3984, 8190],
+ [3983, 8182],
+ [3965, 8175],
+ [3980, 8195],
+ [3984, 8190],
+ ],
+ ],
+ [
+ [
+ [4054, 8360],
+ [4075, 8347],
+ [4039, 8341],
+ [4039, 8358],
+ [4054, 8360],
+ ],
+ ],
+ [
+ [
+ [4072, 8359],
+ [4062, 8358],
+ [4059, 8367],
+ [4066, 8380],
+ [4072, 8359],
+ ],
+ ],
+ [
+ [
+ [3826, 8372],
+ [3831, 8341],
+ [3794, 8296],
+ [3813, 8365],
+ [3826, 8372],
+ ],
+ ],
+ [
+ [
+ [3859, 8374],
+ [3843, 8351],
+ [3835, 8373],
+ [3863, 8394],
+ [3859, 8374],
+ ],
+ ],
+ [
+ [
+ [4024, 8439],
+ [4013, 8439],
+ [4022, 8456],
+ [4030, 8450],
+ [4024, 8439],
+ ],
+ ],
+ [
+ [
+ [3950, 8456],
+ [3946, 8436],
+ [3940, 8449],
+ [3930, 8460],
+ [3950, 8456],
+ ],
+ ],
+ [
+ [
+ [3920, 8440],
+ [3929, 8414],
+ [3900, 8406],
+ [3887, 8379],
+ [3868, 8396],
+ [3868, 8430],
+ [3920, 8440],
+ ],
+ ],
+ [
+ [
+ [4049, 8500],
+ [4009, 8443],
+ [3948, 8407],
+ [3978, 8458],
+ [3965, 8474],
+ [3993, 8493],
+ [4049, 8500],
+ ],
+ ],
+ [
+ [
+ [4187, 8508],
+ [4154, 8495],
+ [4161, 8532],
+ [4178, 8540],
+ [4187, 8508],
+ ],
+ ],
+ [
+ [
+ [4004, 8514],
+ [3985, 8532],
+ [4029, 8533],
+ [4018, 8515],
+ [4004, 8514],
+ ],
+ ],
+ [
+ [
+ [4255, 8614],
+ [4227, 8601],
+ [4226, 8616],
+ [4242, 8644],
+ [4255, 8614],
+ ],
+ ],
+ [
+ [
+ [4265, 8646],
+ [4263, 8664],
+ [4288, 8650],
+ [4267, 8626],
+ [4265, 8646],
+ ],
+ ],
+ [
+ [
+ [4018, 8630],
+ [4005, 8632],
+ [4008, 8645],
+ [4017, 8645],
+ [4018, 8630],
+ ],
+ ],
+ [
+ [
+ [4174, 8672],
+ [4190, 8672],
+ [4192, 8647],
+ [4157, 8669],
+ [4174, 8672],
+ ],
+ ],
+ [
+ [
+ [4280, 8687],
+ [4273, 8700],
+ [4282, 8716],
+ [4293, 8708],
+ [4280, 8687],
+ ],
+ ],
+ [
+ [
+ [4108, 8681],
+ [4067, 8660],
+ [4079, 8704],
+ [4131, 8772],
+ [4131, 8720],
+ [4108, 8681],
+ ],
+ ],
+ [
+ [
+ [4402, 8972],
+ [4427, 8934],
+ [4405, 8912],
+ [4411, 8885],
+ [4347, 8859],
+ [4324, 8875],
+ [4355, 8879],
+ [4340, 8913],
+ [4355, 8940],
+ [4400, 8943],
+ [4402, 8972],
+ ],
+ ],
+ [
+ [
+ [4594, 8976],
+ [4583, 8973],
+ [4580, 9002],
+ [4595, 9008],
+ [4594, 8976],
+ ],
+ ],
+ [
+ [
+ [5553, 9194],
+ [5561, 9190],
+ [5528, 9163],
+ [5532, 9212],
+ [5553, 9194],
+ ],
+ ],
+ [
+ [
+ [4490, 8977],
+ [4471, 8969],
+ [4472, 8994],
+ [4504, 9015],
+ [4490, 8977],
+ ],
+ ],
+ [
+ [
+ [4616, 9050],
+ [4630, 9045],
+ [4617, 9023],
+ [4596, 9036],
+ [4616, 9050],
+ ],
+ ],
+ [
+ [
+ [4434, 9036],
+ [4474, 9017],
+ [4462, 8968],
+ [4435, 8949],
+ [4388, 8992],
+ [4397, 9014],
+ [4434, 9036],
+ ],
+ ],
+ [
+ [
+ [4391, 9028],
+ [4409, 9033],
+ [4384, 9003],
+ [4379, 9041],
+ [4391, 9028],
+ ],
+ ],
+ [
+ [
+ [4606, 9062],
+ [4599, 9059],
+ [4596, 9083],
+ [4607, 9071],
+ [4606, 9062],
+ ],
+ ],
+ [
+ [
+ [4467, 9047],
+ [4447, 9050],
+ [4446, 9063],
+ [4454, 9064],
+ [4467, 9047],
+ ],
+ ],
+ [
+ [
+ [4592, 9071],
+ [4576, 9048],
+ [4553, 9062],
+ [4568, 9105],
+ [4594, 9096],
+ [4592, 9071],
+ ],
+ ],
+ [
+ [
+ [4425, 9091],
+ [4432, 9055],
+ [4420, 9048],
+ [4408, 9057],
+ [4425, 9091],
+ ],
+ ],
+ [
+ [
+ [4476, 9096],
+ [4491, 9074],
+ [4528, 9061],
+ [4496, 9041],
+ [4471, 9086],
+ [4476, 9096],
+ ],
+ ],
+ [
+ [
+ [4683, 9132],
+ [4676, 9137],
+ [4675, 9169],
+ [4684, 9161],
+ [4683, 9132],
+ ],
+ ],
+ [
+ [
+ [4774, 9185],
+ [4804, 9172],
+ [4813, 9150],
+ [4754, 9152],
+ [4753, 9181],
+ [4774, 9185],
+ ],
+ ],
+ [
+ [
+ [4843, 9269],
+ [4867, 9228],
+ [4848, 9178],
+ [4821, 9162],
+ [4791, 9208],
+ [4843, 9269],
+ ],
+ ],
+ [
+ [
+ [4869, 9303],
+ [4905, 9283],
+ [4873, 9246],
+ [4852, 9298],
+ [4869, 9303],
+ ],
+ ],
+ [
+ [
+ [4876, 9399],
+ [4883, 9370],
+ [4863, 9379],
+ [4864, 9402],
+ [4876, 9399],
+ ],
+ ],
+ [
+ [
+ [4940, 9438],
+ [4944, 9418],
+ [4926, 9424],
+ [4933, 9441],
+ [4940, 9438],
+ ],
+ ],
+ [
+ [
+ [5023, 9477],
+ [5051, 9449],
+ [5083, 9441],
+ [5024, 9405],
+ [4993, 9434],
+ [5023, 9477],
+ ],
+ ],
+ [
+ [
+ [1712, 9534],
+ [1697, 9493],
+ [1622, 9482],
+ [1587, 9453],
+ [1577, 9474],
+ [1647, 9502],
+ [1675, 9535],
+ [1712, 9534],
+ ],
+ ],
+ [
+ [
+ [2837, 6137],
+ [2847, 6128],
+ [2861, 6143],
+ [2864, 6225],
+ [2838, 6190],
+ [2804, 6173],
+ [2756, 6246],
+ [2808, 6216],
+ [2808, 6249],
+ [2774, 6257],
+ [2774, 6317],
+ [2832, 6307],
+ [2898, 6331],
+ [2951, 6306],
+ [2999, 6341],
+ [3049, 6311],
+ [3103, 6327],
+ [3106, 6341],
+ [3048, 6320],
+ [2986, 6367],
+ [2975, 6324],
+ [2939, 6346],
+ [2852, 6338],
+ [2825, 6323],
+ [2809, 6354],
+ [2778, 6366],
+ [2772, 6425],
+ [2831, 6461],
+ [2782, 6487],
+ [2782, 6518],
+ [2834, 6545],
+ [2839, 6563],
+ [2889, 6540],
+ [2997, 6528],
+ [2848, 6572],
+ [2810, 6563],
+ [2834, 6599],
+ [2804, 6641],
+ [2820, 6655],
+ [2854, 6608],
+ [2853, 6645],
+ [2921, 6644],
+ [2937, 6675],
+ [3031, 6713],
+ [2977, 6718],
+ [3009, 6739],
+ [2972, 6738],
+ [2981, 6761],
+ [3020, 6745],
+ [3043, 6771],
+ [3086, 6769],
+ [3142, 6735],
+ [3144, 6774],
+ [3186, 6789],
+ [3226, 6784],
+ [3219, 6802],
+ [3125, 6778],
+ [3116, 6795],
+ [3070, 6791],
+ [3065, 6852],
+ [3114, 6874],
+ [3143, 6843],
+ [3207, 6860],
+ [3223, 6899],
+ [3256, 6854],
+ [3254, 6831],
+ [3293, 6829],
+ [3234, 6900],
+ [3284, 6904],
+ [3282, 6916],
+ [3268, 6913],
+ [3248, 6934],
+ [3277, 6938],
+ [3279, 6933],
+ [3276, 6952],
+ [3314, 6967],
+ [3323, 6991],
+ [3380, 6970],
+ [3367, 7013],
+ [3438, 7053],
+ [3472, 6989],
+ [3455, 6960],
+ [3491, 6959],
+ [3490, 6992],
+ [3517, 7000],
+ [3583, 6986],
+ [3598, 7001],
+ [3566, 7025],
+ [3612, 7076],
+ [3668, 7101],
+ [3620, 7126],
+ [3671, 7165],
+ [3640, 7169],
+ [3602, 7143],
+ [3617, 7110],
+ [3596, 7079],
+ [3532, 7034],
+ [3467, 7015],
+ [3451, 7067],
+ [3481, 7094],
+ [3418, 7059],
+ [3418, 7091],
+ [3503, 7139],
+ [3469, 7145],
+ [3499, 7216],
+ [3555, 7265],
+ [3555, 7291],
+ [3591, 7298],
+ [3599, 7336],
+ [3626, 7290],
+ [3653, 7276],
+ [3670, 7328],
+ [3654, 7368],
+ [3710, 7397],
+ [3684, 7402],
+ [3717, 7441],
+ [3664, 7398],
+ [3633, 7401],
+ [3653, 7431],
+ [3707, 7452],
+ [3725, 7476],
+ [3747, 7468],
+ [3802, 7496],
+ [3840, 7559],
+ [3789, 7501],
+ [3768, 7537],
+ [3803, 7582],
+ [3793, 7633],
+ [3773, 7616],
+ [3765, 7646],
+ [3815, 7745],
+ [3843, 7777],
+ [3805, 7768],
+ [3823, 7796],
+ [3901, 7831],
+ [3954, 7833],
+ [3906, 7846],
+ [3842, 7816],
+ [3875, 7848],
+ [3836, 7863],
+ [3856, 7880],
+ [3862, 7946],
+ [3889, 7960],
+ [3894, 7999],
+ [3925, 8002],
+ [3898, 8039],
+ [3971, 8056],
+ [3984, 8110],
+ [4032, 8130],
+ [4047, 8109],
+ [4068, 8132],
+ [4100, 8120],
+ [4110, 8135],
+ [4064, 8142],
+ [4074, 8162],
+ [4019, 8130],
+ [4019, 8148],
+ [3979, 8135],
+ [4013, 8192],
+ [4034, 8179],
+ [4058, 8201],
+ [4020, 8211],
+ [4051, 8236],
+ [4106, 8209],
+ [4149, 8246],
+ [4108, 8224],
+ [4081, 8226],
+ [4071, 8262],
+ [4114, 8296],
+ [4088, 8311],
+ [4030, 8258],
+ [4023, 8284],
+ [4048, 8291],
+ [4021, 8312],
+ [4043, 8335],
+ [4077, 8336],
+ [4131, 8359],
+ [4149, 8378],
+ [4143, 8378],
+ [4136, 8369],
+ [4120, 8376],
+ [4106, 8379],
+ [4072, 8380],
+ [4095, 8411],
+ [4142, 8414],
+ [4143, 8449],
+ [4160, 8428],
+ [4157, 8385],
+ [4183, 8343],
+ [4187, 8376],
+ [4208, 8350],
+ [4209, 8385],
+ [4190, 8403],
+ [4197, 8447],
+ [4164, 8472],
+ [4214, 8458],
+ [4169, 8483],
+ [4220, 8504],
+ [4236, 8481],
+ [4313, 8520],
+ [4310, 8551],
+ [4258, 8516],
+ [4201, 8512],
+ [4206, 8574],
+ [4269, 8615],
+ [4315, 8661],
+ [4285, 8660],
+ [4307, 8721],
+ [4347, 8749],
+ [4335, 8783],
+ [4360, 8847],
+ [4398, 8795],
+ [4432, 8809],
+ [4379, 8837],
+ [4379, 8860],
+ [4415, 8874],
+ [4438, 8829],
+ [4476, 8818],
+ [4476, 8781],
+ [4494, 8783],
+ [4475, 8829],
+ [4454, 8825],
+ [4426, 8878],
+ [4434, 8933],
+ [4453, 8950],
+ [4503, 8963],
+ [4497, 8924],
+ [4518, 8910],
+ [4514, 8952],
+ [4528, 8955],
+ [4537, 9010],
+ [4565, 8998],
+ [4562, 8851],
+ [4539, 8804],
+ [4572, 8846],
+ [4587, 8905],
+ [4581, 8963],
+ [4644, 9005],
+ [4660, 9055],
+ [4723, 9003],
+ [4718, 9051],
+ [4704, 9071],
+ [4669, 9076],
+ [4632, 9106],
+ [4666, 9144],
+ [4703, 9099],
+ [4692, 9135],
+ [4736, 9150],
+ [4749, 9138],
+ [4812, 9136],
+ [4828, 9084],
+ [4863, 9066],
+ [4880, 9092],
+ [4839, 9106],
+ [4860, 9124],
+ [4842, 9148],
+ [4868, 9173],
+ [4858, 9194],
+ [4891, 9245],
+ [4932, 9245],
+ [4908, 9261],
+ [4923, 9308],
+ [4953, 9294],
+ [4939, 9329],
+ [4913, 9329],
+ [4917, 9362],
+ [4944, 9340],
+ [4936, 9401],
+ [4987, 9394],
+ [5005, 9357],
+ [5018, 9381],
+ [5061, 9402],
+ [5068, 9391],
+ [5007, 9267],
+ [5022, 9278],
+ [5032, 9211],
+ [5015, 9183],
+ [5022, 9138],
+ [5040, 9142],
+ [5067, 9216],
+ [5053, 9221],
+ [5092, 9324],
+ [5092, 9351],
+ [5111, 9405],
+ [5136, 9438],
+ [5151, 9400],
+ [5149, 9363],
+ [5123, 9338],
+ [5155, 9343],
+ [5159, 9257],
+ [5203, 9350],
+ [5195, 9385],
+ [5226, 9426],
+ [5181, 9438],
+ [5201, 9450],
+ [5186, 9473],
+ [5220, 9459],
+ [5211, 9501],
+ [5245, 9491],
+ [5272, 9513],
+ [5278, 9486],
+ [5314, 9491],
+ [5314, 9454],
+ [5298, 9425],
+ [5252, 9415],
+ [5293, 9408],
+ [5255, 9357],
+ [5312, 9402],
+ [5312, 9374],
+ [5284, 9325],
+ [5323, 9308],
+ [5342, 9231],
+ [5329, 9315],
+ [5333, 9413],
+ [5347, 9465],
+ [5372, 9475],
+ [5414, 9455],
+ [5416, 9427],
+ [5455, 9448],
+ [5454, 9414],
+ [5477, 9450],
+ [5582, 9386],
+ [5590, 9401],
+ [5620, 9356],
+ [5571, 9330],
+ [5547, 9266],
+ [5450, 9255],
+ [5399, 9256],
+ [5388, 9238],
+ [5508, 9223],
+ [5489, 9196],
+ [5519, 9206],
+ [5527, 9154],
+ [5560, 9161],
+ [5576, 9184],
+ [5564, 9210],
+ [5601, 9202],
+ [5638, 9209],
+ [5659, 9172],
+ [5664, 9128],
+ [5628, 9120],
+ [5599, 9138],
+ [5597, 9081],
+ [5581, 9050],
+ [5529, 9010],
+ [5532, 8960],
+ [5509, 8926],
+ [5490, 8946],
+ [5485, 8979],
+ [5515, 9065],
+ [5476, 9121],
+ [5392, 9139],
+ [5361, 9160],
+ [5320, 9205],
+ [5290, 9182],
+ [5252, 9135],
+ [5225, 9140],
+ [5190, 9125],
+ [5173, 9058],
+ [5157, 9048],
+ [5153, 8993],
+ [5162, 8948],
+ [5159, 8892],
+ [5178, 8840],
+ [5171, 8799],
+ [5127, 8767],
+ [5129, 8714],
+ [5106, 8686],
+ [5079, 8712],
+ [5041, 8717],
+ [4991, 8740],
+ [4976, 8706],
+ [4923, 8666],
+ [4900, 8683],
+ [4835, 8679],
+ [4823, 8711],
+ [4776, 8761],
+ [4725, 8830],
+ [4687, 8832],
+ [4662, 8795],
+ [4680, 8769],
+ [4669, 8753],
+ [4635, 8767],
+ [4625, 8745],
+ [4570, 8732],
+ [4600, 8702],
+ [4600, 8626],
+ [4575, 8586],
+ [4608, 8572],
+ [4579, 8529],
+ [4475, 8562],
+ [4432, 8556],
+ [4406, 8575],
+ [4379, 8560],
+ [4391, 8447],
+ [4367, 8387],
+ [4298, 8421],
+ [4246, 8357],
+ [4219, 8248],
+ [4188, 8230],
+ [4182, 8204],
+ [4224, 8141],
+ [4225, 8096],
+ [4186, 8043],
+ [4149, 7954],
+ [4123, 7920],
+ [4134, 7856],
+ [4086, 7816],
+ [4024, 7804],
+ [4042, 7721],
+ [4035, 7678],
+ [4036, 7564],
+ [4015, 7494],
+ [3940, 7341],
+ [4002, 7302],
+ [4012, 7233],
+ [3986, 7174],
+ [3894, 7193],
+ [3825, 7151],
+ [3762, 7043],
+ [3767, 7001],
+ [3741, 6952],
+ [3774, 6868],
+ [3759, 6845],
+ [3767, 6790],
+ [3760, 6746],
+ [3794, 6644],
+ [3777, 6495],
+ [3814, 6454],
+ [3841, 6445],
+ [3880, 6395],
+ [3857, 6297],
+ [3797, 6278],
+ [3816, 6212],
+ [3850, 6144],
+ [3836, 6080],
+ [3842, 6028],
+ [3790, 5963],
+ [3748, 5954],
+ [3756, 5924],
+ [3725, 5862],
+ [3747, 5773],
+ [3727, 5677],
+ [3695, 5669],
+ [3693, 5697],
+ [3682, 5728],
+ [3612, 5755],
+ [3600, 5745],
+ [3566, 5820],
+ [3574, 5870],
+ [3560, 5908],
+ [3573, 5946],
+ [3555, 5954],
+ [3549, 5910],
+ [3565, 5863],
+ [3549, 5847],
+ [3547, 5769],
+ [3531, 5776],
+ [3524, 5734],
+ [3471, 5685],
+ [3431, 5685],
+ [3368, 5649],
+ [3395, 5649],
+ [3249, 5484],
+ [3226, 5481],
+ [3190, 5441],
+ [3177, 5477],
+ [3158, 5436],
+ [3106, 5419],
+ [3017, 5426],
+ [2946, 5455],
+ [2973, 5484],
+ [2870, 5537],
+ [2865, 5560],
+ [2827, 5578],
+ [2797, 5647],
+ [2813, 5729],
+ [2839, 5695],
+ [2883, 5686],
+ [2862, 5740],
+ [2921, 5792],
+ [2897, 5830],
+ [2835, 5805],
+ [2825, 5838],
+ [2806, 5799],
+ [2767, 5869],
+ [2816, 5932],
+ [2853, 5912],
+ [2876, 5935],
+ [2841, 5964],
+ [2890, 5991],
+ [2919, 6065],
+ [2984, 6134],
+ [2928, 6105],
+ [2878, 6052],
+ [2875, 6012],
+ [2850, 6018],
+ [2855, 6053],
+ [2837, 6076],
+ [2815, 6056],
+ [2787, 6072],
+ [2784, 6124],
+ [2805, 6163],
+ [2820, 6150],
+ [2808, 6168],
+ [2862, 6203],
+ [2857, 6144],
+ [2837, 6137],
+ ],
+ ],
+ [
+ [
+ [3351, 7049],
+ [3352, 7056],
+ [3362, 7056],
+ [3368, 7050],
+ [3353, 7046],
+ [3369, 7031],
+ [3280, 6993],
+ [3251, 7003],
+ [3287, 7042],
+ [3342, 7057],
+ [3351, 7049],
+ ],
+ ],
+ [
+ [
+ [4021, 8662],
+ [4042, 8649],
+ [4054, 8642],
+ [4064, 8566],
+ [4036, 8541],
+ [4007, 8557],
+ [4044, 8579],
+ [4041, 8595],
+ [3986, 8552],
+ [3957, 8569],
+ [3990, 8595],
+ [4025, 8605],
+ [4021, 8662],
+ ],
+ ],
+ [
+ [
+ [4773, 9266],
+ [4803, 9297],
+ [4786, 9313],
+ [4816, 9315],
+ [4819, 9336],
+ [4816, 9285],
+ [4784, 9234],
+ [4713, 9205],
+ [4726, 9247],
+ [4694, 9238],
+ [4726, 9274],
+ [4773, 9266],
+ ],
+ ],
+ [
+ [
+ [4199, 8593],
+ [4192, 8544],
+ [4150, 8536],
+ [4140, 8493],
+ [4115, 8501],
+ [4104, 8462],
+ [4073, 8476],
+ [4050, 8462],
+ [4035, 8461],
+ [4061, 8507],
+ [4055, 8538],
+ [4084, 8562],
+ [4073, 8614],
+ [4091, 8659],
+ [4119, 8663],
+ [4119, 8609],
+ [4133, 8605],
+ [4118, 8557],
+ [4146, 8599],
+ [4158, 8649],
+ [4180, 8635],
+ [4199, 8593],
+ ],
+ ],
+ [
+ [
+ [4220, 8743],
+ [4241, 8781],
+ [4218, 8805],
+ [4266, 8805],
+ [4276, 8820],
+ [4250, 8833],
+ [4254, 8851],
+ [4291, 8832],
+ [4307, 8874],
+ [4333, 8847],
+ [4341, 8804],
+ [4323, 8792],
+ [4334, 8751],
+ [4284, 8737],
+ [4215, 8700],
+ [4238, 8726],
+ [4220, 8743],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'DE',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.47,
+ 'hc-middle-y': 0.53,
+ 'hc-key': 'de',
+ 'hc-a2': 'DE',
+ name: 'Germany',
+ labelrank: '2',
+ 'country-abbrev': 'Ger.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'DEU',
+ 'iso-a2': 'DE',
+ 'woe-id': '23424829',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [3422, 2394],
+ [3345, 2433],
+ [3297, 2473],
+ [3318, 2430],
+ [3264, 2425],
+ [3205, 2468],
+ [3164, 2431],
+ [3174, 2408],
+ [3006, 2412],
+ [2996, 2470],
+ [3016, 2533],
+ [3008, 2560],
+ [3045, 2634],
+ [3059, 2708],
+ [3116, 2766],
+ [3136, 2805],
+ [3085, 2829],
+ [3032, 2830],
+ [2984, 2871],
+ [2960, 2853],
+ [2879, 2886],
+ [2854, 2877],
+ [2819, 2954],
+ [2791, 2962],
+ [2825, 3058],
+ [2774, 3087],
+ [2759, 3155],
+ [2765, 3182],
+ [2809, 3209],
+ [2804, 3257],
+ [2779, 3261],
+ [2778, 3297],
+ [2746, 3338],
+ [2761, 3382],
+ [2737, 3419],
+ [2780, 3452],
+ [2766, 3475],
+ [2794, 3519],
+ [2779, 3594],
+ [2751, 3642],
+ [2788, 3666],
+ [2832, 3644],
+ [2910, 3678],
+ [2887, 3701],
+ [2952, 3754],
+ [2945, 3818],
+ [2897, 3827],
+ [2912, 3874],
+ [2959, 3874],
+ [2969, 3933],
+ [2988, 3965],
+ [2993, 4045],
+ [3013, 4070],
+ [2965, 4084],
+ [2978, 4144],
+ [3003, 4166],
+ [3128, 4178],
+ [3163, 4128],
+ [3144, 4114],
+ [3169, 4087],
+ [3189, 4115],
+ [3179, 4143],
+ [3231, 4125],
+ [3218, 4165],
+ [3235, 4214],
+ [3283, 4206],
+ [3343, 4213],
+ [3309, 4223],
+ [3280, 4265],
+ [3282, 4328],
+ [3250, 4334],
+ [3247, 4367],
+ [3286, 4374],
+ [3312, 4400],
+ [3259, 4467],
+ [3255, 4513],
+ [3282, 4516],
+ [3384, 4487],
+ [3384, 4487],
+ [3408, 4503],
+ [3483, 4447],
+ [3481, 4410],
+ [3608, 4345],
+ [3659, 4353],
+ [3658, 4307],
+ [3605, 4266],
+ [3628, 4244],
+ [3677, 4260],
+ [3725, 4229],
+ [3731, 4256],
+ [3770, 4302],
+ [3833, 4308],
+ [3872, 4347],
+ [3897, 4397],
+ [3961, 4368],
+ [3987, 4389],
+ [4002, 4345],
+ [4064, 4296],
+ [4103, 4313],
+ [4119, 4289],
+ [4122, 4320],
+ [4193, 4256],
+ [4187, 4247],
+ [4192, 4239],
+ [4137, 4226],
+ [4146, 4291],
+ [4124, 4280],
+ [4141, 4255],
+ [4127, 4235],
+ [4157, 4207],
+ [4206, 4188],
+ [4238, 4067],
+ [4231, 4002],
+ [4198, 3974],
+ [4196, 3943],
+ [4292, 3870],
+ [4276, 3824],
+ [4307, 3777],
+ [4322, 3727],
+ [4295, 3647],
+ [4322, 3611],
+ [4327, 3566],
+ [4367, 3549],
+ [4385, 3489],
+ [4354, 3378],
+ [4318, 3372],
+ [4293, 3419],
+ [4256, 3423],
+ [4269, 3379],
+ [4136, 3323],
+ [4109, 3288],
+ [4070, 3282],
+ [4030, 3255],
+ [3940, 3221],
+ [3900, 3155],
+ [3860, 3197],
+ [3894, 3121],
+ [3947, 3082],
+ [3923, 3034],
+ [4004, 2918],
+ [4043, 2910],
+ [4079, 2860],
+ [4139, 2811],
+ [4163, 2815],
+ [4205, 2765],
+ [4189, 2693],
+ [4151, 2710],
+ [4132, 2649],
+ [4062, 2613],
+ [4008, 2569],
+ [4059, 2492],
+ [4041, 2456],
+ [4066, 2454],
+ [4072, 2390],
+ [4021, 2406],
+ [4016, 2438],
+ [3965, 2426],
+ [3902, 2446],
+ [3900, 2416],
+ [3794, 2409],
+ [3724, 2353],
+ [3670, 2350],
+ [3632, 2385],
+ [3558, 2401],
+ [3566, 2362],
+ [3538, 2323],
+ [3467, 2387],
+ [3422, 2394],
+ ],
+ [
+ [3343, 4213],
+ [3357, 4210],
+ [3357, 4210],
+ [3357, 4210],
+ [3357, 4210],
+ [3403, 4138],
+ [3374, 4205],
+ [3357, 4210],
+ [3357, 4210],
+ [3357, 4210],
+ [3357, 4210],
+ [3354, 4215],
+ [3343, 4213],
+ ],
+ ],
+ [
+ [
+ [3731, 4262],
+ [3727, 4247],
+ [3711, 4250],
+ [3726, 4265],
+ [3731, 4262],
+ ],
+ ],
+ [
+ [
+ [3291, 4389],
+ [3278, 4399],
+ [3284, 4404],
+ [3304, 4405],
+ [3291, 4389],
+ ],
+ ],
+ [
+ [
+ [3688, 4393],
+ [3698, 4374],
+ [3646, 4389],
+ [3665, 4409],
+ [3688, 4393],
+ ],
+ ],
+ [
+ [
+ [4044, 4454],
+ [4086, 4437],
+ [4077, 4404],
+ [4111, 4369],
+ [4066, 4367],
+ [4028, 4339],
+ [4002, 4362],
+ [4024, 4377],
+ [4008, 4423],
+ [4044, 4454],
+ ],
+ ],
+ [
+ [
+ [3239, 4455],
+ [3210, 4462],
+ [3221, 4473],
+ [3236, 4473],
+ [3239, 4455],
+ ],
+ ],
+ [
+ [
+ [3210, 4514],
+ [3193, 4513],
+ [3208, 4554],
+ [3204, 4535],
+ [3210, 4514],
+ ],
+ ],
+ [[[3319, 2429], [3321, 2426], [3321, 2426], [3319, 2429]]],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'IE',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.61,
+ 'hc-middle-y': 0.6,
+ 'hc-key': 'ie',
+ 'hc-a2': 'IE',
+ name: 'Ireland',
+ labelrank: '3',
+ 'country-abbrev': 'Ire.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'IRL',
+ 'iso-a2': 'IE',
+ 'woe-id': '23424803',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [[[135, 4725], [124, 4687], [114, 4713], [82, 4730], [135, 4725]]],
+ [
+ [
+ [746, 4592],
+ [766, 4559],
+ [727, 4568],
+ [735, 4525],
+ [725, 4463],
+ [742, 4439],
+ [725, 4388],
+ [719, 4263],
+ [663, 4188],
+ [656, 4154],
+ [613, 4108],
+ [605, 4057],
+ [529, 4093],
+ [512, 4071],
+ [418, 4086],
+ [382, 4055],
+ [338, 4055],
+ [299, 4028],
+ [255, 4032],
+ [161, 3989],
+ [135, 4002],
+ [56, 3997],
+ [36, 4014],
+ [-44, 4006],
+ [16, 4039],
+ [29, 4070],
+ [-68, 4058],
+ [-72, 4082],
+ [1, 4110],
+ [-65, 4105],
+ [-114, 4157],
+ [-78, 4178],
+ [-14, 4185],
+ [-5, 4200],
+ [-102, 4220],
+ [-96, 4241],
+ [-38, 4256],
+ [9, 4227],
+ [26, 4264],
+ [10, 4280],
+ [61, 4287],
+ [79, 4310],
+ [137, 4294],
+ [196, 4300],
+ [197, 4332],
+ [162, 4301],
+ [95, 4324],
+ [45, 4325],
+ [112, 4353],
+ [151, 4397],
+ [130, 4404],
+ [181, 4452],
+ [237, 4436],
+ [245, 4471],
+ [130, 4499],
+ [143, 4528],
+ [92, 4528],
+ [114, 4544],
+ [74, 4553],
+ [62, 4608],
+ [121, 4610],
+ [123, 4652],
+ [182, 4646],
+ [190, 4674],
+ [130, 4679],
+ [153, 4697],
+ [142, 4783],
+ [178, 4806],
+ [276, 4765],
+ [279, 4723],
+ [304, 4760],
+ [397, 4731],
+ [372, 4762],
+ [448, 4791],
+ [481, 4819],
+ [390, 4835],
+ [376, 4862],
+ [424, 4888],
+ [462, 4881],
+ [447, 4915],
+ [493, 4969],
+ [574, 4962],
+ [602, 4975],
+ [614, 4903],
+ [622, 4975],
+ [655, 4972],
+ [651, 4996],
+ [711, 4932],
+ [652, 4902],
+ [622, 4890],
+ [581, 4822],
+ [532, 4831],
+ [538, 4795],
+ [459, 4770],
+ [496, 4684],
+ [576, 4637],
+ [639, 4710],
+ [662, 4684],
+ [668, 4641],
+ [690, 4626],
+ [685, 4588],
+ [746, 4592],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'UA',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.58,
+ 'hc-middle-y': 0.41,
+ 'hc-key': 'ua',
+ 'hc-a2': 'UA',
+ name: 'Ukraine',
+ labelrank: '3',
+ 'country-abbrev': 'Ukr.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'UKR',
+ 'iso-a2': 'UA',
+ 'woe-id': '23424976',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [7455, 2386],
+ [7493, 2450],
+ [7501, 2459],
+ [7470, 2406],
+ [7455, 2386],
+ ],
+ ],
+ [
+ [
+ [7966, 2676],
+ [7994, 2681],
+ [8031, 2696],
+ [8047, 2688],
+ [7966, 2676],
+ ],
+ ],
+ [
+ [
+ [7864, 2673],
+ [7779, 2665],
+ [7752, 2669],
+ [7846, 2675],
+ [7864, 2673],
+ ],
+ ],
+ [
+ [
+ [5798, 2837],
+ [5793, 2890],
+ [5819, 2928],
+ [5819, 2970],
+ [5841, 3040],
+ [5904, 3029],
+ [5867, 3073],
+ [5861, 3130],
+ [5837, 3173],
+ [5900, 3310],
+ [5994, 3455],
+ [6035, 3467],
+ [6051, 3510],
+ [6010, 3586],
+ [6038, 3595],
+ [5989, 3635],
+ [5976, 3670],
+ [5922, 3719],
+ [5907, 3769],
+ [5926, 3810],
+ [5970, 3801],
+ [6008, 3848],
+ [6025, 3898],
+ [6082, 3911],
+ [6159, 3947],
+ [6262, 3963],
+ [6378, 3967],
+ [6462, 3957],
+ [6519, 3969],
+ [6542, 3930],
+ [6616, 3948],
+ [6634, 3914],
+ [6639, 3956],
+ [6687, 3955],
+ [6704, 3988],
+ [6737, 3959],
+ [6780, 3978],
+ [6813, 3942],
+ [6825, 3992],
+ [6865, 4022],
+ [6918, 3960],
+ [6961, 4007],
+ [7005, 4004],
+ [7053, 4033],
+ [7103, 3994],
+ [7140, 3984],
+ [7149, 4017],
+ [7106, 4084],
+ [7114, 4151],
+ [7144, 4237],
+ [7196, 4244],
+ [7228, 4275],
+ [7278, 4286],
+ [7305, 4275],
+ [7359, 4306],
+ [7358, 4378],
+ [7461, 4389],
+ [7495, 4437],
+ [7544, 4450],
+ [7559, 4434],
+ [7598, 4468],
+ [7657, 4432],
+ [7685, 4375],
+ [7746, 4356],
+ [7755, 4326],
+ [7716, 4303],
+ [7775, 4229],
+ [7767, 4189],
+ [7843, 4209],
+ [7871, 4200],
+ [7929, 4227],
+ [7978, 4187],
+ [8043, 4111],
+ [8032, 4093],
+ [8058, 4058],
+ [8114, 4038],
+ [8131, 4069],
+ [8177, 4085],
+ [8220, 4059],
+ [8238, 4073],
+ [8284, 4059],
+ [8325, 4117],
+ [8405, 4175],
+ [8447, 4151],
+ [8492, 4103],
+ [8559, 4075],
+ [8583, 4097],
+ [8571, 4130],
+ [8675, 4127],
+ [8730, 4116],
+ [8766, 4149],
+ [8806, 4125],
+ [8846, 4141],
+ [8909, 4111],
+ [8957, 4148],
+ [8960, 4107],
+ [9002, 4059],
+ [8986, 3990],
+ [8948, 3965],
+ [8976, 3938],
+ [9015, 3941],
+ [8984, 3894],
+ [8990, 3846],
+ [9021, 3859],
+ [9090, 3791],
+ [9081, 3739],
+ [9100, 3657],
+ [8932, 3589],
+ [8934, 3537],
+ [8873, 3489],
+ [8881, 3393],
+ [8905, 3344],
+ [8790, 3293],
+ [8767, 3220],
+ [8748, 3228],
+ [8710, 3193],
+ [8685, 3138],
+ [8660, 3145],
+ [8577, 3079],
+ [8526, 3055],
+ [8457, 2941],
+ [8432, 2953],
+ [8409, 2894],
+ [8369, 2847],
+ [8405, 2786],
+ [8463, 2728],
+ [8547, 2667],
+ [8583, 2657],
+ [8621, 2681],
+ [8638, 2731],
+ [8673, 2711],
+ [8692, 2749],
+ [8781, 2772],
+ [8770, 2707],
+ [8791, 2664],
+ [8756, 2632],
+ [8717, 2630],
+ [8685, 2601],
+ [8631, 2618],
+ [8538, 2498],
+ [8491, 2476],
+ [8444, 2431],
+ [8433, 2370],
+ [8377, 2301],
+ [8328, 2290],
+ [8246, 2312],
+ [8278, 2340],
+ [8252, 2382],
+ [8259, 2429],
+ [8232, 2470],
+ [8195, 2485],
+ [8168, 2467],
+ [8079, 2498],
+ [8006, 2470],
+ [7998, 2503],
+ [8048, 2572],
+ [8195, 2713],
+ [8166, 2718],
+ [8144, 2762],
+ [8135, 2728],
+ [8065, 2759],
+ [8051, 2728],
+ [7988, 2706],
+ [7938, 2672],
+ [7887, 2672],
+ [7783, 2705],
+ [7811, 2745],
+ [7721, 2746],
+ [7876, 2771],
+ [7896, 2816],
+ [7798, 2795],
+ [7766, 2837],
+ [7766, 2785],
+ [7693, 2768],
+ [7604, 2727],
+ [7565, 2690],
+ [7579, 2673],
+ [7551, 2554],
+ [7503, 2462],
+ [7472, 2461],
+ [7470, 2423],
+ [7440, 2382],
+ [7406, 2436],
+ [7425, 2339],
+ [7451, 2343],
+ [7468, 2301],
+ [7457, 2266],
+ [7445, 2302],
+ [7373, 2312],
+ [7282, 2223],
+ [7186, 2225],
+ [7150, 2258],
+ [7203, 2283],
+ [7190, 2327],
+ [7228, 2391],
+ [7223, 2426],
+ [7259, 2448],
+ [7256, 2502],
+ [7235, 2519],
+ [7222, 2574],
+ [7258, 2609],
+ [7279, 2560],
+ [7319, 2610],
+ [7355, 2583],
+ [7369, 2620],
+ [7405, 2591],
+ [7448, 2613],
+ [7404, 2644],
+ [7384, 2725],
+ [7302, 2743],
+ [7303, 2774],
+ [7273, 2849],
+ [7248, 2829],
+ [7174, 2884],
+ [7170, 2984],
+ [7141, 3008],
+ [7112, 2987],
+ [7070, 3029],
+ [7015, 3026],
+ [6981, 3041],
+ [6926, 3031],
+ [6850, 3073],
+ [6803, 3068],
+ [6749, 3021],
+ [6685, 3015],
+ [6652, 2968],
+ [6596, 2941],
+ [6585, 2873],
+ [6419, 2808],
+ [6400, 2767],
+ [6360, 2740],
+ [6283, 2792],
+ [6223, 2767],
+ [6132, 2776],
+ [6052, 2762],
+ [6000, 2782],
+ [5962, 2732],
+ [5928, 2776],
+ [5901, 2766],
+ [5872, 2803],
+ [5848, 2799],
+ [5824, 2842],
+ [5798, 2837],
+ ],
+ [
+ [7457, 2615],
+ [7536, 2553],
+ [7547, 2572],
+ [7470, 2626],
+ [7457, 2615],
+ ],
+ [
+ [8226, 2751],
+ [8230, 2774],
+ [8290, 2767],
+ [8336, 2746],
+ [8341, 2716],
+ [8384, 2771],
+ [8375, 2732],
+ [8448, 2722],
+ [8511, 2641],
+ [8573, 2639],
+ [8552, 2659],
+ [8454, 2726],
+ [8380, 2809],
+ [8334, 2833],
+ [8341, 2785],
+ [8309, 2776],
+ [8319, 2817],
+ [8239, 2836],
+ [8226, 2787],
+ [8209, 2801],
+ [8147, 2787],
+ [8226, 2751],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'FI',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.58,
+ 'hc-middle-y': 0.72,
+ 'hc-key': 'fi',
+ 'hc-a2': 'FI',
+ name: 'Finland',
+ labelrank: '3',
+ 'country-abbrev': 'Fin.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'FIN',
+ 'iso-a2': 'FI',
+ 'woe-id': '23424812',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [4993, 6096],
+ [4976, 6089],
+ [4970, 6088],
+ [4977, 6101],
+ [4993, 6096],
+ ],
+ ],
+ [
+ [
+ [4992, 6109],
+ [5004, 6120],
+ [5016, 6114],
+ [5011, 6102],
+ [4992, 6109],
+ ],
+ ],
+ [
+ [
+ [4939, 6118],
+ [4961, 6095],
+ [4955, 6084],
+ [4930, 6101],
+ [4939, 6118],
+ ],
+ ],
+ [
+ [
+ [4959, 6128],
+ [4966, 6130],
+ [4964, 6111],
+ [4954, 6118],
+ [4959, 6128],
+ ],
+ ],
+ [
+ [
+ [4873, 6139],
+ [4861, 6117],
+ [4851, 6132],
+ [4858, 6155],
+ [4873, 6139],
+ ],
+ ],
+ [
+ [
+ [4902, 6194],
+ [4957, 6174],
+ [4947, 6141],
+ [4922, 6163],
+ [4931, 6115],
+ [4891, 6105],
+ [4867, 6158],
+ [4902, 6194],
+ ],
+ ],
+ [
+ [
+ [5277, 6163],
+ [5280, 6143],
+ [5272, 6140],
+ [5263, 6163],
+ [5277, 6163],
+ ],
+ ],
+ [
+ [
+ [5158, 6164],
+ [5156, 6153],
+ [5142, 6149],
+ [5147, 6172],
+ [5158, 6164],
+ ],
+ ],
+ [
+ [
+ [5191, 6183],
+ [5175, 6160],
+ [5167, 6161],
+ [5170, 6182],
+ [5191, 6183],
+ ],
+ ],
+ [
+ [
+ [5210, 6170],
+ [5199, 6182],
+ [5212, 6195],
+ [5210, 6182],
+ [5210, 6170],
+ ],
+ ],
+ [
+ [
+ [5722, 6296],
+ [5708, 6311],
+ [5710, 6317],
+ [5727, 6305],
+ [5722, 6296],
+ ],
+ ],
+ [
+ [
+ [5326, 6209],
+ [5314, 6149],
+ [5284, 6144],
+ [5272, 6198],
+ [5326, 6209],
+ ],
+ ],
+ [
+ [
+ [5243, 6212],
+ [5215, 6212],
+ [5220, 6227],
+ [5248, 6226],
+ [5243, 6212],
+ ],
+ ],
+ [
+ [
+ [5261, 6239],
+ [5254, 6226],
+ [5245, 6233],
+ [5256, 6244],
+ [5261, 6239],
+ ],
+ ],
+ [
+ [
+ [5222, 6241],
+ [5239, 6247],
+ [5240, 6243],
+ [5227, 6236],
+ [5222, 6241],
+ ],
+ ],
+ [
+ [
+ [5196, 6222],
+ [5169, 6235],
+ [5179, 6259],
+ [5200, 6229],
+ [5196, 6222],
+ ],
+ ],
+ [
+ [
+ [5114, 6275],
+ [5115, 6255],
+ [5107, 6259],
+ [5095, 6277],
+ [5114, 6275],
+ ],
+ ],
+ [
+ [
+ [5079, 6373],
+ [5065, 6389],
+ [5072, 6396],
+ [5084, 6386],
+ [5079, 6373],
+ ],
+ ],
+ [
+ [
+ [4937, 7061],
+ [4954, 7049],
+ [4977, 7043],
+ [4964, 7024],
+ [4937, 7061],
+ ],
+ ],
+ [
+ [
+ [5064, 7083],
+ [5069, 7094],
+ [5088, 7090],
+ [5076, 7072],
+ [5064, 7083],
+ ],
+ ],
+ [
+ [
+ [4972, 7074],
+ [4968, 7065],
+ [4954, 7075],
+ [4968, 7088],
+ [4972, 7074],
+ ],
+ ],
+ [
+ [
+ [5135, 7240],
+ [5138, 7228],
+ [5131, 7222],
+ [5121, 7233],
+ [5135, 7240],
+ ],
+ ],
+ [
+ [
+ [5322, 7664],
+ [5299, 7629],
+ [5286, 7647],
+ [5295, 7662],
+ [5322, 7664],
+ ],
+ ],
+ [
+ [
+ [5345, 6190],
+ [5331, 6207],
+ [5327, 6241],
+ [5281, 6204],
+ [5269, 6214],
+ [5287, 6256],
+ [5239, 6250],
+ [5173, 6282],
+ [5163, 6310],
+ [5142, 6267],
+ [5098, 6304],
+ [5093, 6379],
+ [5067, 6421],
+ [5089, 6423],
+ [5097, 6469],
+ [5073, 6573],
+ [5103, 6565],
+ [5073, 6596],
+ [5037, 6676],
+ [5017, 6687],
+ [5013, 6796],
+ [4984, 6806],
+ [4983, 6864],
+ [4964, 6884],
+ [4975, 6939],
+ [5002, 6971],
+ [5001, 7006],
+ [5028, 6998],
+ [4995, 7046],
+ [5044, 7070],
+ [5050, 7045],
+ [5104, 7098],
+ [5073, 7134],
+ [5102, 7148],
+ [5112, 7214],
+ [5146, 7203],
+ [5158, 7255],
+ [5202, 7289],
+ [5195, 7332],
+ [5255, 7403],
+ [5254, 7443],
+ [5289, 7495],
+ [5290, 7539],
+ [5322, 7603],
+ [5356, 7625],
+ [5385, 7602],
+ [5393, 7628],
+ [5369, 7651],
+ [5398, 7650],
+ [5360, 7689],
+ [5364, 7730],
+ [5355, 7797],
+ [5315, 7825],
+ [5266, 7823],
+ [5238, 7871],
+ [5223, 7856],
+ [5191, 7866],
+ [5161, 7928],
+ [5117, 7968],
+ [5095, 8033],
+ [5116, 8076],
+ [5106, 8131],
+ [5115, 8151],
+ [5047, 8242],
+ [5053, 8324],
+ [5012, 8336],
+ [5020, 8369],
+ [4997, 8455],
+ [5012, 8473],
+ [4945, 8521],
+ [4925, 8569],
+ [4893, 8592],
+ [4833, 8607],
+ [4808, 8603],
+ [4787, 8627],
+ [4732, 8654],
+ [4661, 8729],
+ [4625, 8745],
+ [4635, 8767],
+ [4669, 8753],
+ [4680, 8769],
+ [4662, 8795],
+ [4687, 8832],
+ [4725, 8830],
+ [4776, 8761],
+ [4823, 8711],
+ [4835, 8679],
+ [4900, 8683],
+ [4923, 8666],
+ [4976, 8706],
+ [4991, 8740],
+ [5041, 8717],
+ [5079, 8712],
+ [5106, 8686],
+ [5129, 8714],
+ [5127, 8767],
+ [5171, 8799],
+ [5178, 8840],
+ [5159, 8892],
+ [5162, 8948],
+ [5153, 8993],
+ [5157, 9048],
+ [5173, 9058],
+ [5190, 9125],
+ [5225, 9140],
+ [5252, 9135],
+ [5290, 9182],
+ [5320, 9205],
+ [5361, 9160],
+ [5392, 9139],
+ [5476, 9121],
+ [5515, 9065],
+ [5485, 8979],
+ [5490, 8946],
+ [5509, 8926],
+ [5467, 8875],
+ [5508, 8866],
+ [5495, 8771],
+ [5543, 8678],
+ [5621, 8661],
+ [5680, 8597],
+ [5730, 8568],
+ [5735, 8514],
+ [5708, 8441],
+ [5685, 8340],
+ [5696, 8295],
+ [5773, 8209],
+ [5793, 8170],
+ [5847, 8111],
+ [5891, 8036],
+ [5907, 7989],
+ [5863, 7968],
+ [5889, 7883],
+ [5880, 7852],
+ [5913, 7851],
+ [5920, 7819],
+ [5900, 7782],
+ [5939, 7733],
+ [5974, 7739],
+ [6000, 7703],
+ [5979, 7678],
+ [6002, 7628],
+ [6081, 7597],
+ [6094, 7531],
+ [6072, 7463],
+ [6049, 7441],
+ [6136, 7380],
+ [6185, 7369],
+ [6251, 7333],
+ [6261, 7312],
+ [6320, 7265],
+ [6313, 7140],
+ [6287, 7068],
+ [6260, 7026],
+ [6195, 6828],
+ [6171, 6788],
+ [6144, 6709],
+ [6100, 6652],
+ [6036, 6533],
+ [6004, 6463],
+ [5961, 6425],
+ [5915, 6445],
+ [5896, 6417],
+ [5808, 6365],
+ [5760, 6377],
+ [5762, 6313],
+ [5734, 6307],
+ [5718, 6339],
+ [5702, 6300],
+ [5659, 6290],
+ [5659, 6272],
+ [5580, 6239],
+ [5570, 6198],
+ [5551, 6217],
+ [5449, 6162],
+ [5424, 6157],
+ [5404, 6119],
+ [5356, 6102],
+ [5399, 6143],
+ [5377, 6144],
+ [5394, 6176],
+ [5356, 6176],
+ [5346, 6188],
+ [5344, 6176],
+ [5342, 6158],
+ [5333, 6178],
+ [5345, 6190],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'SE',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.52,
+ 'hc-middle-y': 0.34,
+ 'hc-key': 'se',
+ 'hc-a2': 'SE',
+ name: 'Sweden',
+ labelrank: '3',
+ 'country-abbrev': 'Swe.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'SWE',
+ 'iso-a2': 'SE',
+ 'woe-id': '23424954',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [4581, 5272],
+ [4583, 5238],
+ [4535, 5043],
+ [4529, 4978],
+ [4507, 4942],
+ [4497, 5032],
+ [4523, 5130],
+ [4538, 5137],
+ [4566, 5259],
+ [4581, 5272],
+ ],
+ ],
+ [
+ [
+ [4891, 5495],
+ [4910, 5490],
+ [4866, 5467],
+ [4871, 5487],
+ [4891, 5495],
+ ],
+ ],
+ [
+ [
+ [3744, 5428],
+ [3733, 5400],
+ [3712, 5397],
+ [3709, 5423],
+ [3744, 5428],
+ ],
+ ],
+ [
+ [
+ [3751, 5482],
+ [3754, 5447],
+ [3710, 5435],
+ [3696, 5456],
+ [3732, 5493],
+ [3751, 5482],
+ ],
+ ],
+ [
+ [
+ [4523, 5546],
+ [4520, 5537],
+ [4508, 5566],
+ [4529, 5555],
+ [4523, 5546],
+ ],
+ ],
+ [
+ [
+ [4726, 5760],
+ [4721, 5748],
+ [4707, 5740],
+ [4707, 5752],
+ [4726, 5760],
+ ],
+ ],
+ [
+ [
+ [4703, 5774],
+ [4693, 5756],
+ [4681, 5760],
+ [4687, 5772],
+ [4703, 5774],
+ ],
+ ],
+ [
+ [
+ [4628, 5737],
+ [4620, 5738],
+ [4617, 5776],
+ [4629, 5757],
+ [4628, 5737],
+ ],
+ ],
+ [
+ [
+ [4738, 5788],
+ [4732, 5773],
+ [4722, 5779],
+ [4737, 5805],
+ [4738, 5788],
+ ],
+ ],
+ [
+ [
+ [4740, 5856],
+ [4743, 5848],
+ [4741, 5838],
+ [4713, 5856],
+ [4740, 5856],
+ ],
+ ],
+ [
+ [
+ [4755, 5930],
+ [4740, 5895],
+ [4731, 5912],
+ [4741, 5929],
+ [4755, 5930],
+ ],
+ ],
+ [
+ [
+ [4779, 5953],
+ [4788, 5967],
+ [4786, 5948],
+ [4777, 5952],
+ [4779, 5953],
+ ],
+ ],
+ [
+ [
+ [4790, 6015],
+ [4791, 6010],
+ [4776, 6006],
+ [4783, 6029],
+ [4790, 6015],
+ ],
+ ],
+ [
+ [
+ [4688, 6191],
+ [4710, 6150],
+ [4685, 6166],
+ [4681, 6205],
+ [4688, 6191],
+ ],
+ ],
+ [
+ [
+ [4563, 6851],
+ [4572, 6851],
+ [4569, 6834],
+ [4556, 6831],
+ [4563, 6851],
+ ],
+ ],
+ [
+ [
+ [4889, 7192],
+ [4898, 7199],
+ [4898, 7178],
+ [4891, 7169],
+ [4889, 7192],
+ ],
+ ],
+ [
+ [
+ [4984, 7737],
+ [4981, 7732],
+ [4983, 7723],
+ [4969, 7739],
+ [4984, 7737],
+ ],
+ ],
+ [
+ [
+ [5014, 7760],
+ [5021, 7760],
+ [5017, 7746],
+ [5009, 7757],
+ [5014, 7760],
+ ],
+ ],
+ [
+ [
+ [4737, 5337],
+ [4781, 5427],
+ [4820, 5465],
+ [4829, 5444],
+ [4861, 5466],
+ [4876, 5446],
+ [4837, 5414],
+ [4844, 5332],
+ [4867, 5322],
+ [4830, 5286],
+ [4840, 5271],
+ [4792, 5232],
+ [4785, 5177],
+ [4761, 5169],
+ [4776, 5205],
+ [4743, 5265],
+ [4752, 5301],
+ [4737, 5337],
+ ],
+ ],
+ [
+ [
+ [4625, 8745],
+ [4661, 8729],
+ [4732, 8654],
+ [4787, 8627],
+ [4808, 8603],
+ [4833, 8607],
+ [4893, 8592],
+ [4925, 8569],
+ [4945, 8521],
+ [5012, 8473],
+ [4997, 8455],
+ [5020, 8369],
+ [5012, 8336],
+ [5053, 8324],
+ [5047, 8242],
+ [5115, 8151],
+ [5106, 8131],
+ [5116, 8076],
+ [5095, 8033],
+ [5117, 7968],
+ [5161, 7928],
+ [5191, 7866],
+ [5167, 7842],
+ [5135, 7857],
+ [5097, 7848],
+ [5074, 7811],
+ [5013, 7844],
+ [5017, 7815],
+ [4988, 7838],
+ [4970, 7786],
+ [4995, 7744],
+ [4913, 7774],
+ [4968, 7739],
+ [4929, 7731],
+ [4946, 7697],
+ [4891, 7682],
+ [4922, 7655],
+ [4919, 7613],
+ [4879, 7513],
+ [4863, 7506],
+ [4936, 7408],
+ [4882, 7303],
+ [4872, 7224],
+ [4838, 7205],
+ [4820, 7152],
+ [4789, 7151],
+ [4754, 7104],
+ [4749, 7076],
+ [4715, 7110],
+ [4726, 7067],
+ [4695, 7077],
+ [4698, 7043],
+ [4673, 6991],
+ [4656, 6999],
+ [4622, 6975],
+ [4596, 6913],
+ [4609, 6891],
+ [4560, 6858],
+ [4538, 6870],
+ [4560, 6814],
+ [4521, 6754],
+ [4482, 6780],
+ [4472, 6739],
+ [4501, 6688],
+ [4488, 6609],
+ [4501, 6542],
+ [4458, 6497],
+ [4477, 6471],
+ [4490, 6327],
+ [4518, 6257],
+ [4502, 6243],
+ [4558, 6233],
+ [4571, 6196],
+ [4609, 6224],
+ [4619, 6200],
+ [4713, 6127],
+ [4678, 6140],
+ [4708, 6106],
+ [4754, 6099],
+ [4781, 6040],
+ [4762, 6002],
+ [4798, 6008],
+ [4748, 5958],
+ [4717, 5912],
+ [4660, 5882],
+ [4732, 5872],
+ [4721, 5897],
+ [4770, 5878],
+ [4763, 5862],
+ [4703, 5859],
+ [4729, 5811],
+ [4676, 5782],
+ [4660, 5738],
+ [4637, 5738],
+ [4632, 5796],
+ [4611, 5784],
+ [4615, 5719],
+ [4522, 5639],
+ [4417, 5642],
+ [4446, 5623],
+ [4502, 5632],
+ [4528, 5600],
+ [4497, 5582],
+ [4512, 5550],
+ [4514, 5494],
+ [4490, 5435],
+ [4465, 5421],
+ [4515, 5366],
+ [4494, 5370],
+ [4518, 5303],
+ [4498, 5275],
+ [4491, 5215],
+ [4513, 5179],
+ [4452, 4992],
+ [4446, 4944],
+ [4421, 4893],
+ [4415, 4914],
+ [4373, 4924],
+ [4334, 4902],
+ [4274, 4907],
+ [4232, 4897],
+ [4247, 4864],
+ [4201, 4861],
+ [4161, 4798],
+ [4160, 4770],
+ [4191, 4714],
+ [4163, 4674],
+ [4114, 4683],
+ [4016, 4653],
+ [3962, 4674],
+ [3956, 4718],
+ [3976, 4746],
+ [3953, 4767],
+ [3880, 4916],
+ [3927, 4904],
+ [3897, 4958],
+ [3939, 4970],
+ [3934, 5026],
+ [3912, 5025],
+ [3889, 5074],
+ [3853, 5099],
+ [3798, 5256],
+ [3779, 5227],
+ [3775, 5302],
+ [3742, 5330],
+ [3738, 5364],
+ [3762, 5474],
+ [3756, 5503],
+ [3707, 5491],
+ [3692, 5535],
+ [3665, 5507],
+ [3672, 5577],
+ [3645, 5689],
+ [3660, 5725],
+ [3693, 5697],
+ [3695, 5669],
+ [3727, 5677],
+ [3747, 5773],
+ [3725, 5862],
+ [3756, 5924],
+ [3748, 5954],
+ [3790, 5963],
+ [3842, 6028],
+ [3836, 6080],
+ [3850, 6144],
+ [3816, 6212],
+ [3797, 6278],
+ [3857, 6297],
+ [3880, 6395],
+ [3841, 6445],
+ [3814, 6454],
+ [3777, 6495],
+ [3794, 6644],
+ [3760, 6746],
+ [3767, 6790],
+ [3759, 6845],
+ [3774, 6868],
+ [3741, 6952],
+ [3767, 7001],
+ [3762, 7043],
+ [3825, 7151],
+ [3894, 7193],
+ [3986, 7174],
+ [4012, 7233],
+ [4002, 7302],
+ [3940, 7341],
+ [4015, 7494],
+ [4036, 7564],
+ [4035, 7678],
+ [4042, 7721],
+ [4024, 7804],
+ [4086, 7816],
+ [4134, 7856],
+ [4123, 7920],
+ [4149, 7954],
+ [4186, 8043],
+ [4225, 8096],
+ [4224, 8141],
+ [4182, 8204],
+ [4188, 8230],
+ [4219, 8248],
+ [4246, 8357],
+ [4298, 8421],
+ [4367, 8387],
+ [4391, 8447],
+ [4379, 8560],
+ [4406, 8575],
+ [4432, 8556],
+ [4475, 8562],
+ [4579, 8529],
+ [4608, 8572],
+ [4575, 8586],
+ [4600, 8626],
+ [4600, 8702],
+ [4570, 8732],
+ [4625, 8745],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'RU',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.59,
+ 'hc-middle-y': 0.45,
+ 'hc-key': 'ru',
+ 'hc-a2': 'RU',
+ name: 'Russia',
+ labelrank: '2',
+ 'country-abbrev': 'Rus.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'RUS',
+ 'iso-a2': 'RU',
+ 'woe-id': '23424936',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [6161, 5739],
+ [6243, 5717],
+ [6237, 5759],
+ [6194, 5799],
+ [6149, 5776],
+ [6124, 5800],
+ [6149, 5876],
+ [6122, 5986],
+ [6102, 6021],
+ [6106, 6046],
+ [6108, 6072],
+ [6115, 6109],
+ [6124, 6119],
+ [6130, 6125],
+ [6119, 6126],
+ [6130, 6125],
+ [6143, 6139],
+ [6126, 6160],
+ [6111, 6169],
+ [6091, 6230],
+ [6097, 6261],
+ [6148, 6234],
+ [6154, 6294],
+ [6188, 6280],
+ [6221, 6303],
+ [6234, 6358],
+ [6388, 6364],
+ [6381, 6399],
+ [6342, 6396],
+ [6317, 6431],
+ [6199, 6407],
+ [6158, 6445],
+ [6127, 6446],
+ [6091, 6487],
+ [6133, 6467],
+ [6112, 6530],
+ [6078, 6516],
+ [6061, 6476],
+ [6004, 6463],
+ [6036, 6533],
+ [6100, 6652],
+ [6144, 6709],
+ [6171, 6788],
+ [6195, 6828],
+ [6260, 7026],
+ [6287, 7068],
+ [6313, 7140],
+ [6320, 7265],
+ [6261, 7312],
+ [6251, 7333],
+ [6185, 7369],
+ [6136, 7380],
+ [6049, 7441],
+ [6072, 7463],
+ [6094, 7531],
+ [6081, 7597],
+ [6002, 7628],
+ [5979, 7678],
+ [6000, 7703],
+ [5974, 7739],
+ [5939, 7733],
+ [5900, 7782],
+ [5920, 7819],
+ [5913, 7851],
+ [5880, 7852],
+ [5889, 7883],
+ [5863, 7968],
+ [5907, 7989],
+ [5891, 8036],
+ [5847, 8111],
+ [5793, 8170],
+ [5773, 8209],
+ [5696, 8295],
+ [5685, 8340],
+ [5708, 8441],
+ [5735, 8514],
+ [5730, 8568],
+ [5680, 8597],
+ [5621, 8661],
+ [5543, 8678],
+ [5495, 8771],
+ [5508, 8866],
+ [5467, 8875],
+ [5509, 8926],
+ [5532, 8960],
+ [5529, 9010],
+ [5581, 9050],
+ [5597, 9081],
+ [5599, 9138],
+ [5628, 9120],
+ [5664, 9128],
+ [5659, 9172],
+ [5638, 9209],
+ [5685, 9209],
+ [5710, 9193],
+ [5747, 9204],
+ [5726, 9251],
+ [5760, 9239],
+ [5736, 9277],
+ [5746, 9292],
+ [5820, 9258],
+ [5849, 9267],
+ [5881, 9239],
+ [5863, 9208],
+ [5786, 9206],
+ [5779, 9175],
+ [5814, 9193],
+ [5836, 9176],
+ [5895, 9185],
+ [5883, 9145],
+ [5922, 9186],
+ [5944, 9186],
+ [5940, 9121],
+ [5965, 9116],
+ [5964, 9160],
+ [6046, 9184],
+ [6077, 9175],
+ [6141, 9187],
+ [6142, 9207],
+ [6217, 9203],
+ [6264, 9182],
+ [6330, 9171],
+ [6416, 9139],
+ [6441, 9140],
+ [6559, 9072],
+ [6574, 9088],
+ [6704, 9042],
+ [6761, 9048],
+ [6812, 9033],
+ [6845, 8998],
+ [6855, 9022],
+ [6905, 9008],
+ [6932, 8944],
+ [6953, 8939],
+ [6971, 8891],
+ [6994, 8896],
+ [7027, 8838],
+ [7034, 8774],
+ [7005, 8628],
+ [6980, 8579],
+ [6916, 8501],
+ [6838, 8442],
+ [6764, 8422],
+ [6626, 8430],
+ [6572, 8412],
+ [6444, 8403],
+ [6359, 8434],
+ [6325, 8401],
+ [6282, 8430],
+ [6243, 8419],
+ [6195, 8445],
+ [6200, 8416],
+ [6106, 8461],
+ [6091, 8493],
+ [6038, 8497],
+ [6028, 8483],
+ [6073, 8455],
+ [6081, 8424],
+ [6125, 8392],
+ [6171, 8394],
+ [6159, 8338],
+ [6198, 8349],
+ [6253, 8343],
+ [6252, 8307],
+ [6375, 8282],
+ [6437, 8236],
+ [6462, 8184],
+ [6427, 8204],
+ [6459, 8148],
+ [6442, 8071],
+ [6519, 7996],
+ [6512, 7973],
+ [6552, 7949],
+ [6545, 7915],
+ [6581, 7883],
+ [6562, 7858],
+ [6666, 7811],
+ [6708, 7845],
+ [6743, 7813],
+ [6782, 7804],
+ [6801, 7775],
+ [6860, 7771],
+ [6919, 7785],
+ [6942, 7770],
+ [7012, 7842],
+ [7014, 7867],
+ [6972, 7910],
+ [6972, 7940],
+ [6922, 7956],
+ [6891, 7915],
+ [6859, 7919],
+ [6783, 7980],
+ [6758, 7982],
+ [6722, 8032],
+ [6761, 8060],
+ [6742, 8112],
+ [6761, 8128],
+ [6859, 8118],
+ [6917, 8089],
+ [7033, 8099],
+ [7129, 8080],
+ [7147, 8130],
+ [7199, 8115],
+ [7240, 8128],
+ [7178, 8223],
+ [7129, 8251],
+ [7045, 8320],
+ [7033, 8381],
+ [7069, 8437],
+ [7094, 8533],
+ [7145, 8580],
+ [7172, 8670],
+ [7178, 8751],
+ [7236, 8752],
+ [7235, 8729],
+ [7303, 8780],
+ [7377, 8744],
+ [7353, 8690],
+ [7399, 8745],
+ [7436, 8729],
+ [7476, 8684],
+ [7413, 8795],
+ [7402, 8910],
+ [7374, 8932],
+ [7369, 8976],
+ [7324, 9009],
+ [7263, 9008],
+ [7238, 9051],
+ [7210, 9191],
+ [7194, 9213],
+ [7159, 9318],
+ [7139, 9335],
+ [7019, 9368],
+ [7027, 9390],
+ [7093, 9384],
+ [7223, 9450],
+ [7299, 9457],
+ [7325, 9430],
+ [7402, 9407],
+ [7463, 9341],
+ [7403, 9282],
+ [7343, 9236],
+ [7359, 9198],
+ [7338, 9166],
+ [7360, 9106],
+ [7449, 9098],
+ [7514, 9042],
+ [7542, 9038],
+ [7591, 9079],
+ [7600, 9064],
+ [7667, 9142],
+ [7689, 9179],
+ [7655, 9230],
+ [7644, 9306],
+ [7615, 9329],
+ [7639, 9386],
+ [7683, 9428],
+ [7668, 9467],
+ [7697, 9484],
+ [7728, 9545],
+ [7765, 9652],
+ [7773, 9713],
+ [7794, 9714],
+ [7870, 9851],
+ [7872, 9851],
+ [7892, 9835],
+ [7898, 9795],
+ [7929, 9801],
+ [7936, 9851],
+ [8020, 9851],
+ [8021, 9833],
+ [8055, 9851],
+ [9732, 9851],
+ [9732, 2582],
+ [9688, 2568],
+ [9659, 2542],
+ [9662, 2497],
+ [9589, 2522],
+ [9379, 2615],
+ [9285, 2633],
+ [9196, 2619],
+ [9107, 2671],
+ [9032, 2637],
+ [8968, 2690],
+ [8806, 2713],
+ [8834, 2751],
+ [8827, 2795],
+ [8896, 2789],
+ [8901, 2761],
+ [8965, 2827],
+ [9012, 2828],
+ [8978, 2893],
+ [8970, 2849],
+ [8950, 2912],
+ [8981, 2954],
+ [8977, 3041],
+ [9017, 3090],
+ [9065, 3076],
+ [9077, 3107],
+ [9018, 3114],
+ [8967, 3143],
+ [8941, 3127],
+ [8863, 3194],
+ [8924, 3204],
+ [8970, 3283],
+ [9035, 3333],
+ [9069, 3391],
+ [9105, 3400],
+ [9077, 3467],
+ [9026, 3422],
+ [8905, 3344],
+ [8881, 3393],
+ [8873, 3489],
+ [8934, 3537],
+ [8932, 3589],
+ [9100, 3657],
+ [9081, 3739],
+ [9090, 3791],
+ [9021, 3859],
+ [8990, 3846],
+ [8984, 3894],
+ [9015, 3941],
+ [8976, 3938],
+ [8948, 3965],
+ [8986, 3990],
+ [9002, 4059],
+ [8960, 4107],
+ [8957, 4148],
+ [8909, 4111],
+ [8846, 4141],
+ [8806, 4125],
+ [8766, 4149],
+ [8730, 4116],
+ [8675, 4127],
+ [8571, 4130],
+ [8583, 4097],
+ [8559, 4075],
+ [8492, 4103],
+ [8447, 4151],
+ [8405, 4175],
+ [8325, 4117],
+ [8284, 4059],
+ [8238, 4073],
+ [8220, 4059],
+ [8177, 4085],
+ [8131, 4069],
+ [8114, 4038],
+ [8058, 4058],
+ [8032, 4093],
+ [8043, 4111],
+ [7978, 4187],
+ [7929, 4227],
+ [7871, 4200],
+ [7843, 4209],
+ [7767, 4189],
+ [7775, 4229],
+ [7716, 4303],
+ [7755, 4326],
+ [7746, 4356],
+ [7685, 4375],
+ [7657, 4432],
+ [7598, 4468],
+ [7559, 4434],
+ [7544, 4450],
+ [7495, 4437],
+ [7461, 4389],
+ [7358, 4378],
+ [7359, 4306],
+ [7305, 4275],
+ [7278, 4286],
+ [7227, 4334],
+ [7171, 4478],
+ [7114, 4511],
+ [7126, 4570],
+ [7180, 4585],
+ [7246, 4572],
+ [7290, 4620],
+ [7320, 4704],
+ [7266, 4719],
+ [7254, 4763],
+ [7183, 4772],
+ [7129, 4751],
+ [7118, 4826],
+ [7024, 4849],
+ [6987, 4904],
+ [6960, 4909],
+ [6966, 4950],
+ [6889, 4976],
+ [6884, 5017],
+ [6907, 5053],
+ [6852, 5115],
+ [6861, 5155],
+ [6840, 5206],
+ [6818, 5198],
+ [6759, 5240],
+ [6715, 5246],
+ [6663, 5224],
+ [6610, 5166],
+ [6584, 5189],
+ [6576, 5237],
+ [6517, 5241],
+ [6489, 5207],
+ [6449, 5241],
+ [6400, 5217],
+ [6371, 5238],
+ [6371, 5279],
+ [6340, 5347],
+ [6284, 5395],
+ [6262, 5427],
+ [6240, 5414],
+ [6248, 5510],
+ [6241, 5547],
+ [6181, 5574],
+ [6177, 5602],
+ [6151, 5595],
+ [6159, 5682],
+ [6194, 5705],
+ [6161, 5739],
+ ],
+ [
+ [5965, 9116],
+ [5965, 9113],
+ [5965, 9113],
+ [5965, 9113],
+ [5933, 9064],
+ [5966, 9090],
+ [5965, 9113],
+ [5965, 9113],
+ [5965, 9113],
+ [5967, 9115],
+ [5965, 9116],
+ ],
+ ],
+ [
+ [
+ [6120, 6424],
+ [6130, 6432],
+ [6151, 6421],
+ [6138, 6413],
+ [6120, 6424],
+ ],
+ ],
+ [
+ [
+ [6732, 7851],
+ [6707, 7864],
+ [6714, 7869],
+ [6731, 7863],
+ [6732, 7851],
+ ],
+ ],
+ [
+ [
+ [6624, 8069],
+ [6645, 8030],
+ [6594, 8040],
+ [6591, 8054],
+ [6624, 8069],
+ ],
+ ],
+ [
+ [
+ [6641, 8087],
+ [6652, 8081],
+ [6676, 8089],
+ [6657, 8072],
+ [6641, 8087],
+ ],
+ ],
+ [
+ [
+ [7211, 8811],
+ [7186, 8812],
+ [7174, 8829],
+ [7188, 8834],
+ [7211, 8811],
+ ],
+ ],
+ [
+ [
+ [7795, 9756],
+ [7773, 9714],
+ [7788, 9768],
+ [7821, 9784],
+ [7795, 9756],
+ ],
+ ],
+ [
+ [
+ [6041, 9195],
+ [6002, 9182],
+ [5996, 9191],
+ [6016, 9204],
+ [6041, 9195],
+ ],
+ ],
+ [
+ [
+ [5279, 4758],
+ [5218, 4659],
+ [5310, 4654],
+ [5333, 4669],
+ [5314, 4740],
+ [5326, 4758],
+ [5472, 4718],
+ [5549, 4740],
+ [5594, 4700],
+ [5595, 4571],
+ [5615, 4546],
+ [5604, 4540],
+ [5111, 4489],
+ [5209, 4577],
+ [5134, 4570],
+ [5118, 4544],
+ [5118, 4544],
+ [5118, 4544],
+ [5137, 4642],
+ [5191, 4649],
+ [5231, 4685],
+ [5268, 4759],
+ [5279, 4758],
+ [5279, 4758],
+ ],
+ ],
+ [
+ [
+ [5088, 4491],
+ [5086, 4492],
+ [5103, 4518],
+ [5103, 4518],
+ [5088, 4491],
+ ],
+ ],
+ [
+ [
+ [7186, 8155],
+ [7163, 8163],
+ [7191, 8181],
+ [7206, 8168],
+ [7216, 8145],
+ [7193, 8153],
+ [7230, 8134],
+ [7199, 8120],
+ [7145, 8136],
+ [7155, 8151],
+ [7186, 8155],
+ ],
+ ],
+ [
+ [
+ [5103, 4518],
+ [5118, 4544],
+ [5118, 4544],
+ [5118, 4544],
+ [5117, 4538],
+ [5103, 4518],
+ [5103, 4518],
+ ],
+ ],
+ [
+ [
+ [7399, 9803],
+ [7406, 9851],
+ [7585, 9851],
+ [7583, 9843],
+ [7591, 9782],
+ [7564, 9727],
+ [7510, 9677],
+ [7448, 9702],
+ [7399, 9803],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'GB',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.18,
+ 'hc-middle-y': 0.36,
+ 'hc-key': 'gb',
+ 'hc-a2': 'GB',
+ name: 'United Kingdom',
+ labelrank: '2',
+ 'country-abbrev': 'U.K.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'GBR',
+ 'iso-a2': 'GB',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [1201, 3080],
+ [1215, 3052],
+ [1176, 3062],
+ [1178, 3081],
+ [1201, 3080],
+ ],
+ ],
+ [
+ [
+ [1423, 3486],
+ [1461, 3456],
+ [1411, 3434],
+ [1382, 3463],
+ [1423, 3486],
+ ],
+ ],
+ [[[968, 4314], [973, 4313], [980, 4292], [962, 4305], [968, 4314]]],
+ [
+ [
+ [1043, 4292],
+ [1070, 4288],
+ [1010, 4250],
+ [979, 4298],
+ [986, 4332],
+ [1036, 4324],
+ [1043, 4292],
+ ],
+ ],
+ [
+ [
+ [1017, 4928],
+ [983, 4948],
+ [995, 5006],
+ [1025, 4996],
+ [1017, 4928],
+ ],
+ ],
+ [
+ [
+ [1052, 5006],
+ [1038, 5025],
+ [1033, 5063],
+ [1050, 5050],
+ [1052, 5006],
+ ],
+ ],
+ [
+ [
+ [885, 5073],
+ [888, 5028],
+ [851, 5030],
+ [842, 5065],
+ [811, 5045],
+ [830, 5088],
+ [886, 5105],
+ [885, 5073],
+ ],
+ ],
+ [[[898, 5153], [887, 5135], [874, 5134], [891, 5156], [898, 5153]]],
+ [[[961, 5153], [957, 5129], [905, 5060], [894, 5095], [961, 5153]]],
+ [[[803, 5273], [790, 5294], [831, 5297], [807, 5283], [803, 5273]]],
+ [
+ [
+ [946, 5292],
+ [953, 5262],
+ [986, 5245],
+ [991, 5217],
+ [878, 5206],
+ [922, 5254],
+ [894, 5284],
+ [935, 5305],
+ [946, 5292],
+ ],
+ ],
+ [[[862, 5305], [840, 5306], [862, 5321], [885, 5326], [862, 5305]]],
+ [[[763, 5445], [745, 5435], [733, 5442], [754, 5460], [763, 5445]]],
+ [[[935, 5412], [925, 5393], [906, 5415], [929, 5426], [935, 5412]]],
+ [[[796, 5561], [811, 5523], [775, 5475], [769, 5517], [796, 5561]]],
+ [[[811, 5581], [819, 5559], [805, 5558], [790, 5574], [811, 5581]]],
+ [[[838, 5625], [833, 5583], [780, 5621], [795, 5637], [838, 5625]]],
+ [
+ [
+ [1551, 5818],
+ [1538, 5794],
+ [1529, 5824],
+ [1542, 5826],
+ [1551, 5818],
+ ],
+ ],
+ [
+ [
+ [1501, 5850],
+ [1508, 5826],
+ [1487, 5818],
+ [1473, 5849],
+ [1501, 5850],
+ ],
+ ],
+ [
+ [
+ [1527, 5917],
+ [1583, 5845],
+ [1561, 5835],
+ [1544, 5861],
+ [1509, 5854],
+ [1490, 5887],
+ [1502, 5918],
+ [1527, 5917],
+ ],
+ ],
+ [
+ [
+ [1607, 5906],
+ [1619, 5887],
+ [1606, 5883],
+ [1600, 5908],
+ [1607, 5906],
+ ],
+ ],
+ [
+ [
+ [1548, 5925],
+ [1554, 5910],
+ [1540, 5912],
+ [1538, 5930],
+ [1548, 5925],
+ ],
+ ],
+ [
+ [
+ [1590, 5936],
+ [1590, 5908],
+ [1582, 5907],
+ [1578, 5924],
+ [1590, 5936],
+ ],
+ ],
+ [
+ [
+ [1647, 5941],
+ [1626, 5926],
+ [1614, 5932],
+ [1619, 5939],
+ [1647, 5941],
+ ],
+ ],
+ [
+ [
+ [1569, 5971],
+ [1575, 5943],
+ [1558, 5948],
+ [1549, 5970],
+ [1569, 5971],
+ ],
+ ],
+ [
+ [
+ [1936, 6281],
+ [1938, 6271],
+ [1924, 6271],
+ [1919, 6289],
+ [1936, 6281],
+ ],
+ ],
+ [
+ [
+ [1871, 6164],
+ [1837, 6082],
+ [1824, 6092],
+ [1855, 6186],
+ [1824, 6165],
+ [1802, 6213],
+ [1845, 6210],
+ [1841, 6261],
+ [1817, 6262],
+ [1863, 6293],
+ [1847, 6234],
+ [1892, 6239],
+ [1871, 6164],
+ ],
+ ],
+ [
+ [
+ [1904, 6323],
+ [1916, 6320],
+ [1900, 6254],
+ [1883, 6259],
+ [1904, 6323],
+ ],
+ ],
+ [
+ [
+ [1949, 6333],
+ [1938, 6303],
+ [1918, 6307],
+ [1936, 6350],
+ [1949, 6333],
+ ],
+ ],
+ [
+ [
+ [1131, 3142],
+ [1108, 3146],
+ [1111, 3154],
+ [1140, 3166],
+ [1131, 3142],
+ ],
+ ],
+ [
+ [
+ [1023, 4529],
+ [989, 4528],
+ [1011, 4570],
+ [1049, 4605],
+ [1082, 4612],
+ [1081, 4575],
+ [1023, 4529],
+ ],
+ ],
+ [[[-207, -551], [-210, -560], [-212, -550], [-207, -551]]],
+ [
+ [
+ [9095, -490],
+ [9069, -492],
+ [9034, -504],
+ [9046, -485],
+ [9095, -490],
+ ],
+ ],
+ [
+ [
+ [9270, -328],
+ [9261, -336],
+ [9242, -332],
+ [9236, -330],
+ [9242, -332],
+ [9237, -333],
+ [9224, -339],
+ [9224, -339],
+ [9223, -335],
+ [9219, -325],
+ [9213, -324],
+ [9213, -324],
+ [9233, -318],
+ [9262, -296],
+ [9262, -296],
+ [9261, -299],
+ [9240, -313],
+ [9270, -328],
+ ],
+ [
+ [9232, -327],
+ [9232, -324],
+ [9229, -325],
+ [9230, -327],
+ [9232, -327],
+ ],
+ ],
+ [
+ [
+ [1830, 3601],
+ [1855, 3592],
+ [1936, 3594],
+ [1915, 3521],
+ [1853, 3503],
+ [1840, 3469],
+ [1808, 3479],
+ [1725, 3455],
+ [1705, 3437],
+ [1628, 3471],
+ [1555, 3474],
+ [1508, 3461],
+ [1496, 3491],
+ [1420, 3494],
+ [1303, 3481],
+ [1290, 3456],
+ [1211, 3481],
+ [1203, 3467],
+ [1138, 3522],
+ [1064, 3519],
+ [1015, 3491],
+ [1009, 3452],
+ [970, 3405],
+ [944, 3406],
+ [885, 3466],
+ [776, 3474],
+ [761, 3448],
+ [714, 3448],
+ [705, 3410],
+ [674, 3387],
+ [633, 3446],
+ [587, 3433],
+ [597, 3463],
+ [644, 3463],
+ [728, 3514],
+ [738, 3539],
+ [784, 3551],
+ [840, 3602],
+ [856, 3659],
+ [889, 3647],
+ [934, 3701],
+ [1004, 3698],
+ [1069, 3668],
+ [1134, 3657],
+ [1142, 3691],
+ [1204, 3735],
+ [1257, 3796],
+ [1213, 3761],
+ [1161, 3761],
+ [1116, 3721],
+ [1053, 3733],
+ [1010, 3807],
+ [985, 3794],
+ [929, 3803],
+ [923, 3866],
+ [870, 3863],
+ [817, 3838],
+ [812, 3872],
+ [776, 3942],
+ [818, 3963],
+ [861, 3953],
+ [986, 4004],
+ [1026, 4074],
+ [1039, 4180],
+ [985, 4185],
+ [961, 4159],
+ [918, 4168],
+ [955, 4201],
+ [1001, 4221],
+ [1048, 4271],
+ [1194, 4279],
+ [1224, 4247],
+ [1220, 4281],
+ [1244, 4294],
+ [1243, 4326],
+ [1286, 4374],
+ [1263, 4388],
+ [1277, 4433],
+ [1324, 4481],
+ [1291, 4516],
+ [1249, 4491],
+ [1225, 4578],
+ [1205, 4617],
+ [1266, 4714],
+ [1298, 4729],
+ [1242, 4752],
+ [1231, 4719],
+ [1190, 4724],
+ [1165, 4701],
+ [1132, 4713],
+ [1101, 4753],
+ [1094, 4689],
+ [1025, 4757],
+ [1006, 4744],
+ [1011, 4691],
+ [980, 4761],
+ [1017, 4840],
+ [1101, 4927],
+ [1065, 4997],
+ [1080, 5048],
+ [1101, 5062],
+ [1100, 5109],
+ [1065, 5045],
+ [1039, 5069],
+ [1010, 5064],
+ [1006, 5031],
+ [970, 4998],
+ [950, 4923],
+ [903, 4915],
+ [958, 5036],
+ [958, 5101],
+ [1001, 5152],
+ [978, 5167],
+ [1013, 5213],
+ [1069, 5218],
+ [1025, 5232],
+ [1071, 5292],
+ [995, 5245],
+ [951, 5291],
+ [971, 5303],
+ [922, 5320],
+ [932, 5335],
+ [982, 5321],
+ [988, 5362],
+ [1054, 5463],
+ [1027, 5491],
+ [1037, 5556],
+ [1062, 5536],
+ [1051, 5587],
+ [1058, 5629],
+ [1093, 5647],
+ [1112, 5620],
+ [1131, 5643],
+ [1167, 5614],
+ [1127, 5685],
+ [1148, 5677],
+ [1145, 5729],
+ [1192, 5729],
+ [1185, 5753],
+ [1229, 5825],
+ [1273, 5794],
+ [1400, 5774],
+ [1464, 5786],
+ [1521, 5771],
+ [1498, 5737],
+ [1500, 5708],
+ [1474, 5681],
+ [1325, 5602],
+ [1324, 5566],
+ [1362, 5562],
+ [1274, 5481],
+ [1382, 5502],
+ [1401, 5520],
+ [1462, 5496],
+ [1488, 5501],
+ [1546, 5480],
+ [1637, 5469],
+ [1654, 5405],
+ [1613, 5366],
+ [1592, 5311],
+ [1554, 5245],
+ [1512, 5212],
+ [1491, 5171],
+ [1429, 5146],
+ [1432, 5118],
+ [1469, 5088],
+ [1431, 5067],
+ [1403, 5076],
+ [1362, 5041],
+ [1296, 5041],
+ [1370, 5007],
+ [1422, 5032],
+ [1448, 5025],
+ [1519, 4972],
+ [1558, 4882],
+ [1586, 4863],
+ [1584, 4742],
+ [1603, 4625],
+ [1628, 4576],
+ [1711, 4521],
+ [1730, 4457],
+ [1778, 4405],
+ [1750, 4383],
+ [1756, 4346],
+ [1794, 4266],
+ [1763, 4265],
+ [1724, 4304],
+ [1739, 4267],
+ [1791, 4218],
+ [1813, 4142],
+ [1806, 4103],
+ [1743, 4053],
+ [1803, 4017],
+ [1843, 4064],
+ [1911, 4056],
+ [1963, 4037],
+ [2022, 3985],
+ [2034, 3900],
+ [2002, 3841],
+ [1988, 3788],
+ [1913, 3738],
+ [1898, 3712],
+ [1872, 3728],
+ [1844, 3654],
+ [1767, 3648],
+ [1809, 3635],
+ [1781, 3619],
+ [1823, 3604],
+ [1821, 3625],
+ [1842, 3614],
+ [1848, 3599],
+ [1830, 3601],
+ ],
+ ],
+ [
+ [
+ [989, 5494],
+ [996, 5479],
+ [1046, 5460],
+ [1035, 5441],
+ [976, 5406],
+ [984, 5454],
+ [937, 5454],
+ [922, 5503],
+ [886, 5554],
+ [922, 5560],
+ [917, 5592],
+ [950, 5557],
+ [973, 5607],
+ [990, 5569],
+ [977, 5518],
+ [989, 5495],
+ [995, 5528],
+ [1011, 5545],
+ [999, 5516],
+ [989, 5494],
+ ],
+ ],
+ [
+ [
+ [902, 5785],
+ [935, 5767],
+ [936, 5789],
+ [1032, 5834],
+ [1037, 5783],
+ [993, 5753],
+ [989, 5703],
+ [954, 5676],
+ [875, 5640],
+ [862, 5666],
+ [909, 5691],
+ [872, 5716],
+ [902, 5785],
+ ],
+ ],
+ [
+ [
+ [652, 4902],
+ [679, 4888],
+ [706, 4926],
+ [738, 4913],
+ [787, 4923],
+ [845, 4898],
+ [875, 4749],
+ [902, 4722],
+ [907, 4664],
+ [888, 4631],
+ [888, 4687],
+ [855, 4642],
+ [877, 4622],
+ [822, 4614],
+ [780, 4566],
+ [746, 4592],
+ [685, 4588],
+ [690, 4626],
+ [668, 4641],
+ [662, 4684],
+ [639, 4710],
+ [576, 4637],
+ [496, 4684],
+ [459, 4770],
+ [538, 4795],
+ [532, 4831],
+ [581, 4822],
+ [622, 4890],
+ [652, 4902],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'CY',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.19,
+ 'hc-middle-y': 0.71,
+ 'hc-key': 'cy',
+ 'hc-a2': 'CY',
+ name: 'Cyprus',
+ labelrank: '5',
+ 'country-abbrev': 'Cyp.',
+ subregion: 'Western Asia',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'CYP',
+ 'iso-a2': 'CY',
+ 'woe-id': '-90',
+ continent: 'Asia',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [9232, -327],
+ [9230, -327],
+ [9229, -325],
+ [9232, -324],
+ [9232, -327],
+ ],
+ ],
+ [
+ [
+ [9291, -290],
+ [9318, -310],
+ [9270, -328],
+ [9240, -313],
+ [9261, -299],
+ [9270, -299],
+ [9291, -290],
+ ],
+ ],
+ [
+ [
+ [9224, -339],
+ [9216, -390],
+ [9095, -490],
+ [9046, -485],
+ [9034, -504],
+ [8942, -502],
+ [8881, -414],
+ [8923, -412],
+ [8944, -370],
+ [8955, -373],
+ [8960, -360],
+ [8968, -358],
+ [9008, -383],
+ [9083, -327],
+ [9139, -309],
+ [9162, -352],
+ [9223, -335],
+ [9224, -339],
+ [9224, -339],
+ ],
+ ],
+ [
+ [
+ [9236, -330],
+ [9239, -329],
+ [9245, -331],
+ [9242, -332],
+ [9236, -330],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'PT',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.48,
+ 'hc-middle-y': 0.36,
+ 'hc-key': 'pt',
+ 'hc-a2': 'PT',
+ name: 'Portugal',
+ labelrank: '2',
+ 'country-abbrev': 'Port.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'PRT',
+ 'iso-a2': 'PT',
+ 'woe-id': '23424925',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [-896, 403],
+ [-979, 424],
+ [-941, 512],
+ [-901, 573],
+ [-905, 609],
+ [-867, 611],
+ [-810, 675],
+ [-731, 789],
+ [-719, 832],
+ [-619, 1023],
+ [-609, 1164],
+ [-611, 1246],
+ [-566, 1304],
+ [-534, 1320],
+ [-441, 1327],
+ [-423, 1288],
+ [-463, 1252],
+ [-457, 1228],
+ [-354, 1228],
+ [-338, 1204],
+ [-257, 1193],
+ [-226, 1223],
+ [-107, 1176],
+ [-122, 1124],
+ [-54, 1057],
+ [-134, 993],
+ [-168, 993],
+ [-220, 941],
+ [-249, 936],
+ [-238, 881],
+ [-270, 768],
+ [-262, 740],
+ [-328, 703],
+ [-304, 645],
+ [-361, 562],
+ [-476, 588],
+ [-438, 511],
+ [-449, 478],
+ [-430, 404],
+ [-393, 365],
+ [-423, 324],
+ [-479, 302],
+ [-520, 224],
+ [-481, 131],
+ [-444, 129],
+ [-473, 83],
+ [-533, 84],
+ [-559, 40],
+ [-621, -20],
+ [-621, -134],
+ [-720, -162],
+ [-761, -157],
+ [-805, -120],
+ [-906, -83],
+ [-999, -89],
+ [-917, 33],
+ [-889, 160],
+ [-903, 172],
+ [-858, 231],
+ [-850, 282],
+ [-874, 333],
+ [-937, 322],
+ [-929, 397],
+ [-896, 403],
+ ],
+ [
+ [-896, 403],
+ [-894, 402],
+ [-893, 403],
+ [-893, 403],
+ [-893, 404],
+ [-850, 411],
+ [-856, 453],
+ [-893, 404],
+ [-893, 404],
+ [-893, 404],
+ [-896, 403],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'GR',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.21,
+ 'hc-middle-y': 0.4,
+ 'hc-key': 'gr',
+ 'hc-a2': 'GR',
+ name: 'Greece',
+ labelrank: '3',
+ 'country-abbrev': 'Greece',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'GRC',
+ 'iso-a2': 'GR',
+ 'woe-id': '23424833',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [7604, -670],
+ [7608, -677],
+ [7582, -697],
+ [7580, -676],
+ [7604, -670],
+ ],
+ ],
+ [
+ [
+ [7631, -545],
+ [7629, -606],
+ [7642, -663],
+ [7609, -618],
+ [7631, -545],
+ ],
+ ],
+ [
+ [
+ [6616, -642],
+ [6582, -647],
+ [6584, -593],
+ [6626, -630],
+ [6616, -642],
+ ],
+ ],
+ [
+ [
+ [7823, -305],
+ [7805, -407],
+ [7756, -489],
+ [7713, -417],
+ [7751, -352],
+ [7823, -305],
+ ],
+ ],
+ [
+ [
+ [7182, -475],
+ [7175, -489],
+ [7154, -487],
+ [7169, -474],
+ [7182, -475],
+ ],
+ ],
+ [
+ [
+ [7617, -345],
+ [7625, -359],
+ [7626, -370],
+ [7604, -352],
+ [7617, -345],
+ ],
+ ],
+ [
+ [
+ [7396, -360],
+ [7364, -392],
+ [7351, -370],
+ [7370, -374],
+ [7396, -360],
+ ],
+ ],
+ [
+ [
+ [7712, -275],
+ [7723, -272],
+ [7731, -295],
+ [7701, -292],
+ [7712, -275],
+ ],
+ ],
+ [
+ [
+ [6934, -404],
+ [6941, -431],
+ [6892, -453],
+ [6893, -421],
+ [6934, -404],
+ ],
+ ],
+ [
+ [
+ [7139, -377],
+ [7138, -400],
+ [7105, -385],
+ [7113, -363],
+ [7139, -377],
+ ],
+ ],
+ [
+ [
+ [7551, -257],
+ [7495, -300],
+ [7519, -256],
+ [7566, -224],
+ [7551, -257],
+ ],
+ ],
+ [
+ [
+ [7286, -293],
+ [7247, -333],
+ [7238, -318],
+ [7267, -285],
+ [7286, -293],
+ ],
+ ],
+ [
+ [
+ [6946, -321],
+ [6976, -342],
+ [6967, -360],
+ [6944, -328],
+ [6946, -321],
+ ],
+ ],
+ [
+ [
+ [7485, -202],
+ [7503, -208],
+ [7503, -228],
+ [7477, -234],
+ [7485, -202],
+ ],
+ ],
+ [
+ [
+ [7046, -318],
+ [7057, -279],
+ [7081, -269],
+ [7077, -311],
+ [7046, -318],
+ ],
+ ],
+ [
+ [
+ [7438, -167],
+ [7460, -189],
+ [7449, -192],
+ [7429, -173],
+ [7438, -167],
+ ],
+ ],
+ [
+ [
+ [7161, -259],
+ [7139, -319],
+ [7104, -279],
+ [7140, -233],
+ [7161, -259],
+ ],
+ ],
+ [
+ [
+ [6896, -283],
+ [6906, -283],
+ [6912, -303],
+ [6889, -307],
+ [6896, -283],
+ ],
+ ],
+ [
+ [
+ [6670, -285],
+ [6660, -295],
+ [6632, -304],
+ [6650, -286],
+ [6670, -285],
+ ],
+ ],
+ [
+ [
+ [6880, -220],
+ [6863, -259],
+ [6857, -221],
+ [6868, -204],
+ [6880, -220],
+ ],
+ ],
+ [
+ [
+ [7078, -153],
+ [7107, -159],
+ [7096, -177],
+ [7075, -183],
+ [7078, -153],
+ ],
+ ],
+ [
+ [
+ [6996, -203],
+ [6979, -218],
+ [6972, -209],
+ [6981, -174],
+ [6996, -203],
+ ],
+ ],
+ [
+ [
+ [7008, -125],
+ [7047, -125],
+ [7046, -153],
+ [6989, -133],
+ [7008, -125],
+ ],
+ ],
+ [
+ [
+ [6842, -149],
+ [6851, -166],
+ [6828, -198],
+ [6824, -172],
+ [6842, -149],
+ ],
+ ],
+ [[[7294, -67], [7241, -114], [7221, -109], [7237, -79], [7294, -67]]],
+ [
+ [
+ [6639, -190],
+ [6630, -189],
+ [6618, -168],
+ [6650, -162],
+ [6639, -190],
+ ],
+ ],
+ [
+ [
+ [7431, 3],
+ [7459, -6],
+ [7400, -38],
+ [7346, -22],
+ [7402, 12],
+ [7431, 3],
+ ],
+ ],
+ [
+ [
+ [5994, -248],
+ [6054, -276],
+ [6018, -305],
+ [5965, -262],
+ [5994, -248],
+ ],
+ ],
+ [[[6938, -60], [6962, -58], [6965, -113], [6899, -63], [6938, -60]]],
+ [
+ [
+ [6631, -102],
+ [6637, -116],
+ [6621, -132],
+ [6605, -127],
+ [6631, -102],
+ ],
+ ],
+ [
+ [
+ [5926, -73],
+ [5995, -185],
+ [5927, -181],
+ [5891, -111],
+ [5913, -123],
+ [5926, -73],
+ ],
+ ],
+ [
+ [
+ [7173, 194],
+ [7198, 187],
+ [7214, 118],
+ [7188, 68],
+ [7149, 90],
+ [7172, 121],
+ [7124, 182],
+ [7173, 194],
+ ],
+ ],
+ [[[5956, -15], [5922, -30], [5914, -10], [5935, 41], [5956, -15]]],
+ [[[6817, 208], [6846, 190], [6813, 180], [6793, 232], [6817, 208]]],
+ [[[6561, 245], [6551, 230], [6536, 231], [6549, 254], [6561, 245]]],
+ [[[6579, 258], [6627, 240], [6618, 227], [6600, 227], [6579, 258]]],
+ [[[6648, 257], [6642, 262], [6651, 293], [6659, 292], [6648, 257]]],
+ [
+ [
+ [7202, 424],
+ [7264, 345],
+ [7228, 323],
+ [7167, 325],
+ [7082, 354],
+ [7082, 378],
+ [7183, 438],
+ [7202, 424],
+ ],
+ ],
+ [[[5724, 291], [5711, 248], [5738, 200], [5658, 269], [5724, 291]]],
+ [
+ [
+ [6940, 577],
+ [6935, 505],
+ [6895, 528],
+ [6865, 505],
+ [6853, 550],
+ [6911, 552],
+ [6940, 577],
+ ],
+ ],
+ [[[6963, 721], [6969, 703], [6950, 692], [6917, 710], [6963, 721]]],
+ [[[6760, 718], [6700, 711], [6718, 764], [6750, 754], [6760, 718]]],
+ [
+ [
+ [5744, 264],
+ [5783, 255],
+ [5827, 318],
+ [5801, 361],
+ [5871, 401],
+ [5896, 516],
+ [5934, 546],
+ [5929, 587],
+ [5950, 612],
+ [5928, 589],
+ [5909, 607],
+ [5912, 616],
+ [5923, 633],
+ [5943, 639],
+ [5999, 661],
+ [6044, 658],
+ [6105, 737],
+ [6162, 765],
+ [6216, 761],
+ [6280, 788],
+ [6278, 832],
+ [6313, 844],
+ [6357, 845],
+ [6390, 877],
+ [6462, 882],
+ [6547, 945],
+ [6645, 975],
+ [6671, 941],
+ [6714, 926],
+ [6735, 946],
+ [6831, 918],
+ [6884, 953],
+ [6956, 965],
+ [7004, 992],
+ [7003, 1040],
+ [6967, 1083],
+ [7026, 1104],
+ [7089, 1088],
+ [7113, 1024],
+ [7056, 973],
+ [7081, 892],
+ [7028, 811],
+ [7001, 837],
+ [6909, 825],
+ [6792, 840],
+ [6750, 785],
+ [6693, 803],
+ [6656, 791],
+ [6651, 758],
+ [6606, 719],
+ [6537, 721],
+ [6516, 691],
+ [6698, 573],
+ [6683, 554],
+ [6645, 591],
+ [6585, 607],
+ [6539, 585],
+ [6563, 553],
+ [6615, 538],
+ [6624, 490],
+ [6572, 514],
+ [6539, 553],
+ [6475, 558],
+ [6465, 536],
+ [6562, 466],
+ [6484, 465],
+ [6455, 542],
+ [6391, 557],
+ [6335, 600],
+ [6368, 621],
+ [6348, 644],
+ [6284, 580],
+ [6307, 555],
+ [6293, 492],
+ [6303, 460],
+ [6382, 390],
+ [6406, 343],
+ [6451, 320],
+ [6522, 239],
+ [6421, 274],
+ [6413, 212],
+ [6469, 187],
+ [6414, 128],
+ [6373, 132],
+ [6413, 100],
+ [6482, 95],
+ [6494, 74],
+ [6546, 82],
+ [6561, 42],
+ [6600, 46],
+ [6643, 14],
+ [6710, 7],
+ [6747, -23],
+ [6728, -40],
+ [6771, -143],
+ [6765, -175],
+ [6694, -139],
+ [6639, -80],
+ [6561, -117],
+ [6518, -163],
+ [6560, -167],
+ [6567, -224],
+ [6600, -217],
+ [6659, -253],
+ [6559, -304],
+ [6568, -274],
+ [6468, -264],
+ [6483, -304],
+ [6544, -376],
+ [6599, -470],
+ [6582, -493],
+ [6638, -568],
+ [6536, -516],
+ [6516, -478],
+ [6473, -492],
+ [6460, -548],
+ [6474, -588],
+ [6434, -581],
+ [6425, -525],
+ [6361, -440],
+ [6312, -460],
+ [6310, -537],
+ [6267, -521],
+ [6258, -476],
+ [6217, -423],
+ [6238, -381],
+ [6193, -305],
+ [6081, -240],
+ [6125, -148],
+ [6122, -119],
+ [6178, -130],
+ [6208, -82],
+ [6250, -63],
+ [6320, -96],
+ [6430, -113],
+ [6480, -142],
+ [6472, -115],
+ [6552, -79],
+ [6528, -63],
+ [6420, -38],
+ [6387, -49],
+ [6346, -11],
+ [6348, -44],
+ [6254, -40],
+ [6153, -91],
+ [6112, -64],
+ [6067, -102],
+ [6041, -37],
+ [5962, 66],
+ [6037, 101],
+ [5958, 121],
+ [5942, 72],
+ [5926, 106],
+ [5844, 158],
+ [5781, 221],
+ [5788, 250],
+ [5744, 264],
+ ],
+ ],
+ [[[5953, -97], [5966, -114], [5953, -98], [5953, -97], [5953, -97]]],
+ [
+ [
+ [6631, 30],
+ [6624, 62],
+ [6509, 131],
+ [6453, 139],
+ [6520, 197],
+ [6560, 161],
+ [6601, 132],
+ [6666, 117],
+ [6715, 125],
+ [6761, 87],
+ [6757, 52],
+ [6808, -13],
+ [6863, -2],
+ [6866, -56],
+ [6825, -66],
+ [6725, 22],
+ [6724, 42],
+ [6631, 30],
+ ],
+ ],
+ [
+ [
+ [7250, -790],
+ [7315, -764],
+ [7313, -812],
+ [7342, -826],
+ [7437, -752],
+ [7449, -825],
+ [7297, -867],
+ [7180, -916],
+ [7094, -936],
+ [7076, -889],
+ [6997, -876],
+ [6845, -893],
+ [6778, -888],
+ [6780, -790],
+ [6813, -814],
+ [6809, -762],
+ [6836, -803],
+ [6921, -771],
+ [6955, -832],
+ [7059, -791],
+ [7119, -780],
+ [7144, -796],
+ [7250, -790],
+ ],
+ ],
+ [[[5953, -97], [5936, -73], [5949, -66], [5953, -97], [5953, -97]]],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'LT',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.6,
+ 'hc-middle-y': 0.49,
+ 'hc-key': 'lt',
+ 'hc-a2': 'LT',
+ name: 'Lithuania',
+ labelrank: '5',
+ 'country-abbrev': 'Lith.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'LTU',
+ 'iso-a2': 'LT',
+ 'woe-id': '23424875',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [5326, 4758],
+ [5306, 4834],
+ [5272, 4895],
+ [5254, 4987],
+ [5276, 4994],
+ [5291, 5038],
+ [5404, 5112],
+ [5500, 5110],
+ [5529, 5132],
+ [5570, 5111],
+ [5594, 5133],
+ [5661, 5141],
+ [5729, 5127],
+ [5783, 5137],
+ [5842, 5202],
+ [5891, 5137],
+ [5981, 5144],
+ [5992, 5129],
+ [6081, 5080],
+ [6104, 5054],
+ [6159, 5044],
+ [6157, 4946],
+ [6218, 4942],
+ [6193, 4890],
+ [6147, 4887],
+ [6131, 4831],
+ [6080, 4791],
+ [6092, 4704],
+ [6071, 4634],
+ [6100, 4633],
+ [6118, 4585],
+ [6086, 4576],
+ [6065, 4618],
+ [6026, 4598],
+ [6009, 4557],
+ [5972, 4554],
+ [5971, 4502],
+ [5952, 4504],
+ [5908, 4464],
+ [5875, 4477],
+ [5784, 4444],
+ [5756, 4450],
+ [5735, 4513],
+ [5628, 4561],
+ [5615, 4546],
+ [5595, 4571],
+ [5594, 4700],
+ [5549, 4740],
+ [5472, 4718],
+ [5326, 4758],
+ ],
+ ],
+ [
+ [
+ [5268, 4759],
+ [5285, 4824],
+ [5279, 4758],
+ [5279, 4758],
+ [5268, 4759],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'SI',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.38,
+ 'hc-middle-y': 0.62,
+ 'hc-key': 'si',
+ 'hc-a2': 'SI',
+ name: 'Slovenia',
+ labelrank: '6',
+ 'country-abbrev': 'Slo.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'SVN',
+ 'iso-a2': 'SI',
+ 'woe-id': '23424945',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [4209, 1816],
+ [4208, 1830],
+ [4232, 1848],
+ [4269, 1861],
+ [4203, 1909],
+ [4209, 1955],
+ [4176, 1965],
+ [4209, 2017],
+ [4152, 2046],
+ [4216, 2116],
+ [4358, 2100],
+ [4386, 2084],
+ [4444, 2153],
+ [4485, 2170],
+ [4565, 2165],
+ [4597, 2198],
+ [4673, 2197],
+ [4685, 2247],
+ [4720, 2250],
+ [4777, 2150],
+ [4722, 2143],
+ [4734, 2110],
+ [4614, 2053],
+ [4602, 2023],
+ [4625, 2002],
+ [4624, 1943],
+ [4581, 1934],
+ [4542, 1900],
+ [4570, 1837],
+ [4525, 1818],
+ [4428, 1842],
+ [4403, 1876],
+ [4369, 1822],
+ [4286, 1828],
+ [4271, 1801],
+ [4209, 1816],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'BA',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.49,
+ 'hc-middle-y': 0.42,
+ 'hc-key': 'ba',
+ 'hc-a2': 'BA',
+ name: 'Bosnia and Herzegovina',
+ labelrank: '5',
+ 'country-abbrev': 'B.H.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'BIH',
+ 'iso-a2': 'BA',
+ 'woe-id': '23424761',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [5115, 1130],
+ [5093, 1141],
+ [5098, 1143],
+ [5095, 1184],
+ [5062, 1201],
+ [5019, 1256],
+ [5010, 1291],
+ [4976, 1298],
+ [4890, 1365],
+ [4881, 1385],
+ [4775, 1482],
+ [4747, 1571],
+ [4668, 1659],
+ [4662, 1750],
+ [4705, 1771],
+ [4754, 1721],
+ [4781, 1716],
+ [4805, 1774],
+ [4867, 1774],
+ [4893, 1807],
+ [4950, 1773],
+ [4966, 1787],
+ [5030, 1773],
+ [5051, 1788],
+ [5085, 1763],
+ [5120, 1791],
+ [5164, 1799],
+ [5229, 1777],
+ [5259, 1787],
+ [5308, 1729],
+ [5333, 1734],
+ [5363, 1755],
+ [5405, 1749],
+ [5402, 1704],
+ [5369, 1637],
+ [5388, 1571],
+ [5489, 1511],
+ [5411, 1478],
+ [5467, 1428],
+ [5478, 1370],
+ [5448, 1380],
+ [5419, 1354],
+ [5360, 1334],
+ [5401, 1286],
+ [5364, 1294],
+ [5321, 1259],
+ [5320, 1192],
+ [5282, 1179],
+ [5293, 1114],
+ [5315, 1079],
+ [5293, 1053],
+ [5161, 1114],
+ [5115, 1130],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'MC',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.47,
+ 'hc-middle-y': 0.63,
+ 'hc-key': 'mc',
+ 'hc-a2': 'MC',
+ name: 'Monaco',
+ labelrank: '6',
+ 'country-abbrev': 'Mco.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'MCO',
+ 'iso-a2': 'MC',
+ 'woe-id': '23424892',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [2937, 1301],
+ [2930, 1294],
+ [2922, 1295],
+ [2931, 1307],
+ [2937, 1301],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'AL',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.3,
+ 'hc-middle-y': 0.65,
+ 'hc-key': 'al',
+ 'hc-a2': 'AL',
+ name: 'Albania',
+ labelrank: '6',
+ 'country-abbrev': 'Alb.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'ALB',
+ 'iso-a2': 'AL',
+ 'woe-id': '23424742',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [[[5907, 643], [5905, 642], [5902, 648], [5906, 645], [5907, 643]]],
+ [
+ [
+ [5827, 689],
+ [5837, 642],
+ [5854, 641],
+ [5874, 648],
+ [5902, 648],
+ [5899, 643],
+ [5909, 635],
+ [5909, 634],
+ [5900, 609],
+ [5912, 616],
+ [5909, 607],
+ [5928, 589],
+ [5924, 584],
+ [5929, 587],
+ [5934, 546],
+ [5896, 516],
+ [5871, 401],
+ [5801, 361],
+ [5827, 318],
+ [5783, 255],
+ [5744, 264],
+ [5742, 309],
+ [5697, 364],
+ [5606, 400],
+ [5597, 470],
+ [5552, 520],
+ [5567, 589],
+ [5586, 602],
+ [5563, 670],
+ [5575, 704],
+ [5543, 743],
+ [5572, 801],
+ [5568, 869],
+ [5519, 873],
+ [5511, 904],
+ [5511, 941],
+ [5532, 960],
+ [5508, 1011],
+ [5560, 1115],
+ [5593, 1064],
+ [5642, 1094],
+ [5686, 1036],
+ [5749, 1011],
+ [5782, 938],
+ [5778, 915],
+ [5765, 818],
+ [5792, 778],
+ [5782, 752],
+ [5827, 689],
+ ],
+ ],
+ [[[5503, 1000], [5503, 997], [5502, 997], [5503, 1000]]],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'CNM',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.66,
+ 'hc-middle-y': 0.61,
+ 'hc-key': 'cnm',
+ 'hc-a2': 'CN',
+ name: 'Cyprus No Mans Area',
+ labelrank: '9',
+ 'country-abbrev': null,
+ subregion: 'Western Asia',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': '-99',
+ 'iso-a2': null,
+ 'woe-id': '-99',
+ continent: 'Asia',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [9288, -289],
+ [9288, -289],
+ [9291, -290],
+ [9270, -299],
+ [9261, -299],
+ [9262, -296],
+ [9276, -291],
+ [9288, -289],
+ ],
+ ],
+ [
+ [
+ [8944, -370],
+ [8947, -367],
+ [8947, -367],
+ [8952, -370],
+ [8956, -361],
+ [8958, -360],
+ [8960, -360],
+ [8955, -373],
+ [8944, -370],
+ ],
+ ],
+ [
+ [
+ [8968, -358],
+ [8968, -358],
+ [8973, -358],
+ [9012, -377],
+ [9084, -318],
+ [9132, -299],
+ [9160, -323],
+ [9213, -324],
+ [9213, -324],
+ [9219, -325],
+ [9223, -335],
+ [9162, -352],
+ [9139, -309],
+ [9083, -327],
+ [9008, -383],
+ [8968, -358],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'NC',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.59,
+ 'hc-middle-y': 0.61,
+ 'hc-key': 'nc',
+ 'hc-a2': 'NC',
+ name: 'Northern Cyprus',
+ labelrank: '6',
+ 'country-abbrev': 'N. Cy.',
+ subregion: 'Western Asia',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': '-99',
+ 'iso-a2': 'NC',
+ 'woe-id': '-90',
+ continent: 'Asia',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [9160, -323],
+ [9132, -299],
+ [9084, -318],
+ [9012, -377],
+ [8973, -358],
+ [9011, -353],
+ [9001, -280],
+ [9126, -260],
+ [9253, -171],
+ [9359, -64],
+ [9360, -79],
+ [9246, -235],
+ [9288, -289],
+ [9276, -291],
+ [9262, -296],
+ [9262, -296],
+ [9233, -318],
+ [9213, -324],
+ [9213, -324],
+ [9160, -323],
+ ],
+ ],
+ [
+ [
+ [8947, -367],
+ [8951, -364],
+ [8956, -361],
+ [8952, -370],
+ [8947, -367],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'RS',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.47,
+ 'hc-middle-y': 0.51,
+ 'hc-key': 'rs',
+ 'hc-a2': 'RS',
+ name: 'Republic of Serbia',
+ labelrank: '5',
+ 'country-abbrev': 'Serb.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'SRB',
+ 'iso-a2': 'RS',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [5333, 1734],
+ [5332, 1816],
+ [5399, 1831],
+ [5390, 1853],
+ [5313, 1878],
+ [5308, 1936],
+ [5265, 2001],
+ [5272, 2037],
+ [5302, 2065],
+ [5342, 2061],
+ [5393, 2121],
+ [5468, 2131],
+ [5533, 2124],
+ [5557, 2094],
+ [5657, 2038],
+ [5663, 1963],
+ [5714, 1924],
+ [5826, 1887],
+ [5805, 1838],
+ [5841, 1827],
+ [5814, 1802],
+ [5881, 1761],
+ [5954, 1762],
+ [5997, 1730],
+ [6036, 1801],
+ [6113, 1770],
+ [6059, 1736],
+ [6116, 1666],
+ [6105, 1620],
+ [6067, 1588],
+ [6066, 1533],
+ [6118, 1443],
+ [6229, 1382],
+ [6192, 1283],
+ [6146, 1270],
+ [6144, 1181],
+ [6170, 1136],
+ [6140, 1104],
+ [6119, 1116],
+ [5976, 1056],
+ [5999, 1185],
+ [5913, 1193],
+ [5912, 1226],
+ [5882, 1230],
+ [5837, 1284],
+ [5780, 1298],
+ [5772, 1323],
+ [5728, 1295],
+ [5747, 1275],
+ [5690, 1184],
+ [5685, 1207],
+ [5636, 1220],
+ [5590, 1254],
+ [5522, 1261],
+ [5419, 1354],
+ [5448, 1380],
+ [5478, 1370],
+ [5467, 1428],
+ [5411, 1478],
+ [5489, 1511],
+ [5388, 1571],
+ [5369, 1637],
+ [5402, 1704],
+ [5405, 1749],
+ [5363, 1755],
+ [5333, 1734],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'RO',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.45,
+ 'hc-middle-y': 0.54,
+ 'hc-key': 'ro',
+ 'hc-a2': 'RO',
+ name: 'Romania',
+ labelrank: '3',
+ 'country-abbrev': 'Rom.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'ROU',
+ 'iso-a2': 'RO',
+ 'woe-id': '23424933',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [6059, 1736],
+ [6113, 1770],
+ [6036, 1801],
+ [5997, 1730],
+ [5954, 1762],
+ [5881, 1761],
+ [5814, 1802],
+ [5841, 1827],
+ [5805, 1838],
+ [5826, 1887],
+ [5714, 1924],
+ [5663, 1963],
+ [5657, 2038],
+ [5557, 2094],
+ [5533, 2124],
+ [5575, 2150],
+ [5605, 2141],
+ [5645, 2188],
+ [5703, 2199],
+ [5724, 2302],
+ [5756, 2338],
+ [5767, 2428],
+ [5790, 2458],
+ [5814, 2573],
+ [5856, 2646],
+ [5943, 2693],
+ [5962, 2732],
+ [6000, 2782],
+ [6052, 2762],
+ [6132, 2776],
+ [6223, 2767],
+ [6283, 2792],
+ [6360, 2740],
+ [6400, 2767],
+ [6419, 2808],
+ [6585, 2873],
+ [6596, 2941],
+ [6652, 2968],
+ [6687, 2976],
+ [6729, 2959],
+ [6775, 2912],
+ [6821, 2832],
+ [6884, 2789],
+ [6953, 2710],
+ [7003, 2689],
+ [7070, 2596],
+ [7089, 2531],
+ [7089, 2403],
+ [7132, 2304],
+ [7114, 2288],
+ [7150, 2258],
+ [7186, 2225],
+ [7282, 2223],
+ [7373, 2312],
+ [7445, 2302],
+ [7457, 2266],
+ [7476, 2165],
+ [7469, 2151],
+ [7380, 2113],
+ [7337, 2172],
+ [7324, 2132],
+ [7352, 2077],
+ [7322, 2035],
+ [7356, 2049],
+ [7322, 1963],
+ [7352, 1873],
+ [7353, 1794],
+ [7278, 1781],
+ [7223, 1793],
+ [7199, 1830],
+ [7163, 1808],
+ [7144, 1825],
+ [7089, 1809],
+ [7055, 1833],
+ [7006, 1837],
+ [6838, 1749],
+ [6780, 1652],
+ [6698, 1611],
+ [6610, 1620],
+ [6512, 1615],
+ [6444, 1587],
+ [6264, 1592],
+ [6183, 1561],
+ [6168, 1606],
+ [6193, 1640],
+ [6116, 1666],
+ [6115, 1666],
+ [6059, 1736],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'ME',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.29,
+ 'hc-middle-y': 0.67,
+ 'hc-key': 'me',
+ 'hc-a2': 'ME',
+ name: 'Montenegro',
+ labelrank: '6',
+ 'country-abbrev': 'Mont.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'MNE',
+ 'iso-a2': 'ME',
+ 'woe-id': '20069817',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [5642, 1094],
+ [5593, 1064],
+ [5560, 1115],
+ [5508, 1011],
+ [5505, 1006],
+ [5503, 1000],
+ [5502, 997],
+ [5456, 988],
+ [5511, 941],
+ [5511, 904],
+ [5519, 873],
+ [5473, 892],
+ [5463, 922],
+ [5396, 986],
+ [5377, 978],
+ [5344, 1027],
+ [5311, 1013],
+ [5298, 1030],
+ [5293, 1053],
+ [5315, 1079],
+ [5293, 1114],
+ [5282, 1179],
+ [5320, 1192],
+ [5321, 1259],
+ [5364, 1294],
+ [5401, 1286],
+ [5360, 1334],
+ [5419, 1354],
+ [5522, 1261],
+ [5590, 1254],
+ [5636, 1220],
+ [5685, 1207],
+ [5690, 1184],
+ [5626, 1144],
+ [5642, 1094],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'LI',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.62,
+ 'hc-middle-y': 0.51,
+ 'hc-key': 'li',
+ 'hc-a2': 'LI',
+ name: 'Liechtenstein',
+ labelrank: '6',
+ 'country-abbrev': 'Liech.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'LIE',
+ 'iso-a2': 'LI',
+ 'woe-id': '23424879',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [3383, 2312],
+ [3402, 2266],
+ [3395, 2252],
+ [3374, 2254],
+ [3383, 2312],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'AT',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.68,
+ 'hc-middle-y': 0.5,
+ 'hc-key': 'at',
+ 'hc-a2': 'AT',
+ name: 'Austria',
+ labelrank: '4',
+ 'country-abbrev': 'Aust.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'AUT',
+ 'iso-a2': 'AT',
+ 'woe-id': '23424750',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [3395, 2252],
+ [3402, 2266],
+ [3383, 2312],
+ [3409, 2354],
+ [3390, 2383],
+ [3413, 2380],
+ [3422, 2394],
+ [3467, 2387],
+ [3538, 2323],
+ [3566, 2362],
+ [3558, 2401],
+ [3632, 2385],
+ [3670, 2350],
+ [3724, 2353],
+ [3794, 2409],
+ [3900, 2416],
+ [3902, 2446],
+ [3965, 2426],
+ [4016, 2438],
+ [4021, 2406],
+ [4072, 2390],
+ [4066, 2454],
+ [4041, 2456],
+ [4059, 2492],
+ [4008, 2569],
+ [4062, 2613],
+ [4132, 2649],
+ [4151, 2710],
+ [4189, 2693],
+ [4205, 2765],
+ [4257, 2717],
+ [4304, 2710],
+ [4329, 2736],
+ [4376, 2724],
+ [4392, 2779],
+ [4415, 2776],
+ [4422, 2848],
+ [4476, 2844],
+ [4558, 2815],
+ [4583, 2821],
+ [4627, 2791],
+ [4689, 2788],
+ [4702, 2808],
+ [4787, 2794],
+ [4804, 2763],
+ [4792, 2692],
+ [4860, 2595],
+ [4836, 2551],
+ [4854, 2508],
+ [4801, 2493],
+ [4763, 2511],
+ [4726, 2482],
+ [4770, 2475],
+ [4777, 2426],
+ [4737, 2393],
+ [4759, 2293],
+ [4717, 2291],
+ [4685, 2247],
+ [4673, 2197],
+ [4597, 2198],
+ [4565, 2165],
+ [4485, 2170],
+ [4444, 2153],
+ [4386, 2084],
+ [4358, 2100],
+ [4216, 2116],
+ [4122, 2120],
+ [3956, 2154],
+ [3895, 2240],
+ [3913, 2265],
+ [3823, 2232],
+ [3737, 2234],
+ [3694, 2212],
+ [3676, 2170],
+ [3567, 2197],
+ [3550, 2234],
+ [3500, 2191],
+ [3450, 2218],
+ [3449, 2240],
+ [3395, 2252],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'SK',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.4,
+ 'hc-middle-y': 0.46,
+ 'hc-key': 'sk',
+ 'hc-a2': 'SK',
+ name: 'Slovakia',
+ labelrank: '6',
+ 'country-abbrev': 'Svk.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'SVK',
+ 'iso-a2': 'SK',
+ 'woe-id': '23424877',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [4860, 2595],
+ [4792, 2692],
+ [4804, 2763],
+ [4839, 2840],
+ [4910, 2834],
+ [4968, 2872],
+ [5005, 2912],
+ [5019, 2981],
+ [5077, 3047],
+ [5131, 3062],
+ [5160, 3030],
+ [5198, 3039],
+ [5241, 3102],
+ [5283, 3050],
+ [5310, 3051],
+ [5313, 2997],
+ [5371, 2995],
+ [5381, 3035],
+ [5411, 3063],
+ [5481, 3078],
+ [5533, 3055],
+ [5545, 3087],
+ [5585, 3108],
+ [5692, 3104],
+ [5736, 3063],
+ [5841, 3040],
+ [5819, 2970],
+ [5819, 2928],
+ [5793, 2890],
+ [5798, 2837],
+ [5724, 2806],
+ [5656, 2860],
+ [5600, 2830],
+ [5535, 2843],
+ [5479, 2822],
+ [5459, 2748],
+ [5381, 2693],
+ [5328, 2714],
+ [5305, 2677],
+ [5184, 2641],
+ [5168, 2619],
+ [5187, 2581],
+ [5078, 2545],
+ [4999, 2535],
+ [4947, 2553],
+ [4897, 2596],
+ [4860, 2595],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'HU',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.45,
+ 'hc-middle-y': 0.54,
+ 'hc-key': 'hu',
+ 'hc-a2': 'HU',
+ name: 'Hungary',
+ labelrank: '5',
+ 'country-abbrev': 'Hun.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'HUN',
+ 'iso-a2': 'HU',
+ 'woe-id': '23424844',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [4777, 2150],
+ [4720, 2250],
+ [4685, 2247],
+ [4717, 2291],
+ [4759, 2293],
+ [4737, 2393],
+ [4777, 2426],
+ [4770, 2475],
+ [4726, 2482],
+ [4763, 2511],
+ [4801, 2493],
+ [4854, 2508],
+ [4836, 2551],
+ [4860, 2595],
+ [4897, 2596],
+ [4947, 2553],
+ [4999, 2535],
+ [5078, 2545],
+ [5187, 2581],
+ [5168, 2619],
+ [5184, 2641],
+ [5305, 2677],
+ [5328, 2714],
+ [5381, 2693],
+ [5459, 2748],
+ [5479, 2822],
+ [5535, 2843],
+ [5600, 2830],
+ [5656, 2860],
+ [5724, 2806],
+ [5798, 2837],
+ [5824, 2842],
+ [5848, 2799],
+ [5872, 2803],
+ [5901, 2766],
+ [5928, 2776],
+ [5962, 2732],
+ [5943, 2693],
+ [5856, 2646],
+ [5814, 2573],
+ [5790, 2458],
+ [5767, 2428],
+ [5756, 2338],
+ [5724, 2302],
+ [5703, 2199],
+ [5645, 2188],
+ [5605, 2141],
+ [5575, 2150],
+ [5533, 2124],
+ [5468, 2131],
+ [5393, 2121],
+ [5342, 2061],
+ [5302, 2065],
+ [5272, 2037],
+ [5227, 2026],
+ [5180, 1971],
+ [5138, 1979],
+ [5070, 1968],
+ [5008, 2009],
+ [4959, 2009],
+ [4924, 2054],
+ [4877, 2075],
+ [4851, 2116],
+ [4777, 2150],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'AD',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.48,
+ 'hc-middle-y': 0.52,
+ 'hc-key': 'ad',
+ 'hc-a2': 'AD',
+ name: 'Andorra',
+ labelrank: '6',
+ 'country-abbrev': 'And.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'AND',
+ 'iso-a2': 'AD',
+ 'woe-id': '23424744',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [1691, 1033],
+ [1645, 1016],
+ [1634, 1067],
+ [1697, 1064],
+ [1691, 1033],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'LU',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.5,
+ 'hc-middle-y': 0.58,
+ 'hc-key': 'lu',
+ 'hc-a2': 'LU',
+ name: 'Luxembourg',
+ labelrank: '6',
+ 'country-abbrev': 'Lux.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'LUX',
+ 'iso-a2': 'LU',
+ 'woe-id': '23424881',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [2791, 2962],
+ [2752, 2975],
+ [2719, 2961],
+ [2688, 2991],
+ [2708, 3020],
+ [2680, 3091],
+ [2737, 3172],
+ [2759, 3155],
+ [2774, 3087],
+ [2825, 3058],
+ [2791, 2962],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'CH',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.51,
+ 'hc-middle-y': 0.49,
+ 'hc-key': 'ch',
+ 'hc-a2': 'CH',
+ name: 'Switzerland',
+ labelrank: '4',
+ 'country-abbrev': 'Switz.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'CHE',
+ 'iso-a2': 'CH',
+ 'woe-id': '23424957',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [3006, 2412],
+ [3174, 2408],
+ [3164, 2431],
+ [3205, 2468],
+ [3264, 2425],
+ [3318, 2430],
+ [3319, 2429],
+ [3321, 2426],
+ [3321, 2426],
+ [3378, 2377],
+ [3390, 2383],
+ [3409, 2354],
+ [3383, 2312],
+ [3374, 2254],
+ [3395, 2252],
+ [3449, 2240],
+ [3450, 2218],
+ [3500, 2191],
+ [3550, 2234],
+ [3567, 2197],
+ [3551, 2141],
+ [3562, 2101],
+ [3495, 2121],
+ [3486, 2071],
+ [3509, 2022],
+ [3486, 2010],
+ [3470, 2049],
+ [3389, 2031],
+ [3365, 2089],
+ [3330, 2087],
+ [3331, 2036],
+ [3272, 1939],
+ [3287, 1913],
+ [3255, 1898],
+ [3243, 1967],
+ [3196, 1984],
+ [3162, 2022],
+ [3166, 2075],
+ [3091, 2025],
+ [3097, 1988],
+ [3039, 1928],
+ [2981, 1950],
+ [2908, 1923],
+ [2876, 1937],
+ [2844, 1995],
+ [2835, 2080],
+ [2852, 2092],
+ [2803, 2112],
+ [2741, 2096],
+ [2720, 2051],
+ [2731, 2035],
+ [2664, 2007],
+ [2704, 2071],
+ [2688, 2089],
+ [2706, 2139],
+ [2768, 2184],
+ [2773, 2237],
+ [2805, 2247],
+ [2897, 2346],
+ [2862, 2351],
+ [2892, 2392],
+ [2964, 2369],
+ [3006, 2412],
+ [3006, 2412],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'BE',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.53,
+ 'hc-middle-y': 0.37,
+ 'hc-key': 'be',
+ 'hc-a2': 'BE',
+ name: 'Belgium',
+ labelrank: '2',
+ 'country-abbrev': 'Belg.',
+ subregion: 'Western Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'BEL',
+ 'iso-a2': 'BE',
+ 'woe-id': '23424757',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [2759, 3155],
+ [2737, 3172],
+ [2680, 3091],
+ [2708, 3020],
+ [2688, 2991],
+ [2629, 2982],
+ [2536, 3076],
+ [2519, 3074],
+ [2510, 3129],
+ [2529, 3175],
+ [2492, 3162],
+ [2486, 3135],
+ [2443, 3122],
+ [2390, 3138],
+ [2408, 3217],
+ [2377, 3244],
+ [2310, 3245],
+ [2310, 3281],
+ [2244, 3311],
+ [2227, 3382],
+ [2161, 3376],
+ [2129, 3413],
+ [2124, 3485],
+ [2239, 3543],
+ [2280, 3553],
+ [2285, 3515],
+ [2330, 3523],
+ [2380, 3495],
+ [2437, 3537],
+ [2452, 3509],
+ [2444, 3537],
+ [2467, 3530],
+ [2486, 3564],
+ [2511, 3546],
+ [2537, 3566],
+ [2561, 3534],
+ [2581, 3557],
+ [2614, 3492],
+ [2660, 3498],
+ [2723, 3456],
+ [2690, 3344],
+ [2746, 3338],
+ [2778, 3297],
+ [2779, 3261],
+ [2804, 3257],
+ [2809, 3209],
+ [2765, 3182],
+ [2759, 3155],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'KV',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.89,
+ 'hc-middle-y': 0.48,
+ 'hc-key': 'kv',
+ 'hc-a2': 'KV',
+ name: 'Kosovo',
+ labelrank: '6',
+ 'country-abbrev': 'Kos.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': '-99',
+ 'iso-a2': 'KV',
+ 'woe-id': '-90',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [5778, 915],
+ [5782, 938],
+ [5749, 1011],
+ [5686, 1036],
+ [5642, 1094],
+ [5626, 1144],
+ [5690, 1184],
+ [5747, 1275],
+ [5728, 1295],
+ [5772, 1323],
+ [5780, 1298],
+ [5837, 1284],
+ [5882, 1230],
+ [5912, 1226],
+ [5913, 1193],
+ [5999, 1185],
+ [5976, 1056],
+ [5945, 1049],
+ [5913, 1002],
+ [5878, 1026],
+ [5813, 977],
+ [5816, 931],
+ [5778, 915],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'PL',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.56,
+ 'hc-middle-y': 0.5,
+ 'hc-key': 'pl',
+ 'hc-a2': 'PL',
+ name: 'Poland',
+ labelrank: '3',
+ 'country-abbrev': 'Pol.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'POL',
+ 'iso-a2': 'PL',
+ 'woe-id': '23424923',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [
+ [
+ [5615, 4546],
+ [5628, 4561],
+ [5735, 4513],
+ [5756, 4450],
+ [5791, 4360],
+ [5868, 4241],
+ [5895, 4126],
+ [5890, 4104],
+ [5817, 4042],
+ [5789, 3973],
+ [5882, 3930],
+ [5894, 3906],
+ [5886, 3834],
+ [5907, 3769],
+ [5922, 3719],
+ [5976, 3670],
+ [5989, 3635],
+ [6038, 3595],
+ [6010, 3586],
+ [6051, 3510],
+ [6035, 3467],
+ [5994, 3455],
+ [5900, 3310],
+ [5837, 3173],
+ [5861, 3130],
+ [5867, 3073],
+ [5904, 3029],
+ [5841, 3040],
+ [5736, 3063],
+ [5692, 3104],
+ [5585, 3108],
+ [5545, 3087],
+ [5533, 3055],
+ [5481, 3078],
+ [5411, 3063],
+ [5381, 3035],
+ [5371, 2995],
+ [5313, 2997],
+ [5310, 3051],
+ [5283, 3050],
+ [5241, 3102],
+ [5198, 3039],
+ [5160, 3030],
+ [5131, 3062],
+ [5114, 3108],
+ [5088, 3112],
+ [5067, 3169],
+ [4967, 3187],
+ [4931, 3173],
+ [4880, 3222],
+ [4880, 3250],
+ [4830, 3248],
+ [4797, 3277],
+ [4739, 3283],
+ [4762, 3230],
+ [4718, 3186],
+ [4643, 3260],
+ [4615, 3272],
+ [4648, 3301],
+ [4636, 3338],
+ [4591, 3335],
+ [4470, 3369],
+ [4453, 3363],
+ [4435, 3411],
+ [4378, 3418],
+ [4385, 3380],
+ [4354, 3378],
+ [4385, 3489],
+ [4367, 3549],
+ [4327, 3566],
+ [4322, 3611],
+ [4295, 3647],
+ [4322, 3727],
+ [4307, 3777],
+ [4276, 3824],
+ [4292, 3870],
+ [4196, 3943],
+ [4198, 3974],
+ [4231, 4002],
+ [4238, 4067],
+ [4206, 4188],
+ [4249, 4181],
+ [4266, 4236],
+ [4192, 4239],
+ [4187, 4247],
+ [4193, 4256],
+ [4220, 4252],
+ [4288, 4290],
+ [4511, 4381],
+ [4576, 4464],
+ [4637, 4484],
+ [4699, 4531],
+ [4787, 4562],
+ [4858, 4575],
+ [4910, 4497],
+ [4917, 4464],
+ [4989, 4447],
+ [5048, 4464],
+ [5048, 4464],
+ [5027, 4450],
+ [5056, 4436],
+ [5111, 4489],
+ [5604, 4540],
+ [5615, 4546],
+ ],
+ ],
+ [
+ [
+ [5086, 4492],
+ [5088, 4491],
+ [5060, 4472],
+ [5060, 4472],
+ [5086, 4492],
+ ],
+ ],
+ [
+ [
+ [5048, 4464],
+ [5060, 4472],
+ [5060, 4472],
+ [5050, 4465],
+ [5048, 4464],
+ [5048, 4464],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'MK',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.49,
+ 'hc-middle-y': 0.49,
+ 'hc-key': 'mk',
+ 'hc-a2': 'MK',
+ name: 'Macedonia',
+ labelrank: '6',
+ 'country-abbrev': 'Mkd.',
+ subregion: 'Southern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'MKD',
+ 'iso-a2': 'MK',
+ 'woe-id': '23424890',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'MultiPolygon',
+ coordinates: [
+ [[[5909, 635], [5910, 635], [5909, 634], [5909, 635]]],
+ [
+ [
+ [6140, 1104],
+ [6189, 1058],
+ [6262, 1037],
+ [6313, 957],
+ [6303, 916],
+ [6313, 844],
+ [6278, 832],
+ [6280, 788],
+ [6216, 761],
+ [6162, 765],
+ [6105, 737],
+ [6044, 658],
+ [5999, 661],
+ [5943, 639],
+ [5902, 680],
+ [5907, 643],
+ [5906, 645],
+ [5902, 648],
+ [5902, 648],
+ [5874, 648],
+ [5854, 641],
+ [5866, 703],
+ [5827, 689],
+ [5782, 752],
+ [5792, 778],
+ [5765, 818],
+ [5778, 915],
+ [5816, 931],
+ [5813, 977],
+ [5878, 1026],
+ [5913, 1002],
+ [5945, 1049],
+ [5976, 1056],
+ [6119, 1116],
+ [6140, 1104],
+ ],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'LV',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.68,
+ 'hc-middle-y': 0.47,
+ 'hc-key': 'lv',
+ 'hc-a2': 'LV',
+ name: 'Latvia',
+ labelrank: '5',
+ 'country-abbrev': 'Lat.',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'LVA',
+ 'iso-a2': 'LV',
+ 'woe-id': '23424874',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [6371, 5238],
+ [6337, 5217],
+ [6307, 5156],
+ [6308, 5118],
+ [6209, 5104],
+ [6192, 5064],
+ [6159, 5044],
+ [6104, 5054],
+ [6081, 5080],
+ [5992, 5129],
+ [5981, 5144],
+ [5891, 5137],
+ [5842, 5202],
+ [5783, 5137],
+ [5729, 5127],
+ [5661, 5141],
+ [5594, 5133],
+ [5570, 5111],
+ [5529, 5132],
+ [5500, 5110],
+ [5404, 5112],
+ [5291, 5038],
+ [5276, 4994],
+ [5254, 4987],
+ [5233, 5037],
+ [5222, 5208],
+ [5266, 5271],
+ [5258, 5343],
+ [5288, 5426],
+ [5332, 5447],
+ [5414, 5508],
+ [5433, 5460],
+ [5517, 5412],
+ [5549, 5343],
+ [5626, 5314],
+ [5663, 5335],
+ [5716, 5410],
+ [5714, 5443],
+ [5669, 5588],
+ [5699, 5617],
+ [5801, 5677],
+ [5861, 5642],
+ [5926, 5637],
+ [5934, 5617],
+ [6022, 5561],
+ [6071, 5605],
+ [6151, 5595],
+ [6177, 5602],
+ [6181, 5574],
+ [6241, 5547],
+ [6248, 5510],
+ [6240, 5414],
+ [6262, 5427],
+ [6284, 5395],
+ [6340, 5347],
+ [6371, 5279],
+ [6371, 5238],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'BY',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.48,
+ 'hc-middle-y': 0.57,
+ 'hc-key': 'by',
+ 'hc-a2': 'BY',
+ name: 'Belarus',
+ labelrank: '4',
+ 'country-abbrev': 'Bela.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'BLR',
+ 'iso-a2': 'BY',
+ 'woe-id': '23424765',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [6159, 5044],
+ [6192, 5064],
+ [6209, 5104],
+ [6308, 5118],
+ [6307, 5156],
+ [6337, 5217],
+ [6371, 5238],
+ [6400, 5217],
+ [6449, 5241],
+ [6489, 5207],
+ [6517, 5241],
+ [6576, 5237],
+ [6584, 5189],
+ [6610, 5166],
+ [6663, 5224],
+ [6715, 5246],
+ [6759, 5240],
+ [6818, 5198],
+ [6840, 5206],
+ [6861, 5155],
+ [6852, 5115],
+ [6907, 5053],
+ [6884, 5017],
+ [6889, 4976],
+ [6966, 4950],
+ [6960, 4909],
+ [6987, 4904],
+ [7024, 4849],
+ [7118, 4826],
+ [7129, 4751],
+ [7183, 4772],
+ [7254, 4763],
+ [7266, 4719],
+ [7320, 4704],
+ [7290, 4620],
+ [7246, 4572],
+ [7180, 4585],
+ [7126, 4570],
+ [7114, 4511],
+ [7171, 4478],
+ [7227, 4334],
+ [7278, 4286],
+ [7228, 4275],
+ [7196, 4244],
+ [7144, 4237],
+ [7114, 4151],
+ [7106, 4084],
+ [7149, 4017],
+ [7140, 3984],
+ [7103, 3994],
+ [7053, 4033],
+ [7005, 4004],
+ [6961, 4007],
+ [6918, 3960],
+ [6865, 4022],
+ [6825, 3992],
+ [6813, 3942],
+ [6780, 3978],
+ [6737, 3959],
+ [6704, 3988],
+ [6687, 3955],
+ [6639, 3956],
+ [6634, 3914],
+ [6616, 3948],
+ [6542, 3930],
+ [6519, 3969],
+ [6462, 3957],
+ [6378, 3967],
+ [6262, 3963],
+ [6159, 3947],
+ [6082, 3911],
+ [6025, 3898],
+ [6008, 3848],
+ [5970, 3801],
+ [5926, 3810],
+ [5907, 3769],
+ [5886, 3834],
+ [5894, 3906],
+ [5882, 3930],
+ [5789, 3973],
+ [5817, 4042],
+ [5890, 4104],
+ [5895, 4126],
+ [5868, 4241],
+ [5791, 4360],
+ [5756, 4450],
+ [5784, 4444],
+ [5875, 4477],
+ [5908, 4464],
+ [5952, 4504],
+ [5971, 4502],
+ [5972, 4554],
+ [6009, 4557],
+ [6026, 4598],
+ [6065, 4618],
+ [6086, 4576],
+ [6118, 4585],
+ [6100, 4633],
+ [6071, 4634],
+ [6092, 4704],
+ [6080, 4791],
+ [6131, 4831],
+ [6147, 4887],
+ [6193, 4890],
+ [6218, 4942],
+ [6157, 4946],
+ [6159, 5044],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'IS',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.59,
+ 'hc-middle-y': 0.68,
+ 'hc-key': 'is',
+ 'hc-a2': 'IS',
+ name: 'Iceland',
+ labelrank: '3',
+ 'country-abbrev': 'Iceland',
+ subregion: 'Northern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'ISL',
+ 'iso-a2': 'IS',
+ 'woe-id': '23424845',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [23, 7765],
+ [-31, 7764],
+ [-42, 7780],
+ [-86, 7762],
+ [-64, 7754],
+ [-101, 7722],
+ [-209, 7727],
+ [-271, 7767],
+ [-318, 7818],
+ [-367, 7843],
+ [-388, 7915],
+ [-443, 7984],
+ [-435, 8008],
+ [-470, 7988],
+ [-517, 8017],
+ [-554, 8023],
+ [-582, 8046],
+ [-631, 8058],
+ [-594, 8126],
+ [-590, 8089],
+ [-546, 8080],
+ [-466, 8107],
+ [-487, 8122],
+ [-442, 8153],
+ [-483, 8140],
+ [-497, 8153],
+ [-458, 8196],
+ [-397, 8218],
+ [-488, 8200],
+ [-493, 8230],
+ [-466, 8281],
+ [-602, 8368],
+ [-616, 8355],
+ [-649, 8375],
+ [-644, 8415],
+ [-596, 8393],
+ [-542, 8384],
+ [-532, 8401],
+ [-506, 8378],
+ [-474, 8390],
+ [-473, 8368],
+ [-433, 8366],
+ [-370, 8331],
+ [-345, 8373],
+ [-387, 8362],
+ [-439, 8405],
+ [-423, 8419],
+ [-332, 8436],
+ [-332, 8465],
+ [-371, 8459],
+ [-387, 8509],
+ [-413, 8504],
+ [-455, 8548],
+ [-556, 8542],
+ [-556, 8561],
+ [-613, 8605],
+ [-567, 8624],
+ [-538, 8578],
+ [-544, 8617],
+ [-519, 8656],
+ [-469, 8575],
+ [-488, 8630],
+ [-478, 8675],
+ [-451, 8648],
+ [-466, 8697],
+ [-455, 8712],
+ [-432, 8685],
+ [-436, 8718],
+ [-402, 8730],
+ [-378, 8700],
+ [-381, 8676],
+ [-344, 8653],
+ [-330, 8618],
+ [-337, 8579],
+ [-309, 8641],
+ [-344, 8686],
+ [-333, 8728],
+ [-353, 8755],
+ [-336, 8773],
+ [-272, 8752],
+ [-251, 8712],
+ [-259, 8681],
+ [-233, 8670],
+ [-219, 8634],
+ [-229, 8605],
+ [-208, 8600],
+ [-197, 8559],
+ [-209, 8522],
+ [-269, 8453],
+ [-246, 8455],
+ [-266, 8427],
+ [-254, 8402],
+ [-265, 8355],
+ [-201, 8434],
+ [-164, 8447],
+ [-167, 8384],
+ [-110, 8440],
+ [-96, 8526],
+ [-87, 8540],
+ [-45, 8536],
+ [-48, 8465],
+ [-33, 8447],
+ [-39, 8415],
+ [-19, 8396],
+ [-2, 8460],
+ [31, 8489],
+ [61, 8471],
+ [71, 8495],
+ [101, 8497],
+ [121, 8449],
+ [109, 8419],
+ [128, 8404],
+ [123, 8338],
+ [146, 8358],
+ [140, 8395],
+ [160, 8464],
+ [199, 8439],
+ [214, 8374],
+ [237, 8373],
+ [282, 8419],
+ [307, 8391],
+ [363, 8386],
+ [381, 8410],
+ [391, 8477],
+ [452, 8463],
+ [449, 8428],
+ [472, 8410],
+ [453, 8383],
+ [483, 8328],
+ [504, 8358],
+ [527, 8353],
+ [569, 8373],
+ [592, 8356],
+ [537, 8346],
+ [535, 8321],
+ [502, 8309],
+ [508, 8287],
+ [554, 8273],
+ [551, 8240],
+ [502, 8190],
+ [566, 8182],
+ [553, 8170],
+ [604, 8087],
+ [624, 8078],
+ [583, 8028],
+ [604, 8005],
+ [589, 7946],
+ [569, 7931],
+ [532, 7974],
+ [550, 7914],
+ [516, 7902],
+ [505, 7876],
+ [444, 7877],
+ [405, 7807],
+ [384, 7815],
+ [347, 7800],
+ [289, 7807],
+ [204, 7798],
+ [142, 7765],
+ [77, 7752],
+ [64, 7775],
+ [45, 7750],
+ [23, 7765],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'MD',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.47,
+ 'hc-middle-y': 0.3,
+ 'hc-key': 'md',
+ 'hc-a2': 'MD',
+ name: 'Moldova',
+ labelrank: '6',
+ 'country-abbrev': 'Mda.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'MDA',
+ 'iso-a2': 'MD',
+ 'woe-id': '23424885',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [7150, 2258],
+ [7114, 2288],
+ [7132, 2304],
+ [7089, 2403],
+ [7089, 2531],
+ [7070, 2596],
+ [7003, 2689],
+ [6953, 2710],
+ [6884, 2789],
+ [6821, 2832],
+ [6775, 2912],
+ [6729, 2959],
+ [6687, 2976],
+ [6652, 2968],
+ [6685, 3015],
+ [6749, 3021],
+ [6803, 3068],
+ [6850, 3073],
+ [6926, 3031],
+ [6981, 3041],
+ [7015, 3026],
+ [7070, 3029],
+ [7112, 2987],
+ [7141, 3008],
+ [7170, 2984],
+ [7174, 2884],
+ [7248, 2829],
+ [7273, 2849],
+ [7303, 2774],
+ [7302, 2743],
+ [7384, 2725],
+ [7404, 2644],
+ [7448, 2613],
+ [7405, 2591],
+ [7369, 2620],
+ [7355, 2583],
+ [7319, 2610],
+ [7279, 2560],
+ [7258, 2609],
+ [7222, 2574],
+ [7235, 2519],
+ [7256, 2502],
+ [7259, 2448],
+ [7223, 2426],
+ [7228, 2391],
+ [7190, 2327],
+ [7203, 2283],
+ [7150, 2258],
+ ],
+ ],
+ },
+ },
+ {
+ type: 'Feature',
+ id: 'CZ',
+ properties: {
+ 'hc-group': 'admin0',
+ 'hc-middle-x': 0.39,
+ 'hc-middle-y': 0.51,
+ 'hc-key': 'cz',
+ 'hc-a2': 'CZ',
+ name: 'Czech Republic',
+ labelrank: '5',
+ 'country-abbrev': 'Cz. Rep.',
+ subregion: 'Eastern Europe',
+ 'region-wb': 'Europe & Central Asia',
+ 'iso-a3': 'CZE',
+ 'iso-a2': 'CZ',
+ 'woe-id': '23424810',
+ continent: 'Europe',
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [
+ [
+ [5131, 3062],
+ [5077, 3047],
+ [5019, 2981],
+ [5005, 2912],
+ [4968, 2872],
+ [4910, 2834],
+ [4839, 2840],
+ [4804, 2763],
+ [4787, 2794],
+ [4702, 2808],
+ [4689, 2788],
+ [4627, 2791],
+ [4583, 2821],
+ [4558, 2815],
+ [4476, 2844],
+ [4422, 2848],
+ [4415, 2776],
+ [4392, 2779],
+ [4376, 2724],
+ [4329, 2736],
+ [4304, 2710],
+ [4257, 2717],
+ [4205, 2765],
+ [4163, 2815],
+ [4139, 2811],
+ [4079, 2860],
+ [4043, 2910],
+ [4004, 2918],
+ [3923, 3034],
+ [3947, 3082],
+ [3894, 3121],
+ [3860, 3197],
+ [3900, 3155],
+ [3940, 3221],
+ [4030, 3255],
+ [4070, 3282],
+ [4109, 3288],
+ [4136, 3323],
+ [4269, 3379],
+ [4256, 3423],
+ [4293, 3419],
+ [4318, 3372],
+ [4354, 3378],
+ [4385, 3380],
+ [4378, 3418],
+ [4435, 3411],
+ [4453, 3363],
+ [4470, 3369],
+ [4591, 3335],
+ [4636, 3338],
+ [4648, 3301],
+ [4615, 3272],
+ [4643, 3260],
+ [4718, 3186],
+ [4762, 3230],
+ [4739, 3283],
+ [4797, 3277],
+ [4830, 3248],
+ [4880, 3250],
+ [4880, 3222],
+ [4931, 3173],
+ [4967, 3187],
+ [5067, 3169],
+ [5088, 3112],
+ [5114, 3108],
+ [5131, 3062],
+ ],
+ ],
+ },
+ },
+ ],
+}
diff --git a/src/pages/dashboard/components/browser.js b/src/pages/dashboard/components/browser.js
new file mode 100644
index 0000000..c17239f
--- /dev/null
+++ b/src/pages/dashboard/components/browser.js
@@ -0,0 +1,51 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Table, Tag } from 'antd'
+import { Color } from 'utils'
+import styles from './browser.less'
+
+const status = {
+ 1: {
+ color: Color.green,
+ },
+ 2: {
+ color: Color.red,
+ },
+ 3: {
+ color: Color.blue,
+ },
+ 4: {
+ color: Color.yellow,
+ },
+}
+
+function Browser({ data }) {
+ const columns = [
+ {
+ title: 'name',
+ dataIndex: 'name',
+ className: styles.name,
+ },
+ {
+ title: 'percent',
+ dataIndex: 'percent',
+ className: styles.percent,
+ render: (text, it) => {text}% ,
+ },
+ ]
+ return (
+
+ )
+}
+
+Browser.propTypes = {
+ data: PropTypes.array,
+}
+
+export default Browser
diff --git a/src/pages/dashboard/components/browser.less b/src/pages/dashboard/components/browser.less
new file mode 100644
index 0000000..631ad64
--- /dev/null
+++ b/src/pages/dashboard/components/browser.less
@@ -0,0 +1,7 @@
+.percent {
+ text-align: right !important;
+}
+
+.name {
+ text-align: left !important;
+}
diff --git a/src/pages/dashboard/components/comments.js b/src/pages/dashboard/components/comments.js
new file mode 100644
index 0000000..6403860
--- /dev/null
+++ b/src/pages/dashboard/components/comments.js
@@ -0,0 +1,68 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Table, Tag } from 'antd'
+import { Color } from 'utils'
+import styles from './comments.less'
+
+const status = {
+ 1: {
+ color: Color.green,
+ text: 'APPROVED',
+ },
+ 2: {
+ color: Color.yellow,
+ text: 'PENDING',
+ },
+ 3: {
+ color: Color.red,
+ text: 'REJECTED',
+ },
+}
+
+function Comments({ data }) {
+ const columns = [
+ {
+ title: 'avatar',
+ dataIndex: 'avatar',
+ width: 48,
+ className: styles.avatarcolumn,
+ render: text => (
+
+ ),
+ },
+ {
+ title: 'content',
+ dataIndex: 'content',
+ render: (text, it) => (
+
+
{it.name}
+
{it.content}
+
+ {status[it.status].text}
+ {it.date}
+
+
+ ),
+ },
+ ]
+ return (
+
+
key < 3)}
+ />
+
+ )
+}
+
+Comments.propTypes = {
+ data: PropTypes.array,
+}
+
+export default Comments
diff --git a/src/pages/dashboard/components/comments.less b/src/pages/dashboard/components/comments.less
new file mode 100644
index 0000000..98cbeaf
--- /dev/null
+++ b/src/pages/dashboard/components/comments.less
@@ -0,0 +1,43 @@
+@import '~themes/vars';
+
+.comments {
+ :global .ant-table-thead > tr > th {
+ background: #fff;
+ border-bottom: solid 1px @border-color-base;
+ }
+
+ .avatar {
+ width: 48px;
+ height: 48px;
+ background-position: center;
+ background-size: cover;
+ border-radius: 50%;
+ background: #f8f8f8;
+ display: inline-block;
+ }
+
+ .content {
+ text-align: left;
+ color: #757575;
+ }
+
+ .date {
+ color: #a3a3a3;
+ line-height: 30px;
+ }
+
+ .daterow {
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .name {
+ font-size: 14px;
+ color: #474747;
+ text-align: left;
+ }
+
+ .avatarcolumn {
+ vertical-align: top;
+ }
+}
diff --git a/src/pages/dashboard/components/completed.js b/src/pages/dashboard/components/completed.js
new file mode 100644
index 0000000..02ad904
--- /dev/null
+++ b/src/pages/dashboard/components/completed.js
@@ -0,0 +1,109 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+import { Color } from 'utils'
+import {
+ AreaChart,
+ Area,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+ ResponsiveContainer,
+} from 'recharts'
+import styles from './completed.less'
+
+function Completed({ data }) {
+ return (
+
+
TEAM TOTAL COMPLETED
+
+
+ {
+ const { payload } = prop
+ return (
+
+ {payload.map((item, key) => (
+
+
+ {item.value}
+
+ ))}
+
+ )
+ }}
+ />
+
+
+
+ {
+ const list = content.payload.map((item, key) => (
+
+
+ {`${item.name}:${item.value}`}
+
+ ))
+ return (
+
+
{content.label}
+ {content.payload &&
}
+
+ )
+ }}
+ />
+
+
+
+
+
+ )
+}
+
+Completed.propTypes = {
+ data: PropTypes.array,
+}
+
+export default Completed
diff --git a/src/pages/dashboard/components/completed.less b/src/pages/dashboard/components/completed.less
new file mode 100644
index 0000000..b334092
--- /dev/null
+++ b/src/pages/dashboard/components/completed.less
@@ -0,0 +1,49 @@
+@import '~themes/vars';
+
+.sales {
+ .title {
+ margin-left: 32px;
+ font-size: 16px;
+ }
+}
+
+.radiusdot {
+ width: 12px;
+ height: 12px;
+ margin-right: 8px;
+ border-radius: 50%;
+ display: inline-block;
+}
+
+.legend {
+ text-align: right;
+ color: #999;
+ font-size: 14px;
+
+ li {
+ height: 48px;
+ line-height: 48px;
+ display: inline-block;
+
+ & + li {
+ margin-left: 24px;
+ }
+ }
+}
+
+.tooltip {
+ background: #fff;
+ padding: 20px;
+ font-size: 14px;
+
+ .tiptitle {
+ font-weight: 700;
+ font-size: 16px;
+ margin-bottom: 8px;
+ }
+
+ .tipitem {
+ height: 32px;
+ line-height: 32px;
+ }
+}
diff --git a/src/pages/dashboard/components/cpu.js b/src/pages/dashboard/components/cpu.js
new file mode 100644
index 0000000..3561555
--- /dev/null
+++ b/src/pages/dashboard/components/cpu.js
@@ -0,0 +1,79 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Color } from 'utils'
+import CountUp from 'react-countup'
+import {
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ ResponsiveContainer,
+} from 'recharts'
+import styles from './cpu.less'
+
+const countUpProps = {
+ start: 0,
+ duration: 2.75,
+ useEasing: true,
+ useGrouping: true,
+ separator: ',',
+}
+
+function Cpu({ usage = 0, space = 0, cpu = 0, data }) {
+ return (
+
+ )
+}
+
+Cpu.propTypes = {
+ data: PropTypes.array,
+ usage: PropTypes.number,
+ space: PropTypes.number,
+ cpu: PropTypes.number,
+}
+
+export default Cpu
diff --git a/src/pages/dashboard/components/cpu.less b/src/pages/dashboard/components/cpu.less
new file mode 100644
index 0000000..d23163b
--- /dev/null
+++ b/src/pages/dashboard/components/cpu.less
@@ -0,0 +1,40 @@
+.cpu {
+ .number {
+ display: flex;
+ height: 64px;
+ justify-content: space-between;
+ margin-bottom: 32px;
+
+ .item {
+ text-align: center;
+ height: 64px;
+ width: 100%;
+ position: relative;
+
+ & + .item {
+ &::before {
+ content: '';
+ display: block;
+ width: 1px;
+ height: 40px;
+ position: absolute;
+ background: #f5f5f5;
+ top: 12px;
+ }
+ }
+
+ p {
+ color: #757575;
+
+ &:first-child {
+ font-size: 16px;
+ }
+
+ &:last-child {
+ font-size: 20px;
+ font-weight: 700;
+ }
+ }
+ }
+ }
+}
diff --git a/src/pages/dashboard/components/index.js b/src/pages/dashboard/components/index.js
new file mode 100644
index 0000000..a3d2993
--- /dev/null
+++ b/src/pages/dashboard/components/index.js
@@ -0,0 +1,23 @@
+import NumberCard from './numberCard'
+import Quote from './quote'
+import Sales from './sales'
+import Weather from './weather'
+import RecentSales from './recentSales'
+import Comments from './comments'
+import Completed from './completed'
+import Browser from './browser'
+import Cpu from './cpu'
+import User from './user'
+
+export {
+ NumberCard,
+ Quote,
+ Sales,
+ Weather,
+ RecentSales,
+ Comments,
+ Completed,
+ Browser,
+ Cpu,
+ User,
+}
diff --git a/src/pages/dashboard/components/numberCard.js b/src/pages/dashboard/components/numberCard.js
new file mode 100644
index 0000000..dbab616
--- /dev/null
+++ b/src/pages/dashboard/components/numberCard.js
@@ -0,0 +1,45 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Card } from 'antd'
+import CountUp from 'react-countup'
+import iconMap from 'utils/iconMap'
+import styles from './numberCard.less'
+
+
+function NumberCard({ icon, color, title, number, countUp }) {
+ return (
+
+
+ {iconMap[icon]}
+
+
+
{title || 'No Title'}
+
+
+
+
+
+ )
+}
+
+NumberCard.propTypes = {
+ icon: PropTypes.string,
+ color: PropTypes.string,
+ title: PropTypes.string,
+ number: PropTypes.number,
+ countUp: PropTypes.object,
+}
+
+export default NumberCard
diff --git a/src/pages/dashboard/components/numberCard.less b/src/pages/dashboard/components/numberCard.less
new file mode 100644
index 0000000..237d3bf
--- /dev/null
+++ b/src/pages/dashboard/components/numberCard.less
@@ -0,0 +1,33 @@
+@import '~themes/vars';
+
+.numberCard {
+ padding: 32px;
+ margin-bottom: 24px;
+ cursor: pointer;
+
+ .iconWarp {
+ font-size: 54px;
+ float: left;
+ }
+
+ .content {
+ width: 100%;
+ padding-left: 78px;
+
+ .title {
+ line-height: 16px;
+ font-size: 16px;
+ margin-bottom: 8px;
+ height: 16px;
+ .text-overflow();
+ }
+
+ .number {
+ line-height: 32px;
+ font-size: 24px;
+ height: 32px;
+ .text-overflow();
+ margin-bottom: 0;
+ }
+ }
+}
diff --git a/src/pages/dashboard/components/quote.js b/src/pages/dashboard/components/quote.js
new file mode 100644
index 0000000..751a65d
--- /dev/null
+++ b/src/pages/dashboard/components/quote.js
@@ -0,0 +1,30 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './quote.less'
+
+function Quote({ name, content, title, avatar }) {
+ return (
+
+ )
+}
+
+Quote.propTypes = {
+ name: PropTypes.string,
+ content: PropTypes.string,
+ title: PropTypes.string,
+ avatar: PropTypes.string,
+}
+
+export default Quote
diff --git a/src/pages/dashboard/components/quote.less b/src/pages/dashboard/components/quote.less
new file mode 100644
index 0000000..18e8d92
--- /dev/null
+++ b/src/pages/dashboard/components/quote.less
@@ -0,0 +1,52 @@
+@import '~themes/vars';
+
+.quote {
+ color: #fff;
+ height: 100%;
+ width: 100%;
+ padding: 24px;
+ font-size: 16px;
+ font-weight: 700;
+
+ .inner {
+ text-overflow: ellipsis;
+ word-wrap: normal;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 4;
+ overflow: hidden;
+ text-indent: 24px;
+ }
+
+ .footer {
+ position: relative;
+ margin-top: 14px;
+
+ .description {
+ width: 100%;
+
+ p {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 64px;
+ text-align: right;
+
+ &:last-child {
+ font-weight: 100;
+ }
+ }
+ }
+
+ .avatar {
+ width: 48px;
+ height: 48px;
+ background-position: center;
+ background-size: cover;
+ border-radius: 50%;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
+}
diff --git a/src/pages/dashboard/components/recentSales.js b/src/pages/dashboard/components/recentSales.js
new file mode 100644
index 0000000..01907dc
--- /dev/null
+++ b/src/pages/dashboard/components/recentSales.js
@@ -0,0 +1,67 @@
+import React from 'react'
+import moment from 'moment'
+import PropTypes from 'prop-types'
+import { Table, Tag } from 'antd'
+import { Color } from 'utils'
+import styles from './recentSales.less'
+
+const status = {
+ 1: {
+ color: Color.green,
+ text: 'SALE',
+ },
+ 2: {
+ color: Color.yellow,
+ text: 'REJECT',
+ },
+ 3: {
+ color: Color.red,
+ text: 'TAX',
+ },
+ 4: {
+ color: Color.blue,
+ text: 'EXTENDED',
+ },
+}
+
+function RecentSales({ data }) {
+ const columns = [
+ {
+ title: 'NAME',
+ dataIndex: 'name',
+ },
+ {
+ title: 'STATUS',
+ dataIndex: 'status',
+ render: text => {status[text].text} ,
+ },
+ {
+ title: 'DATE',
+ dataIndex: 'date',
+ render: text => moment(text).format('YYYY-MM-DD'),
+ },
+ {
+ title: 'PRICE',
+ dataIndex: 'price',
+ render: (text, it) => (
+ ${text}
+ ),
+ },
+ ]
+ return (
+
+
key < 5)}
+ />
+
+ )
+}
+
+RecentSales.propTypes = {
+ data: PropTypes.array,
+}
+
+export default RecentSales
diff --git a/src/pages/dashboard/components/recentSales.less b/src/pages/dashboard/components/recentSales.less
new file mode 100644
index 0000000..9fcb7a2
--- /dev/null
+++ b/src/pages/dashboard/components/recentSales.less
@@ -0,0 +1,8 @@
+@import '~themes/vars';
+
+.recentsales {
+ :global .ant-table-thead > tr > th {
+ background: #fff;
+ border-bottom: solid 1px @border-color-base;
+ }
+}
diff --git a/src/pages/dashboard/components/sales.js b/src/pages/dashboard/components/sales.js
new file mode 100644
index 0000000..0c6e78d
--- /dev/null
+++ b/src/pages/dashboard/components/sales.js
@@ -0,0 +1,115 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+import { Color } from 'utils'
+import {
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+ ResponsiveContainer,
+} from 'recharts'
+import styles from './sales.less'
+
+function Sales({ data }) {
+ return (
+
+
Yearly Sales
+
+
+ {
+ const { payload } = prop
+ return (
+
+ {payload.map((item, key) => (
+
+
+ {item.value}
+
+ ))}
+
+ )
+ }}
+ />
+
+
+
+ {
+ const list = content.payload.map((item, key) => (
+
+
+ {`${item.name}:${item.value}`}
+
+ ))
+ return (
+
+
{content.label}
+ {content.payload &&
}
+
+ )
+ }}
+ />
+
+
+
+
+
+
+ )
+}
+
+Sales.propTypes = {
+ data: PropTypes.array,
+}
+
+export default Sales
diff --git a/src/pages/dashboard/components/sales.less b/src/pages/dashboard/components/sales.less
new file mode 100644
index 0000000..6d07f21
--- /dev/null
+++ b/src/pages/dashboard/components/sales.less
@@ -0,0 +1,50 @@
+@import '~themes/vars';
+
+.sales {
+ overflow: hidden;
+ .title {
+ margin-left: 32px;
+ font-size: 16px;
+ }
+}
+
+.radiusdot {
+ width: 12px;
+ height: 12px;
+ margin-right: 8px;
+ border-radius: 50%;
+ display: inline-block;
+}
+
+.legend {
+ text-align: right;
+ color: #999;
+ font-size: 14px;
+
+ li {
+ height: 48px;
+ line-height: 48px;
+ display: inline-block;
+
+ & + li {
+ margin-left: 24px;
+ }
+ }
+}
+
+.tooltip {
+ background: #fff;
+ padding: 20px;
+ font-size: 14px;
+
+ .tiptitle {
+ font-weight: 700;
+ font-size: 16px;
+ margin-bottom: 8px;
+ }
+
+ .tipitem {
+ height: 32px;
+ line-height: 32px;
+ }
+}
diff --git a/src/pages/dashboard/components/user-background.png b/src/pages/dashboard/components/user-background.png
new file mode 100644
index 0000000..5f99e13
Binary files /dev/null and b/src/pages/dashboard/components/user-background.png differ
diff --git a/src/pages/dashboard/components/user.js b/src/pages/dashboard/components/user.js
new file mode 100644
index 0000000..c988487
--- /dev/null
+++ b/src/pages/dashboard/components/user.js
@@ -0,0 +1,55 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Button, Avatar } from 'antd'
+import CountUp from 'react-countup'
+import { Color } from 'utils'
+import styles from './user.less'
+
+const countUpProps = {
+ start: 0,
+ duration: 2.75,
+ useEasing: true,
+ useGrouping: true,
+ separator: ',',
+}
+
+function User({ avatar, username, sales = 0, sold = 0 }) {
+ return (
+
+
+
+
+
+ View Profile
+
+
+
+ )
+}
+
+User.propTypes = {
+ avatar: PropTypes.string,
+ username: PropTypes.string,
+ sales: PropTypes.number,
+ sold: PropTypes.number,
+}
+
+export default User
diff --git a/src/pages/dashboard/components/user.less b/src/pages/dashboard/components/user.less
new file mode 100644
index 0000000..2babcc7
--- /dev/null
+++ b/src/pages/dashboard/components/user.less
@@ -0,0 +1,88 @@
+@import '~themes/vars';
+
+.user {
+ .header {
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ color: #fff;
+ height: 200px;
+ background-size: cover;
+ align-items: center;
+
+ .headerinner {
+ z-index: 2;
+ }
+
+ &::after {
+ content: '';
+ background-image: url('./user-background.png');
+ background-size: cover;
+ position: absolute;
+ width: 100%;
+ height: 200px;
+ left: 0;
+ top: 0;
+ opacity: 0.4;
+ z-index: 1;
+ }
+
+ .name {
+ font-size: 16px;
+ margin-top: 8px;
+ }
+ }
+
+ .number {
+ display: flex;
+ height: 116px;
+ justify-content: space-between;
+ border-bottom: solid 1px #f5f5f5;
+
+ .item {
+ text-align: center;
+ height: 116px;
+ width: 100%;
+ position: relative;
+ padding: 30px 0;
+
+ & + .item {
+ &::before {
+ content: '';
+ display: block;
+ width: 1px;
+ height: 116px;
+ position: absolute;
+ background: #f5f5f5;
+ top: 0;
+ }
+ }
+
+ p {
+ color: #757575;
+
+ &:first-child {
+ font-size: 16px;
+ }
+
+ &:last-child {
+ font-size: 20px;
+ font-weight: 700;
+ }
+ }
+ }
+ }
+
+ .footer {
+ height: 116px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ :global .ant-btn {
+ color: @purple;
+ border-color: @purple;
+ padding: 6px 16px;
+ }
+ }
+}
diff --git a/src/pages/dashboard/components/weather.js b/src/pages/dashboard/components/weather.js
new file mode 100644
index 0000000..2cc8d31
--- /dev/null
+++ b/src/pages/dashboard/components/weather.js
@@ -0,0 +1,39 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Spin } from 'antd'
+import styles from './weather.less'
+
+function Weather({ city, icon, dateTime, temperature, name, loading }) {
+ return (
+
+
+
+
+
{`${temperature}°`}
+
+ {city},{dateTime}
+
+
+
+
+ )
+}
+
+Weather.propTypes = {
+ city: PropTypes.string,
+ icon: PropTypes.string,
+ dateTime: PropTypes.string,
+ temperature: PropTypes.string,
+ name: PropTypes.string,
+ loading: PropTypes.bool,
+}
+
+export default Weather
diff --git a/src/pages/dashboard/components/weather.less b/src/pages/dashboard/components/weather.less
new file mode 100644
index 0000000..a3f0e5b
--- /dev/null
+++ b/src/pages/dashboard/components/weather.less
@@ -0,0 +1,48 @@
+@import '~themes/vars';
+
+.weather {
+ color: #fff;
+ height: 204px;
+ padding: 24px;
+ justify-content: space-between;
+ display: flex;
+ font-size: 14px;
+
+ .left {
+ display: flex;
+ flex-direction: column;
+ width: 64px;
+ padding-top: 55px;
+
+ .icon {
+ width: 64px;
+ height: 64px;
+ background-position: center;
+ background-size: contain;
+ }
+
+ p {
+ margin-top: 16px;
+ }
+ }
+
+ .right {
+ display: flex;
+ flex-direction: column;
+ width: 50%;
+
+ .temperature {
+ font-size: 36px;
+ text-align: right;
+ height: 64px;
+ color: #fff;
+ }
+
+ .description {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ text-align: right;
+ }
+ }
+}
diff --git a/src/pages/dashboard/index.js b/src/pages/dashboard/index.js
new file mode 100644
index 0000000..0fbc129
--- /dev/null
+++ b/src/pages/dashboard/index.js
@@ -0,0 +1,162 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Row, Col, Card } from 'antd'
+import { Color } from 'utils'
+import { Page, ScrollBar } from 'components'
+import {
+ NumberCard,
+ Quote,
+ Sales,
+ Weather,
+ RecentSales,
+ Comments,
+ Completed,
+ Browser,
+ Cpu,
+ User,
+} from './components'
+import styles from './index.less'
+import store from 'store'
+
+const bodyStyle = {
+ bodyStyle: {
+ height: 432,
+ background: '#fff',
+ },
+}
+
+@connect(({ app, dashboard, loading }) => ({
+ dashboard,
+ loading,
+}))
+class Dashboard extends PureComponent {
+ render() {
+ const userDetail = store.get('user')
+ const { avatar, username } = userDetail
+ const { dashboard, loading } = this.props
+ const {
+ weather,
+ sales,
+ quote,
+ numbers,
+ recentSales,
+ comments,
+ completed,
+ browser,
+ cpu,
+ user,
+ } = dashboard
+
+ const numberCards = numbers.map((item, key) => (
+
+
+
+ ))
+
+ return (
+
+
+ {numberCards}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+Dashboard.propTypes = {
+ dashboard: PropTypes.object,
+ loading: PropTypes.object,
+}
+
+export default Dashboard
diff --git a/src/pages/dashboard/index.less b/src/pages/dashboard/index.less
new file mode 100644
index 0000000..596b1c4
--- /dev/null
+++ b/src/pages/dashboard/index.less
@@ -0,0 +1,27 @@
+.dashboard {
+ position: relative;
+ :global {
+ .ant-card {
+ border-radius: 0;
+ margin-bottom: 24px;
+ &:hover {
+ box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
+ }
+ }
+ .ant-card-body {
+ overflow-x: hidden;
+ }
+ }
+
+ .weather {
+ &:hover {
+ box-shadow: 4px 4px 40px rgba(143, 201, 251, 0.6);
+ }
+ }
+
+ .quote {
+ &:hover {
+ box-shadow: 4px 4px 40px rgba(246, 152, 153, 0.6);
+ }
+ }
+}
diff --git a/src/pages/dashboard/model.js b/src/pages/dashboard/model.js
new file mode 100644
index 0000000..19ae6a6
--- /dev/null
+++ b/src/pages/dashboard/model.js
@@ -0,0 +1,75 @@
+import { parse } from 'qs'
+import modelExtend from 'dva-model-extend'
+import api from 'api'
+const { pathToRegexp } = require("path-to-regexp")
+import { model } from 'utils/model'
+
+const { queryDashboard, queryWeather } = api
+const avatar = '//cdn.antd-admin.zuiidea.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236.jpeg'
+
+export default modelExtend(model, {
+ namespace: 'dashboard',
+ state: {
+ weather: {
+ city: '深圳',
+ temperature: '30',
+ name: '晴',
+ icon: '//cdn.antd-admin.zuiidea.com/sun.png',
+ },
+ sales: [],
+ quote: {
+ avatar,
+ },
+ numbers: [],
+ recentSales: [],
+ comments: [],
+ completed: [],
+ browser: [],
+ cpu: {},
+ user: {
+ avatar,
+ },
+ },
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(({ pathname }) => {
+ if (
+ pathToRegexp('/dashboard').exec(pathname) ||
+ pathToRegexp('/').exec(pathname)
+ ) {
+ dispatch({ type: 'query' })
+ dispatch({ type: 'queryWeather' })
+ }
+ })
+ },
+ },
+ effects: {
+ *query({ payload }, { call, put }) {
+ const data = yield call(queryDashboard, parse(payload))
+ yield put({
+ type: 'updateState',
+ payload: data,
+ })
+ },
+ *queryWeather({ payload = {} }, { call, put }) {
+ payload.location = 'shenzhen'
+ const result = yield call(queryWeather, payload)
+ const { success } = result
+ if (success) {
+ const data = result.results[0]
+ const weather = {
+ city: data.location.name,
+ temperature: data.now.temperature,
+ name: data.now.text,
+ icon: `//cdn.antd-admin.zuiidea.com/web/icons/3d_50/${data.now.code}.png`,
+ }
+ yield put({
+ type: 'updateState',
+ payload: {
+ weather,
+ },
+ })
+ }
+ },
+ },
+})
diff --git a/src/pages/dashboard/services/dashboard.js b/src/pages/dashboard/services/dashboard.js
new file mode 100644
index 0000000..71e9470
--- /dev/null
+++ b/src/pages/dashboard/services/dashboard.js
@@ -0,0 +1,12 @@
+import { request, config } from 'utils'
+
+const { api } = config
+const { dashboard } = api
+
+export function query(params) {
+ return request({
+ url: dashboard,
+ method: 'get',
+ data: params,
+ })
+}
diff --git a/src/pages/dashboard/services/weather.js b/src/pages/dashboard/services/weather.js
new file mode 100644
index 0000000..a87179e
--- /dev/null
+++ b/src/pages/dashboard/services/weather.js
@@ -0,0 +1,12 @@
+import { request, config } from 'utils'
+
+const { APIV1 } = config
+
+export function query(params) {
+ params.key = 'i7sau1babuzwhycn'
+ return request({
+ url: `${APIV1}/weather/now.json`,
+ method: 'get',
+ data: params,
+ })
+}
diff --git a/src/pages/editor/index.js b/src/pages/editor/index.js
new file mode 100644
index 0000000..f65bb6a
--- /dev/null
+++ b/src/pages/editor/index.js
@@ -0,0 +1,105 @@
+import { Component } from 'react'
+import { Editor, Page } from 'components'
+import { convertToRaw } from 'draft-js'
+import { Row, Col, Card } from 'antd'
+import draftToHtml from 'draftjs-to-html'
+import draftToMarkdown from 'draftjs-to-markdown'
+
+export default class EditorPage extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ editorContent: null,
+ }
+ }
+
+ onEditorStateChange = editorContent => {
+ this.setState({
+ editorContent,
+ })
+ }
+
+ render() {
+ const { editorContent } = this.state
+ const colProps = {
+ lg: 12,
+ md: 24,
+ style: {
+ marginBottom: 32,
+ }
+ }
+ const textareaStyle = {
+ minHeight: 496,
+ width: '100%',
+ background: '#f7f7f7',
+ borderColor: '#F1F1F1',
+ padding: '16px 8px'
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/src/pages/index.js b/src/pages/index.js
new file mode 100644
index 0000000..346f576
--- /dev/null
+++ b/src/pages/index.js
@@ -0,0 +1,11 @@
+import React, { PureComponent } from 'react'
+import { Redirect } from 'umi'
+import { t } from "@lingui/macro"
+
+class Index extends PureComponent {
+ render() {
+ return
+ }
+}
+
+export default Index
diff --git a/src/pages/login/index.js b/src/pages/login/index.js
new file mode 100644
index 0000000..bcb6c3a
--- /dev/null
+++ b/src/pages/login/index.js
@@ -0,0 +1,90 @@
+import React, { PureComponent, Fragment } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Button, Row, Input, Form } from 'antd'
+import { GlobalFooter } from 'components'
+import { GithubOutlined } from '@ant-design/icons'
+import { t, Trans } from "@lingui/macro"
+import { setLocale } from 'utils'
+import config from 'utils/config'
+
+import styles from './index.less'
+
+const FormItem = Form.Item
+
+@connect(({ loading, dispatch }) => ({ loading, dispatch }))
+class Login extends PureComponent {
+
+ render() {
+ const { dispatch, loading } = this.props
+
+ const handleOk = values => {
+ dispatch({ type: 'login/login', payload: values })
+ }
+ let footerLinks = [
+ {
+ key: 'github',
+ title: ,
+ href: 'https://github.com/zuiidea/antd-admin',
+ blankTarget: true,
+ },
+ ]
+
+ if (config.i18n) {
+ footerLinks = footerLinks.concat(
+ config.i18n.languages.map(item => ({
+ key: item.key,
+ title: (
+ {item.title}
+ ),
+ }))
+ )
+ }
+
+ return (
+
+
+
+
+
{config.siteName}
+
+
+
+
+
+
+
+ )
+ }
+}
+
+Login.propTypes = {
+ form: PropTypes.object,
+ dispatch: PropTypes.func,
+ loading: PropTypes.object,
+}
+
+export default Login
diff --git a/src/pages/login/index.less b/src/pages/login/index.less
new file mode 100644
index 0000000..d7642d6
--- /dev/null
+++ b/src/pages/login/index.less
@@ -0,0 +1,60 @@
+@import '~themes/vars';
+
+.form {
+ position: absolute;
+ top: 45%;
+ left: 50%;
+ margin: -160px 0 0 -160px;
+ width: 320px;
+ height: 320px;
+ padding: 36px;
+ box-shadow: 0 0 100px rgba(0, 0, 0, 0.08);
+
+ button {
+ width: 100%;
+ }
+
+ p {
+ color: rgb(204, 204, 204);
+ text-align: center;
+ margin-top: 16px;
+ font-size: 12px;
+ display: flex;
+ justify-content: space-between;
+ }
+}
+
+.logo {
+ text-align: center;
+ cursor: pointer;
+ margin-bottom: 24px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ img {
+ width: 40px;
+ margin-right: 8px;
+ }
+
+ span {
+ vertical-align: text-bottom;
+ font-size: 16px;
+ text-transform: uppercase;
+ display: inline-block;
+ font-weight: 700;
+ color: @primary-color;
+ .text-gradient();
+ }
+}
+
+.ant-spin-container,
+.ant-spin-nested-loading {
+ height: 100%;
+}
+
+.footer {
+ position: absolute;
+ width: 100%;
+ bottom: 0;
+}
diff --git a/src/pages/login/model.js b/src/pages/login/model.js
new file mode 100644
index 0000000..4f2b2a0
--- /dev/null
+++ b/src/pages/login/model.js
@@ -0,0 +1,39 @@
+import { history } from 'umi'
+const { pathToRegexp } = require("path-to-regexp")
+import api from 'api'
+import store from 'store'
+
+const { loginUser } = api
+
+export default {
+ namespace: 'login',
+
+ state: {},
+ // subscriptions: {
+ // setup({ dispatch, history }) {
+ // history.listen(location => {
+ // if (pathToRegexp('/login').exec(location.pathname)) {
+ // }
+ // })
+ // },
+ // },
+ effects: {
+ *login({ payload }, { put, call, select }) {
+ const data = yield call(loginUser, payload)
+ const { locationQuery } = yield select(_ => _.app)
+ if (data.success) {
+ store.set('token', data.token);
+ const { from } = locationQuery
+ yield put({ type: 'app/query' })
+ if (!pathToRegexp('/login').exec(from)) {
+ if (['', '/'].includes(from)) history.push('/dashboard')
+ else history.push(from)
+ } else {
+ history.push('/dashboard')
+ }
+ } else {
+ throw data
+ }
+ },
+ },
+}
diff --git a/src/pages/org/[id]/index.js b/src/pages/org/[id]/index.js
new file mode 100644
index 0000000..65cc94e
--- /dev/null
+++ b/src/pages/org/[id]/index.js
@@ -0,0 +1,35 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Page } from 'components'
+import styles from './index.less'
+
+@connect(({ orgDetail }) => ({ orgDetail }))
+class OrgDetail extends PureComponent {
+ render() {
+ const { orgDetail } = this.props
+ const { data } = orgDetail
+ const content = []
+ for (let key in data) {
+ if ({}.hasOwnProperty.call(data, key)) {
+ content.push(
+
+
{key}
+
{String(data[key])}
+
+ )
+ }
+ }
+ return (
+
+ {content}
+
+ )
+ }
+}
+
+orgDetail.propTypes = {
+ orgDetail: PropTypes.object,
+}
+
+export default OrgDetail
diff --git a/src/pages/org/[id]/index.less b/src/pages/org/[id]/index.less
new file mode 100644
index 0000000..fa9c7d4
--- /dev/null
+++ b/src/pages/org/[id]/index.less
@@ -0,0 +1,14 @@
+.content {
+ line-height: 2.4;
+ font-size: 13px;
+
+ .item {
+ display: flex;
+
+ & > div {
+ &:first-child {
+ width: 100px;
+ }
+ }
+ }
+}
diff --git a/src/pages/org/[id]/models/detail.js b/src/pages/org/[id]/models/detail.js
new file mode 100644
index 0000000..b8f1d5f
--- /dev/null
+++ b/src/pages/org/[id]/models/detail.js
@@ -0,0 +1,50 @@
+const { pathToRegexp } = require("path-to-regexp")
+import api from 'api'
+
+const { queryOrg } = api
+
+export default {
+ namespace: 'orgDetail',
+
+ state: {
+ data: {},
+ },
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(({ pathname }) => {
+ const match = pathToRegexp('/org/:id').exec(pathname)
+ if (match) {
+ dispatch({ type: 'query', payload: { id: match[1] } })
+ }
+ })
+ },
+ },
+
+ effects: {
+ *query({ payload }, { call, put }) {
+ const data = yield call(queryOrg, payload)
+ const { success, message, status, ...other } = data
+ if (success) {
+ yield put({
+ type: 'querySuccess',
+ payload: {
+ data: other,
+ },
+ })
+ } else {
+ throw data
+ }
+ },
+ },
+
+ reducers: {
+ querySuccess(state, { payload }) {
+ const { data } = payload
+ return {
+ ...state,
+ data,
+ }
+ },
+ },
+}
diff --git a/src/pages/org/components/Filter.js b/src/pages/org/components/Filter.js
new file mode 100644
index 0000000..a1b9226
--- /dev/null
+++ b/src/pages/org/components/Filter.js
@@ -0,0 +1,143 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import moment from 'moment'
+import { FilterItem } from 'components'
+import { Trans } from "@lingui/macro"
+import { t } from "@lingui/macro"
+import { Button, Row, Col, DatePicker, Form, Input, Cascader } from 'antd'
+
+const { Search } = Input
+const { RangePicker } = DatePicker
+
+const ColProps = {
+ xs: 24,
+ sm: 12,
+ style: {
+ marginBottom: 16,
+ },
+}
+
+const TwoColProps = {
+ ...ColProps,
+ xl: 96,
+}
+
+class Filter extends Component {
+ formRef = React.createRef()
+
+ handleFields = fields => {
+ const { createTime } = fields
+ if (createTime && createTime.length) {
+ fields.createTime = [
+ moment(createTime[0]).format('YYYY-MM-DD'),
+ moment(createTime[1]).format('YYYY-MM-DD'),
+ ]
+ }
+ return fields
+ }
+
+ handleSubmit = () => {
+ const { onFilterChange } = this.props
+ const values = this.formRef.current.getFieldsValue()
+ const fields = this.handleFields(values)
+ onFilterChange(fields)
+ }
+
+ handleReset = () => {
+ const fields = this.formRef.current.getFieldsValue()
+ for (let item in fields) {
+ if ({}.hasOwnProperty.call(fields, item)) {
+ if (fields[item] instanceof Array) {
+ fields[item] = []
+ } else {
+ fields[item] = undefined
+ }
+ }
+ }
+ this.formRef.current.setFieldsValue(fields)
+ this.handleSubmit()
+ }
+ handleChange = (key, values) => {
+ const { onFilterChange } = this.props
+ let fields = this.formRef.current.getFieldsValue()
+ fields[key] = values
+ fields = this.handleFields(fields)
+ onFilterChange(fields)
+ }
+
+ render() {
+ const { onAdd, filter } = this.props
+ const { name, address } = filter
+
+ let initialCreateTime = []
+ if (filter.createTime && filter.createTime[0]) {
+ initialCreateTime[0] = moment(filter.createTime[0])
+ }
+ if (filter.createTime && filter.createTime[1]) {
+ initialCreateTime[1] = moment(filter.createTime[1])
+ }
+
+ return (
+
+ )
+ }
+}
+
+Filter.propTypes = {
+ onAdd: PropTypes.func,
+ filter: PropTypes.object,
+ onFilterChange: PropTypes.func,
+}
+
+export default Filter
diff --git a/src/pages/org/components/List.js b/src/pages/org/components/List.js
new file mode 100644
index 0000000..a2a8f1b
--- /dev/null
+++ b/src/pages/org/components/List.js
@@ -0,0 +1,113 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { Table, Modal, Avatar } from 'antd'
+import { DropOption } from 'components'
+import { t } from "@lingui/macro"
+import { Trans } from "@lingui/macro"
+import { Link } from 'umi'
+import styles from './List.less'
+
+const { confirm } = Modal
+
+class List extends PureComponent {
+ handleMenuClick = (record, e) => {
+ const { onDeleteItem, onEditItem } = this.props
+
+ if (e.key === '1') {
+ onEditItem(record)
+ } else if (e.key === '2') {
+ confirm({
+ title: t`Are you sure delete this record?`,
+ onOk() {
+ onDeleteItem(record.id)
+ },
+ })
+ }
+ }
+
+ render() {
+ const { onDeleteItem, onEditItem, ...tableProps } = this.props
+
+ const columns = [
+ {
+ title: Name ,
+ dataIndex: 'name',
+ key: 'name',
+ },
+ {
+ width: '22%',
+ title: OrgKey ,
+ dataIndex: 'orgkey',
+ key: 'orgkey',
+ },
+ {
+ title: Host ,
+ dataIndex: 'host',
+ key: 'host',
+ },
+ {
+ title: Status ,
+ dataIndex: 'status',
+ key: 'status',
+ width: '7%',
+ render: status => {status === 1 ? '正常' : '停用'} ,
+ },
+ {
+ title: CreateTime ,
+ dataIndex: 'create_time',
+ key: 'create_time',
+ },
+ {
+ title: OrgUsername ,
+ dataIndex: 'username',
+ key: 'username',
+ },
+ {
+ title: OrgMobile ,
+ dataIndex: 'mobile',
+ key: 'mobile',
+ },
+ {
+ title: Operation ,
+ key: 'operation',
+ fixed: 'right',
+ width: '8%',
+ render: (text, record) => {
+ return (
+ this.handleMenuClick(record, e)}
+ menuOptions={[
+ { key: '1', name: t`Update` },
+ { key: '2', name: t`Delete` },
+ ]}
+ />
+ )
+ },
+ },
+ ]
+
+ return (
+ t`Total ${total} Items`,
+ }}
+ className={styles.table}
+ bordered
+ scroll={{ x: 1200 }}
+ columns={columns}
+ simple
+ rowKey={record => record.id}
+ />
+ )
+ }
+}
+
+List.propTypes = {
+ onDeleteItem: PropTypes.func,
+ onEditItem: PropTypes.func,
+ location: PropTypes.object,
+}
+
+export default List
diff --git a/src/pages/org/components/List.less b/src/pages/org/components/List.less
new file mode 100644
index 0000000..6d35765
--- /dev/null
+++ b/src/pages/org/components/List.less
@@ -0,0 +1,7 @@
+.table {
+ :global {
+ .ant-table td {
+ white-space: nowrap;
+ }
+ }
+}
diff --git a/src/pages/org/components/Modal.js b/src/pages/org/components/Modal.js
new file mode 100644
index 0000000..3bd02d8
--- /dev/null
+++ b/src/pages/org/components/Modal.js
@@ -0,0 +1,82 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { Form, Input, Radio, Modal } from 'antd'
+import { Trans } from "@lingui/macro"
+import { t } from "@lingui/macro"
+
+const FormItem = Form.Item
+
+const formItemLayout = {
+ labelCol: {
+ span: 6,
+ },
+ wrapperCol: {
+ span: 14,
+ },
+}
+
+class OrgModal extends PureComponent {
+ formRef = React.createRef()
+
+ handleOk = () => {
+ const { item = {}, onOk } = this.props
+
+ this.formRef.current.validateFields()
+ .then(values => {
+ const data = {
+ ...values,
+ key: item.key,
+ }
+ onOk(data)
+ })
+ .catch(errorInfo => {
+ console.log(errorInfo)
+ })
+ }
+
+ render() {
+ const { item = {}, onOk, form, ...modalProps } = this.props
+
+ return (
+
+
+
+ )
+ }
+}
+
+OrgModal.propTypes = {
+ type: PropTypes.string,
+ item: PropTypes.object,
+ onOk: PropTypes.func,
+}
+
+export default OrgModal
diff --git a/src/pages/org/index.js b/src/pages/org/index.js
new file mode 100644
index 0000000..8e8aa98
--- /dev/null
+++ b/src/pages/org/index.js
@@ -0,0 +1,190 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { history } from 'umi'
+import { connect } from 'umi'
+import { Row, Col, Button, Popconfirm } from 'antd'
+import { t } from "@lingui/macro"
+import { Page } from 'components'
+import { stringify } from 'qs'
+import List from './components/List'
+import Filter from './components/Filter'
+import Modal from './components/Modal'
+
+@connect(({ org, loading }) => ({ org, loading }))
+class Org extends PureComponent {
+ handleRefresh = newQuery => {
+ const { location } = this.props
+ const { query, pathname } = location
+
+ history.push({
+ pathname,
+ search: stringify(
+ {
+ ...query,
+ ...newQuery,
+ },
+ { arrayFormat: 'repeat' }
+ ),
+ })
+ }
+
+ handleDeleteItems = () => {
+ const { dispatch, org } = this.props
+ const { list, pagination, selectedRowKeys } = org
+
+ dispatch({
+ type: 'org/multiDelete',
+ payload: {
+ ids: selectedRowKeys,
+ },
+ }).then(() => {
+ this.handleRefresh({
+ page:
+ list.length === selectedRowKeys.length && pagination.current > 1
+ ? pagination.current - 1
+ : pagination.current,
+ })
+ })
+ }
+
+ get modalProps() {
+ const { dispatch, org, loading } = this.props
+ const { currentItem, modalVisible, modalType } = org
+
+ return {
+ item: modalType === 'create' ? {} : currentItem,
+ visible: modalVisible,
+ destroyOnClose: true,
+ maskClosable: false,
+ confirmLoading: loading.effects[`org/${modalType}`],
+ title: `${modalType === 'create' ? t`Create Org` : t`Update Org`
+ }`,
+ centered: true,
+ onOk: data => {
+ dispatch({
+ type: `org/${modalType}`,
+ payload: data,
+ }).then(() => {
+ this.handleRefresh()
+ })
+ },
+ onCancel() {
+ dispatch({
+ type: 'org/hideModal',
+ })
+ },
+ }
+ }
+
+ get listProps() {
+ const { dispatch, org, loading } = this.props
+ const { list, pagination, selectedRowKeys } = org
+
+ return {
+ dataSource: list,
+ loading: loading.effects['org/query'],
+ pagination,
+ onChange: page => {
+ this.handleRefresh({
+ page: page.current,
+ pageSize: page.pageSize,
+ })
+ },
+ onDeleteItem: id => {
+ dispatch({
+ type: 'org/delete',
+ payload: id,
+ }).then(() => {
+ this.handleRefresh({
+ page:
+ list.length === 1 && pagination.current > 1
+ ? pagination.current - 1
+ : pagination.current,
+ })
+ })
+ },
+ onEditItem(item) {
+ dispatch({
+ type: 'org/showModal',
+ payload: {
+ modalType: 'update',
+ currentItem: item,
+ },
+ })
+ },
+ rowSelection: {
+ selectedRowKeys,
+ onChange: keys => {
+ dispatch({
+ type: 'org/updateState',
+ payload: {
+ selectedRowKeys: keys,
+ },
+ })
+ },
+ },
+ }
+ }
+
+ get filterProps() {
+ const { location, dispatch } = this.props
+ const { query } = location
+
+ return {
+ filter: {
+ ...query,
+ },
+ onFilterChange: value => {
+ this.handleRefresh({
+ ...value,
+ })
+ },
+ onAdd() {
+ dispatch({
+ type: 'org/showModal',
+ payload: {
+ modalType: 'create',
+ },
+ })
+ },
+ }
+ }
+
+ render() {
+ const { org } = this.props
+ const { selectedRowKeys } = org
+
+ return (
+
+
+ {selectedRowKeys.length > 0 && (
+
+
+ {`Selected ${selectedRowKeys.length} items `}
+
+
+ Remove
+
+
+
+
+ )}
+
+
+
+ )
+ }
+}
+
+Org.propTypes = {
+ org: PropTypes.object,
+ location: PropTypes.object,
+ dispatch: PropTypes.func,
+ loading: PropTypes.object,
+}
+
+export default Org
diff --git a/src/pages/org/model.js b/src/pages/org/model.js
new file mode 100644
index 0000000..5e76b58
--- /dev/null
+++ b/src/pages/org/model.js
@@ -0,0 +1,110 @@
+import modelExtend from 'dva-model-extend'
+const { pathToRegexp } = require("path-to-regexp")
+import api from 'api'
+import { pageModel } from 'utils/model'
+
+const {
+ queryOrgList,
+ updateOrg,
+ createOrg,
+ removeOrg,
+ removeOrgList
+} = api
+
+export default modelExtend(pageModel, {
+ namespace: 'org',
+
+ state: {
+ currentItem: {},
+ modalVisible: false,
+ modalType: 'create',
+ selectedRowKeys: [],
+ },
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(location => {
+ if (pathToRegexp('/org').exec(location.pathname)) {
+ const payload = location.query || { page: 1, pageSize: 10 }
+ dispatch({
+ type: 'query',
+ payload,
+ })
+ }
+ })
+ },
+ },
+
+ effects: {
+ *query({ payload = {} }, { call, put }) {
+ const data = yield call(queryOrgList, payload)
+ if (data) {
+ yield put({
+ type: 'querySuccess',
+ payload: {
+ list: data.data,
+ pagination: {
+ current: Number(payload.page) || 1,
+ pageSize: Number(payload.pageSize) || 10,
+ total: data.total,
+ },
+ },
+ })
+ }
+ },
+
+ *delete({ payload }, { call, put, select }) {
+ const data = yield call(removeOrg, { id: payload })
+ const { selectedRowKeys } = yield select(_ => _.org)
+ if (data.success) {
+ yield put({
+ type: 'updateState',
+ payload: {
+ selectedRowKeys: selectedRowKeys.filter(_ => _ !== payload),
+ },
+ })
+ } else {
+ throw data
+ }
+ },
+
+ *multiDelete({ payload }, { call, put }) {
+ const data = yield call(removeOrgList, payload)
+ if (data.success) {
+ yield put({ type: 'updateState', payload: { selectedRowKeys: [] } })
+ } else {
+ throw data
+ }
+ },
+
+ *create({ payload }, { call, put }) {
+ const data = yield call(createOrg, payload)
+ if (data.success) {
+ yield put({ type: 'hideModal' })
+ } else {
+ throw data
+ }
+ },
+
+ *update({ payload }, { select, call, put }) {
+ const id = yield select(({ org }) => org.currentItem.id)
+ const newOrg = { ...payload, id }
+ const data = yield call(updateOrg, newOrg)
+ if (data.success) {
+ yield put({ type: 'hideModal' })
+ } else {
+ throw data
+ }
+ },
+ },
+
+ reducers: {
+ showModal(state, { payload }) {
+ return { ...state, ...payload, modalVisible: true }
+ },
+
+ hideModal(state) {
+ return { ...state, modalVisible: false }
+ },
+ },
+})
diff --git a/src/pages/post/components/List.js b/src/pages/post/components/List.js
new file mode 100644
index 0000000..cde1d4a
--- /dev/null
+++ b/src/pages/post/components/List.js
@@ -0,0 +1,73 @@
+import React, { PureComponent } from 'react'
+import { Table, Avatar } from 'antd'
+import { t } from "@lingui/macro"
+import { Ellipsis } from 'components'
+import styles from './List.less'
+
+class List extends PureComponent {
+ render() {
+ const { ...tableProps } = this.props
+ const columns = [
+ {
+ title: t`Image`,
+ dataIndex: 'image',
+ render: text => ,
+ },
+ {
+ title: t`Title`,
+ dataIndex: 'title',
+ render: text => (
+
+ {text}
+
+ ),
+ },
+ {
+ title: t`Author`,
+ dataIndex: 'author',
+ },
+ {
+ title: t`Categories`,
+ dataIndex: 'categories',
+ },
+ {
+ title: t`Tags`,
+ dataIndex: 'tags',
+ },
+ {
+ title: t`Visibility`,
+ dataIndex: 'visibility',
+ },
+ {
+ title: t`Comments`,
+ dataIndex: 'comments',
+ },
+ {
+ title: t`Views`,
+ dataIndex: 'views',
+ },
+ {
+ title: t`Publish Date`,
+ dataIndex: 'date',
+ },
+ ]
+
+ return (
+ t`Total ${total} Items`,
+ }}
+ bordered
+ scroll={{ x: 1200 }}
+ className={styles.table}
+ columns={columns}
+ simple
+ rowKey={record => record.id}
+ />
+ )
+ }
+}
+
+export default List
diff --git a/src/pages/post/components/List.less b/src/pages/post/components/List.less
new file mode 100644
index 0000000..6d35765
--- /dev/null
+++ b/src/pages/post/components/List.less
@@ -0,0 +1,7 @@
+.table {
+ :global {
+ .ant-table td {
+ white-space: nowrap;
+ }
+ }
+}
diff --git a/src/pages/post/index.js b/src/pages/post/index.js
new file mode 100644
index 0000000..cd398f6
--- /dev/null
+++ b/src/pages/post/index.js
@@ -0,0 +1,92 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Tabs } from 'antd'
+import { history } from 'umi'
+import { stringify } from 'qs'
+import { t } from "@lingui/macro"
+import { Page } from 'components'
+import List from './components/List'
+
+const { TabPane } = Tabs
+
+const EnumPostStatus = {
+ UNPUBLISH: 1,
+ PUBLISHED: 2,
+}
+
+@connect(({ post, loading }) => ({ post, loading }))
+class Post extends PureComponent {
+ handleTabClick = key => {
+ const { pathname } = this.props.location
+
+ history.push({
+ pathname,
+ search: stringify({
+ status: key,
+ }),
+ })
+ }
+
+ get listProps() {
+ const { post, loading, location } = this.props
+ const { list, pagination } = post
+ const { query, pathname } = location
+
+ return {
+ pagination,
+ dataSource: list,
+ loading: loading.effects['post/query'],
+ onChange(page) {
+ history.push({
+ pathname,
+ search: stringify({
+ ...query,
+ page: page.current,
+ pageSize: page.pageSize,
+ }),
+ })
+ },
+ }
+ }
+
+ render() {
+ const { location } = this.props
+ const { query } = location
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+Post.propTypes = {
+ post: PropTypes.object,
+ loading: PropTypes.object,
+ location: PropTypes.object,
+ dispatch: PropTypes.func,
+}
+
+export default Post
diff --git a/src/pages/post/model.js b/src/pages/post/model.js
new file mode 100644
index 0000000..6a3ba7d
--- /dev/null
+++ b/src/pages/post/model.js
@@ -0,0 +1,47 @@
+import modelExtend from 'dva-model-extend'
+import api from 'api'
+const { pathToRegexp } = require("path-to-regexp")
+import { pageModel } from 'utils/model'
+
+const { queryPostList } = api
+
+export default modelExtend(pageModel, {
+ namespace: 'post',
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(location => {
+ if (pathToRegexp('/post').exec(location.pathname)) {
+ dispatch({
+ type: 'query',
+ payload: {
+ status: 2,
+ ...location.query,
+ },
+ })
+ }
+ })
+ },
+ },
+
+ effects: {
+ *query({ payload }, { call, put }) {
+ const data = yield call(queryPostList, payload)
+ if (data.success) {
+ yield put({
+ type: 'querySuccess',
+ payload: {
+ list: data.data,
+ pagination: {
+ current: Number(payload.page) || 1,
+ pageSize: Number(payload.pageSize) || 10,
+ total: data.total,
+ },
+ },
+ })
+ } else {
+ throw data
+ }
+ },
+ },
+})
diff --git a/src/pages/request/index.js b/src/pages/request/index.js
new file mode 100644
index 0000000..71c4d1c
--- /dev/null
+++ b/src/pages/request/index.js
@@ -0,0 +1,259 @@
+import React from 'react'
+import { request } from 'utils'
+import { apiPrefix } from 'utils/config'
+import { Row, Col, Select, Form, Input, Button, List, Tag, Checkbox } from 'antd'
+import classnames from 'classnames'
+import { CloseOutlined } from '@ant-design/icons'
+import { Trans } from "@lingui/macro"
+import api from '@/services/api'
+import { Page } from 'components'
+
+import styles from './index.less'
+
+const { Option } = Select
+const InputGroup = Input.Group
+const methods = ['POST', 'GET', 'PUT', 'PATCH', 'DELETE']
+
+const methodTagColor = {
+ GET: 'green',
+ POST: 'orange',
+ DELETE: 'red',
+ PUT: 'geekblue',
+}
+
+const requests = Object.values(api).map(item => {
+ let url = apiPrefix + item
+ let method = 'GET'
+ const paramsArray = item.split(' ')
+ if (paramsArray.length === 2) {
+ method = paramsArray[0]
+ url = apiPrefix + paramsArray[1]
+ }
+ return {
+ method,
+ url,
+ }
+})
+
+let uuid = 2
+class RequestPage extends React.Component {
+ formRef = React.createRef()
+ constructor(props) {
+ super(props)
+ this.state = {
+ method: 'GET',
+ url: '/api/v1/routes',
+ keys: [1],
+ result: null,
+ visible: true,
+ }
+ }
+
+ handleRequest = () => {
+ const { method, url } = this.state
+
+ this.formRef.current.validateFields()
+ .then(values => {
+ // values: { check[1]: true, key[1]: 'username', value[1]: 'admin' }
+
+ const params = {}
+ for (let i in values) {
+ if (i.startsWith('check')) {
+ const index = i.match(/check\[(\d+)\]/)[1]
+ const key = values[`key[${index}]`]
+ params[key] = values[`value[${index}]`]
+ }
+ }
+
+ request({ method, url, data: params }).then(data => {
+ this.setState({
+ result: JSON.stringify(data),
+ })
+ })
+ })
+ .catch(errorInfo => {
+ console.log("request error...")
+ console.log(errorInfo)
+ /*
+ errorInfo:
+ {
+ values: {
+ username: 'username',
+ password: 'password',
+ },
+ errorFields: [
+ { password: ['username'], errors: ['Please input your Password!'] },
+ ],
+ outOfDate: false,
+ }
+ */
+ })
+ }
+
+ handleClickListItem = ({ method, url }) => {
+ this.setState({
+ method,
+ url,
+ keys: [uuid++],
+ result: null,
+ })
+ }
+
+ handleInputChange = e => {
+ this.setState({
+ url: e.target.value,
+ })
+ }
+
+ handleSelectChange = method => {
+ this.setState({
+ method,
+ })
+ }
+
+ handleAddField = () => {
+ const { keys } = this.state
+ const nextKeys = keys.concat(uuid)
+ uuid++
+ this.setState({
+ keys: nextKeys,
+ })
+ }
+
+ handleRemoveField = key => {
+ const { keys } = this.state
+ this.setState({
+ keys: keys.filter(item => item !== key),
+ })
+ }
+
+ handleVisible = () => {
+ this.setState({
+ visible: !this.state.visible,
+ })
+ }
+
+ render() {
+ const { result, url, method, keys, visible } = this.state
+
+ return (
+
+
+
+ (
+
+
+
+ {item.method}
+
+
+ {item.url}
+
+ )}
+ />
+
+
+
+
+
+ {methods.map(item => (
+
+ {item}
+
+ ))}
+
+
+
+ Params
+
+
+
+
+ Send
+
+
+
+ {result}
+
+
+
+ )
+ }
+}
+
+export default RequestPage
diff --git a/src/pages/request/index.less b/src/pages/request/index.less
new file mode 100644
index 0000000..a878f39
--- /dev/null
+++ b/src/pages/request/index.less
@@ -0,0 +1,39 @@
+@import '~themes/vars';
+
+.result {
+ height: 600px;
+ width: 100%;
+ background: @hover-color;
+ border-color: #ddd;
+ padding: 16px;
+ margin-top: 16px;
+ word-break: break-word;
+ line-height: 2;
+ overflow: scroll;
+}
+
+.requestList {
+ padding-right: 24px;
+ margin-bottom: 24px;
+ .listItem {
+ cursor: pointer;
+ padding-left: 8px;
+ &.lstItemActive {
+ background-color: @hover-color;
+ }
+ .background-hover();
+ }
+}
+
+.paramsBlock {
+ overflow: visible;
+ opacity: 1;
+ height: auto;
+ transition: opacity 0.3s;
+ &.hideParams {
+ width: 0;
+ height: 0;
+ opacity: 0;
+ overflow: hidden;
+ }
+}
diff --git a/src/pages/user/[id]/index.js b/src/pages/user/[id]/index.js
new file mode 100644
index 0000000..5c7614c
--- /dev/null
+++ b/src/pages/user/[id]/index.js
@@ -0,0 +1,35 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'umi'
+import { Page } from 'components'
+import styles from './index.less'
+
+@connect(({ userDetail }) => ({ userDetail }))
+class UserDetail extends PureComponent {
+ render() {
+ const { userDetail } = this.props
+ const { data } = userDetail
+ const content = []
+ for (let key in data) {
+ if ({}.hasOwnProperty.call(data, key)) {
+ content.push(
+
+
{key}
+
{String(data[key])}
+
+ )
+ }
+ }
+ return (
+
+ {content}
+
+ )
+ }
+}
+
+UserDetail.propTypes = {
+ userDetail: PropTypes.object,
+}
+
+export default UserDetail
diff --git a/src/pages/user/[id]/index.less b/src/pages/user/[id]/index.less
new file mode 100644
index 0000000..fa9c7d4
--- /dev/null
+++ b/src/pages/user/[id]/index.less
@@ -0,0 +1,14 @@
+.content {
+ line-height: 2.4;
+ font-size: 13px;
+
+ .item {
+ display: flex;
+
+ & > div {
+ &:first-child {
+ width: 100px;
+ }
+ }
+ }
+}
diff --git a/src/pages/user/[id]/models/detail.js b/src/pages/user/[id]/models/detail.js
new file mode 100644
index 0000000..2f18531
--- /dev/null
+++ b/src/pages/user/[id]/models/detail.js
@@ -0,0 +1,50 @@
+const { pathToRegexp } = require("path-to-regexp")
+import api from 'api'
+
+const { queryUser } = api
+
+export default {
+ namespace: 'userDetail',
+
+ state: {
+ data: {},
+ },
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(({ pathname }) => {
+ const match = pathToRegexp('/user/:id').exec(pathname)
+ if (match) {
+ dispatch({ type: 'query', payload: { id: match[1] } })
+ }
+ })
+ },
+ },
+
+ effects: {
+ *query({ payload }, { call, put }) {
+ const data = yield call(queryUser, payload)
+ const { success, message, status, ...other } = data
+ if (success) {
+ yield put({
+ type: 'querySuccess',
+ payload: {
+ data: other,
+ },
+ })
+ } else {
+ throw data
+ }
+ },
+ },
+
+ reducers: {
+ querySuccess(state, { payload }) {
+ const { data } = payload
+ return {
+ ...state,
+ data,
+ }
+ },
+ },
+}
diff --git a/src/pages/user/components/Filter.js b/src/pages/user/components/Filter.js
new file mode 100644
index 0000000..5b14f0f
--- /dev/null
+++ b/src/pages/user/components/Filter.js
@@ -0,0 +1,141 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import moment from 'moment'
+import { FilterItem } from 'components'
+import { Trans } from "@lingui/macro"
+import { t } from "@lingui/macro"
+import { Button, Row, Col, DatePicker, Form, Input } from 'antd'
+
+const { Search } = Input
+const { RangePicker } = DatePicker
+
+const ColProps = {
+ xs: 24,
+ sm: 12,
+ style: {
+ marginBottom: 16,
+ },
+}
+
+const TwoColProps = {
+ ...ColProps,
+ xl: 96,
+}
+
+class Filter extends Component {
+ formRef = React.createRef()
+
+ handleFields = fields => {
+ const { lastLoginTime } = fields
+ if (lastLoginTime && lastLoginTime.length) {
+ fields.lastLoginTime = [
+ moment(lastLoginTime[0]).format('YYYY-MM-DD'),
+ moment(lastLoginTime[1]).format('YYYY-MM-DD'),
+ ]
+ }
+ return fields
+ }
+
+ handleSubmit = () => {
+ const { onFilterChange } = this.props
+ const values = this.formRef.current.getFieldsValue()
+ const fields = this.handleFields(values)
+ onFilterChange(fields)
+ }
+
+ handleReset = () => {
+ const fields = this.formRef.current.getFieldsValue()
+ for (let item in fields) {
+ if ({}.hasOwnProperty.call(fields, item)) {
+ if (fields[item] instanceof Array) {
+ fields[item] = []
+ } else {
+ fields[item] = undefined
+ }
+ }
+ }
+ this.formRef.current.setFieldsValue(fields)
+ this.handleSubmit()
+ }
+ handleChange = (key, values) => {
+ const { onFilterChange } = this.props
+ let fields = this.formRef.current.getFieldsValue()
+ fields[key] = values
+ fields = this.handleFields(fields)
+ onFilterChange(fields)
+ }
+
+ render() {
+ const { onAdd, filter } = this.props
+
+ let initialLastLoginTime = []
+ if (filter.lastLoginTime && filter.lastLoginTime[0]) {
+ initialLastLoginTime[0] = moment(filter.lastLoginTime[0])
+ }
+ if (filter.createTime && filter.lastLoginTime[1]) {
+ initialLastLoginTime[1] = moment(filter.lastLoginTime[1])
+ }
+
+ return (
+
+ )
+ }
+}
+
+Filter.propTypes = {
+ onAdd: PropTypes.func,
+ filter: PropTypes.object,
+ onFilterChange: PropTypes.func,
+}
+
+export default Filter
diff --git a/src/pages/user/components/List.js b/src/pages/user/components/List.js
new file mode 100644
index 0000000..b1b2cbf
--- /dev/null
+++ b/src/pages/user/components/List.js
@@ -0,0 +1,99 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { Table, Modal, Avatar } from 'antd'
+import { DropOption } from 'components'
+import { t } from "@lingui/macro"
+import { Trans } from "@lingui/macro"
+import { Link } from 'umi'
+import styles from './List.less'
+
+const { confirm } = Modal
+
+class List extends PureComponent {
+ handleMenuClick = (record, e) => {
+ const { onDeleteItem, onEditItem } = this.props
+
+ if (e.key === '1') {
+ onEditItem(record)
+ } else if (e.key === '2') {
+ confirm({
+ title: t`Are you sure delete this record?`,
+ onOk() {
+ onDeleteItem(record.id)
+ },
+ })
+ }
+ }
+
+ render() {
+ const { onDeleteItem, onEditItem, ...tableProps } = this.props
+
+ const columns = [
+ {
+ title: Avatar ,
+ dataIndex: 'avatar',
+ key: 'avatar',
+ width: '7%',
+ fixed: 'left',
+ render: text => ,
+ },
+ {
+ title: Name ,
+ dataIndex: 'username',
+ key: 'username',
+ render: (text, record) => {text},
+ },
+ {
+ title: NickName ,
+ dataIndex: 'nickname',
+ key: 'nickname',
+ },
+ {
+ title: LastLoginTime ,
+ dataIndex: 'last_login_time',
+ key: 'last_login_time',
+ },
+ {
+ title: Operation ,
+ key: 'operation',
+ fixed: 'right',
+ width: '8%',
+ render: (text, record) => {
+ return (
+ this.handleMenuClick(record, e)}
+ menuOptions={[
+ { key: '1', name: t`Update` },
+ { key: '2', name: t`Delete` },
+ ]}
+ />
+ )
+ },
+ },
+ ]
+
+ return (
+ t`Total ${total} Items`,
+ }}
+ className={styles.table}
+ bordered
+ scroll={{ x: 1200 }}
+ columns={columns}
+ simple
+ rowKey={record => record.id}
+ />
+ )
+ }
+}
+
+List.propTypes = {
+ onDeleteItem: PropTypes.func,
+ onEditItem: PropTypes.func,
+ location: PropTypes.object,
+}
+
+export default List
diff --git a/src/pages/user/components/List.less b/src/pages/user/components/List.less
new file mode 100644
index 0000000..6d35765
--- /dev/null
+++ b/src/pages/user/components/List.less
@@ -0,0 +1,7 @@
+.table {
+ :global {
+ .ant-table td {
+ white-space: nowrap;
+ }
+ }
+}
diff --git a/src/pages/user/components/Modal.js b/src/pages/user/components/Modal.js
new file mode 100644
index 0000000..639888a
--- /dev/null
+++ b/src/pages/user/components/Modal.js
@@ -0,0 +1,67 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { Form, Input, Modal } from 'antd'
+import { t } from "@lingui/macro"
+
+const FormItem = Form.Item
+
+const formItemLayout = {
+ labelCol: {
+ span: 6,
+ },
+ wrapperCol: {
+ span: 14,
+ },
+}
+
+class UserModal extends PureComponent {
+ formRef = React.createRef()
+
+ handleOk = () => {
+ const { item = {}, onOk } = this.props
+
+ this.formRef.current.validateFields()
+ .then(values => {
+ const data = {
+ ...values,
+ key: item.key,
+ }
+ onOk(data)
+ })
+ .catch(errorInfo => {
+ console.log(errorInfo)
+ })
+ }
+
+ render() {
+ const { item = {}, onOk, form, ...modalProps } = this.props
+
+ return (
+
+
+
+ )
+ }
+}
+
+UserModal.propTypes = {
+ type: PropTypes.string,
+ item: PropTypes.object,
+ onOk: PropTypes.func,
+}
+
+export default UserModal
diff --git a/src/pages/user/index.js b/src/pages/user/index.js
new file mode 100644
index 0000000..392b313
--- /dev/null
+++ b/src/pages/user/index.js
@@ -0,0 +1,199 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { history } from 'umi'
+import { connect } from 'umi'
+import { Row, Col, Button, Popconfirm } from 'antd'
+import { t } from "@lingui/macro"
+import { Page } from 'components'
+import { stringify } from 'qs'
+import List from './components/List'
+import Filter from './components/Filter'
+import Modal from './components/Modal'
+
+@connect(({ user, loading }) => ({ user, loading }))
+class User extends PureComponent {
+ handleRefresh = newQuery => {
+
+ const { location } = this.props
+ const { query, pathname } = location
+
+ console.log("string...",stringify(
+ {
+ ...query,
+ ...newQuery,
+ }))
+
+ history.push({
+ pathname,
+ search: stringify(
+ {
+ ...query,
+ ...newQuery,
+ },
+ { arrayFormat: 'repeat' }
+ ),
+ })
+ }
+
+ handleDeleteItems = () => {
+ const { dispatch, user } = this.props
+ const { list, pagination, selectedRowKeys } = user
+
+ dispatch({
+ type: 'user/multiDelete',
+ payload: {
+ ids: selectedRowKeys,
+ },
+ }).then(() => {
+ this.handleRefresh({
+ page:
+ list.length === selectedRowKeys.length && pagination.current > 1
+ ? pagination.current - 1
+ : pagination.current,
+ })
+ })
+ }
+
+ get modalProps() {
+ const { dispatch, user, loading } = this.props
+ const { currentItem, modalVisible, modalType } = user
+
+ return {
+ item: modalType === 'create' ? {} : currentItem,
+ visible: modalVisible,
+ destroyOnClose: true,
+ maskClosable: false,
+ confirmLoading: loading.effects[`user/${modalType}`],
+ title: `${modalType === 'create' ? t`Create User` : t`Update User`
+ }`,
+ centered: true,
+ onOk: data => {
+ dispatch({
+ type: `user/${modalType}`,
+ payload: data,
+ }).then(() => {
+ this.handleRefresh()
+ })
+ },
+ onCancel() {
+ dispatch({
+ type: 'user/hideModal',
+ })
+ },
+ }
+ }
+
+ get listProps() {
+ const { dispatch, user, loading } = this.props
+ const { list, pagination, selectedRowKeys } = user
+
+ return {
+ dataSource: list,
+ loading: loading.effects['user/query'],
+ pagination,
+ onChange: page => {
+ this.handleRefresh({
+ page: page.current,
+ pageSize: page.pageSize,
+ })
+ },
+ onDeleteItem: id => {
+ dispatch({
+ type: 'user/delete',
+ payload: id,
+ }).then(() => {
+ this.handleRefresh({
+ page:
+ list.length === 1 && pagination.current > 1
+ ? pagination.current - 1
+ : pagination.current,
+ })
+ })
+ },
+ onEditItem(item) {
+ dispatch({
+ type: 'user/showModal',
+ payload: {
+ modalType: 'update',
+ currentItem: item,
+ },
+ })
+ },
+ rowSelection: {
+ selectedRowKeys,
+ onChange: keys => {
+ dispatch({
+ type: 'user/updateState',
+ payload: {
+ selectedRowKeys: keys,
+ },
+ })
+ },
+ },
+ }
+ }
+
+ get filterProps() {
+ const { location, dispatch } = this.props
+ const { query } = location
+
+ return {
+ filter: {
+ ...query,
+ },
+ onFilterChange: value => {
+ this.handleRefresh({
+ ...value,
+ })
+ },
+ onAdd() {
+ dispatch({
+ type: 'user/showModal',
+ payload: {
+ modalType: 'create',
+ },
+ })
+ },
+ }
+ }
+
+ render() {
+ const { user } = this.props
+ const { selectedRowKeys } = user
+
+ console.log("this:", this);
+
+ return (
+
+
+ {selectedRowKeys.length > 0 && (
+
+
+ {`Selected ${selectedRowKeys.length} items `}
+
+
+ Remove
+
+
+
+
+ )}
+
+
+
+ )
+ }
+}
+
+User.propTypes = {
+ user: PropTypes.object,
+ location: PropTypes.object,
+ dispatch: PropTypes.func,
+ loading: PropTypes.object,
+}
+
+export default User
diff --git a/src/pages/user/model.js b/src/pages/user/model.js
new file mode 100644
index 0000000..cd7c8ce
--- /dev/null
+++ b/src/pages/user/model.js
@@ -0,0 +1,111 @@
+import modelExtend from 'dva-model-extend'
+const { pathToRegexp } = require("path-to-regexp")
+import api from 'api'
+import { pageModel } from 'utils/model'
+
+const {
+ queryUserList,
+ createUser,
+ removeUser,
+ updateUser,
+ removeUserList,
+} = api
+
+export default modelExtend(pageModel, {
+ namespace: 'user',
+
+ state: {
+ currentItem: {},
+ modalVisible: false,
+ modalType: 'create',
+ selectedRowKeys: [],
+ },
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ history.listen(location => {
+ if (pathToRegexp('/user').exec(location.pathname)) {
+ const payload = location.query || { page: 1, pageSize: 10 }
+ dispatch({
+ type: 'query',
+ payload,
+ })
+ }
+ })
+ },
+ },
+
+ effects: {
+ *query({ payload = {} }, { call, put }) {
+ console.log("palload: ", payload)
+ const data = yield call(queryUserList, payload)
+ if (data) {
+ yield put({
+ type: 'querySuccess',
+ payload: {
+ list: data.data,
+ pagination: {
+ current: Number(payload.page) || 1,
+ pageSize: Number(payload.pageSize) || 10,
+ total: data.total,
+ },
+ },
+ })
+ }
+ },
+
+ *delete({ payload }, { call, put, select }) {
+ const data = yield call(removeUser, { id: payload })
+ const { selectedRowKeys } = yield select(_ => _.user)
+ if (data.success) {
+ yield put({
+ type: 'updateState',
+ payload: {
+ selectedRowKeys: selectedRowKeys.filter(_ => _ !== payload),
+ },
+ })
+ } else {
+ throw data
+ }
+ },
+
+ *multiDelete({ payload }, { call, put }) {
+ const data = yield call(removeUserList, payload)
+ if (data.success) {
+ yield put({ type: 'updateState', payload: { selectedRowKeys: [] } })
+ } else {
+ throw data
+ }
+ },
+
+ *create({ payload }, { call, put }) {
+ const data = yield call(createUser, payload)
+ if (data.success) {
+ yield put({ type: 'hideModal' })
+ } else {
+ throw data
+ }
+ },
+
+ *update({ payload }, { select, call, put }) {
+ const id = yield select(({ user }) => user.currentItem.id)
+ const newUser = { ...payload, id }
+ const data = yield call(updateUser, newUser)
+ if (data.success) {
+ yield put({ type: 'hideModal' })
+ } else {
+ throw data
+ }
+ },
+ },
+
+ reducers: {
+ showModal(state, { payload }) {
+ return { ...state, ...payload, modalVisible: true }
+ },
+
+ hideModal(state) {
+ return { ...state, modalVisible: false }
+ },
+ },
+})
diff --git a/src/plugins/onError.js b/src/plugins/onError.js
new file mode 100644
index 0000000..d929ab9
--- /dev/null
+++ b/src/plugins/onError.js
@@ -0,0 +1,13 @@
+import { message } from 'antd'
+
+export default {
+ onError(e, a) {
+ e.preventDefault()
+ if (e.message) {
+ message.error(e.message)
+ } else {
+ /* eslint-disable */
+ console.error(e)
+ }
+ },
+}
diff --git a/src/services/api.js b/src/services/api.js
new file mode 100644
index 0000000..97ede5c
--- /dev/null
+++ b/src/services/api.js
@@ -0,0 +1,25 @@
+export default {
+ queryRouteList: '/routes',
+
+ queryUserInfo: '/user',
+ logoutUser: '/user/logout',
+ loginUser: 'POST /user/login',
+
+ queryUser: '/user/:id',
+ queryUserList: '/users',
+ updateUser: 'Patch /user/:id',
+ createUser: 'POST /user',
+ removeUser: 'DELETE /user/:id',
+ removeUserList: 'POST /users/delete',
+
+ queryOrg: '/org/:id',
+ queryOrgList: '/orgs',
+ updateOrg: 'Patch /org/:id',
+ createOrg: 'POST /org',
+ removeOrg: 'DELETE /org/:id',
+ removeOrgList: 'POST /org/delete',
+
+ queryPostList: '/posts',
+
+ queryDashboard: '/dashboard',
+}
diff --git a/src/services/index.js b/src/services/index.js
new file mode 100644
index 0000000..67236ea
--- /dev/null
+++ b/src/services/index.js
@@ -0,0 +1,38 @@
+import request from 'utils/request'
+import { apiPrefix } from 'utils/config'
+
+import api from './api'
+
+const gen = params => {
+ let url = apiPrefix + params
+ let method = 'GET'
+
+ const paramsArray = params.split(' ')
+ if (paramsArray.length === 2) {
+ method = paramsArray[0]
+ url = apiPrefix + paramsArray[1]
+ }
+
+ return function(data) {
+ return request({
+ url,
+ data,
+ method,
+ })
+ }
+}
+
+const APIFunction = {}
+for (const key in api) {
+ APIFunction[key] = gen(api[key])
+}
+
+APIFunction.queryWeather = params => {
+ params.key = 'i7sau1babuzwhycn'
+ return request({
+ url: `${apiPrefix}/weather/now.json`,
+ data: params,
+ })
+}
+
+export default APIFunction
diff --git a/src/themes/default.less b/src/themes/default.less
new file mode 100644
index 0000000..8fabcc1
--- /dev/null
+++ b/src/themes/default.less
@@ -0,0 +1,16 @@
+// 本文件是对 ant-design:
+// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
+// 相应变量值的覆盖
+// 注意:只需写出要覆盖的变量即可(不需要覆盖的变量不要写)
+
+@import '../../node_modules/antd/lib/style/themes/default.less';
+
+@border-radius-base: 3px;
+@border-radius-sm: 2px;
+@shadow-color: rgba(0, 0, 0, 0.05);
+@shadow-1-down: 4px 4px 40px @shadow-color;
+@border-color-split: #f4f4f4;
+@border-color-base: #e5e5e5;
+@font-size-base: 13px;
+@text-color: #666;
+@hover-color: #f9f9fc;
diff --git a/src/themes/index.less b/src/themes/index.less
new file mode 100644
index 0000000..fc5d498
--- /dev/null
+++ b/src/themes/index.less
@@ -0,0 +1,124 @@
+@import '~themes/vars.less';
+
+body {
+ height: 100%;
+ overflow-y: hidden;
+ background-color: #f8f8f8;
+}
+
+::-webkit-scrollbar-thumb {
+ background-color: #e6e6e6;
+}
+
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+.margin-right {
+ margin-right: 16px;
+}
+
+:global {
+ .ant-breadcrumb {
+ & > span {
+ &:last-child {
+ color: #999;
+ font-weight: normal;
+ }
+ }
+ }
+
+ .ant-breadcrumb-link {
+ .anticon + span {
+ margin-left: 4px;
+ }
+ }
+
+ .ant-table {
+ .ant-table-thead > tr > th {
+ text-align: center;
+ }
+
+ .ant-table-tbody > tr > td {
+ text-align: center;
+ }
+
+ &.ant-table-small {
+ .ant-table-thead > tr > th {
+ background: #f7f7f7;
+ }
+
+ .ant-table-body > table {
+ padding: 0;
+ }
+ }
+ }
+
+ .ant-table-pagination {
+ float: none !important;
+ display: table;
+ margin: 16px auto !important;
+ }
+
+ .ant-popover-inner {
+ border: none;
+ border-radius: 0;
+ box-shadow: 0 0 20px rgba(100, 100, 100, 0.2);
+ }
+
+ .ant-form-item-control {
+ vertical-align: middle;
+ }
+
+ .ant-modal-mask {
+ background-color: rgba(55, 55, 55, 0.2);
+ }
+
+ .ant-modal-content {
+ box-shadow: none;
+ }
+
+ .ant-select-dropdown-menu-item {
+ padding: 12px 16px !important;
+ }
+
+ a:focus {
+ text-decoration: none;
+ }
+
+ .ant-table-layout-fixed table {
+ table-layout: auto;
+ }
+}
+@media (min-width: 1600px) {
+ :global {
+ .ant-col-xl-48 {
+ width: 20%;
+ }
+
+ .ant-col-xl-96 {
+ width: 40%;
+ }
+ }
+}
+@media (max-width: 767px) {
+ :global {
+ .ant-pagination-item,
+ .ant-pagination-next,
+ .ant-pagination-options,
+ .ant-pagination-prev {
+ margin-bottom: 8px;
+ }
+
+ .ant-card {
+ .ant-card-head {
+ padding: 0 12px;
+ }
+
+ .ant-card-body {
+ padding: 12px;
+ }
+ }
+ }
+}
diff --git a/src/themes/mixin.less b/src/themes/mixin.less
new file mode 100644
index 0000000..16db875
--- /dev/null
+++ b/src/themes/mixin.less
@@ -0,0 +1,35 @@
+@import '~themes/default';
+
+@dark-half: #494949;
+@purple: #d897eb;
+@shadow-1: 4px 4px 20px 0 rgba(0, 0, 0, 0.01);
+@shadow-2: 4px 4px 40px 0 rgba(0, 0, 0, 0.05);
+@transition-ease-in: all 0.3s ease-out;
+@transition-ease-out: all 0.3s ease-out;
+@ease-in: ease-in;
+
+.text-overflow {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.text-gradient {
+ background-image: -webkit-gradient(
+ linear,
+ 37.219838% 34.532506%,
+ 36.425669% 93.178216%,
+ from(#29cdff),
+ to(#0a60ff),
+ color-stop(0.37, #148eff)
+ );
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.background-hover {
+ transition: @transition-ease-in;
+ &:hover {
+ background-color: @hover-color;
+ }
+}
diff --git a/src/themes/vars.less b/src/themes/vars.less
new file mode 100644
index 0000000..b2d50af
--- /dev/null
+++ b/src/themes/vars.less
@@ -0,0 +1,2 @@
+@import '~themes/default.less';
+@import '~themes/mixin.less';
diff --git a/src/utils/city.js b/src/utils/city.js
new file mode 100644
index 0000000..25900d3
--- /dev/null
+++ b/src/utils/city.js
@@ -0,0 +1,4055 @@
+/*
+ ## Address 字典数据
+ 字典数据来源 http://www.atatech.org/articles/30028?rnd=254259856
+ 国标 省(市)级行政区划码表
+ 华北 北京市 天津市 河北省 山西省 内蒙古自治区
+ 东北 辽宁省 吉林省 黑龙江省
+ 华东 上海市 江苏省 浙江省 安徽省 福建省 江西省 山东省
+ 华南 广东省 广西壮族自治区 海南省
+ 华中 河南省 湖北省 湖南省
+ 西南 重庆市 四川省 贵州省 云南省 西藏自治区
+ 西北 陕西省 甘肃省 青海省 宁夏回族自治区 新疆维吾尔自治区
+ 港澳台 香港特别行政区 澳门特别行政区 台湾省
+
+ **排序**
+
+ ```js
+ var map = {}
+ _.each(_.keys(REGIONS),function(id){
+ map[id] = REGIONS[ID]
+ })
+ JSON.stringify(map)
+ ```
+*/
+let DICT = {
+ 110000: '北京',
+ 110100: '北京市',
+ 110101: '东城区',
+ 110102: '西城区',
+ 110105: '朝阳区',
+ 110106: '丰台区',
+ 110107: '石景山区',
+ 110108: '海淀区',
+ 110109: '门头沟区',
+ 110111: '房山区',
+ 110112: '通州区',
+ 110113: '顺义区',
+ 110114: '昌平区',
+ 110115: '大兴区',
+ 110116: '怀柔区',
+ 110117: '平谷区',
+ 110228: '密云县',
+ 110229: '延庆县',
+ 110230: '其它区',
+ 120000: '天津',
+ 120100: '天津市',
+ 120101: '和平区',
+ 120102: '河东区',
+ 120103: '河西区',
+ 120104: '南开区',
+ 120105: '河北区',
+ 120106: '红桥区',
+ 120110: '东丽区',
+ 120111: '西青区',
+ 120112: '津南区',
+ 120113: '北辰区',
+ 120114: '武清区',
+ 120115: '宝坻区',
+ 120116: '滨海新区',
+ 120221: '宁河县',
+ 120223: '静海县',
+ 120225: '蓟县',
+ 120226: '其它区',
+ 130000: '河北省',
+ 130100: '石家庄市',
+ 130102: '长安区',
+ 130103: '桥东区',
+ 130104: '桥西区',
+ 130105: '新华区',
+ 130107: '井陉矿区',
+ 130108: '裕华区',
+ 130121: '井陉县',
+ 130123: '正定县',
+ 130124: '栾城县',
+ 130125: '行唐县',
+ 130126: '灵寿县',
+ 130127: '高邑县',
+ 130128: '深泽县',
+ 130129: '赞皇县',
+ 130130: '无极县',
+ 130131: '平山县',
+ 130132: '元氏县',
+ 130133: '赵县',
+ 130181: '辛集市',
+ 130182: '藁城市',
+ 130183: '晋州市',
+ 130184: '新乐市',
+ 130185: '鹿泉市',
+ 130186: '其它区',
+ 130200: '唐山市',
+ 130202: '路南区',
+ 130203: '路北区',
+ 130204: '古冶区',
+ 130205: '开平区',
+ 130207: '丰南区',
+ 130208: '丰润区',
+ 130223: '滦县',
+ 130224: '滦南县',
+ 130225: '乐亭县',
+ 130227: '迁西县',
+ 130229: '玉田县',
+ 130230: '曹妃甸区',
+ 130281: '遵化市',
+ 130283: '迁安市',
+ 130284: '其它区',
+ 130300: '秦皇岛市',
+ 130302: '海港区',
+ 130303: '山海关区',
+ 130304: '北戴河区',
+ 130321: '青龙满族自治县',
+ 130322: '昌黎县',
+ 130323: '抚宁县',
+ 130324: '卢龙县',
+ 130398: '其它区',
+ 130400: '邯郸市',
+ 130402: '邯山区',
+ 130403: '丛台区',
+ 130404: '复兴区',
+ 130406: '峰峰矿区',
+ 130421: '邯郸县',
+ 130423: '临漳县',
+ 130424: '成安县',
+ 130425: '大名县',
+ 130426: '涉县',
+ 130427: '磁县',
+ 130428: '肥乡县',
+ 130429: '永年县',
+ 130430: '邱县',
+ 130431: '鸡泽县',
+ 130432: '广平县',
+ 130433: '馆陶县',
+ 130434: '魏县',
+ 130435: '曲周县',
+ 130481: '武安市',
+ 130482: '其它区',
+ 130500: '邢台市',
+ 130502: '桥东区',
+ 130503: '桥西区',
+ 130521: '邢台县',
+ 130522: '临城县',
+ 130523: '内丘县',
+ 130524: '柏乡县',
+ 130525: '隆尧县',
+ 130526: '任县',
+ 130527: '南和县',
+ 130528: '宁晋县',
+ 130529: '巨鹿县',
+ 130530: '新河县',
+ 130531: '广宗县',
+ 130532: '平乡县',
+ 130533: '威县',
+ 130534: '清河县',
+ 130535: '临西县',
+ 130581: '南宫市',
+ 130582: '沙河市',
+ 130583: '其它区',
+ 130600: '保定市',
+ 130602: '新市区',
+ 130603: '北市区',
+ 130604: '南市区',
+ 130621: '满城县',
+ 130622: '清苑县',
+ 130623: '涞水县',
+ 130624: '阜平县',
+ 130625: '徐水县',
+ 130626: '定兴县',
+ 130627: '唐县',
+ 130628: '高阳县',
+ 130629: '容城县',
+ 130630: '涞源县',
+ 130631: '望都县',
+ 130632: '安新县',
+ 130633: '易县',
+ 130634: '曲阳县',
+ 130635: '蠡县',
+ 130636: '顺平县',
+ 130637: '博野县',
+ 130638: '雄县',
+ 130681: '涿州市',
+ 130682: '定州市',
+ 130683: '安国市',
+ 130684: '高碑店市',
+ 130699: '其它区',
+ 130700: '张家口市',
+ 130702: '桥东区',
+ 130703: '桥西区',
+ 130705: '宣化区',
+ 130706: '下花园区',
+ 130721: '宣化县',
+ 130722: '张北县',
+ 130723: '康保县',
+ 130724: '沽源县',
+ 130725: '尚义县',
+ 130726: '蔚县',
+ 130727: '阳原县',
+ 130728: '怀安县',
+ 130729: '万全县',
+ 130730: '怀来县',
+ 130731: '涿鹿县',
+ 130732: '赤城县',
+ 130733: '崇礼县',
+ 130734: '其它区',
+ 130800: '承德市',
+ 130802: '双桥区',
+ 130803: '双滦区',
+ 130804: '鹰手营子矿区',
+ 130821: '承德县',
+ 130822: '兴隆县',
+ 130823: '平泉县',
+ 130824: '滦平县',
+ 130825: '隆化县',
+ 130826: '丰宁满族自治县',
+ 130827: '宽城满族自治县',
+ 130828: '围场满族蒙古族自治县',
+ 130829: '其它区',
+ 130900: '沧州市',
+ 130902: '新华区',
+ 130903: '运河区',
+ 130921: '沧县',
+ 130922: '青县',
+ 130923: '东光县',
+ 130924: '海兴县',
+ 130925: '盐山县',
+ 130926: '肃宁县',
+ 130927: '南皮县',
+ 130928: '吴桥县',
+ 130929: '献县',
+ 130930: '孟村回族自治县',
+ 130981: '泊头市',
+ 130982: '任丘市',
+ 130983: '黄骅市',
+ 130984: '河间市',
+ 130985: '其它区',
+ 131000: '廊坊市',
+ 131002: '安次区',
+ 131003: '广阳区',
+ 131022: '固安县',
+ 131023: '永清县',
+ 131024: '香河县',
+ 131025: '大城县',
+ 131026: '文安县',
+ 131028: '大厂回族自治县',
+ 131081: '霸州市',
+ 131082: '三河市',
+ 131083: '其它区',
+ 131100: '衡水市',
+ 131102: '桃城区',
+ 131121: '枣强县',
+ 131122: '武邑县',
+ 131123: '武强县',
+ 131124: '饶阳县',
+ 131125: '安平县',
+ 131126: '故城县',
+ 131127: '景县',
+ 131128: '阜城县',
+ 131181: '冀州市',
+ 131182: '深州市',
+ 131183: '其它区',
+ 140000: '山西省',
+ 140100: '太原市',
+ 140105: '小店区',
+ 140106: '迎泽区',
+ 140107: '杏花岭区',
+ 140108: '尖草坪区',
+ 140109: '万柏林区',
+ 140110: '晋源区',
+ 140121: '清徐县',
+ 140122: '阳曲县',
+ 140123: '娄烦县',
+ 140181: '古交市',
+ 140182: '其它区',
+ 140200: '大同市',
+ 140202: '城区',
+ 140203: '矿区',
+ 140211: '南郊区',
+ 140212: '新荣区',
+ 140221: '阳高县',
+ 140222: '天镇县',
+ 140223: '广灵县',
+ 140224: '灵丘县',
+ 140225: '浑源县',
+ 140226: '左云县',
+ 140227: '大同县',
+ 140228: '其它区',
+ 140300: '阳泉市',
+ 140302: '城区',
+ 140303: '矿区',
+ 140311: '郊区',
+ 140321: '平定县',
+ 140322: '盂县',
+ 140323: '其它区',
+ 140400: '长治市',
+ 140421: '长治县',
+ 140423: '襄垣县',
+ 140424: '屯留县',
+ 140425: '平顺县',
+ 140426: '黎城县',
+ 140427: '壶关县',
+ 140428: '长子县',
+ 140429: '武乡县',
+ 140430: '沁县',
+ 140431: '沁源县',
+ 140481: '潞城市',
+ 140482: '城区',
+ 140483: '郊区',
+ 140485: '其它区',
+ 140500: '晋城市',
+ 140502: '城区',
+ 140521: '沁水县',
+ 140522: '阳城县',
+ 140524: '陵川县',
+ 140525: '泽州县',
+ 140581: '高平市',
+ 140582: '其它区',
+ 140600: '朔州市',
+ 140602: '朔城区',
+ 140603: '平鲁区',
+ 140621: '山阴县',
+ 140622: '应县',
+ 140623: '右玉县',
+ 140624: '怀仁县',
+ 140625: '其它区',
+ 140700: '晋中市',
+ 140702: '榆次区',
+ 140721: '榆社县',
+ 140722: '左权县',
+ 140723: '和顺县',
+ 140724: '昔阳县',
+ 140725: '寿阳县',
+ 140726: '太谷县',
+ 140727: '祁县',
+ 140728: '平遥县',
+ 140729: '灵石县',
+ 140781: '介休市',
+ 140782: '其它区',
+ 140800: '运城市',
+ 140802: '盐湖区',
+ 140821: '临猗县',
+ 140822: '万荣县',
+ 140823: '闻喜县',
+ 140824: '稷山县',
+ 140825: '新绛县',
+ 140826: '绛县',
+ 140827: '垣曲县',
+ 140828: '夏县',
+ 140829: '平陆县',
+ 140830: '芮城县',
+ 140881: '永济市',
+ 140882: '河津市',
+ 140883: '其它区',
+ 140900: '忻州市',
+ 140902: '忻府区',
+ 140921: '定襄县',
+ 140922: '五台县',
+ 140923: '代县',
+ 140924: '繁峙县',
+ 140925: '宁武县',
+ 140926: '静乐县',
+ 140927: '神池县',
+ 140928: '五寨县',
+ 140929: '岢岚县',
+ 140930: '河曲县',
+ 140931: '保德县',
+ 140932: '偏关县',
+ 140981: '原平市',
+ 140982: '其它区',
+ 141000: '临汾市',
+ 141002: '尧都区',
+ 141021: '曲沃县',
+ 141022: '翼城县',
+ 141023: '襄汾县',
+ 141024: '洪洞县',
+ 141025: '古县',
+ 141026: '安泽县',
+ 141027: '浮山县',
+ 141028: '吉县',
+ 141029: '乡宁县',
+ 141030: '大宁县',
+ 141031: '隰县',
+ 141032: '永和县',
+ 141033: '蒲县',
+ 141034: '汾西县',
+ 141081: '侯马市',
+ 141082: '霍州市',
+ 141083: '其它区',
+ 141100: '吕梁市',
+ 141102: '离石区',
+ 141121: '文水县',
+ 141122: '交城县',
+ 141123: '兴县',
+ 141124: '临县',
+ 141125: '柳林县',
+ 141126: '石楼县',
+ 141127: '岚县',
+ 141128: '方山县',
+ 141129: '中阳县',
+ 141130: '交口县',
+ 141181: '孝义市',
+ 141182: '汾阳市',
+ 141183: '其它区',
+ 150000: '内蒙古自治区',
+ 150100: '呼和浩特市',
+ 150102: '新城区',
+ 150103: '回民区',
+ 150104: '玉泉区',
+ 150105: '赛罕区',
+ 150121: '土默特左旗',
+ 150122: '托克托县',
+ 150123: '和林格尔县',
+ 150124: '清水河县',
+ 150125: '武川县',
+ 150126: '其它区',
+ 150200: '包头市',
+ 150202: '东河区',
+ 150203: '昆都仑区',
+ 150204: '青山区',
+ 150205: '石拐区',
+ 150206: '白云鄂博矿区',
+ 150207: '九原区',
+ 150221: '土默特右旗',
+ 150222: '固阳县',
+ 150223: '达尔罕茂明安联合旗',
+ 150224: '其它区',
+ 150300: '乌海市',
+ 150302: '海勃湾区',
+ 150303: '海南区',
+ 150304: '乌达区',
+ 150305: '其它区',
+ 150400: '赤峰市',
+ 150402: '红山区',
+ 150403: '元宝山区',
+ 150404: '松山区',
+ 150421: '阿鲁科尔沁旗',
+ 150422: '巴林左旗',
+ 150423: '巴林右旗',
+ 150424: '林西县',
+ 150425: '克什克腾旗',
+ 150426: '翁牛特旗',
+ 150428: '喀喇沁旗',
+ 150429: '宁城县',
+ 150430: '敖汉旗',
+ 150431: '其它区',
+ 150500: '通辽市',
+ 150502: '科尔沁区',
+ 150521: '科尔沁左翼中旗',
+ 150522: '科尔沁左翼后旗',
+ 150523: '开鲁县',
+ 150524: '库伦旗',
+ 150525: '奈曼旗',
+ 150526: '扎鲁特旗',
+ 150581: '霍林郭勒市',
+ 150582: '其它区',
+ 150600: '鄂尔多斯市',
+ 150602: '东胜区',
+ 150621: '达拉特旗',
+ 150622: '准格尔旗',
+ 150623: '鄂托克前旗',
+ 150624: '鄂托克旗',
+ 150625: '杭锦旗',
+ 150626: '乌审旗',
+ 150627: '伊金霍洛旗',
+ 150628: '其它区',
+ 150700: '呼伦贝尔市',
+ 150702: '海拉尔区',
+ 150703: '扎赉诺尔区',
+ 150721: '阿荣旗',
+ 150722: '莫力达瓦达斡尔族自治旗',
+ 150723: '鄂伦春自治旗',
+ 150724: '鄂温克族自治旗',
+ 150725: '陈巴尔虎旗',
+ 150726: '新巴尔虎左旗',
+ 150727: '新巴尔虎右旗',
+ 150781: '满洲里市',
+ 150782: '牙克石市',
+ 150783: '扎兰屯市',
+ 150784: '额尔古纳市',
+ 150785: '根河市',
+ 150786: '其它区',
+ 150800: '巴彦淖尔市',
+ 150802: '临河区',
+ 150821: '五原县',
+ 150822: '磴口县',
+ 150823: '乌拉特前旗',
+ 150824: '乌拉特中旗',
+ 150825: '乌拉特后旗',
+ 150826: '杭锦后旗',
+ 150827: '其它区',
+ 150900: '乌兰察布市',
+ 150902: '集宁区',
+ 150921: '卓资县',
+ 150922: '化德县',
+ 150923: '商都县',
+ 150924: '兴和县',
+ 150925: '凉城县',
+ 150926: '察哈尔右翼前旗',
+ 150927: '察哈尔右翼中旗',
+ 150928: '察哈尔右翼后旗',
+ 150929: '四子王旗',
+ 150981: '丰镇市',
+ 150982: '其它区',
+ 152200: '兴安盟',
+ 152201: '乌兰浩特市',
+ 152202: '阿尔山市',
+ 152221: '科尔沁右翼前旗',
+ 152222: '科尔沁右翼中旗',
+ 152223: '扎赉特旗',
+ 152224: '突泉县',
+ 152225: '其它区',
+ 152500: '锡林郭勒盟',
+ 152501: '二连浩特市',
+ 152502: '锡林浩特市',
+ 152522: '阿巴嘎旗',
+ 152523: '苏尼特左旗',
+ 152524: '苏尼特右旗',
+ 152525: '东乌珠穆沁旗',
+ 152526: '西乌珠穆沁旗',
+ 152527: '太仆寺旗',
+ 152528: '镶黄旗',
+ 152529: '正镶白旗',
+ 152530: '正蓝旗',
+ 152531: '多伦县',
+ 152532: '其它区',
+ 152900: '阿拉善盟',
+ 152921: '阿拉善左旗',
+ 152922: '阿拉善右旗',
+ 152923: '额济纳旗',
+ 152924: '其它区',
+ 210000: '辽宁省',
+ 210100: '沈阳市',
+ 210102: '和平区',
+ 210103: '沈河区',
+ 210104: '大东区',
+ 210105: '皇姑区',
+ 210106: '铁西区',
+ 210111: '苏家屯区',
+ 210112: '东陵区',
+ 210113: '新城子区',
+ 210114: '于洪区',
+ 210122: '辽中县',
+ 210123: '康平县',
+ 210124: '法库县',
+ 210181: '新民市',
+ 210184: '沈北新区',
+ 210185: '其它区',
+ 210200: '大连市',
+ 210202: '中山区',
+ 210203: '西岗区',
+ 210204: '沙河口区',
+ 210211: '甘井子区',
+ 210212: '旅顺口区',
+ 210213: '金州区',
+ 210224: '长海县',
+ 210281: '瓦房店市',
+ 210282: '普兰店市',
+ 210283: '庄河市',
+ 210298: '其它区',
+ 210300: '鞍山市',
+ 210302: '铁东区',
+ 210303: '铁西区',
+ 210304: '立山区',
+ 210311: '千山区',
+ 210321: '台安县',
+ 210323: '岫岩满族自治县',
+ 210381: '海城市',
+ 210382: '其它区',
+ 210400: '抚顺市',
+ 210402: '新抚区',
+ 210403: '东洲区',
+ 210404: '望花区',
+ 210411: '顺城区',
+ 210421: '抚顺县',
+ 210422: '新宾满族自治县',
+ 210423: '清原满族自治县',
+ 210424: '其它区',
+ 210500: '本溪市',
+ 210502: '平山区',
+ 210503: '溪湖区',
+ 210504: '明山区',
+ 210505: '南芬区',
+ 210521: '本溪满族自治县',
+ 210522: '桓仁满族自治县',
+ 210523: '其它区',
+ 210600: '丹东市',
+ 210602: '元宝区',
+ 210603: '振兴区',
+ 210604: '振安区',
+ 210624: '宽甸满族自治县',
+ 210681: '东港市',
+ 210682: '凤城市',
+ 210683: '其它区',
+ 210700: '锦州市',
+ 210702: '古塔区',
+ 210703: '凌河区',
+ 210711: '太和区',
+ 210726: '黑山县',
+ 210727: '义县',
+ 210781: '凌海市',
+ 210782: '北镇市',
+ 210783: '其它区',
+ 210800: '营口市',
+ 210802: '站前区',
+ 210803: '西市区',
+ 210804: '鲅鱼圈区',
+ 210811: '老边区',
+ 210881: '盖州市',
+ 210882: '大石桥市',
+ 210883: '其它区',
+ 210900: '阜新市',
+ 210902: '海州区',
+ 210903: '新邱区',
+ 210904: '太平区',
+ 210905: '清河门区',
+ 210911: '细河区',
+ 210921: '阜新蒙古族自治县',
+ 210922: '彰武县',
+ 210923: '其它区',
+ 211000: '辽阳市',
+ 211002: '白塔区',
+ 211003: '文圣区',
+ 211004: '宏伟区',
+ 211005: '弓长岭区',
+ 211011: '太子河区',
+ 211021: '辽阳县',
+ 211081: '灯塔市',
+ 211082: '其它区',
+ 211100: '盘锦市',
+ 211102: '双台子区',
+ 211103: '兴隆台区',
+ 211121: '大洼县',
+ 211122: '盘山县',
+ 211123: '其它区',
+ 211200: '铁岭市',
+ 211202: '银州区',
+ 211204: '清河区',
+ 211221: '铁岭县',
+ 211223: '西丰县',
+ 211224: '昌图县',
+ 211281: '调兵山市',
+ 211282: '开原市',
+ 211283: '其它区',
+ 211300: '朝阳市',
+ 211302: '双塔区',
+ 211303: '龙城区',
+ 211321: '朝阳县',
+ 211322: '建平县',
+ 211324: '喀喇沁左翼蒙古族自治县',
+ 211381: '北票市',
+ 211382: '凌源市',
+ 211383: '其它区',
+ 211400: '葫芦岛市',
+ 211402: '连山区',
+ 211403: '龙港区',
+ 211404: '南票区',
+ 211421: '绥中县',
+ 211422: '建昌县',
+ 211481: '兴城市',
+ 211482: '其它区',
+ 220000: '吉林省',
+ 220100: '长春市',
+ 220102: '南关区',
+ 220103: '宽城区',
+ 220104: '朝阳区',
+ 220105: '二道区',
+ 220106: '绿园区',
+ 220112: '双阳区',
+ 220122: '农安县',
+ 220181: '九台市',
+ 220182: '榆树市',
+ 220183: '德惠市',
+ 220188: '其它区',
+ 220200: '吉林市',
+ 220202: '昌邑区',
+ 220203: '龙潭区',
+ 220204: '船营区',
+ 220211: '丰满区',
+ 220221: '永吉县',
+ 220281: '蛟河市',
+ 220282: '桦甸市',
+ 220283: '舒兰市',
+ 220284: '磐石市',
+ 220285: '其它区',
+ 220300: '四平市',
+ 220302: '铁西区',
+ 220303: '铁东区',
+ 220322: '梨树县',
+ 220323: '伊通满族自治县',
+ 220381: '公主岭市',
+ 220382: '双辽市',
+ 220383: '其它区',
+ 220400: '辽源市',
+ 220402: '龙山区',
+ 220403: '西安区',
+ 220421: '东丰县',
+ 220422: '东辽县',
+ 220423: '其它区',
+ 220500: '通化市',
+ 220502: '东昌区',
+ 220503: '二道江区',
+ 220521: '通化县',
+ 220523: '辉南县',
+ 220524: '柳河县',
+ 220581: '梅河口市',
+ 220582: '集安市',
+ 220583: '其它区',
+ 220600: '白山市',
+ 220602: '浑江区',
+ 220621: '抚松县',
+ 220622: '靖宇县',
+ 220623: '长白朝鲜族自治县',
+ 220625: '江源区',
+ 220681: '临江市',
+ 220682: '其它区',
+ 220700: '松原市',
+ 220702: '宁江区',
+ 220721: '前郭尔罗斯蒙古族自治县',
+ 220722: '长岭县',
+ 220723: '乾安县',
+ 220724: '扶余市',
+ 220725: '其它区',
+ 220800: '白城市',
+ 220802: '洮北区',
+ 220821: '镇赉县',
+ 220822: '通榆县',
+ 220881: '洮南市',
+ 220882: '大安市',
+ 220883: '其它区',
+ 222400: '延边朝鲜族自治州',
+ 222401: '延吉市',
+ 222402: '图们市',
+ 222403: '敦化市',
+ 222404: '珲春市',
+ 222405: '龙井市',
+ 222406: '和龙市',
+ 222424: '汪清县',
+ 222426: '安图县',
+ 222427: '其它区',
+ 230000: '黑龙江省',
+ 230100: '哈尔滨市',
+ 230102: '道里区',
+ 230103: '南岗区',
+ 230104: '道外区',
+ 230106: '香坊区',
+ 230108: '平房区',
+ 230109: '松北区',
+ 230111: '呼兰区',
+ 230123: '依兰县',
+ 230124: '方正县',
+ 230125: '宾县',
+ 230126: '巴彦县',
+ 230127: '木兰县',
+ 230128: '通河县',
+ 230129: '延寿县',
+ 230181: '阿城区',
+ 230182: '双城市',
+ 230183: '尚志市',
+ 230184: '五常市',
+ 230186: '其它区',
+ 230200: '齐齐哈尔市',
+ 230202: '龙沙区',
+ 230203: '建华区',
+ 230204: '铁锋区',
+ 230205: '昂昂溪区',
+ 230206: '富拉尔基区',
+ 230207: '碾子山区',
+ 230208: '梅里斯达斡尔族区',
+ 230221: '龙江县',
+ 230223: '依安县',
+ 230224: '泰来县',
+ 230225: '甘南县',
+ 230227: '富裕县',
+ 230229: '克山县',
+ 230230: '克东县',
+ 230231: '拜泉县',
+ 230281: '讷河市',
+ 230282: '其它区',
+ 230300: '鸡西市',
+ 230302: '鸡冠区',
+ 230303: '恒山区',
+ 230304: '滴道区',
+ 230305: '梨树区',
+ 230306: '城子河区',
+ 230307: '麻山区',
+ 230321: '鸡东县',
+ 230381: '虎林市',
+ 230382: '密山市',
+ 230383: '其它区',
+ 230400: '鹤岗市',
+ 230402: '向阳区',
+ 230403: '工农区',
+ 230404: '南山区',
+ 230405: '兴安区',
+ 230406: '东山区',
+ 230407: '兴山区',
+ 230421: '萝北县',
+ 230422: '绥滨县',
+ 230423: '其它区',
+ 230500: '双鸭山市',
+ 230502: '尖山区',
+ 230503: '岭东区',
+ 230505: '四方台区',
+ 230506: '宝山区',
+ 230521: '集贤县',
+ 230522: '友谊县',
+ 230523: '宝清县',
+ 230524: '饶河县',
+ 230525: '其它区',
+ 230600: '大庆市',
+ 230602: '萨尔图区',
+ 230603: '龙凤区',
+ 230604: '让胡路区',
+ 230605: '红岗区',
+ 230606: '大同区',
+ 230621: '肇州县',
+ 230622: '肇源县',
+ 230623: '林甸县',
+ 230624: '杜尔伯特蒙古族自治县',
+ 230625: '其它区',
+ 230700: '伊春市',
+ 230702: '伊春区',
+ 230703: '南岔区',
+ 230704: '友好区',
+ 230705: '西林区',
+ 230706: '翠峦区',
+ 230707: '新青区',
+ 230708: '美溪区',
+ 230709: '金山屯区',
+ 230710: '五营区',
+ 230711: '乌马河区',
+ 230712: '汤旺河区',
+ 230713: '带岭区',
+ 230714: '乌伊岭区',
+ 230715: '红星区',
+ 230716: '上甘岭区',
+ 230722: '嘉荫县',
+ 230781: '铁力市',
+ 230782: '其它区',
+ 230800: '佳木斯市',
+ 230803: '向阳区',
+ 230804: '前进区',
+ 230805: '东风区',
+ 230811: '郊区',
+ 230822: '桦南县',
+ 230826: '桦川县',
+ 230828: '汤原县',
+ 230833: '抚远县',
+ 230881: '同江市',
+ 230882: '富锦市',
+ 230883: '其它区',
+ 230900: '七台河市',
+ 230902: '新兴区',
+ 230903: '桃山区',
+ 230904: '茄子河区',
+ 230921: '勃利县',
+ 230922: '其它区',
+ 231000: '牡丹江市',
+ 231002: '东安区',
+ 231003: '阳明区',
+ 231004: '爱民区',
+ 231005: '西安区',
+ 231024: '东宁县',
+ 231025: '林口县',
+ 231081: '绥芬河市',
+ 231083: '海林市',
+ 231084: '宁安市',
+ 231085: '穆棱市',
+ 231086: '其它区',
+ 231100: '黑河市',
+ 231102: '爱辉区',
+ 231121: '嫩江县',
+ 231123: '逊克县',
+ 231124: '孙吴县',
+ 231181: '北安市',
+ 231182: '五大连池市',
+ 231183: '其它区',
+ 231200: '绥化市',
+ 231202: '北林区',
+ 231221: '望奎县',
+ 231222: '兰西县',
+ 231223: '青冈县',
+ 231224: '庆安县',
+ 231225: '明水县',
+ 231226: '绥棱县',
+ 231281: '安达市',
+ 231282: '肇东市',
+ 231283: '海伦市',
+ 231284: '其它区',
+ 232700: '大兴安岭地区',
+ 232702: '松岭区',
+ 232703: '新林区',
+ 232704: '呼中区',
+ 232721: '呼玛县',
+ 232722: '塔河县',
+ 232723: '漠河县',
+ 232724: '加格达奇区',
+ 232725: '其它区',
+ 310000: '上海',
+ 310100: '上海市',
+ 310101: '黄浦区',
+ 310104: '徐汇区',
+ 310105: '长宁区',
+ 310106: '静安区',
+ 310107: '普陀区',
+ 310108: '闸北区',
+ 310109: '虹口区',
+ 310110: '杨浦区',
+ 310112: '闵行区',
+ 310113: '宝山区',
+ 310114: '嘉定区',
+ 310115: '浦东新区',
+ 310116: '金山区',
+ 310117: '松江区',
+ 310118: '青浦区',
+ 310120: '奉贤区',
+ 310230: '崇明县',
+ 310231: '其它区',
+ 320000: '江苏省',
+ 320100: '南京市',
+ 320102: '玄武区',
+ 320104: '秦淮区',
+ 320105: '建邺区',
+ 320106: '鼓楼区',
+ 320111: '浦口区',
+ 320113: '栖霞区',
+ 320114: '雨花台区',
+ 320115: '江宁区',
+ 320116: '六合区',
+ 320124: '溧水区',
+ 320125: '高淳区',
+ 320126: '其它区',
+ 320200: '无锡市',
+ 320202: '崇安区',
+ 320203: '南长区',
+ 320204: '北塘区',
+ 320205: '锡山区',
+ 320206: '惠山区',
+ 320211: '滨湖区',
+ 320281: '江阴市',
+ 320282: '宜兴市',
+ 320297: '其它区',
+ 320300: '徐州市',
+ 320302: '鼓楼区',
+ 320303: '云龙区',
+ 320305: '贾汪区',
+ 320311: '泉山区',
+ 320321: '丰县',
+ 320322: '沛县',
+ 320323: '铜山区',
+ 320324: '睢宁县',
+ 320381: '新沂市',
+ 320382: '邳州市',
+ 320383: '其它区',
+ 320400: '常州市',
+ 320402: '天宁区',
+ 320404: '钟楼区',
+ 320405: '戚墅堰区',
+ 320411: '新北区',
+ 320412: '武进区',
+ 320481: '溧阳市',
+ 320482: '金坛市',
+ 320483: '其它区',
+ 320500: '苏州市',
+ 320505: '虎丘区',
+ 320506: '吴中区',
+ 320507: '相城区',
+ 320508: '姑苏区',
+ 320581: '常熟市',
+ 320582: '张家港市',
+ 320583: '昆山市',
+ 320584: '吴江区',
+ 320585: '太仓市',
+ 320596: '其它区',
+ 320600: '南通市',
+ 320602: '崇川区',
+ 320611: '港闸区',
+ 320612: '通州区',
+ 320621: '海安县',
+ 320623: '如东县',
+ 320681: '启东市',
+ 320682: '如皋市',
+ 320684: '海门市',
+ 320694: '其它区',
+ 320700: '连云港市',
+ 320703: '连云区',
+ 320705: '新浦区',
+ 320706: '海州区',
+ 320721: '赣榆县',
+ 320722: '东海县',
+ 320723: '灌云县',
+ 320724: '灌南县',
+ 320725: '其它区',
+ 320800: '淮安市',
+ 320802: '清河区',
+ 320803: '淮安区',
+ 320804: '淮阴区',
+ 320811: '清浦区',
+ 320826: '涟水县',
+ 320829: '洪泽县',
+ 320830: '盱眙县',
+ 320831: '金湖县',
+ 320832: '其它区',
+ 320900: '盐城市',
+ 320902: '亭湖区',
+ 320903: '盐都区',
+ 320921: '响水县',
+ 320922: '滨海县',
+ 320923: '阜宁县',
+ 320924: '射阳县',
+ 320925: '建湖县',
+ 320981: '东台市',
+ 320982: '大丰市',
+ 320983: '其它区',
+ 321000: '扬州市',
+ 321002: '广陵区',
+ 321003: '邗江区',
+ 321023: '宝应县',
+ 321081: '仪征市',
+ 321084: '高邮市',
+ 321088: '江都区',
+ 321093: '其它区',
+ 321100: '镇江市',
+ 321102: '京口区',
+ 321111: '润州区',
+ 321112: '丹徒区',
+ 321181: '丹阳市',
+ 321182: '扬中市',
+ 321183: '句容市',
+ 321184: '其它区',
+ 321200: '泰州市',
+ 321202: '海陵区',
+ 321203: '高港区',
+ 321281: '兴化市',
+ 321282: '靖江市',
+ 321283: '泰兴市',
+ 321284: '姜堰区',
+ 321285: '其它区',
+ 321300: '宿迁市',
+ 321302: '宿城区',
+ 321311: '宿豫区',
+ 321322: '沭阳县',
+ 321323: '泗阳县',
+ 321324: '泗洪县',
+ 321325: '其它区',
+ 330000: '浙江省',
+ 330100: '杭州市',
+ 330102: '上城区',
+ 330103: '下城区',
+ 330104: '江干区',
+ 330105: '拱墅区',
+ 330106: '西湖区',
+ 330108: '滨江区',
+ 330109: '萧山区',
+ 330110: '余杭区',
+ 330122: '桐庐县',
+ 330127: '淳安县',
+ 330182: '建德市',
+ 330183: '富阳市',
+ 330185: '临安市',
+ 330186: '其它区',
+ 330200: '宁波市',
+ 330203: '海曙区',
+ 330204: '江东区',
+ 330205: '江北区',
+ 330206: '北仑区',
+ 330211: '镇海区',
+ 330212: '鄞州区',
+ 330225: '象山县',
+ 330226: '宁海县',
+ 330281: '余姚市',
+ 330282: '慈溪市',
+ 330283: '奉化市',
+ 330284: '其它区',
+ 330300: '温州市',
+ 330302: '鹿城区',
+ 330303: '龙湾区',
+ 330304: '瓯海区',
+ 330322: '洞头县',
+ 330324: '永嘉县',
+ 330326: '平阳县',
+ 330327: '苍南县',
+ 330328: '文成县',
+ 330329: '泰顺县',
+ 330381: '瑞安市',
+ 330382: '乐清市',
+ 330383: '其它区',
+ 330400: '嘉兴市',
+ 330402: '南湖区',
+ 330411: '秀洲区',
+ 330421: '嘉善县',
+ 330424: '海盐县',
+ 330481: '海宁市',
+ 330482: '平湖市',
+ 330483: '桐乡市',
+ 330484: '其它区',
+ 330500: '湖州市',
+ 330502: '吴兴区',
+ 330503: '南浔区',
+ 330521: '德清县',
+ 330522: '长兴县',
+ 330523: '安吉县',
+ 330524: '其它区',
+ 330600: '绍兴市',
+ 330602: '越城区',
+ 330621: '绍兴县',
+ 330624: '新昌县',
+ 330681: '诸暨市',
+ 330682: '上虞市',
+ 330683: '嵊州市',
+ 330684: '其它区',
+ 330700: '金华市',
+ 330702: '婺城区',
+ 330703: '金东区',
+ 330723: '武义县',
+ 330726: '浦江县',
+ 330727: '磐安县',
+ 330781: '兰溪市',
+ 330782: '义乌市',
+ 330783: '东阳市',
+ 330784: '永康市',
+ 330785: '其它区',
+ 330800: '衢州市',
+ 330802: '柯城区',
+ 330803: '衢江区',
+ 330822: '常山县',
+ 330824: '开化县',
+ 330825: '龙游县',
+ 330881: '江山市',
+ 330882: '其它区',
+ 330900: '舟山市',
+ 330902: '定海区',
+ 330903: '普陀区',
+ 330921: '岱山县',
+ 330922: '嵊泗县',
+ 330923: '其它区',
+ 331000: '台州市',
+ 331002: '椒江区',
+ 331003: '黄岩区',
+ 331004: '路桥区',
+ 331021: '玉环县',
+ 331022: '三门县',
+ 331023: '天台县',
+ 331024: '仙居县',
+ 331081: '温岭市',
+ 331082: '临海市',
+ 331083: '其它区',
+ 331100: '丽水市',
+ 331102: '莲都区',
+ 331121: '青田县',
+ 331122: '缙云县',
+ 331123: '遂昌县',
+ 331124: '松阳县',
+ 331125: '云和县',
+ 331126: '庆元县',
+ 331127: '景宁畲族自治县',
+ 331181: '龙泉市',
+ 331182: '其它区',
+ 340000: '安徽省',
+ 340100: '合肥市',
+ 340102: '瑶海区',
+ 340103: '庐阳区',
+ 340104: '蜀山区',
+ 340111: '包河区',
+ 340121: '长丰县',
+ 340122: '肥东县',
+ 340123: '肥西县',
+ 340192: '其它区',
+ 340200: '芜湖市',
+ 340202: '镜湖区',
+ 340203: '弋江区',
+ 340207: '鸠江区',
+ 340208: '三山区',
+ 340221: '芜湖县',
+ 340222: '繁昌县',
+ 340223: '南陵县',
+ 340224: '其它区',
+ 340300: '蚌埠市',
+ 340302: '龙子湖区',
+ 340303: '蚌山区',
+ 340304: '禹会区',
+ 340311: '淮上区',
+ 340321: '怀远县',
+ 340322: '五河县',
+ 340323: '固镇县',
+ 340324: '其它区',
+ 340400: '淮南市',
+ 340402: '大通区',
+ 340403: '田家庵区',
+ 340404: '谢家集区',
+ 340405: '八公山区',
+ 340406: '潘集区',
+ 340421: '凤台县',
+ 340422: '其它区',
+ 340500: '马鞍山市',
+ 340503: '花山区',
+ 340504: '雨山区',
+ 340506: '博望区',
+ 340521: '当涂县',
+ 340522: '其它区',
+ 340600: '淮北市',
+ 340602: '杜集区',
+ 340603: '相山区',
+ 340604: '烈山区',
+ 340621: '濉溪县',
+ 340622: '其它区',
+ 340700: '铜陵市',
+ 340702: '铜官山区',
+ 340703: '狮子山区',
+ 340711: '郊区',
+ 340721: '铜陵县',
+ 340722: '其它区',
+ 340800: '安庆市',
+ 340802: '迎江区',
+ 340803: '大观区',
+ 340811: '宜秀区',
+ 340822: '怀宁县',
+ 340823: '枞阳县',
+ 340824: '潜山县',
+ 340825: '太湖县',
+ 340826: '宿松县',
+ 340827: '望江县',
+ 340828: '岳西县',
+ 340881: '桐城市',
+ 340882: '其它区',
+ 341000: '黄山市',
+ 341002: '屯溪区',
+ 341003: '黄山区',
+ 341004: '徽州区',
+ 341021: '歙县',
+ 341022: '休宁县',
+ 341023: '黟县',
+ 341024: '祁门县',
+ 341025: '其它区',
+ 341100: '滁州市',
+ 341102: '琅琊区',
+ 341103: '南谯区',
+ 341122: '来安县',
+ 341124: '全椒县',
+ 341125: '定远县',
+ 341126: '凤阳县',
+ 341181: '天长市',
+ 341182: '明光市',
+ 341183: '其它区',
+ 341200: '阜阳市',
+ 341202: '颍州区',
+ 341203: '颍东区',
+ 341204: '颍泉区',
+ 341221: '临泉县',
+ 341222: '太和县',
+ 341225: '阜南县',
+ 341226: '颍上县',
+ 341282: '界首市',
+ 341283: '其它区',
+ 341300: '宿州市',
+ 341302: '埇桥区',
+ 341321: '砀山县',
+ 341322: '萧县',
+ 341323: '灵璧县',
+ 341324: '泗县',
+ 341325: '其它区',
+ 341400: '巢湖市',
+ 341421: '庐江县',
+ 341422: '无为县',
+ 341423: '含山县',
+ 341424: '和县',
+ 341500: '六安市',
+ 341502: '金安区',
+ 341503: '裕安区',
+ 341521: '寿县',
+ 341522: '霍邱县',
+ 341523: '舒城县',
+ 341524: '金寨县',
+ 341525: '霍山县',
+ 341526: '其它区',
+ 341600: '亳州市',
+ 341602: '谯城区',
+ 341621: '涡阳县',
+ 341622: '蒙城县',
+ 341623: '利辛县',
+ 341624: '其它区',
+ 341700: '池州市',
+ 341702: '贵池区',
+ 341721: '东至县',
+ 341722: '石台县',
+ 341723: '青阳县',
+ 341724: '其它区',
+ 341800: '宣城市',
+ 341802: '宣州区',
+ 341821: '郎溪县',
+ 341822: '广德县',
+ 341823: '泾县',
+ 341824: '绩溪县',
+ 341825: '旌德县',
+ 341881: '宁国市',
+ 341882: '其它区',
+ 350000: '福建省',
+ 350100: '福州市',
+ 350102: '鼓楼区',
+ 350103: '台江区',
+ 350104: '仓山区',
+ 350105: '马尾区',
+ 350111: '晋安区',
+ 350121: '闽侯县',
+ 350122: '连江县',
+ 350123: '罗源县',
+ 350124: '闽清县',
+ 350125: '永泰县',
+ 350128: '平潭县',
+ 350181: '福清市',
+ 350182: '长乐市',
+ 350183: '其它区',
+ 350200: '厦门市',
+ 350203: '思明区',
+ 350205: '海沧区',
+ 350206: '湖里区',
+ 350211: '集美区',
+ 350212: '同安区',
+ 350213: '翔安区',
+ 350214: '其它区',
+ 350300: '莆田市',
+ 350302: '城厢区',
+ 350303: '涵江区',
+ 350304: '荔城区',
+ 350305: '秀屿区',
+ 350322: '仙游县',
+ 350323: '其它区',
+ 350400: '三明市',
+ 350402: '梅列区',
+ 350403: '三元区',
+ 350421: '明溪县',
+ 350423: '清流县',
+ 350424: '宁化县',
+ 350425: '大田县',
+ 350426: '尤溪县',
+ 350427: '沙县',
+ 350428: '将乐县',
+ 350429: '泰宁县',
+ 350430: '建宁县',
+ 350481: '永安市',
+ 350482: '其它区',
+ 350500: '泉州市',
+ 350502: '鲤城区',
+ 350503: '丰泽区',
+ 350504: '洛江区',
+ 350505: '泉港区',
+ 350521: '惠安县',
+ 350524: '安溪县',
+ 350525: '永春县',
+ 350526: '德化县',
+ 350527: '金门县',
+ 350581: '石狮市',
+ 350582: '晋江市',
+ 350583: '南安市',
+ 350584: '其它区',
+ 350600: '漳州市',
+ 350602: '芗城区',
+ 350603: '龙文区',
+ 350622: '云霄县',
+ 350623: '漳浦县',
+ 350624: '诏安县',
+ 350625: '长泰县',
+ 350626: '东山县',
+ 350627: '南靖县',
+ 350628: '平和县',
+ 350629: '华安县',
+ 350681: '龙海市',
+ 350682: '其它区',
+ 350700: '南平市',
+ 350702: '延平区',
+ 350721: '顺昌县',
+ 350722: '浦城县',
+ 350723: '光泽县',
+ 350724: '松溪县',
+ 350725: '政和县',
+ 350781: '邵武市',
+ 350782: '武夷山市',
+ 350783: '建瓯市',
+ 350784: '建阳市',
+ 350785: '其它区',
+ 350800: '龙岩市',
+ 350802: '新罗区',
+ 350821: '长汀县',
+ 350822: '永定县',
+ 350823: '上杭县',
+ 350824: '武平县',
+ 350825: '连城县',
+ 350881: '漳平市',
+ 350882: '其它区',
+ 350900: '宁德市',
+ 350902: '蕉城区',
+ 350921: '霞浦县',
+ 350922: '古田县',
+ 350923: '屏南县',
+ 350924: '寿宁县',
+ 350925: '周宁县',
+ 350926: '柘荣县',
+ 350981: '福安市',
+ 350982: '福鼎市',
+ 350983: '其它区',
+ 360000: '江西省',
+ 360100: '南昌市',
+ 360102: '东湖区',
+ 360103: '西湖区',
+ 360104: '青云谱区',
+ 360105: '湾里区',
+ 360111: '青山湖区',
+ 360121: '南昌县',
+ 360122: '新建县',
+ 360123: '安义县',
+ 360124: '进贤县',
+ 360128: '其它区',
+ 360200: '景德镇市',
+ 360202: '昌江区',
+ 360203: '珠山区',
+ 360222: '浮梁县',
+ 360281: '乐平市',
+ 360282: '其它区',
+ 360300: '萍乡市',
+ 360302: '安源区',
+ 360313: '湘东区',
+ 360321: '莲花县',
+ 360322: '上栗县',
+ 360323: '芦溪县',
+ 360324: '其它区',
+ 360400: '九江市',
+ 360402: '庐山区',
+ 360403: '浔阳区',
+ 360421: '九江县',
+ 360423: '武宁县',
+ 360424: '修水县',
+ 360425: '永修县',
+ 360426: '德安县',
+ 360427: '星子县',
+ 360428: '都昌县',
+ 360429: '湖口县',
+ 360430: '彭泽县',
+ 360481: '瑞昌市',
+ 360482: '其它区',
+ 360483: '共青城市',
+ 360500: '新余市',
+ 360502: '渝水区',
+ 360521: '分宜县',
+ 360522: '其它区',
+ 360600: '鹰潭市',
+ 360602: '月湖区',
+ 360622: '余江县',
+ 360681: '贵溪市',
+ 360682: '其它区',
+ 360700: '赣州市',
+ 360702: '章贡区',
+ 360721: '赣县',
+ 360722: '信丰县',
+ 360723: '大余县',
+ 360724: '上犹县',
+ 360725: '崇义县',
+ 360726: '安远县',
+ 360727: '龙南县',
+ 360728: '定南县',
+ 360729: '全南县',
+ 360730: '宁都县',
+ 360731: '于都县',
+ 360732: '兴国县',
+ 360733: '会昌县',
+ 360734: '寻乌县',
+ 360735: '石城县',
+ 360781: '瑞金市',
+ 360782: '南康市',
+ 360783: '其它区',
+ 360800: '吉安市',
+ 360802: '吉州区',
+ 360803: '青原区',
+ 360821: '吉安县',
+ 360822: '吉水县',
+ 360823: '峡江县',
+ 360824: '新干县',
+ 360825: '永丰县',
+ 360826: '泰和县',
+ 360827: '遂川县',
+ 360828: '万安县',
+ 360829: '安福县',
+ 360830: '永新县',
+ 360881: '井冈山市',
+ 360882: '其它区',
+ 360900: '宜春市',
+ 360902: '袁州区',
+ 360921: '奉新县',
+ 360922: '万载县',
+ 360923: '上高县',
+ 360924: '宜丰县',
+ 360925: '靖安县',
+ 360926: '铜鼓县',
+ 360981: '丰城市',
+ 360982: '樟树市',
+ 360983: '高安市',
+ 360984: '其它区',
+ 361000: '抚州市',
+ 361002: '临川区',
+ 361021: '南城县',
+ 361022: '黎川县',
+ 361023: '南丰县',
+ 361024: '崇仁县',
+ 361025: '乐安县',
+ 361026: '宜黄县',
+ 361027: '金溪县',
+ 361028: '资溪县',
+ 361029: '东乡县',
+ 361030: '广昌县',
+ 361031: '其它区',
+ 361100: '上饶市',
+ 361102: '信州区',
+ 361121: '上饶县',
+ 361122: '广丰县',
+ 361123: '玉山县',
+ 361124: '铅山县',
+ 361125: '横峰县',
+ 361126: '弋阳县',
+ 361127: '余干县',
+ 361128: '鄱阳县',
+ 361129: '万年县',
+ 361130: '婺源县',
+ 361181: '德兴市',
+ 361182: '其它区',
+ 370000: '山东省',
+ 370100: '济南市',
+ 370102: '历下区',
+ 370103: '市中区',
+ 370104: '槐荫区',
+ 370105: '天桥区',
+ 370112: '历城区',
+ 370113: '长清区',
+ 370124: '平阴县',
+ 370125: '济阳县',
+ 370126: '商河县',
+ 370181: '章丘市',
+ 370182: '其它区',
+ 370200: '青岛市',
+ 370202: '市南区',
+ 370203: '市北区',
+ 370211: '黄岛区',
+ 370212: '崂山区',
+ 370213: '李沧区',
+ 370214: '城阳区',
+ 370281: '胶州市',
+ 370282: '即墨市',
+ 370283: '平度市',
+ 370285: '莱西市',
+ 370286: '其它区',
+ 370300: '淄博市',
+ 370302: '淄川区',
+ 370303: '张店区',
+ 370304: '博山区',
+ 370305: '临淄区',
+ 370306: '周村区',
+ 370321: '桓台县',
+ 370322: '高青县',
+ 370323: '沂源县',
+ 370324: '其它区',
+ 370400: '枣庄市',
+ 370402: '市中区',
+ 370403: '薛城区',
+ 370404: '峄城区',
+ 370405: '台儿庄区',
+ 370406: '山亭区',
+ 370481: '滕州市',
+ 370482: '其它区',
+ 370500: '东营市',
+ 370502: '东营区',
+ 370503: '河口区',
+ 370521: '垦利县',
+ 370522: '利津县',
+ 370523: '广饶县',
+ 370591: '其它区',
+ 370600: '烟台市',
+ 370602: '芝罘区',
+ 370611: '福山区',
+ 370612: '牟平区',
+ 370613: '莱山区',
+ 370634: '长岛县',
+ 370681: '龙口市',
+ 370682: '莱阳市',
+ 370683: '莱州市',
+ 370684: '蓬莱市',
+ 370685: '招远市',
+ 370686: '栖霞市',
+ 370687: '海阳市',
+ 370688: '其它区',
+ 370700: '潍坊市',
+ 370702: '潍城区',
+ 370703: '寒亭区',
+ 370704: '坊子区',
+ 370705: '奎文区',
+ 370724: '临朐县',
+ 370725: '昌乐县',
+ 370781: '青州市',
+ 370782: '诸城市',
+ 370783: '寿光市',
+ 370784: '安丘市',
+ 370785: '高密市',
+ 370786: '昌邑市',
+ 370787: '其它区',
+ 370800: '济宁市',
+ 370802: '市中区',
+ 370811: '任城区',
+ 370826: '微山县',
+ 370827: '鱼台县',
+ 370828: '金乡县',
+ 370829: '嘉祥县',
+ 370830: '汶上县',
+ 370831: '泗水县',
+ 370832: '梁山县',
+ 370881: '曲阜市',
+ 370882: '兖州市',
+ 370883: '邹城市',
+ 370884: '其它区',
+ 370900: '泰安市',
+ 370902: '泰山区',
+ 370903: '岱岳区',
+ 370921: '宁阳县',
+ 370923: '东平县',
+ 370982: '新泰市',
+ 370983: '肥城市',
+ 370984: '其它区',
+ 371000: '威海市',
+ 371002: '环翠区',
+ 371081: '文登市',
+ 371082: '荣成市',
+ 371083: '乳山市',
+ 371084: '其它区',
+ 371100: '日照市',
+ 371102: '东港区',
+ 371103: '岚山区',
+ 371121: '五莲县',
+ 371122: '莒县',
+ 371123: '其它区',
+ 371200: '莱芜市',
+ 371202: '莱城区',
+ 371203: '钢城区',
+ 371204: '其它区',
+ 371300: '临沂市',
+ 371302: '兰山区',
+ 371311: '罗庄区',
+ 371312: '河东区',
+ 371321: '沂南县',
+ 371322: '郯城县',
+ 371323: '沂水县',
+ 371324: '苍山县',
+ 371325: '费县',
+ 371326: '平邑县',
+ 371327: '莒南县',
+ 371328: '蒙阴县',
+ 371329: '临沭县',
+ 371330: '其它区',
+ 371400: '德州市',
+ 371402: '德城区',
+ 371421: '陵县',
+ 371422: '宁津县',
+ 371423: '庆云县',
+ 371424: '临邑县',
+ 371425: '齐河县',
+ 371426: '平原县',
+ 371427: '夏津县',
+ 371428: '武城县',
+ 371481: '乐陵市',
+ 371482: '禹城市',
+ 371483: '其它区',
+ 371500: '聊城市',
+ 371502: '东昌府区',
+ 371521: '阳谷县',
+ 371522: '莘县',
+ 371523: '茌平县',
+ 371524: '东阿县',
+ 371525: '冠县',
+ 371526: '高唐县',
+ 371581: '临清市',
+ 371582: '其它区',
+ 371600: '滨州市',
+ 371602: '滨城区',
+ 371621: '惠民县',
+ 371622: '阳信县',
+ 371623: '无棣县',
+ 371624: '沾化县',
+ 371625: '博兴县',
+ 371626: '邹平县',
+ 371627: '其它区',
+ 371700: '菏泽市',
+ 371702: '牡丹区',
+ 371721: '曹县',
+ 371722: '单县',
+ 371723: '成武县',
+ 371724: '巨野县',
+ 371725: '郓城县',
+ 371726: '鄄城县',
+ 371727: '定陶县',
+ 371728: '东明县',
+ 371729: '其它区',
+ 410000: '河南省',
+ 410100: '郑州市',
+ 410102: '中原区',
+ 410103: '二七区',
+ 410104: '管城回族区',
+ 410105: '金水区',
+ 410106: '上街区',
+ 410108: '惠济区',
+ 410122: '中牟县',
+ 410181: '巩义市',
+ 410182: '荥阳市',
+ 410183: '新密市',
+ 410184: '新郑市',
+ 410185: '登封市',
+ 410188: '其它区',
+ 410200: '开封市',
+ 410202: '龙亭区',
+ 410203: '顺河回族区',
+ 410204: '鼓楼区',
+ 410205: '禹王台区',
+ 410211: '金明区',
+ 410221: '杞县',
+ 410222: '通许县',
+ 410223: '尉氏县',
+ 410224: '开封县',
+ 410225: '兰考县',
+ 410226: '其它区',
+ 410300: '洛阳市',
+ 410302: '老城区',
+ 410303: '西工区',
+ 410304: '瀍河回族区',
+ 410305: '涧西区',
+ 410306: '吉利区',
+ 410307: '洛龙区',
+ 410322: '孟津县',
+ 410323: '新安县',
+ 410324: '栾川县',
+ 410325: '嵩县',
+ 410326: '汝阳县',
+ 410327: '宜阳县',
+ 410328: '洛宁县',
+ 410329: '伊川县',
+ 410381: '偃师市',
+ 410400: '平顶山市',
+ 410402: '新华区',
+ 410403: '卫东区',
+ 410404: '石龙区',
+ 410411: '湛河区',
+ 410421: '宝丰县',
+ 410422: '叶县',
+ 410423: '鲁山县',
+ 410425: '郏县',
+ 410481: '舞钢市',
+ 410482: '汝州市',
+ 410483: '其它区',
+ 410500: '安阳市',
+ 410502: '文峰区',
+ 410503: '北关区',
+ 410505: '殷都区',
+ 410506: '龙安区',
+ 410522: '安阳县',
+ 410523: '汤阴县',
+ 410526: '滑县',
+ 410527: '内黄县',
+ 410581: '林州市',
+ 410582: '其它区',
+ 410600: '鹤壁市',
+ 410602: '鹤山区',
+ 410603: '山城区',
+ 410611: '淇滨区',
+ 410621: '浚县',
+ 410622: '淇县',
+ 410623: '其它区',
+ 410700: '新乡市',
+ 410702: '红旗区',
+ 410703: '卫滨区',
+ 410704: '凤泉区',
+ 410711: '牧野区',
+ 410721: '新乡县',
+ 410724: '获嘉县',
+ 410725: '原阳县',
+ 410726: '延津县',
+ 410727: '封丘县',
+ 410728: '长垣县',
+ 410781: '卫辉市',
+ 410782: '辉县市',
+ 410783: '其它区',
+ 410800: '焦作市',
+ 410802: '解放区',
+ 410803: '中站区',
+ 410804: '马村区',
+ 410811: '山阳区',
+ 410821: '修武县',
+ 410822: '博爱县',
+ 410823: '武陟县',
+ 410825: '温县',
+ 410881: '济源市',
+ 410882: '沁阳市',
+ 410883: '孟州市',
+ 410884: '其它区',
+ 410900: '濮阳市',
+ 410902: '华龙区',
+ 410922: '清丰县',
+ 410923: '南乐县',
+ 410926: '范县',
+ 410927: '台前县',
+ 410928: '濮阳县',
+ 410929: '其它区',
+ 411000: '许昌市',
+ 411002: '魏都区',
+ 411023: '许昌县',
+ 411024: '鄢陵县',
+ 411025: '襄城县',
+ 411081: '禹州市',
+ 411082: '长葛市',
+ 411083: '其它区',
+ 411100: '漯河市',
+ 411102: '源汇区',
+ 411103: '郾城区',
+ 411104: '召陵区',
+ 411121: '舞阳县',
+ 411122: '临颍县',
+ 411123: '其它区',
+ 411200: '三门峡市',
+ 411202: '湖滨区',
+ 411221: '渑池县',
+ 411222: '陕县',
+ 411224: '卢氏县',
+ 411281: '义马市',
+ 411282: '灵宝市',
+ 411283: '其它区',
+ 411300: '南阳市',
+ 411302: '宛城区',
+ 411303: '卧龙区',
+ 411321: '南召县',
+ 411322: '方城县',
+ 411323: '西峡县',
+ 411324: '镇平县',
+ 411325: '内乡县',
+ 411326: '淅川县',
+ 411327: '社旗县',
+ 411328: '唐河县',
+ 411329: '新野县',
+ 411330: '桐柏县',
+ 411381: '邓州市',
+ 411382: '其它区',
+ 411400: '商丘市',
+ 411402: '梁园区',
+ 411403: '睢阳区',
+ 411421: '民权县',
+ 411422: '睢县',
+ 411423: '宁陵县',
+ 411424: '柘城县',
+ 411425: '虞城县',
+ 411426: '夏邑县',
+ 411481: '永城市',
+ 411482: '其它区',
+ 411500: '信阳市',
+ 411502: '浉河区',
+ 411503: '平桥区',
+ 411521: '罗山县',
+ 411522: '光山县',
+ 411523: '新县',
+ 411524: '商城县',
+ 411525: '固始县',
+ 411526: '潢川县',
+ 411527: '淮滨县',
+ 411528: '息县',
+ 411529: '其它区',
+ 411600: '周口市',
+ 411602: '川汇区',
+ 411621: '扶沟县',
+ 411622: '西华县',
+ 411623: '商水县',
+ 411624: '沈丘县',
+ 411625: '郸城县',
+ 411626: '淮阳县',
+ 411627: '太康县',
+ 411628: '鹿邑县',
+ 411681: '项城市',
+ 411682: '其它区',
+ 411700: '驻马店市',
+ 411702: '驿城区',
+ 411721: '西平县',
+ 411722: '上蔡县',
+ 411723: '平舆县',
+ 411724: '正阳县',
+ 411725: '确山县',
+ 411726: '泌阳县',
+ 411727: '汝南县',
+ 411728: '遂平县',
+ 411729: '新蔡县',
+ 411730: '其它区',
+ 420000: '湖北省',
+ 420100: '武汉市',
+ 420102: '江岸区',
+ 420103: '江汉区',
+ 420104: '硚口区',
+ 420105: '汉阳区',
+ 420106: '武昌区',
+ 420107: '青山区',
+ 420111: '洪山区',
+ 420112: '东西湖区',
+ 420113: '汉南区',
+ 420114: '蔡甸区',
+ 420115: '江夏区',
+ 420116: '黄陂区',
+ 420117: '新洲区',
+ 420118: '其它区',
+ 420200: '黄石市',
+ 420202: '黄石港区',
+ 420203: '西塞山区',
+ 420204: '下陆区',
+ 420205: '铁山区',
+ 420222: '阳新县',
+ 420281: '大冶市',
+ 420282: '其它区',
+ 420300: '十堰市',
+ 420302: '茅箭区',
+ 420303: '张湾区',
+ 420321: '郧县',
+ 420322: '郧西县',
+ 420323: '竹山县',
+ 420324: '竹溪县',
+ 420325: '房县',
+ 420381: '丹江口市',
+ 420383: '其它区',
+ 420500: '宜昌市',
+ 420502: '西陵区',
+ 420503: '伍家岗区',
+ 420504: '点军区',
+ 420505: '猇亭区',
+ 420506: '夷陵区',
+ 420525: '远安县',
+ 420526: '兴山县',
+ 420527: '秭归县',
+ 420528: '长阳土家族自治县',
+ 420529: '五峰土家族自治县',
+ 420581: '宜都市',
+ 420582: '当阳市',
+ 420583: '枝江市',
+ 420584: '其它区',
+ 420600: '襄阳市',
+ 420602: '襄城区',
+ 420606: '樊城区',
+ 420607: '襄州区',
+ 420624: '南漳县',
+ 420625: '谷城县',
+ 420626: '保康县',
+ 420682: '老河口市',
+ 420683: '枣阳市',
+ 420684: '宜城市',
+ 420685: '其它区',
+ 420700: '鄂州市',
+ 420702: '梁子湖区',
+ 420703: '华容区',
+ 420704: '鄂城区',
+ 420705: '其它区',
+ 420800: '荆门市',
+ 420802: '东宝区',
+ 420804: '掇刀区',
+ 420821: '京山县',
+ 420822: '沙洋县',
+ 420881: '钟祥市',
+ 420882: '其它区',
+ 420900: '孝感市',
+ 420902: '孝南区',
+ 420921: '孝昌县',
+ 420922: '大悟县',
+ 420923: '云梦县',
+ 420981: '应城市',
+ 420982: '安陆市',
+ 420984: '汉川市',
+ 420985: '其它区',
+ 421000: '荆州市',
+ 421002: '沙市区',
+ 421003: '荆州区',
+ 421022: '公安县',
+ 421023: '监利县',
+ 421024: '江陵县',
+ 421081: '石首市',
+ 421083: '洪湖市',
+ 421087: '松滋市',
+ 421088: '其它区',
+ 421100: '黄冈市',
+ 421102: '黄州区',
+ 421121: '团风县',
+ 421122: '红安县',
+ 421123: '罗田县',
+ 421124: '英山县',
+ 421125: '浠水县',
+ 421126: '蕲春县',
+ 421127: '黄梅县',
+ 421181: '麻城市',
+ 421182: '武穴市',
+ 421183: '其它区',
+ 421200: '咸宁市',
+ 421202: '咸安区',
+ 421221: '嘉鱼县',
+ 421222: '通城县',
+ 421223: '崇阳县',
+ 421224: '通山县',
+ 421281: '赤壁市',
+ 421283: '其它区',
+ 421300: '随州市',
+ 421302: '曾都区',
+ 421321: '随县',
+ 421381: '广水市',
+ 421382: '其它区',
+ 422800: '恩施土家族苗族自治州',
+ 422801: '恩施市',
+ 422802: '利川市',
+ 422822: '建始县',
+ 422823: '巴东县',
+ 422825: '宣恩县',
+ 422826: '咸丰县',
+ 422827: '来凤县',
+ 422828: '鹤峰县',
+ 422829: '其它区',
+ 429004: '仙桃市',
+ 429005: '潜江市',
+ 429006: '天门市',
+ 429021: '神农架林区',
+ 430000: '湖南省',
+ 430100: '长沙市',
+ 430102: '芙蓉区',
+ 430103: '天心区',
+ 430104: '岳麓区',
+ 430105: '开福区',
+ 430111: '雨花区',
+ 430121: '长沙县',
+ 430122: '望城区',
+ 430124: '宁乡县',
+ 430181: '浏阳市',
+ 430182: '其它区',
+ 430200: '株洲市',
+ 430202: '荷塘区',
+ 430203: '芦淞区',
+ 430204: '石峰区',
+ 430211: '天元区',
+ 430221: '株洲县',
+ 430223: '攸县',
+ 430224: '茶陵县',
+ 430225: '炎陵县',
+ 430281: '醴陵市',
+ 430282: '其它区',
+ 430300: '湘潭市',
+ 430302: '雨湖区',
+ 430304: '岳塘区',
+ 430321: '湘潭县',
+ 430381: '湘乡市',
+ 430382: '韶山市',
+ 430383: '其它区',
+ 430400: '衡阳市',
+ 430405: '珠晖区',
+ 430406: '雁峰区',
+ 430407: '石鼓区',
+ 430408: '蒸湘区',
+ 430412: '南岳区',
+ 430421: '衡阳县',
+ 430422: '衡南县',
+ 430423: '衡山县',
+ 430424: '衡东县',
+ 430426: '祁东县',
+ 430481: '耒阳市',
+ 430482: '常宁市',
+ 430483: '其它区',
+ 430500: '邵阳市',
+ 430502: '双清区',
+ 430503: '大祥区',
+ 430511: '北塔区',
+ 430521: '邵东县',
+ 430522: '新邵县',
+ 430523: '邵阳县',
+ 430524: '隆回县',
+ 430525: '洞口县',
+ 430527: '绥宁县',
+ 430528: '新宁县',
+ 430529: '城步苗族自治县',
+ 430581: '武冈市',
+ 430582: '其它区',
+ 430600: '岳阳市',
+ 430602: '岳阳楼区',
+ 430603: '云溪区',
+ 430611: '君山区',
+ 430621: '岳阳县',
+ 430623: '华容县',
+ 430624: '湘阴县',
+ 430626: '平江县',
+ 430681: '汨罗市',
+ 430682: '临湘市',
+ 430683: '其它区',
+ 430700: '常德市',
+ 430702: '武陵区',
+ 430703: '鼎城区',
+ 430721: '安乡县',
+ 430722: '汉寿县',
+ 430723: '澧县',
+ 430724: '临澧县',
+ 430725: '桃源县',
+ 430726: '石门县',
+ 430781: '津市市',
+ 430782: '其它区',
+ 430800: '张家界市',
+ 430802: '永定区',
+ 430811: '武陵源区',
+ 430821: '慈利县',
+ 430822: '桑植县',
+ 430823: '其它区',
+ 430900: '益阳市',
+ 430902: '资阳区',
+ 430903: '赫山区',
+ 430921: '南县',
+ 430922: '桃江县',
+ 430923: '安化县',
+ 430981: '沅江市',
+ 430982: '其它区',
+ 431000: '郴州市',
+ 431002: '北湖区',
+ 431003: '苏仙区',
+ 431021: '桂阳县',
+ 431022: '宜章县',
+ 431023: '永兴县',
+ 431024: '嘉禾县',
+ 431025: '临武县',
+ 431026: '汝城县',
+ 431027: '桂东县',
+ 431028: '安仁县',
+ 431081: '资兴市',
+ 431082: '其它区',
+ 431100: '永州市',
+ 431102: '零陵区',
+ 431103: '冷水滩区',
+ 431121: '祁阳县',
+ 431122: '东安县',
+ 431123: '双牌县',
+ 431124: '道县',
+ 431125: '江永县',
+ 431126: '宁远县',
+ 431127: '蓝山县',
+ 431128: '新田县',
+ 431129: '江华瑶族自治县',
+ 431130: '其它区',
+ 431200: '怀化市',
+ 431202: '鹤城区',
+ 431221: '中方县',
+ 431222: '沅陵县',
+ 431223: '辰溪县',
+ 431224: '溆浦县',
+ 431225: '会同县',
+ 431226: '麻阳苗族自治县',
+ 431227: '新晃侗族自治县',
+ 431228: '芷江侗族自治县',
+ 431229: '靖州苗族侗族自治县',
+ 431230: '通道侗族自治县',
+ 431281: '洪江市',
+ 431282: '其它区',
+ 431300: '娄底市',
+ 431302: '娄星区',
+ 431321: '双峰县',
+ 431322: '新化县',
+ 431381: '冷水江市',
+ 431382: '涟源市',
+ 431383: '其它区',
+ 433100: '湘西土家族苗族自治州',
+ 433101: '吉首市',
+ 433122: '泸溪县',
+ 433123: '凤凰县',
+ 433124: '花垣县',
+ 433125: '保靖县',
+ 433126: '古丈县',
+ 433127: '永顺县',
+ 433130: '龙山县',
+ 433131: '其它区',
+ 440000: '广东省',
+ 440100: '广州市',
+ 440103: '荔湾区',
+ 440104: '越秀区',
+ 440105: '海珠区',
+ 440106: '天河区',
+ 440111: '白云区',
+ 440112: '黄埔区',
+ 440113: '番禺区',
+ 440114: '花都区',
+ 440115: '南沙区',
+ 440116: '萝岗区',
+ 440183: '增城市',
+ 440184: '从化市',
+ 440189: '其它区',
+ 440200: '韶关市',
+ 440203: '武江区',
+ 440204: '浈江区',
+ 440205: '曲江区',
+ 440222: '始兴县',
+ 440224: '仁化县',
+ 440229: '翁源县',
+ 440232: '乳源瑶族自治县',
+ 440233: '新丰县',
+ 440281: '乐昌市',
+ 440282: '南雄市',
+ 440283: '其它区',
+ 440300: '深圳市',
+ 440303: '罗湖区',
+ 440304: '福田区',
+ 440305: '南山区',
+ 440306: '宝安区',
+ 440307: '龙岗区',
+ 440308: '盐田区',
+ 440309: '其它区',
+ 440320: '光明新区',
+ 440321: '坪山新区',
+ 440322: '大鹏新区',
+ 440323: '龙华新区',
+ 440400: '珠海市',
+ 440402: '香洲区',
+ 440403: '斗门区',
+ 440404: '金湾区',
+ 440488: '其它区',
+ 440500: '汕头市',
+ 440507: '龙湖区',
+ 440511: '金平区',
+ 440512: '濠江区',
+ 440513: '潮阳区',
+ 440514: '潮南区',
+ 440515: '澄海区',
+ 440523: '南澳县',
+ 440524: '其它区',
+ 440600: '佛山市',
+ 440604: '禅城区',
+ 440605: '南海区',
+ 440606: '顺德区',
+ 440607: '三水区',
+ 440608: '高明区',
+ 440609: '其它区',
+ 440700: '江门市',
+ 440703: '蓬江区',
+ 440704: '江海区',
+ 440705: '新会区',
+ 440781: '台山市',
+ 440783: '开平市',
+ 440784: '鹤山市',
+ 440785: '恩平市',
+ 440786: '其它区',
+ 440800: '湛江市',
+ 440802: '赤坎区',
+ 440803: '霞山区',
+ 440804: '坡头区',
+ 440811: '麻章区',
+ 440823: '遂溪县',
+ 440825: '徐闻县',
+ 440881: '廉江市',
+ 440882: '雷州市',
+ 440883: '吴川市',
+ 440884: '其它区',
+ 440900: '茂名市',
+ 440902: '茂南区',
+ 440903: '茂港区',
+ 440923: '电白县',
+ 440981: '高州市',
+ 440982: '化州市',
+ 440983: '信宜市',
+ 440984: '其它区',
+ 441200: '肇庆市',
+ 441202: '端州区',
+ 441203: '鼎湖区',
+ 441223: '广宁县',
+ 441224: '怀集县',
+ 441225: '封开县',
+ 441226: '德庆县',
+ 441283: '高要市',
+ 441284: '四会市',
+ 441285: '其它区',
+ 441300: '惠州市',
+ 441302: '惠城区',
+ 441303: '惠阳区',
+ 441322: '博罗县',
+ 441323: '惠东县',
+ 441324: '龙门县',
+ 441325: '其它区',
+ 441400: '梅州市',
+ 441402: '梅江区',
+ 441421: '梅县',
+ 441422: '大埔县',
+ 441423: '丰顺县',
+ 441424: '五华县',
+ 441426: '平远县',
+ 441427: '蕉岭县',
+ 441481: '兴宁市',
+ 441482: '其它区',
+ 441500: '汕尾市',
+ 441502: '城区',
+ 441521: '海丰县',
+ 441523: '陆河县',
+ 441581: '陆丰市',
+ 441582: '其它区',
+ 441600: '河源市',
+ 441602: '源城区',
+ 441621: '紫金县',
+ 441622: '龙川县',
+ 441623: '连平县',
+ 441624: '和平县',
+ 441625: '东源县',
+ 441626: '其它区',
+ 441700: '阳江市',
+ 441702: '江城区',
+ 441721: '阳西县',
+ 441723: '阳东县',
+ 441781: '阳春市',
+ 441782: '其它区',
+ 441800: '清远市',
+ 441802: '清城区',
+ 441821: '佛冈县',
+ 441823: '阳山县',
+ 441825: '连山壮族瑶族自治县',
+ 441826: '连南瑶族自治县',
+ 441827: '清新区',
+ 441881: '英德市',
+ 441882: '连州市',
+ 441883: '其它区',
+ 441900: '东莞市',
+ 442000: '中山市',
+ 442101: '东沙群岛',
+ 445100: '潮州市',
+ 445102: '湘桥区',
+ 445121: '潮安区',
+ 445122: '饶平县',
+ 445186: '其它区',
+ 445200: '揭阳市',
+ 445202: '榕城区',
+ 445221: '揭东区',
+ 445222: '揭西县',
+ 445224: '惠来县',
+ 445281: '普宁市',
+ 445285: '其它区',
+ 445300: '云浮市',
+ 445302: '云城区',
+ 445321: '新兴县',
+ 445322: '郁南县',
+ 445323: '云安县',
+ 445381: '罗定市',
+ 445382: '其它区',
+ 450000: '广西壮族自治区',
+ 450100: '南宁市',
+ 450102: '兴宁区',
+ 450103: '青秀区',
+ 450105: '江南区',
+ 450107: '西乡塘区',
+ 450108: '良庆区',
+ 450109: '邕宁区',
+ 450122: '武鸣县',
+ 450123: '隆安县',
+ 450124: '马山县',
+ 450125: '上林县',
+ 450126: '宾阳县',
+ 450127: '横县',
+ 450128: '其它区',
+ 450200: '柳州市',
+ 450202: '城中区',
+ 450203: '鱼峰区',
+ 450204: '柳南区',
+ 450205: '柳北区',
+ 450221: '柳江县',
+ 450222: '柳城县',
+ 450223: '鹿寨县',
+ 450224: '融安县',
+ 450225: '融水苗族自治县',
+ 450226: '三江侗族自治县',
+ 450227: '其它区',
+ 450300: '桂林市',
+ 450302: '秀峰区',
+ 450303: '叠彩区',
+ 450304: '象山区',
+ 450305: '七星区',
+ 450311: '雁山区',
+ 450321: '阳朔县',
+ 450322: '临桂区',
+ 450323: '灵川县',
+ 450324: '全州县',
+ 450325: '兴安县',
+ 450326: '永福县',
+ 450327: '灌阳县',
+ 450328: '龙胜各族自治县',
+ 450329: '资源县',
+ 450330: '平乐县',
+ 450331: '荔浦县',
+ 450332: '恭城瑶族自治县',
+ 450333: '其它区',
+ 450400: '梧州市',
+ 450403: '万秀区',
+ 450405: '长洲区',
+ 450406: '龙圩区',
+ 450421: '苍梧县',
+ 450422: '藤县',
+ 450423: '蒙山县',
+ 450481: '岑溪市',
+ 450482: '其它区',
+ 450500: '北海市',
+ 450502: '海城区',
+ 450503: '银海区',
+ 450512: '铁山港区',
+ 450521: '合浦县',
+ 450522: '其它区',
+ 450600: '防城港市',
+ 450602: '港口区',
+ 450603: '防城区',
+ 450621: '上思县',
+ 450681: '东兴市',
+ 450682: '其它区',
+ 450700: '钦州市',
+ 450702: '钦南区',
+ 450703: '钦北区',
+ 450721: '灵山县',
+ 450722: '浦北县',
+ 450723: '其它区',
+ 450800: '贵港市',
+ 450802: '港北区',
+ 450803: '港南区',
+ 450804: '覃塘区',
+ 450821: '平南县',
+ 450881: '桂平市',
+ 450882: '其它区',
+ 450900: '玉林市',
+ 450902: '玉州区',
+ 450903: '福绵区',
+ 450921: '容县',
+ 450922: '陆川县',
+ 450923: '博白县',
+ 450924: '兴业县',
+ 450981: '北流市',
+ 450982: '其它区',
+ 451000: '百色市',
+ 451002: '右江区',
+ 451021: '田阳县',
+ 451022: '田东县',
+ 451023: '平果县',
+ 451024: '德保县',
+ 451025: '靖西县',
+ 451026: '那坡县',
+ 451027: '凌云县',
+ 451028: '乐业县',
+ 451029: '田林县',
+ 451030: '西林县',
+ 451031: '隆林各族自治县',
+ 451032: '其它区',
+ 451100: '贺州市',
+ 451102: '八步区',
+ 451119: '平桂管理区',
+ 451121: '昭平县',
+ 451122: '钟山县',
+ 451123: '富川瑶族自治县',
+ 451124: '其它区',
+ 451200: '河池市',
+ 451202: '金城江区',
+ 451221: '南丹县',
+ 451222: '天峨县',
+ 451223: '凤山县',
+ 451224: '东兰县',
+ 451225: '罗城仫佬族自治县',
+ 451226: '环江毛南族自治县',
+ 451227: '巴马瑶族自治县',
+ 451228: '都安瑶族自治县',
+ 451229: '大化瑶族自治县',
+ 451281: '宜州市',
+ 451282: '其它区',
+ 451300: '来宾市',
+ 451302: '兴宾区',
+ 451321: '忻城县',
+ 451322: '象州县',
+ 451323: '武宣县',
+ 451324: '金秀瑶族自治县',
+ 451381: '合山市',
+ 451382: '其它区',
+ 451400: '崇左市',
+ 451402: '江州区',
+ 451421: '扶绥县',
+ 451422: '宁明县',
+ 451423: '龙州县',
+ 451424: '大新县',
+ 451425: '天等县',
+ 451481: '凭祥市',
+ 451482: '其它区',
+ 460000: '海南省',
+ 460100: '海口市',
+ 460105: '秀英区',
+ 460106: '龙华区',
+ 460107: '琼山区',
+ 460108: '美兰区',
+ 460109: '其它区',
+ 460200: '三亚市',
+ 460300: '三沙市',
+ 460321: '西沙群岛',
+ 460322: '南沙群岛',
+ 460323: '中沙群岛的岛礁及其海域',
+ 469001: '五指山市',
+ 469002: '琼海市',
+ 469003: '儋州市',
+ 469005: '文昌市',
+ 469006: '万宁市',
+ 469007: '东方市',
+ 469025: '定安县',
+ 469026: '屯昌县',
+ 469027: '澄迈县',
+ 469028: '临高县',
+ 469030: '白沙黎族自治县',
+ 469031: '昌江黎族自治县',
+ 469033: '乐东黎族自治县',
+ 469034: '陵水黎族自治县',
+ 469035: '保亭黎族苗族自治县',
+ 469036: '琼中黎族苗族自治县',
+ 471005: '其它区',
+ 500000: '重庆',
+ 500100: '重庆市',
+ 500101: '万州区',
+ 500102: '涪陵区',
+ 500103: '渝中区',
+ 500104: '大渡口区',
+ 500105: '江北区',
+ 500106: '沙坪坝区',
+ 500107: '九龙坡区',
+ 500108: '南岸区',
+ 500109: '北碚区',
+ 500110: '万盛区',
+ 500111: '双桥区',
+ 500112: '渝北区',
+ 500113: '巴南区',
+ 500114: '黔江区',
+ 500115: '长寿区',
+ 500222: '綦江区',
+ 500223: '潼南县',
+ 500224: '铜梁县',
+ 500225: '大足区',
+ 500226: '荣昌县',
+ 500227: '璧山县',
+ 500228: '梁平县',
+ 500229: '城口县',
+ 500230: '丰都县',
+ 500231: '垫江县',
+ 500232: '武隆县',
+ 500233: '忠县',
+ 500234: '开县',
+ 500235: '云阳县',
+ 500236: '奉节县',
+ 500237: '巫山县',
+ 500238: '巫溪县',
+ 500240: '石柱土家族自治县',
+ 500241: '秀山土家族苗族自治县',
+ 500242: '酉阳土家族苗族自治县',
+ 500243: '彭水苗族土家族自治县',
+ 500381: '江津区',
+ 500382: '合川区',
+ 500383: '永川区',
+ 500384: '南川区',
+ 500385: '其它区',
+ 510000: '四川省',
+ 510100: '成都市',
+ 510104: '锦江区',
+ 510105: '青羊区',
+ 510106: '金牛区',
+ 510107: '武侯区',
+ 510108: '成华区',
+ 510112: '龙泉驿区',
+ 510113: '青白江区',
+ 510114: '新都区',
+ 510115: '温江区',
+ 510121: '金堂县',
+ 510122: '双流县',
+ 510124: '郫县',
+ 510129: '大邑县',
+ 510131: '蒲江县',
+ 510132: '新津县',
+ 510181: '都江堰市',
+ 510182: '彭州市',
+ 510183: '邛崃市',
+ 510184: '崇州市',
+ 510185: '其它区',
+ 510300: '自贡市',
+ 510302: '自流井区',
+ 510303: '贡井区',
+ 510304: '大安区',
+ 510311: '沿滩区',
+ 510321: '荣县',
+ 510322: '富顺县',
+ 510323: '其它区',
+ 510400: '攀枝花市',
+ 510402: '东区',
+ 510403: '西区',
+ 510411: '仁和区',
+ 510421: '米易县',
+ 510422: '盐边县',
+ 510423: '其它区',
+ 510500: '泸州市',
+ 510502: '江阳区',
+ 510503: '纳溪区',
+ 510504: '龙马潭区',
+ 510521: '泸县',
+ 510522: '合江县',
+ 510524: '叙永县',
+ 510525: '古蔺县',
+ 510526: '其它区',
+ 510600: '德阳市',
+ 510603: '旌阳区',
+ 510623: '中江县',
+ 510626: '罗江县',
+ 510681: '广汉市',
+ 510682: '什邡市',
+ 510683: '绵竹市',
+ 510684: '其它区',
+ 510700: '绵阳市',
+ 510703: '涪城区',
+ 510704: '游仙区',
+ 510722: '三台县',
+ 510723: '盐亭县',
+ 510724: '安县',
+ 510725: '梓潼县',
+ 510726: '北川羌族自治县',
+ 510727: '平武县',
+ 510781: '江油市',
+ 510782: '其它区',
+ 510800: '广元市',
+ 510802: '利州区',
+ 510811: '昭化区',
+ 510812: '朝天区',
+ 510821: '旺苍县',
+ 510822: '青川县',
+ 510823: '剑阁县',
+ 510824: '苍溪县',
+ 510825: '其它区',
+ 510900: '遂宁市',
+ 510903: '船山区',
+ 510904: '安居区',
+ 510921: '蓬溪县',
+ 510922: '射洪县',
+ 510923: '大英县',
+ 510924: '其它区',
+ 511000: '内江市',
+ 511002: '市中区',
+ 511011: '东兴区',
+ 511024: '威远县',
+ 511025: '资中县',
+ 511028: '隆昌县',
+ 511029: '其它区',
+ 511100: '乐山市',
+ 511102: '市中区',
+ 511111: '沙湾区',
+ 511112: '五通桥区',
+ 511113: '金口河区',
+ 511123: '犍为县',
+ 511124: '井研县',
+ 511126: '夹江县',
+ 511129: '沐川县',
+ 511132: '峨边彝族自治县',
+ 511133: '马边彝族自治县',
+ 511181: '峨眉山市',
+ 511182: '其它区',
+ 511300: '南充市',
+ 511302: '顺庆区',
+ 511303: '高坪区',
+ 511304: '嘉陵区',
+ 511321: '南部县',
+ 511322: '营山县',
+ 511323: '蓬安县',
+ 511324: '仪陇县',
+ 511325: '西充县',
+ 511381: '阆中市',
+ 511382: '其它区',
+ 511400: '眉山市',
+ 511402: '东坡区',
+ 511421: '仁寿县',
+ 511422: '彭山县',
+ 511423: '洪雅县',
+ 511424: '丹棱县',
+ 511425: '青神县',
+ 511426: '其它区',
+ 511500: '宜宾市',
+ 511502: '翠屏区',
+ 511521: '宜宾县',
+ 511522: '南溪区',
+ 511523: '江安县',
+ 511524: '长宁县',
+ 511525: '高县',
+ 511526: '珙县',
+ 511527: '筠连县',
+ 511528: '兴文县',
+ 511529: '屏山县',
+ 511530: '其它区',
+ 511600: '广安市',
+ 511602: '广安区',
+ 511603: '前锋区',
+ 511621: '岳池县',
+ 511622: '武胜县',
+ 511623: '邻水县',
+ 511681: '华蓥市',
+ 511683: '其它区',
+ 511700: '达州市',
+ 511702: '通川区',
+ 511721: '达川区',
+ 511722: '宣汉县',
+ 511723: '开江县',
+ 511724: '大竹县',
+ 511725: '渠县',
+ 511781: '万源市',
+ 511782: '其它区',
+ 511800: '雅安市',
+ 511802: '雨城区',
+ 511821: '名山区',
+ 511822: '荥经县',
+ 511823: '汉源县',
+ 511824: '石棉县',
+ 511825: '天全县',
+ 511826: '芦山县',
+ 511827: '宝兴县',
+ 511828: '其它区',
+ 511900: '巴中市',
+ 511902: '巴州区',
+ 511903: '恩阳区',
+ 511921: '通江县',
+ 511922: '南江县',
+ 511923: '平昌县',
+ 511924: '其它区',
+ 512000: '资阳市',
+ 512002: '雁江区',
+ 512021: '安岳县',
+ 512022: '乐至县',
+ 512081: '简阳市',
+ 512082: '其它区',
+ 513200: '阿坝藏族羌族自治州',
+ 513221: '汶川县',
+ 513222: '理县',
+ 513223: '茂县',
+ 513224: '松潘县',
+ 513225: '九寨沟县',
+ 513226: '金川县',
+ 513227: '小金县',
+ 513228: '黑水县',
+ 513229: '马尔康县',
+ 513230: '壤塘县',
+ 513231: '阿坝县',
+ 513232: '若尔盖县',
+ 513233: '红原县',
+ 513234: '其它区',
+ 513300: '甘孜藏族自治州',
+ 513321: '康定县',
+ 513322: '泸定县',
+ 513323: '丹巴县',
+ 513324: '九龙县',
+ 513325: '雅江县',
+ 513326: '道孚县',
+ 513327: '炉霍县',
+ 513328: '甘孜县',
+ 513329: '新龙县',
+ 513330: '德格县',
+ 513331: '白玉县',
+ 513332: '石渠县',
+ 513333: '色达县',
+ 513334: '理塘县',
+ 513335: '巴塘县',
+ 513336: '乡城县',
+ 513337: '稻城县',
+ 513338: '得荣县',
+ 513339: '其它区',
+ 513400: '凉山彝族自治州',
+ 513401: '西昌市',
+ 513422: '木里藏族自治县',
+ 513423: '盐源县',
+ 513424: '德昌县',
+ 513425: '会理县',
+ 513426: '会东县',
+ 513427: '宁南县',
+ 513428: '普格县',
+ 513429: '布拖县',
+ 513430: '金阳县',
+ 513431: '昭觉县',
+ 513432: '喜德县',
+ 513433: '冕宁县',
+ 513434: '越西县',
+ 513435: '甘洛县',
+ 513436: '美姑县',
+ 513437: '雷波县',
+ 513438: '其它区',
+ 520000: '贵州省',
+ 520100: '贵阳市',
+ 520102: '南明区',
+ 520103: '云岩区',
+ 520111: '花溪区',
+ 520112: '乌当区',
+ 520113: '白云区',
+ 520121: '开阳县',
+ 520122: '息烽县',
+ 520123: '修文县',
+ 520151: '观山湖区',
+ 520181: '清镇市',
+ 520182: '其它区',
+ 520200: '六盘水市',
+ 520201: '钟山区',
+ 520203: '六枝特区',
+ 520221: '水城县',
+ 520222: '盘县',
+ 520223: '其它区',
+ 520300: '遵义市',
+ 520302: '红花岗区',
+ 520303: '汇川区',
+ 520321: '遵义县',
+ 520322: '桐梓县',
+ 520323: '绥阳县',
+ 520324: '正安县',
+ 520325: '道真仡佬族苗族自治县',
+ 520326: '务川仡佬族苗族自治县',
+ 520327: '凤冈县',
+ 520328: '湄潭县',
+ 520329: '余庆县',
+ 520330: '习水县',
+ 520381: '赤水市',
+ 520382: '仁怀市',
+ 520383: '其它区',
+ 520400: '安顺市',
+ 520402: '西秀区',
+ 520421: '平坝县',
+ 520422: '普定县',
+ 520423: '镇宁布依族苗族自治县',
+ 520424: '关岭布依族苗族自治县',
+ 520425: '紫云苗族布依族自治县',
+ 520426: '其它区',
+ 522200: '铜仁市',
+ 522201: '碧江区',
+ 522222: '江口县',
+ 522223: '玉屏侗族自治县',
+ 522224: '石阡县',
+ 522225: '思南县',
+ 522226: '印江土家族苗族自治县',
+ 522227: '德江县',
+ 522228: '沿河土家族自治县',
+ 522229: '松桃苗族自治县',
+ 522230: '万山区',
+ 522231: '其它区',
+ 522300: '黔西南布依族苗族自治州',
+ 522301: '兴义市',
+ 522322: '兴仁县',
+ 522323: '普安县',
+ 522324: '晴隆县',
+ 522325: '贞丰县',
+ 522326: '望谟县',
+ 522327: '册亨县',
+ 522328: '安龙县',
+ 522329: '其它区',
+ 522400: '毕节市',
+ 522401: '七星关区',
+ 522422: '大方县',
+ 522423: '黔西县',
+ 522424: '金沙县',
+ 522425: '织金县',
+ 522426: '纳雍县',
+ 522427: '威宁彝族回族苗族自治县',
+ 522428: '赫章县',
+ 522429: '其它区',
+ 522600: '黔东南苗族侗族自治州',
+ 522601: '凯里市',
+ 522622: '黄平县',
+ 522623: '施秉县',
+ 522624: '三穗县',
+ 522625: '镇远县',
+ 522626: '岑巩县',
+ 522627: '天柱县',
+ 522628: '锦屏县',
+ 522629: '剑河县',
+ 522630: '台江县',
+ 522631: '黎平县',
+ 522632: '榕江县',
+ 522633: '从江县',
+ 522634: '雷山县',
+ 522635: '麻江县',
+ 522636: '丹寨县',
+ 522637: '其它区',
+ 522700: '黔南布依族苗族自治州',
+ 522701: '都匀市',
+ 522702: '福泉市',
+ 522722: '荔波县',
+ 522723: '贵定县',
+ 522725: '瓮安县',
+ 522726: '独山县',
+ 522727: '平塘县',
+ 522728: '罗甸县',
+ 522729: '长顺县',
+ 522730: '龙里县',
+ 522731: '惠水县',
+ 522732: '三都水族自治县',
+ 522733: '其它区',
+ 530000: '云南省',
+ 530100: '昆明市',
+ 530102: '五华区',
+ 530103: '盘龙区',
+ 530111: '官渡区',
+ 530112: '西山区',
+ 530113: '东川区',
+ 530121: '呈贡区',
+ 530122: '晋宁县',
+ 530124: '富民县',
+ 530125: '宜良县',
+ 530126: '石林彝族自治县',
+ 530127: '嵩明县',
+ 530128: '禄劝彝族苗族自治县',
+ 530129: '寻甸回族彝族自治县',
+ 530181: '安宁市',
+ 530182: '其它区',
+ 530300: '曲靖市',
+ 530302: '麒麟区',
+ 530321: '马龙县',
+ 530322: '陆良县',
+ 530323: '师宗县',
+ 530324: '罗平县',
+ 530325: '富源县',
+ 530326: '会泽县',
+ 530328: '沾益县',
+ 530381: '宣威市',
+ 530382: '其它区',
+ 530400: '玉溪市',
+ 530402: '红塔区',
+ 530421: '江川县',
+ 530422: '澄江县',
+ 530423: '通海县',
+ 530424: '华宁县',
+ 530425: '易门县',
+ 530426: '峨山彝族自治县',
+ 530427: '新平彝族傣族自治县',
+ 530428: '元江哈尼族彝族傣族自治县',
+ 530429: '其它区',
+ 530500: '保山市',
+ 530502: '隆阳区',
+ 530521: '施甸县',
+ 530522: '腾冲县',
+ 530523: '龙陵县',
+ 530524: '昌宁县',
+ 530525: '其它区',
+ 530600: '昭通市',
+ 530602: '昭阳区',
+ 530621: '鲁甸县',
+ 530622: '巧家县',
+ 530623: '盐津县',
+ 530624: '大关县',
+ 530625: '永善县',
+ 530626: '绥江县',
+ 530627: '镇雄县',
+ 530628: '彝良县',
+ 530629: '威信县',
+ 530630: '水富县',
+ 530631: '其它区',
+ 530700: '丽江市',
+ 530702: '古城区',
+ 530721: '玉龙纳西族自治县',
+ 530722: '永胜县',
+ 530723: '华坪县',
+ 530724: '宁蒗彝族自治县',
+ 530725: '其它区',
+ 530800: '普洱市',
+ 530802: '思茅区',
+ 530821: '宁洱哈尼族彝族自治县',
+ 530822: '墨江哈尼族自治县',
+ 530823: '景东彝族自治县',
+ 530824: '景谷傣族彝族自治县',
+ 530825: '镇沅彝族哈尼族拉祜族自治县',
+ 530826: '江城哈尼族彝族自治县',
+ 530827: '孟连傣族拉祜族佤族自治县',
+ 530828: '澜沧拉祜族自治县',
+ 530829: '西盟佤族自治县',
+ 530830: '其它区',
+ 530900: '临沧市',
+ 530902: '临翔区',
+ 530921: '凤庆县',
+ 530922: '云县',
+ 530923: '永德县',
+ 530924: '镇康县',
+ 530925: '双江拉祜族佤族布朗族傣族自治县',
+ 530926: '耿马傣族佤族自治县',
+ 530927: '沧源佤族自治县',
+ 530928: '其它区',
+ 532300: '楚雄彝族自治州',
+ 532301: '楚雄市',
+ 532322: '双柏县',
+ 532323: '牟定县',
+ 532324: '南华县',
+ 532325: '姚安县',
+ 532326: '大姚县',
+ 532327: '永仁县',
+ 532328: '元谋县',
+ 532329: '武定县',
+ 532331: '禄丰县',
+ 532332: '其它区',
+ 532500: '红河哈尼族彝族自治州',
+ 532501: '个旧市',
+ 532502: '开远市',
+ 532522: '蒙自市',
+ 532523: '屏边苗族自治县',
+ 532524: '建水县',
+ 532525: '石屏县',
+ 532526: '弥勒市',
+ 532527: '泸西县',
+ 532528: '元阳县',
+ 532529: '红河县',
+ 532530: '金平苗族瑶族傣族自治县',
+ 532531: '绿春县',
+ 532532: '河口瑶族自治县',
+ 532533: '其它区',
+ 532600: '文山壮族苗族自治州',
+ 532621: '文山市',
+ 532622: '砚山县',
+ 532623: '西畴县',
+ 532624: '麻栗坡县',
+ 532625: '马关县',
+ 532626: '丘北县',
+ 532627: '广南县',
+ 532628: '富宁县',
+ 532629: '其它区',
+ 532800: '西双版纳傣族自治州',
+ 532801: '景洪市',
+ 532822: '勐海县',
+ 532823: '勐腊县',
+ 532824: '其它区',
+ 532900: '大理白族自治州',
+ 532901: '大理市',
+ 532922: '漾濞彝族自治县',
+ 532923: '祥云县',
+ 532924: '宾川县',
+ 532925: '弥渡县',
+ 532926: '南涧彝族自治县',
+ 532927: '巍山彝族回族自治县',
+ 532928: '永平县',
+ 532929: '云龙县',
+ 532930: '洱源县',
+ 532931: '剑川县',
+ 532932: '鹤庆县',
+ 532933: '其它区',
+ 533100: '德宏傣族景颇族自治州',
+ 533102: '瑞丽市',
+ 533103: '芒市',
+ 533122: '梁河县',
+ 533123: '盈江县',
+ 533124: '陇川县',
+ 533125: '其它区',
+ 533300: '怒江傈僳族自治州',
+ 533321: '泸水县',
+ 533323: '福贡县',
+ 533324: '贡山独龙族怒族自治县',
+ 533325: '兰坪白族普米族自治县',
+ 533326: '其它区',
+ 533400: '迪庆藏族自治州',
+ 533421: '香格里拉县',
+ 533422: '德钦县',
+ 533423: '维西傈僳族自治县',
+ 533424: '其它区',
+ 540000: '西藏自治区',
+ 540100: '拉萨市',
+ 540102: '城关区',
+ 540121: '林周县',
+ 540122: '当雄县',
+ 540123: '尼木县',
+ 540124: '曲水县',
+ 540125: '堆龙德庆县',
+ 540126: '达孜县',
+ 540127: '墨竹工卡县',
+ 540128: '其它区',
+ 542100: '昌都地区',
+ 542121: '昌都县',
+ 542122: '江达县',
+ 542123: '贡觉县',
+ 542124: '类乌齐县',
+ 542125: '丁青县',
+ 542126: '察雅县',
+ 542127: '八宿县',
+ 542128: '左贡县',
+ 542129: '芒康县',
+ 542132: '洛隆县',
+ 542133: '边坝县',
+ 542134: '其它区',
+ 542200: '山南地区',
+ 542221: '乃东县',
+ 542222: '扎囊县',
+ 542223: '贡嘎县',
+ 542224: '桑日县',
+ 542225: '琼结县',
+ 542226: '曲松县',
+ 542227: '措美县',
+ 542228: '洛扎县',
+ 542229: '加查县',
+ 542231: '隆子县',
+ 542232: '错那县',
+ 542233: '浪卡子县',
+ 542234: '其它区',
+ 542300: '日喀则地区',
+ 542301: '日喀则市',
+ 542322: '南木林县',
+ 542323: '江孜县',
+ 542324: '定日县',
+ 542325: '萨迦县',
+ 542326: '拉孜县',
+ 542327: '昂仁县',
+ 542328: '谢通门县',
+ 542329: '白朗县',
+ 542330: '仁布县',
+ 542331: '康马县',
+ 542332: '定结县',
+ 542333: '仲巴县',
+ 542334: '亚东县',
+ 542335: '吉隆县',
+ 542336: '聂拉木县',
+ 542337: '萨嘎县',
+ 542338: '岗巴县',
+ 542339: '其它区',
+ 542400: '那曲地区',
+ 542421: '那曲县',
+ 542422: '嘉黎县',
+ 542423: '比如县',
+ 542424: '聂荣县',
+ 542425: '安多县',
+ 542426: '申扎县',
+ 542427: '索县',
+ 542428: '班戈县',
+ 542429: '巴青县',
+ 542430: '尼玛县',
+ 542431: '其它区',
+ 542432: '双湖县',
+ 542500: '阿里地区',
+ 542521: '普兰县',
+ 542522: '札达县',
+ 542523: '噶尔县',
+ 542524: '日土县',
+ 542525: '革吉县',
+ 542526: '改则县',
+ 542527: '措勤县',
+ 542528: '其它区',
+ 542600: '林芝地区',
+ 542621: '林芝县',
+ 542622: '工布江达县',
+ 542623: '米林县',
+ 542624: '墨脱县',
+ 542625: '波密县',
+ 542626: '察隅县',
+ 542627: '朗县',
+ 542628: '其它区',
+ 610000: '陕西省',
+ 610100: '西安市',
+ 610102: '新城区',
+ 610103: '碑林区',
+ 610104: '莲湖区',
+ 610111: '灞桥区',
+ 610112: '未央区',
+ 610113: '雁塔区',
+ 610114: '阎良区',
+ 610115: '临潼区',
+ 610116: '长安区',
+ 610122: '蓝田县',
+ 610124: '周至县',
+ 610125: '户县',
+ 610126: '高陵县',
+ 610127: '其它区',
+ 610200: '铜川市',
+ 610202: '王益区',
+ 610203: '印台区',
+ 610204: '耀州区',
+ 610222: '宜君县',
+ 610223: '其它区',
+ 610300: '宝鸡市',
+ 610302: '渭滨区',
+ 610303: '金台区',
+ 610304: '陈仓区',
+ 610322: '凤翔县',
+ 610323: '岐山县',
+ 610324: '扶风县',
+ 610326: '眉县',
+ 610327: '陇县',
+ 610328: '千阳县',
+ 610329: '麟游县',
+ 610330: '凤县',
+ 610331: '太白县',
+ 610332: '其它区',
+ 610400: '咸阳市',
+ 610402: '秦都区',
+ 610403: '杨陵区',
+ 610404: '渭城区',
+ 610422: '三原县',
+ 610423: '泾阳县',
+ 610424: '乾县',
+ 610425: '礼泉县',
+ 610426: '永寿县',
+ 610427: '彬县',
+ 610428: '长武县',
+ 610429: '旬邑县',
+ 610430: '淳化县',
+ 610431: '武功县',
+ 610481: '兴平市',
+ 610482: '其它区',
+ 610500: '渭南市',
+ 610502: '临渭区',
+ 610521: '华县',
+ 610522: '潼关县',
+ 610523: '大荔县',
+ 610524: '合阳县',
+ 610525: '澄城县',
+ 610526: '蒲城县',
+ 610527: '白水县',
+ 610528: '富平县',
+ 610581: '韩城市',
+ 610582: '华阴市',
+ 610583: '其它区',
+ 610600: '延安市',
+ 610602: '宝塔区',
+ 610621: '延长县',
+ 610622: '延川县',
+ 610623: '子长县',
+ 610624: '安塞县',
+ 610625: '志丹县',
+ 610626: '吴起县',
+ 610627: '甘泉县',
+ 610628: '富县',
+ 610629: '洛川县',
+ 610630: '宜川县',
+ 610631: '黄龙县',
+ 610632: '黄陵县',
+ 610633: '其它区',
+ 610700: '汉中市',
+ 610702: '汉台区',
+ 610721: '南郑县',
+ 610722: '城固县',
+ 610723: '洋县',
+ 610724: '西乡县',
+ 610725: '勉县',
+ 610726: '宁强县',
+ 610727: '略阳县',
+ 610728: '镇巴县',
+ 610729: '留坝县',
+ 610730: '佛坪县',
+ 610731: '其它区',
+ 610800: '榆林市',
+ 610802: '榆阳区',
+ 610821: '神木县',
+ 610822: '府谷县',
+ 610823: '横山县',
+ 610824: '靖边县',
+ 610825: '定边县',
+ 610826: '绥德县',
+ 610827: '米脂县',
+ 610828: '佳县',
+ 610829: '吴堡县',
+ 610830: '清涧县',
+ 610831: '子洲县',
+ 610832: '其它区',
+ 610900: '安康市',
+ 610902: '汉滨区',
+ 610921: '汉阴县',
+ 610922: '石泉县',
+ 610923: '宁陕县',
+ 610924: '紫阳县',
+ 610925: '岚皋县',
+ 610926: '平利县',
+ 610927: '镇坪县',
+ 610928: '旬阳县',
+ 610929: '白河县',
+ 610930: '其它区',
+ 611000: '商洛市',
+ 611002: '商州区',
+ 611021: '洛南县',
+ 611022: '丹凤县',
+ 611023: '商南县',
+ 611024: '山阳县',
+ 611025: '镇安县',
+ 611026: '柞水县',
+ 611027: '其它区',
+ 620000: '甘肃省',
+ 620100: '兰州市',
+ 620102: '城关区',
+ 620103: '七里河区',
+ 620104: '西固区',
+ 620105: '安宁区',
+ 620111: '红古区',
+ 620121: '永登县',
+ 620122: '皋兰县',
+ 620123: '榆中县',
+ 620124: '其它区',
+ 620200: '嘉峪关市',
+ 620300: '金昌市',
+ 620302: '金川区',
+ 620321: '永昌县',
+ 620322: '其它区',
+ 620400: '白银市',
+ 620402: '白银区',
+ 620403: '平川区',
+ 620421: '靖远县',
+ 620422: '会宁县',
+ 620423: '景泰县',
+ 620424: '其它区',
+ 620500: '天水市',
+ 620502: '秦州区',
+ 620503: '麦积区',
+ 620521: '清水县',
+ 620522: '秦安县',
+ 620523: '甘谷县',
+ 620524: '武山县',
+ 620525: '张家川回族自治县',
+ 620526: '其它区',
+ 620600: '武威市',
+ 620602: '凉州区',
+ 620621: '民勤县',
+ 620622: '古浪县',
+ 620623: '天祝藏族自治县',
+ 620624: '其它区',
+ 620700: '张掖市',
+ 620702: '甘州区',
+ 620721: '肃南裕固族自治县',
+ 620722: '民乐县',
+ 620723: '临泽县',
+ 620724: '高台县',
+ 620725: '山丹县',
+ 620726: '其它区',
+ 620800: '平凉市',
+ 620802: '崆峒区',
+ 620821: '泾川县',
+ 620822: '灵台县',
+ 620823: '崇信县',
+ 620824: '华亭县',
+ 620825: '庄浪县',
+ 620826: '静宁县',
+ 620827: '其它区',
+ 620900: '酒泉市',
+ 620902: '肃州区',
+ 620921: '金塔县',
+ 620922: '瓜州县',
+ 620923: '肃北蒙古族自治县',
+ 620924: '阿克塞哈萨克族自治县',
+ 620981: '玉门市',
+ 620982: '敦煌市',
+ 620983: '其它区',
+ 621000: '庆阳市',
+ 621002: '西峰区',
+ 621021: '庆城县',
+ 621022: '环县',
+ 621023: '华池县',
+ 621024: '合水县',
+ 621025: '正宁县',
+ 621026: '宁县',
+ 621027: '镇原县',
+ 621028: '其它区',
+ 621100: '定西市',
+ 621102: '安定区',
+ 621121: '通渭县',
+ 621122: '陇西县',
+ 621123: '渭源县',
+ 621124: '临洮县',
+ 621125: '漳县',
+ 621126: '岷县',
+ 621127: '其它区',
+ 621200: '陇南市',
+ 621202: '武都区',
+ 621221: '成县',
+ 621222: '文县',
+ 621223: '宕昌县',
+ 621224: '康县',
+ 621225: '西和县',
+ 621226: '礼县',
+ 621227: '徽县',
+ 621228: '两当县',
+ 621229: '其它区',
+ 622900: '临夏回族自治州',
+ 622901: '临夏市',
+ 622921: '临夏县',
+ 622922: '康乐县',
+ 622923: '永靖县',
+ 622924: '广河县',
+ 622925: '和政县',
+ 622926: '东乡族自治县',
+ 622927: '积石山保安族东乡族撒拉族自治县',
+ 622928: '其它区',
+ 623000: '甘南藏族自治州',
+ 623001: '合作市',
+ 623021: '临潭县',
+ 623022: '卓尼县',
+ 623023: '舟曲县',
+ 623024: '迭部县',
+ 623025: '玛曲县',
+ 623026: '碌曲县',
+ 623027: '夏河县',
+ 623028: '其它区',
+ 630000: '青海省',
+ 630100: '西宁市',
+ 630102: '城东区',
+ 630103: '城中区',
+ 630104: '城西区',
+ 630105: '城北区',
+ 630121: '大通回族土族自治县',
+ 630122: '湟中县',
+ 630123: '湟源县',
+ 630124: '其它区',
+ 632100: '海东市',
+ 632121: '平安县',
+ 632122: '民和回族土族自治县',
+ 632123: '乐都区',
+ 632126: '互助土族自治县',
+ 632127: '化隆回族自治县',
+ 632128: '循化撒拉族自治县',
+ 632129: '其它区',
+ 632200: '海北藏族自治州',
+ 632221: '门源回族自治县',
+ 632222: '祁连县',
+ 632223: '海晏县',
+ 632224: '刚察县',
+ 632225: '其它区',
+ 632300: '黄南藏族自治州',
+ 632321: '同仁县',
+ 632322: '尖扎县',
+ 632323: '泽库县',
+ 632324: '河南蒙古族自治县',
+ 632325: '其它区',
+ 632500: '海南藏族自治州',
+ 632521: '共和县',
+ 632522: '同德县',
+ 632523: '贵德县',
+ 632524: '兴海县',
+ 632525: '贵南县',
+ 632526: '其它区',
+ 632600: '果洛藏族自治州',
+ 632621: '玛沁县',
+ 632622: '班玛县',
+ 632623: '甘德县',
+ 632624: '达日县',
+ 632625: '久治县',
+ 632626: '玛多县',
+ 632627: '其它区',
+ 632700: '玉树藏族自治州',
+ 632721: '玉树市',
+ 632722: '杂多县',
+ 632723: '称多县',
+ 632724: '治多县',
+ 632725: '囊谦县',
+ 632726: '曲麻莱县',
+ 632727: '其它区',
+ 632800: '海西蒙古族藏族自治州',
+ 632801: '格尔木市',
+ 632802: '德令哈市',
+ 632821: '乌兰县',
+ 632822: '都兰县',
+ 632823: '天峻县',
+ 632824: '其它区',
+ 640000: '宁夏回族自治区',
+ 640100: '银川市',
+ 640104: '兴庆区',
+ 640105: '西夏区',
+ 640106: '金凤区',
+ 640121: '永宁县',
+ 640122: '贺兰县',
+ 640181: '灵武市',
+ 640182: '其它区',
+ 640200: '石嘴山市',
+ 640202: '大武口区',
+ 640205: '惠农区',
+ 640221: '平罗县',
+ 640222: '其它区',
+ 640300: '吴忠市',
+ 640302: '利通区',
+ 640303: '红寺堡区',
+ 640323: '盐池县',
+ 640324: '同心县',
+ 640381: '青铜峡市',
+ 640382: '其它区',
+ 640400: '固原市',
+ 640402: '原州区',
+ 640422: '西吉县',
+ 640423: '隆德县',
+ 640424: '泾源县',
+ 640425: '彭阳县',
+ 640426: '其它区',
+ 640500: '中卫市',
+ 640502: '沙坡头区',
+ 640521: '中宁县',
+ 640522: '海原县',
+ 640523: '其它区',
+ 650000: '新疆维吾尔自治区',
+ 650100: '乌鲁木齐市',
+ 650102: '天山区',
+ 650103: '沙依巴克区',
+ 650104: '新市区',
+ 650105: '水磨沟区',
+ 650106: '头屯河区',
+ 650107: '达坂城区',
+ 650109: '米东区',
+ 650121: '乌鲁木齐县',
+ 650122: '其它区',
+ 650200: '克拉玛依市',
+ 650202: '独山子区',
+ 650203: '克拉玛依区',
+ 650204: '白碱滩区',
+ 650205: '乌尔禾区',
+ 650206: '其它区',
+ 652100: '吐鲁番地区',
+ 652101: '吐鲁番市',
+ 652122: '鄯善县',
+ 652123: '托克逊县',
+ 652124: '其它区',
+ 652200: '哈密地区',
+ 652201: '哈密市',
+ 652222: '巴里坤哈萨克自治县',
+ 652223: '伊吾县',
+ 652224: '其它区',
+ 652300: '昌吉回族自治州',
+ 652301: '昌吉市',
+ 652302: '阜康市',
+ 652323: '呼图壁县',
+ 652324: '玛纳斯县',
+ 652325: '奇台县',
+ 652327: '吉木萨尔县',
+ 652328: '木垒哈萨克自治县',
+ 652329: '其它区',
+ 652700: '博尔塔拉蒙古自治州',
+ 652701: '博乐市',
+ 652702: '阿拉山口市',
+ 652722: '精河县',
+ 652723: '温泉县',
+ 652724: '其它区',
+ 652800: '巴音郭楞蒙古自治州',
+ 652801: '库尔勒市',
+ 652822: '轮台县',
+ 652823: '尉犁县',
+ 652824: '若羌县',
+ 652825: '且末县',
+ 652826: '焉耆回族自治县',
+ 652827: '和静县',
+ 652828: '和硕县',
+ 652829: '博湖县',
+ 652830: '其它区',
+ 652900: '阿克苏地区',
+ 652901: '阿克苏市',
+ 652922: '温宿县',
+ 652923: '库车县',
+ 652924: '沙雅县',
+ 652925: '新和县',
+ 652926: '拜城县',
+ 652927: '乌什县',
+ 652928: '阿瓦提县',
+ 652929: '柯坪县',
+ 652930: '其它区',
+ 653000: '克孜勒苏柯尔克孜自治州',
+ 653001: '阿图什市',
+ 653022: '阿克陶县',
+ 653023: '阿合奇县',
+ 653024: '乌恰县',
+ 653025: '其它区',
+ 653100: '喀什地区',
+ 653101: '喀什市',
+ 653121: '疏附县',
+ 653122: '疏勒县',
+ 653123: '英吉沙县',
+ 653124: '泽普县',
+ 653125: '莎车县',
+ 653126: '叶城县',
+ 653127: '麦盖提县',
+ 653128: '岳普湖县',
+ 653129: '伽师县',
+ 653130: '巴楚县',
+ 653131: '塔什库尔干塔吉克自治县',
+ 653132: '其它区',
+ 653200: '和田地区',
+ 653201: '和田市',
+ 653221: '和田县',
+ 653222: '墨玉县',
+ 653223: '皮山县',
+ 653224: '洛浦县',
+ 653225: '策勒县',
+ 653226: '于田县',
+ 653227: '民丰县',
+ 653228: '其它区',
+ 654000: '伊犁哈萨克自治州',
+ 654002: '伊宁市',
+ 654003: '奎屯市',
+ 654021: '伊宁县',
+ 654022: '察布查尔锡伯自治县',
+ 654023: '霍城县',
+ 654024: '巩留县',
+ 654025: '新源县',
+ 654026: '昭苏县',
+ 654027: '特克斯县',
+ 654028: '尼勒克县',
+ 654029: '其它区',
+ 654200: '塔城地区',
+ 654201: '塔城市',
+ 654202: '乌苏市',
+ 654221: '额敏县',
+ 654223: '沙湾县',
+ 654224: '托里县',
+ 654225: '裕民县',
+ 654226: '和布克赛尔蒙古自治县',
+ 654227: '其它区',
+ 654300: '阿勒泰地区',
+ 654301: '阿勒泰市',
+ 654321: '布尔津县',
+ 654322: '富蕴县',
+ 654323: '福海县',
+ 654324: '哈巴河县',
+ 654325: '青河县',
+ 654326: '吉木乃县',
+ 654327: '其它区',
+ 659001: '石河子市',
+ 659002: '阿拉尔市',
+ 659003: '图木舒克市',
+ 659004: '五家渠市',
+ 710000: '台湾',
+ 710100: '台北市',
+ 710101: '中正区',
+ 710102: '大同区',
+ 710103: '中山区',
+ 710104: '松山区',
+ 710105: '大安区',
+ 710106: '万华区',
+ 710107: '信义区',
+ 710108: '士林区',
+ 710109: '北投区',
+ 710110: '内湖区',
+ 710111: '南港区',
+ 710112: '文山区',
+ 710113: '其它区',
+ 710200: '高雄市',
+ 710201: '新兴区',
+ 710202: '前金区',
+ 710203: '芩雅区',
+ 710204: '盐埕区',
+ 710205: '鼓山区',
+ 710206: '旗津区',
+ 710207: '前镇区',
+ 710208: '三民区',
+ 710209: '左营区',
+ 710210: '楠梓区',
+ 710211: '小港区',
+ 710212: '其它区',
+ 710241: '苓雅区',
+ 710242: '仁武区',
+ 710243: '大社区',
+ 710244: '冈山区',
+ 710245: '路竹区',
+ 710246: '阿莲区',
+ 710247: '田寮区',
+ 710248: '燕巢区',
+ 710249: '桥头区',
+ 710250: '梓官区',
+ 710251: '弥陀区',
+ 710252: '永安区',
+ 710253: '湖内区',
+ 710254: '凤山区',
+ 710255: '大寮区',
+ 710256: '林园区',
+ 710257: '鸟松区',
+ 710258: '大树区',
+ 710259: '旗山区',
+ 710260: '美浓区',
+ 710261: '六龟区',
+ 710262: '内门区',
+ 710263: '杉林区',
+ 710264: '甲仙区',
+ 710265: '桃源区',
+ 710266: '那玛夏区',
+ 710267: '茂林区',
+ 710268: '茄萣区',
+ 710300: '台南市',
+ 710301: '中西区',
+ 710302: '东区',
+ 710303: '南区',
+ 710304: '北区',
+ 710305: '安平区',
+ 710306: '安南区',
+ 710307: '其它区',
+ 710339: '永康区',
+ 710340: '归仁区',
+ 710341: '新化区',
+ 710342: '左镇区',
+ 710343: '玉井区',
+ 710344: '楠西区',
+ 710345: '南化区',
+ 710346: '仁德区',
+ 710347: '关庙区',
+ 710348: '龙崎区',
+ 710349: '官田区',
+ 710350: '麻豆区',
+ 710351: '佳里区',
+ 710352: '西港区',
+ 710353: '七股区',
+ 710354: '将军区',
+ 710355: '学甲区',
+ 710356: '北门区',
+ 710357: '新营区',
+ 710358: '后壁区',
+ 710359: '白河区',
+ 710360: '东山区',
+ 710361: '六甲区',
+ 710362: '下营区',
+ 710363: '柳营区',
+ 710364: '盐水区',
+ 710365: '善化区',
+ 710366: '大内区',
+ 710367: '山上区',
+ 710368: '新市区',
+ 710369: '安定区',
+ 710400: '台中市',
+ 710401: '中区',
+ 710402: '东区',
+ 710403: '南区',
+ 710404: '西区',
+ 710405: '北区',
+ 710406: '北屯区',
+ 710407: '西屯区',
+ 710408: '南屯区',
+ 710409: '其它区',
+ 710431: '太平区',
+ 710432: '大里区',
+ 710433: '雾峰区',
+ 710434: '乌日区',
+ 710435: '丰原区',
+ 710436: '后里区',
+ 710437: '石冈区',
+ 710438: '东势区',
+ 710439: '和平区',
+ 710440: '新社区',
+ 710441: '潭子区',
+ 710442: '大雅区',
+ 710443: '神冈区',
+ 710444: '大肚区',
+ 710445: '沙鹿区',
+ 710446: '龙井区',
+ 710447: '梧栖区',
+ 710448: '清水区',
+ 710449: '大甲区',
+ 710450: '外埔区',
+ 710451: '大安区',
+ 710500: '金门县',
+ 710507: '金沙镇',
+ 710508: '金湖镇',
+ 710509: '金宁乡',
+ 710510: '金城镇',
+ 710511: '烈屿乡',
+ 710512: '乌坵乡',
+ 710600: '南投县',
+ 710614: '南投市',
+ 710615: '中寮乡',
+ 710616: '草屯镇',
+ 710617: '国姓乡',
+ 710618: '埔里镇',
+ 710619: '仁爱乡',
+ 710620: '名间乡',
+ 710621: '集集镇',
+ 710622: '水里乡',
+ 710623: '鱼池乡',
+ 710624: '信义乡',
+ 710625: '竹山镇',
+ 710626: '鹿谷乡',
+ 710700: '基隆市',
+ 710701: '仁爱区',
+ 710702: '信义区',
+ 710703: '中正区',
+ 710704: '中山区',
+ 710705: '安乐区',
+ 710706: '暖暖区',
+ 710707: '七堵区',
+ 710708: '其它区',
+ 710800: '新竹市',
+ 710801: '东区',
+ 710802: '北区',
+ 710803: '香山区',
+ 710804: '其它区',
+ 710900: '嘉义市',
+ 710901: '东区',
+ 710902: '西区',
+ 710903: '其它区',
+ 711100: '新北市',
+ 711130: '万里区',
+ 711131: '金山区',
+ 711132: '板桥区',
+ 711133: '汐止区',
+ 711134: '深坑区',
+ 711135: '石碇区',
+ 711136: '瑞芳区',
+ 711137: '平溪区',
+ 711138: '双溪区',
+ 711139: '贡寮区',
+ 711140: '新店区',
+ 711141: '坪林区',
+ 711142: '乌来区',
+ 711143: '永和区',
+ 711144: '中和区',
+ 711145: '土城区',
+ 711146: '三峡区',
+ 711147: '树林区',
+ 711148: '莺歌区',
+ 711149: '三重区',
+ 711150: '新庄区',
+ 711151: '泰山区',
+ 711152: '林口区',
+ 711153: '芦洲区',
+ 711154: '五股区',
+ 711155: '八里区',
+ 711156: '淡水区',
+ 711157: '三芝区',
+ 711158: '石门区',
+ 711200: '宜兰县',
+ 711214: '宜兰市',
+ 711215: '头城镇',
+ 711216: '礁溪乡',
+ 711217: '壮围乡',
+ 711218: '员山乡',
+ 711219: '罗东镇',
+ 711220: '三星乡',
+ 711221: '大同乡',
+ 711222: '五结乡',
+ 711223: '冬山乡',
+ 711224: '苏澳镇',
+ 711225: '南澳乡',
+ 711226: '钓鱼台',
+ 711300: '新竹县',
+ 711314: '竹北市',
+ 711315: '湖口乡',
+ 711316: '新丰乡',
+ 711317: '新埔镇',
+ 711318: '关西镇',
+ 711319: '芎林乡',
+ 711320: '宝山乡',
+ 711321: '竹东镇',
+ 711322: '五峰乡',
+ 711323: '横山乡',
+ 711324: '尖石乡',
+ 711325: '北埔乡',
+ 711326: '峨眉乡',
+ 711400: '桃园县',
+ 711414: '中坜市',
+ 711415: '平镇市',
+ 711416: '龙潭乡',
+ 711417: '杨梅市',
+ 711418: '新屋乡',
+ 711419: '观音乡',
+ 711420: '桃园市',
+ 711421: '龟山乡',
+ 711422: '八德市',
+ 711423: '大溪镇',
+ 711424: '复兴乡',
+ 711425: '大园乡',
+ 711426: '芦竹乡',
+ 711500: '苗栗县',
+ 711519: '竹南镇',
+ 711520: '头份镇',
+ 711521: '三湾乡',
+ 711522: '南庄乡',
+ 711523: '狮潭乡',
+ 711524: '后龙镇',
+ 711525: '通霄镇',
+ 711526: '苑里镇',
+ 711527: '苗栗市',
+ 711528: '造桥乡',
+ 711529: '头屋乡',
+ 711530: '公馆乡',
+ 711531: '大湖乡',
+ 711532: '泰安乡',
+ 711533: '铜锣乡',
+ 711534: '三义乡',
+ 711535: '西湖乡',
+ 711536: '卓兰镇',
+ 711700: '彰化县',
+ 711727: '彰化市',
+ 711728: '芬园乡',
+ 711729: '花坛乡',
+ 711730: '秀水乡',
+ 711731: '鹿港镇',
+ 711732: '福兴乡',
+ 711733: '线西乡',
+ 711734: '和美镇',
+ 711735: '伸港乡',
+ 711736: '员林镇',
+ 711737: '社头乡',
+ 711738: '永靖乡',
+ 711739: '埔心乡',
+ 711740: '溪湖镇',
+ 711741: '大村乡',
+ 711742: '埔盐乡',
+ 711743: '田中镇',
+ 711744: '北斗镇',
+ 711745: '田尾乡',
+ 711746: '埤头乡',
+ 711747: '溪州乡',
+ 711748: '竹塘乡',
+ 711749: '二林镇',
+ 711750: '大城乡',
+ 711751: '芳苑乡',
+ 711752: '二水乡',
+ 711900: '嘉义县',
+ 711919: '番路乡',
+ 711920: '梅山乡',
+ 711921: '竹崎乡',
+ 711922: '阿里山乡',
+ 711923: '中埔乡',
+ 711924: '大埔乡',
+ 711925: '水上乡',
+ 711926: '鹿草乡',
+ 711927: '太保市',
+ 711928: '朴子市',
+ 711929: '东石乡',
+ 711930: '六脚乡',
+ 711931: '新港乡',
+ 711932: '民雄乡',
+ 711933: '大林镇',
+ 711934: '溪口乡',
+ 711935: '义竹乡',
+ 711936: '布袋镇',
+ 712100: '云林县',
+ 712121: '斗南镇',
+ 712122: '大埤乡',
+ 712123: '虎尾镇',
+ 712124: '土库镇',
+ 712125: '褒忠乡',
+ 712126: '东势乡',
+ 712127: '台西乡',
+ 712128: '仑背乡',
+ 712129: '麦寮乡',
+ 712130: '斗六市',
+ 712131: '林内乡',
+ 712132: '古坑乡',
+ 712133: '莿桐乡',
+ 712134: '西螺镇',
+ 712135: '二仑乡',
+ 712136: '北港镇',
+ 712137: '水林乡',
+ 712138: '口湖乡',
+ 712139: '四湖乡',
+ 712140: '元长乡',
+ 712400: '屏东县',
+ 712434: '屏东市',
+ 712435: '三地门乡',
+ 712436: '雾台乡',
+ 712437: '玛家乡',
+ 712438: '九如乡',
+ 712439: '里港乡',
+ 712440: '高树乡',
+ 712441: '盐埔乡',
+ 712442: '长治乡',
+ 712443: '麟洛乡',
+ 712444: '竹田乡',
+ 712445: '内埔乡',
+ 712446: '万丹乡',
+ 712447: '潮州镇',
+ 712448: '泰武乡',
+ 712449: '来义乡',
+ 712450: '万峦乡',
+ 712451: '崁顶乡',
+ 712452: '新埤乡',
+ 712453: '南州乡',
+ 712454: '林边乡',
+ 712455: '东港镇',
+ 712456: '琉球乡',
+ 712457: '佳冬乡',
+ 712458: '新园乡',
+ 712459: '枋寮乡',
+ 712460: '枋山乡',
+ 712461: '春日乡',
+ 712462: '狮子乡',
+ 712463: '车城乡',
+ 712464: '牡丹乡',
+ 712465: '恒春镇',
+ 712466: '满州乡',
+ 712500: '台东县',
+ 712517: '台东市',
+ 712518: '绿岛乡',
+ 712519: '兰屿乡',
+ 712520: '延平乡',
+ 712521: '卑南乡',
+ 712522: '鹿野乡',
+ 712523: '关山镇',
+ 712524: '海端乡',
+ 712525: '池上乡',
+ 712526: '东河乡',
+ 712527: '成功镇',
+ 712528: '长滨乡',
+ 712529: '金峰乡',
+ 712530: '大武乡',
+ 712531: '达仁乡',
+ 712532: '太麻里乡',
+ 712600: '花莲县',
+ 712615: '花莲市',
+ 712616: '新城乡',
+ 712617: '太鲁阁',
+ 712618: '秀林乡',
+ 712619: '吉安乡',
+ 712620: '寿丰乡',
+ 712621: '凤林镇',
+ 712622: '光复乡',
+ 712623: '丰滨乡',
+ 712624: '瑞穗乡',
+ 712625: '万荣乡',
+ 712626: '玉里镇',
+ 712627: '卓溪乡',
+ 712628: '富里乡',
+ 712700: '澎湖县',
+ 712707: '马公市',
+ 712708: '西屿乡',
+ 712709: '望安乡',
+ 712710: '七美乡',
+ 712711: '白沙乡',
+ 712712: '湖西乡',
+ 712800: '连江县',
+ 712805: '南竿乡',
+ 712806: '北竿乡',
+ 712807: '莒光乡',
+ 712808: '东引乡',
+ 810000: '香港特别行政区',
+ 810100: '香港岛',
+ 810101: '中西区',
+ 810102: '湾仔',
+ 810103: '东区',
+ 810104: '南区',
+ 810200: '九龙',
+ 810201: '九龙城区',
+ 810202: '油尖旺区',
+ 810203: '深水埗区',
+ 810204: '黄大仙区',
+ 810205: '观塘区',
+ 810300: '新界',
+ 810301: '北区',
+ 810302: '大埔区',
+ 810303: '沙田区',
+ 810304: '西贡区',
+ 810305: '元朗区',
+ 810306: '屯门区',
+ 810307: '荃湾区',
+ 810308: '葵青区',
+ 810309: '离岛区',
+ 820000: '澳门特别行政区',
+ 820100: '澳门半岛',
+ 820200: '离岛',
+ 990000: '海外',
+ 990100: '海外',
+}
+
+const tree = list => {
+ let hashTable = Object.create(null)
+ list.forEach(aData => (hashTable[aData.id] = { ...aData, children: [] }))
+ let dataTree = []
+ list.forEach(aData => {
+ if (aData.pid) {
+ if (hashTable[aData.pid])
+ hashTable[aData.pid].children.push(hashTable[aData.id])
+ } else dataTree.push(hashTable[aData.id])
+ })
+ return dataTree
+}
+
+let DICT_FIXED = (function() {
+ let fixed = []
+ for (let id in DICT) {
+ if ({}.hasOwnProperty.call(DICT, id)) {
+ let pid
+ const tmpObj = { id, value: DICT[id], label: DICT[id] }
+ if (id.slice(2, 6) !== '0000') {
+ pid =
+ id.slice(4, 6) === '00'
+ ? `${id.slice(0, 2)}0000`
+ : `${id.slice(0, 4)}00`
+ }
+ if (pid) tmpObj.pid = pid
+ fixed.push(tmpObj)
+ }
+ }
+ return tree(fixed)
+})()
+
+export default DICT_FIXED
diff --git a/src/utils/config.js b/src/utils/config.js
new file mode 100644
index 0000000..61e4b07
--- /dev/null
+++ b/src/utils/config.js
@@ -0,0 +1,39 @@
+module.exports = {
+ siteName: 'AntD Admin',
+ copyright: 'Ant Design Admin ©2020 zuiidea',
+ logoPath: '/logo.svg',
+ apiPrefix: '/api/v1',
+ fixedHeader: true, // sticky primary layout header
+
+ /* Layout configuration, specify which layout to use for route. */
+ layouts: [
+ {
+ name: 'primary',
+ include: [/.*/],
+ exclude: [/(\/(en|zh))*\/login/],
+ },
+ ],
+
+ /* I18n configuration, `languages` and `defaultLanguage` are required currently. */
+ i18n: {
+ /* Countrys flags: https://www.flaticon.com/packs/countrys-flags */
+ languages: [
+ {
+ key: 'pt-br',
+ title: 'Português',
+ flag: '/portugal.svg',
+ },
+ {
+ key: 'en',
+ title: 'English',
+ flag: '/america.svg',
+ },
+ {
+ key: 'zh',
+ title: '中文',
+ flag: '/china.svg',
+ },
+ ],
+ defaultLanguage: 'zh',
+ },
+}
diff --git a/src/utils/constant.js b/src/utils/constant.js
new file mode 100644
index 0000000..3ca2222
--- /dev/null
+++ b/src/utils/constant.js
@@ -0,0 +1,7 @@
+export const ROLE_TYPE = {
+ ADMIN: 'admin',
+ DEFAULT: 'admin',
+ DEVELOPER: 'developer',
+}
+
+export const CANCEL_REQUEST_MESSAGE = 'cancel request'
diff --git a/src/utils/iconMap.jsx b/src/utils/iconMap.jsx
new file mode 100644
index 0000000..ceacadf
--- /dev/null
+++ b/src/utils/iconMap.jsx
@@ -0,0 +1,31 @@
+import {
+ PayCircleOutlined,
+ ShoppingCartOutlined,
+ MessageOutlined,
+ TeamOutlined,
+ UserOutlined,
+ DashboardOutlined,
+ ApiOutlined,
+ CameraOutlined,
+ EditOutlined,
+ CodeOutlined,
+ LineOutlined,
+ BarChartOutlined,
+ AreaChartOutlined,
+} from '@ant-design/icons'
+
+export default {
+ 'pay-circle-o': ,
+ 'shopping-cart': ,
+ 'camera-o': ,
+ 'line-chart': ,
+ 'code-o': ,
+ 'area-chart': ,
+ 'bar-chart': ,
+ message: ,
+ team: ,
+ dashboard: ,
+ user: ,
+ api: ,
+ edit: ,
+}
diff --git a/src/utils/index.js b/src/utils/index.js
new file mode 100644
index 0000000..925bc5b
--- /dev/null
+++ b/src/utils/index.js
@@ -0,0 +1,172 @@
+import { cloneDeep } from 'lodash'
+const { pathToRegexp } = require("path-to-regexp")
+import moment from 'moment'
+import 'moment/locale/zh-cn'
+import store from 'store'
+import { i18n } from './config'
+
+export classnames from 'classnames'
+export config from './config'
+export request from './request'
+export { Color } from './theme'
+
+export const languages = i18n ? i18n.languages.map(item => item.key) : []
+export const defaultLanguage = i18n ? i18n.defaultLanguage : ''
+
+/**
+ * Query objects that specify keys and values in an array where all values are objects.
+ * @param {array} array An array where all values are objects, like [{key:1},{key:2}].
+ * @param {string} key The key of the object that needs to be queried.
+ * @param {string} value The value of the object that needs to be queried.
+ * @return {object|undefined} Return frist object when query success.
+ */
+export function queryArray(array, key, value) {
+ if (!Array.isArray(array)) {
+ return
+ }
+ return array.find(_ => _[key] === value)
+}
+
+/**
+ * Convert an array to a tree-structured array.
+ * @param {array} array The Array need to Converted.
+ * @param {string} id The alias of the unique ID of the object in the array.
+ * @param {string} parentId The alias of the parent ID of the object in the array.
+ * @param {string} children The alias of children of the object in the array.
+ * @return {array} Return a tree-structured array.
+ */
+export function arrayToTree(
+ array,
+ id = 'id',
+ parentId = 'pid',
+ children = 'children'
+) {
+ const result = []
+ const hash = {}
+ const data = cloneDeep(array)
+
+ data.forEach((item, index) => {
+ hash[data[index][id]] = data[index]
+ })
+
+ data.forEach(item => {
+ const hashParent = hash[item[parentId]]
+ if (hashParent) {
+ !hashParent[children] && (hashParent[children] = [])
+ hashParent[children].push(item)
+ } else {
+ result.push(item)
+ }
+ })
+ return result
+}
+
+
+
+/**
+ * In an array object, traverse all parent IDs based on the value of an object.
+ * @param {array} array The Array need to Converted.
+ * @param {string} current Specify the value of the object that needs to be queried.
+ * @param {string} parentId The alias of the parent ID of the object in the array.
+ * @param {string} id The alias of the unique ID of the object in the array.
+ * @return {array} Return a key array.
+ */
+export function queryPathKeys(array, current, parentId, id = 'id') {
+ const result = [current]
+ const hashMap = new Map()
+ array.forEach(item => hashMap.set(item[id], item))
+
+ const getPath = current => {
+ const currentParentId = hashMap.get(current)[parentId]
+ if (currentParentId) {
+ result.push(currentParentId)
+ getPath(currentParentId)
+ }
+ }
+
+ getPath(current)
+ return result
+}
+
+/**
+ * In an array of objects, specify an object that traverses the objects whose parent ID matches.
+ * @param {array} array The Array need to Converted.
+ * @param {string} current Specify the object that needs to be queried.
+ * @param {string} parentId The alias of the parent ID of the object in the array.
+ * @param {string} id The alias of the unique ID of the object in the array.
+ * @return {array} Return a key array.
+ */
+export function queryAncestors(array, current, parentId, id = 'id') {
+ const result = [current]
+ const hashMap = new Map()
+ array.forEach(item => hashMap.set(item[id], item))
+
+ const getPath = current => {
+ const currentParentId = hashMap.get(current[id])[parentId]
+ if (currentParentId) {
+ result.push(hashMap.get(currentParentId))
+ getPath(hashMap.get(currentParentId))
+ }
+ }
+
+ getPath(current)
+ return result
+}
+
+/**
+ * Query which layout should be used for the current path based on the configuration.
+ * @param {layouts} layouts Layout configuration.
+ * @param {pathname} pathname Path name to be queried.
+ * @return {string} Return frist object when query success.
+ */
+export function queryLayout(layouts, pathname) {
+ let result = 'public'
+
+ const isMatch = regepx => {
+ return regepx instanceof RegExp
+ ? regepx.test(pathname)
+ : pathToRegexp(regepx).exec(pathname)
+ }
+
+ for (const item of layouts) {
+ let include = false
+ let exclude = false
+ if (item.include) {
+ for (const regepx of item.include) {
+ if (isMatch(regepx)) {
+ include = true
+ break
+ }
+ }
+ }
+
+ if (include && item.exclude) {
+ for (const regepx of item.exclude) {
+ if (isMatch(regepx)) {
+ exclude = true
+ break
+ }
+ }
+ }
+
+ if (include && !exclude) {
+ result = item.name
+ break
+ }
+ }
+
+ return result
+}
+
+
+export function getLocale() {
+ return store.get('locale') || defaultLanguage
+}
+
+export function setLocale(language) {
+ if (getLocale() !== language) {
+ moment.locale(language === 'zh' ? 'zh-cn' : language)
+ store.set('locale', language)
+ window.location.reload()
+ }
+}
\ No newline at end of file
diff --git a/src/utils/index.test.js b/src/utils/index.test.js
new file mode 100644
index 0000000..c4c0b6f
--- /dev/null
+++ b/src/utils/index.test.js
@@ -0,0 +1,19 @@
+const { pathToRegexp } = require("path-to-regexp")
+
+describe('test pathToRegexp', () => {
+ it('get right', () => {
+ expect(pathToRegexp('/user').exec('/zh/user')).toEqual(
+ pathToRegexp('/user').exec('/user')
+ )
+ expect(pathToRegexp('/user').exec('/user')).toEqual(
+ pathToRegexp('/user').exec('/user')
+ )
+
+ expect(pathToRegexp('/user/:id').exec('/zh/user/1')).toEqual(
+ pathToRegexp('/user/:id').exec('/user/1')
+ )
+ expect(pathToRegexp('/user/:id').exec('/user/1')).toEqual(
+ pathToRegexp('/user/:id').exec('/user/1')
+ )
+ })
+})
diff --git a/src/utils/model.js b/src/utils/model.js
new file mode 100644
index 0000000..6bc8b9b
--- /dev/null
+++ b/src/utils/model.js
@@ -0,0 +1,39 @@
+import modelExtend from 'dva-model-extend'
+
+export const model = {
+ reducers: {
+ updateState(state, { payload }) {
+ return {
+ ...state,
+ ...payload,
+ }
+ },
+ },
+}
+
+export const pageModel = modelExtend(model, {
+ state: {
+ list: [],
+ pagination: {
+ showSizeChanger: true,
+ showQuickJumper: true,
+ current: 1,
+ total: 0,
+ pageSize: 10,
+ },
+ },
+
+ reducers: {
+ querySuccess(state, { payload }) {
+ const { list, pagination } = payload
+ return {
+ ...state,
+ list,
+ pagination: {
+ ...state.pagination,
+ ...pagination,
+ },
+ }
+ },
+ },
+})
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..4e5f0a3
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,112 @@
+import axios from 'axios'
+import qs from 'qs'
+import { cloneDeep, method } from 'lodash'
+const { parse, compile } = require("path-to-regexp")
+import { message } from 'antd'
+import { CANCEL_REQUEST_MESSAGE } from 'utils/constant'
+import store from 'store'
+
+const { CancelToken } = axios
+window.cancelRequest = new Map()
+
+export default function request(options) {
+ let { data, url } = options
+ const cloneData = cloneDeep(data)
+
+ try {
+ let domain = 'http://140.249.182.90:8081'
+ // let domain = 'http://localhost:8080'
+ const urlMatch = url.match(/[a-zA-z]+:\/\/[^/]*/)
+ if (urlMatch) {
+ ;[domain] = urlMatch
+ url = url.slice(domain.length)
+ }
+
+ const match = parse(url)
+ url = compile(url)(data)
+
+ for (const item of match) {
+ if (item instanceof Object && item.name in cloneData) {
+ delete cloneData[item.name]
+ }
+ }
+
+ // token 及 get 传值处理
+ let params = {}
+ const token = store.get("token")
+ if (token) {
+ params.token = token
+ options.data = { ...options.data, ...{ token: token } };
+ }
+ console.log("token: ", token)
+ if (options.method == "GET") {
+ // && Object.keys(options.data).length != 0
+ options.params = { ...params, ...data };
+ options.paramsSerializer = function (params) {
+ return qs.stringify(params)
+ }
+ }
+
+ url = domain + url
+ } catch (e) {
+ message.error(e.message)
+ }
+
+ options.url = url
+ options.cancelToken = new CancelToken(cancel => {
+ window.cancelRequest.set(Symbol(Date.now()), {
+ pathname: window.location.pathname,
+ cancel,
+ })
+ })
+
+ return axios(options)
+ .then(response => {
+ const { statusText, status, data } = response
+
+ let result = {}
+ if (typeof data === 'object') {
+ result = data
+ if (Array.isArray(data)) {
+ result.list = data
+ }
+ } else {
+ result.data = data
+ }
+
+ return Promise.resolve({
+ success: true,
+ message: statusText,
+ statusCode: status,
+ ...result,
+ })
+ })
+ .catch(error => {
+ const { response, message } = error
+
+ if (String(message) === CANCEL_REQUEST_MESSAGE) {
+ return {
+ success: false,
+ }
+ }
+
+ let msg
+ let statusCode
+
+ if (response && response instanceof Object) {
+ const { data, statusText } = response
+ statusCode = response.status
+ msg = data.message || statusText
+ } else {
+ statusCode = 600
+ msg = error.message || 'Network Error'
+ }
+
+ /* eslint-disable */
+ return Promise.reject({
+ success: false,
+ statusCode,
+ message: msg,
+ })
+ })
+}
diff --git a/src/utils/theme.js b/src/utils/theme.js
new file mode 100644
index 0000000..0a610df
--- /dev/null
+++ b/src/utils/theme.js
@@ -0,0 +1,14 @@
+module.exports = {
+ Color: {
+ green: '#64ea91',
+ blue: '#8fc9fb',
+ purple: '#d897eb',
+ red: '#f69899',
+ yellow: '#f8c82e',
+ peach: '#f797d6',
+ borderBase: '#e5e5e5',
+ borderSplit: '#f4f4f4',
+ grass: '#d6fbb5',
+ sky: '#c1e0fc',
+ },
+}