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

|
||||

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

|
||||

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

|
||||
|
||||
|
Before Width: | Height: | Size: 3.7 MiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 645 KiB |
@@ -1,5 +1,5 @@
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const queryArray = (array, key, keyAlias = 'key') => {
|
||||
if (!(array instanceof Array)) {
|
||||
@@ -1,7 +1,7 @@
|
||||
import { color } from '../utils/theme'
|
||||
import { color } from '../src/utils/theme'
|
||||
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const { apiPrefix } = config
|
||||
|
||||
@@ -50,14 +50,14 @@ let database = [
|
||||
icon: 'heart-o',
|
||||
route: '/UIElement/iconfont',
|
||||
},
|
||||
// {
|
||||
// id: '42',
|
||||
// bpid: '4',
|
||||
// mpid: '4',
|
||||
// name: 'DataTable',
|
||||
// icon: 'database',
|
||||
// route: '/UIElement/dataTable',
|
||||
// },
|
||||
{
|
||||
id: '42',
|
||||
bpid: '4',
|
||||
mpid: '4',
|
||||
name: 'DataTable',
|
||||
icon: 'database',
|
||||
route: '/UIElement/dataTable',
|
||||
},
|
||||
{
|
||||
id: '43',
|
||||
bpid: '4',
|
||||
@@ -74,22 +74,22 @@ let database = [
|
||||
icon: 'search',
|
||||
route: '/UIElement/search',
|
||||
},
|
||||
// {
|
||||
// id: '45',
|
||||
// bpid: '4',
|
||||
// mpid: '4',
|
||||
// name: '56pxor',
|
||||
// icon: 'edit',
|
||||
// route: '/UIElement/editor',
|
||||
// },
|
||||
// {
|
||||
// id: '46',
|
||||
// bpid: '4',
|
||||
// mpid: '4',
|
||||
// name: 'layer (Function)',
|
||||
// icon: 'credit-card',
|
||||
// route: '/UIElement/layer',
|
||||
// },
|
||||
{
|
||||
id: '45',
|
||||
bpid: '4',
|
||||
mpid: '4',
|
||||
name: '56pxor',
|
||||
icon: 'edit',
|
||||
route: '/UIElement/editor',
|
||||
},
|
||||
{
|
||||
id: '46',
|
||||
bpid: '4',
|
||||
mpid: '4',
|
||||
name: 'layer (Function)',
|
||||
icon: 'credit-card',
|
||||
route: '/UIElement/layer',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
bpid: '1',
|
||||
@@ -1,6 +1,6 @@
|
||||
const qs = require('qs')
|
||||
const Mock = require('mockjs')
|
||||
const config = require('../utils/config')
|
||||
const config = require('../src/utils/config')
|
||||
|
||||
const { apiPrefix } = config
|
||||
|
||||
@@ -173,7 +173,7 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
|
||||
[`DELETE ${apiPrefix}/users`] (req, res) {
|
||||
[`POST ${apiPrefix}/users/delete`] (req, res) {
|
||||
const { ids } = req.body
|
||||
database = database.filter(item => !ids.some(_ => _ === item.id))
|
||||
res.status(204).end()
|
||||
@@ -1,72 +1,63 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "antd-admin",
|
||||
"version": "4.3.9",
|
||||
"version": "5.0.0-beta",
|
||||
"dependencies": {
|
||||
"antd": "3.0.3",
|
||||
"axios": "^0.17.1",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"classnames": "^2.2.5",
|
||||
"cross-env": "^5.0.5",
|
||||
"d3-shape": "^1.2.0",
|
||||
"draftjs-to-markdown": "^0.5.0",
|
||||
"dva": "2.1.0",
|
||||
"dva-loading": "^1.0.4",
|
||||
"echarts": "^3.7.2",
|
||||
"echarts-for-react": "^2.0.0",
|
||||
"echarts-gl": "^1.0.0-beta.5",
|
||||
"echarts-liquidfill": "^1.1.0",
|
||||
"ejs-loader": "^0.3.0",
|
||||
"highcharts-exporting": "^0.1.2",
|
||||
"highcharts-more": "^0.1.2",
|
||||
"history": "^4.7.2",
|
||||
"js-beautify": "^1.6.14",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"antd": "^3.9.0",
|
||||
"axios": "^0.18.0",
|
||||
"classnames": "^2.2.6",
|
||||
"d3-shape": "^1.2.2",
|
||||
"draftjs-to-html": "^0.8.4",
|
||||
"draftjs-to-markdown": "^0.5.1",
|
||||
"dva-model-extend": "^0.1.2",
|
||||
"echarts": "^4.1.0",
|
||||
"echarts-for-react": "^2.0.14",
|
||||
"echarts-gl": "^1.1.1",
|
||||
"echarts-liquidfill": "^2.0.2",
|
||||
"highcharts-exporting": "^0.1.7",
|
||||
"highcharts-more": "^0.1.7",
|
||||
"jsonp": "^0.2.1",
|
||||
"less-vars-to-js": "^1.1.2",
|
||||
"lodash": "^4.17.4",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^2.1.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"qs": "^6.5.0",
|
||||
"query-string": "^5.0.0",
|
||||
"rc-tween-one": "^1.3.1",
|
||||
"react": "^16.2.0",
|
||||
"react-countup": "^3.0.2",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-draft-wysiwyg": "^1.10.0",
|
||||
"react-helmet": "^5.1.3",
|
||||
"react-highcharts": "^15.0.0",
|
||||
"recharts": "^1.0.0-beta.0"
|
||||
"path-to-regexp": "^2.4.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"qs": "^6.5.2",
|
||||
"query-string": "^6.1.0",
|
||||
"rc-tween-one": "^2.2.3",
|
||||
"react-adsense": "^0.0.6",
|
||||
"react-countup": "^4.0.0-alpha.6",
|
||||
"react-draft-wysiwyg": "^1.12.13",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-highcharts": "^16.0.2",
|
||||
"recharts": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^8.1.0",
|
||||
"babel-plugin-dev-expression": "^0.2.1",
|
||||
"babel-plugin-dva-hmr": "^0.4.0",
|
||||
"babel-plugin-import": "^1.1.1",
|
||||
"babel-plugin-transform-runtime": "^6.9.0",
|
||||
"babel-runtime": "^6.9.2",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"draftjs-to-html": "^0.8.1",
|
||||
"dva-model-extend": "^0.1.1",
|
||||
"eslint": "^4.1.1",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-import-resolver-node": "^0.3.1",
|
||||
"eslint-loader": "^1.9.0",
|
||||
"eslint-plugin-import": "^2.6.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"html-webpack-plugin": "^2.29.0",
|
||||
"redbox-react": "^1.2.10",
|
||||
"roadhog": "1.3.1"
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "^5.5.0",
|
||||
"eslint-config-umi": "^0.1.5",
|
||||
"eslint-plugin-flowtype": "^2.50.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"js-beautify": "^1.8.1",
|
||||
"less-vars-to-js": "^1.3.0",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"svg-sprite-loader": "^3.9.2",
|
||||
"umi": "^2.0.0",
|
||||
"umi-plugin-react": "^1.0.0"
|
||||
},
|
||||
"pre-commit": ["lint"],
|
||||
"pre-commit": [
|
||||
"lint"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
|
||||
"start": "roadhog buildDll && cross-env BROWSER=none HOST=0.0.0.0 roadhog server",
|
||||
"analyze": "cross-env ANALYZE=1 umi build",
|
||||
"start": "umi dev",
|
||||
"lint": "eslint --fix --ext .js src",
|
||||
"build": "roadhog build",
|
||||
"build:dll": "roadhog buildDll",
|
||||
"build:new": "node version && roadhog build"
|
||||
"build": "umi build",
|
||||
"test": "umi test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
@@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { TweenOneGroup } from 'rc-tween-one'
|
||||
|
||||
const enterAnim = [
|
||||
@@ -40,28 +39,12 @@ const leaveAnim = [
|
||||
},
|
||||
]
|
||||
|
||||
const AnimTableBody = ({ body, page = 1, current }) => {
|
||||
if (current !== +page) {
|
||||
return body
|
||||
}
|
||||
|
||||
return (
|
||||
<TweenOneGroup
|
||||
component="tbody"
|
||||
className={body.props.className}
|
||||
enter={enterAnim}
|
||||
leave={leaveAnim}
|
||||
appear={false}
|
||||
>
|
||||
{body.props.children}
|
||||
</TweenOneGroup>
|
||||
)
|
||||
}
|
||||
|
||||
AnimTableBody.propTypes = {
|
||||
body: PropTypes.element,
|
||||
page: PropTypes.any,
|
||||
current: PropTypes.number.isRequired,
|
||||
}
|
||||
const AnimTableBody = props => (<TweenOneGroup
|
||||
component="tbody"
|
||||
{...props}
|
||||
enter={enterAnim}
|
||||
leave={leaveAnim}
|
||||
appear={false}
|
||||
/>)
|
||||
|
||||
export default AnimTableBody
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Table } from 'antd'
|
||||
import { request } from 'utils'
|
||||
import lodash from 'lodash'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import isEqual from 'lodash.isequal'
|
||||
import './DataTable.less'
|
||||
|
||||
class DataTable extends React.Component {
|
||||
@@ -31,12 +32,12 @@ class DataTable extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const staticNextProps = lodash.cloneDeep(nextProps)
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
const staticNextProps = cloneDeep(nextProps)
|
||||
delete staticNextProps.columns
|
||||
const { columns, ...otherProps } = this.props
|
||||
|
||||
if (!lodash.isEqual(staticNextProps, otherProps)) {
|
||||
if (!isEqual(staticNextProps, otherProps)) {
|
||||
this.props = nextProps
|
||||
this.fetch()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dropdown, Button, Icon, Menu } from 'antd'
|
||||
|
||||
const DropOption = ({ onMenuClick, menuOptions = [], buttonStyle, dropdownProps }) => {
|
||||
const DropOption = ({
|
||||
onMenuClick, menuOptions = [], buttonStyle, dropdownProps,
|
||||
}) => {
|
||||
const menu = menuOptions.map(item => <Menu.Item key={item.key}>{item.name}</Menu.Item>)
|
||||
return (<Dropdown
|
||||
overlay={<Menu onClick={onMenuClick}>{menu}</Menu>}
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.header {
|
||||
:global {
|
||||
.ant-menu-submenu-title {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal {
|
||||
line-height: 56px;
|
||||
|
||||
& > .ant-menu-submenu:hover {
|
||||
color: #1890ff;
|
||||
background-color: rgba(24, 144, 255, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
border-bottom: none;
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-submenu {
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item,
|
||||
.ant-menu-horizontal > .ant-menu-submenu {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item-active,
|
||||
.ant-menu-horizontal > .ant-menu-item-open,
|
||||
.ant-menu-horizontal > .ant-menu-item-selected,
|
||||
.ant-menu-horizontal > .ant-menu-item:hover,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-active,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-open,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-selected,
|
||||
.ant-menu-horizontal > .ant-menu-submenu:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
box-shadow: @shadow-2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
|
||||
.rightWarpper {
|
||||
display: flex;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: fade(@primary-color, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu {
|
||||
width: 280px;
|
||||
margin-left: 6px;
|
||||
|
||||
:global .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
|
||||
.ant-menu-inline .ant-menu-item,
|
||||
.ant-menu-vertical .ant-menu-item {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.ant-menu-inline .ant-menu-item-selected,
|
||||
.ant-menu-inline .ant-menu-selected {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
.header {
|
||||
:global {
|
||||
.ant-menu-submenu-title {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal {
|
||||
line-height: 56px;
|
||||
|
||||
& > .ant-menu-submenu:hover {
|
||||
color: #1890ff;
|
||||
background-color: rgba(24, 144, 255, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
border-bottom: none;
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-submenu {
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item,
|
||||
.ant-menu-horizontal > .ant-menu-submenu {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item-active,
|
||||
.ant-menu-horizontal > .ant-menu-item-open,
|
||||
.ant-menu-horizontal > .ant-menu-item-selected,
|
||||
.ant-menu-horizontal > .ant-menu-item:hover,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-active,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-open,
|
||||
.ant-menu-horizontal > .ant-menu-submenu-selected,
|
||||
.ant-menu-horizontal > .ant-menu-submenu:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
box-shadow: @shadow-2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
|
||||
.rightWarpper {
|
||||
display: flex;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: fade(@primary-color, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu {
|
||||
width: 280px;
|
||||
margin-left: 6px;
|
||||
|
||||
:global .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
|
||||
.ant-menu-inline .ant-menu-item,
|
||||
.ant-menu-vertical .ant-menu-item {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.ant-menu-inline .ant-menu-item-selected,
|
||||
.ant-menu-inline .ant-menu-selected {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,169 +1,191 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
:global {
|
||||
.ant-layout-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
transition: all 0.3s;
|
||||
|
||||
.ant-menu-root {
|
||||
height: ~"calc(100vh - 144px)";
|
||||
overflow-x: hidden;
|
||||
border-right: none;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-content {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.ant-layout-footer {
|
||||
text-align: center;
|
||||
padding: 0 24px;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.ant-back-top {
|
||||
right: 50px;
|
||||
}
|
||||
|
||||
.ant-switch.ant-switch-large {
|
||||
line-height: 24px;
|
||||
height: 26px;
|
||||
|
||||
&:after,
|
||||
&:before {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
&.ant-switch-checked:after,
|
||||
&.ant-switch-checked:before {
|
||||
margin-left: -23px;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-vertical-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 96px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.switchtheme {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 48px;
|
||||
background-color: #fff;
|
||||
border-top: solid 1px #f8f8f8;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
overflow: hidden;
|
||||
z-index: 9;
|
||||
transition: all 0.3s;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global {
|
||||
.anticon {
|
||||
min-width: 14px;
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bread {
|
||||
margin-bottom: 24px;
|
||||
|
||||
:global {
|
||||
.ant-breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.switchtheme {
|
||||
background-color: #000d18;
|
||||
border-color: #001629;
|
||||
}
|
||||
}
|
||||
|
||||
.light {
|
||||
:global {
|
||||
.ant-layout-sider {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.bread {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-layout-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-back-top {
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
:global {
|
||||
.ant-layout-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
transition: all 0.3s;
|
||||
|
||||
.ant-menu-root {
|
||||
height: ~"calc(100vh - 144px)";
|
||||
overflow-x: hidden;
|
||||
border-right: none;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-content {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.ant-layout-footer {
|
||||
text-align: center;
|
||||
padding: 0 24px;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.ant-back-top {
|
||||
right: 50px;
|
||||
}
|
||||
|
||||
.ant-switch.ant-switch-large {
|
||||
line-height: 24px;
|
||||
height: 26px;
|
||||
|
||||
&:after,
|
||||
&:before {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-vertical-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.logo {
|
||||
height: 96px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
color: @primary-color;
|
||||
white-space: nowrap;
|
||||
:local {
|
||||
animation: fadeLeftIn 500ms linear;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidemenu {
|
||||
:global{
|
||||
.ant-menu-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switchtheme {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 48px;
|
||||
background-color: #fff;
|
||||
border-top: solid 1px #f8f8f8;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
overflow: hidden;
|
||||
z-index: 9;
|
||||
transition: all 0.3s;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global {
|
||||
.anticon {
|
||||
min-width: 14px;
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bread {
|
||||
margin-bottom: 24px;
|
||||
|
||||
:global {
|
||||
.ant-breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.switchtheme {
|
||||
background-color: #000d18;
|
||||
border-color: #001629;
|
||||
}
|
||||
}
|
||||
|
||||
.light {
|
||||
:global {
|
||||
.ant-layout-sider {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.bread {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-layout-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-back-top {
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeLeftIn {
|
||||
0% {
|
||||
transform: translateX(5px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,14 @@ import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { arrayToTree, queryArray } from 'utils'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
import styles from './Layout.less'
|
||||
|
||||
const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, location }) => {
|
||||
const { SubMenu } = Menu
|
||||
let openKeysFlag = false
|
||||
|
||||
const Menus = ({
|
||||
siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, location,
|
||||
}) => {
|
||||
// 生成树状
|
||||
const menuTree = arrayToTree(menu.filter(_ => _.mpid !== '-1'), 'id', 'mpid')
|
||||
const levelMap = {}
|
||||
@@ -18,7 +24,7 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
levelMap[item.id] = item.mpid
|
||||
}
|
||||
return (
|
||||
<Menu.SubMenu
|
||||
<SubMenu
|
||||
key={item.id}
|
||||
title={<span>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
@@ -26,14 +32,14 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
</span>}
|
||||
>
|
||||
{getMenus(item.children, siderFoldN)}
|
||||
</Menu.SubMenu>
|
||||
</SubMenu>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={item.id}>
|
||||
<Link to={item.route || '#'}>
|
||||
<Link to={item.route || '#'} style={siderFoldN ? { width: 10 } : {}}>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
{(!siderFoldN || !menuTree.includes(item)) && item.name}
|
||||
{item.name}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)
|
||||
@@ -60,6 +66,7 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
}
|
||||
|
||||
const onOpenChange = (openKeys) => {
|
||||
if (navOpenKeys.length) changeOpenKeys([]), openKeysFlag = true
|
||||
const latestOpenKey = openKeys.find(key => !navOpenKeys.includes(key))
|
||||
const latestCloseKey = navOpenKeys.find(key => !openKeys.includes(key))
|
||||
let nextOpenKeys = []
|
||||
@@ -83,6 +90,7 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
let defaultSelectedKeys
|
||||
for (let item of menu) {
|
||||
if (item.route && pathToRegexp(item.route).exec(location.pathname)) {
|
||||
if (!navOpenKeys.length && item.mpid && !openKeysFlag) changeOpenKeys([String(item.mpid)])
|
||||
currentMenu = item
|
||||
break
|
||||
}
|
||||
@@ -91,8 +99,12 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
let result = [String(current[id])]
|
||||
const getPath = (item) => {
|
||||
if (item && item[pid]) {
|
||||
result.unshift(String(item[pid]))
|
||||
getPath(queryArray(array, item[pid], id))
|
||||
if (item[pid] === '-1') {
|
||||
result.unshift(String(item['bpid']))
|
||||
} else {
|
||||
result.unshift(String(item[pid]))
|
||||
getPath(queryArray(array, item[pid], id))
|
||||
}
|
||||
}
|
||||
}
|
||||
getPath(current)
|
||||
@@ -112,6 +124,7 @@ const Menus = ({ siderFold, darkTheme, navOpenKeys, changeOpenKeys, menu, locati
|
||||
mode={siderFold ? 'vertical' : 'inline'}
|
||||
theme={darkTheme ? 'dark' : 'light'}
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
className={styles.sidemenu}
|
||||
>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
|
||||
@@ -6,7 +6,9 @@ import styles from './Page.less'
|
||||
|
||||
export default class Page extends Component {
|
||||
render () {
|
||||
const { className, children, loading = false, inner = false } = this.props
|
||||
const {
|
||||
className, children, loading = false, inner = false,
|
||||
} = this.props
|
||||
const loadingStyle = {
|
||||
height: 'calc(100vh - 184px)',
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
.contentInner{
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: ~"calc(100vh - 198px)";
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.contentInner {
|
||||
padding: 12px;
|
||||
min-height: ~"calc(100vh - 160px)";
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
.contentInner{
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: ~"calc(100vh - 198px)";
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.contentInner {
|
||||
padding: 12px;
|
||||
min-height: ~"calc(100vh - 160px)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@ class Search extends React.Component {
|
||||
this.handleSearch()
|
||||
}
|
||||
render () {
|
||||
const { size, select, selectOptions, selectProps, style, keyword } = this.props
|
||||
const {
|
||||
size, select, selectOptions, selectProps, style, keyword,
|
||||
} = this.props
|
||||
const { clearVisible } = this.state
|
||||
return (
|
||||
<Input.Group compact size={size} className={styles.search} style={style}>
|
||||
|
||||
@@ -5,7 +5,9 @@ import ReactDOM from 'react-dom'
|
||||
import classnames from 'classnames'
|
||||
import styles from './layer.less'
|
||||
|
||||
const { info, success, error, warning, confirm } = Modal
|
||||
const {
|
||||
info, success, error, warning, confirm,
|
||||
} = Modal
|
||||
|
||||
const layer = {
|
||||
prefixCls: 'ant-layer',
|
||||
@@ -53,32 +55,31 @@ layer.open = (config) => {
|
||||
const { className, wrapClassName = '', verticalCenter = true } = modalProps
|
||||
const { prefixCls } = layer
|
||||
layer.index += 1
|
||||
const index = layer.index
|
||||
const { index } = layer
|
||||
let div = document.createElement('div')
|
||||
div.id = `${prefixCls}-reference-${index}`
|
||||
div.className = `${prefixCls}-reference`
|
||||
document.body.appendChild(div)
|
||||
|
||||
ReactDOM.render(
|
||||
<Modal
|
||||
visible
|
||||
title="Title"
|
||||
transitionName="zoom"
|
||||
maskTransitionName="fade"
|
||||
onCancel={() => {
|
||||
ReactDOM.render(<Modal
|
||||
visible
|
||||
title="Title"
|
||||
transitionName="zoom"
|
||||
maskTransitionName="fade"
|
||||
onCancel={() => {
|
||||
layer.close(index)
|
||||
}}
|
||||
onOk={() => {
|
||||
onOk={() => {
|
||||
layer.close(index)
|
||||
}}
|
||||
{...modalProps}
|
||||
wrapClassName={classnames({ [styles.verticalCenter]: verticalCenter, [wrapClassName]: true })}
|
||||
className={classnames(prefixCls, className, [`${prefixCls}-${index}`])}
|
||||
>
|
||||
<div className={`${prefixCls}-body-wrapper`} style={{ maxHeight: document.body.clientHeight - 256 }}>
|
||||
{content}
|
||||
</div>
|
||||
</Modal>, div)
|
||||
{...modalProps}
|
||||
wrapClassName={classnames({ [styles.verticalCenter]: verticalCenter, [wrapClassName]: true })}
|
||||
className={classnames(prefixCls, className, [`${prefixCls}-${index}`])}
|
||||
>
|
||||
<div className={`${prefixCls}-body-wrapper`} style={{ maxHeight: document.body.clientHeight - 256 }}>
|
||||
{content}
|
||||
</div>
|
||||
</Modal>, div)
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import '@babel/polyfill'
|
||||
@@ -1,25 +0,0 @@
|
||||
import { message } from 'antd'
|
||||
import dva from 'dva'
|
||||
import createLoading from 'dva-loading'
|
||||
import createHistory from 'history/createBrowserHistory'
|
||||
import 'babel-polyfill'
|
||||
|
||||
// 1. Initialize
|
||||
const app = dva({
|
||||
...createLoading({
|
||||
effects: true,
|
||||
}),
|
||||
history: createHistory(),
|
||||
onError (error) {
|
||||
message.error(error.message)
|
||||
},
|
||||
})
|
||||
|
||||
// 2. Model
|
||||
app.model(require('./models/app'))
|
||||
|
||||
// 3. Router
|
||||
app.router(require('./router'))
|
||||
|
||||
// 4. Start
|
||||
app.start('#root')
|
||||
@@ -10,7 +10,7 @@ import { BackTop, Layout } from 'antd'
|
||||
import { classnames, config } from 'utils'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { withRouter } from 'dva/router'
|
||||
import Error from './error'
|
||||
import Error from '../pages/404'
|
||||
import '../themes/index.less'
|
||||
import './app.less'
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
@import "~themes/vars";
|
||||
|
||||
:global {
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
|
||||
.bar {
|
||||
background: @primary-color;
|
||||
position: fixed;
|
||||
z-index: 1024;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px @primary-color,0 0 5px @primary-color;
|
||||
opacity: 1.0;
|
||||
transform: rotate(3deg) translate(0px,-4px);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
border-top-color: @primary-color;
|
||||
border-left-color: @primary-color;
|
||||
border-radius: 50%;
|
||||
|
||||
:local {
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
#nprogress {
|
||||
.bar,
|
||||
.spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@import "~themes/vars.less";
|
||||
|
||||
:global {
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
|
||||
.bar {
|
||||
background: @primary-color;
|
||||
position: fixed;
|
||||
z-index: 1024;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px @primary-color,0 0 5px @primary-color;
|
||||
opacity: 1.0;
|
||||
transform: rotate(3deg) translate(0px,-4px);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
border-top-color: @primary-color;
|
||||
border-left-color: @primary-color;
|
||||
border-radius: 50%;
|
||||
|
||||
:local {
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
#nprogress {
|
||||
.bar,
|
||||
.spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { LocaleProvider } from 'antd'
|
||||
import enUS from 'antd/lib/locale-provider/en_US'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import App from './app'
|
||||
|
||||
export default withRouter((props) => {
|
||||
return (
|
||||
<LocaleProvider locale={enUS}>
|
||||
<App>
|
||||
{ props.children }
|
||||
</App>
|
||||
</LocaleProvider>
|
||||
)
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
/* global window */
|
||||
/* global document */
|
||||
/* global location */
|
||||
/* eslint no-restricted-globals: ["error", "event"] */
|
||||
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { parse } from 'qs'
|
||||
import config from 'config'
|
||||
@@ -42,7 +44,7 @@ export default {
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
locationPathname: location.pathname,
|
||||
locationQuery: queryString.parse(location.search),
|
||||
locationQuery: location.query,
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -111,6 +113,16 @@ export default {
|
||||
}, { call, put }) {
|
||||
const data = yield call(logout, parse(payload))
|
||||
if (data.success) {
|
||||
yield put({ type: 'updateState', payload: {
|
||||
user: {},
|
||||
permissions: { visit: [] },
|
||||
menu: [{
|
||||
id: 1,
|
||||
icon: 'laptop',
|
||||
name: 'Dashboard',
|
||||
router: '/dashboard',
|
||||
}],
|
||||
}})
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw (data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Icon } from 'antd'
|
||||
import styles from './index.less'
|
||||
import { Page } from 'components'
|
||||
import styles from './404.less'
|
||||
|
||||
const Error = () => (<Page inner>
|
||||
<div className={styles.error}>
|
||||
@@ -5,9 +5,11 @@ import { Table, Row, Col, Card, Select } from 'antd'
|
||||
class DataTablePage extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = { filterCase: {
|
||||
gender: '',
|
||||
} }
|
||||
this.state = {
|
||||
filterCase: {
|
||||
gender: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectChange = (gender) => {
|
||||
@@ -20,7 +22,11 @@ class DataTablePage extends React.Component {
|
||||
render () {
|
||||
const { filterCase } = this.state
|
||||
const staticDataTableProps = {
|
||||
dataSource: [{ key: '1', name: 'John Brown', age: 24, address: 'New York' }, { key: '2', name: 'Jim Green', age: 23, address: 'London' }],
|
||||
dataSource: [{
|
||||
key: '1', name: 'John Brown', age: 24, address: 'New York',
|
||||
}, {
|
||||
key: '2', name: 'Jim Green', age: 23, address: 'London',
|
||||
}],
|
||||
columns: [{ title: 'name', dataIndex: 'name' }, { title: 'Age', dataIndex: 'age' }, { title: 'Address', dataIndex: 'address' }],
|
||||
pagination: false,
|
||||
}
|
||||
@@ -39,7 +45,7 @@ class DataTablePage extends React.Component {
|
||||
{ title: 'Phone', dataIndex: 'phone' },
|
||||
{ title: 'Gender', dataIndex: 'gender' },
|
||||
],
|
||||
rowKey: 'registered',
|
||||
rowKey: 'email',
|
||||
}
|
||||
|
||||
const caseChangeDataTableProps = {
|
||||
@@ -57,7 +63,7 @@ class DataTablePage extends React.Component {
|
||||
{ title: 'Phone', dataIndex: 'phone' },
|
||||
{ title: 'Gender', dataIndex: 'gender' },
|
||||
],
|
||||
rowKey: 'registered',
|
||||
rowKey: 'email',
|
||||
}
|
||||
|
||||
return (<div className="content-inner">
|
||||
@@ -125,6 +131,7 @@ class DataTablePage extends React.Component {
|
||||
desciption: '远程获取数据的参数',
|
||||
type: 'Object',
|
||||
default: '后面有空加上',
|
||||
key: 'basetable'
|
||||
}]}
|
||||
/>
|
||||
</Col>
|
||||
@@ -4,7 +4,6 @@ import { convertToRaw } from 'draft-js'
|
||||
import { Row, Col, Card } from 'antd'
|
||||
import draftToHtml from 'draftjs-to-html'
|
||||
import draftToMarkdown from 'draftjs-to-markdown'
|
||||
// https://github.com/jpuri/react-draft-wysiwyg/blob/master/docs/src/components/Demo/index.js
|
||||
|
||||
export default class EditorPage extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -3,7 +3,9 @@ import PropTypes from 'prop-types'
|
||||
import { ResponsiveContainer } from 'recharts'
|
||||
import styles from './Container.less'
|
||||
|
||||
const Container = ({ children, ratio = 5 / 2, minHeight = 250, maxHeight = 350 }) => (<div className={styles.container} style={{ minHeight, maxHeight }}>
|
||||
const Container = ({
|
||||
children, ratio = 5 / 2, minHeight = 250, maxHeight = 350,
|
||||
}) => (<div className={styles.container} style={{ minHeight, maxHeight }}>
|
||||
<div style={{ marginTop: `${100 / ratio}%` || '100%' }} />
|
||||
<div className={styles.content} style={{ minHeight, maxHeight }}>
|
||||
<ResponsiveContainer>
|
||||
@@ -1,7 +1,7 @@
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
if (typeof define === 'function' && define.amd) { // eslint-disable-line
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory)
|
||||
define(['exports', 'echarts'], factory) // eslint-disable-line
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports, require('echarts'))
|
||||
@@ -1,7 +1,7 @@
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
if (typeof define === 'function' && define.amd) { // eslint-disable-line
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory)
|
||||
define(['exports', 'echarts'], factory) // eslint-disable-line
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports, require('echarts'))
|
||||
@@ -3,7 +3,9 @@ import PropTypes from 'prop-types'
|
||||
import { ResponsiveContainer } from 'recharts'
|
||||
import styles from './Container.less'
|
||||
|
||||
const Container = ({ children, ratio = 5 / 2, minHeight = 250, maxHeight = 350 }) => (<div className={styles.container} style={{ minHeight, maxHeight }}>
|
||||
const Container = ({
|
||||
children, ratio = 5 / 2, minHeight = 250, maxHeight = 350,
|
||||
}) => (<div className={styles.container} style={{ minHeight, maxHeight }}>
|
||||
<div style={{ marginTop: `${100 / ratio}%` || '100%' }} />
|
||||
<div className={styles.content} style={{ minHeight, maxHeight }}>
|
||||
<ResponsiveContainer>
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react'
|
||||
import ReactHighcharts from 'react-highcharts'
|
||||
import highchartsMore from 'highcharts-more'
|
||||
import highchartsExporting from 'highcharts-exporting'
|
||||
import HighchartsExporting from 'highcharts-exporting'
|
||||
import HighchartsMore from 'highcharts-more'
|
||||
|
||||
highchartsMore(ReactHighcharts.Highcharts)
|
||||
highchartsExporting(ReactHighcharts.Highcharts)
|
||||
|
||||
HighchartsMore(ReactHighcharts.Highcharts)
|
||||
HighchartsExporting(ReactHighcharts.Highcharts)
|
||||
|
||||
const config = {
|
||||
chart: {
|
||||