Browse Source

merge master

pull/1238/head
jim 8 years ago
parent
commit
6ef237e517
  1. 44
      .eslintrc
  2. 1
      .gitignore
  3. 2
      .prettierignore
  4. 11
      .prettierrc
  5. 3
      .stylelintrc
  6. 3
      .vscode/settings.json
  7. 22
      .webpackrc.js
  8. 15
      mock/api.js
  9. 10
      mock/chart.js
  10. 16
      mock/rule.js
  11. 13
      package.json
  12. 298
      src/common/menu.js
  13. 71
      src/common/router.js
  14. 2
      src/components/ActiveChart/index.js
  15. 22
      src/components/Authorized/AuthorizedRoute.js
  16. 16
      src/components/Authorized/CheckPermissions.test.js
  17. 2
      src/components/Authorized/PromiseRender.js
  18. 6
      src/components/Authorized/Secured.js
  19. 11
      src/components/Authorized/index.d.ts
  20. 2
      src/components/Authorized/index.js
  21. 4
      src/components/AvatarList/index.d.ts
  22. 18
      src/components/AvatarList/index.js
  23. 2
      src/components/AvatarList/index.less
  24. 2
      src/components/Charts/Bar/index.d.ts
  25. 4
      src/components/Charts/Bar/index.js
  26. 2
      src/components/Charts/ChartCard/index.d.ts
  27. 12
      src/components/Charts/ChartCard/index.js
  28. 2
      src/components/Charts/ChartCard/index.less
  29. 2
      src/components/Charts/Field/index.d.ts
  30. 2
      src/components/Charts/Field/index.less
  31. 2
      src/components/Charts/Gauge/index.d.ts
  32. 2
      src/components/Charts/Gauge/index.js
  33. 7
      src/components/Charts/MiniProgress/index.d.ts
  34. 15
      src/components/Charts/MiniProgress/index.js
  35. 4
      src/components/Charts/MiniProgress/index.less
  36. 12
      src/components/Charts/Pie/index.js
  37. 4
      src/components/Charts/Pie/index.less
  38. 2
      src/components/Charts/Radar/index.d.ts
  39. 19
      src/components/Charts/Radar/index.js
  40. 2
      src/components/Charts/Radar/index.less
  41. 2
      src/components/Charts/TagCloud/index.d.ts
  42. 4
      src/components/Charts/TagCloud/index.js
  43. 7
      src/components/Charts/TimelineChart/index.d.ts
  44. 2
      src/components/Charts/TimelineChart/index.js
  45. 4
      src/components/Charts/WaterWave/index.less
  46. 4
      src/components/Charts/autoHeight.js
  47. 2
      src/components/CountDown/index.d.ts
  48. 61
      src/components/CountDown/index.js
  49. 12
      src/components/DescriptionList/DescriptionList.js
  50. 5
      src/components/DescriptionList/index.d.ts
  51. 9
      src/components/DescriptionList/index.less
  52. 44
      src/components/EditableItem/index.js
  53. 2
      src/components/EditableItem/index.less
  54. 14
      src/components/EditableLinkGroup/index.js
  55. 2
      src/components/EditableLinkGroup/index.less
  56. 10
      src/components/Ellipsis/index.js
  57. 4
      src/components/Exception/index.d.ts
  58. 12
      src/components/Exception/index.js
  59. 4
      src/components/Exception/index.less
  60. 5
      src/components/FooterToolbar/index.d.ts
  61. 5
      src/components/FooterToolbar/index.js
  62. 6
      src/components/FooterToolbar/index.less
  63. 7
      src/components/GlobalFooter/index.d.ts
  64. 24
      src/components/GlobalFooter/index.js
  65. 4
      src/components/GlobalFooter/index.less
  66. 5
      src/components/GlobalHeader/index.js
  67. 5
      src/components/HeaderSearch/index.d.ts
  68. 21
      src/components/HeaderSearch/index.js
  69. 4
      src/components/HeaderSearch/index.less
  70. 6
      src/components/Login/LoginItem.js
  71. 4
      src/components/Login/index.d.ts
  72. 56
      src/components/Login/index.js
  73. 3
      src/components/Login/index.less
  74. 42
      src/components/Login/map.js
  75. 5
      src/components/NoticeIcon/NoticeIconTab.d.ts
  76. 15
      src/components/NoticeIcon/NoticeList.js
  77. 8
      src/components/NoticeIcon/NoticeList.less
  78. 14
      src/components/NoticeIcon/index.js
  79. 4
      src/components/NoticeIcon/index.less
  80. 5
      src/components/NumberInfo/index.d.ts
  81. 26
      src/components/NumberInfo/index.js
  82. 4
      src/components/NumberInfo/index.less
  83. 39
      src/components/PageHeader/index.js
  84. 24
      src/components/PageHeader/index.less
  85. 20
      src/components/PageHeader/index.test.js
  86. 8
      src/components/Result/index.js
  87. 2
      src/components/Result/index.less
  88. 26
      src/components/SiderMenu/BaseMeun.js
  89. 32
      src/components/SiderMenu/SiderMenu.js
  90. 20
      src/components/SiderMenu/SilderMenu.test.js
  91. 11
      src/components/SiderMenu/index.js
  92. 9
      src/components/SiderMenu/index.less
  93. 16
      src/components/StandardFormRow/index.js
  94. 2
      src/components/StandardFormRow/index.less
  95. 34
      src/components/StandardTable/index.js
  96. 2
      src/components/StandardTable/index.less
  97. 5
      src/components/TagSelect/TagSelectOption.d.ts
  98. 53
      src/components/TagSelect/index.js
  99. 6
      src/components/TagSelect/index.less
  100. 22
      src/components/Trend/index.js

44
.eslintrc

@ -1,7 +1,6 @@
{
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": ["compat"],
"extends": ["airbnb", "prettier"],
"env": {
"browser": true,
"node": true,
@ -20,15 +19,18 @@
"react/jsx-no-bind": [0],
"react/prop-types": [0],
"react/prefer-stateless-function": [0],
"react/jsx-wrap-multilines": ["error", {
"declaration": "parens-new-line",
"assignment": "parens-new-line",
"return": "parens-new-line",
"arrow": "parens-new-line",
"condition": "parens-new-line",
"logical": "parens-new-line",
"prop": "ignore"
}],
"react/jsx-wrap-multilines": [
"error",
{
"declaration": "parens-new-line",
"assignment": "parens-new-line",
"return": "parens-new-line",
"arrow": "parens-new-line",
"condition": "parens-new-line",
"logical": "parens-new-line",
"prop": "ignore"
}
],
"no-else-return": [0],
"no-restricted-syntax": [0],
"import/no-extraneous-dependencies": [0],
@ -43,18 +45,20 @@
"no-bitwise": [0],
"no-cond-assign": [0],
"import/no-unresolved": [0],
"comma-dangle": ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}],
"comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}
],
"object-curly-newline": [0],
"function-paren-newline": [0],
"no-restricted-globals": [0],
"require-yield": [1],
"compat/compat": "error"
"require-yield": [1]
},
"parserOptions": {
"ecmaFeatures": {

1
.gitignore

@ -20,4 +20,3 @@ yarn.lock
package-lock.json
*bak
jsconfig.json
.prettierrc

2
.prettierignore

@ -0,0 +1,2 @@
**/*.md
**/*.svg

11
.prettierrc

@ -0,0 +1,11 @@
{
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}

3
.stylelintrc

@ -1,5 +1,5 @@
{
"extends": "stylelint-config-standard",
"extends": ["stylelint-config-standard", "stylelint-config-prettier"],
"rules": {
"selector-pseudo-class-no-unknown": null,
"shorthand-property-no-redundant-values": null,
@ -17,6 +17,7 @@
"number-no-trailing-zeros": null,
"rule-empty-line-before": null,
"selector-combinator-space-after": null,
"selector-descendant-combinator-no-non-space": null,
"selector-list-comma-newline-after": null,
"selector-pseudo-element-colon-notation": null,
"unit-no-unknown": null,

3
.vscode/settings.json

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

22
.webpackrc.js

@ -1,25 +1,25 @@
const path = require("path");
const path = require('path');
export default {
entry: "src/index.js",
entry: 'src/index.js',
extraBabelPlugins: [
"transform-decorators-legacy",
["import", { libraryName: "antd", libraryDirectory: "es", style: true }]
'transform-decorators-legacy',
['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
],
env: {
development: {
extraBabelPlugins: ["dva-hmr"]
}
extraBabelPlugins: ['dva-hmr'],
},
},
alias: {
components: path.resolve(__dirname, "src/components/")
components: path.resolve(__dirname, 'src/components/'),
},
ignoreMomentLocale: true,
theme: "./src/theme.js",
theme: './src/theme.js',
html: {
template: "./src/index.ejs"
template: './src/index.ejs',
},
disableDynamicImport: true,
publicPath: "/",
hash: true
publicPath: '/',
hash: true,
};

15
mock/api.js

@ -69,21 +69,23 @@ export function fakeList(count) {
owner: user[i % 10],
title: titles[i % 8],
avatar: avatars[i % 8],
cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - i % 4],
status: ['active', 'exception', 'normal'][i % 3],
percent: Math.ceil(Math.random() * 50) + 50,
logo: avatars[i % 8],
href: 'https://ant.design',
updatedAt: new Date(new Date().getTime() - (1000 * 60 * 60 * 2 * i)),
createdAt: new Date(new Date().getTime() - (1000 * 60 * 60 * 2 * i)),
updatedAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
createdAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
subDescription: desc[i % 5],
description: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。',
description:
'在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。',
activeUser: Math.ceil(Math.random() * 100000) + 100000,
newUser: Math.ceil(Math.random() * 1000) + 1000,
star: Math.ceil(Math.random() * 100) + 100,
like: Math.ceil(Math.random() * 100) + 100,
message: Math.ceil(Math.random() * 10) + 10,
content: '段落示意:蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。',
content:
'段落示意:蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。',
members: [
{
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ZiESqWwCXBRQoaPONSJe.png',
@ -117,7 +119,7 @@ export function getFakeList(req, res, u) {
const params = parse(url, true).query;
const count = (params.count * 1) || 20;
const count = params.count * 1 || 20;
const result = fakeList(count);
sourceData = result;
@ -330,7 +332,6 @@ export const getActivities = [
},
];
export default {
getNotice,
getActivities,

10
mock/chart.js

@ -7,7 +7,7 @@ const beginDay = new Date().getTime();
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
for (let i = 0; i < fakeY.length; i += 1) {
visitData.push({
x: moment(new Date(beginDay + (1000 * 60 * 60 * 24 * i))).format('YYYY-MM-DD'),
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
y: fakeY[i],
});
}
@ -16,7 +16,7 @@ const visitData2 = [];
const fakeY2 = [1, 6, 4, 8, 3, 7, 2];
for (let i = 0; i < fakeY2.length; i += 1) {
visitData2.push({
x: moment(new Date(beginDay + (1000 * 60 * 60 * 24 * i))).format('YYYY-MM-DD'),
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
y: fakeY2[i],
});
}
@ -125,7 +125,7 @@ for (let i = 0; i < 10; i += 1) {
const offlineChartData = [];
for (let i = 0; i < 20; i += 1) {
offlineChartData.push({
x: (new Date().getTime()) + (1000 * 60 * 30 * i),
x: new Date().getTime() + 1000 * 60 * 30 * i,
y1: Math.floor(Math.random() * 100) + 10,
y2: Math.floor(Math.random() * 100) + 10,
});
@ -167,8 +167,8 @@ const radarTitleMap = {
contribute: '贡献',
hot: '热度',
};
radarOriginData.forEach((item) => {
Object.keys(item).forEach((key) => {
radarOriginData.forEach(item => {
Object.keys(item).forEach(key => {
if (key !== 'name') {
radarData.push({
name: item.name,

16
mock/rule.js

@ -5,9 +5,12 @@ let tableListDataSource = [];
for (let i = 0; i < 46; i += 1) {
tableListDataSource.push({
key: i,
disabled: ((i % 6) === 0),
disabled: i % 6 === 0,
href: 'https://ant.design',
avatar: ['https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png'][i % 2],
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${i}`,
title: `一个任务名称 ${i}`,
owner: '曲丽丽',
@ -43,7 +46,7 @@ export function getRule(req, res, u) {
if (params.status) {
const status = params.status.split(',');
let filterDataSource = [];
status.forEach((s) => {
status.forEach(s => {
filterDataSource = filterDataSource.concat(
[...dataSource].filter(data => parseInt(data.status, 10) === parseInt(s[0], 10))
);
@ -95,7 +98,10 @@ export function postRule(req, res, u, b) {
tableListDataSource.unshift({
key: i,
href: 'https://ant.design',
avatar: ['https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png'][i % 2],
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${i}`,
title: `一个任务名称 ${i}`,
owner: '曲丽丽',
@ -108,7 +114,7 @@ export function postRule(req, res, u, b) {
});
break;
case 'update':
tableListDataSource = tableListDataSource.map((item) => {
tableListDataSource = tableListDataSource.map(item => {
if (item.key === key) {
return { ...item, desc, name };
}

13
package.json

@ -17,7 +17,8 @@
"lint-staged:js": "eslint --ext .js",
"test": "roadhog test",
"test:component": "roadhog test ./src/components",
"test:all": "node ./tests/run-tests.js"
"test:all": "node ./tests/run-tests.js",
"prettier": "prettier --write ./src/**/**/**/*"
},
"dependencies": {
"@antv/data-set": "^0.8.0",
@ -64,31 +65,31 @@
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-markdown": "^1.0.0-beta.6",
"eslint-plugin-react": "^7.0.1",
"eslint-config-prettier": "^2.9.0",
"gh-pages": "^1.0.0",
"husky": "^0.14.3",
"lint-staged": "^6.0.0",
"mockjs": "^1.0.1-beta3",
"prettier": "1.11.1",
"pro-download": "^1.0.1",
"redbox-react": "^1.5.0",
"regenerator-runtime": "^0.11.1",
"roadhog": "^2.3.0",
"roadhog-api-doc": "^0.3.4",
"stylelint": "^8.4.0",
"stylelint-config-prettier": "^3.0.4",
"stylelint-config-standard": "^18.0.0"
},
"optionalDependencies": {
"puppeteer": "^1.1.1"
},
"lint-staged": {
"**/*.{js,jsx,less}": ["prettier --wirter", "git add"],
"**/*.{js,jsx}": "lint-staged:js",
"**/*.less": "stylelint --syntax less"
},
"engines": {
"node": ">=8.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 10"
]
"browserslist": ["> 1%", "last 2 versions", "not ie <= 10"]
}

298
src/common/menu.js

@ -1,134 +1,178 @@
import { isUrl } from '../utils/utils';
const menuData = [{
name: 'dashboard',
icon: 'dashboard',
path: 'dashboard',
children: [{
name: '分析页',
path: 'analysis',
}, {
name: '监控页',
path: 'monitor',
}, {
name: '工作台',
path: 'workplace',
// hideInBreadcrumb: true,
// hideInMenu: true,
}],
}, {
name: '表单页',
icon: 'form',
path: 'form',
children: [{
name: '基础表单',
path: 'basic-form',
}, {
name: '分步表单',
path: 'step-form',
}, {
name: '高级表单',
authority: 'admin',
path: 'advanced-form',
}],
}, {
name: '列表页',
icon: 'table',
path: 'list',
children: [{
name: '查询表格',
path: 'table-list',
}, {
name: '标准列表',
path: 'basic-list',
}, {
name: '卡片列表',
path: 'card-list',
}, {
name: '搜索列表',
path: 'search',
children: [{
name: '搜索列表(文章)',
path: 'articles',
}, {
name: '搜索列表(项目)',
path: 'projects',
}, {
name: '搜索列表(应用)',
path: 'applications',
}],
}],
}, {
name: '详情页',
icon: 'profile',
path: 'profile',
children: [{
name: '基础详情页',
path: 'basic',
}, {
name: '高级详情页',
path: 'advanced',
authority: 'admin',
}],
}, {
name: '结果页',
icon: 'check-circle-o',
path: 'result',
children: [{
name: '成功',
path: 'success',
}, {
name: '失败',
path: 'fail',
}],
}, {
name: '异常页',
icon: 'warning',
path: 'exception',
children: [{
name: '403',
path: '403',
}, {
name: '404',
path: '404',
}, {
name: '500',
path: '500',
}, {
name: '触发异常',
path: 'trigger',
hideInMenu: true,
}],
}, {
name: '账户',
icon: 'user',
path: 'user',
authority: 'guest',
children: [{
name: '登录',
path: 'login',
}, {
name: '注册',
path: 'register',
}, {
name: '注册结果',
path: 'register-result',
}],
}, {
name: '个人页',
icon: 'user',
path: 'account',
children: [{
name: '个人中心',
path: 'center',
}, {
name: '个人设置',
path: 'settings',
}],
}];
const menuData = [
{
name: 'dashboard',
icon: 'dashboard',
path: 'dashboard',
children: [
{
name: '分析页',
path: 'analysis',
},
{
name: '监控页',
path: 'monitor',
},
{
name: '工作台',
path: 'workplace',
// hideInBreadcrumb: true,
// hideInMenu: true,
},
],
},
{
name: '表单页',
icon: 'form',
path: 'form',
children: [
{
name: '基础表单',
path: 'basic-form',
},
{
name: '分步表单',
path: 'step-form',
},
{
name: '高级表单',
authority: 'admin',
path: 'advanced-form',
},
],
},
{
name: '列表页',
icon: 'table',
path: 'list',
children: [
{
name: '查询表格',
path: 'table-list',
},
{
name: '标准列表',
path: 'basic-list',
},
{
name: '卡片列表',
path: 'card-list',
},
{
name: '搜索列表',
path: 'search',
children: [
{
name: '搜索列表(文章)',
path: 'articles',
},
{
name: '搜索列表(项目)',
path: 'projects',
},
{
name: '搜索列表(应用)',
path: 'applications',
},
],
},
],
},
{
name: '详情页',
icon: 'profile',
path: 'profile',
children: [
{
name: '基础详情页',
path: 'basic',
},
{
name: '高级详情页',
path: 'advanced',
authority: 'admin',
},
],
},
{
name: '结果页',
icon: 'check-circle-o',
path: 'result',
children: [
{
name: '成功',
path: 'success',
},
{
name: '失败',
path: 'fail',
},
],
},
{
name: '异常页',
icon: 'warning',
path: 'exception',
children: [
{
name: '403',
path: '403',
},
{
name: '404',
path: '404',
},
{
name: '500',
path: '500',
},
{
name: '触发异常',
path: 'trigger',
hideInMenu: true,
},
],
},
{
name: '账户',
icon: 'user',
path: 'user',
authority: 'guest',
children: [
{
name: '登录',
path: 'login',
},
{
name: '注册',
path: 'register',
},
{
name: '注册结果',
path: 'register-result',
},
],
},
{
name: '个人页',
icon: 'user',
path: 'account',
children: [
{
name: '个人中心',
path: 'center',
},
{
name: '个人设置',
path: 'settings',
},
],
},
];
function formatter(data, parentPath = '/', parentAuthority) {
return data.map((item) => {
return data.map(item => {
let { path } = item;
if (!isUrl(path)) {
path = parentPath + item.path;

71
src/common/router.js

@ -5,25 +5,24 @@ import { getMenuData } from './menu';
let routerDataCache;
const modelNotExisted = (app, model) => (
const modelNotExisted = (app, model) =>
// eslint-disable-next-line
!app._models.some(({ namespace }) => {
return namespace === model.substring(model.lastIndexOf('/') + 1);
})
);
});
// wrapper of dynamic
const dynamicWrapper = (app, models, component) => {
// () => require('module')
// transformed by babel-plugin-dynamic-import-node-sync
if (component.toString().indexOf('.then(') < 0) {
models.forEach((model) => {
models.forEach(model => {
if (modelNotExisted(app, model)) {
// eslint-disable-next-line
app.model(require(`../models/${model}`).default);
}
});
return (props) => {
return props => {
if (!routerDataCache) {
routerDataCache = getRouterData(app);
}
@ -36,20 +35,20 @@ const dynamicWrapper = (app, models, component) => {
// () => import('module')
return dynamic({
app,
models: () => models.filter(
model => modelNotExisted(app, model)).map(m => import(`../models/${m}.js`)
),
models: () =>
models.filter(model => modelNotExisted(app, model)).map(m => import(`../models/${m}.js`)),
// add routerData prop
component: () => {
if (!routerDataCache) {
routerDataCache = getRouterData(app);
}
return component().then((raw) => {
return component().then(raw => {
const Component = raw.default || raw;
return props => createElement(Component, {
...props,
routerData: routerDataCache,
});
return props =>
createElement(Component, {
...props,
routerData: routerDataCache,
});
});
},
});
@ -57,7 +56,7 @@ const dynamicWrapper = (app, models, component) => {
function getFlatMenuData(menus) {
let keys = {};
menus.forEach((item) => {
menus.forEach(item => {
if (item.children) {
keys[item.path] = { ...item };
keys = { ...keys, ...getFlatMenuData(item.children) };
@ -68,10 +67,12 @@ function getFlatMenuData(menus) {
return keys;
}
export const getRouterData = (app) => {
export const getRouterData = app => {
const routerConfig = {
'/': {
component: dynamicWrapper(app, ['user', 'login', 'setting'], () => import('../layouts/LoadingPage')),
component: dynamicWrapper(app, ['user', 'login', 'setting'], () =>
import('../layouts/LoadingPage')
),
},
'/dashboard/analysis': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
@ -80,7 +81,9 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},
'/dashboard/workplace': {
component: dynamicWrapper(app, ['user', 'project', 'activities', 'chart'], () => import('../routes/Dashboard/Workplace')),
component: dynamicWrapper(app, ['user', 'project', 'activities', 'chart'], () =>
import('../routes/Dashboard/Workplace')
),
// hideInBreadcrumb: true,
// name: '工作台',
// authority: 'admin',
@ -131,7 +134,9 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/BasicProfile')),
},
'/profile/advanced': {
component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/AdvancedProfile')),
component: dynamicWrapper(app, ['profile'], () =>
import('../routes/Profile/AdvancedProfile')
),
},
'/result/success': {
component: dynamicWrapper(app, [], () => import('../routes/Result/Success')),
@ -149,7 +154,9 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, [], () => import('../routes/Exception/500')),
},
'/exception/trigger': {
component: dynamicWrapper(app, ['error'], () => import('../routes/Exception/triggerException')),
component: dynamicWrapper(app, ['error'], () =>
import('../routes/Exception/triggerException')
),
},
'/user': {
component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')),
@ -164,7 +171,9 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')),
},
'/account/center': {
component: dynamicWrapper(app, ['list', 'user', 'project'], () => import('../routes/Account/Center/Center')),
component: dynamicWrapper(app, ['list', 'user', 'project'], () =>
import('../routes/Account/Center/Center')
),
},
'/account/center/articles': {
component: dynamicWrapper(app, [], () => import('../routes/Account/Center/Articles')),
@ -176,19 +185,29 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, [], () => import('../routes/Account/Center/Projects')),
},
'/account/settings': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/Info')),
component: dynamicWrapper(app, ['geographic'], () =>
import('../routes/Account/Settings/Info')
),
},
'/account/settings/base': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/BaseView')),
component: dynamicWrapper(app, ['geographic'], () =>
import('../routes/Account/Settings/BaseView')
),
},
'/account/settings/security': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/SecurityView')),
component: dynamicWrapper(app, ['geographic'], () =>
import('../routes/Account/Settings/SecurityView')
),
},
'/account/settings/binding': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/BindingView')),
component: dynamicWrapper(app, ['geographic'], () =>
import('../routes/Account/Settings/BindingView')
),
},
'/account/settings/notification': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/NotificationView')),
component: dynamicWrapper(app, ['geographic'], () =>
import('../routes/Account/Settings/NotificationView')
),
},
// '/user/:id': {
// component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')),
@ -201,7 +220,7 @@ export const getRouterData = (app) => {
// eg. {name,authority ...routerConfig }
const routerData = {};
// The route matches the menu
Object.keys(routerConfig).forEach((path) => {
Object.keys(routerConfig).forEach(path => {
// Regular match item name
// eg. router /user/:id === /user/chen
const pathRegexp = pathToRegexp(path);

2
src/components/ActiveChart/index.js

@ -14,7 +14,7 @@ function getActiveData() {
for (let i = 0; i < 24; i += 1) {
activeData.push({
x: `${fixedZero(i)}:00`,
y: Math.floor(Math.random() * 200) + (i * 50),
y: Math.floor(Math.random() * 200) + i * 50,
});
}
return activeData;

22
src/components/Authorized/AuthorizedRoute.js

@ -4,29 +4,13 @@ import Authorized from './Authorized';
class AuthorizedRoute extends React.Component {
render() {
const {
component: Component,
render,
authority,
redirectPath,
...rest
} = this.props;
const { component: Component, render, authority, redirectPath, ...rest } = this.props;
return (
<Authorized
authority={authority}
noMatch={
<Route
{...rest}
render={() => <Redirect to={{ pathname: redirectPath }} />}
/>
}
noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
>
<Route
{...rest}
render={props =>
(Component ? <Component {...props} /> : render(props))
}
/>
<Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} />
</Authorized>
);
}

16
src/components/Authorized/CheckPermissions.test.js

@ -20,24 +20,16 @@ describe('test CheckPermissions', () => {
expect(checkPermissions('admin', 'user', target, error)).toEqual('error');
});
it('Correct Array permission authentication', () => {
expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual(
'ok'
);
expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual('ok');
});
it('Wrong Array permission authentication,currentAuthority error', () => {
expect(
checkPermissions(['user', 'admin'], 'user,admin', target, error)
).toEqual('error');
expect(checkPermissions(['user', 'admin'], 'user,admin', target, error)).toEqual('error');
});
it('Wrong Array permission authentication', () => {
expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual(
'error'
);
expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual('error');
});
it('Wrong Function permission authentication', () => {
expect(checkPermissions(() => false, 'guest', target, error)).toEqual(
'error'
);
expect(checkPermissions(() => false, 'guest', target, error)).toEqual('error');
});
it('Correct Function permission authentication', () => {
expect(checkPermissions(() => true, 'guest', target, error)).toEqual('ok');

2
src/components/Authorized/PromiseRender.js

@ -32,7 +32,7 @@ export default class PromiseRender extends React.PureComponent {
// AuthorizedRoute is already instantiated
// Authorized render is already instantiated, children is no instantiated
// Secured is not instantiated
checkIsInstantiation = (target) => {
checkIsInstantiation = target => {
if (!React.isValidElement(target)) {
return target;
}

6
src/components/Authorized/Secured.js

@ -5,15 +5,13 @@ import CheckPermissions from './CheckPermissions';
* 默认不能访问任何页面
* default is "NULL"
*/
const Exception403 = () => (
<Exception type="403" style={{ minHeight: 500, height: '80%' }} />
);
const Exception403 = () => <Exception type="403" style={{ minHeight: 500, height: '80%' }} />;
// Determine whether the incoming component has been instantiated
// AuthorizedRoute is already instantiated
// Authorized render is already instantiated, children is no instantiated
// Secured is not instantiated
const checkIsInstantiation = (target) => {
const checkIsInstantiation = target => {
if (!React.isValidElement(target)) {
return target;
}

11
src/components/Authorized/index.d.ts

@ -11,24 +11,19 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>;
interface Secured {
(authority: authority, error?: React.ReactNode): <T extends IReactComponent>(
target: T,
) => T;
(authority: authority, error?: React.ReactNode): <T extends IReactComponent>(target: T) => T;
}
export interface AuthorizedRouteProps extends RouteProps {
authority: authority;
}
export class AuthorizedRoute extends React.Component<
AuthorizedRouteProps,
any
> {}
export class AuthorizedRoute extends React.Component<AuthorizedRouteProps, any> {}
interface check {
<T extends IReactComponent, S extends IReactComponent>(
authority: authority,
target: T,
Exception: S,
Exception: S
): T | S;
}

2
src/components/Authorized/index.js

@ -14,7 +14,7 @@ Authorized.check = check;
* use authority or getAuthority
* @param {string|()=>String} currentAuthority
*/
const renderAuthorize = (currentAuthority) => {
const renderAuthorize = currentAuthority => {
if (currentAuthority) {
if (currentAuthority.constructor.name === 'Function') {
CURRENT = currentAuthority();

4
src/components/AvatarList/index.d.ts

@ -4,9 +4,7 @@ import AvatarItem from './AvatarItem';
export interface IAvatarListProps {
size?: 'large' | 'small' | 'mini' | 'default';
style?: React.CSSProperties;
children:
| React.ReactElement<AvatarItem>
| Array<React.ReactElement<AvatarItem>>;
children: React.ReactElement<AvatarItem> | Array<React.ReactElement<AvatarItem>>;
}
export default class AvatarList extends React.Component<IAvatarListProps, any> {

18
src/components/AvatarList/index.js

@ -18,7 +18,7 @@ const AvatarList = ({ children, size, ...other }) => {
);
};
const Item = ({ src, size, tips, onClick = (() => {}) }) => {
const Item = ({ src, size, tips, onClick = () => {} }) => {
const cls = classNames(styles.avatarItem, {
[styles.avatarItemLarge]: size === 'large',
[styles.avatarItemSmall]: size === 'small',
@ -26,14 +26,14 @@ const Item = ({ src, size, tips, onClick = (() => {}) }) => {
});
return (
<li className={cls} onClick={onClick} >
{
tips ? (
<Tooltip title={tips}>
<Avatar src={src} size={size} style={{ cursor: 'pointer' }} />
</Tooltip>
) : <Avatar src={src} size={size} />
}
<li className={cls} onClick={onClick}>
{tips ? (
<Tooltip title={tips}>
<Avatar src={src} size={size} style={{ cursor: 'pointer' }} />
</Tooltip>
) : (
<Avatar src={src} size={size} />
)}
</li>
);
};

2
src/components/AvatarList/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.avatarList {
display: inline-block;

2
src/components/Charts/Bar/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IBarProps {
title: React.ReactNode;
color?: string;

4
src/components/Charts/Bar/index.js

@ -46,11 +46,11 @@ class Bar extends Component {
}
}
handleRoot = (n) => {
handleRoot = n => {
this.root = n;
};
handleRef = (n) => {
handleRef = n => {
this.node = n;
};

2
src/components/Charts/ChartCard/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IChartCardProps {
title: React.ReactNode;
action?: React.ReactNode;

12
src/components/Charts/ChartCard/index.js

@ -4,7 +4,7 @@ import classNames from 'classnames';
import styles from './index.less';
const renderTotal = (total) => {
const renderTotal = total => {
let totalDom;
switch (typeof total) {
case undefined:
@ -33,7 +33,9 @@ const ChartCard = ({
const content = (
<div className={styles.chartCard}>
<div
className={classNames(styles.chartTop, { [styles.chartTopMargin]: !children && !footer })}
className={classNames(styles.chartTop, {
[styles.chartTopMargin]: !children && !footer,
})}
>
<div className={styles.avatar}>{avatar}</div>
<div className={styles.metaWrap}>
@ -50,7 +52,11 @@ const ChartCard = ({
</div>
)}
{footer && (
<div className={classNames(styles.footer, { [styles.footerMargin]: !children })}>
<div
className={classNames(styles.footer, {
[styles.footerMargin]: !children,
})}
>
{footer}
</div>
)}

2
src/components/Charts/ChartCard/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.chartCard {
position: relative;

2
src/components/Charts/Field/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IFieldProps {
label: React.ReactNode;
value: React.ReactNode;

2
src/components/Charts/Field/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.field {
white-space: nowrap;

2
src/components/Charts/Gauge/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IGaugeProps {
title: React.ReactNode;
color?: string;

2
src/components/Charts/Gauge/index.js

@ -4,7 +4,7 @@ import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide;
const defaultFormatter = (val) => {
const defaultFormatter = val => {
switch (val) {
case '2':
return '差';

7
src/components/Charts/MiniProgress/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IMiniProgressProps {
target: number;
color?: string;
@ -7,7 +7,4 @@ export interface IMiniProgressProps {
style?: React.CSSProperties;
}
export default class MiniProgress extends React.Component<
IMiniProgressProps,
any
> {}
export default class MiniProgress extends React.Component<IMiniProgressProps, any> {}

15
src/components/Charts/MiniProgress/index.js

@ -6,21 +6,18 @@ import styles from './index.less';
const MiniProgress = ({ target, color = 'rgb(19, 194, 194)', strokeWidth, percent }) => (
<div className={styles.miniProgress}>
<Tooltip title={`目标值: ${target}%`}>
<div
className={styles.target}
style={{ left: (target ? `${target}%` : null) }}
>
<span style={{ backgroundColor: (color || null) }} />
<span style={{ backgroundColor: (color || null) }} />
<div className={styles.target} style={{ left: target ? `${target}%` : null }}>
<span style={{ backgroundColor: color || null }} />
<span style={{ backgroundColor: color || null }} />
</div>
</Tooltip>
<div className={styles.progressWrap}>
<div
className={styles.progress}
style={{
backgroundColor: (color || null),
width: (percent ? `${percent}%` : null),
height: (strokeWidth || null),
backgroundColor: color || null,
width: percent ? `${percent}%` : null,
height: strokeWidth || null,
}}
/>
</div>

4
src/components/Charts/MiniProgress/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.miniProgress {
padding: 5px 0;
@ -9,7 +9,7 @@
position: relative;
}
.progress {
transition: all .4s cubic-bezier(.08, .82, .17, 1) 0s;
transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
border-radius: 1px 0 0 1px;
background-color: @primary-color;
width: 0;

12
src/components/Charts/Pie/index.js

@ -44,7 +44,7 @@ export default class Pie extends Component {
this.resize.cancel();
}
getG2Instance = (chart) => {
getG2Instance = chart => {
this.chart = chart;
};
@ -54,7 +54,7 @@ export default class Pie extends Component {
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
const items = geom.get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item) => {
const legendData = items.map(item => {
/* eslint no-underscore-dangle:0 */
const origin = item[0]._origin;
origin.color = item[0].color;
@ -89,7 +89,7 @@ export default class Pie extends Component {
}
}
handleRoot = (n) => {
handleRoot = n => {
this.root = n;
};
@ -154,7 +154,7 @@ export default class Pie extends Component {
if (percent) {
selected = false;
tooltip = false;
formatColor = (value) => {
formatColor = value => {
if (value === '占比') {
return color || 'rgba(24, 144, 255, 0.85)';
} else {
@ -235,7 +235,9 @@ export default class Pie extends Component {
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
<span
className={styles.dot}
style={{ backgroundColor: !item.checked ? '#aaa' : item.color }}
style={{
backgroundColor: !item.checked ? '#aaa' : item.color,
}}
/>
<span className={styles.legendTitle}>{item.x}</span>
<Divider type="vertical" />

4
src/components/Charts/Pie/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.pie {
position: relative;
@ -6,7 +6,7 @@
position: relative;
}
&.hasLegend .chart {
width: ~"calc(100% - 240px)";
width: ~'calc(100% - 240px)';
}
.legend {
position: absolute;

2
src/components/Charts/Radar/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IRadarProps {
title?: React.ReactNode;
height: number;

19
src/components/Charts/Radar/index.js

@ -21,7 +21,7 @@ export default class Radar extends Component {
}
}
getG2Instance = (chart) => {
getG2Instance = chart => {
this.chart = chart;
};
@ -31,7 +31,7 @@ export default class Radar extends Component {
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
const items = geom.get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item) => {
const legendData = items.map(item => {
// eslint-disable-next-line
const origins = item.map(t => t._origin);
const result = {
@ -49,7 +49,7 @@ export default class Radar extends Component {
});
};
handleRef = (n) => {
handleRef = n => {
this.node = n;
};
@ -60,9 +60,7 @@ export default class Radar extends Component {
const { legendData } = this.state;
legendData[i] = newItem;
const filteredLegendData = legendData
.filter(l => l.checked)
.map(l => l.name);
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.name);
if (this.chart) {
this.chart.filter('name', val => filteredLegendData.indexOf(val) > -1);
@ -143,12 +141,7 @@ export default class Radar extends Component {
},
}}
/>
<Geom
type="line"
position="label*value"
color={['name', colors]}
size={1}
/>
<Geom type="line" position="label*value" color={['name', colors]} size={1} />
<Geom
type="point"
position="label*value"
@ -178,7 +171,7 @@ export default class Radar extends Component {
<h6>{item.value}</h6>
</div>
</Col>
))}
))}
</Row>
)}
</div>

2
src/components/Charts/Radar/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.radar {
.legend {

2
src/components/Charts/TagCloud/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface ITagCloudProps {
data: Array<{
name: string;

4
src/components/Charts/TagCloud/index.js

@ -39,7 +39,7 @@ class TagCloud extends Component {
this.renderChart();
};
saveRootRef = (node) => {
saveRootRef = node => {
this.root = node;
};
@ -77,7 +77,7 @@ class TagCloud extends Component {
@Bind()
@Debounce(500)
renderChart = (nextProps) => {
renderChart = nextProps => {
// const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
const { data, height } = nextProps || this.props;

7
src/components/Charts/TimelineChart/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface ITimelineChartProps {
data: Array<{
x: string;
@ -11,7 +11,4 @@ export interface ITimelineChartProps {
style?: React.CSSProperties;
}
export default class TimelineChart extends React.Component<
ITimelineChartProps,
any
> {}
export default class TimelineChart extends React.Component<ITimelineChartProps, any> {}

2
src/components/Charts/TimelineChart/index.js

@ -48,7 +48,7 @@ export default class TimelineChart extends React.Component {
.source(data)
.transform({
type: 'filter',
callback: (obj) => {
callback: obj => {
const date = obj.x;
return date <= ds.state.end && date >= ds.state.start;
},

4
src/components/Charts/WaterWave/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.waterWave {
display: inline-block;
@ -22,7 +22,7 @@
}
}
.waterWaveCanvasWrapper {
transform: scale(.5);
transform: scale(0.5);
transform-origin: 0 0;
}
}

4
src/components/Charts/autoHeight.js

@ -30,7 +30,7 @@ function getAutoHeight(n) {
return height;
}
const autoHeight = () => (WrappedComponent) => {
const autoHeight = () => WrappedComponent => {
return class extends React.Component {
state = {
computedHeight: 0,
@ -45,7 +45,7 @@ const autoHeight = () => (WrappedComponent) => {
}
}
handleRoot = (node) => {
handleRoot = node => {
this.root = node;
};

2
src/components/CountDown/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface ICountDownProps {
format?: (time: number) => void;
target: Date | number;

61
src/components/CountDown/index.js

@ -23,11 +23,14 @@ class CountDown extends Component {
if (this.props.target !== nextProps.target) {
clearTimeout(this.timer);
const { lastTime } = this.initTime(nextProps);
this.setState({
lastTime,
}, () => {
this.tick();
});
this.setState(
{
lastTime,
},
() => {
this.tick();
}
);
}
}
@ -37,7 +40,7 @@ class CountDown extends Component {
timer = 0;
interval = 1000;
initTime = (props) => {
initTime = props => {
let lastTime = 0;
let targetTime = 0;
try {
@ -54,21 +57,23 @@ class CountDown extends Component {
return {
lastTime: lastTime < 0 ? 0 : lastTime,
};
}
};
// defaultFormat = time => (
// <span>{moment(time).format('hh:mm:ss')}</span>
// );
defaultFormat = (time) => {
defaultFormat = time => {
const hours = 60 * 60 * 1000;
const minutes = 60 * 1000;
const h = Math.floor(time / hours);
const m = Math.floor((time - (h * hours)) / minutes);
const s = Math.floor((time - (h * hours) - (m * minutes)) / 1000);
const m = Math.floor((time - h * hours) / minutes);
const s = Math.floor((time - h * hours - m * minutes) / 1000);
return (
<span>{fixedZero(h)}:{fixedZero(m)}:{fixedZero(s)}</span>
<span>
{fixedZero(h)}:{fixedZero(m)}:{fixedZero(s)}
</span>
);
}
};
tick = () => {
const { onEnd } = this.props;
let { lastTime } = this.state;
@ -76,30 +81,36 @@ class CountDown extends Component {
this.timer = setTimeout(() => {
if (lastTime < this.interval) {
clearTimeout(this.timer);
this.setState({
lastTime: 0,
}, () => {
if (onEnd) {
onEnd();
this.setState(
{
lastTime: 0,
},
() => {
if (onEnd) {
onEnd();
}
}
});
);
} else {
lastTime -= this.interval;
this.setState({
lastTime,
}, () => {
this.tick();
});
this.setState(
{
lastTime,
},
() => {
this.tick();
}
);
}
}, this.interval);
}
};
render() {
const { format = this.defaultFormat, onEnd, ...rest } = this.props;
const { lastTime } = this.state;
const result = format(lastTime);
return (<span {...rest}>{result}</span>);
return <span {...rest}>{result}</span>;
}
}

12
src/components/DescriptionList/DescriptionList.js

@ -3,8 +3,16 @@ import classNames from 'classnames';
import { Row } from 'antd';
import styles from './index.less';
export default ({ className, title, col = 3, layout = 'horizontal', gutter = 32,
children, size, ...restProps }) => {
export default ({
className,
title,
col = 3,
layout = 'horizontal',
gutter = 32,
children,
size,
...restProps
}) => {
const clsString = classNames(styles.descriptionList, styles[layout], className, {
[styles.small]: size === 'small',
[styles.large]: size === 'large',

5
src/components/DescriptionList/index.d.ts

@ -10,9 +10,6 @@ export interface IDescriptionListProps {
style?: React.CSSProperties;
}
export default class DescriptionList extends React.Component<
IDescriptionListProps,
any
> {
export default class DescriptionList extends React.Component<IDescriptionListProps, any> {
public static Description: typeof Description;
}

9
src/components/DescriptionList/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.descriptionList {
// offset the padding-bottom of last row
@ -25,10 +25,10 @@
display: table-cell;
&:after {
content: ":";
content: ':';
margin: 0 8px 0 2px;
position: relative;
top: -.5px;
top: -0.5px;
}
}
@ -51,7 +51,8 @@
margin-bottom: 12px;
color: @text-color;
}
.term, .detail {
.term,
.detail {
padding-bottom: 8px;
}
}

44
src/components/EditableItem/index.js

@ -7,48 +7,34 @@ export default class EditableItem extends PureComponent {
value: this.props.value,
editable: false,
};
handleChange = (e) => {
handleChange = e => {
const { value } = e.target;
this.setState({ value });
}
};
check = () => {
this.setState({ editable: false });
if (this.props.onChange) {
this.props.onChange(this.state.value);
}
}
};
edit = () => {
this.setState({ editable: true });
}
};
render() {
const { value, editable } = this.state;
return (
<div className={styles.editableItem}>
{
editable ? (
<div className={styles.wrapper}>
<Input
value={value}
onChange={this.handleChange}
onPressEnter={this.check}
/>
<Icon
type="check"
className={styles.icon}
onClick={this.check}
/>
</div>
) : (
<div className={styles.wrapper}>
<span>{value || ' '}</span>
<Icon
type="edit"
className={styles.icon}
onClick={this.edit}
/>
</div>
)
}
{editable ? (
<div className={styles.wrapper}>
<Input value={value} onChange={this.handleChange} onPressEnter={this.check} />
<Icon type="check" className={styles.icon} onClick={this.check} />
</div>
) : (
<div className={styles.wrapper}>
<span>{value || ' '}</span>
<Icon type="edit" className={styles.icon} onClick={this.edit} />
</div>
)}
</div>
);
}

2
src/components/EditableItem/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.editableItem {
line-height: @input-height-base;

14
src/components/EditableLinkGroup/index.js

@ -22,15 +22,17 @@ class EditableLinkGroup extends PureComponent {
const { links, linkElement, onAdd } = this.props;
return (
<div className={styles.linkGroup}>
{
links.map(link => (
createElement(linkElement, {
{links.map(link =>
createElement(
linkElement,
{
key: `linkGroup-item-${link.id || link.title}`,
to: link.href,
href: link.href,
}, link.title)
))
}
},
link.title
)
)}
{
<Button size="small" type="primary" ghost onClick={onAdd} icon="plus">
添加

2
src/components/EditableLinkGroup/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.linkGroup {
padding: 20px 0 8px 24px;

10
src/components/Ellipsis/index.js

@ -125,23 +125,23 @@ export default class Ellipsis extends Component {
}
};
handleRoot = (n) => {
handleRoot = n => {
this.root = n;
};
handleContent = (n) => {
handleContent = n => {
this.content = n;
};
handleNode = (n) => {
handleNode = n => {
this.node = n;
};
handleShadow = (n) => {
handleShadow = n => {
this.shadow = n;
};
handleShadowChildren = (n) => {
handleShadowChildren = n => {
this.shadowChildren = n;
};

4
src/components/Exception/index.d.ts

@ -1,6 +1,6 @@
import * as React from "react";
import * as React from 'react';
export interface IExceptionProps {
type?: "403" | "404" | "500";
type?: '403' | '404' | '500';
title?: React.ReactNode;
desc?: React.ReactNode;
img?: string;

12
src/components/Exception/index.js

@ -19,13 +19,15 @@ export default ({ className, linkElement = 'a', type, title, desc, img, actions,
<h1>{title || config[pageType].title}</h1>
<div className={styles.desc}>{desc || config[pageType].desc}</div>
<div className={styles.actions}>
{
actions ||
createElement(linkElement, {
{actions ||
createElement(
linkElement,
{
to: '/',
href: '/',
}, <Button type="primary">返回首页</Button>)
}
},
<Button type="primary">返回首页</Button>
)}
</div>
</div>
</div>

4
src/components/Exception/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.exception {
display: flex;
@ -12,7 +12,7 @@
zoom: 1;
&:before,
&:after {
content: " ";
content: ' ';
display: table;
}
&:after {

5
src/components/FooterToolbar/index.d.ts

@ -4,7 +4,4 @@ export interface IFooterToolbarProps {
style?: React.CSSProperties;
}
export default class FooterToolbar extends React.Component<
IFooterToolbarProps,
any
> {}
export default class FooterToolbar extends React.Component<IFooterToolbarProps, any> {}

5
src/components/FooterToolbar/index.js

@ -6,10 +6,7 @@ export default class FooterToolbar extends Component {
render() {
const { children, className, extra, ...restProps } = this.props;
return (
<div
className={classNames(className, styles.toolbar)}
{...restProps}
>
<div className={classNames(className, styles.toolbar)} {...restProps}>
<div className={styles.left}>{extra}</div>
<div className={styles.right}>{children}</div>
</div>

6
src/components/FooterToolbar/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.toolbar {
position: fixed;
@ -7,14 +7,14 @@
right: 0;
height: 56px;
line-height: 56px;
box-shadow: 0 -1px 2px rgba(0, 0, 0, .03);
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03);
background: #fff;
border-top: 1px solid @border-color-split;
padding: 0 24px;
z-index: 9;
&:after {
content: "";
content: '';
display: block;
clear: both;
}

7
src/components/GlobalFooter/index.d.ts

@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
export interface IGlobalFooterProps {
links?: Array<{
title: React.ReactNode;
@ -9,7 +9,4 @@ export interface IGlobalFooterProps {
style?: React.CSSProperties;
}
export default class GlobalFooter extends React.Component<
IGlobalFooterProps,
any
> {}
export default class GlobalFooter extends React.Component<IGlobalFooterProps, any> {}

24
src/components/GlobalFooter/index.js

@ -6,21 +6,15 @@ export default ({ className, links, copyright }) => {
const clsString = classNames(styles.globalFooter, className);
return (
<div className={clsString}>
{
links && (
<div className={styles.links}>
{links.map(link => (
<a
key={link.key}
target={link.blankTarget ? '_blank' : '_self'}
href={link.href}
>
{link.title}
</a>
))}
</div>
)
}
{links && (
<div className={styles.links}>
{links.map(link => (
<a key={link.key} target={link.blankTarget ? '_blank' : '_self'} href={link.href}>
{link.title}
</a>
))}
</div>
)}
{copyright && <div className={styles.copyright}>{copyright}</div>}
</div>
);

4
src/components/GlobalFooter/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.globalFooter {
padding: 0 16px;
@ -10,7 +10,7 @@
a {
color: @text-color-secondary;
transition: all .3s;
transition: all 0.3s;
&:not(:last-child) {
margin-right: 40px;

5
src/components/GlobalHeader/index.js

@ -10,11 +10,12 @@ export default class GlobalHeader extends PureComponent {
this.triggerResizeEvent.cancel();
}
@Debounce(600)
triggerResizeEvent() { // eslint-disable-line
triggerResizeEvent = () => {
// eslint-disable-line
const event = document.createEvent('HTMLEvents');
event.initEvent('resize', true, false);
window.dispatchEvent(event);
}
};
toggle = () => {
const { collapsed, onCollapse } = this.props;
onCollapse(!collapsed);

5
src/components/HeaderSearch/index.d.ts

@ -8,7 +8,4 @@ export interface IHeaderSearchProps {
style?: React.CSSProperties;
}
export default class HeaderSearch extends React.Component<
IHeaderSearchProps,
any
> {}
export default class HeaderSearch extends React.Component<IHeaderSearchProps, any> {}

21
src/components/HeaderSearch/index.js

@ -28,42 +28,39 @@ export default class HeaderSearch extends PureComponent {
componentWillUnmount() {
clearTimeout(this.timeout);
}
onKeyDown = (e) => {
onKeyDown = e => {
if (e.key === 'Enter') {
this.timeout = setTimeout(() => {
this.props.onPressEnter(this.state.value); // Fix duplicate onPressEnter
}, 0);
}
}
onChange = (value) => {
};
onChange = value => {
this.setState({ value });
if (this.props.onChange) {
this.props.onChange();
}
}
};
enterSearchMode = () => {
this.setState({ searchMode: true }, () => {
if (this.state.searchMode) {
this.input.focus();
}
});
}
};
leaveSearchMode = () => {
this.setState({
searchMode: false,
value: '',
});
}
};
render() {
const { className, placeholder, ...restProps } = this.props;
const inputClass = classNames(styles.input, {
[styles.show]: this.state.searchMode,
});
return (
<span
className={classNames(className, styles.headerSearch)}
onClick={this.enterSearchMode}
>
<span className={classNames(className, styles.headerSearch)} onClick={this.enterSearchMode}>
<Icon type="search" key="Icon" />
<AutoComplete
key="AutoComplete"
@ -74,7 +71,9 @@ export default class HeaderSearch extends PureComponent {
>
<Input
placeholder={placeholder}
ref={(node) => { this.input = node; }}
ref={node => {
this.input = node;
}}
onKeyDown={this.onKeyDown}
onBlur={this.leaveSearchMode}
/>

4
src/components/HeaderSearch/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.headerSearch {
:global(.anticon-search) {
@ -6,7 +6,7 @@
font-size: 16px;
}
.input {
transition: width .3s, margin-left .3s;
transition: width 0.3s, margin-left 0.3s;
width: 0;
background: transparent;
border-radius: 0;

6
src/components/Login/LoginItem.js

@ -8,7 +8,7 @@ import map from './map';
const FormItem = Form.Item;
function generator({ defaultProps, defaultRules, type }) {
return (WrappedComponent) => {
return WrappedComponent => {
return class BasicComponent extends Component {
static contextTypes = {
form: PropTypes.object,
@ -41,7 +41,7 @@ function generator({ defaultProps, defaultRules, type }) {
clearInterval(this.interval);
}
}, 1000);
}
};
render() {
const { getFieldDecorator } = this.context.form;
const options = {};
@ -93,7 +93,7 @@ function generator({ defaultProps, defaultRules, type }) {
}
const LoginItem = {};
Object.keys(map).forEach((item) => {
Object.keys(map).forEach(item => {
LoginItem[item] = generator({
defaultProps: map[item].props,
defaultRules: map[item].rules,

4
src/components/Login/index.d.ts

@ -1,5 +1,5 @@
import * as React from "react";
import Button from "antd/lib/button";
import * as React from 'react';
import Button from 'antd/lib/button';
export interface LoginProps {
defaultActiveKey?: string;
onTabChange?: (key: string) => void;

56
src/components/Login/index.js

@ -34,19 +34,19 @@ class Login extends Component {
getChildContext() {
return {
tabUtil: {
addTab: (id) => {
addTab: id => {
this.setState({
tabs: [...this.state.tabs, id],
});
},
removeTab: (id) => {
removeTab: id => {
this.setState({
tabs: this.state.tabs.filter(currentId => currentId !== id),
});
},
},
form: this.props.form,
updateActive: (activeItem) => {
updateActive: activeItem => {
const { type, active } = this.state;
if (active[type]) {
active[type].push(activeItem);
@ -59,28 +59,26 @@ class Login extends Component {
},
};
}
onSwitch = (type) => {
onSwitch = type => {
this.setState({
type,
});
this.props.onTabChange(type);
}
handleSubmit = (e) => {
};
handleSubmit = e => {
e.preventDefault();
const { active, type } = this.state;
const activeFileds = active[type];
this.props.form.validateFields(activeFileds, { force: true },
(err, values) => {
this.props.onSubmit(err, values);
}
);
}
this.props.form.validateFields(activeFileds, { force: true }, (err, values) => {
this.props.onSubmit(err, values);
});
};
render() {
const { className, children } = this.props;
const { type, tabs } = this.state;
const TabChildren = [];
const otherChildren = [];
React.Children.forEach(children, (item) => {
React.Children.forEach(children, item => {
if (!item) {
return;
}
@ -94,21 +92,21 @@ class Login extends Component {
return (
<div className={classNames(className, styles.login)}>
<Form onSubmit={this.handleSubmit}>
{
tabs.length ? (
<div>
<Tabs
animated={false}
className={styles.tabs}
activeKey={type}
onChange={this.onSwitch}
>
{TabChildren}
</Tabs>
{otherChildren}
</div>
) : [...children]
}
{tabs.length ? (
<div>
<Tabs
animated={false}
className={styles.tabs}
activeKey={type}
onChange={this.onSwitch}
>
{TabChildren}
</Tabs>
{otherChildren}
</div>
) : (
[...children]
)}
</Form>
</div>
);
@ -117,7 +115,7 @@ class Login extends Component {
Login.Tab = LoginTab;
Login.Submit = LoginSubmit;
Object.keys(LoginItem).forEach((item) => {
Object.keys(LoginItem).forEach(item => {
Login[item] = LoginItem[item];
});

3
src/components/Login/index.less

@ -1,7 +1,6 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.login {
.tabs {
padding: 0 2px;
margin: 0 -2px;

42
src/components/Login/map.js

@ -10,9 +10,12 @@ const map = {
prefix: <Icon type="user" className={styles.prefixIcon} />,
placeholder: 'admin',
},
rules: [{
required: true, message: 'Please enter username!',
}],
rules: [
{
required: true,
message: 'Please enter username!',
},
],
},
Password: {
component: Input,
@ -22,9 +25,12 @@ const map = {
type: 'password',
placeholder: '888888',
},
rules: [{
required: true, message: 'Please enter password!',
}],
rules: [
{
required: true,
message: 'Please enter password!',
},
],
},
Mobile: {
component: Input,
@ -33,11 +39,16 @@ const map = {
prefix: <Icon type="mobile" className={styles.prefixIcon} />,
placeholder: 'mobile number',
},
rules: [{
required: true, message: 'Please enter mobile number!',
}, {
pattern: /^1\d{10}$/, message: 'Wrong mobile number format!',
}],
rules: [
{
required: true,
message: 'Please enter mobile number!',
},
{
pattern: /^1\d{10}$/,
message: 'Wrong mobile number format!',
},
],
},
Captcha: {
component: Input,
@ -46,9 +57,12 @@ const map = {
prefix: <Icon type="mail" className={styles.prefixIcon} />,
placeholder: 'captcha',
},
rules: [{
required: true, message: 'Please enter Captcha!',
}],
rules: [
{
required: true,
message: 'Please enter Captcha!',
},
],
},
};

5
src/components/NoticeIcon/NoticeIconTab.d.ts

@ -16,7 +16,4 @@ export interface INoticeIconTabProps {
style?: React.CSSProperties;
}
export default class NoticeIconTab extends React.Component<
INoticeIconTabProps,
any
> {}
export default class NoticeIconTab extends React.Component<INoticeIconTabProps, any> {}

15
src/components/NoticeIcon/NoticeList.js

@ -4,14 +4,18 @@ import classNames from 'classnames';
import styles from './NoticeList.less';
export default function NoticeList({
data = [], onClick, onClear, title, locale, emptyText, emptyImage,
data = [],
onClick,
onClear,
title,
locale,
emptyText,
emptyImage,
}) {
if (data.length === 0) {
return (
<div className={styles.notFound}>
{emptyImage ? (
<img src={emptyImage} alt="not found" />
) : null}
{emptyImage ? <img src={emptyImage} alt="not found" /> : null}
<div>{emptyText || locale.emptyText}</div>
</div>
);
@ -48,7 +52,8 @@ export default function NoticeList({
})}
</List>
<div className={styles.clear} onClick={onClear}>
{locale.clear}{title}
{locale.clear}
{title}
</div>
</div>
);

8
src/components/NoticeIcon/NoticeList.less

@ -1,10 +1,10 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.list {
max-height: 400px;
overflow: auto;
.item {
transition: all .3s;
transition: all 0.3s;
overflow: hidden;
cursor: pointer;
padding-left: 24px;
@ -20,7 +20,7 @@
}
&.read {
opacity: .4;
opacity: 0.4;
}
&:last-child {
border-bottom: 0;
@ -69,7 +69,7 @@
color: @text-color;
border-radius: 0 0 @border-radius-base @border-radius-base;
border-top: 1px solid @border-color-split;
transition: all .3s;
transition: all 0.3s;
cursor: pointer;
&:hover {

14
src/components/NoticeIcon/index.js

@ -30,19 +30,21 @@ export default class NoticeIcon extends PureComponent {
onItemClick = (item, tabProps) => {
const { onItemClick } = this.props;
onItemClick(item, tabProps);
}
onTabChange = (tabType) => {
};
onTabChange = tabType => {
this.setState({ tabType });
this.props.onTabChange(tabType);
}
};
getNotificationBox() {
const { children, loading, locale } = this.props;
if (!children) {
return null;
}
const panes = React.Children.map(children, (child) => {
const title = child.props.list && child.props.list.length > 0
? `${child.props.title} (${child.props.list.length})` : child.props.title;
const panes = React.Children.map(children, child => {
const title =
child.props.list && child.props.list.length > 0
? `${child.props.title} (${child.props.list.length})`
: child.props.title;
return (
<TabPane tab={title} key={child.props.title}>
<List

4
src/components/NoticeIcon/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.popover {
width: 336px;
@ -10,7 +10,7 @@
.noticeButton {
cursor: pointer;
display: inline-block;
transition: all .3s;
transition: all 0.3s;
}
.icon {

5
src/components/NumberInfo/index.d.ts

@ -10,7 +10,4 @@ export interface INumberInfoProps {
style?: React.CSSProperties;
}
export default class NumberInfo extends React.Component<
INumberInfoProps,
any
> {}
export default class NumberInfo extends React.Component<INumberInfoProps, any> {}

26
src/components/NumberInfo/index.js

@ -3,15 +3,11 @@ import { Icon } from 'antd';
import classNames from 'classnames';
import styles from './index.less';
export default ({
theme, title, subTitle, total, subTotal, status, suffix, gap, ...rest
}) => (
export default ({ theme, title, subTitle, total, subTotal, status, suffix, gap, ...rest }) => (
<div
className={
classNames(styles.numberInfo, {
[styles[`numberInfo${theme}`]]: theme,
})
}
className={classNames(styles.numberInfo, {
[styles[`numberInfo${theme}`]]: theme,
})}
{...rest}
>
{title && <div className={styles.numberInfoTitle}>{title}</div>}
@ -21,14 +17,12 @@ export default ({
{total}
{suffix && <em className={styles.suffix}>{suffix}</em>}
</span>
{
(status || subTotal) && (
<span className={styles.subTotal}>
{subTotal}
{status && <Icon type={`caret-${status}`} />}
</span>
)
}
{(status || subTotal) && (
<span className={styles.subTotal}>
{subTotal}
{status && <Icon type={`caret-${status}`} />}
</span>
)}
</div>
</div>
);

4
src/components/NumberInfo/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.numberInfo {
.suffix {
@ -11,7 +11,7 @@
color: @text-color;
font-size: @font-size-lg;
margin-bottom: 16px;
transition: all .3s;
transition: all 0.3s;
}
.numberInfoSubTitle {
color: @text-color-secondary;

39
src/components/PageHeader/index.js

@ -4,13 +4,13 @@ import pathToRegexp from 'path-to-regexp';
import { Breadcrumb, Tabs } from 'antd';
import classNames from 'classnames';
import styles from './index.less';
import { urlToList } from '../utils/pathTools';
import { urlToList } from '../_utils/pathTools';
const { TabPane } = Tabs;
export function getBreadcrumb(breadcrumbNameMap, url) {
let breadcrumb = breadcrumbNameMap[url];
if (!breadcrumb) {
Object.keys(breadcrumbNameMap).forEach((item) => {
Object.keys(breadcrumbNameMap).forEach(item => {
if (pathToRegexp(item).test(url)) {
breadcrumb = breadcrumbNameMap[item];
}
@ -26,7 +26,7 @@ export default class PageHeader extends PureComponent {
location: PropTypes.object,
breadcrumbNameMap: PropTypes.object,
};
onChange = (key) => {
onChange = key => {
if (this.props.onTabChange) {
this.props.onTabChange(key);
}
@ -36,17 +36,12 @@ export default class PageHeader extends PureComponent {
routes: this.props.routes || this.context.routes,
params: this.props.params || this.context.params,
routerLocation: this.props.location || this.context.location,
breadcrumbNameMap:
this.props.breadcrumbNameMap || this.context.breadcrumbNameMap,
breadcrumbNameMap: this.props.breadcrumbNameMap || this.context.breadcrumbNameMap,
};
};
// Generated according to props
conversionFromProps = () => {
const {
breadcrumbList,
breadcrumbSeparator,
linkElement = 'a',
} = this.props;
const { breadcrumbList, breadcrumbSeparator, linkElement = 'a' } = this.props;
return (
<Breadcrumb className={styles.breadcrumb} separator={breadcrumbSeparator}>
{breadcrumbList.map(item => (
@ -57,7 +52,7 @@ export default class PageHeader extends PureComponent {
{
[linkElement === 'a' ? 'href' : 'to']: item.href,
},
item.title,
item.title
)
: item.title}
</Breadcrumb.Item>
@ -72,14 +67,13 @@ export default class PageHeader extends PureComponent {
// Loop data mosaic routing
const extraBreadcrumbItems = pathSnippets.map((url, index) => {
const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url);
const isLinkable =
index !== pathSnippets.length - 1 && currentBreadcrumb.component;
const isLinkable = index !== pathSnippets.length - 1 && currentBreadcrumb.component;
return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? (
<Breadcrumb.Item key={url}>
{createElement(
isLinkable ? linkElement : 'span',
{ [linkElement === 'a' ? 'href' : 'to']: url },
currentBreadcrumb.name,
currentBreadcrumb.name
)}
</Breadcrumb.Item>
) : null;
@ -92,9 +86,9 @@ export default class PageHeader extends PureComponent {
{
[linkElement === 'a' ? 'href' : 'to']: '/',
},
'首页',
'首页'
)}
</Breadcrumb.Item>,
</Breadcrumb.Item>
);
return (
<Breadcrumb className={styles.breadcrumb} separator={breadcrumbSeparator}>
@ -108,12 +102,7 @@ export default class PageHeader extends PureComponent {
*/
conversionBreadcrumbList = () => {
const { breadcrumbList, breadcrumbSeparator } = this.props;
const {
routes,
params,
routerLocation,
breadcrumbNameMap,
} = this.getBreadcrumbProps();
const { routes, params, routerLocation, breadcrumbNameMap } = this.getBreadcrumbProps();
if (breadcrumbList && breadcrumbList.length) {
return this.conversionFromProps();
}
@ -151,7 +140,7 @@ export default class PageHeader extends PureComponent {
href: paths.join('/') || '/',
to: paths.join('/') || '/',
},
route.breadcrumbName,
route.breadcrumbName
)
);
};
@ -191,9 +180,7 @@ export default class PageHeader extends PureComponent {
</div>
<div className={styles.row}>
{content && <div className={styles.content}>{content}</div>}
{extraContent && (
<div className={styles.extraContent}>{extraContent}</div>
)}
{extraContent && <div className={styles.extraContent}>{extraContent}</div>}
</div>
</div>
</div>

24
src/components/PageHeader/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.pageHeader {
background: @component-background;
@ -61,19 +61,27 @@
}
}
.title, .action, .content, .extraContent, .main {
.title,
.action,
.content,
.extraContent,
.main {
flex: auto;
}
.title, .action {
.title,
.action {
margin-bottom: 16px;
}
.logo, .content, .extraContent {
.logo,
.content,
.extraContent {
margin-bottom: 16px;
}
.action, .extraContent {
.action,
.extraContent {
text-align: right;
}
@ -105,7 +113,8 @@
display: block;
}
.action, .extraContent {
.action,
.extraContent {
margin-left: 0;
text-align: left;
}
@ -124,7 +133,8 @@
.pageHeader {
.action {
:global {
.ant-btn-group, .ant-btn {
.ant-btn-group,
.ant-btn {
display: block;
margin-bottom: 8px;
}

20
src/components/PageHeader/index.test.js

@ -1,5 +1,5 @@
import { getBreadcrumb } from './index';
import { urlToList } from '../utils/pathTools';
import { urlToList } from '../_utils/pathTools';
const routerData = {
'/dashboard/analysis': {
@ -17,35 +17,29 @@ const routerData = {
};
describe('test getBreadcrumb', () => {
it('Simple url', () => {
expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual(
'分析页',
);
expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual('分析页');
});
it('Parameters url', () => {
expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual(
'用户信息',
);
expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual('用户信息');
});
it('The middle parameter url', () => {
expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual(
'收货订单',
);
expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual('收货订单');
});
it('Loop through the parameters', () => {
const urlNameList = urlToList('/userinfo/2144/addr').map((url) => {
const urlNameList = urlToList('/userinfo/2144/addr').map(url => {
return getBreadcrumb(routerData, url).name;
});
expect(urlNameList).toEqual(['用户列表', '用户信息', '收货订单']);
});
it('a path', () => {
const urlNameList = urlToList('/userinfo').map((url) => {
const urlNameList = urlToList('/userinfo').map(url => {
return getBreadcrumb(routerData, url).name;
});
expect(urlNameList).toEqual(['用户列表']);
});
it('Secondary path', () => {
const urlNameList = urlToList('/userinfo/2144').map((url) => {
const urlNameList = urlToList('/userinfo/2144').map(url => {
return getBreadcrumb(routerData, url).name;
});
expect(urlNameList).toEqual(['用户列表', '用户信息']);

8
src/components/Result/index.js

@ -4,7 +4,13 @@ import { Icon } from 'antd';
import styles from './index.less';
export default function Result({
className, type, title, description, extra, actions, ...restProps
className,
type,
title,
description,
extra,
actions,
...restProps
}) {
const iconMap = {
error: <Icon className={styles.error} type="close-circle" />,

2
src/components/Result/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.result {
text-align: center;

26
src/components/SiderMenu/BaseMeun.js

@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import { Menu, Icon } from 'antd';
import { Link } from 'dva/router';
import pathToRegexp from 'path-to-regexp';
import { urlToList } from '../utils/pathTools';
import { urlToList } from '../_utils/pathTools';
import styles from './index.less';
const { SubMenu } = Menu;
@ -11,7 +11,7 @@ const { SubMenu } = Menu;
// icon: 'setting',
// icon: 'http://demo.com/icon.png',
// icon: <Icon type="setting" />,
const getIcon = (icon) => {
const getIcon = icon => {
if (typeof icon === 'string' && icon.indexOf('http') === 0) {
return <img src={icon} alt="icon" className={styles.icon} />;
}
@ -22,7 +22,7 @@ const getIcon = (icon) => {
};
export const getMeunMatcheys = (flatMenuKeys, path) => {
return flatMenuKeys.filter((item) => {
return flatMenuKeys.filter(item => {
return pathToRegexp(item).test(path);
});
};
@ -40,7 +40,7 @@ export default class BaseMeun extends PureComponent {
*/
getFlatMenuKeys(menus) {
let keys = [];
menus.forEach((item) => {
menus.forEach(item => {
if (item.children) {
keys = keys.concat(this.getFlatMenuKeys(item.children));
}
@ -52,13 +52,13 @@ export default class BaseMeun extends PureComponent {
* 获得菜单子节点
* @memberof SiderMenu
*/
getNavMenuItems = (menusData) => {
getNavMenuItems = menusData => {
if (!menusData) {
return [];
}
return menusData
.filter(item => item.name && !item.hideInMenu)
.map((item) => {
.map(item => {
// make dom
const ItemDom = this.getSubMenuOrItem(item);
return this.checkPermissionItem(item.authority, ItemDom);
@ -68,14 +68,12 @@ export default class BaseMeun extends PureComponent {
// Get the currently selected menu
getSelectedMenuKeys = () => {
const { location: { pathname } } = this.props;
return urlToList(pathname).map(itemPath =>
getMeunMatcheys(this.flatMenuKeys, itemPath).pop(),
);
return urlToList(pathname).map(itemPath => getMeunMatcheys(this.flatMenuKeys, itemPath).pop());
};
/**
* get SubMenu or Item
*/
getSubMenuOrItem = (item) => {
getSubMenuOrItem = item => {
if (item.children && item.children.some(child => child.name)) {
return (
<SubMenu
@ -95,9 +93,7 @@ export default class BaseMeun extends PureComponent {
</SubMenu>
);
} else {
return (
<Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>
);
return <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>;
}
};
/**
@ -105,7 +101,7 @@ export default class BaseMeun extends PureComponent {
* Judge whether it is http link.return a or Link
* @memberof SiderMenu
*/
getMenuItemPath = (item) => {
getMenuItemPath = item => {
const itemPath = this.conversionPath(item.path);
const icon = getIcon(item.icon);
const { target, name } = item;
@ -144,7 +140,7 @@ export default class BaseMeun extends PureComponent {
}
return ItemDom;
};
conversionPath = (path) => {
conversionPath = path => {
if (path && path.indexOf('http') === 0) {
return path;
} else {

32
src/components/SiderMenu/SiderMenu.js

@ -3,7 +3,7 @@ import { Layout, Menu, Icon } from 'antd';
import { Link } from 'dva/router';
import styles from './index.less';
import BaseMeun, { getMeunMatcheys } from './BaseMeun';
import { urlToList } from '../utils/pathTools';
import { urlToList } from '../_utils/pathTools';
const { Sider } = Layout;
const { SubMenu } = Menu;
@ -12,7 +12,7 @@ const { SubMenu } = Menu;
// icon: 'setting',
// icon: 'http://demo.com/icon.png',
// icon: <Icon type="setting" />,
const getIcon = (icon) => {
const getIcon = icon => {
if (typeof icon === 'string' && icon.indexOf('http') === 0) {
return <img src={icon} alt="icon" className={`${styles.icon} sider-menu-item-img`} />;
}
@ -22,7 +22,6 @@ const getIcon = (icon) => {
return icon;
};
export default class SiderMenu extends PureComponent {
constructor(props) {
super(props);
@ -46,7 +45,7 @@ export default class SiderMenu extends PureComponent {
*/
getFlatMenuKeys(menus) {
let keys = [];
menus.forEach((item) => {
menus.forEach(item => {
if (item.children) {
keys = keys.concat(this.getFlatMenuKeys(item.children));
}
@ -62,7 +61,7 @@ export default class SiderMenu extends PureComponent {
* Judge whether it is http link.return a or Link
* @memberof SiderMenu
*/
getMenuItemPath = (item) => {
getMenuItemPath = item => {
const itemPath = this.conversionPath(item.path);
const icon = getIcon(item.icon);
const { target, name } = item;
@ -96,7 +95,7 @@ export default class SiderMenu extends PureComponent {
/**
* get SubMenu or Item
*/
getSubMenuOrItem = (item) => {
getSubMenuOrItem = item => {
if (item.children && item.children.some(child => child.name)) {
const childrenItems = this.getNavMenuItems(item.children);
// 当无子菜单时就不展示菜单
@ -110,8 +109,8 @@ export default class SiderMenu extends PureComponent {
<span>{item.name}</span>
</span>
) : (
item.name
)
item.name
)
}
key={item.path}
>
@ -121,9 +120,7 @@ export default class SiderMenu extends PureComponent {
}
return null;
} else {
return (
<Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>
);
return <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>;
}
};
/**
@ -133,18 +130,15 @@ export default class SiderMenu extends PureComponent {
getDefaultCollapsedSubMenus(props) {
const { location: { pathname } } = props || this.props;
return urlToList(pathname)
.map((item) => {
.map(item => {
return getMeunMatcheys(this.flatMenuKeys, item)[0];
})
.filter(item => item);
}
isMainMenu = (key) => {
return this.menus.some(
item =>
key && (item.key === key || item.path === key),
);
}
handleOpenChange = (openKeys) => {
isMainMenu = key => {
return this.menus.some(item => key && (item.key === key || item.path === key));
};
handleOpenChange = openKeys => {
const lastOpenKey = openKeys[openKeys.length - 1];
const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
this.setState({

20
src/components/SiderMenu/SilderMenu.test.js

@ -1,12 +1,6 @@
import { getMeunMatcheys } from './BaseMeun';
const meun = [
'/dashboard',
'/userinfo',
'/dashboard/name',
'/userinfo/:id',
'/userinfo/:id/info',
];
const meun = ['/dashboard', '/userinfo', '/dashboard/name', '/userinfo/:id', '/userinfo/:id/info'];
describe('test meun match', () => {
it('simple path', () => {
@ -17,20 +11,14 @@ describe('test meun match', () => {
});
it('Secondary path', () => {
expect(getMeunMatcheys(meun, '/dashboard/name')).toEqual([
'/dashboard/name',
]);
expect(getMeunMatcheys(meun, '/dashboard/name')).toEqual(['/dashboard/name']);
});
it('Parameter path', () => {
expect(getMeunMatcheys(meun, '/userinfo/2144')).toEqual([
'/userinfo/:id',
]);
expect(getMeunMatcheys(meun, '/userinfo/2144')).toEqual(['/userinfo/:id']);
});
it('three parameter path', () => {
expect(getMeunMatcheys(meun, '/userinfo/2144/info')).toEqual([
'/userinfo/:id/info',
]);
expect(getMeunMatcheys(meun, '/userinfo/2144/info')).toEqual(['/userinfo/:id/info']);
});
});

11
src/components/SiderMenu/index.js

@ -3,17 +3,20 @@ import React from 'react';
import DrawerMenu from 'rc-drawer-menu';
import SiderMenu from './SiderMenu';
export default props => (
export default props =>
props.isMobile || props.fixSiderbar ? (
<DrawerMenu
parent={null}
level={null}
iconChild={null}
open={!props.collapsed}
onMaskClick={() => { props.onCollapse(true); }}
onMaskClick={() => {
props.onCollapse(true);
}}
width="256px"
>
<SiderMenu {...props} collapsed={props.isMobile ? false : props.collapsed} />
</DrawerMenu>
) : <SiderMenu {...props} />
);
) : (
<SiderMenu {...props} />
);

9
src/components/SiderMenu/index.less

@ -51,7 +51,12 @@
}
.ant-menu-inline-collapsed {
& > .ant-menu-item .sider-menu-item-img + span,
& > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item .sider-menu-item-img + span,
&
> .ant-menu-item-group
> .ant-menu-item-group-list
> .ant-menu-item
.sider-menu-item-img
+ span,
& > .ant-menu-submenu > .ant-menu-submenu-title .sider-menu-item-img + span {
max-width: 0;
display: inline-block;
@ -60,7 +65,7 @@
}
.ant-menu-item .sider-menu-item-img + span,
.ant-menu-submenu-title .sider-menu-item-img + span {
transition: opacity .3s @ease-in-out, width .3s @ease-in-out;
transition: opacity 0.3s @ease-in-out, width 0.3s @ease-in-out;
opacity: 1;
}
}

16
src/components/StandardFormRow/index.js

@ -11,16 +11,12 @@ export default ({ title, children, last, block, grid, ...rest }) => {
return (
<div className={cls} {...rest}>
{
title && (
<div className={styles.label}>
<span>{title}</span>
</div>
)
}
<div className={styles.content}>
{children}
</div>
{title && (
<div className={styles.label}>
<span>{title}</span>
</div>
)}
<div className={styles.content}>{children}</div>
</div>
);
};

2
src/components/StandardFormRow/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.standardFormRow {
border-bottom: 1px dashed @border-color-split;

34
src/components/StandardTable/index.js

@ -4,7 +4,7 @@ import styles from './index.less';
function initTotalList(columns) {
const totalList = [];
columns.forEach((column) => {
columns.forEach(column => {
if (column.needTotal) {
totalList.push({ ...column, total: 0 });
}
@ -37,7 +37,7 @@ class StandardTable extends PureComponent {
handleRowSelectChange = (selectedRowKeys, selectedRows) => {
let needTotalList = [...this.state.needTotalList];
needTotalList = needTotalList.map((item) => {
needTotalList = needTotalList.map(item => {
return {
...item,
total: selectedRows.reduce((sum, val) => {
@ -51,15 +51,15 @@ class StandardTable extends PureComponent {
}
this.setState({ selectedRowKeys, needTotalList });
}
};
handleTableChange = (pagination, filters, sorter) => {
this.props.onChange(pagination, filters, sorter);
}
};
cleanSelectedKeys = () => {
this.handleRowSelectChange([], []);
}
};
render() {
const { selectedRowKeys, needTotalList } = this.state;
@ -83,22 +83,22 @@ class StandardTable extends PureComponent {
<div className={styles.standardTable}>
<div className={styles.tableAlert}>
<Alert
message={(
message={
<Fragment>
已选择 <a style={{ fontWeight: 600 }}>{selectedRowKeys.length}</a> &nbsp;&nbsp;
{
needTotalList.map(item => (
<span style={{ marginLeft: 8 }} key={item.dataIndex}>{item.title}总计&nbsp;
<span style={{ fontWeight: 600 }}>
{item.render ? item.render(item.total) : item.total}
</span>
{needTotalList.map(item => (
<span style={{ marginLeft: 8 }} key={item.dataIndex}>
{item.title}总计&nbsp;
<span style={{ fontWeight: 600 }}>
{item.render ? item.render(item.total) : item.total}
</span>
)
)
}
<a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>清空</a>
</span>
))}
<a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>
清空
</a>
</Fragment>
)}
}
type="info"
showIcon
/>

2
src/components/StandardTable/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.standardTable {
:global {

5
src/components/TagSelect/TagSelectOption.d.ts

@ -5,7 +5,4 @@ export interface ITagSelectOptionProps {
style?: React.CSSProperties;
}
export default class TagSelectOption extends React.Component<
ITagSelectOptionProps,
any
> {}
export default class TagSelectOption extends React.Component<ITagSelectOptionProps, any> {}

53
src/components/TagSelect/index.js

@ -7,11 +7,7 @@ import styles from './index.less';
const { CheckableTag } = Tag;
const TagSelectOption = ({ children, checked, onChange, value }) => (
<CheckableTag
checked={checked}
key={value}
onChange={state => onChange(value, state)}
>
<CheckableTag checked={checked} key={value} onChange={state => onChange(value, state)}>
{children}
</CheckableTag>
);
@ -29,7 +25,7 @@ class TagSelect extends Component {
}
}
onChange = (value) => {
onChange = value => {
const { onChange } = this.props;
if (!('value' in this.props)) {
this.setState({ value });
@ -37,15 +33,15 @@ class TagSelect extends Component {
if (onChange) {
onChange(value);
}
}
};
onSelectAll = (checked) => {
onSelectAll = checked => {
let checkedTags = [];
if (checked) {
checkedTags = this.getAllTags();
}
this.onChange(checkedTags);
}
};
getAllTags() {
let { children } = this.props;
@ -66,19 +62,21 @@ class TagSelect extends Component {
checkedTags.splice(index, 1);
}
this.onChange(checkedTags);
}
};
handleExpand = () => {
this.setState({
expand: !this.state.expand,
});
}
};
isTagSelectOption = (node) => {
return node && node.type && (
node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption'
isTagSelectOption = node => {
return (
node &&
node.type &&
(node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption')
);
}
};
render() {
const { value, expand } = this.state;
@ -92,15 +90,11 @@ class TagSelect extends Component {
});
return (
<div className={cls} style={style}>
<CheckableTag
checked={checkedAll}
key="tag-select-__all__"
onChange={this.onSelectAll}
>
<CheckableTag checked={checkedAll} key="tag-select-__all__" onChange={this.onSelectAll}>
全部
</CheckableTag>
{
value && React.Children.map(children, (child) => {
{value &&
React.Children.map(children, child => {
if (this.isTagSelectOption(child)) {
return React.cloneElement(child, {
key: `tag-select-${child.props.value}`,
@ -110,15 +104,12 @@ class TagSelect extends Component {
});
}
return child;
})
}
{
expandable && (
<a className={styles.trigger} onClick={this.handleExpand}>
{expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
</a>
)
}
})}
{expandable && (
<a className={styles.trigger} onClick={this.handleExpand}>
{expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
</a>
)}
</div>
);
}

6
src/components/TagSelect/index.less

@ -1,4 +1,4 @@
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.tagSelect {
user-select: none;
@ -7,7 +7,7 @@
overflow: hidden;
max-height: 32px;
line-height: 32px;
transition: all .3s;
transition: all 0.3s;
:global {
.ant-tag {
padding: 0 8px;
@ -16,7 +16,7 @@
}
}
&.expanded {
transition: all .3s;
transition: all 0.3s;
max-height: 200px;
}
.trigger {

22
src/components/Trend/index.js

@ -4,17 +4,21 @@ import classNames from 'classnames';
import styles from './index.less';
const Trend = ({ colorful = true, flag, children, className, ...rest }) => {
const classString = classNames(styles.trendItem, {
[styles.trendItemGrey]: !colorful,
}, className);
const classString = classNames(
styles.trendItem,
{
[styles.trendItemGrey]: !colorful,
},
className
);
return (
<div
{...rest}
className={classString}
title={typeof children === 'string' ? children : ''}
>
<div {...rest} className={classString} title={typeof children === 'string' ? children : ''}>
<span className={styles.value}>{children}</span>
{flag && <span className={styles[flag]}><Icon type={`caret-${flag}`} /></span>}
{flag && (
<span className={styles[flag]}>
<Icon type={`caret-${flag}`} />
</span>
)}
</div>
);
};

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save