Commit 645f7daf authored by jim's avatar jim Committed by 陈帅

support perttier

parent 08456b98
{
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": ["compat"],
"extends": ["airbnb", "prettier"],
"env": {
"browser": true,
"node": true,
......@@ -20,7 +19,9 @@
"react/jsx-no-bind": [0],
"react/prop-types": [0],
"react/prefer-stateless-function": [0],
"react/jsx-wrap-multilines": ["error", {
"react/jsx-wrap-multilines": [
"error",
{
"declaration": "parens-new-line",
"assignment": "parens-new-line",
"return": "parens-new-line",
......@@ -28,7 +29,8 @@
"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", {
"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": {
......
......@@ -20,4 +20,3 @@ yarn.lock
package-lock.json
*bak
jsconfig.json
.prettierrc
**/*.md
**/*.svg
\ No newline at end of file
{
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}
......@@ -14,7 +14,7 @@ const noProxy = process.env.NO_PROXY === 'true';
const proxy = {
// 支持值为 Object 和 Array
'GET /api/currentUser': {
$desc: "获取当前用户接口",
$desc: '获取当前用户接口',
$params: {
pageSize: {
desc: '分页',
......@@ -29,22 +29,26 @@ const proxy = {
},
},
// GET POST 可省略
'GET /api/users': [{
'GET /api/users': [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
}, {
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
}, {
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
}],
},
],
'GET /api/project/notice': getNotice,
'GET /api/activities': getActivities,
'GET /api/rule': getRule,
......@@ -61,7 +65,7 @@ const proxy = {
res.send({ message: 'Ok' });
},
'GET /api/tags': mockjs.mock({
'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }]
'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }],
}),
'GET /api/fake_list': getFakeList,
'GET /api/fake_chart_data': getFakeChartData,
......@@ -69,26 +73,26 @@ const proxy = {
'GET /api/profile/advanced': getProfileAdvancedData,
'POST /api/login/account': (req, res) => {
const { password, userName, type } = req.body;
if(password === '888888' && userName === 'admin'){
if (password === '888888' && userName === 'admin') {
res.send({
status: 'ok',
type,
currentAuthority: 'admin'
currentAuthority: 'admin',
});
return ;
return;
}
if(password === '123456' && userName === 'user'){
if (password === '123456' && userName === 'user') {
res.send({
status: 'ok',
type,
currentAuthority: 'user'
currentAuthority: 'user',
});
return ;
return;
}
res.send({
status: 'error',
type,
currentAuthority: 'guest'
currentAuthority: 'guest',
});
},
'POST /api/register': (req, res) => {
......@@ -97,40 +101,40 @@ const proxy = {
'GET /api/notices': getNotices,
'GET /api/500': (req, res) => {
res.status(500).send({
"timestamp": 1513932555104,
"status": 500,
"error": "error",
"message": "error",
"path": "/base/category/list"
timestamp: 1513932555104,
status: 500,
error: 'error',
message: 'error',
path: '/base/category/list',
});
},
'GET /api/404': (req, res) => {
res.status(404).send({
"timestamp": 1513932643431,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/base/category/list/2121212"
timestamp: 1513932643431,
status: 404,
error: 'Not Found',
message: 'No message available',
path: '/base/category/list/2121212',
});
},
'GET /api/403': (req, res) => {
res.status(403).send({
"timestamp": 1513932555104,
"status": 403,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/base/category/list"
timestamp: 1513932555104,
status: 403,
error: 'Unauthorized',
message: 'Unauthorized',
path: '/base/category/list',
});
},
'GET /api/401': (req, res) => {
res.status(401).send({
"timestamp": 1513932555104,
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/base/category/list"
timestamp: 1513932555104,
status: 401,
error: 'Unauthorized',
message: 'Unauthorized',
path: '/base/category/list',
});
},
};
export default noProxy ? {} : delay(proxy, 1000);
export default (noProxy ? {} : delay(proxy, 1000));
{
"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,
......
{
"editor.formatOnSave": true
}
......@@ -12,7 +12,7 @@ export default {
},
},
alias: {
'components': path.resolve(__dirname, 'src/components/'),
components: path.resolve(__dirname, 'src/components/'),
},
ignoreMomentLocale: true,
theme: './src/theme.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',
......@@ -112,7 +114,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);
......@@ -287,7 +289,6 @@ export const getActivities = [
},
];
export default {
getNotice,
getActivities,
......
......@@ -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,
......
......@@ -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],
no: `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],
no: `TradeCode ${i}`,
title: `一个任务名称 ${i}`,
owner: '曲丽丽',
......
......@@ -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"]
}
import { isUrl } from '../utils/utils';
const menuData = [{
const menuData = [
{
name: 'dashboard',
icon: 'dashboard',
path: 'dashboard',
children: [{
children: [
{
name: '分析页',
path: 'analysis',
}, {
},
{
name: '监控页',
path: 'monitor',
}, {
},
{
name: '工作台',
path: 'workplace',
// hideInBreadcrumb: true,
// hideInMenu: true,
}],
}, {
},
],
},
{
name: '表单页',
icon: 'form',
path: 'form',
children: [{
children: [
{
name: '基础表单',
path: 'basic-form',
}, {
},
{
name: '分步表单',
path: 'step-form',
}, {
},
{
name: '高级表单',
authority: 'admin',
path: 'advanced-form',
}],
}, {
},
],
},
{
name: '列表页',
icon: 'table',
path: 'list',
children: [{
children: [
{
name: '查询表格',
path: 'table-list',
}, {
},
{
name: '标准列表',
path: 'basic-list',
}, {
},
{
name: '卡片列表',
path: 'card-list',
}, {
},
{
name: '搜索列表',
path: 'search',
children: [{
children: [
{
name: '搜索列表(文章)',
path: 'articles',
}, {
},
{
name: '搜索列表(项目)',
path: 'projects',
}, {
},
{
name: '搜索列表(应用)',
path: 'applications',
}],
}],
}, {
},
],
},
],
},
{
name: '详情页',
icon: 'profile',
path: 'profile',
children: [{
children: [
{
name: '基础详情页',
path: 'basic',
}, {
},
{
name: '高级详情页',
path: 'advanced',
authority: 'admin',
}],
}, {
},
],
},
{
name: '结果页',
icon: 'check-circle-o',
path: 'result',
children: [{
children: [
{
name: '成功',
path: 'success',
}, {
},
{
name: '失败',
path: 'fail',
}],
}, {
},
],
},
{
name: '异常页',
icon: 'warning',
path: 'exception',
children: [{
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: [{
children: [
{
name: '登录',
path: 'login',
}, {
},
{
name: '注册',
path: 'register',
}, {
},
{
name: '注册结果',
path: 'register-result',
}],
}];
},
],
},
];
function formatter(data, parentPath = '/', parentAuthority) {
return data.map((item) => {
return data.map(item => {
let { path } = item;
if (!isUrl(path)) {
path = parentPath + item.path;
......
......@@ -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,17 +35,17 @@ 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, {
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,7 +67,7 @@ function getFlatMenuData(menus) {
return keys;
}
export const getRouterData = (app) => {
export const getRouterData = app => {
const routerConfig = {
'/': {
component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
......@@ -80,7 +79,9 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},
'/dashboard/workplace': {
component: dynamicWrapper(app, ['project', 'activities', 'chart'], () => import('../routes/Dashboard/Workplace')),
component: dynamicWrapper(app, ['project', 'activities', 'chart'], () =>
import('../routes/Dashboard/Workplace')
),
// hideInBreadcrumb: true,
// name: '工作台',
// authority: 'admin',
......@@ -131,7 +132,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 +152,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')),
......@@ -174,7 +179,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);
......
......@@ -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;
......
......@@ -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>
);
}
......
......@@ -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');
......
......@@ -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;
}
......
......@@ -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,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;
}
......
......@@ -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,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,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 ? (
<li className={cls} onClick={onClick}>
{tips ? (
<Tooltip title={tips}>
<Avatar src={src} size={size} style={{ cursor: 'pointer' }} />
</Tooltip>
) : <Avatar src={src} size={size} />
}
) : (
<Avatar src={src} size={size} />
)}
</li>
);
};
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.avatarList {
display: inline-block;
......
import * as React from "react";
import * as React from 'react';
export interface IBarProps {
title: React.ReactNode;
color?: string;
......
......@@ -46,11 +46,11 @@ class Bar extends Component {
}
}
handleRoot = (n) => {
handleRoot = n => {
this.root = n;
};
handleRef = (n) => {
handleRef = n => {
this.node = n;
};
......
import * as React from "react";
import * as React from 'react';
export interface IChartCardProps {
title: React.ReactNode;
action?: React.ReactNode;
......
......@@ -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>
)}
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.chartCard {
position: relative;
......
import * as React from "react";
import * as React from 'react';
export interface IFieldProps {
label: React.ReactNode;
value: React.ReactNode;
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.field {
white-space: nowrap;
......
import * as React from "react";
import * as React from 'react';
export interface IGaugeProps {
title: React.ReactNode;
color?: string;
......
......@@ -4,7 +4,7 @@ import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide;
const defaultFormatter = (val) => {
const defaultFormatter = val => {
switch (val) {
case '2':
return '';
......
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> {}
......@@ -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>
......
@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;
......
......@@ -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" />
......
@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;
......
import * as React from "react";
import * as React from 'react';
export interface IRadarProps {
title?: React.ReactNode;
height: number;
......
......@@ -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"
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.radar {
.legend {
......
import * as React from "react";
import * as React from 'react';
export interface ITagCloudProps {
data: Array<{
name: string;
......
......@@ -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;
......
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> {}
......@@ -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;
},
......
@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;
}
}
......@@ -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;
};
......
import * as React from "react";
import * as React from 'react';
export interface ICountDownProps {
format?: (time: number) => void;
target: Date | number;
......
......@@ -23,11 +23,14 @@ class CountDown extends Component {
if (this.props.target !== nextProps.target) {
clearTimeout(this.timer);
const { lastTime } = this.initTime(nextProps);
this.setState({
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({
this.setState(
{
lastTime: 0,
}, () => {
},
() => {
if (onEnd) {
onEnd();
}
});
}
);
} else {
lastTime -= this.interval;
this.setState({
this.setState(
{
lastTime,
}, () => {
},
() => {
this.tick();
});
}
}, this.interval);
);
}
}, 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>;
}
}
......
......@@ -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',
......
......@@ -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;
}
@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;
}
}
......
......@@ -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 ? (
{editable ? (
<div className={styles.wrapper}>
<Input
value={value}
onChange={this.handleChange}
onPressEnter={this.check}
/>
<Icon
type="check"
className={styles.icon}
onClick={this.check}
/>
<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}
/>
<Icon type="edit" className={styles.icon} onClick={this.edit} />
</div>
)
}
)}
</div>
);
}
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.editableItem {
line-height: @input-height-base;
......
......@@ -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">
添加
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.linkGroup {
padding: 20px 0 8px 24px;
......
......@@ -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;
};
......
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;
......
......@@ -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>
......
@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 {
......
......@@ -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> {}
......@@ -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>
......
@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;
}
......
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> {}
......@@ -6,21 +6,15 @@ export default ({ className, links, copyright }) => {
const clsString = classNames(styles.globalFooter, className);
return (
<div className={clsString}>
{
links && (
{links && (
<div className={styles.links}>
{links.map(link => (
<a
key={link.key}
target={link.blankTarget ? '_blank' : '_self'}
href={link.href}
>
<a key={link.key} target={link.blankTarget ? '_blank' : '_self'} href={link.href}>
{link.title}
</a>
))}
</div>
)
}
)}
{copyright && <div className={styles.copyright}>{copyright}</div>}
</div>
);
......
@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;
......
......@@ -17,7 +17,7 @@ export default class GlobalHeader extends PureComponent {
if (notices.length === 0) {
return {};
}
const newNotices = notices.map((notice) => {
const newNotices = notices.map(notice => {
const newNotice = { ...notice };
if (newNotice.datetime) {
newNotice.datetime = moment(notice.datetime).fromNow();
......@@ -27,13 +27,17 @@ export default class GlobalHeader extends PureComponent {
newNotice.key = newNotice.id;
}
if (newNotice.extra && newNotice.status) {
const color = ({
const color = {
todo: '',
processing: 'blue',
urgent: 'red',
doing: 'gold',
})[newNotice.status];
newNotice.extra = <Tag color={color} style={{ marginRight: 0 }}>{newNotice.extra}</Tag>;
}[newNotice.status];
newNotice.extra = (
<Tag color={color} style={{ marginRight: 0 }}>
{newNotice.extra}
</Tag>
);
}
return newNotice;
});
......@@ -43,40 +47,50 @@ export default class GlobalHeader extends PureComponent {
const { collapsed, onCollapse } = this.props;
onCollapse(!collapsed);
this.triggerResizeEvent();
}
};
@Debounce(600)
triggerResizeEvent() { // eslint-disable-line
triggerResizeEvent = () => {
const event = document.createEvent('HTMLEvents');
event.initEvent('resize', true, false);
window.dispatchEvent(event);
}
};
render() {
const {
currentUser, collapsed, fetchingNotices, isMobile, logo,
onNoticeVisibleChange, onMenuClick, onNoticeClear,
currentUser,
collapsed,
fetchingNotices,
isMobile,
logo,
onNoticeVisibleChange,
onMenuClick,
onNoticeClear,
} = this.props;
const menu = (
<Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
<Menu.Item disabled><Icon type="user" />个人中心</Menu.Item>
<Menu.Item disabled><Icon type="setting" />设置</Menu.Item>
<Menu.Item key="triggerError"><Icon type="close-circle" />触发报错</Menu.Item>
<Menu.Item disabled>
<Icon type="user" />个人中心
</Menu.Item>
<Menu.Item disabled>
<Icon type="setting" />设置
</Menu.Item>
<Menu.Item key="triggerError">
<Icon type="close-circle" />触发报错
</Menu.Item>
<Menu.Divider />
<Menu.Item key="logout"><Icon type="logout" />退出登录</Menu.Item>
<Menu.Item key="logout">
<Icon type="logout" />退出登录
</Menu.Item>
</Menu>
);
const noticeData = this.getNoticeData();
return (
<div className={styles.header}>
{isMobile && (
[
(
{isMobile && [
<Link to="/" className={styles.logo} key="logo">
<img src={logo} alt="logo" width="32" />
</Link>
),
</Link>,
<Divider type="vertical" key="line" />,
]
)}
]}
<Icon
className={styles.trigger}
type={collapsed ? 'menu-unfold' : 'menu-fold'}
......@@ -87,10 +101,10 @@ export default class GlobalHeader extends PureComponent {
className={`${styles.action} ${styles.search}`}
placeholder="站内搜索"
dataSource={['搜索提示一', '搜索提示二', '搜索提示三']}
onSearch={(value) => {
onSearch={value => {
console.log('input', value); // eslint-disable-line
}}
onPressEnter={(value) => {
onPressEnter={value => {
console.log('enter', value); // eslint-disable-line
}}
/>
......@@ -102,7 +116,7 @@ export default class GlobalHeader extends PureComponent {
className={styles.action}
>
<Icon type="question-circle-o" />
</a >
</a>
</Tooltip>
<NoticeIcon
className={styles.action}
......@@ -141,7 +155,9 @@ export default class GlobalHeader extends PureComponent {
<span className={styles.name}>{currentUser.name}</span>
</span>
</Dropdown>
) : <Spin size="small" style={{ marginLeft: 8 }} />}
) : (
<Spin size="small" style={{ marginLeft: 8 }} />
)}
</div>
</div>
);
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.header {
height: 64px;
padding: 0 12px 0 0;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
position: relative;
}
......@@ -42,7 +42,7 @@ i.trigger {
font-size: 20px;
line-height: 64px;
cursor: pointer;
transition: all .3s, padding 0s;
transition: all 0.3s, padding 0s;
padding: 0 24px;
&:hover {
background: @primary-1;
......@@ -56,7 +56,7 @@ i.trigger {
cursor: pointer;
padding: 0 12px;
display: inline-block;
transition: all .3s;
transition: all 0.3s;
height: 100%;
> i {
font-size: 16px;
......@@ -79,7 +79,7 @@ i.trigger {
.avatar {
margin: 20px 8px 20px 0;
color: @primary-color;
background: rgba(255, 255, 255, .85);
background: rgba(255, 255, 255, 0.85);
vertical-align: middle;
}
}
......
......@@ -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> {}
......@@ -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}
/>
......
@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;
......
......@@ -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,
......
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;
......
......@@ -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.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,8 +92,7 @@ class Login extends Component {
return (
<div className={classNames(className, styles.login)}>
<Form onSubmit={this.handleSubmit}>
{
tabs.length ? (
{tabs.length ? (
<div>
<Tabs
animated={false}
......@@ -107,8 +104,9 @@ class Login extends Component {
</Tabs>
{otherChildren}
</div>
) : [...children]
}
) : (
[...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];
});
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.login {
.tabs {
padding: 0 2px;
margin: 0 -2px;
......
......@@ -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!',
},
],
},
};
......
......@@ -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> {}
......@@ -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>
);
......
@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 {
......
......@@ -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
......
@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 {
......
......@@ -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> {}
......@@ -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, {
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) && (
{(status || subTotal) && (
<span className={styles.subTotal}>
{subTotal}
{status && <Icon type={`caret-${status}`} />}
</span>
)
}
)}
</div>
</div>
);
@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;
......
......@@ -10,7 +10,7 @@ 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>
......
@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;
}
......
......@@ -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(['用户列表', '用户信息']);
......
......@@ -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" />,
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.result {
text-align: center;
......
......@@ -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`} />;
}
......@@ -23,7 +23,7 @@ const getIcon = (icon) => {
};
export const getMeunMatcheys = (flatMenuKeys, path) => {
return flatMenuKeys.filter((item) => {
return flatMenuKeys.filter(item => {
return pathToRegexp(item).test(path);
});
};
......@@ -52,7 +52,7 @@ 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);
......@@ -64,7 +64,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));
}
......@@ -77,7 +77,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;
......@@ -111,7 +111,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);
// 当无子菜单时就不展示菜单
......@@ -136,22 +136,20 @@ 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>;
}
};
/**
* 获得菜单子节点
* @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);
......@@ -161,13 +159,11 @@ export default class SiderMenu 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());
};
// conversion Path
// 转化路径
conversionPath = (path) => {
conversionPath = path => {
if (path && path.indexOf('http') === 0) {
return path;
} else {
......@@ -182,13 +178,10 @@ export default class SiderMenu extends PureComponent {
}
return ItemDom;
};
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({
......
import { getMeunMatcheys } from './SiderMenu';
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']);
});
});
......@@ -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 ? (
<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} />
);
......@@ -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;
}
}
......@@ -11,16 +11,12 @@ export default ({ title, children, last, block, grid, ...rest }) => {
return (
<div className={cls} {...rest}>
{
title && (
{title && (
<div className={styles.label}>
<span>{title}</span>
</div>
)
}
<div className={styles.content}>
{children}
</div>
)}
<div className={styles.content}>{children}</div>
</div>
);
};
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.standardFormRow {
border-bottom: 1px dashed @border-color-split;
......
......@@ -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;
{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>
</span>
)
)
}
<a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>清空</a>
))}
<a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>
清空
</a>
</Fragment>
)}
}
type="info"
showIcon
/>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.standardTable {
:global {
......
......@@ -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> {}
......@@ -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 && (
})}
{expandable && (
<a className={styles.trigger} onClick={this.handleExpand}>
{expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
</a>
)
}
)}
</div>
);
}
......
@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 {
......
......@@ -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, {
const classString = classNames(
styles.trendItem,
{
[styles.trendItemGrey]: !colorful,
}, className);
},
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>
);
};
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.trendItem {
display: inline-block;
......
......@@ -5,10 +5,7 @@ describe('test urlToList', () => {
expect(urlToList('/userinfo')).toEqual(['/userinfo']);
});
it('Secondary path', () => {
expect(urlToList('/userinfo/2144')).toEqual([
'/userinfo',
'/userinfo/2144',
]);
expect(urlToList('/userinfo/2144')).toEqual(['/userinfo', '/userinfo/2144']);
});
it('Three paths', () => {
expect(urlToList('/userinfo/2144/addr')).toEqual([
......
......@@ -23,14 +23,14 @@ const { AuthorizedRoute, check } = Authorized;
* 根据菜单取得重定向地址.
*/
const redirectData = [];
const getRedirect = (item) => {
const getRedirect = item => {
if (item && item.children) {
if (item.children[0] && item.children[0].path) {
redirectData.push({
from: `${item.path}`,
to: `${item.children[0].path}`,
});
item.children.forEach((children) => {
item.children.forEach(children => {
getRedirect(children);
});
}
......@@ -79,7 +79,7 @@ const query = {
};
let isMobile;
enquireScreen((b) => {
enquireScreen(b => {
isMobile = b;
});
......@@ -87,7 +87,7 @@ class BasicLayout extends React.PureComponent {
static childContextTypes = {
location: PropTypes.object,
breadcrumbNameMap: PropTypes.object,
}
};
state = {
isMobile,
};
......@@ -99,7 +99,7 @@ class BasicLayout extends React.PureComponent {
};
}
componentDidMount() {
enquireScreen((mobile) => {
enquireScreen(mobile => {
this.setState({
isMobile: mobile,
});
......@@ -130,25 +130,26 @@ class BasicLayout extends React.PureComponent {
} else {
const { routerData } = this.props;
// get the first authorized route path in routerData
const authorizedPath = Object.keys(routerData).find(item =>
check(routerData[item].authority, item) && item !== '/');
const authorizedPath = Object.keys(routerData).find(
item => check(routerData[item].authority, item) && item !== '/'
);
return authorizedPath;
}
return redirect;
}
handleMenuCollapse = (collapsed) => {
};
handleMenuCollapse = collapsed => {
this.props.dispatch({
type: 'global/changeLayoutCollapsed',
payload: collapsed,
});
}
handleNoticeClear = (type) => {
};
handleNoticeClear = type => {
message.success(`清空了${type}`);
this.props.dispatch({
type: 'global/clearNotices',
payload: type,
});
}
};
handleMenuClick = ({ key }) => {
if (key === 'triggerError') {
this.props.dispatch(routerRedux.push('/exception/trigger'));
......@@ -159,17 +160,23 @@ class BasicLayout extends React.PureComponent {
type: 'login/logout',
});
}
}
handleNoticeVisibleChange = (visible) => {
};
handleNoticeVisibleChange = visible => {
if (visible) {
this.props.dispatch({
type: 'global/fetchNotices',
});
}
}
};
render() {
const {
currentUser, collapsed, fetchingNotices, notices, routerData, match, location,
currentUser,
collapsed,
fetchingNotices,
notices,
routerData,
match,
location,
} = this.props;
const bashRedirect = this.getBashRedirect();
const layout = (
......@@ -203,14 +210,10 @@ class BasicLayout extends React.PureComponent {
</Header>
<Content style={{ margin: '24px 24px 0', height: '100%' }}>
<Switch>
{
redirectData.map(item =>
{redirectData.map(item => (
<Redirect key={item.from} exact from={item.from} to={item.to} />
)
}
{
getRoutes(match.path, routerData).map(item =>
(
))}
{getRoutes(match.path, routerData).map(item => (
<AuthorizedRoute
key={item.key}
path={item.path}
......@@ -219,31 +222,33 @@ class BasicLayout extends React.PureComponent {
authority={item.authority}
redirectPath="/exception/403"
/>
)
)
}
))}
<Redirect exact from="/" to={bashRedirect} />
<Route render={NotFound} />
</Switch>
</Content>
<Footer style={{ padding: 0 }}>
<GlobalFooter
links={[{
links={[
{
key: 'Pro 首页',
title: 'Pro 首页',
href: 'http://pro.ant.design',
blankTarget: true,
}, {
},
{
key: 'github',
title: <Icon type="github" />,
href: 'https://github.com/ant-design/ant-design-pro',
blankTarget: true,
}, {
},
{
key: 'Ant Design',
title: 'Ant Design',
href: 'http://ant.design',
blankTarget: true,
}]}
},
]}
copyright={
<Fragment>
Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.content {
margin: 24px 24px 0;
......
......@@ -7,21 +7,29 @@ import styles from './UserLayout.less';
import logo from '../assets/logo.svg';
import { getRoutes } from '../utils/utils';
const links = [{
const links = [
{
key: 'help',
title: '帮助',
href: '',
}, {
},
{
key: 'privacy',
title: '隐私',
href: '',
}, {
},
{
key: 'terms',
title: '条款',
href: '',
}];
},
];
const copyright = <Fragment>Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品</Fragment>;
const copyright = (
<Fragment>
Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品
</Fragment>
);
class UserLayout extends React.PureComponent {
getPageTitle() {
......@@ -49,16 +57,14 @@ class UserLayout extends React.PureComponent {
<div className={styles.desc}>Ant Design 是西湖区最具影响力的 Web 设计规范</div>
</div>
<Switch>
{getRoutes(match.path, routerData).map(item =>
(
{getRoutes(match.path, routerData).map(item => (
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
)
)}
))}
<Redirect exact from="/user" to="/user/login" />
</Switch>
</div>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.container {
display: flex;
......
// Use require.context to require reducers automatically
// Ref: https://webpack.js.org/guides/dependency-management/#require-context
const context = require.context('./', false, /\.js$/);
export default context.keys().filter(item => item !== './index.js').map(key => context(key));
export default context
.keys()
.filter(item => item !== './index.js')
.map(key => context(key));
......@@ -21,10 +21,7 @@ function RouterConfig({ history, app }) {
<LocaleProvider locale={zhCN}>
<ConnectedRouter history={history}>
<Switch>
<Route
path="/user"
component={UserLayout}
/>
<Route path="/user" component={UserLayout} />
<AuthorizedRoute
path="/"
render={props => <BasicLayout {...props} />}
......
......@@ -66,19 +66,19 @@ export default class Analysis extends Component {
});
}
handleChangeSalesType = (e) => {
handleChangeSalesType = e => {
this.setState({
salesType: e.target.value,
});
};
handleTabChange = (key) => {
handleTabChange = key => {
this.setState({
currentTabKey: key,
});
};
handleRangePickerChange = (rangePickerValue) => {
handleRangePickerChange = rangePickerValue => {
this.setState({
rangePickerValue,
});
......@@ -88,7 +88,7 @@ export default class Analysis extends Component {
});
};
selectDate = (type) => {
selectDate = type => {
this.setState({
rangePickerValue: getTimeDistance(type),
});
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.iconGroup {
i {
......
......@@ -14,7 +14,7 @@ const { Secured } = Authorized;
const targetTime = new Date().getTime() + 3900000;
// use permission as a parameter
const havePermissionAsync = new Promise((resolve) => {
const havePermissionAsync = new Promise(resolve => {
// Call resolve on behalf of passed
setTimeout(() => resolve(), 1000);
});
......@@ -81,11 +81,7 @@ export default class Monitor extends PureComponent {
bodyStyle={{ textAlign: 'center' }}
bordered={false}
>
<Gauge
title="跳出率"
height={180}
percent={87}
/>
<Gauge title="跳出率" height={180} percent={87} />
</Card>
</Col>
</Row>
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.mapChart {
padding-top: 24px;
......@@ -13,7 +13,7 @@
}
.pieCard :global(.pie-stat) {
font-size: 24px!important;
font-size: 24px !important;
}
@media screen and (max-width: @screen-lg) {
......
......@@ -99,13 +99,15 @@ export default class Workplace extends PureComponent {
}
renderActivities() {
const {
activities: { list },
} = this.props;
return list.map((item) => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map((key) => {
const { activities: { list } } = this.props;
return list.map(item => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => {
if (item[key]) {
return <a href={item[key].link} key={item[key].name}>{item[key].name}</a>;
return (
<a href={item[key].link} key={item[key].name}>
{item[key].name}
</a>
);
}
return key;
});
......@@ -142,7 +144,10 @@ export default class Workplace extends PureComponent {
const pageHeaderContent = (
<div className={styles.pageHeaderContent}>
<div className={styles.avatar}>
<Avatar size="large" src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png" />
<Avatar
size="large"
src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"
/>
</div>
<div className={styles.content}>
<div className={styles.contentTitle}>早安曲丽丽祝你开心每一天</div>
......@@ -159,7 +164,9 @@ export default class Workplace extends PureComponent {
</div>
<div className={styles.statItem}>
<p>团队内排名</p>
<p>8<span> / 24</span></p>
<p>
8<span> / 24</span>
</p>
</div>
<div className={styles.statItem}>
<p>项目访问</p>
......@@ -169,10 +176,7 @@ export default class Workplace extends PureComponent {
);
return (
<PageHeaderLayout
content={pageHeaderContent}
extraContent={extraContent}
>
<PageHeaderLayout content={pageHeaderContent} extraContent={extraContent}>
<Row gutter={24}>
<Col xl={16} lg={24} md={24} sm={24} xs={24}>
<Card
......@@ -184,17 +188,16 @@ export default class Workplace extends PureComponent {
loading={projectLoading}
bodyStyle={{ padding: 0 }}
>
{
notice.map(item => (
{notice.map(item => (
<Card.Grid className={styles.projectGrid} key={item.id}>
<Card bodyStyle={{ padding: 0 }} bordered={false}>
<Card.Meta
title={(
title={
<div className={styles.cardTitle}>
<Avatar size="small" src={item.logo} />
<Link to={item.href}>{item.title}</Link>
</div>
)}
}
description={item.description}
/>
<div className={styles.projectItemContent}>
......@@ -207,8 +210,7 @@ export default class Workplace extends PureComponent {
</div>
</Card>
</Card.Grid>
))
}
))}
</Card>
<Card
bodyStyle={{ padding: 0 }}
......@@ -218,9 +220,7 @@ export default class Workplace extends PureComponent {
loading={activitiesLoading}
>
<List loading={activitiesLoading} size="large">
<div className={styles.activitiesList}>
{this.renderActivities()}
</div>
<div className={styles.activitiesList}>{this.renderActivities()}</div>
</List>
</Card>
</Col>
......@@ -231,11 +231,7 @@ export default class Workplace extends PureComponent {
bordered={false}
bodyStyle={{ padding: 0 }}
>
<EditableLinkGroup
onAdd={() => {}}
links={links}
linkElement={Link}
/>
<EditableLinkGroup onAdd={() => {}} links={links} linkElement={Link} />
</Card>
<Card
style={{ marginBottom: 24 }}
......@@ -247,23 +243,17 @@ export default class Workplace extends PureComponent {
<Radar hasLegend height={343} data={radarData} />
</div>
</Card>
<Card
bodyStyle={{ paddingTop: 12, paddingBottom: 12 }}
bordered={false}
title="团队"
>
<Card bodyStyle={{ paddingTop: 12, paddingBottom: 12 }} bordered={false} title="团队">
<div className={styles.members}>
<Row gutter={48}>
{
members.map(item => (
{members.map(item => (
<Col span={12} key={`members-item-${item.id}`}>
<Link to={item.link}>
<Avatar src={item.logo} size="small" />
<span className={styles.member}>{item.title}</span>
</Link>
</Col>
))
}
))}
</Row>
</div>
</Card>
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.activitiesList {
padding: 0 24px 8px 24px;
......@@ -96,7 +96,7 @@
max-width: 100px;
vertical-align: top;
margin-left: 12px;
transition: all .3s;
transition: all 0.3s;
display: inline-block;
.textOverflow();
}
......
.trigger {
background: "red";
background: 'red';
:global(.ant-btn) {
margin-right: 8px;
margin-bottom: 12px;
......
......@@ -10,7 +10,7 @@ export default class TriggerException extends PureComponent {
state = {
isloading: false,
};
triggerError = (code) => {
triggerError = code => {
this.setState({
isloading: true,
});
......
import React, { PureComponent } from 'react';
import { Card, Button, Form, Icon, Col, Row, DatePicker, TimePicker, Input, Select, Popover } from 'antd';
import {
Card,
Button,
Form,
Icon,
Col,
Row,
DatePicker,
TimePicker,
Input,
Select,
Popover,
} from 'antd';
import { connect } from 'dva';
import FooterToolbar from 'components/FooterToolbar';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
......@@ -24,22 +36,26 @@ const fieldLabels = {
type2: '任务类型',
};
const tableData = [{
const tableData = [
{
key: '1',
workId: '00001',
name: 'John Brown',
department: 'New York No. 1 Lake Park',
}, {
},
{
key: '2',
workId: '00002',
name: 'Jim Green',
department: 'London No. 1 Lake Park',
}, {
},
{
key: '3',
workId: '00003',
name: 'Joe Black',
department: 'Sidney No. 1 Lake Park',
}];
},
];
class AdvancedForm extends PureComponent {
state = {
......@@ -57,7 +73,7 @@ class AdvancedForm extends PureComponent {
if (this.state.width !== width) {
this.setState({ width });
}
}
};
render() {
const { form, dispatch, submitting } = this.props;
const { getFieldDecorator, validateFieldsAndScroll, getFieldsError } = form;
......@@ -78,13 +94,13 @@ class AdvancedForm extends PureComponent {
if (!errors || errorCount === 0) {
return null;
}
const scrollToField = (fieldKey) => {
const scrollToField = fieldKey => {
const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
if (labelNode) {
labelNode.scrollIntoView(true);
}
};
const errorList = Object.keys(errors).map((key) => {
const errorList = Object.keys(errors).map(key => {
if (!errors[key]) {
return null;
}
......@@ -124,9 +140,7 @@ class AdvancedForm extends PureComponent {
<Form.Item label={fieldLabels.name}>
{getFieldDecorator('name', {
rules: [{ required: true, message: '请输入仓库名称' }],
})(
<Input placeholder="请输入仓库名称" />
)}
})(<Input placeholder="请输入仓库名称" />)}
</Form.Item>
</Col>
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
......@@ -200,18 +214,14 @@ class AdvancedForm extends PureComponent {
<Form.Item label={fieldLabels.name2}>
{getFieldDecorator('name2', {
rules: [{ required: true, message: '请输入' }],
})(
<Input placeholder="请输入" />
)}
})(<Input placeholder="请输入" />)}
</Form.Item>
</Col>
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
<Form.Item label={fieldLabels.url2}>
{getFieldDecorator('url2', {
rules: [{ required: true, message: '请选择' }],
})(
<Input placeholder="请输入" />
)}
})(<Input placeholder="请输入" />)}
</Form.Item>
</Col>
<Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
......
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import {
Form, Input, DatePicker, Select, Button, Card, InputNumber, Radio, Icon, Tooltip,
Form,
Input,
DatePicker,
Select,
Button,
Card,
InputNumber,
Radio,
Icon,
Tooltip,
} from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import styles from './style.less';
......@@ -16,7 +25,7 @@ const { TextArea } = Input;
}))
@Form.create()
export default class BasicForms extends PureComponent {
handleSubmit = (e) => {
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
......@@ -26,7 +35,7 @@ export default class BasicForms extends PureComponent {
});
}
});
}
};
render() {
const { submitting } = this.props;
const { getFieldDecorator, getFieldValue } = this.props.form;
......@@ -51,60 +60,57 @@ export default class BasicForms extends PureComponent {
};
return (
<PageHeaderLayout title="基础表单" content="表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。">
<Card bordered={false}>
<Form
onSubmit={this.handleSubmit}
hideRequiredMark
style={{ marginTop: 8 }}
>
<FormItem
{...formItemLayout}
label="标题"
<PageHeaderLayout
title="基础表单"
content="表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。"
>
<Card bordered={false}>
<Form onSubmit={this.handleSubmit} hideRequiredMark style={{ marginTop: 8 }}>
<FormItem {...formItemLayout} label="标题">
{getFieldDecorator('title', {
rules: [{
required: true, message: '请输入标题',
}],
})(
<Input placeholder="给目标起个名字" />
)}
rules: [
{
required: true,
message: '请输入标题',
},
],
})(<Input placeholder="给目标起个名字" />)}
</FormItem>
<FormItem
{...formItemLayout}
label="起止日期"
>
<FormItem {...formItemLayout} label="起止日期">
{getFieldDecorator('date', {
rules: [{
required: true, message: '请选择起止日期',
}],
})(
<RangePicker style={{ width: '100%' }} placeholder={['开始日期', '结束日期']} />
)}
rules: [
{
required: true,
message: '请选择起止日期',
},
],
})(<RangePicker style={{ width: '100%' }} placeholder={['开始日期', '结束日期']} />)}
</FormItem>
<FormItem
{...formItemLayout}
label="目标描述"
>
<FormItem {...formItemLayout} label="目标描述">
{getFieldDecorator('goal', {
rules: [{
required: true, message: '请输入目标描述',
}],
rules: [
{
required: true,
message: '请输入目标描述',
},
],
})(
<TextArea style={{ minHeight: 32 }} placeholder="请输入你的阶段性工作目标" rows={4} />
<TextArea
style={{ minHeight: 32 }}
placeholder="请输入你的阶段性工作目标"
rows={4}
/>
)}
</FormItem>
<FormItem
{...formItemLayout}
label="衡量标准"
>
<FormItem {...formItemLayout} label="衡量标准">
{getFieldDecorator('standard', {
rules: [{
required: true, message: '请输入衡量标准',
}],
})(
<TextArea style={{ minHeight: 32 }} placeholder="请输入衡量标准" rows={4} />
)}
rules: [
{
required: true,
message: '请输入衡量标准',
},
],
})(<TextArea style={{ minHeight: 32 }} placeholder="请输入衡量标准" rows={4} />)}
</FormItem>
<FormItem
{...formItemLayout}
......@@ -126,7 +132,11 @@ export default class BasicForms extends PureComponent {
</FormItem>
<FormItem
{...formItemLayout}
label={<span>邀评人<em className={styles.optional}>选填</em></span>}
label={
<span>
邀评人<em className={styles.optional}>选填</em>
</span>
}
>
{getFieldDecorator('invites')(
<Input placeholder="请直接 @姓名/工号,最多可邀请 5 人" />
......@@ -134,18 +144,16 @@ export default class BasicForms extends PureComponent {
</FormItem>
<FormItem
{...formItemLayout}
label={<span>权重<em className={styles.optional}>选填</em></span>}
label={
<span>
权重<em className={styles.optional}>选填</em>
</span>
}
>
{getFieldDecorator('weight')(
<InputNumber placeholder="请输入" min={0} max={100} />
)}
{getFieldDecorator('weight')(<InputNumber placeholder="请输入" min={0} max={100} />)}
<span>%</span>
</FormItem>
<FormItem
{...formItemLayout}
label="目标公开"
help="客户、邀评人默认被分享"
>
<FormItem {...formItemLayout} label="目标公开" help="客户、邀评人默认被分享">
<div>
{getFieldDecorator('public', {
initialValue: '1',
......
......@@ -34,10 +34,7 @@ class Step1 extends React.PureComponent {
return (
<Fragment>
<Form layout="horizontal" className={styles.stepForm} hideRequiredMark>
<Form.Item
{...formItemLayout}
label="付款账户"
>
<Form.Item {...formItemLayout} label="付款账户">
{getFieldDecorator('payAccount', {
initialValue: data.payAccount,
rules: [{ required: true, message: '请选择付款账户' }],
......@@ -47,10 +44,7 @@ class Step1 extends React.PureComponent {
</Select>
)}
</Form.Item>
<Form.Item
{...formItemLayout}
label="收款账户"
>
<Form.Item {...formItemLayout} label="收款账户">
<Input.Group compact>
<Select defaultValue="alipay" style={{ width: 100 }}>
<Option value="alipay">支付宝</Option>
......@@ -62,40 +56,34 @@ class Step1 extends React.PureComponent {
{ required: true, message: '请输入收款人账户' },
{ type: 'email', message: '账户名应为邮箱格式' },
],
})(
<Input style={{ width: 'calc(100% - 100px)' }} placeholder="test@example.com" />
)}
})(<Input style={{ width: 'calc(100% - 100px)' }} placeholder="test@example.com" />)}
</Input.Group>
</Form.Item>
<Form.Item
{...formItemLayout}
label="收款人姓名"
>
<Form.Item {...formItemLayout} label="收款人姓名">
{getFieldDecorator('receiverName', {
initialValue: data.receiverName,
rules: [{ required: true, message: '请输入收款人姓名' }],
})(
<Input placeholder="请输入收款人姓名" />
)}
})(<Input placeholder="请输入收款人姓名" />)}
</Form.Item>
<Form.Item
{...formItemLayout}
label="转账金额"
>
<Form.Item {...formItemLayout} label="转账金额">
{getFieldDecorator('amount', {
initialValue: data.amount,
rules: [
{ required: true, message: '请输入转账金额' },
{ pattern: /^(\d+)((?:\.\d+)?)$/, message: '请输入合法金额数字' },
{
pattern: /^(\d+)((?:\.\d+)?)$/,
message: '请输入合法金额数字',
},
],
})(
<Input prefix="" placeholder="请输入金额" />
)}
})(<Input prefix="" placeholder="请输入金额" />)}
</Form.Item>
<Form.Item
wrapperCol={{
xs: { span: 24, offset: 0 },
sm: { span: formItemLayout.wrapperCol.span, offset: formItemLayout.labelCol.span },
sm: {
span: formItemLayout.wrapperCol.span,
offset: formItemLayout.labelCol.span,
},
}}
label=""
>
......@@ -108,9 +96,13 @@ class Step1 extends React.PureComponent {
<div className={styles.desc}>
<h3>说明</h3>
<h4>转账到支付宝账户</h4>
<p>如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明</p>
<p>
如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明
</p>
<h4>转账到银行卡</h4>
<p>如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明</p>
<p>
如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明
</p>
</div>
</Fragment>
);
......
......@@ -22,7 +22,7 @@ class Step2 extends React.PureComponent {
const onPrev = () => {
dispatch(routerRedux.push('/form/step-form'));
};
const onValidateForm = (e) => {
const onValidateForm = e => {
e.preventDefault();
validateFields((err, values) => {
if (!err) {
......@@ -44,55 +44,39 @@ class Step2 extends React.PureComponent {
message="确认转账后,资金将直接打入对方账户,无法退回。"
style={{ marginBottom: 24 }}
/>
<Form.Item
{...formItemLayout}
className={styles.stepFormText}
label="付款账户"
>
<Form.Item {...formItemLayout} className={styles.stepFormText} label="付款账户">
{data.payAccount}
</Form.Item>
<Form.Item
{...formItemLayout}
className={styles.stepFormText}
label="收款账户"
>
<Form.Item {...formItemLayout} className={styles.stepFormText} label="收款账户">
{data.receiverAccount}
</Form.Item>
<Form.Item
{...formItemLayout}
className={styles.stepFormText}
label="收款人姓名"
>
<Form.Item {...formItemLayout} className={styles.stepFormText} label="收款人姓名">
{data.receiverName}
</Form.Item>
<Form.Item
{...formItemLayout}
className={styles.stepFormText}
label="转账金额"
>
<Form.Item {...formItemLayout} className={styles.stepFormText} label="转账金额">
<span className={styles.money}>{data.amount}</span>
<span className={styles.uppercase}>{digitUppercase(data.amount)}</span>
</Form.Item>
<Divider style={{ margin: '24px 0' }} />
<Form.Item
{...formItemLayout}
label="支付密码"
required={false}
>
<Form.Item {...formItemLayout} label="支付密码" required={false}>
{getFieldDecorator('password', {
initialValue: '123456',
rules: [{
required: true, message: '需要支付密码才能进行支付',
}],
})(
<Input type="password" autoComplete="off" style={{ width: '80%' }} />
)}
rules: [
{
required: true,
message: '需要支付密码才能进行支付',
},
],
})(<Input type="password" autoComplete="off" style={{ width: '80%' }} />)}
</Form.Item>
<Form.Item
style={{ marginBottom: 8 }}
wrapperCol={{
xs: { span: 24, offset: 0 },
sm: { span: formItemLayout.wrapperCol.span, offset: formItemLayout.labelCol.span },
sm: {
span: formItemLayout.wrapperCol.span,
offset: formItemLayout.labelCol.span,
},
}}
label=""
>
......
......@@ -14,20 +14,30 @@ class Step3 extends React.PureComponent {
const information = (
<div className={styles.information}>
<Row>
<Col span={8} className={styles.label}>付款账户</Col>
<Col span={8} className={styles.label}>
付款账户
</Col>
<Col span={16}>{data.payAccount}</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>收款账户</Col>
<Col span={8} className={styles.label}>
收款账户
</Col>
<Col span={16}>{data.receiverAccount}</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>收款人姓名</Col>
<Col span={8} className={styles.label}>
收款人姓名
</Col>
<Col span={16}>{data.receiverName}</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>转账金额</Col>
<Col span={16}><span className={styles.money}>{data.amount}</span> 元</Col>
<Col span={8} className={styles.label}>
转账金额
</Col>
<Col span={16}>
<span className={styles.money}>{data.amount}</span>
</Col>
</Row>
</div>
);
......@@ -36,9 +46,7 @@ class Step3 extends React.PureComponent {
<Button type="primary" onClick={onFinish}>
再转一笔
</Button>
<Button>
查看账单
</Button>
<Button>查看账单</Button>
</Fragment>
);
return (
......
......@@ -14,16 +14,23 @@ export default class StepForm extends PureComponent {
const { pathname } = location;
const pathList = pathname.split('/');
switch (pathList[pathList.length - 1]) {
case 'info': return 0;
case 'confirm': return 1;
case 'result': return 2;
default: return 0;
case 'info':
return 0;
case 'confirm':
return 1;
case 'result':
return 2;
default:
return 0;
}
}
render() {
const { match, routerData } = this.props;
return (
<PageHeaderLayout title="分步表单" content="将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。">
<PageHeaderLayout
title="分步表单"
content="将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。"
>
<Card bordered={false}>
<Fragment>
<Steps current={this.getCurrentStep()} className={styles.steps}>
......@@ -32,16 +39,14 @@ export default class StepForm extends PureComponent {
<Step title="完成" />
</Steps>
<Switch>
{
getRoutes(match.path, routerData).map(item => (
{getRoutes(match.path, routerData).map(item => (
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
))
}
))}
<Redirect exact from="/form/step-form" to="/form/step-form/info" />
<Route render={NotFound} />
</Switch>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.stepForm {
margin: 40px auto 0;
......@@ -64,7 +64,7 @@
}
.money {
font-family: "Helvetica Neue", sans-serif;
font-family: 'Helvetica Neue', sans-serif;
font-weight: 500;
font-size: 20px;
line-height: 14px;
......
......@@ -23,7 +23,7 @@ export default class TableForm extends PureComponent {
}
index = 0;
cacheOriginData = {};
toggleEditable=(e, key) => {
toggleEditable = (e, key) => {
e.preventDefault();
const newData = this.state.data.map(item => ({ ...item }));
const target = this.getRowByKey(key, newData);
......@@ -35,7 +35,7 @@ export default class TableForm extends PureComponent {
target.editable = !target.editable;
this.setState({ data: newData });
}
}
};
remove(key) {
const newData = this.state.data.filter(item => item.key !== key);
this.setState({ data: newData });
......@@ -53,7 +53,7 @@ export default class TableForm extends PureComponent {
});
this.index += 1;
this.setState({ data: newData });
}
};
handleKeyPress(e, key) {
if (e.key === 'Enter') {
this.saveRow(e, key);
......@@ -108,7 +108,8 @@ export default class TableForm extends PureComponent {
this.clickedCancel = false;
}
render() {
const columns = [{
const columns = [
{
title: '成员姓名',
dataIndex: 'name',
key: 'name',
......@@ -127,7 +128,8 @@ export default class TableForm extends PureComponent {
}
return text;
},
}, {
},
{
title: '工号',
dataIndex: 'workId',
key: 'workId',
......@@ -145,7 +147,8 @@ export default class TableForm extends PureComponent {
}
return text;
},
}, {
},
{
title: '所属部门',
dataIndex: 'department',
key: 'department',
......@@ -163,7 +166,8 @@ export default class TableForm extends PureComponent {
}
return text;
},
}, {
},
{
title: '操作',
key: 'action',
render: (text, record) => {
......@@ -200,7 +204,8 @@ export default class TableForm extends PureComponent {
</span>
);
},
}];
},
];
return (
<Fragment>
......@@ -209,7 +214,7 @@ export default class TableForm extends PureComponent {
columns={columns}
dataSource={this.state.data}
pagination={false}
rowClassName={(record) => {
rowClassName={record => {
return record.editable ? styles.editable : '';
}}
/>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.card {
margin-bottom: 24px;
......@@ -40,7 +40,7 @@
border-bottom: 1px solid @border-color-split;
padding: 8px 16px;
cursor: pointer;
transition: all .3s;
transition: all 0.3s;
&:hover {
background: @primary-1;
}
......
......@@ -11,14 +11,19 @@ import styles from './Applications.less';
const { Option } = Select;
const FormItem = Form.Item;
const formatWan = (val) => {
const formatWan = val => {
const v = val * 1;
if (!v || isNaN(v)) return '';
let result = val;
if (val > 10000) {
result = Math.floor(val / 10000);
result = <span>{result}<em className={styles.wan}></em></span>;
result = (
<span>
{result}
<em className={styles.wan}></em>
</span>
);
}
return result;
};
......@@ -43,7 +48,7 @@ export default class FilterCardList extends PureComponent {
const { form, dispatch } = this.props;
// setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候
setTimeout(() => {
form.validateFields((err) => {
form.validateFields(err => {
if (!err) {
// eslint-disable-next-line
dispatch({
......@@ -55,7 +60,7 @@ export default class FilterCardList extends PureComponent {
}
});
}, 0);
}
};
render() {
const { list: { list }, loading, form } = this.props;
......@@ -84,13 +89,19 @@ export default class FilterCardList extends PureComponent {
const itemMenu = (
<Menu>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">1st menu item</a>
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
1st menu item
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">2nd menu item</a>
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">
2nd menu item
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">3d menu item</a>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
3d menu item
</a>
</Menu.Item>
</Menu>
);
......@@ -119,17 +130,10 @@ export default class FilterCardList extends PureComponent {
)}
</FormItem>
</StandardFormRow>
<StandardFormRow
title="其它选项"
grid
last
>
<StandardFormRow title="其它选项" grid last>
<Row gutter={16}>
<Col lg={8} md={10} sm={10} xs={24}>
<FormItem
{...formItemLayout}
label="作者"
>
<FormItem {...formItemLayout} label="作者">
{getFieldDecorator('author', {})(
<Select
onChange={this.handleFormSubmit}
......@@ -142,10 +146,7 @@ export default class FilterCardList extends PureComponent {
</FormItem>
</Col>
<Col lg={8} md={10} sm={10} xs={24}>
<FormItem
{...formItemLayout}
label="好评度"
>
<FormItem {...formItemLayout} label="好评度">
{getFieldDecorator('rate', {})(
<Select
onChange={this.handleFormSubmit}
......@@ -174,16 +175,21 @@ export default class FilterCardList extends PureComponent {
hoverable
bodyStyle={{ paddingBottom: 20 }}
actions={[
<Tooltip title="下载"><Icon type="download" /></Tooltip>,
<Tooltip title="编辑"><Icon type="edit" /></Tooltip>,
<Tooltip title="分享"><Icon type="share-alt" /></Tooltip>,
<Dropdown overlay={itemMenu}><Icon type="ellipsis" /></Dropdown>,
<Tooltip title="下载">
<Icon type="download" />
</Tooltip>,
<Tooltip title="编辑">
<Icon type="edit" />
</Tooltip>,
<Tooltip title="分享">
<Icon type="share-alt" />
</Tooltip>,
<Dropdown overlay={itemMenu}>
<Icon type="ellipsis" />
</Dropdown>,
]}
>
<Card.Meta
avatar={<Avatar size="small" src={item.avatar} />}
title={item.title}
/>
<Card.Meta avatar={<Avatar size="small" src={item.avatar} />} title={item.title} />
<div className={styles.cardItemContent}>
<CardInfo
activeUser={formatWan(item.activeUser)}
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.filterCardList {
margin-bottom: -24px;
......
......@@ -27,7 +27,7 @@ export default class SearchList extends Component {
form.setFieldsValue({
owner: ['wzj'],
});
}
};
fetchMore = () => {
this.props.dispatch({
......@@ -36,7 +36,7 @@ export default class SearchList extends Component {
count: pageSize,
},
});
}
};
render() {
const { form, list: { list }, loading } = this.props;
......@@ -76,7 +76,8 @@ export default class SearchList extends Component {
<div className={styles.listContent}>
<div className={styles.description}>{content}</div>
<div className={styles.extra}>
<Avatar src={avatar} size="small" /><a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
<Avatar src={avatar} size="small" />
<a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
<em>{moment(updatedAt).format('YYYY-MM-DD HH:mm')}</em>
</div>
</div>
......@@ -90,10 +91,17 @@ export default class SearchList extends Component {
},
};
const loadMore = list.length > 0 ? (
const loadMore =
list.length > 0 ? (
<div style={{ textAlign: 'center', marginTop: 16 }}>
<Button onClick={this.fetchMore} style={{ paddingLeft: 48, paddingRight: 48 }}>
{loading ? <span><Icon type="loading" /> 加载中...</span> : '加载更多'}
{loading ? (
<span>
<Icon type="loading" /> 加载中...
</span>
) : (
'加载更多'
)}
</Button>
</div>
) : null;
......@@ -122,10 +130,7 @@ export default class SearchList extends Component {
)}
</FormItem>
</StandardFormRow>
<StandardFormRow
title="owner"
grid
>
<StandardFormRow title="owner" grid>
<Row>
<Col lg={16} md={24} sm={24} xs={24}>
<FormItem>
......@@ -137,29 +142,24 @@ export default class SearchList extends Component {
style={{ maxWidth: 286, width: '100%' }}
placeholder="选择 owner"
>
{
owners.map(owner =>
<Option key={owner.id} value={owner.id}>{owner.name}</Option>
)
}
{owners.map(owner => (
<Option key={owner.id} value={owner.id}>
{owner.name}
</Option>
))}
</Select>
)}
<a className={styles.selfTrigger} onClick={this.setOwner}>只看自己的</a>
<a className={styles.selfTrigger} onClick={this.setOwner}>
只看自己的
</a>
</FormItem>
</Col>
</Row>
</StandardFormRow>
<StandardFormRow
title="其它选项"
grid
last
>
<StandardFormRow title="其它选项" grid last>
<Row gutter={16}>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="活跃用户"
>
<FormItem {...formItemLayout} label="活跃用户">
{getFieldDecorator('user', {})(
<Select
onChange={this.handleFormSubmit}
......@@ -172,10 +172,7 @@ export default class SearchList extends Component {
</FormItem>
</Col>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="好评度"
>
<FormItem {...formItemLayout} label="好评度">
{getFieldDecorator('rate', {})(
<Select
onChange={this.handleFormSubmit}
......@@ -214,9 +211,11 @@ export default class SearchList extends Component {
extra={<div className={styles.listItemExtra} />}
>
<List.Item.Meta
title={(
<a className={styles.listItemMetaTitle} href={item.href}>{item.title}</a>
)}
title={
<a className={styles.listItemMetaTitle} href={item.href}>
{item.title}
</a>
}
description={
<span>
<Tag>Ant Design</Tag>
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.listContent {
.description {
......
import React, { PureComponent } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import { List, Card, Row, Col, Radio, Input, Progress, Button, Icon, Dropdown, Menu, Avatar } from 'antd';
import {
List,
Card,
Row,
Col,
Radio,
Input,
Progress,
Button,
Icon,
Dropdown,
Menu,
Avatar,
} from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
......@@ -43,11 +56,7 @@ export default class BasicList extends PureComponent {
<RadioButton value="progress">进行中</RadioButton>
<RadioButton value="waiting">等待中</RadioButton>
</RadioGroup>
<Search
className={styles.extraContentSearch}
placeholder="请输入"
onSearch={() => ({})}
/>
<Search className={styles.extraContentSearch} placeholder="请输入" onSearch={() => ({})} />
</div>
);
......@@ -128,9 +137,7 @@ export default class BasicList extends PureComponent {
pagination={paginationProps}
dataSource={list}
renderItem={item => (
<List.Item
actions={[<a>编辑</a>, <MoreBtn />]}
>
<List.Item actions={[<a>编辑</a>, <MoreBtn />]}>
<List.Item.Meta
avatar={<Avatar src={item.logo} shape="square" size="large" />}
title={<a href={item.href}>{item.title}</a>}
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.standardList {
:global {
......
......@@ -32,13 +32,16 @@ export default class CardList extends PureComponent {
</p>
<div className={styles.contentLink}>
<a>
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/MjEImQtenlyueSmVEfUD.svg" /> 快速开始
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/MjEImQtenlyueSmVEfUD.svg" />{' '}
快速开始
</a>
<a>
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/NbuDUAuBlIApFuDvWiND.svg" /> 产品简介
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/NbuDUAuBlIApFuDvWiND.svg" />{' '}
产品简介
</a>
<a>
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/ohOEPSYdDTNnyMbGuyLb.svg" /> 产品文档
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/ohOEPSYdDTNnyMbGuyLb.svg" />{' '}
产品文档
</a>
</div>
</div>
......@@ -46,31 +49,33 @@ export default class CardList extends PureComponent {
const extraContent = (
<div className={styles.extraImg}>
<img alt="这是一个标题" src="https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png" />
<img
alt="这是一个标题"
src="https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png"
/>
</div>
);
return (
<PageHeaderLayout
title="卡片列表"
content={content}
extraContent={extraContent}
>
<PageHeaderLayout title="卡片列表" content={content} extraContent={extraContent}>
<div className={styles.cardList}>
<List
rowKey="id"
loading={loading}
grid={{ gutter: 24, lg: 3, md: 2, sm: 1, xs: 1 }}
dataSource={['', ...list]}
renderItem={item => (item ? (
renderItem={item =>
item ? (
<List.Item key={item.id}>
<Card hoverable className={styles.card} actions={[<a>操作一</a>, <a>操作二</a>]}>
<Card.Meta
avatar={<img alt="" className={styles.cardAvatar} src={item.avatar} />}
title={<a href="#">{item.title}</a>}
description={(
<Ellipsis className={styles.item} lines={3}>{item.description}</Ellipsis>
)}
description={
<Ellipsis className={styles.item} lines={3}>
{item.description}
</Ellipsis>
}
/>
</Card>
</List.Item>
......@@ -81,7 +86,7 @@ export default class CardList extends PureComponent {
</Button>
</List.Item>
)
)}
}
/>
</div>
</PageHeaderLayout>
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.cardList {
margin-bottom: -24px;
......
......@@ -7,7 +7,7 @@ import { getRoutes } from '../../utils/utils';
@connect()
export default class SearchList extends Component {
handleTabChange = (key) => {
handleTabChange = key => {
const { dispatch, match } = this.props;
switch (key) {
case 'articles':
......@@ -22,19 +22,23 @@ export default class SearchList extends Component {
default:
break;
}
}
};
render() {
const tabList = [{
const tabList = [
{
key: 'articles',
tab: '文章',
}, {
},
{
key: 'applications',
tab: '应用',
}, {
},
{
key: 'projects',
tab: '项目',
}];
},
];
const mainSearch = (
<div style={{ textAlign: 'center' }}>
......@@ -60,18 +64,9 @@ export default class SearchList extends Component {
onTabChange={this.handleTabChange}
>
<Switch>
{
routes.map(item =>
(
<Route
key={item.key}
path={item.path}
component={item.component}
exact={item.exact}
/>
)
)
}
{routes.map(item => (
<Route key={item.key} path={item.path} component={item.component} exact={item.exact} />
))}
</Switch>
</PageHeaderLayout>
);
......
......@@ -33,7 +33,7 @@ export default class CoverCardList extends PureComponent {
const { form, dispatch } = this.props;
// setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候
setTimeout(() => {
form.validateFields((err) => {
form.validateFields(err => {
if (!err) {
// eslint-disable-next-line
dispatch({
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.coverCardList {
margin-bottom: -24px;
......
import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import moment from 'moment';
import { Row, Col, Card, Form, Input, Select, Icon, Button, Dropdown, Menu, InputNumber, DatePicker, Modal, message, Badge, Divider } from 'antd';
import {
Row,
Col,
Card,
Form,
Input,
Select,
Icon,
Button,
Dropdown,
Menu,
InputNumber,
DatePicker,
Modal,
message,
Badge,
Divider,
} from 'antd';
import StandardTable from 'components/StandardTable';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
......@@ -9,7 +26,10 @@ import styles from './TableList.less';
const FormItem = Form.Item;
const { Option } = Select;
const getValue = obj => Object.keys(obj).map(key => obj[key]).join(',');
const getValue = obj =>
Object.keys(obj)
.map(key => obj[key])
.join(',');
const statusMap = ['default', 'processing', 'success', 'error'];
const status = ['关闭', '运行中', '已上线', '异常'];
const columns = [
......@@ -73,7 +93,7 @@ const columns = [
},
];
const CreateForm = Form.create()((props) => {
const CreateForm = Form.create()(props => {
const { modalVisible, form, handleAdd, handleModalVisible } = props;
const okHandle = () => {
form.validateFields((err, fieldsValue) => {
......@@ -89,16 +109,10 @@ const CreateForm = Form.create()((props) => {
onOk={okHandle}
onCancel={() => handleModalVisible()}
>
<FormItem
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
label="描述"
>
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="描述">
{form.getFieldDecorator('desc', {
rules: [{ required: true, message: 'Please input some description...' }],
})(
<Input placeholder="请输入" />
)}
})(<Input placeholder="请输入" />)}
</FormItem>
</Modal>
);
......@@ -148,7 +162,7 @@ export default class TableList extends PureComponent {
type: 'rule/fetch',
payload: params,
});
}
};
handleFormReset = () => {
const { form, dispatch } = this.props;
......@@ -160,15 +174,15 @@ export default class TableList extends PureComponent {
type: 'rule/fetch',
payload: {},
});
}
};
toggleForm = () => {
this.setState({
expandForm: !this.state.expandForm,
});
}
};
handleMenuClick = (e) => {
handleMenuClick = e => {
const { dispatch } = this.props;
const { selectedRows } = this.state;
......@@ -191,15 +205,15 @@ export default class TableList extends PureComponent {
default:
break;
}
}
};
handleSelectRows = (rows) => {
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
}
};
handleSearch = (e) => {
handleSearch = e => {
e.preventDefault();
const { dispatch, form } = this.props;
......@@ -221,15 +235,15 @@ export default class TableList extends PureComponent {
payload: values,
});
});
}
};
handleModalVisible = (flag) => {
handleModalVisible = flag => {
this.setState({
modalVisible: !!flag,
});
}
};
handleAdd = (fields) => {
handleAdd = fields => {
this.props.dispatch({
type: 'rule/add',
payload: {
......@@ -241,7 +255,7 @@ export default class TableList extends PureComponent {
this.setState({
modalVisible: false,
});
}
};
renderSimpleForm() {
const { getFieldDecorator } = this.props.form;
......@@ -250,9 +264,7 @@ export default class TableList extends PureComponent {
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<FormItem label="规则编号">
{getFieldDecorator('no')(
<Input placeholder="请输入" />
)}
{getFieldDecorator('no')(<Input placeholder="请输入" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
......@@ -267,8 +279,12 @@ export default class TableList extends PureComponent {
</Col>
<Col md={8} sm={24}>
<span className={styles.submitButtons}>
<Button type="primary" htmlType="submit">查询</Button>
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>重置</Button>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
重置
</Button>
<a style={{ marginLeft: 8 }} onClick={this.toggleForm}>
展开 <Icon type="down" />
</a>
......@@ -286,9 +302,7 @@ export default class TableList extends PureComponent {
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<FormItem label="规则编号">
{getFieldDecorator('no')(
<Input placeholder="请输入" />
)}
{getFieldDecorator('no')(<Input placeholder="请输入" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
......@@ -303,9 +317,7 @@ export default class TableList extends PureComponent {
</Col>
<Col md={8} sm={24}>
<FormItem label="调用次数">
{getFieldDecorator('number')(
<InputNumber style={{ width: '100%' }} />
)}
{getFieldDecorator('number')(<InputNumber style={{ width: '100%' }} />)}
</FormItem>
</Col>
</Row>
......@@ -340,8 +352,12 @@ export default class TableList extends PureComponent {
</Row>
<div style={{ overflow: 'hidden' }}>
<span style={{ float: 'right', marginBottom: 24 }}>
<Button type="primary" htmlType="submit">查询</Button>
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>重置</Button>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
重置
</Button>
<a style={{ marginLeft: 8 }} onClick={this.toggleForm}>
收起 <Icon type="up" />
</a>
......@@ -375,15 +391,12 @@ export default class TableList extends PureComponent {
<PageHeaderLayout title="查询表格">
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
{this.renderForm()}
</div>
<div className={styles.tableListForm}>{this.renderForm()}</div>
<div className={styles.tableListOperator}>
<Button icon="plus" type="primary" onClick={() => this.handleModalVisible(true)}>
新建
</Button>
{
selectedRows.length > 0 && (
{selectedRows.length > 0 && (
<span>
<Button>批量操作</Button>
<Dropdown overlay={menu}>
......@@ -392,8 +405,7 @@ export default class TableList extends PureComponent {
</Button>
</Dropdown>
</span>
)
}
)}
</div>
<StandardTable
selectedRows={selectedRows}
......@@ -405,10 +417,7 @@ export default class TableList extends PureComponent {
/>
</div>
</Card>
<CreateForm
{...parentMethods}
modalVisible={modalVisible}
/>
<CreateForm {...parentMethods} modalVisible={modalVisible} />
</PageHeaderLayout>
);
}
......
@import "~antd/lib/style/themes/default.less";
@import "../../utils/utils.less";
@import '~antd/lib/style/themes/default.less';
@import '../../utils/utils.less';
.tableList {
.tableListOperator {
......
......@@ -2,7 +2,21 @@ import React, { Component, Fragment } from 'react';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import { connect } from 'dva';
import { Button, Menu, Dropdown, Icon, Row, Col, Steps, Card, Popover, Badge, Table, Tooltip, Divider } from 'antd';
import {
Button,
Menu,
Dropdown,
Icon,
Row,
Col,
Steps,
Card,
Popover,
Badge,
Table,
Tooltip,
Divider,
} from 'antd';
import classNames from 'classnames';
import DescriptionList from 'components/DescriptionList';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
......@@ -12,7 +26,7 @@ const { Step } = Steps;
const { Description } = DescriptionList;
const ButtonGroup = Button.Group;
const getWindowWidth = () => (window.innerWidth || document.documentElement.clientWidth);
const getWindowWidth = () => window.innerWidth || document.documentElement.clientWidth;
const menu = (
<Menu>
......@@ -28,7 +42,9 @@ const action = (
<Button>操作</Button>
<Button>操作</Button>
<Dropdown overlay={menu} placement="bottomRight">
<Button><Icon type="ellipsis" /></Button>
<Button>
<Icon type="ellipsis" />
</Button>
</Dropdown>
</ButtonGroup>
<Button type="primary">主操作</Button>
......@@ -53,19 +69,24 @@ const description = (
<Description term="创建人">曲丽丽</Description>
<Description term="订购产品">XX 服务</Description>
<Description term="创建时间">2017-07-07</Description>
<Description term="关联单据"><a href="">12421</a></Description>
<Description term="关联单据">
<a href="">12421</a>
</Description>
<Description term="生效日期">2017-07-07 ~ 2017-08-08</Description>
<Description term="备注">请于两个工作日内确认</Description>
</DescriptionList>
);
const tabList = [{
const tabList = [
{
key: 'detail',
tab: '详情',
}, {
},
{
key: 'rule',
tab: '规则',
}];
},
];
const desc1 = (
<div className={classNames(styles.textSecondary, styles.stepDescription)}>
......@@ -83,7 +104,9 @@ const desc2 = (
周毛毛
<Icon type="dingding-o" style={{ color: '#00A0E9', marginLeft: 8 }} />
</Fragment>
<div><a href="">催一下</a></div>
<div>
<a href="">催一下</a>
</div>
</div>
);
......@@ -93,51 +116,69 @@ const popoverContent = (
<span className={styles.textSecondary} style={{ float: 'right' }}>
<Badge status="default" text={<span style={{ color: 'rgba(0, 0, 0, 0.45)' }}>未响应</span>} />
</span>
<div className={styles.textSecondary} style={{ marginTop: 4 }}>耗时2小时25分钟</div>
<div className={styles.textSecondary} style={{ marginTop: 4 }}>
耗时2小时25分钟
</div>
</div>
);
const customDot = (dot, { status }) => (status === 'process' ? (
const customDot = (dot, { status }) =>
status === 'process' ? (
<Popover placement="topLeft" arrowPointAtCenter content={popoverContent}>
{dot}
</Popover>
) : dot);
) : (
dot
);
const operationTabList = [{
const operationTabList = [
{
key: 'tab1',
tab: '操作日志一',
}, {
},
{
key: 'tab2',
tab: '操作日志二',
}, {
},
{
key: 'tab3',
tab: '操作日志三',
}];
},
];
const columns = [{
const columns = [
{
title: '操作类型',
dataIndex: 'type',
key: 'type',
}, {
},
{
title: '操作人',
dataIndex: 'name',
key: 'name',
}, {
},
{
title: '执行结果',
dataIndex: 'status',
key: 'status',
render: text => (
text === 'agree' ? <Badge status="success" text="成功" /> : <Badge status="error" text="驳回" />
render: text =>
text === 'agree' ? (
<Badge status="success" text="成功" />
) : (
<Badge status="error" text="驳回" />
),
}, {
},
{
title: '操作时间',
dataIndex: 'updatedAt',
key: 'updatedAt',
}, {
},
{
title: '备注',
dataIndex: 'memo',
key: 'memo',
}];
},
];
@connect(({ profile, loading }) => ({
profile,
......@@ -147,7 +188,7 @@ export default class AdvancedProfile extends Component {
state = {
operationkey: 'tab1',
stepDirection: 'horizontal',
}
};
componentDidMount() {
const { dispatch } = this.props;
......@@ -164,9 +205,9 @@ export default class AdvancedProfile extends Component {
this.setStepDirection.cancel();
}
onOperationTabChange = (key) => {
onOperationTabChange = key => {
this.setState({ operationkey: key });
}
};
@Bind()
@Debounce(200)
......@@ -189,30 +230,38 @@ export default class AdvancedProfile extends Component {
const { profile, loading } = this.props;
const { advancedOperation1, advancedOperation2, advancedOperation3 } = profile;
const contentList = {
tab1: <Table
tab1: (
<Table
pagination={false}
loading={loading}
dataSource={advancedOperation1}
columns={columns}
/>,
tab2: <Table
/>
),
tab2: (
<Table
pagination={false}
loading={loading}
dataSource={advancedOperation2}
columns={columns}
/>,
tab3: <Table
/>
),
tab3: (
<Table
pagination={false}
loading={loading}
dataSource={advancedOperation3}
columns={columns}
/>,
/>
),
};
return (
<PageHeaderLayout
title="单号:234231029431"
logo={<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png" />}
logo={
<img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png" />
}
action={action}
content={description}
extraContent={extra}
......@@ -232,17 +281,23 @@ export default class AdvancedProfile extends Component {
<Description term="会员卡号">32943898021309809423</Description>
<Description term="身份证">3321944288191034921</Description>
<Description term="联系方式">18112345678</Description>
<Description term="联系地址">曲丽丽 18100000000 浙江省杭州市西湖区黄姑山路工专路交叉路口</Description>
<Description term="联系地址">
曲丽丽 18100000000 浙江省杭州市西湖区黄姑山路工专路交叉路口
</Description>
</DescriptionList>
<DescriptionList style={{ marginBottom: 24 }} title="信息组">
<Description term="某某数据">725</Description>
<Description term="该数据更新时间">2017-08-08</Description>
<Description>&nbsp;</Description>
<Description term={
<Description
term={
<span>
某某数据
<Tooltip title="数据说明">
<Icon style={{ color: 'rgba(0, 0, 0, 0.43)', marginLeft: 4 }} type="info-circle-o" />
<Icon
style={{ color: 'rgba(0, 0, 0, 0.43)', marginLeft: 4 }}
type="info-circle-o"
/>
</Tooltip>
</span>
}
......@@ -258,12 +313,15 @@ export default class AdvancedProfile extends Component {
<Description term="角色码">1234567</Description>
<Description term="所属部门">XX公司 - YY部</Description>
<Description term="过期时间">2017-08-08</Description>
<Description term="描述">这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...</Description>
<Description term="描述">
这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...
</Description>
</DescriptionList>
<Divider style={{ margin: '16px 0' }} />
<DescriptionList size="small" style={{ marginBottom: 16 }} title="组名称" col="1">
<Description term="学名">
Citrullus lanatus (Thunb.) Matsum. et Nakai一年生蔓生藤本枝粗壮具明显的棱卷须较粗..
Citrullus lanatus (Thunb.) Matsum. et
Nakai一年生蔓生藤本枝粗壮具明显的棱卷须较粗..
</Description>
</DescriptionList>
<Divider style={{ margin: '16px 0' }} />
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.headerList {
margin-bottom: 4px;
......
......@@ -23,11 +23,11 @@ const progressColumns = [
dataIndex: 'status',
key: 'status',
render: text =>
(text === 'success' ? (
text === 'success' ? (
<Badge status="success" text="成功" />
) : (
<Badge status="processing" text="进行中" />
)),
),
},
{
title: '操作员ID',
......@@ -60,7 +60,7 @@ export default class BasicProfile extends Component {
if (basicGoods.length) {
let num = 0;
let amount = 0;
basicGoods.forEach((item) => {
basicGoods.forEach(item => {
num += Number(item.num);
amount += Number(item.amount);
});
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.title {
color: @heading-color;
......
......@@ -5,16 +5,27 @@ import PageHeaderLayout from '../../layouts/PageHeaderLayout';
const extra = (
<Fragment>
<div style={{ fontSize: 16, color: 'rgba(0, 0, 0, 0.85)', fontWeight: '500', marginBottom: 16 }}>
<div
style={{
fontSize: 16,
color: 'rgba(0, 0, 0, 0.85)',
fontWeight: '500',
marginBottom: 16,
}}
>
您提交的内容有如下错误
</div>
<div style={{ marginBottom: 16 }}>
<Icon style={{ color: '#f5222d', marginRight: 8 }} type="close-circle-o" />您的账户已被冻结
<a style={{ marginLeft: 16 }}>立即解冻 <Icon type="right" /></a>
<a style={{ marginLeft: 16 }}>
立即解冻 <Icon type="right" />
</a>
</div>
<div>
<Icon style={{ color: '#f5222d', marginRight: 8 }} type="close-circle-o" />您的账户还不具备申请资格
<a style={{ marginLeft: 16 }}>立即升级 <Icon type="right" /></a>
<a style={{ marginLeft: 16 }}>
立即升级 <Icon type="right" />
</a>
</div>
</Fragment>
);
......
......@@ -6,7 +6,14 @@ import PageHeaderLayout from '../../layouts/PageHeaderLayout';
const { Step } = Steps;
const desc1 = (
<div style={{ fontSize: 12, color: 'rgba(0, 0, 0, 0.45)', position: 'relative', left: 42 }}>
<div
style={{
fontSize: 12,
color: 'rgba(0, 0, 0, 0.45)',
position: 'relative',
left: 42,
}}
>
<div style={{ margin: '8px 0 4px' }}>
曲丽丽<Icon style={{ marginLeft: 8 }} type="dingding-o" />
</div>
......@@ -19,13 +26,22 @@ const desc2 = (
<div style={{ margin: '8px 0 4px' }}>
周毛毛<Icon type="dingding-o" style={{ color: '#00A0E9', marginLeft: 8 }} />
</div>
<div><a href="">催一下</a></div>
<div>
<a href="">催一下</a>
</div>
</div>
);
const extra = (
<Fragment>
<div style={{ fontSize: 16, color: 'rgba(0, 0, 0, 0.85)', fontWeight: '500', marginBottom: 20 }}>
<div
style={{
fontSize: 16,
color: 'rgba(0, 0, 0, 0.85)',
fontWeight: '500',
marginBottom: 20,
}}
>
项目名称
</div>
<Row style={{ marginBottom: 16 }}>
......
......@@ -15,11 +15,11 @@ export default class LoginPage extends Component {
state = {
type: 'account',
autoLogin: true,
}
};
onTabChange = (type) => {
onTabChange = type => {
this.setState({ type });
}
};
handleSubmit = (err, values) => {
const { type } = this.state;
......@@ -32,53 +32,47 @@ export default class LoginPage extends Component {
},
});
}
}
};
changeAutoLogin = (e) => {
changeAutoLogin = e => {
this.setState({
autoLogin: e.target.checked,
});
}
};
renderMessage = (content) => {
return (
<Alert style={{ marginBottom: 24 }} message={content} type="error" showIcon />
);
}
renderMessage = content => {
return <Alert style={{ marginBottom: 24 }} message={content} type="error" showIcon />;
};
render() {
const { login, submitting } = this.props;
const { type } = this.state;
return (
<div className={styles.main}>
<Login
defaultActiveKey={type}
onTabChange={this.onTabChange}
onSubmit={this.handleSubmit}
>
<Login defaultActiveKey={type} onTabChange={this.onTabChange} onSubmit={this.handleSubmit}>
<Tab key="account" tab="账户密码登录">
{
login.status === 'error' &&
{login.status === 'error' &&
login.type === 'account' &&
!login.submitting &&
this.renderMessage('账户或密码错误(admin/888888)')
}
this.renderMessage('账户或密码错误(admin/888888)')}
<UserName name="userName" placeholder="admin/user" />
<Password name="password" placeholder="888888/123456" />
</Tab>
<Tab key="mobile" tab="手机号登录">
{
login.status === 'error' &&
{login.status === 'error' &&
login.type === 'mobile' &&
!login.submitting &&
this.renderMessage('验证码错误')
}
this.renderMessage('验证码错误')}
<Mobile name="mobile" />
<Captcha name="captcha" />
</Tab>
<div>
<Checkbox checked={this.state.autoLogin} onChange={this.changeAutoLogin}>自动登录</Checkbox>
<a style={{ float: 'right' }} href="">忘记密码</a>
<Checkbox checked={this.state.autoLogin} onChange={this.changeAutoLogin}>
自动登录
</Checkbox>
<a style={{ float: 'right' }} href="">
忘记密码
</a>
</div>
<Submit loading={submitting}>登录</Submit>
<div className={styles.other}>
......@@ -86,7 +80,9 @@ export default class LoginPage extends Component {
<Icon className={styles.icon} type="alipay-circle" />
<Icon className={styles.icon} type="taobao-circle" />
<Icon className={styles.icon} type="weibo-circle" />
<Link className={styles.register} to="/user/register">注册账户</Link>
<Link className={styles.register} to="/user/register">
注册账户
</Link>
</div>
</Login>
</div>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.main {
width: 368px;
......@@ -10,7 +10,7 @@
margin-left: 16px;
vertical-align: middle;
cursor: pointer;
transition: color .3s;
transition: color 0.3s;
&:hover {
color: @primary-color;
......
......@@ -37,12 +37,14 @@ export default class Register extends Component {
componentWillReceiveProps(nextProps) {
const account = this.props.form.getFieldValue('mail');
if (nextProps.register.status === 'ok') {
this.props.dispatch(routerRedux.push({
this.props.dispatch(
routerRedux.push({
pathname: '/user/register-result',
state: {
account,
},
}));
})
);
}
}
......@@ -74,7 +76,7 @@ export default class Register extends Component {
return 'poor';
};
handleSubmit = (e) => {
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields({ force: true }, (err, values) => {
if (!err) {
......@@ -89,7 +91,7 @@ export default class Register extends Component {
});
};
handleConfirmBlur = (e) => {
handleConfirmBlur = e => {
const { value } = e.target;
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
};
......@@ -131,7 +133,7 @@ export default class Register extends Component {
}
};
changePrefix = (value) => {
changePrefix = value => {
this.setState({
prefix: value,
});
......@@ -197,13 +199,7 @@ export default class Register extends Component {
validator: this.checkPassword,
},
],
})(
<Input
size="large"
type="password"
placeholder="至少6位密码,区分大小写"
/>
)}
})(<Input size="large" type="password" placeholder="至少6位密码,区分大小写" />)}
</Popover>
</FormItem>
<FormItem>
......@@ -241,13 +237,7 @@ export default class Register extends Component {
message: '手机号格式错误!',
},
],
})(
<Input
size="large"
style={{ width: '80%' }}
placeholder="11位手机号"
/>
)}
})(<Input size="large" style={{ width: '80%' }} placeholder="11位手机号" />)}
</InputGroup>
</FormItem>
<FormItem>
......
@import "~antd/lib/style/themes/default.less";
@import '~antd/lib/style/themes/default.less';
.main {
width: 368px;
......
......@@ -6,8 +6,14 @@ import styles from './RegisterResult.less';
const actions = (
<div className={styles.actions}>
<a href=""><Button size="large" type="primary">查看邮箱</Button></a>
<Link to="/"><Button size="large">返回首页</Button></Link>
<a href="">
<Button size="large" type="primary">
查看邮箱
</Button>
</a>
<Link to="/">
<Button size="large">返回首页</Button>
</Link>
</div>
);
......
......@@ -67,13 +67,13 @@ export default function request(url, options) {
return fetch(url, newOptions)
.then(checkStatus)
.then((response) => {
.then(response => {
if (newOptions.method === 'DELETE' || response.status === 204) {
return response.text();
}
return response.json();
})
.catch((e) => {
.catch(e => {
const { dispatch } = store;
const status = e.name;
if (status === 401) {
......
......@@ -27,9 +27,9 @@ export function getTimeDistance(type) {
day -= 1;
}
const beginTime = now.getTime() - (day * oneDay);
const beginTime = now.getTime() - day * oneDay;
return [moment(beginTime), moment(beginTime + ((7 * oneDay) - 1000))];
return [moment(beginTime), moment(beginTime + (7 * oneDay - 1000))];
}
if (type === 'month') {
......@@ -39,7 +39,10 @@ export function getTimeDistance(type) {
const nextYear = nextDate.year();
const nextMonth = nextDate.month();
return [moment(`${year}-${fixedZero(month + 1)}-01 00:00:00`), moment(moment(`${nextYear}-${fixedZero(nextMonth + 1)}-01 00:00:00`).valueOf() - 1000)];
return [
moment(`${year}-${fixedZero(month + 1)}-01 00:00:00`),
moment(moment(`${nextYear}-${fixedZero(nextMonth + 1)}-01 00:00:00`).valueOf() - 1000),
];
}
if (type === 'year') {
......@@ -51,7 +54,7 @@ export function getTimeDistance(type) {
export function getPlainNode(nodeList, parentPath = '') {
const arr = [];
nodeList.forEach((node) => {
nodeList.forEach(node => {
const item = node;
item.path = `${parentPath}/${item.path || ''}`.replace(/\/+/g, '/');
item.exact = true;
......@@ -70,14 +73,11 @@ export function getPlainNode(nodeList, parentPath = '') {
export function digitUppercase(n) {
const fraction = ['', ''];
const digit = ['', '', '', '', '', '', '', '', '', ''];
const unit = [
['', '', '亿'],
['', '', '', ''],
];
const unit = [['', '', '亿'], ['', '', '', '']];
let num = Math.abs(n);
let s = '';
fraction.forEach((item, index) => {
s += (digit[Math.floor(num * 10 * (10 ** index)) % 10] + item).replace(/零./, '');
s += (digit[Math.floor(num * 10 * 10 ** index) % 10] + item).replace(/零./, '');
});
s = s || '';
num = Math.floor(num);
......@@ -90,10 +90,12 @@ export function digitUppercase(n) {
s = p.replace(/(零.)*零$/, '').replace(/^$/, '') + unit[0][i] + s;
}
return s.replace(/(零.)*零元/, '').replace(/(零.)+/g, '').replace(/^整$/, '零元整');
return s
.replace(/(零.)*零元/, '')
.replace(/(零.)+/g, '')
.replace(/^整$/, '零元整');
}
function getRelation(str1, str2) {
if (str1 === str2) {
console.warn('Two path are equal!'); // eslint-disable-line
......@@ -131,14 +133,15 @@ function getRenderArr(routes) {
* @param {routerData} routerData
*/
export function getRoutes(path, routerData) {
let routes = Object.keys(routerData).filter(routePath =>
routePath.indexOf(path) === 0 && routePath !== path);
let routes = Object.keys(routerData).filter(
routePath => routePath.indexOf(path) === 0 && routePath !== path
);
// Replace path to '' eg. path='user' /user/name => name
routes = routes.map(item => item.replace(path, ''));
// Get the route to be rendered to remove the deep rendering
const renderArr = getRenderArr(routes);
// Conversion and stitching parameters
const renderRoutes = renderArr.map((item) => {
const renderRoutes = renderArr.map(item => {
const exact = !routes.some(route => route !== item && getRelation(route, item) === 1);
return {
exact,
......@@ -150,7 +153,6 @@ export function getRoutes(path, routerData) {
return renderRoutes;
}
/* eslint no-useless-escape:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/g;
......
......@@ -38,7 +38,7 @@
zoom: 1;
&:before,
&:after {
content: " ";
content: ' ';
display: table;
}
&:after {
......
......@@ -7,7 +7,7 @@ const startServer = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['s
env,
});
startServer.stderr.on('data', (data) => {
startServer.stderr.on('data', data => {
// eslint-disable-next-line
console.log(data);
});
......@@ -18,11 +18,13 @@ startServer.on('exit', () => {
// eslint-disable-next-line
console.log('Starting development server for e2e tests...');
startServer.stdout.on('data', (data) => {
startServer.stdout.on('data', data => {
// eslint-disable-next-line
console.log(data.toString());
if (data.toString().indexOf('Compiled successfully') >= 0 ||
data.toString().indexOf('Compiled with warnings') >= 0) {
if (
data.toString().indexOf('Compiled successfully') >= 0 ||
data.toString().indexOf('Compiled with warnings') >= 0
) {
// eslint-disable-next-line
console.log('Development server is started, ready to run tests.');
const testCmd = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['test'], {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment