Unverified Commit 6ef0c23f authored by 陈帅's avatar 陈帅 Committed by GitHub

fix all eslint-error (#28)

* run eslint fix

* import sorted

* fix some warning

* fix all eslint-error

* fix all eslint-error

* fix all eslint error

* remove .eslintcache
parent 8ae5c0b9
/functions/mock/** /functions/mock/**
/scripts /scripts
/config /config
**/node_modules/**
_scripts
\ No newline at end of file
const fabric = require('@umijs/fabric');
module.exports = { module.exports = {
parser: 'babel-eslint', ...fabric.default,
extends: ['airbnb', 'prettier', 'plugin:compat/recommended'], rules: {
env: { ...fabric.default.rules,
browser: true, '@typescript-eslint/camelcase': 0,
node: true, '@typescript-eslint/class-name-casing': 0,
es6: true,
mocha: true,
jest: true,
jasmine: true,
}, },
globals: { globals: {
APP_TYPE: true, ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
page: true, page: true,
}, },
rules: {
'react/jsx-filename-extension': [1, { extensions: ['.js'] }],
'react/jsx-wrap-multilines': 0,
'react/prop-types': 0,
'react/forbid-prop-types': 0,
'react/jsx-one-expression-per-line': 0,
'import/no-unresolved': [2, { ignore: ['^@/', '^umi/'] }],
'import/no-extraneous-dependencies': [
2,
{
optionalDependencies: true,
devDependencies: ['**/tests/**.js', '/mock/**.js', '**/**.test.js'],
},
],
'jsx-a11y/no-noninteractive-element-interactions': 0,
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/no-static-element-interactions': 0,
'jsx-a11y/anchor-is-valid': 0,
'linebreak-style': 0,
},
settings: {
polyfills: ['fetch', 'promises', 'url'],
},
}; };
...@@ -36,3 +36,5 @@ functions/mock ...@@ -36,3 +36,5 @@ functions/mock
# screenshot # screenshot
screenshot screenshot
.firebase .firebase
.eslintcache
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"proseWrap": "never",
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
]
}
\ No newline at end of file
const fabric = require('@umijs/fabric');
module.exports = {
...fabric.prettier,
};
const fabric = require('@umijs/fabric');
module.exports = {
...fabric.stylelint,
};
{
"extends": [
"stylelint-config-standard",
"stylelint-config-css-modules",
"stylelint-config-rational-order",
"stylelint-config-prettier"
],
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
"rules": {
"no-descending-specificity": null,
"plugin/declaration-block-no-ignored-properties": true
}
}
...@@ -11,16 +11,21 @@ ...@@ -11,16 +11,21 @@
"url": "https://github.com/umijs/umi-blocks/ant-design-pro/accountcenter" "url": "https://github.com/umijs/umi-blocks/ant-design-pro/accountcenter"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3", "antd": "^3.16.3",
"classnames": "^2.2.6",
"dva": "^2.4.0", "dva": "^2.4.0",
"moment": "^2.24.0",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"react": "^16.6.3", "react": "^16.6.3",
"react-router": "^5.0.1",
"redux": "^4.0.1",
"umi-request": "^1.0.0" "umi-request": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"umi": "^2.6.9", "umi": "^2.6.9",
"umi-plugin-react": "^1.7.2", "umi-plugin-block-dev": "^1.0.0",
"umi-plugin-block-dev": "^1.0.0" "umi-plugin-react": "^1.7.2"
}, },
"license": "ISC", "license": "ISC",
"blockConfig": { "blockConfig": {
......
import { ListItemDataType } from './data'; import { ListItemDataType } from './data.d';
const titles = [ const titles = [
'Alipay', 'Alipay',
...@@ -21,69 +21,6 @@ const avatars = [ ...@@ -21,69 +21,6 @@ const avatars = [
'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', // Webpack 'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', // Webpack
]; ];
const getNotice = [
{
id: 'xxx1',
title: titles[0],
logo: avatars[0],
description: '那是一种内在的东西,他们到达不了,也无法触及的',
updatedAt: new Date(),
member: '科学搬砖组',
href: '',
memberLink: '',
},
{
id: 'xxx2',
title: titles[1],
logo: avatars[1],
description: '希望是一个好东西,也许是最好的,好东西是不会消亡的',
updatedAt: new Date('2017-07-24'),
member: '全组都是吴彦祖',
href: '',
memberLink: '',
},
{
id: 'xxx3',
title: titles[2],
logo: avatars[2],
description: '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
updatedAt: new Date(),
member: '中二少女团',
href: '',
memberLink: '',
},
{
id: 'xxx4',
title: titles[3],
logo: avatars[3],
description: '那时候我只会想自己想要什么,从不想自己拥有什么',
updatedAt: new Date('2017-07-23'),
member: '程序员日常',
href: '',
memberLink: '',
},
{
id: 'xxx5',
title: titles[4],
logo: avatars[4],
description: '凛冬将至',
updatedAt: new Date('2017-07-23'),
member: '高逼格设计天团',
href: '',
memberLink: '',
},
{
id: 'xxx6',
title: titles[5],
logo: avatars[5],
description: '生命就像一盒巧克力,结果往往出人意料',
updatedAt: new Date('2017-07-23'),
member: '骗你来学计算机',
href: '',
memberLink: '',
},
];
const covers = [ const covers = [
'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png', 'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png',
'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png', 'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png',
...@@ -119,7 +56,7 @@ function fakeList(count: number): ListItemDataType[] { ...@@ -119,7 +56,7 @@ function fakeList(count: number): ListItemDataType[] {
owner: user[i % 10], owner: user[i % 10],
title: titles[i % 8], title: titles[i % 8],
avatar: avatars[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] as status: ['active', 'exception', 'normal'][i % 3] as
| 'normal' | 'normal'
| 'exception' | 'exception'
......
import { Avatar, Card, Dropdown, Icon, List, Menu, Tooltip } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { List, Card, Icon, Dropdown, Menu, Avatar, Tooltip } from 'antd';
import numeral from 'numeral';
import { connect } from 'dva'; import { connect } from 'dva';
import stylesApplications from './index.less'; import numeral from 'numeral';
import { ModalState } from '../../model'; import { ModalState } from '../../model';
import stylesApplications from './index.less';
export function formatWan(val: number) { export function formatWan(val: number) {
const v = val * 1; const v = val * 1;
......
import { Avatar } from 'antd';
import React from 'react'; import React from 'react';
import moment from 'moment'; import moment from 'moment';
import { Avatar } from 'antd';
import styles from './index.less'; import styles from './index.less';
export interface ApplicationsProps { export interface ApplicationsProps {
......
import { Icon, List, Tag } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { List, Icon, Tag } from 'antd';
import { connect } from 'dva'; import { connect } from 'dva';
import ArticleListContent from '../ArticleListContent'; import ArticleListContent from '../ArticleListContent';
import styles from './index.less'; import { ListItemDataType } from '../../data.d';
import { ModalState } from '../../model'; import { ModalState } from '../../model';
import { ListItemDataType } from '../../data'; import styles from './index.less';
@connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({ @connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({
list: BLOCK_NAME_CAMEL_CASE.list, list: BLOCK_NAME_CAMEL_CASE.list,
......
import { Avatar, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Tooltip, Avatar } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
...@@ -19,10 +20,10 @@ export interface AvatarListProps { ...@@ -19,10 +20,10 @@ export interface AvatarListProps {
maxLength?: number; maxLength?: number;
excessItemsStyle?: React.CSSProperties; excessItemsStyle?: React.CSSProperties;
style?: React.CSSProperties; style?: React.CSSProperties;
children: React.ReactElement<AvatarItemProps> | Array<React.ReactElement<AvatarItemProps>>; children: React.ReactElement<AvatarItemProps> | React.ReactElement<AvatarItemProps>[];
} }
const avatarSizeToClassName = (size?: SizeType) => const avatarSizeToClassName = (size?: SizeType | 'mini') =>
classNames(styles.avatarItem, { classNames(styles.avatarItem, {
[styles.avatarItemLarge]: size === 'large', [styles.avatarItemLarge]: size === 'large',
[styles.avatarItemSmall]: size === 'small', [styles.avatarItemSmall]: size === 'small',
...@@ -54,9 +55,7 @@ const AvatarList: React.SFC<AvatarListProps> & { Item: typeof Item } = ({ ...@@ -54,9 +55,7 @@ const AvatarList: React.SFC<AvatarListProps> & { Item: typeof Item } = ({
}) => { }) => {
const numOfChildren = React.Children.count(children); const numOfChildren = React.Children.count(children);
const numToShow = maxLength >= numOfChildren ? numOfChildren : maxLength; const numToShow = maxLength >= numOfChildren ? numOfChildren : maxLength;
const childrenArray = React.Children.toArray(children) as Array< const childrenArray = React.Children.toArray(children) as React.ReactElement<AvatarItemProps>[];
React.ReactElement<AvatarItemProps>
>;
const childrenWithProps = childrenArray.slice(0, numToShow).map(child => const childrenWithProps = childrenArray.slice(0, numToShow).map(child =>
React.cloneElement(child, { React.cloneElement(child, {
size, size,
......
import { Card, List } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { List, Card } from 'antd';
import moment from 'moment';
import { connect } from 'dva'; import { connect } from 'dva';
import moment from 'moment';
import AvatarList from '../AvatarList'; import AvatarList from '../AvatarList';
import styles from './index.less'; import { ListItemDataType } from '../../data.d';
import { ModalState } from '../../model'; import { ModalState } from '../../model';
import { ListItemDataType } from '../../data'; import styles from './index.less';
@connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({ @connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({
list: BLOCK_NAME_CAMEL_CASE.list, list: BLOCK_NAME_CAMEL_CASE.list,
......
export interface ITag { export interface TagType {
key: string; key: string;
label: string; label: string;
} }
export interface IProvince { export interface ProvinceType {
label: string; label: string;
key: string; key: string;
} }
export interface ICity { export interface CityType {
label: string; label: string;
key: string; key: string;
} }
export interface IGeographic { export interface GeographicType {
province: IProvince; province: ProvinceType;
city: ICity; city: CityType;
} }
export interface INotice { export interface NoticeType {
id: string; id: string;
title: string; title: string;
logo: string; logo: string;
...@@ -33,16 +33,16 @@ export interface CurrentUser { ...@@ -33,16 +33,16 @@ export interface CurrentUser {
name: string; name: string;
avatar: string; avatar: string;
userid: string; userid: string;
notice: INotice[]; notice: NoticeType[];
email: string; email: string;
signature: string; signature: string;
title: string; title: string;
group: string; group: string;
tags: ITag[]; tags: TagType[];
notifyCount: number; notifyCount: number;
unreadCount: number; unreadCount: number;
country: string; country: string;
geographic: IGeographic; geographic: GeographicType;
address: string; address: string;
phone: string; phone: string;
} }
......
import { Avatar, Card, Col, Divider, Icon, Input, Row, Tag } from 'antd';
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import Link from 'umi/link';
import { GridContent } from '@ant-design/pro-layout'; import { GridContent } from '@ant-design/pro-layout';
import Link from 'umi/link';
import { RouteChildrenProps } from 'react-router'; import { RouteChildrenProps } from 'react-router';
import { Card, Row, Col, Icon, Avatar, Tag, Divider, Input } from 'antd'; import { connect } from 'dva';
import styles from './Center.less';
import { ITag, CurrentUser } from './data';
import { ModalState } from './model'; import { ModalState } from './model';
import Projects from './components/Projects';
import Articles from './components/Articles'; import Articles from './components/Articles';
import Applications from './components/Applications'; import Applications from './components/Applications';
import Projects from './components/Projects'; import { CurrentUser, TagType } from './data.d';
import styles from './Center.less';
const operationTabList = [ const operationTabList = [
{ {
...@@ -45,7 +46,7 @@ interface BLOCK_NAME_CAMEL_CASEProps extends RouteChildrenProps { ...@@ -45,7 +46,7 @@ interface BLOCK_NAME_CAMEL_CASEProps extends RouteChildrenProps {
currentUserLoading: boolean; currentUserLoading: boolean;
} }
interface BLOCK_NAME_CAMEL_CASEState { interface BLOCK_NAME_CAMEL_CASEState {
newTags: ITag[]; newTags: TagType[];
tabKey: 'articles' | 'applications' | 'projects'; tabKey: 'articles' | 'applications' | 'projects';
inputVisible: boolean; inputVisible: boolean;
inputValue: string; inputValue: string;
...@@ -56,7 +57,7 @@ interface BLOCK_NAME_CAMEL_CASEState { ...@@ -56,7 +57,7 @@ interface BLOCK_NAME_CAMEL_CASEState {
loading, loading,
BLOCK_NAME_CAMEL_CASE, BLOCK_NAME_CAMEL_CASE,
}: { }: {
loading: { effects: any }; loading: { effects: { [key: string]: boolean } };
BLOCK_NAME_CAMEL_CASE: ModalState; BLOCK_NAME_CAMEL_CASE: ModalState;
}) => ({ }) => ({
currentUser: BLOCK_NAME_CAMEL_CASE.currentUser, currentUser: BLOCK_NAME_CAMEL_CASE.currentUser,
...@@ -92,7 +93,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent< ...@@ -92,7 +93,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
tabKey: 'articles', tabKey: 'articles',
}; };
input: Input | null | undefined; public input: Input | null | undefined = undefined;
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
...@@ -138,6 +139,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent< ...@@ -138,6 +139,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
inputValue: '', inputValue: '',
}); });
}; };
renderChildrenByTabKey = (tabKey: BLOCK_NAME_CAMEL_CASEState['tabKey']) => { renderChildrenByTabKey = (tabKey: BLOCK_NAME_CAMEL_CASEState['tabKey']) => {
if (tabKey === 'projects') { if (tabKey === 'projects') {
return <Projects />; return <Projects />;
...@@ -150,6 +152,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent< ...@@ -150,6 +152,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
} }
return null; return null;
}; };
render() { render() {
const { newTags, inputVisible, inputValue, tabKey } = this.state; const { newTags, inputVisible, inputValue, tabKey } = this.state;
const { currentUser, currentUserLoading } = this.props; const { currentUser, currentUserLoading } = this.props;
...@@ -184,9 +187,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent< ...@@ -184,9 +187,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
<Divider dashed /> <Divider dashed />
<div className={styles.tags}> <div className={styles.tags}>
<div className={styles.tagsTitle}>标签</div> <div className={styles.tagsTitle}>标签</div>
{currentUser.tags.concat(newTags).map(item => { {currentUser.tags.concat(newTags).map(item => (
return <Tag key={item.key}>{item.label}</Tag>; <Tag key={item.key}>{item.label}</Tag>
})} ))}
{inputVisible && ( {inputVisible && (
<Input <Input
ref={ref => this.saveInputRef(ref)} ref={ref => this.saveInputRef(ref)}
......
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { CurrentUser, ListItemDataType } from './data.d';
import { queryCurrent, queryFakeList } from './service'; import { queryCurrent, queryFakeList } from './service';
import { CurrentUser, ListItemDataType } from './data';
export interface ModalState { export interface ModalState {
currentUser: Partial<CurrentUser>; currentUser: Partial<CurrentUser>;
list: ListItemDataType[]; list: ListItemDataType[];
} }
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
export type Effect = ( export type Effect = (
action: AnyAction, action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: ModalState) => T) => T }, effects: EffectsCommandMap & { select: <T>(func: (state: ModalState) => T) => T },
...@@ -56,13 +54,13 @@ const Model: ModelType = { ...@@ -56,13 +54,13 @@ const Model: ModelType = {
reducers: { reducers: {
saveCurrentUser(state, action) { saveCurrentUser(state, action) {
return { return {
...state!, ...(state as ModalState),
currentUser: action.payload || {}, currentUser: action.payload || {},
}; };
}, },
queryList(state, action) { queryList(state, action) {
return { return {
...state!, ...(state as ModalState),
list: action.payload, list: action.payload,
}; };
}, },
......
...@@ -5,7 +5,7 @@ export async function queryCurrent() { ...@@ -5,7 +5,7 @@ export async function queryCurrent() {
} }
export async function queryFakeList(params: { count: number }) { export async function queryFakeList(params: { count: number }) {
return request(`/api/fake_list`, { return request('/api/fake_list', {
params, params,
}); });
} }
...@@ -12,15 +12,18 @@ ...@@ -12,15 +12,18 @@
"dev": "umi dev" "dev": "umi dev"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3", "antd": "^3.16.3",
"dva": "^2.4.0", "dva": "^2.4.0",
"react": "^16.6.3", "react": "^16.6.3",
"umi-request": "^1.0.0" "redux": "^4.0.1",
"umi-request": "^1.0.0",
"umi-plugin-react": "^1.8.4",
"umi": "^2.6.9"
}, },
"devDependencies": { "devDependencies": {
"umi": "^2.6.9", "umi-plugin-block-dev": "^1.0.0"
"umi-plugin-block-dev": "^1.0.0",
"umi-plugin-react": "^1.3.0-beta.1"
}, },
"blockConfig": { "blockConfig": {
"specVersion": "0.1" "specVersion": "0.1"
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Select, Spin } from 'antd'; import { Select, Spin } from 'antd';
import { Dispatch } from 'redux';
import { connect } from 'dva'; import { connect } from 'dva';
import { CityType, ProvinceType } from '../data.d';
import styles from './GeographicView.less'; import styles from './GeographicView.less';
import { Dispatch } from 'redux';
import { ProvinceData, CityData } from '../data';
const { Option } = Select; const { Option } = Select;
interface SelectItem { interface SelectItem {
label: string; label: string;
key: string; key: string;
} }
const nullSlectItem: SelectItem = { const nullSelectItem: SelectItem = {
label: '', label: '',
key: '', key: '',
}; };
interface GeographicViewProps { interface GeographicViewProps {
dispatch?: Dispatch<any>; dispatch?: Dispatch<any>;
province?: ProvinceData[]; province?: ProvinceType[];
city?: CityData[]; city?: CityType[];
value?: { value?: {
province: SelectItem; province: SelectItem;
city: SelectItem; city: SelectItem;
...@@ -33,8 +35,8 @@ interface GeographicViewProps { ...@@ -33,8 +35,8 @@ interface GeographicViewProps {
loading, loading,
}: { }: {
BLOCK_NAME_CAMEL_CASE: { BLOCK_NAME_CAMEL_CASE: {
province: ProvinceData[]; province: ProvinceType[];
city: CityData[]; city: CityType[];
}; };
loading: any; loading: any;
}) => { }) => {
...@@ -85,7 +87,7 @@ class GeographicView extends Component<GeographicViewProps> { ...@@ -85,7 +87,7 @@ class GeographicView extends Component<GeographicViewProps> {
return []; return [];
}; };
getOption = (list: CityData[] | ProvinceData[]) => { getOption = (list: CityType[] | ProvinceType[]) => {
if (!list || list.length < 1) { if (!list || list.length < 1) {
return ( return (
<Option key={0} value={0}> <Option key={0} value={0}>
...@@ -93,9 +95,9 @@ class GeographicView extends Component<GeographicViewProps> { ...@@ -93,9 +95,9 @@ class GeographicView extends Component<GeographicViewProps> {
</Option> </Option>
); );
} }
return (list as CityData[]).map(item => ( return (list as CityType[]).map(item => (
<Option key={item.id} value={item.id}> <Option key={item.key} value={item.key}>
{item.name} {item.label}
</Option> </Option>
)); ));
}; };
...@@ -112,7 +114,7 @@ class GeographicView extends Component<GeographicViewProps> { ...@@ -112,7 +114,7 @@ class GeographicView extends Component<GeographicViewProps> {
if (onChange) { if (onChange) {
onChange({ onChange({
province: item, province: item,
city: nullSlectItem, city: nullSelectItem,
}); });
} }
}; };
...@@ -131,14 +133,14 @@ class GeographicView extends Component<GeographicViewProps> { ...@@ -131,14 +133,14 @@ class GeographicView extends Component<GeographicViewProps> {
const { value } = this.props; const { value } = this.props;
if (!value) { if (!value) {
return { return {
province: nullSlectItem, province: nullSelectItem,
city: nullSlectItem, city: nullSelectItem,
}; };
} }
const { province, city } = value; const { province, city } = value;
return { return {
province: province || nullSlectItem, province: province || nullSelectItem,
city: city || nullSlectItem, city: city || nullSelectItem,
}; };
} }
......
import React, { Fragment, PureComponent } from 'react'; import React, { Fragment, PureComponent } from 'react';
import { Input } from 'antd'; import { Input } from 'antd';
import styles from './PhoneView.less'; import styles from './PhoneView.less';
...@@ -20,15 +21,17 @@ class PhoneView extends PureComponent<PhoneViewProps> { ...@@ -20,15 +21,17 @@ class PhoneView extends PureComponent<PhoneViewProps> {
className={styles.area_code} className={styles.area_code}
value={values[0]} value={values[0]}
onChange={e => { onChange={e => {
// tslint:disable-next-line: no-unused-expression if (onChange) {
onChange && onChange(`${e.target.value}-${values[1]}`); onChange(`${e.target.value}-${values[1]}`);
}
}} }}
/> />
<Input <Input
className={styles.phone_number} className={styles.phone_number}
onChange={e => { onChange={e => {
// tslint:disable-next-line: no-unused-expression if (onChange) {
onChange && onChange(`${values[0]}-${e.target.value}`); onChange(`${values[0]}-${e.target.value}`);
}
}} }}
value={values[1]} value={values[1]}
/> />
......
import { Button, Form, Input, Select, Upload, message } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { Form, Input, Upload, Select, Button, message } from 'antd';
import { FormComponentProps } from 'antd/es/form'; import { FormComponentProps } from 'antd/es/form';
import { connect } from 'dva'; import { connect } from 'dva';
import styles from './BaseView.less'; import { CurrentUser } from '../data.d';
import GeographicView from './GeographicView'; import GeographicView from './GeographicView';
import PhoneView from './PhoneView'; import PhoneView from './PhoneView';
import { CurrentUser } from '../data'; import styles from './BaseView.less';
const FormItem = Form.Item; const FormItem = Form.Item;
const { Option } = Select; const { Option } = Select;
...@@ -70,7 +72,8 @@ interface BaseViewProps extends FormComponentProps { ...@@ -70,7 +72,8 @@ interface BaseViewProps extends FormComponentProps {
currentUser: BLOCK_NAME_CAMEL_CASE.currentUser, currentUser: BLOCK_NAME_CAMEL_CASE.currentUser,
})) }))
class BaseView extends Component<BaseViewProps> { class BaseView extends Component<BaseViewProps> {
view: HTMLDivElement | undefined; view: HTMLDivElement | undefined = undefined;
componentDidMount() { componentDidMount() {
this.setBaseInfo(); this.setBaseInfo();
} }
...@@ -102,10 +105,10 @@ class BaseView extends Component<BaseViewProps> { ...@@ -102,10 +105,10 @@ class BaseView extends Component<BaseViewProps> {
this.view = ref; this.view = ref;
}; };
handlerSubmit = (event: Event) => { handlerSubmit = (event: React.MouseEvent) => {
event.preventDefault(); event.preventDefault();
const { form } = this.props; const { form } = this.props;
form.validateFields((err, values) => { form.validateFields(err => {
if (!err) { if (!err) {
message.success(formatMessage({ id: 'BLOCK_NAME.basic.update.success' })); message.success(formatMessage({ id: 'BLOCK_NAME.basic.update.success' }));
} }
......
import React, { Component, Fragment } from 'react'; import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { Icon, List } from 'antd'; import { Icon, List } from 'antd';
import React, { Component, Fragment } from 'react';
class BindingView extends Component { class BindingView extends Component {
getData = () => [ getData = () => [
......
import { List, Switch } from 'antd';
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import { formatMessage } from 'umi-plugin-react/locale'; import { formatMessage } from 'umi-plugin-react/locale';
import { Switch, List } from 'antd';
type Unpacked<T> = T extends (infer U)[] ? U : T; type Unpacked<T> = T extends (infer U)[] ? U : T;
......
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { List } from 'antd'; import { List } from 'antd';
type Unpacked<T> = T extends (infer U)[] ? U : T; type Unpacked<T> = T extends (infer U)[] ? U : T;
......
export interface ITag { export interface TagType {
key: string; key: string;
label: string; label: string;
} }
export interface IProvince { export interface ProvinceType {
label: string; label: string;
key: string; key: string;
} }
export interface ICity { export interface CityType {
label: string; label: string;
key: string; key: string;
} }
export interface IGeographic { export interface GeographicType {
province: IProvince; province: ProvinceType;
city: ICity; city: CityType;
} }
export interface INotice { export interface NoticeType {
id: string; id: string;
title: string; title: string;
logo: string; logo: string;
...@@ -33,16 +33,16 @@ export interface CurrentUser { ...@@ -33,16 +33,16 @@ export interface CurrentUser {
name: string; name: string;
avatar: string; avatar: string;
userid: string; userid: string;
notice: INotice[]; notice: NoticeType[];
email: string; email: string;
signature: string; signature: string;
title: string; title: string;
group: string; group: string;
tags: ITag[]; tags: TagType[];
notifyCount: number; notifyCount: number;
unreadCount: number; unreadCount: number;
country: string; country: string;
geographic: IGeographic; geographic: GeographicType;
address: string; address: string;
phone: string; phone: string;
} }
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'dva';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import { FormattedMessage } from 'umi-plugin-react/locale'; import { FormattedMessage } from 'umi-plugin-react/locale';
import { GridContent } from '@ant-design/pro-layout'; import { GridContent } from '@ant-design/pro-layout';
import { Menu } from 'antd'; import { Menu } from 'antd';
import styles from './style.less'; import { connect } from 'dva';
import BaseView from './components/base'; import BaseView from './components/base';
import SecurityView from './components/security';
import BindingView from './components/binding'; import BindingView from './components/binding';
import { CurrentUser } from './data.d';
import NotificationView from './components/notification'; import NotificationView from './components/notification';
import { CurrentUser } from './data'; import SecurityView from './components/security';
import styles from './style.less';
const { Item } = Menu; const { Item } = Menu;
...@@ -33,7 +34,8 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component< ...@@ -33,7 +34,8 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
PAGE_NAME_UPPER_CAMEL_CASEProps, PAGE_NAME_UPPER_CAMEL_CASEProps,
PAGE_NAME_UPPER_CAMEL_CASEState PAGE_NAME_UPPER_CAMEL_CASEState
> { > {
main: HTMLDivElement | undefined; main: HTMLDivElement | undefined = undefined;
constructor(props: PAGE_NAME_UPPER_CAMEL_CASEProps) { constructor(props: PAGE_NAME_UPPER_CAMEL_CASEProps) {
super(props); super(props);
const menuMap = { const menuMap = {
......
import { query as queryUsers, queryCurrent, queryProvince, queryCity } from './service'; import { AnyAction, Reducer } from 'redux';
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva'; import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux'; import { CityType, CurrentUser, ProvinceType } from './data.d';
import { CurrentUser, City, Province } from './data'; import { queryCity, queryCurrent, queryProvince, query as queryUsers } from './service';
export interface ModalState { export interface ModalState {
currentUser?: Partial<CurrentUser>; currentUser?: Partial<CurrentUser>;
province?: Province[]; province?: ProvinceType[];
city?: City[]; city?: CityType[];
isLoading?: boolean; isLoading?: boolean;
} }
......
...@@ -12,22 +12,27 @@ ...@@ -12,22 +12,27 @@
"dev": "umi dev" "dev": "umi dev"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2", "@antv/data-set": "^0.10.2",
"antd": "^3.16.3", "antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0", "bizcharts": "^3.5.3-beta.0",
"bizcharts-plugin-slider": "^2.1.1-beta.1", "bizcharts-plugin-slider": "^2.1.1-beta.1",
"classnames": "^2.2.6",
"dva": "^2.4.0", "dva": "^2.4.0",
"@types/lodash.debounce": "^4.0.6",
"lodash.debounce": "^4.0.8",
"moment": "^2.22.2", "moment": "^2.22.2",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"react": "^16.6.3", "react": "^16.6.3",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"redux": "^4.0.1",
"umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0" "umi-request": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/numeral": "^0.0.25",
"umi": "^2.6.9", "umi": "^2.6.9",
"umi-plugin-block-dev": "^1.1.0", "umi-plugin-block-dev": "^1.1.0"
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
}, },
"blockConfig": { "blockConfig": {
"specVersion": "0.1" "specVersion": "0.1"
......
import moment from 'moment'; import moment from 'moment';
import { IVisitData, IRadarData, IAnalysisData } from './data'; import { AnalysisData, RadarData, VisitDataType } from './data.d';
// mock data // mock data
const visitData: IVisitData[] = []; const visitData: VisitDataType[] = [];
const beginDay = new Date().getTime(); const beginDay = new Date().getTime();
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5]; const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
...@@ -159,7 +159,7 @@ const radarOriginData = [ ...@@ -159,7 +159,7 @@ const radarOriginData = [
}, },
]; ];
const radarData: IRadarData[] = []; const radarData: RadarData[] = [];
const radarTitleMap = { const radarTitleMap = {
ref: '引用', ref: '引用',
koubei: '口碑', koubei: '口碑',
...@@ -179,7 +179,7 @@ radarOriginData.forEach(item => { ...@@ -179,7 +179,7 @@ radarOriginData.forEach(item => {
}); });
}); });
const getFakeChartData: IAnalysisData = { const getFakeChartData: AnalysisData = {
visitData, visitData,
visitData2, visitData2,
salesData, salesData,
......
import { Axis, Chart, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import Debounce from 'lodash-decorators/debounce'; import Debounce from 'lodash.debounce';
import Bind from 'lodash-decorators/bind';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from '../index.less'; import styles from '../index.less';
export interface IBarProps { export interface BarProps {
title: React.ReactNode; title: React.ReactNode;
color?: string; color?: string;
padding?: [number, number, number, number]; padding?: [number, number, number, number];
height?: number; height?: number;
data: Array<{ data: {
x: string; x: string;
y: number; y: number;
}>; }[];
forceFit?: boolean; forceFit?: boolean;
autoLabel?: boolean; autoLabel?: boolean;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
class Bar extends Component< class Bar extends Component<
IBarProps, BarProps,
{ {
autoHideXLabels: boolean; autoHideXLabels: boolean;
} }
...@@ -28,26 +28,12 @@ class Bar extends Component< ...@@ -28,26 +28,12 @@ class Bar extends Component<
state = { state = {
autoHideXLabels: false, autoHideXLabels: false,
}; };
root: HTMLDivElement | undefined;
node: HTMLDivElement | undefined;
componentDidMount() { root: HTMLDivElement | undefined = undefined;
window.addEventListener('resize', this.resize, { passive: true });
}
componentWillUnmount() { node: HTMLDivElement | undefined = undefined;
window.removeEventListener('resize', this.resize);
}
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleRef = (n: HTMLDivElement) => {
this.node = n;
};
@Bind() resize = Debounce(() => {
@Debounce(400)
resize() {
if (!this.node || !this.node.parentNode) { if (!this.node || !this.node.parentNode) {
return; return;
} }
...@@ -70,8 +56,24 @@ class Bar extends Component< ...@@ -70,8 +56,24 @@ class Bar extends Component<
autoHideXLabels: false, autoHideXLabels: false,
}); });
} }
}, 500);
componentDidMount() {
window.addEventListener('resize', this.resize, { passive: true });
}
componentWillUnmount() {
window.removeEventListener('resize', this.resize);
} }
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleRef = (n: HTMLDivElement) => {
this.node = n;
};
render() { render() {
const { const {
height = 1, height = 1,
...@@ -115,8 +117,8 @@ class Bar extends Component< ...@@ -115,8 +117,8 @@ class Bar extends Component<
<Axis <Axis
name="x" name="x"
title={false} title={false}
label={autoHideXLabels ? false : {}} label={autoHideXLabels ? undefined : {}}
tickLine={autoHideXLabels ? false : {}} tickLine={autoHideXLabels ? undefined : {}}
/> />
<Axis name="y" min={0} /> <Axis name="y" min={0} />
<Tooltip showTitle={false} crosshairs={false} /> <Tooltip showTitle={false} crosshairs={false} />
......
import React from 'react';
import { Card } from 'antd'; import { Card } from 'antd';
import classNames from 'classnames';
import { CardProps } from 'antd/es/card'; import { CardProps } from 'antd/es/card';
import React from 'react';
import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
type totalType = () => React.ReactNode; type totalType = () => React.ReactNode;
const renderTotal = (total?: number | totalType | React.ReactNode) => { const renderTotal = (total?: number | totalType | React.ReactNode) => {
if (!total) { if (!total) {
return; return null;
} }
let totalDom; let totalDom;
switch (typeof total) { switch (typeof total) {
...@@ -25,7 +24,7 @@ const renderTotal = (total?: number | totalType | React.ReactNode) => { ...@@ -25,7 +24,7 @@ const renderTotal = (total?: number | totalType | React.ReactNode) => {
return totalDom; return totalDom;
}; };
export interface IChartCardProps extends CardProps { export interface ChartCardProps extends CardProps {
title: React.ReactNode; title: React.ReactNode;
action?: React.ReactNode; action?: React.ReactNode;
total?: React.ReactNode | number | (() => React.ReactNode | number); total?: React.ReactNode | number | (() => React.ReactNode | number);
...@@ -35,7 +34,7 @@ export interface IChartCardProps extends CardProps { ...@@ -35,7 +34,7 @@ export interface IChartCardProps extends CardProps {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
class ChartCard extends React.Component<IChartCardProps> { class ChartCard extends React.Component<ChartCardProps> {
renderContent = () => { renderContent = () => {
const { contentHeight, title, avatar, action, total, footer, children, loading } = this.props; const { contentHeight, title, avatar, action, total, footer, children, loading } = this.props;
if (loading) { if (loading) {
......
import React from 'react'; import React from 'react';
import styles from './index.less'; import styles from './index.less';
export interface IFieldProps { export interface FieldProps {
label: React.ReactNode; label: React.ReactNode;
value: React.ReactNode; value: React.ReactNode;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
const Field: React.SFC<IFieldProps> = ({ label, value, ...rest }) => ( const Field: React.SFC<FieldProps> = ({ label, value, ...rest }) => (
<div className={styles.field} {...rest}> <div className={styles.field} {...rest}>
<span className={styles.label}>{label}</span> <span className={styles.label}>{label}</span>
<span className={styles.number}>{value}</span> <span className={styles.number}>{value}</span>
......
import { Axis, Chart, Coord, Geom, Guide, Shape } from 'bizcharts';
import React from 'react'; import React from 'react';
import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide; const { Arc, Html, Line } = Guide;
export interface IGaugeProps { export interface GaugeProps {
title: React.ReactNode; title: React.ReactNode;
color?: string; color?: string;
height?: number; height?: number;
...@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => { ...@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => {
} }
}; };
Shape.registerShape!('point', 'pointer', { if (Shape.registerShape) {
Shape.registerShape('point', 'pointer', {
drawShape(cfg: any, group: any) { drawShape(cfg: any, group: any) {
let point = cfg.points[0]; let point = cfg.points[0];
point = (this as any).parsePoint(point); point = (this as any).parsePoint(point);
...@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', { ...@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', {
}, },
}); });
}, },
}); });
}
class Gauge extends React.Component<IGaugeProps> { const Gauge: React.FC<GaugeProps> = props => {
render() {
const { const {
title, title,
height = 1, height = 1,
...@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> {
formatter = defaultFormatter, formatter = defaultFormatter,
color = '#2F9CFF', color = '#2F9CFF',
bgColor = '#F0F2F5', bgColor = '#F0F2F5',
} = this.props; } = props;
const cols = { const cols = {
value: { value: {
type: 'linear', type: 'linear',
...@@ -82,6 +84,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -82,6 +84,7 @@ class Gauge extends React.Component<IGaugeProps> {
nice: true, nice: true,
}, },
}; };
const data = [{ value: percent / 10 }];
const renderHtml = () => ` const renderHtml = () => `
<div style="width: 300px;text-align: center;font-size: 12px!important;"> <div style="width: 300px;text-align: center;font-size: 12px!important;">
<p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p> <p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
...@@ -89,7 +92,6 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -89,7 +92,6 @@ class Gauge extends React.Component<IGaugeProps> {
${(data[0].value * 10).toFixed(2)}% ${(data[0].value * 10).toFixed(2)}%
</p> </p>
</div>`; </div>`;
const data = [{ value: percent / 10 }];
const textStyle: { const textStyle: {
fontSize: number; fontSize: number;
fill: string; fill: string;
...@@ -99,6 +101,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -99,6 +101,7 @@ class Gauge extends React.Component<IGaugeProps> {
fill: 'rgba(0, 0, 0, 0.65)', fill: 'rgba(0, 0, 0, 0.65)',
textAlign: 'center', textAlign: 'center',
}; };
return ( return (
<Chart height={height} data={data} scale={cols} padding={[-16, 0, 16, 0]} forceFit={forceFit}> <Chart height={height} data={data} scale={cols} padding={[-16, 0, 16, 0]} forceFit={forceFit}>
<Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={0.8} /> <Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={0.8} />
...@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> {
label={{ label={{
offset: -12, offset: -12,
formatter, formatter,
textStyle: textStyle, textStyle,
}} }}
/> />
<Guide> <Guide>
...@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> {
/> />
</Chart> </Chart>
); );
} };
}
export default autoHeight()(Gauge); export default autoHeight()(Gauge);
import { Axis, Chart, Geom, Tooltip, AxisProps } from 'bizcharts';
import React from 'react'; import React from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from '../index.less'; import styles from '../index.less';
export interface IAxis { export interface MiniAreaProps {
title: any;
line: any;
gridAlign: any;
labels: any;
tickLine: any;
grid: any;
}
export interface IMiniAreaProps {
color?: string; color?: string;
height?: number; height?: number;
borderColor?: string; borderColor?: string;
line?: boolean; line?: boolean;
animate?: boolean; animate?: boolean;
xAxis?: IAxis; xAxis?: AxisProps;
forceFit?: boolean; forceFit?: boolean;
scale?: { x: any; y: any }; scale?: {
yAxis?: IAxis; x?: {
tickCount: number;
};
y?: {
tickCount: number;
};
};
yAxis?: Partial<AxisProps>;
borderWidth?: number; borderWidth?: number;
data: Array<{ data: {
x: number | string; x: number | string;
y: number; y: number;
}>; }[];
} }
class MiniArea extends React.Component<IMiniAreaProps> { const MiniArea: React.FC<MiniAreaProps> = props => {
render() {
const { const {
height = 1, height = 1,
data = [], data = [],
...@@ -43,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -43,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> {
xAxis, xAxis,
yAxis, yAxis,
animate = true, animate = true,
} = this.props; } = props;
const padding: [number, number, number, number] = [36, 5, 30, 5]; const padding: [number, number, number, number] = [36, 5, 30, 5];
...@@ -51,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -51,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> {
x: { x: {
type: 'cat', type: 'cat',
range: [0, 1], range: [0, 1],
...scale!.x, ...scale.x,
}, },
y: { y: {
min: 0, min: 0,
...scale!.y, ...scale.y,
}, },
}; };
...@@ -84,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -84,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> {
<Axis <Axis
key="axis-x" key="axis-x"
name="x" name="x"
label={false} label={undefined}
line={false} line={undefined}
tickLine={false} tickLine={undefined}
grid={false} grid={undefined}
{...xAxis} {...xAxis}
/> />
<Axis <Axis
key="axis-y" key="axis-y"
name="y" name="y"
label={false} label={undefined}
line={false} line={undefined}
tickLine={false} tickLine={undefined}
grid={false} grid={undefined}
{...yAxis} {...yAxis}
/> />
<Tooltip showTitle={false} crosshairs={false} /> <Tooltip showTitle={false} crosshairs={false} />
...@@ -127,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -127,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> {
</div> </div>
</div> </div>
); );
} };
}
export default autoHeight()(MiniArea); export default autoHeight()(MiniArea);
import { Chart, Geom, Tooltip } from 'bizcharts';
import React from 'react'; import React from 'react';
import { Chart, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from '../index.less'; import styles from '../index.less';
export interface IMiniBarProps { export interface MiniBarProps {
color?: string; color?: string;
height?: number; height?: number;
data: Array<{ data: {
x: number | string; x: number | string;
y: number; y: number;
}>; }[];
forceFit?: boolean; forceFit?: boolean;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
class MiniBar extends React.Component<IMiniBarProps> { const MiniBar: React.FC<MiniBarProps> = props => {
render() { const { height = 0, forceFit = true, color = '#1890FF', data = [] } = props;
const { height = 0, forceFit = true, color = '#1890FF', data = [] } = this.props;
const scale = { const scale = {
x: { x: {
...@@ -43,19 +43,12 @@ class MiniBar extends React.Component<IMiniBarProps> { ...@@ -43,19 +43,12 @@ class MiniBar extends React.Component<IMiniBarProps> {
return ( return (
<div className={styles.miniChart} style={{ height }}> <div className={styles.miniChart} style={{ height }}>
<div className={styles.chartContent}> <div className={styles.chartContent}>
<Chart <Chart scale={scale} height={chartHeight} forceFit={forceFit} data={data} padding={padding}>
scale={scale}
height={chartHeight}
forceFit={forceFit}
data={data}
padding={padding}
>
<Tooltip showTitle={false} crosshairs={false} /> <Tooltip showTitle={false} crosshairs={false} />
<Geom type="interval" position="x*y" color={color} tooltip={tooltip} /> <Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
</Chart> </Chart>
</div> </div>
</div> </div>
); );
} };
}
export default autoHeight()(MiniBar); export default autoHeight()(MiniBar);
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
import { Tooltip } from 'antd'; import { Tooltip } from 'antd';
import styles from './index.less'; import styles from './index.less';
export interface IMiniProgressProps { export interface MiniProgressProps {
target: number; target: number;
targetLabel?: string; targetLabel?: string;
color?: string; color?: string;
...@@ -11,14 +11,13 @@ export interface IMiniProgressProps { ...@@ -11,14 +11,13 @@ export interface IMiniProgressProps {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
const MiniProgress: React.SFC<IMiniProgressProps> = ({ const MiniProgress: React.SFC<MiniProgressProps> = ({
targetLabel, targetLabel,
target, target,
color = 'rgb(19, 194, 194)', color = 'rgb(19, 194, 194)',
strokeWidth, strokeWidth,
percent, percent,
}) => { }) => (
return (
<div className={styles.miniProgress}> <div className={styles.miniProgress}>
<Tooltip title={targetLabel}> <Tooltip title={targetLabel}>
<div className={styles.target} style={{ left: target ? `${target}%` : undefined }}> <div className={styles.target} style={{ left: target ? `${target}%` : undefined }}>
...@@ -37,7 +36,6 @@ const MiniProgress: React.SFC<IMiniProgressProps> = ({ ...@@ -37,7 +36,6 @@ const MiniProgress: React.SFC<IMiniProgressProps> = ({
/> />
</div> </div>
</div> </div>
); );
};
export default MiniProgress; export default MiniProgress;
import { Chart, Coord, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set'; import { DataView } from '@antv/data-set';
import Debounce from 'lodash.debounce';
import { Divider } from 'antd'; import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext'; import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce'; import classNames from 'classnames';
import Bind from 'lodash-decorators/bind';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
export interface IPieProps {
export interface PieProps {
animate?: boolean; animate?: boolean;
color?: string; color?: string;
colors?: string[]; colors?: string[];
...@@ -19,10 +19,10 @@ export interface IPieProps { ...@@ -19,10 +19,10 @@ export interface IPieProps {
hasLegend?: boolean; hasLegend?: boolean;
padding?: [number, number, number, number]; padding?: [number, number, number, number];
percent?: number; percent?: number;
data?: Array<{ data?: {
x: string | string; x: string | string;
y: number; y: number;
}>; }[];
inner?: number; inner?: number;
lineWidth?: number; lineWidth?: number;
forceFit?: boolean; forceFit?: boolean;
...@@ -34,19 +34,46 @@ export interface IPieProps { ...@@ -34,19 +34,46 @@ export interface IPieProps {
valueFormat?: (value: string) => string | React.ReactNode; valueFormat?: (value: string) => string | React.ReactNode;
subTitle?: React.ReactNode; subTitle?: React.ReactNode;
} }
interface IPieState { interface PieState {
legendData: Array<{ checked: boolean; x: string; color: string; percent: number; y: string }>; legendData: { checked: boolean; x: string; color: string; percent: number; y: string }[];
legendBlock: boolean; legendBlock: boolean;
} }
class Pie extends Component<IPieProps, IPieState> { class Pie extends Component<PieProps, PieState> {
state: IPieState = { state: PieState = {
legendData: [], legendData: [],
legendBlock: false, legendBlock: false,
}; };
requestRef: number | undefined; requestRef: number | undefined = undefined;
root!: HTMLDivElement;
chart: G2.Chart | undefined; root: HTMLDivElement | undefined = undefined;
chart: G2.Chart | undefined = undefined;
// for window resize auto responsive legend
resize = Debounce(() => {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}, 400);
componentDidMount() { componentDidMount() {
window.addEventListener( window.addEventListener(
...@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> {
); );
} }
componentDidUpdate(preProps: IPieProps) { componentDidUpdate(preProps: PieProps) {
const { data } = this.props; const { data } = this.props;
if (data !== preProps.data) { if (data !== preProps.data) {
// because of charts data create when rendered // because of charts data create when rendered
...@@ -90,7 +117,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -90,7 +117,7 @@ class Pie extends Component<IPieProps, IPieState> {
if (!this.chart) return; if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形 const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return; if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的 const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => { const legendData = items.map((item: { color: any; _origin: any }[]) => {
/* eslint no-underscore-dangle:0 */ /* eslint no-underscore-dangle:0 */
...@@ -104,6 +131,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -104,6 +131,7 @@ class Pie extends Component<IPieProps, IPieState> {
legendData, legendData,
}); });
}; };
handleRoot = (n: HTMLDivElement) => { handleRoot = (n: HTMLDivElement) => {
this.root = n; this.root = n;
}; };
...@@ -118,7 +146,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -118,7 +146,7 @@ class Pie extends Component<IPieProps, IPieState> {
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x); const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
if (this.chart) { if (this.chart) {
this.chart.filter('x', val => filteredLegendData.indexOf(val + '') > -1); this.chart.filter('x', val => filteredLegendData.indexOf(`${val}`) > -1);
} }
this.setState({ this.setState({
...@@ -126,33 +154,6 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -126,33 +154,6 @@ class Pie extends Component<IPieProps, IPieState> {
}); });
}; };
// for window resize auto responsive legend
@Bind()
@Debounce(300)
resize() {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}
render() { render() {
const { const {
valueFormat, valueFormat,
...@@ -216,11 +217,11 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -216,11 +217,11 @@ class Pie extends Component<IPieProps, IPieState> {
data = [ data = [
{ {
x: '占比', x: '占比',
y: parseFloat(percent + ''), y: parseFloat(`${percent}`),
}, },
{ {
x: '反比', x: '反比',
y: 100 - parseFloat(percent + ''), y: 100 - parseFloat(`${percent}`),
}, },
]; ];
} }
......
import { Chart, Coord, Geom, Shape, Tooltip } from 'bizcharts';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
import DataSet from '@antv/data-set'; import DataSet from '@antv/data-set';
import Debounce from 'lodash-decorators/debounce'; import Debounce from 'lodash.debounce';
import Bind from 'lodash-decorators/bind';
import classNames from 'classnames'; import classNames from 'classnames';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
...@@ -12,33 +12,36 @@ import styles from './index.less'; ...@@ -12,33 +12,36 @@ import styles from './index.less';
const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'; const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
export interface ITagCloudProps { export interface TagCloudProps {
data: Array<{ data: {
name: string; name: string;
value: number; value: number;
}>; }[];
height?: number; height?: number;
className?: string; className?: string;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
interface ITagCloudState { interface TagCloudState {
dv: any; dv: any;
height?: number; height?: number;
width: number; width: number;
} }
class TagCloud extends Component<ITagCloudProps, ITagCloudState> { class TagCloud extends Component<TagCloudProps, TagCloudState> {
state = { state = {
dv: null, dv: null,
height: 0, height: 0,
width: 0, width: 0,
}; };
isUnmount!: boolean;
requestRef!: number;
root: HTMLDivElement | undefined; isUnmount: boolean = false;
imageMask: HTMLImageElement | undefined;
requestRef: number = 0;
root: HTMLDivElement | undefined = undefined;
imageMask: HTMLImageElement | undefined = undefined;
componentDidMount() { componentDidMount() {
requestAnimationFrame(() => { requestAnimationFrame(() => {
...@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
window.addEventListener('resize', this.resize, { passive: true }); window.addEventListener('resize', this.resize, { passive: true });
} }
componentDidUpdate(preProps?: ITagCloudProps) { componentDidUpdate(preProps?: TagCloudProps) {
const { data } = this.props; const { data } = this.props;
if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) { if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) {
this.renderChart(this.props); this.renderChart(this.props);
} }
} }
componentWillUnmount() { componentWillUnmount() {
this.isUnmount = true; this.isUnmount = true;
window.cancelAnimationFrame(this.requestRef); window.cancelAnimationFrame(this.requestRef);
window.removeEventListener('resize', this.resize); window.removeEventListener('resize', this.resize);
} }
resize = () => { resize = () => {
this.requestRef = requestAnimationFrame(() => { this.requestRef = requestAnimationFrame(() => {
this.renderChart(this.props); this.renderChart(this.props);
}); });
}; };
saveRootRef = (node: HTMLDivElement) => { saveRootRef = (node: HTMLDivElement) => {
this.root = node; this.root = node;
}; };
...@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
origin?: any; origin?: any;
color?: any; color?: any;
}) { }) {
return Object.assign({}, cfg.style, { return {
...cfg.style,
fillOpacity: cfg.opacity, fillOpacity: cfg.opacity,
fontSize: cfg.origin._origin.size, fontSize: cfg.origin._origin.size,
rotate: cfg.origin._origin.rotate, rotate: cfg.origin._origin.rotate,
...@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
fontFamily: cfg.origin._origin.font, fontFamily: cfg.origin._origin.font,
fill: cfg.color, fill: cfg.color,
textBaseline: 'Alphabetic', textBaseline: 'Alphabetic',
}); };
} }
(Shape as any).registerShape('point', 'cloud', { (Shape as any).registerShape('point', 'cloud', {
...@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
) { ) {
const attrs = getTextAttrs(cfg); const attrs = getTextAttrs(cfg);
return container.addShape('text', { return container.addShape('text', {
attrs: Object.assign(attrs, { attrs: {
...attrs,
x: cfg.x, x: cfg.x,
y: cfg.y, y: cfg.y,
}), },
}); });
}, },
}); });
}; };
@Bind() renderChart = Debounce((nextProps: TagCloudProps) => {
@Debounce(500)
renderChart(nextProps: ITagCloudProps) {
// const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C']; // const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
const { data, height } = nextProps || this.props; const { data, height } = nextProps || this.props;
...@@ -134,8 +140,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -134,8 +140,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
return 0; return 0;
}, },
fontSize(d: { value: number }) { fontSize(d: { value: number }) {
// eslint-disable-next-line const size = ((d.value - min) / (max - min)) ** 2;
return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5; return size * (17.5 - 5) + 5;
}, },
}); });
...@@ -159,7 +165,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -159,7 +165,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
} else { } else {
onload(); onload();
} }
} }, 500);
render() { render() {
const { className, height } = this.props; const { className, height } = this.props;
......
import React from 'react'; import { Axis, Chart, Geom, Legend, Tooltip } from 'bizcharts';
import { Chart, Tooltip, Geom, Legend, Axis } from 'bizcharts';
import DataSet from '@antv/data-set'; import DataSet from '@antv/data-set';
import React from 'react';
import Slider from 'bizcharts-plugin-slider'; import Slider from 'bizcharts-plugin-slider';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
export interface ITimelineChartProps { export interface TimelineChartProps {
data: Array<{ data: {
x: number; x: number;
y1: number; y1: number;
y2: number; y2: number;
}>; }[];
title?: string; title?: string;
titleMap: { y1: string; y2: string }; titleMap: { y1: string; y2: string };
padding?: [number, number, number, number]; padding?: [number, number, number, number];
...@@ -19,8 +20,7 @@ export interface ITimelineChartProps { ...@@ -19,8 +20,7 @@ export interface ITimelineChartProps {
borderWidth?: number; borderWidth?: number;
} }
class TimelineChart extends React.Component<ITimelineChartProps> { const TimelineChart: React.FC<TimelineChartProps> = props => {
render() {
const { const {
title, title,
height = 400, height = 400,
...@@ -31,7 +31,7 @@ class TimelineChart extends React.Component<ITimelineChartProps> { ...@@ -31,7 +31,7 @@ class TimelineChart extends React.Component<ITimelineChartProps> {
}, },
borderWidth = 2, borderWidth = 2,
data: sourceData, data: sourceData,
} = this.props; } = props;
const data = Array.isArray(sourceData) ? sourceData : [{ x: 0, y1: 0, y2: 0 }]; const data = Array.isArray(sourceData) ? sourceData : [{ x: 0, y1: 0, y2: 0 }];
...@@ -127,7 +127,6 @@ class TimelineChart extends React.Component<ITimelineChartProps> { ...@@ -127,7 +127,6 @@ class TimelineChart extends React.Component<ITimelineChartProps> {
</div> </div>
</div> </div>
); );
} };
}
export default autoHeight()(TimelineChart); export default autoHeight()(TimelineChart);
import React, { Component } from 'react'; import React, { Component } from 'react';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
...@@ -6,7 +7,7 @@ import styles from './index.less'; ...@@ -6,7 +7,7 @@ import styles from './index.less';
/* eslint no-mixed-operators: 0 */ /* eslint no-mixed-operators: 0 */
// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90 // riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
export interface IWaterWaveProps { export interface WaterWaveProps {
title: React.ReactNode; title: React.ReactNode;
color?: string; color?: string;
height?: number; height?: number;
...@@ -14,13 +15,16 @@ export interface IWaterWaveProps { ...@@ -14,13 +15,16 @@ export interface IWaterWaveProps {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
class WaterWave extends Component<IWaterWaveProps> { class WaterWave extends Component<WaterWaveProps> {
state = { state = {
radio: 1, radio: 1,
}; };
timer: number = 0; timer: number = 0;
root: HTMLDivElement | undefined | null;
node: HTMLCanvasElement | undefined | null; root: HTMLDivElement | undefined | null = null;
node: HTMLCanvasElement | undefined | null = null;
componentDidMount() { componentDidMount() {
this.renderChart(); this.renderChart();
...@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> {
); );
} }
componentDidUpdate(props: IWaterWaveProps) { componentDidUpdate(props: WaterWaveProps) {
const { percent } = this.props; const { percent } = this.props;
if (props.percent !== percent) { if (props.percent !== percent) {
// 不加这个会造成绘制缓慢 // 不加这个会造成绘制缓慢
...@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> {
}); });
} }
}; };
renderChart(type?: string) { renderChart(type?: string) {
const { percent, color = '#1890FF' } = this.props; const { percent, color = '#1890FF' } = this.props;
const data = percent / 100; const data = percent / 100;
...@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> {
} }
render(); render();
} }
render() { render() {
const { radio } = this.state; const { radio } = this.state;
const { percent, title, height = 1 } = this.props; const { percent, title, height = 1 } = this.props;
......
...@@ -6,15 +6,16 @@ export type IReactComponent<P = any> = ...@@ -6,15 +6,16 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>; | React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) { function computeHeight(node: HTMLDivElement) {
node.style.height = '100%'; const { style } = node;
const totalHeight = parseInt(getComputedStyle(node).height + '', 10); style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding = const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) + parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10); parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding; return totalHeight - padding;
} }
function getAutoHeight(n: HTMLDivElement) { function getAutoHeight(n: HTMLDivElement | undefined) {
if (!n) { if (!n) {
return 0; return 0;
} }
...@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) { ...@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) {
return height; return height;
} }
interface IAutoHeightProps { interface AutoHeightProps {
height?: number; height?: number;
} }
function autoHeight() { function autoHeight() {
return function<P extends IAutoHeightProps>( return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>, WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> { ): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> { class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = { state = {
computedHeight: 0, computedHeight: 0,
}; };
root!: HTMLDivElement;
root: HTMLDivElement | undefined = undefined;
componentDidMount() { componentDidMount() {
const { height } = this.props; const { height } = this.props;
if (!height) { if (!height) {
let h = getAutoHeight(this.root); let h = getAutoHeight(this.root);
// eslint-disable-next-line
this.setState({ computedHeight: h }); this.setState({ computedHeight: h });
if (h < 1) { if (h < 1) {
h = getAutoHeight(this.root); h = getAutoHeight(this.root);
...@@ -55,9 +57,11 @@ function autoHeight() { ...@@ -55,9 +57,11 @@ function autoHeight() {
} }
} }
} }
handleRoot = (node: HTMLDivElement) => { handleRoot = (node: HTMLDivElement) => {
this.root = node; this.root = node;
}; };
render() { render() {
const { height } = this.props; const { height } = this.props;
const { computedHeight } = this.state; const { computedHeight } = this.state;
......
import numeral from 'numeral'; import numeral from 'numeral';
import Bar from './Bar';
import ChartCard from './ChartCard'; import ChartCard from './ChartCard';
import Field from './Field'; import Field from './Field';
import Bar from './Bar';
import Pie from './Pie';
import Gauge from './Gauge'; import Gauge from './Gauge';
import MiniArea from './MiniArea'; import MiniArea from './MiniArea';
import MiniBar from './MiniBar'; import MiniBar from './MiniBar';
import MiniProgress from './MiniProgress'; import MiniProgress from './MiniProgress';
import WaterWave from './WaterWave'; import Pie from './Pie';
import TagCloud from './TagCloud'; import TagCloud from './TagCloud';
import TimelineChart from './TimelineChart'; import TimelineChart from './TimelineChart';
import WaterWave from './WaterWave';
const yuan = (val: number | string) => ${numeral(val).format('0,0')}`; const yuan = (val: number | string) => ${numeral(val).format('0,0')}`;
......
import React from 'react'; import { Col, Icon, Row, Tooltip } from 'antd';
import { Row, Col, Icon, Tooltip } from 'antd';
import { FormattedMessage } from 'umi-plugin-react/locale'; import { FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts'; import React from 'react';
import numeral from 'numeral'; import numeral from 'numeral';
import styles from '../style.less'; import { ChartCard, MiniArea, MiniBar, MiniProgress, Field } from './Charts';
import Yuan from '../utils/Yuan'; import { VisitDataType } from '../data.d';
import Trend from './Trend'; import Trend from './Trend';
import { IVisitData } from '../data.d'; import Yuan from '../utils/Yuan';
const { ChartCard, MiniArea, MiniBar, MiniProgress, Field } = Charts; import styles from '../style.less';
const topColResponsiveProps = { const topColResponsiveProps = {
xs: 24, xs: 24,
...@@ -18,8 +18,7 @@ const topColResponsiveProps = { ...@@ -18,8 +18,7 @@ const topColResponsiveProps = {
style: { marginBottom: 24 }, style: { marginBottom: 24 },
}; };
const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVisitData[] }) => { const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: VisitDataType[] }) => (
return (
<Row gutter={24}> <Row gutter={24}>
<Col {...topColResponsiveProps}> <Col {...topColResponsiveProps}>
<ChartCard <ChartCard
...@@ -77,10 +76,7 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi ...@@ -77,10 +76,7 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi
footer={ footer={
<Field <Field
label={ label={
<FormattedMessage <FormattedMessage id="BLOCK_NAME.analysis.day-visits" defaultMessage="Daily Visits" />
id="BLOCK_NAME.analysis.day-visits"
defaultMessage="Daily Visits"
/>
} }
value={numeral(1234).format('0,0')} value={numeral(1234).format('0,0')}
/> />
...@@ -159,7 +155,6 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi ...@@ -159,7 +155,6 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi
</ChartCard> </ChartCard>
</Col> </Col>
</Row> </Row>
); );
};
export default IntroduceRow; export default IntroduceRow;
import React from 'react';
import { Icon } from 'antd'; import { Icon } from 'antd';
import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
export interface NumberInfoProps { export interface NumberInfoProps {
title?: React.ReactNode | string; title?: React.ReactNode | string;
subTitle?: React.ReactNode | string; subTitle?: React.ReactNode | string;
......
import { Card, Col, Row, Tabs } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React from 'react'; import React from 'react';
import { Card, Tabs, Row, Col } from 'antd'; import { OfflineChartData, OfflineDataType } from '../data.d';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts'; import { TimelineChart, Pie } from './Charts';
import styles from '../style.less';
import NumberInfo from './NumberInfo'; import NumberInfo from './NumberInfo';
import { IOfflineData, IOfflineChartData } from '../data'; import styles from '../style.less';
const { TimelineChart, Pie } = Charts;
const CustomTab = ({ const CustomTab = ({
data, data,
currentTabKey: currentKey, currentTabKey: currentKey,
}: { }: {
data: IOfflineData; data: OfflineDataType;
currentTabKey: string; currentTabKey: string;
}) => { }) => (
return (
<Row gutter={8} style={{ width: 138, margin: '8px 0' }}> <Row gutter={8} style={{ width: 138, margin: '8px 0' }}>
<Col span={12}> <Col span={12}>
<NumberInfo <NumberInfo
...@@ -41,8 +40,7 @@ const CustomTab = ({ ...@@ -41,8 +40,7 @@ const CustomTab = ({
/> />
</Col> </Col>
</Row> </Row>
); );
};
const { TabPane } = Tabs; const { TabPane } = Tabs;
...@@ -55,8 +53,8 @@ const OfflineData = ({ ...@@ -55,8 +53,8 @@ const OfflineData = ({
}: { }: {
activeKey: string; activeKey: string;
loading: boolean; loading: boolean;
offlineData: IOfflineData[]; offlineData: OfflineDataType[];
offlineChartData: IOfflineChartData[]; offlineChartData: OfflineChartData[];
handleTabChange: (activeKey: string) => void; handleTabChange: (activeKey: string) => void;
}) => ( }) => (
<Card loading={loading} className={styles.offlineCard} bordered={false} style={{ marginTop: 32 }}> <Card loading={loading} className={styles.offlineCard} bordered={false} style={{ marginTop: 32 }}>
......
import React from 'react';
import { Card, Radio } from 'antd'; import { Card, Radio } from 'antd';
import Charts from './Charts';
import { FormattedMessage } from 'umi-plugin-react/locale'; import { FormattedMessage } from 'umi-plugin-react/locale';
import styles from '../style.less';
import Yuan from '../utils/Yuan';
import { RadioChangeEvent } from 'antd/es/radio'; import { RadioChangeEvent } from 'antd/es/radio';
import { ISalesData } from '../data'; import React from 'react';
import { VisitDataType } from '../data.d';
const { Pie } = Charts; import { Pie } from './Charts';
import Yuan from '../utils/Yuan';
import styles from '../style.less';
const ProportionSales = ({ const ProportionSales = ({
dropdownGroup, dropdownGroup,
...@@ -19,10 +18,9 @@ const ProportionSales = ({ ...@@ -19,10 +18,9 @@ const ProportionSales = ({
loading: boolean; loading: boolean;
dropdownGroup: React.ReactNode; dropdownGroup: React.ReactNode;
salesType: 'all' | 'online' | 'stores'; salesType: 'all' | 'online' | 'stores';
salesPieData: ISalesData[]; salesPieData: VisitDataType[];
handleChangeSalesType?: (e: RadioChangeEvent) => void; handleChangeSalesType?: (e: RadioChangeEvent) => void;
}) => { }) => (
return (
<Card <Card
loading={loading} loading={loading}
className={styles.salesCard} className={styles.salesCard}
...@@ -73,7 +71,6 @@ const ProportionSales = ({ ...@@ -73,7 +71,6 @@ const ProportionSales = ({
/> />
</div> </div>
</Card> </Card>
); );
};
export default ProportionSales; export default ProportionSales;
import React from 'react'; import { Card, Col, DatePicker, Row, Tabs } from 'antd';
import { Row, Col, Card, Tabs, DatePicker } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale'; import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import numeral from 'numeral';
import Charts from './Charts';
import { RangePickerValue } from 'antd/es/date-picker/interface'; import { RangePickerValue } from 'antd/es/date-picker/interface';
import { ISalesData } from '../data'; import React from 'react';
import numeral from 'numeral';
import { VisitDataType } from '../data.d';
import { Bar } from './Charts';
import styles from '../style.less'; import styles from '../style.less';
const { Bar } = Charts;
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const { TabPane } = Tabs; const { TabPane } = Tabs;
...@@ -30,7 +29,7 @@ const SalesCard = ({ ...@@ -30,7 +29,7 @@ const SalesCard = ({
}: { }: {
rangePickerValue: RangePickerValue; rangePickerValue: RangePickerValue;
isActive: (key: 'today' | 'week' | 'month' | 'year') => string; isActive: (key: 'today' | 'week' | 'month' | 'year') => string;
salesData: ISalesData[]; salesData: VisitDataType[];
loading: boolean; loading: boolean;
handleRangePickerChange: (dates: RangePickerValue, dateStrings: [string, string]) => void; handleRangePickerChange: (dates: RangePickerValue, dateStrings: [string, string]) => void;
selectDate: (key: 'today' | 'week' | 'month' | 'year') => void; selectDate: (key: 'today' | 'week' | 'month' | 'year') => void;
......
import React from 'react'; import { Card, Col, Icon, Row, Table, Tooltip } from 'antd';
import { Row, Col, Table, Tooltip, Card, Icon } from 'antd';
import { FormattedMessage } from 'umi-plugin-react/locale'; import { FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts'; import React from 'react';
import Trend from './Trend';
import NumberInfo from './NumberInfo';
import numeral from 'numeral'; import numeral from 'numeral';
import styles from '../style.less'; import { SearchDataType, VisitDataType } from '../data.d';
import { ISearchData, IVisitData2 } from '../data';
const { MiniArea } = Charts; import { MiniArea } from './Charts';
import NumberInfo from './NumberInfo';
import Trend from './Trend';
import styles from '../style.less';
const columns = [ const columns = [
{ {
...@@ -51,9 +50,9 @@ const TopSearch = ({ ...@@ -51,9 +50,9 @@ const TopSearch = ({
dropdownGroup, dropdownGroup,
}: { }: {
loading: boolean; loading: boolean;
visitData2: IVisitData2[]; visitData2: VisitDataType[];
dropdownGroup: React.ReactNode; dropdownGroup: React.ReactNode;
searchData: ISearchData[]; searchData: SearchDataType[];
}) => ( }) => (
<Card <Card
loading={loading} loading={loading}
......
import React from 'react';
import { Icon } from 'antd'; import { Icon } from 'antd';
import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
export interface ITrendProps { export interface TrendProps {
colorful?: boolean; colorful?: boolean;
flag: 'up' | 'down'; flag: 'up' | 'down';
style?: React.CSSProperties; style?: React.CSSProperties;
...@@ -11,7 +11,7 @@ export interface ITrendProps { ...@@ -11,7 +11,7 @@ export interface ITrendProps {
className?: string; className?: string;
} }
const Trend: React.SFC<ITrendProps> = ({ const Trend: React.SFC<TrendProps> = ({
colorful = true, colorful = true,
reverseColor = false, reverseColor = false,
flag, flag,
......
export interface IVisitData { export interface VisitDataType {
x: string; x: string;
y: number; y: number;
} }
export interface IVisitData2 { export interface SearchDataType {
x: string;
y: number;
}
export interface ISalesData {
x: string;
y: number;
}
export interface ISearchData {
index: number; index: number;
keyword: string; keyword: string;
count: number; count: number;
...@@ -21,47 +11,32 @@ export interface ISearchData { ...@@ -21,47 +11,32 @@ export interface ISearchData {
status: number; status: number;
} }
export interface IOfflineData { export interface OfflineDataType {
name: string; name: string;
cvr: number; cvr: number;
} }
export interface IOfflineChartData { export interface OfflineChartData {
x: any; x: any;
y1: number; y1: number;
y2: number; y2: number;
} }
export interface ISalesTypeData { export interface RadarData {
x: string;
y: number;
}
export interface ISalesTypeDataOnline {
x: string;
y: number;
}
export interface ISalesTypeDataOffline {
x: string;
y: number;
}
export interface IRadarData {
name: string; name: string;
label: string; label: string;
value: number; value: number;
} }
export interface IAnalysisData { export interface AnalysisData {
visitData: IVisitData[]; visitData: VisitDataType[];
visitData2: IVisitData2[]; visitData2: VisitDataType[];
salesData: ISalesData[]; salesData: VisitDataType[];
searchData: ISearchData[]; searchData: SearchDataType[];
offlineData: IOfflineData[]; offlineData: OfflineDataType[];
offlineChartData: IOfflineChartData[]; offlineChartData: OfflineChartData[];
salesTypeData: ISalesTypeData[]; salesTypeData: VisitDataType[];
salesTypeDataOnline: ISalesTypeDataOnline[]; salesTypeDataOnline: VisitDataType[];
salesTypeDataOffline: ISalesTypeDataOffline[]; salesTypeDataOffline: VisitDataType[];
radarData: IRadarData[]; radarData: RadarData[];
} }
import { Col, Dropdown, Icon, Menu, Row } from 'antd';
import React, { Component, Suspense } from 'react'; import React, { Component, Suspense } from 'react';
import { connect } from 'dva';
import { Row, Col, Icon, Menu, Dropdown } from 'antd'; import { Dispatch } from 'redux';
import { GridContent } from '@ant-design/pro-layout';
import { RadioChangeEvent } from 'antd/es/radio';
import { RangePickerValue } from 'antd/es/date-picker/interface'; import { RangePickerValue } from 'antd/es/date-picker/interface';
import { connect } from 'dva';
import PageLoading from './components/PageLoading';
import { getTimeDistance } from './utils/utils'; import { getTimeDistance } from './utils/utils';
import { AnalysisData } from './data.d';
import styles from './style.less'; import styles from './style.less';
import PageLoading from './components/PageLoading';
import { Dispatch } from 'redux';
import { IAnalysisData } from './data.d';
import { RadioChangeEvent } from 'antd/es/radio';
import { GridContent } from '@ant-design/pro-layout';
const IntroduceRow = React.lazy(() => import('./components/IntroduceRow')); const IntroduceRow = React.lazy(() => import('./components/IntroduceRow'));
const SalesCard = React.lazy(() => import('./components/SalesCard')); const SalesCard = React.lazy(() => import('./components/SalesCard'));
...@@ -17,7 +18,7 @@ const ProportionSales = React.lazy(() => import('./components/ProportionSales')) ...@@ -17,7 +18,7 @@ const ProportionSales = React.lazy(() => import('./components/ProportionSales'))
const OfflineData = React.lazy(() => import('./components/OfflineData')); const OfflineData = React.lazy(() => import('./components/OfflineData'));
interface BLOCK_NAME_CAMEL_CASEProps { interface BLOCK_NAME_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE: IAnalysisData; BLOCK_NAME_CAMEL_CASE: AnalysisData;
dispatch: Dispatch<any>; dispatch: Dispatch<any>;
loading: boolean; loading: boolean;
} }
...@@ -51,8 +52,11 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component< ...@@ -51,8 +52,11 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
currentTabKey: '', currentTabKey: '',
rangePickerValue: getTimeDistance('year'), rangePickerValue: getTimeDistance('year'),
}; };
reqRef!: number;
timeoutId!: number; reqRef: number = 0;
timeoutId: number = 0;
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
this.reqRef = requestAnimationFrame(() => { this.reqRef = requestAnimationFrame(() => {
......
import { fakeChartData } from './service'; import { AnyAction, Reducer } from 'redux';
import { IAnalysisData } from './data';
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva'; import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux'; import { AnalysisData } from './data.d';
import { fakeChartData } from './service';
export type Effect = ( export type Effect = (
action: AnyAction, action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: IAnalysisData) => T) => T }, effects: EffectsCommandMap & { select: <T>(func: (state: AnalysisData) => T) => T },
) => void; ) => void;
export interface ModelType { export interface ModelType {
namespace: string; namespace: string;
state: IAnalysisData; state: AnalysisData;
effects: { effects: {
fetch: Effect; fetch: Effect;
fetchSalesData: Effect; fetchSalesData: Effect;
}; };
reducers: { reducers: {
save: Reducer<IAnalysisData>; save: Reducer<AnalysisData>;
clear: Reducer<IAnalysisData>; clear: Reducer<AnalysisData>;
}; };
} }
......
...@@ -6,7 +6,8 @@ import { yuan } from '../components/Charts'; ...@@ -6,7 +6,8 @@ import { yuan } from '../components/Charts';
export default class Yuan extends React.Component<{ export default class Yuan extends React.Component<{
children: React.ReactText; children: React.ReactText;
}> { }> {
main: HTMLSpanElement | undefined | null; main: HTMLSpanElement | undefined | null = null;
componentDidMount() { componentDidMount() {
this.renderToHtml(); this.renderToHtml();
} }
...@@ -14,6 +15,7 @@ export default class Yuan extends React.Component<{ ...@@ -14,6 +15,7 @@ export default class Yuan extends React.Component<{
componentDidUpdate() { componentDidUpdate() {
this.renderToHtml(); this.renderToHtml();
} }
renderToHtml = () => { renderToHtml = () => {
const { children } = this.props; const { children } = this.props;
if (this.main) { if (this.main) {
......
import moment from 'moment';
import { RangePickerValue } from 'antd/es/date-picker/interface'; import { RangePickerValue } from 'antd/es/date-picker/interface';
import moment from 'moment';
export function fixedZero(val: number) { export function fixedZero(val: number) {
return val * 1 < 10 ? `0${val}` : val; return val * 1 < 10 ? `0${val}` : val;
......
...@@ -13,21 +13,25 @@ ...@@ -13,21 +13,25 @@
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.2", "@ant-design/pro-layout": "^4.5.2",
"@antv/data-set": "^0.10.2", "@antv/data-set": "^0.10.2",
"@types/lodash.debounce": "^4.0.6",
"antd": "^3.16.3", "antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0", "bizcharts": "^3.5.3-beta.0",
"bizcharts-plugin-slider": "^2.1.1-beta.1", "bizcharts-plugin-slider": "^2.1.1-beta.1",
"classnames": "^2.2.6",
"dva": "^2.4.0", "dva": "^2.4.0",
"lodash.debounce": "^4.0.8",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"react": "^16.8.6", "react": "^16.8.6",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"umi-request": "^1.0.0" "redux": "^4.0.1",
},
"devDependencies": {
"@types/numeral": "^0.0.25",
"mockjs": "^1.0.1-beta3",
"umi": "^2.6.9", "umi": "^2.6.9",
"umi-plugin-block-dev": "^1.0.0", "umi-plugin-block-dev": "^1.0.0",
"umi-plugin-react": "^1.7.2" "umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0",
"mockjs": "^1.0.1-beta3"
},
"devDependencies": {
"@types/numeral": "^0.0.25"
}, },
"license": "ISC", "license": "ISC",
"blockConfig": { "blockConfig": {
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import Charts from '../Charts';
import { Statistic } from 'antd'; import { Statistic } from 'antd';
import { MiniArea } from '../Charts';
import styles from './index.less'; import styles from './index.less';
const { MiniArea } = Charts;
function fixedZero(val: number) { function fixedZero(val: number) {
return val * 1 < 10 ? `0${val}` : val; return val * 1 < 10 ? `0${val}` : val;
} }
...@@ -24,12 +23,15 @@ export default class ActiveChart extends Component { ...@@ -24,12 +23,15 @@ export default class ActiveChart extends Component {
state = { state = {
activeData: getActiveData(), activeData: getActiveData(),
}; };
timer: number | undefined;
requestRef: number | undefined; timer: number | undefined = undefined;
requestRef: number | undefined = undefined;
componentDidMount() { componentDidMount() {
this.loopData(); this.loopData();
} }
componentWillUnmount() { componentWillUnmount() {
clearTimeout(this.timer); clearTimeout(this.timer);
if (this.requestRef) { if (this.requestRef) {
......
import { Axis, Chart, Coord, Geom, Guide, Shape } from 'bizcharts';
import React from 'react'; import React from 'react';
import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide; const { Arc, Html, Line } = Guide;
export interface IGaugeProps { export interface GaugeProps {
title: React.ReactNode; title: React.ReactNode;
color?: string; color?: string;
height?: number; height?: number;
...@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => { ...@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => {
} }
}; };
Shape.registerShape!('point', 'pointer', { if (Shape.registerShape) {
Shape.registerShape('point', 'pointer', {
drawShape(cfg: any, group: any) { drawShape(cfg: any, group: any) {
let point = cfg.points[0]; let point = cfg.points[0];
point = (this as any).parsePoint(point); point = (this as any).parsePoint(point);
...@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', { ...@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', {
}, },
}); });
}, },
}); });
}
class Gauge extends React.Component<IGaugeProps> { const Gauge: React.FC<GaugeProps> = props => {
render() {
const { const {
title, title,
height = 1, height = 1,
...@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> {
formatter = defaultFormatter, formatter = defaultFormatter,
color = '#2F9CFF', color = '#2F9CFF',
bgColor = '#F0F2F5', bgColor = '#F0F2F5',
} = this.props; } = props;
const cols = { const cols = {
value: { value: {
type: 'linear', type: 'linear',
...@@ -82,6 +84,8 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -82,6 +84,8 @@ class Gauge extends React.Component<IGaugeProps> {
nice: true, nice: true,
}, },
}; };
const data = [{ value: percent / 10 }];
const renderHtml = () => ` const renderHtml = () => `
<div style="width: 300px;text-align: center;font-size: 12px!important;"> <div style="width: 300px;text-align: center;font-size: 12px!important;">
<p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p> <p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
...@@ -89,7 +93,6 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -89,7 +93,6 @@ class Gauge extends React.Component<IGaugeProps> {
${(data[0].value * 10).toFixed(2)}% ${(data[0].value * 10).toFixed(2)}%
</p> </p>
</div>`; </div>`;
const data = [{ value: percent / 10 }];
const textStyle: { const textStyle: {
fontSize: number; fontSize: number;
fill: string; fill: string;
...@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> {
label={{ label={{
offset: -12, offset: -12,
formatter, formatter,
textStyle: textStyle, textStyle,
}} }}
/> />
<Guide> <Guide>
...@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> { ...@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> {
/> />
</Chart> </Chart>
); );
} };
}
export default autoHeight()(Gauge); export default autoHeight()(Gauge);
import { Axis, AxisProps, Chart, Geom, Tooltip } from 'bizcharts';
import React from 'react'; import React from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from '../index.less'; import styles from '../index.less';
export interface IAxis { export interface MiniAreaProps {
title: any;
line: any;
gridAlign: any;
labels: any;
tickLine: any;
grid: any;
label: any;
}
export interface IMiniAreaProps {
color?: string; color?: string;
height?: number; height?: number;
borderColor?: string; borderColor?: string;
line?: boolean; line?: boolean;
animate?: boolean; animate?: boolean;
xAxis?: IAxis; xAxis?: AxisProps;
forceFit?: boolean; forceFit?: boolean;
scale?: { x?: any; y?: any }; scale?: {
yAxis?: Partial<IAxis>; x?: {
tickCount: number;
};
y?: {
tickCount: number;
};
};
yAxis?: Partial<AxisProps>;
borderWidth?: number; borderWidth?: number;
data: Array<{ data: {
x: number | string; x: number | string;
y: number; y: number;
}>; }[];
} }
class MiniArea extends React.Component<IMiniAreaProps> { const MiniArea: React.FC<MiniAreaProps> = props => {
render() {
const { const {
height = 1, height = 1,
data = [], data = [],
...@@ -44,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -44,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> {
xAxis, xAxis,
yAxis, yAxis,
animate = true, animate = true,
} = this.props; } = props;
const padding: [number, number, number, number] = [36, 5, 30, 5]; const padding: [number, number, number, number] = [36, 5, 30, 5];
...@@ -52,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -52,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> {
x: { x: {
type: 'cat', type: 'cat',
range: [0, 1], range: [0, 1],
...scale!.x, ...scale.x,
}, },
y: { y: {
min: 0, min: 0,
...scale!.y, ...scale.y,
}, },
}; };
...@@ -85,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -85,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> {
<Axis <Axis
key="axis-x" key="axis-x"
name="x" name="x"
label={false} label={null}
line={false} line={null}
tickLine={false} tickLine={null}
grid={false} grid={null}
{...xAxis} {...xAxis}
/> />
<Axis <Axis
key="axis-y" key="axis-y"
name="y" name="y"
label={false} label={null}
line={false} line={null}
tickLine={false} tickLine={null}
grid={false} grid={null}
{...yAxis} {...yAxis}
/> />
<Tooltip showTitle={false} crosshairs={false} /> <Tooltip showTitle={false} crosshairs={false} />
...@@ -128,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> { ...@@ -128,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> {
</div> </div>
</div> </div>
); );
} };
}
export default autoHeight()(MiniArea); export default autoHeight()(MiniArea);
import { Chart, Coord, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set'; import { DataView } from '@antv/data-set';
import Debounce from 'lodash.debounce';
import { Divider } from 'antd'; import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext'; import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce'; import classNames from 'classnames';
import Bind from 'lodash-decorators/bind';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
export interface IPieProps {
export interface PieProps {
animate?: boolean; animate?: boolean;
color?: string; color?: string;
colors?: string[]; colors?: string[];
...@@ -19,10 +19,10 @@ export interface IPieProps { ...@@ -19,10 +19,10 @@ export interface IPieProps {
hasLegend?: boolean; hasLegend?: boolean;
padding?: [number, number, number, number]; padding?: [number, number, number, number];
percent?: number; percent?: number;
data?: Array<{ data?: {
x: string | string; x: string | string;
y: number; y: number;
}>; }[];
inner?: number; inner?: number;
lineWidth?: number; lineWidth?: number;
forceFit?: boolean; forceFit?: boolean;
...@@ -34,19 +34,46 @@ export interface IPieProps { ...@@ -34,19 +34,46 @@ export interface IPieProps {
valueFormat?: (value: string) => string | React.ReactNode; valueFormat?: (value: string) => string | React.ReactNode;
subTitle?: React.ReactNode; subTitle?: React.ReactNode;
} }
interface IPieState { interface PieState {
legendData: Array<{ checked: boolean; x: string; color: string; percent: number; y: string }>; legendData: { checked: boolean; x: string; color: string; percent: number; y: string }[];
legendBlock: boolean; legendBlock: boolean;
} }
class Pie extends Component<IPieProps, IPieState> { class Pie extends Component<PieProps, PieState> {
state: IPieState = { state: PieState = {
legendData: [], legendData: [],
legendBlock: false, legendBlock: false,
}; };
requestRef: number | undefined; chart: G2.Chart | undefined = undefined;
root!: HTMLDivElement;
chart: G2.Chart | undefined; root: HTMLDivElement | undefined = undefined;
requestRef: number | undefined = 0;
// for window resize auto responsive legend
resize = Debounce(() => {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}, 300);
componentDidMount() { componentDidMount() {
window.addEventListener( window.addEventListener(
...@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> {
); );
} }
componentDidUpdate(preProps: IPieProps) { componentDidUpdate(preProps: PieProps) {
const { data } = this.props; const { data } = this.props;
if (data !== preProps.data) { if (data !== preProps.data) {
// because of charts data create when rendered // because of charts data create when rendered
...@@ -90,7 +117,8 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -90,7 +117,8 @@ class Pie extends Component<IPieProps, IPieState> {
if (!this.chart) return; if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形 const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return; if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的 // g2 的类型有问题
const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => { const legendData = items.map((item: { color: any; _origin: any }[]) => {
/* eslint no-underscore-dangle:0 */ /* eslint no-underscore-dangle:0 */
...@@ -104,11 +132,12 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -104,11 +132,12 @@ class Pie extends Component<IPieProps, IPieState> {
legendData, legendData,
}); });
}; };
handleRoot = (n: HTMLDivElement) => { handleRoot = (n: HTMLDivElement) => {
this.root = n; this.root = n;
}; };
handleLegendClick = (item: any, i: string | number) => { handleLegendClick = (item: { checked: boolean }, i: string | number) => {
const newItem = item; const newItem = item;
newItem.checked = !newItem.checked; newItem.checked = !newItem.checked;
...@@ -118,7 +147,7 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -118,7 +147,7 @@ class Pie extends Component<IPieProps, IPieState> {
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x); const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
if (this.chart) { if (this.chart) {
this.chart.filter('x', val => filteredLegendData.indexOf(val + '') > -1); this.chart.filter('x', val => filteredLegendData.indexOf(`${val}`) > -1);
} }
this.setState({ this.setState({
...@@ -126,33 +155,6 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -126,33 +155,6 @@ class Pie extends Component<IPieProps, IPieState> {
}); });
}; };
// for window resize auto responsive legend
@Bind()
@Debounce(300)
resize() {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}
render() { render() {
const { const {
valueFormat, valueFormat,
...@@ -216,11 +218,11 @@ class Pie extends Component<IPieProps, IPieState> { ...@@ -216,11 +218,11 @@ class Pie extends Component<IPieProps, IPieState> {
data = [ data = [
{ {
x: '占比', x: '占比',
y: parseFloat(percent + ''), y: parseFloat(`${percent}`),
}, },
{ {
x: '反比', x: '反比',
y: 100 - parseFloat(percent + ''), y: 100 - parseFloat(`${percent}`),
}, },
]; ];
} }
......
import { Chart, Coord, Geom, Shape, Tooltip } from 'bizcharts';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
import DataSet from '@antv/data-set'; import DataSet from '@antv/data-set';
import Debounce from 'lodash-decorators/debounce'; import Debounce from 'lodash.debounce';
import Bind from 'lodash-decorators/bind';
import classNames from 'classnames'; import classNames from 'classnames';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
...@@ -12,33 +12,36 @@ import styles from './index.less'; ...@@ -12,33 +12,36 @@ import styles from './index.less';
const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'; const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
export interface ITagCloudProps { export interface TagCloudProps {
data: Array<{ data: {
name: string; name: string;
value: string; value: string;
}>; }[];
height?: number; height?: number;
className?: string; className?: string;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
interface ITagCloudState { interface TagCloudState {
dv: any; dv: any;
height?: number; height?: number;
width: number; width: number;
} }
class TagCloud extends Component<ITagCloudProps, ITagCloudState> { class TagCloud extends Component<TagCloudProps, TagCloudState> {
state = { state = {
dv: null, dv: null,
height: 0, height: 0,
width: 0, width: 0,
}; };
isUnmount!: boolean;
requestRef!: number;
root: HTMLDivElement | undefined; requestRef: number = 0;
imageMask: HTMLImageElement | undefined;
isUnmount: boolean = false;
root: HTMLDivElement | undefined = undefined;
imageMask: HTMLImageElement | undefined = undefined;
componentDidMount() { componentDidMount() {
requestAnimationFrame(() => { requestAnimationFrame(() => {
...@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
window.addEventListener('resize', this.resize, { passive: true }); window.addEventListener('resize', this.resize, { passive: true });
} }
componentDidUpdate(preProps?: ITagCloudProps) { componentDidUpdate(preProps?: TagCloudProps) {
const { data } = this.props; const { data } = this.props;
if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) { if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) {
this.renderChart(this.props); this.renderChart(this.props);
} }
} }
componentWillUnmount() { componentWillUnmount() {
this.isUnmount = true; this.isUnmount = true;
window.cancelAnimationFrame(this.requestRef); window.cancelAnimationFrame(this.requestRef);
window.removeEventListener('resize', this.resize); window.removeEventListener('resize', this.resize);
} }
resize = () => { resize = () => {
this.requestRef = requestAnimationFrame(() => { this.requestRef = requestAnimationFrame(() => {
this.renderChart(this.props); this.renderChart(this.props);
}); });
}; };
saveRootRef = (node: HTMLDivElement) => { saveRootRef = (node: HTMLDivElement) => {
this.root = node; this.root = node;
}; };
...@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
origin?: any; origin?: any;
color?: any; color?: any;
}) { }) {
return Object.assign({}, cfg.style, { return {
...cfg.style,
fillOpacity: cfg.opacity, fillOpacity: cfg.opacity,
fontSize: cfg.origin._origin.size, fontSize: cfg.origin._origin.size,
rotate: cfg.origin._origin.rotate, rotate: cfg.origin._origin.rotate,
...@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
fontFamily: cfg.origin._origin.font, fontFamily: cfg.origin._origin.font,
fill: cfg.color, fill: cfg.color,
textBaseline: 'Alphabetic', textBaseline: 'Alphabetic',
}); };
} }
(Shape as any).registerShape('point', 'cloud', { (Shape as any).registerShape('point', 'cloud', {
...@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
) { ) {
const attrs = getTextAttrs(cfg); const attrs = getTextAttrs(cfg);
return container.addShape('text', { return container.addShape('text', {
attrs: Object.assign(attrs, { attrs: {
...attrs,
x: cfg.x, x: cfg.x,
y: cfg.y, y: cfg.y,
}), },
}); });
}, },
}); });
}; };
@Bind() renderChart = Debounce((nextProps: TagCloudProps) => {
@Debounce(500)
renderChart(nextProps: ITagCloudProps) {
// const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C']; // const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
const { data, height } = nextProps || this.props; const { data, height } = nextProps || this.props;
if (data.length < 1 || !this.root) { if (data.length < 1 || !this.root) {
...@@ -133,8 +139,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -133,8 +139,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
return 0; return 0;
}, },
fontSize(d: { value: number }) { fontSize(d: { value: number }) {
// eslint-disable-next-line const size = ((d.value - min) / (max - min)) ** 2;
return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5; return size * (17.5 - 5) + 5;
}, },
}); });
...@@ -158,7 +164,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> { ...@@ -158,7 +164,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
} else { } else {
onload(); onload();
} }
} }, 200);
render() { render() {
const { className, height } = this.props; const { className, height } = this.props;
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import autoHeight from '../autoHeight'; import autoHeight from '../autoHeight';
import styles from './index.less'; import styles from './index.less';
...@@ -6,7 +7,7 @@ import styles from './index.less'; ...@@ -6,7 +7,7 @@ import styles from './index.less';
/* eslint no-mixed-operators: 0 */ /* eslint no-mixed-operators: 0 */
// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90 // riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
export interface IWaterWaveProps { export interface WaterWaveProps {
title: React.ReactNode; title: React.ReactNode;
color?: string; color?: string;
height?: number; height?: number;
...@@ -14,13 +15,16 @@ export interface IWaterWaveProps { ...@@ -14,13 +15,16 @@ export interface IWaterWaveProps {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
class WaterWave extends Component<IWaterWaveProps> { class WaterWave extends Component<WaterWaveProps> {
state = { state = {
radio: 1, radio: 1,
}; };
timer: number = 0; timer: number = 0;
root: HTMLDivElement | undefined | null;
node: HTMLCanvasElement | undefined | null; root: HTMLDivElement | undefined | null = null;
node: HTMLCanvasElement | undefined | null = null;
componentDidMount() { componentDidMount() {
this.renderChart(); this.renderChart();
...@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> {
); );
} }
componentDidUpdate(props: IWaterWaveProps) { componentDidUpdate(props: WaterWaveProps) {
const { percent } = this.props; const { percent } = this.props;
if (props.percent !== percent) { if (props.percent !== percent) {
// 不加这个会造成绘制缓慢 // 不加这个会造成绘制缓慢
...@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> {
}); });
} }
}; };
renderChart(type?: string) { renderChart(type?: string) {
const { percent, color = '#1890FF' } = this.props; const { percent, color = '#1890FF' } = this.props;
const data = percent / 100; const data = percent / 100;
...@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> { ...@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> {
} }
render(); render();
} }
render() { render() {
const { radio } = this.state; const { radio } = this.state;
const { percent, title, height = 1 } = this.props; const { percent, title, height = 1 } = this.props;
......
...@@ -6,11 +6,12 @@ export type IReactComponent<P = any> = ...@@ -6,11 +6,12 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>; | React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) { function computeHeight(node: HTMLDivElement) {
node.style.height = '100%'; const { style } = node;
const totalHeight = parseInt(getComputedStyle(node).height + '', 10); style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding = const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) + parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10); parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding; return totalHeight - padding;
} }
...@@ -30,22 +31,24 @@ function getAutoHeight(n: HTMLDivElement) { ...@@ -30,22 +31,24 @@ function getAutoHeight(n: HTMLDivElement) {
return height; return height;
} }
interface IAutoHeightProps { interface AutoHeightProps {
height?: number; height?: number;
} }
function autoHeight() { function autoHeight() {
return function<P extends IAutoHeightProps>( return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>, WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> { ): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> { class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = { state = {
computedHeight: 0, computedHeight: 0,
}; };
root!: HTMLDivElement;
root: HTMLDivElement | null = null;
componentDidMount() { componentDidMount() {
const { height } = this.props; const { height } = this.props;
if (!height) { if (!height && this.root) {
let h = getAutoHeight(this.root); let h = getAutoHeight(this.root);
this.setState({ computedHeight: h }); this.setState({ computedHeight: h });
if (h < 1) { if (h < 1) {
...@@ -54,9 +57,11 @@ function autoHeight() { ...@@ -54,9 +57,11 @@ function autoHeight() {
} }
} }
} }
handleRoot = (node: HTMLDivElement) => { handleRoot = (node: HTMLDivElement) => {
this.root = node; this.root = node;
}; };
render() { render() {
const { height } = this.props; const { height } = this.props;
const { computedHeight } = this.state; const { computedHeight } = this.state;
......
import Pie from './Pie';
import Gauge from './Gauge'; import Gauge from './Gauge';
import WaterWave from './WaterWave';
import TagCloud from './TagCloud';
import MiniArea from './MiniArea'; import MiniArea from './MiniArea';
import Pie from './Pie';
import TagCloud from './TagCloud';
import WaterWave from './WaterWave';
const Charts = { const Charts = {
Pie, Pie,
WaterWave, WaterWave,
......
export interface ITag { export interface TagType {
name: string; name: string;
value: string; value: string;
type: string; type: string;
......
import { Card, Col, Row, Statistic, Tooltip } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Dispatch } from 'redux';
import { GridContent } from '@ant-design/pro-layout';
import { connect } from 'dva'; import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { Row, Col, Card, Statistic, Tooltip } from 'antd';
import numeral from 'numeral'; import numeral from 'numeral';
import { Dispatch } from 'redux'; import { StateType } from './model';
import { IStateType } from './model'; import { Pie, WaterWave, Gauge, TagCloud } from './components/Charts';
import ActiveChart from './components/ActiveChart'; import ActiveChart from './components/ActiveChart';
import styles from './style.less'; import styles from './style.less';
import Charts from './components/Charts';
import { GridContent } from '@ant-design/pro-layout';
const { Countdown } = Statistic; const { Countdown } = Statistic;
const { Pie, WaterWave, Gauge, TagCloud } = Charts;
const targetTime = new Date().getTime() + 3900000; const targetTime = new Date().getTime() + 3900000;
interface PAGE_NAME_UPPER_CAMEL_CASEProps { interface PAGE_NAME_UPPER_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE: IStateType; BLOCK_NAME_CAMEL_CASE: StateType;
dispatch: Dispatch<any>; dispatch: Dispatch<any>;
loading: boolean; loading: boolean;
} }
...@@ -27,7 +26,7 @@ interface PAGE_NAME_UPPER_CAMEL_CASEProps { ...@@ -27,7 +26,7 @@ interface PAGE_NAME_UPPER_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE, BLOCK_NAME_CAMEL_CASE,
loading, loading,
}: { }: {
BLOCK_NAME_CAMEL_CASE: IStateType; BLOCK_NAME_CAMEL_CASE: StateType;
loading: { loading: {
models: { [key: string]: boolean }; models: { [key: string]: boolean };
}; };
......
import { queryTags } from './service'; import { AnyAction, Reducer } from 'redux';
import { ITag } from './data';
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva'; import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux'; import { TagType } from './data.d';
import { queryTags } from './service';
export interface IStateType { export interface StateType {
tags: ITag[]; tags: TagType[];
} }
export type Effect = ( export type Effect = (
action: AnyAction, action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: IStateType) => T) => T }, effects: EffectsCommandMap & { select: <T>(func: (state: StateType) => T) => T },
) => void; ) => void;
export interface ModelType { export interface ModelType {
namespace: string; namespace: string;
state: IStateType; state: StateType;
effects: { effects: {
fetchTags: Effect; fetchTags: Effect;
}; };
reducers: { reducers: {
saveTags: Reducer<IStateType>; saveTags: Reducer<StateType>;
}; };
} }
......
...@@ -11,13 +11,15 @@ ...@@ -11,13 +11,15 @@
"url": "https://github.com/umijs/umi-blocks/ant-design-pro/workplace" "url": "https://github.com/umijs/umi-blocks/ant-design-pro/workplace"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3", "antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
"dva": "^2.4.0", "dva": "^2.4.0",
"moment": "^2.22.2", "moment": "^2.22.2",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"react": "^16.6.3", "react": "^16.6.3",
"umi-request": "^1.0.0", "redux": "^4.0.1",
"bizcharts": "^3.5.3-beta.0" "umi-request": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"umi": "^2.6.9", "umi": "^2.6.9",
......
import React, { PureComponent, createElement } from 'react'; import React, { PureComponent, createElement } from 'react';
import { Button } from 'antd'; import { Button } from 'antd';
import styles from './index.less'; import styles from './index.less';
......
...@@ -6,15 +6,16 @@ export type IReactComponent<P = any> = ...@@ -6,15 +6,16 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>; | React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) { function computeHeight(node: HTMLDivElement) {
node.style.height = '100%'; const { style } = node;
const totalHeight = parseInt(getComputedStyle(node).height + '', 10); style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding = const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) + parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10); parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding; return totalHeight - padding;
} }
function getAutoHeight(n: HTMLDivElement) { function getAutoHeight(n: HTMLDivElement | undefined) {
if (!n) { if (!n) {
return 0; return 0;
} }
...@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) { ...@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) {
return height; return height;
} }
interface IAutoHeightProps { interface AutoHeightProps {
height?: number; height?: number;
} }
function autoHeight() { function autoHeight() {
return function<P extends IAutoHeightProps>( return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>, WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> { ): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> { class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = { state = {
computedHeight: 0, computedHeight: 0,
}; };
root!: HTMLDivElement;
root: HTMLDivElement | undefined = undefined;
componentDidMount() { componentDidMount() {
const { height } = this.props; const { height } = this.props;
if (!height) { if (!height) {
let h = getAutoHeight(this.root); let h = getAutoHeight(this.root);
// eslint-disable-next-line
this.setState({ computedHeight: h }); this.setState({ computedHeight: h });
if (h < 1) { if (h < 1) {
h = getAutoHeight(this.root); h = getAutoHeight(this.root);
...@@ -55,9 +57,11 @@ function autoHeight() { ...@@ -55,9 +57,11 @@ function autoHeight() {
} }
} }
} }
handleRoot = (node: HTMLDivElement) => { handleRoot = (node: HTMLDivElement) => {
this.root = node; this.root = node;
}; };
render() { render() {
const { height } = this.props; const { height } = this.props;
const { computedHeight } = this.state; const { computedHeight } = this.state;
......
import { Axis, Chart, Coord, Geom, Tooltip } from 'bizcharts';
import { Col, Row } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord, Axis } from 'bizcharts';
import { Row, Col } from 'antd';
import autoHeight from './autoHeight'; import autoHeight from './autoHeight';
import styles from './index.less'; import styles from './index.less';
export interface IRadarProps { export interface RadarProps {
title?: React.ReactNode; title?: React.ReactNode;
height?: number; height?: number;
padding?: [number, number, number, number]; padding?: [number, number, number, number];
hasLegend?: boolean; hasLegend?: boolean;
data: Array<{ data: {
name: string; name: string;
label: string; label: string;
value: string | number; value: string | number;
}>; }[];
colors?: string[]; colors?: string[];
animate?: boolean; animate?: boolean;
forceFit?: boolean; forceFit?: boolean;
tickCount?: number; tickCount?: number;
style?: React.CSSProperties; style?: React.CSSProperties;
} }
interface IRadarState { interface RadarState {
legendData: Array<{ legendData: {
checked: boolean; checked: boolean;
name: string; name: string;
color: string; color: string;
percent: number; percent: number;
value: string; value: string;
}>; }[];
} }
/* eslint react/no-danger:0 */ /* eslint react/no-danger:0 */
class Radar extends Component<IRadarProps, IRadarState> { class Radar extends Component<RadarProps, RadarState> {
state: IRadarState = { state: RadarState = {
legendData: [], legendData: [],
}; };
chart: G2.Chart | undefined;
node: HTMLDivElement | undefined; chart: G2.Chart | undefined = undefined;
node: HTMLDivElement | undefined = undefined;
componentDidMount() { componentDidMount() {
this.getLegendData(); this.getLegendData();
} }
componentDidUpdate(preProps: IRadarProps) { componentDidUpdate(preProps: RadarProps) {
const { data } = this.props; const { data } = this.props;
if (data !== preProps.data) { if (data !== preProps.data) {
this.getLegendData(); this.getLegendData();
...@@ -57,10 +60,10 @@ class Radar extends Component<IRadarProps, IRadarState> { ...@@ -57,10 +60,10 @@ class Radar extends Component<IRadarProps, IRadarState> {
if (!this.chart) return; if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形 const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return; if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的 const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => { const legendData = items.map((item: { color: any; _origin: any }[]) => {
// eslint-disable-next-line // eslint-disable-next-line no-underscore-dangle
const origins = item.map(t => t._origin); const origins = item.map(t => t._origin);
const result = { const result = {
name: origins[0].name, name: origins[0].name,
...@@ -97,7 +100,7 @@ class Radar extends Component<IRadarProps, IRadarState> { ...@@ -97,7 +100,7 @@ class Radar extends Component<IRadarProps, IRadarState> {
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) { if (this.chart) {
this.chart.filter('name', val => filteredLegendData.indexOf(val + '') > -1); this.chart.filter('name', val => filteredLegendData.indexOf(`${val}`) > -1);
this.chart.repaint(); this.chart.repaint();
} }
......
export interface ITag { export interface TagType {
key: string; key: string;
label: string; label: string;
} }
export interface IProvince { export interface ProvinceType {
label: string; label: string;
key: string; key: string;
} }
export interface ICity { export interface CityType {
label: string; label: string;
key: string; key: string;
} }
export interface IGeographic { export interface GeographicType {
province: IProvince; province: ProvinceType;
city: ICity; city: CityType;
} }
export interface INotice { export interface NoticeType {
id: string; id: string;
title: string; title: string;
logo: string; logo: string;
...@@ -29,30 +29,30 @@ export interface INotice { ...@@ -29,30 +29,30 @@ export interface INotice {
memberLink: string; memberLink: string;
} }
export interface ICurrentUser { export interface CurrentUser {
name: string; name: string;
avatar: string; avatar: string;
userid: string; userid: string;
notice: INotice[]; notice: NoticeType[];
email: string; email: string;
signature: string; signature: string;
title: string; title: string;
group: string; group: string;
tags: ITag[]; tags: TagType[];
notifyCount: number; notifyCount: number;
unreadCount: number; unreadCount: number;
country: string; country: string;
geographic: IGeographic; geographic: GeographicType;
address: string; address: string;
phone: string; phone: string;
} }
export interface IMember { export interface Member {
avatar: string; avatar: string;
name: string; name: string;
id: string; id: string;
} }
export interface IActivities { export interface ActivitiesType {
id: string; id: string;
updatedAt: string; updatedAt: string;
user: { user: {
...@@ -71,7 +71,7 @@ export interface IActivities { ...@@ -71,7 +71,7 @@ export interface IActivities {
template: string; template: string;
} }
export interface IRadarData { export interface RadarDataType {
label: string; label: string;
name: string; name: string;
value: number; value: number;
......
import { Avatar, Card, Col, List, Row } from 'antd';
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import Link from 'umi/link';
import { Row, Col, Card, List, Avatar } from 'antd';
import { Dispatch } from 'redux';
import EditableLinkGroup from './components/EditableLinkGroup'; import { Dispatch } from 'redux';
import Link from 'umi/link';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import moment from 'moment';
import Radar from './components/Radar'; import Radar from './components/Radar';
import { ModalState } from './model'; import { ModalState } from './model';
import { ICurrentUser, IActivities, IRadarData, INotice } from './data'; import EditableLinkGroup from './components/EditableLinkGroup';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import styles from './style.less'; import styles from './style.less';
import { ActivitiesType, CurrentUser, NoticeType, RadarDataType } from './data.d';
const links = [ const links = [
{ {
...@@ -41,10 +40,10 @@ const links = [ ...@@ -41,10 +40,10 @@ const links = [
]; ];
interface BLOCK_NAME_CAMEL_CASEProps { interface BLOCK_NAME_CAMEL_CASEProps {
currentUser: ICurrentUser; currentUser: CurrentUser;
projectNotice: INotice[]; projectNotice: NoticeType[];
activities: IActivities[]; activities: ActivitiesType[];
radarData: IRadarData[]; radarData: RadarDataType[];
dispatch: Dispatch<any>; dispatch: Dispatch<any>;
currentUserLoading: boolean; currentUserLoading: boolean;
projectLoading: boolean; projectLoading: boolean;
...@@ -83,7 +82,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp ...@@ -83,7 +82,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
}); });
} }
renderActivities(item: IActivities) { renderActivities = (item: ActivitiesType) => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => { const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => {
if (item[key]) { if (item[key]) {
return ( return (
...@@ -113,7 +112,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp ...@@ -113,7 +112,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
/> />
</List.Item> </List.Item>
); );
} };
render() { render() {
const { const {
...@@ -207,11 +206,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp ...@@ -207,11 +206,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
title="动态" title="动态"
loading={activitiesLoading} loading={activitiesLoading}
> >
<List<IActivities> <List<ActivitiesType>
loading={activitiesLoading} loading={activitiesLoading}
renderItem={item => { renderItem={item => this.renderActivities(item)}
return this.renderActivities(item);
}}
dataSource={activities} dataSource={activities}
className={styles.activitiesList} className={styles.activitiesList}
size="large" size="large"
......
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva'; import { EffectsCommandMap } from 'dva';
import { Reducer, AnyAction } from 'redux'; import { ActivitiesType, CurrentUser, NoticeType, RadarDataType } from './data.d';
import { queryCurrent, queryProjectNotice, queryActivities, fakeChartData } from './service'; import { fakeChartData, queryActivities, queryCurrent, queryProjectNotice } from './service';
import { CurrentUser, Notice, Activeties, RadarData } from './data';
export interface ModalState { export interface ModalState {
currentUser: Partial<CurrentUser>; currentUser: Partial<CurrentUser>;
projectNotice: Notice[]; projectNotice: NoticeType[];
activities: Activeties[]; activities: ActivitiesType[];
radarData: RadarData[]; radarData: RadarDataType[];
} }
export type Effect = ( export type Effect = (
......
...@@ -7,6 +7,7 @@ flow ...@@ -7,6 +7,7 @@ flow
```sh ```sh
umi block add ant-design-pro/flow umi block add ant-design-pro/flow
``` ```
## SNAPSHOT ## SNAPSHOT
![SNAPSHOT](./snapshot.png) ![SNAPSHOT](./snapshot.png)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"dev": "umi dev" "dev": "umi dev"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2", "@antv/data-set": "^0.10.2",
"antd": "^3.16.3", "antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0", "bizcharts": "^3.5.3-beta.0",
...@@ -22,13 +23,13 @@ ...@@ -22,13 +23,13 @@
"numeral": "^2.0.6", "numeral": "^2.0.6",
"react": "^16.6.3", "react": "^16.6.3",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"umi": "^2.6.9",
"umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0" "umi-request": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"umi": "^2.6.9", "@types/numeral": "^0.0.25",
"umi-plugin-block-dev": "^1.1.0", "umi-plugin-block-dev": "^1.1.0"
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
}, },
"blockConfig": { "blockConfig": {
"specVersion": "0.1" "specVersion": "0.1"
......
import { CanvasMenu, ContextMenu, EdgeMenu, GroupMenu, MultiMenu, NodeMenu } from 'gg-editor';
import React from 'react'; import React from 'react';
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem'; import MenuItem from './MenuItem';
import styles from './index.less'; import styles from './index.less';
const FlowContextMenu = () => { const FlowContextMenu = () => (
return (
<ContextMenu className={styles.contextMenu}> <ContextMenu className={styles.contextMenu}>
<NodeMenu> <NodeMenu>
<MenuItem command="copy" /> <MenuItem command="copy" />
...@@ -30,7 +30,6 @@ const FlowContextMenu = () => { ...@@ -30,7 +30,6 @@ const FlowContextMenu = () => {
<MenuItem command="pasteHere" icon="paste" text="Paste Here" /> <MenuItem command="pasteHere" icon="paste" text="Paste Here" />
</CanvasMenu> </CanvasMenu>
</ContextMenu> </ContextMenu>
); );
};
export default FlowContextMenu; export default FlowContextMenu;
import React from 'react';
import { Command } from 'gg-editor'; import { Command } from 'gg-editor';
import React from 'react';
import IconFont from '../../common/IconFont'; import IconFont from '../../common/IconFont';
import styles from './index.less'; import styles from './index.less';
const upperFirst = (str: string) => { const upperFirst = (str: string) =>
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
interface MenuItemProps { interface MenuItemProps {
command: string; command: string;
......
import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor';
import React from 'react'; import React from 'react';
import { NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem'; import MenuItem from './MenuItem';
import styles from './index.less'; import styles from './index.less';
const MindContextMenu = () => { const MindContextMenu = () => (
return (
<ContextMenu className={styles.contextMenu}> <ContextMenu className={styles.contextMenu}>
<NodeMenu> <NodeMenu>
<MenuItem command="append" text="Topic" /> <MenuItem command="append" text="Topic" />
...@@ -18,7 +18,6 @@ const MindContextMenu = () => { ...@@ -18,7 +18,6 @@ const MindContextMenu = () => {
<MenuItem command="redo" /> <MenuItem command="redo" />
</CanvasMenu> </CanvasMenu>
</ContextMenu> </ContextMenu>
); );
};
export default MindContextMenu; export default MindContextMenu;
import FlowContextMenu from './FlowContextMenu'; import FlowContextMenu from './FlowContextMenu';
import MindContextMenu from './MindContextMenu';
import KoniContextMenu from './KoniContextMenu'; import KoniContextMenu from './KoniContextMenu';
import MindContextMenu from './MindContextMenu';
export { FlowContextMenu, MindContextMenu, KoniContextMenu }; export { FlowContextMenu, MindContextMenu, KoniContextMenu };
import React, { Fragment } from 'react';
import { Card, Form, Input, Select } from 'antd'; import { Card, Form, Input, Select } from 'antd';
import { withPropsAPI } from 'gg-editor'; import React, { Fragment } from 'react';
import { FormComponentProps } from 'antd/es/form'; import { FormComponentProps } from 'antd/es/form';
import { withPropsAPI } from 'gg-editor';
const upperFirst = (str: string) => { const upperFirst = (str: string) =>
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const { Item } = Form; const { Item } = Form;
const { Option } = Select; const { Option } = Select;
...@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> { ...@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> {
}, 0); }, 0);
}; };
renderEdgeShapeSelect = () => { renderEdgeShapeSelect = () => (
return (
<Select onChange={this.handleSubmit}> <Select onChange={this.handleSubmit}>
<Option value="flow-smooth">Smooth</Option> <Option value="flow-smooth">Smooth</Option>
<Option value="flow-polyline">Polyline</Option> <Option value="flow-polyline">Polyline</Option>
<Option value="flow-polyline-round">Polyline Round</Option> <Option value="flow-polyline-round">Polyline Round</Option>
</Select> </Select>
); );
};
renderNodeDetail = () => { renderNodeDetail = () => {
const { form } = this.props; const { form } = this.props;
......
import React from 'react'; import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd'; import { Card } from 'antd';
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor'; import React from 'react';
import DetailForm from './DetailForm'; import DetailForm from './DetailForm';
import styles from './index.less'; import styles from './index.less';
const FlowDetailPanel = () => { const FlowDetailPanel = () => (
return (
<DetailPanel className={styles.detailPanel}> <DetailPanel className={styles.detailPanel}>
<NodePanel> <NodePanel>
<DetailForm type="node" /> <DetailForm type="node" />
...@@ -23,7 +23,6 @@ const FlowDetailPanel = () => { ...@@ -23,7 +23,6 @@ const FlowDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} /> <Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel> </CanvasPanel>
</DetailPanel> </DetailPanel>
); );
};
export default FlowDetailPanel; export default FlowDetailPanel;
import React from 'react'; import { CanvasPanel, DetailPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd'; import { Card } from 'antd';
import { NodePanel, CanvasPanel, DetailPanel } from 'gg-editor'; import React from 'react';
import DetailForm from './DetailForm'; import DetailForm from './DetailForm';
import styles from './index.less'; import styles from './index.less';
const MindDetailPanel = () => { const MindDetailPanel = () => (
return (
<DetailPanel className={styles.detailPanel}> <DetailPanel className={styles.detailPanel}>
<NodePanel> <NodePanel>
<DetailForm type="node" /> <DetailForm type="node" />
...@@ -14,7 +14,6 @@ const MindDetailPanel = () => { ...@@ -14,7 +14,6 @@ const MindDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} /> <Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel> </CanvasPanel>
</DetailPanel> </DetailPanel>
); );
};
export default MindDetailPanel; export default MindDetailPanel;
import FlowDetailPanel from './FlowDetailPanel'; import FlowDetailPanel from './FlowDetailPanel';
import MindDetailPanel from './MindDetailPanel';
import KoniDetailPanel from './KoniDetailPanel'; import KoniDetailPanel from './KoniDetailPanel';
import MindDetailPanel from './MindDetailPanel';
export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel }; export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel };
import React from 'react'; import { Item, ItemPanel } from 'gg-editor';
import { Card } from 'antd'; import { Card } from 'antd';
import { ItemPanel, Item } from 'gg-editor'; import React from 'react';
import styles from './index.less'; import styles from './index.less';
const FlowItemPanel = () => { const FlowItemPanel = () => (
return (
<ItemPanel className={styles.itemPanel}> <ItemPanel className={styles.itemPanel}>
<Card bordered={false}> <Card bordered={false}>
<Item <Item
...@@ -49,7 +49,6 @@ const FlowItemPanel = () => { ...@@ -49,7 +49,6 @@ const FlowItemPanel = () => {
/> />
</Card> </Card>
</ItemPanel> </ItemPanel>
); );
};
export default FlowItemPanel; export default FlowItemPanel;
import React from 'react'; import { Item, ItemPanel } from 'gg-editor';
import { Card } from 'antd'; import { Card } from 'antd';
import { ItemPanel, Item } from 'gg-editor'; import React from 'react';
import styles from './index.less'; import styles from './index.less';
const KoniItemPanel = () => { const KoniItemPanel = () => (
return (
<ItemPanel className={styles.itemPanel}> <ItemPanel className={styles.itemPanel}>
<Card bordered={false}> <Card bordered={false}>
<Item <Item
...@@ -48,7 +48,6 @@ const KoniItemPanel = () => { ...@@ -48,7 +48,6 @@ const KoniItemPanel = () => {
/> />
</Card> </Card>
</ItemPanel> </ItemPanel>
); );
};
export default KoniItemPanel; export default KoniItemPanel;
import React from 'react';
import { Card } from 'antd'; import { Card } from 'antd';
import { Minimap } from 'gg-editor'; import { Minimap } from 'gg-editor';
import React from 'react';
const EditorMinimap = () => { const EditorMinimap = () => (
return (
<Card type="inner" size="small" title="Minimap" bordered={false}> <Card type="inner" size="small" title="Minimap" bordered={false}>
<Minimap height={200} /> <Minimap height={200} />
</Card> </Card>
); );
};
export default EditorMinimap; export default EditorMinimap;
import React from 'react';
import { Divider } from 'antd'; import { Divider } from 'antd';
import React from 'react';
import { Toolbar } from 'gg-editor'; import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton'; import ToolbarButton from './ToolbarButton';
import styles from './index.less'; import styles from './index.less';
const FlowToolbar = () => { const FlowToolbar = () => (
return (
<Toolbar className={styles.toolbar}> <Toolbar className={styles.toolbar}>
<ToolbarButton command="undo" /> <ToolbarButton command="undo" />
<ToolbarButton command="redo" /> <ToolbarButton command="redo" />
...@@ -26,7 +25,6 @@ const FlowToolbar = () => { ...@@ -26,7 +25,6 @@ const FlowToolbar = () => {
<ToolbarButton command="addGroup" icon="group" text="Add Group" /> <ToolbarButton command="addGroup" icon="group" text="Add Group" />
<ToolbarButton command="unGroup" icon="ungroup" text="Ungroup" /> <ToolbarButton command="unGroup" icon="ungroup" text="Ungroup" />
</Toolbar> </Toolbar>
); );
};
export default FlowToolbar; export default FlowToolbar;
import React from 'react';
import { Divider } from 'antd'; import { Divider } from 'antd';
import React from 'react';
import { Toolbar } from 'gg-editor'; import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton'; import ToolbarButton from './ToolbarButton';
import styles from './index.less'; import styles from './index.less';
const FlowToolbar = () => { const FlowToolbar = () => (
return (
<Toolbar className={styles.toolbar}> <Toolbar className={styles.toolbar}>
<ToolbarButton command="undo" /> <ToolbarButton command="undo" />
<ToolbarButton command="redo" /> <ToolbarButton command="redo" />
...@@ -21,7 +20,6 @@ const FlowToolbar = () => { ...@@ -21,7 +20,6 @@ const FlowToolbar = () => {
<ToolbarButton command="collapse" text="Fold" /> <ToolbarButton command="collapse" text="Fold" />
<ToolbarButton command="expand" text="Unfold" /> <ToolbarButton command="expand" text="Unfold" />
</Toolbar> </Toolbar>
); );
};
export default FlowToolbar; export default FlowToolbar;
import { Command } from 'gg-editor';
import React from 'react'; import React from 'react';
import { Tooltip } from 'antd'; import { Tooltip } from 'antd';
import { Command } from 'gg-editor';
import IconFont from '../../common/IconFont'; import IconFont from '../../common/IconFont';
import styles from './index.less'; import styles from './index.less';
const upperFirst = (str: string) => { const upperFirst = (str: string) =>
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
interface ToolbarButtonProps { interface ToolbarButtonProps {
command: string; command: string;
......
import FlowToolbar from './FlowToolbar'; import FlowToolbar from './FlowToolbar';
import MindToolbar from './MindToolbar';
import KoniToolbar from './KoniToolbar'; import KoniToolbar from './KoniToolbar';
import MindToolbar from './MindToolbar';
export { FlowToolbar, MindToolbar, KoniToolbar }; export { FlowToolbar, MindToolbar, KoniToolbar };
import React from 'react'; import { Col, Row } from 'antd';
import { Row, Col } from 'antd';
import GGEditor, { Flow } from 'gg-editor'; import GGEditor, { Flow } from 'gg-editor';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import React from 'react';
import { formatMessage } from 'umi-plugin-react/locale';
import EditorMinimap from './components/EditorMinimap'; import EditorMinimap from './components/EditorMinimap';
import { FlowContextMenu } from './components/EditorContextMenu'; import { FlowContextMenu } from './components/EditorContextMenu';
import { FlowToolbar } from './components/EditorToolbar';
import { FlowItemPanel } from './components/EditorItemPanel';
import { FlowDetailPanel } from './components/EditorDetailPanel'; import { FlowDetailPanel } from './components/EditorDetailPanel';
import { FlowItemPanel } from './components/EditorItemPanel';
import { FlowToolbar } from './components/EditorToolbar';
import styles from './index.less'; import styles from './index.less';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { formatMessage } from 'umi-plugin-react/locale';
GGEditor.setTrackable(false); GGEditor.setTrackable(false);
export default () => { export default () => (
return (
<PageHeaderWrapper <PageHeaderWrapper
content={formatMessage({ content={formatMessage({
id: 'BLOCK_NAME.description', id: 'BLOCK_NAME.description',
...@@ -41,5 +41,4 @@ export default () => { ...@@ -41,5 +41,4 @@ export default () => {
<FlowContextMenu /> <FlowContextMenu />
</GGEditor> </GGEditor>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
};
...@@ -7,6 +7,7 @@ flow ...@@ -7,6 +7,7 @@ flow
```sh ```sh
umi block add ant-design-pro/flow umi block add ant-design-pro/flow
``` ```
## SNAPSHOT ## SNAPSHOT
![SNAPSHOT](./snapshot.png) ![SNAPSHOT](./snapshot.png)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"dev": "umi dev" "dev": "umi dev"
}, },
"dependencies": { "dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2", "@antv/data-set": "^0.10.2",
"antd": "^3.16.3", "antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0", "bizcharts": "^3.5.3-beta.0",
...@@ -22,13 +23,14 @@ ...@@ -22,13 +23,14 @@
"numeral": "^2.0.6", "numeral": "^2.0.6",
"react": "^16.6.3", "react": "^16.6.3",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"umi-request": "^1.0.0" "umi-request": "^1.0.0",
"umi-plugin-react": "^1.7.2",
"umi-plugin-block-dev": "^1.1.0"
}, },
"devDependencies": { "devDependencies": {
"umi": "^2.6.9", "@types/numeral": "^0.0.25",
"umi-plugin-block-dev": "^1.1.0", "umi": "^2.6.9"
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
}, },
"blockConfig": { "blockConfig": {
"specVersion": "0.1" "specVersion": "0.1"
......
import { CanvasMenu, ContextMenu, EdgeMenu, GroupMenu, MultiMenu, NodeMenu } from 'gg-editor';
import React from 'react'; import React from 'react';
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem'; import MenuItem from './MenuItem';
import styles from './index.less'; import styles from './index.less';
const FlowContextMenu = () => { const FlowContextMenu = () => (
return (
<ContextMenu className={styles.contextMenu}> <ContextMenu className={styles.contextMenu}>
<NodeMenu> <NodeMenu>
<MenuItem command="copy" /> <MenuItem command="copy" />
...@@ -30,7 +30,6 @@ const FlowContextMenu = () => { ...@@ -30,7 +30,6 @@ const FlowContextMenu = () => {
<MenuItem command="pasteHere" icon="paste" text="Paste Here" /> <MenuItem command="pasteHere" icon="paste" text="Paste Here" />
</CanvasMenu> </CanvasMenu>
</ContextMenu> </ContextMenu>
); );
};
export default FlowContextMenu; export default FlowContextMenu;
import React from 'react';
import { Command } from 'gg-editor'; import { Command } from 'gg-editor';
import React from 'react';
import IconFont from '../../common/IconFont'; import IconFont from '../../common/IconFont';
import styles from './index.less'; import styles from './index.less';
const upperFirst = (str: string) => { const upperFirst = (str: string) =>
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
interface MenuItemProps { interface MenuItemProps {
command: string; command: string;
......
import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor';
import React from 'react'; import React from 'react';
import { NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem'; import MenuItem from './MenuItem';
import styles from './index.less'; import styles from './index.less';
const MindContextMenu = () => { const MindContextMenu = () => (
return (
<ContextMenu className={styles.contextMenu}> <ContextMenu className={styles.contextMenu}>
<NodeMenu> <NodeMenu>
<MenuItem command="append" text="Topic" /> <MenuItem command="append" text="Topic" />
...@@ -18,7 +18,6 @@ const MindContextMenu = () => { ...@@ -18,7 +18,6 @@ const MindContextMenu = () => {
<MenuItem command="redo" /> <MenuItem command="redo" />
</CanvasMenu> </CanvasMenu>
</ContextMenu> </ContextMenu>
); );
};
export default MindContextMenu; export default MindContextMenu;
import FlowContextMenu from './FlowContextMenu'; import FlowContextMenu from './FlowContextMenu';
import MindContextMenu from './MindContextMenu';
import KoniContextMenu from './KoniContextMenu'; import KoniContextMenu from './KoniContextMenu';
import MindContextMenu from './MindContextMenu';
export { FlowContextMenu, MindContextMenu, KoniContextMenu }; export { FlowContextMenu, MindContextMenu, KoniContextMenu };
import React, { Fragment } from 'react';
import { Card, Form, Input, Select } from 'antd'; import { Card, Form, Input, Select } from 'antd';
import { withPropsAPI } from 'gg-editor'; import React, { Fragment } from 'react';
import { FormComponentProps } from 'antd/es/form'; import { FormComponentProps } from 'antd/es/form';
import { withPropsAPI } from 'gg-editor';
const upperFirst = (str: string) => { const upperFirst = (str: string) =>
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const { Item } = Form; const { Item } = Form;
const { Option } = Select; const { Option } = Select;
...@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> { ...@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> {
}, 0); }, 0);
}; };
renderEdgeShapeSelect = () => { renderEdgeShapeSelect = () => (
return (
<Select onChange={this.handleSubmit}> <Select onChange={this.handleSubmit}>
<Option value="flow-smooth">Smooth</Option> <Option value="flow-smooth">Smooth</Option>
<Option value="flow-polyline">Polyline</Option> <Option value="flow-polyline">Polyline</Option>
<Option value="flow-polyline-round">Polyline Round</Option> <Option value="flow-polyline-round">Polyline Round</Option>
</Select> </Select>
); );
};
renderNodeDetail = () => { renderNodeDetail = () => {
const { form } = this.props; const { form } = this.props;
......
import React from 'react'; import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd'; import { Card } from 'antd';
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor'; import React from 'react';
import DetailForm from './DetailForm'; import DetailForm from './DetailForm';
import styles from './index.less'; import styles from './index.less';
const FlowDetailPanel = () => { const FlowDetailPanel = () => (
return (
<DetailPanel className={styles.detailPanel}> <DetailPanel className={styles.detailPanel}>
<NodePanel> <NodePanel>
<DetailForm type="node" /> <DetailForm type="node" />
...@@ -23,7 +23,6 @@ const FlowDetailPanel = () => { ...@@ -23,7 +23,6 @@ const FlowDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} /> <Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel> </CanvasPanel>
</DetailPanel> </DetailPanel>
); );
};
export default FlowDetailPanel; export default FlowDetailPanel;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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