Commit 45474f29 authored by 愚道's avatar 愚道

migrate workplace to ts

parent 127df717
...@@ -3,7 +3,7 @@ export default { ...@@ -3,7 +3,7 @@ export default {
[ [
'umi-plugin-block-dev', 'umi-plugin-block-dev',
{ {
layout: 'ant-design-pro-user', layout: 'ant-design-pro',
menu: { menu: {
name: '主页', name: '主页',
icon: 'home', icon: 'home',
......
import React, { PureComponent, createElement } from 'react'; import React, { PureComponent, createElement } from 'react';
import PropTypes from 'prop-types'; import PropTypes, { string } from 'prop-types';
import { Button } from 'antd'; import { Button } from 'antd';
import styles from './index.less'; import styles from './index.less';
// TODO: 添加逻辑 export interface EditableLink {
title: string;
href: string;
}
interface EditableLinkGroupProps {
onAdd: () => void;
links: EditableLink[];
linkElement: React.Component;
}
class EditableLinkGroup extends PureComponent { class EditableLinkGroup extends PureComponent<EditableLinkGroupProps> {
static propTypes = { static propTypes = {
links: PropTypes.array, links: PropTypes.array,
onAdd: PropTypes.func, onAdd: PropTypes.func,
......
@import '~antd/lib/style/themes/default.less'; @import '~antd/lib/style/themes/default.less';
.content { .children-content {
margin: 24px 24px 0; margin: 24px 24px 0;
} }
@media screen and (max-width: @screen-sm) { .main {
.detail {
display: flex;
}
.row {
display: flex;
width: 100%;
}
.title-content {
margin-bottom: 16px;
}
@media screen and (max-width: @screen-sm) {
.content { .content {
margin: 24px 0 0; margin: 24px 0 0;
} }
}
.title,
.content {
flex: auto;
}
.extraContent,
.main {
flex: 0 1 auto;
}
.main {
width: 100%;
}
.title {
margin-bottom: 16px;
}
.logo,
.content,
.extraContent {
margin-bottom: 16px;
}
.extraContent {
min-width: 242px;
margin-left: 88px;
text-align: right;
}
}
@media screen and (max-width: @screen-xl) {
.extraContent {
margin-left: 44px;
}
}
@media screen and (max-width: @screen-lg) {
.extraContent {
margin-left: 20px;
}
}
@media screen and (max-width: @screen-md) {
.row {
display: block;
}
.action,
.extraContent {
margin-left: 0;
text-align: left;
}
}
@media screen and (max-width: @screen-sm) {
.detail {
display: block;
}
} }
import React from 'react'; import React from 'react';
import { FormattedMessage } from 'umi-plugin-react/locale'; import { RouteContext } from '@ant-design/pro-layout';
import Link from 'umi/link'; import { PageHeader, Typography } from 'antd';
import { PageHeader } from 'ant-design-pro';
import styles from './index.less'; import styles from './index.less';
import { GridContent } from '@ant-design/pro-layout';
const PageHeaderWrapper = ({ children, contentWidth, wrapperClassName, ...restProps }) => ( interface IPageHeaderWrapperProps {
<div style={{ margin: '-24px -24px 0' }} className={wrapperClassName}> content?: React.ReactNode;
title?: React.ReactNode;
extraContent?: React.ReactNode;
}
const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({
children,
content,
title,
extraContent,
...restProps
}) => (
<RouteContext.Consumer>
{value => (
<div style={{ margin: '-24px -24px 0' }}>
<PageHeader <PageHeader
wide={contentWidth === 'Fixed'} title={title}
home={<FormattedMessage id="BLOCK_NAME.menu.home" defaultMessage="Home" />}
key="pageheader"
{...restProps} {...restProps}
linkElement={Link} {...value}
itemRender={item => { >
if (item.locale) { <div className={styles.detail}>
return <FormattedMessage id={item.locale} defaultMessage={item.title} />; <div className={styles.main}>
} <div className={styles.row}>
return item.title; {content && <div className={styles.content}>{content}</div>}
}} {extraContent && <div className={styles.extraContent}>{extraContent}</div>}
/> </div>
{children ? <div className={styles.content}>{children}</div> : null} </div>
</div>
</PageHeader>
{children ? (
<GridContent>
<div className={styles['children-content']}>{children}</div>
</GridContent>
) : null}
</div> </div>
)}
</RouteContext.Consumer>
); );
export default PageHeaderWrapper; export default PageHeaderWrapper;
export interface ITag {
key: string;
label: string;
}
export interface Province {
label: string;
key: string;
}
export interface City {
label: string;
key: string;
}
export interface Geographic {
province: Province;
city: City;
}
export interface Notice {
id: string;
title: string;
logo: string;
description: string;
updatedAt: string;
member: string;
href: string;
memberLink: string;
}
export interface CurrentUser {
name: string;
avatar: string;
userid: string;
notice: Notice[];
email: string;
signature: string;
title: string;
group: string;
tags: ITag[];
notifyCount: number;
unreadCount: number;
country: string;
geographic: Geographic;
address: string;
phone: string;
}
export interface Member {
avatar: string;
name: string;
id: string;
}
export interface Activeties {
id: string,
updatedAt: string,
user: {
name: string,
avatar: string,
},
group: {
name: string,
link: string,
},
project: {
name: string,
link: string,
},
template: string,
}
export interface RadarData {
label: string;
name: string;
value: number;
}
...@@ -3,10 +3,13 @@ import moment from 'moment'; ...@@ -3,10 +3,13 @@ import moment from 'moment';
import { connect } from 'dva'; import { connect } from 'dva';
import Link from 'umi/link'; import Link from 'umi/link';
import { Row, Col, Card, List, Avatar } from 'antd'; import { Row, Col, Card, List, Avatar } from 'antd';
import { Dispatch } from 'redux';
import { Charts } from 'ant-design-pro'; import { Charts } from 'ant-design-pro';
import EditableLinkGroup from './components/EditableLinkGroup'; import EditableLinkGroup from './components/EditableLinkGroup';
import PageHeaderWrapper from './components/PageHeaderWrapper'; import PageHeaderWrapper from './components/PageHeaderWrapper';
import { ModalState } from './model';
import { CurrentUser, Activeties, RadarData, Notice } from './data';
import styles from './style.less'; import styles from './style.less';
...@@ -39,16 +42,33 @@ const links = [ ...@@ -39,16 +42,33 @@ const links = [
}, },
]; ];
@connect(({ BLOCK_NAME_CAMEL_CASE: { user, project, activities, chart }, loading }) => ({ interface BLOCK_NAME_CAMEL_CASEProps {
currentUser: user.currentUser, currentUser: CurrentUser;
project, projectNotice: Notice[];
activities: Activeties[];
radarData: RadarData[];
dispatch: Dispatch;
currentUserLoading: boolean;
projectLoading: boolean;
activitiesLoading: boolean;
}
@connect(({
BLOCK_NAME_CAMEL_CASE: { currentUser, projectNotice, activities, radarData },
loading,
}: {
BLOCK_NAME_CAMEL_CASE: ModalState,
loading: { effects: any },
}) => ({
currentUser,
projectNotice,
activities, activities,
chart, radarData,
currentUserLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchUserCurrent'], currentUserLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchUserCurrent'],
projectLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchProjectNotice'], projectLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchProjectNotice'],
activitiesLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchActivitiesList'], activitiesLoading: loading.effects['BLOCK_NAME_CAMEL_CASE/fetchActivitiesList'],
})) }))
class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProps> {
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch({ dispatch({
...@@ -65,9 +85,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -65,9 +85,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
renderActivities() { renderActivities() {
const { const {
activities: { list }, activities,
} = this.props; } = this.props;
return list.map(item => { return activities.map(item => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => { const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => {
if (item[key]) { if (item[key]) {
return ( return (
...@@ -103,11 +123,10 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -103,11 +123,10 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
render() { render() {
const { const {
currentUser, currentUser,
currentUserLoading, projectNotice,
project: { notice },
projectLoading, projectLoading,
activitiesLoading, activitiesLoading,
chart: { radarData }, radarData,
} = this.props; } = this.props;
const pageHeaderContent = const pageHeaderContent =
...@@ -150,7 +169,6 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -150,7 +169,6 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
return ( return (
<PageHeaderWrapper <PageHeaderWrapper
loading={currentUserLoading}
content={pageHeaderContent} content={pageHeaderContent}
extraContent={extraContent} extraContent={extraContent}
> >
...@@ -165,7 +183,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -165,7 +183,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
loading={projectLoading} loading={projectLoading}
bodyStyle={{ padding: 0 }} bodyStyle={{ padding: 0 }}
> >
{notice.map(item => ( {projectNotice.map(item => (
<Card.Grid className={styles.projectGrid} key={item.id}> <Card.Grid className={styles.projectGrid} key={item.id}>
<Card bodyStyle={{ padding: 0 }} bordered={false}> <Card bodyStyle={{ padding: 0 }} bordered={false}>
<Card.Meta <Card.Meta
...@@ -228,7 +246,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -228,7 +246,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
> >
<div className={styles.members}> <div className={styles.members}>
<Row gutter={48}> <Row gutter={48}>
{notice.map(item => ( {projectNotice.map(item => (
<Col span={12} key={`members-item-${item.id}`}> <Col span={12} key={`members-item-${item.id}`}>
<Link to={item.href}> <Link to={item.href}>
<Avatar src={item.logo} size="small" /> <Avatar src={item.logo} size="small" />
......
import { EffectsCommandMap } from 'dva';
import { Reducer, AnyAction } from 'redux';
import { queryCurrent, queryProjectNotice, queryActivities, fakeChartData } from './service'; import { queryCurrent, queryProjectNotice, queryActivities, fakeChartData } from './service';
import { CurrentUser, Notice, Activeties, RadarData } from './data';
export default { export interface ModalState {
namespace: 'BLOCK_NAME_CAMEL_CASE', currentUser: Partial<CurrentUser>;
state: { projectNotice: Notice[];
user: { activities: Activeties[];
currentUser: {}, radarData: RadarData[];
}, }
project: {
notice: [], export type Effect = (
}, action: AnyAction,
activities: { effects: EffectsCommandMap & { select: <T>(func: (state: ModalState) => T) => T }
list: [], ) => void;
},
chart: { export interface ModelType {
visitData: [], namespace: string;
visitData2: [], state: ModalState;
salesData: [],
searchData: [],
offlineData: [],
offlineChartData: [],
salesTypeData: [],
salesTypeDataOnline: [],
salesTypeDataOffline: [],
radarData: [],
loading: false,
},
},
reducers: { reducers: {
saveCurrentUser(state, action) { save: Reducer<ModalState>;
return { clear: Reducer<ModalState>;
...state,
user: {
currentUser: action.payload || {},
},
}; };
}, effects: {
saveNotice(state, action) { init: Effect;
return { fetchUserCurrent: Effect;
...state, fetchProjectNotice: Effect;
project: { fetchActivitiesList: Effect;
notice: action.payload, fetchChart: Effect;
},
};
},
saveList(state, action) {
return {
...state,
activities: {
list: action.payload,
},
};
},
saveChart(state, { payload }) {
return {
...state,
chart: {
...payload,
},
}; };
}, }
clear(state) {
return { const Model: ModelType = {
...state, namespace: 'BLOCK_NAME_CAMEL_CASE',
chart: { state: {
visitData: [], currentUser: {},
visitData2: [], projectNotice: [],
salesData: [], activities: [],
searchData: [],
offlineData: [],
offlineChartData: [],
salesTypeData: [],
salesTypeDataOnline: [],
salesTypeDataOffline: [],
radarData: [], radarData: [],
}, },
};
},
},
effects: { effects: {
*init(_, { put }) { *init(_, { put }) {
yield put({ type: 'fetchUserCurrent' }); yield put({ type: 'fetchUserCurrent' });
...@@ -87,30 +49,56 @@ export default { ...@@ -87,30 +49,56 @@ export default {
*fetchUserCurrent(_, { call, put }) { *fetchUserCurrent(_, { call, put }) {
const response = yield call(queryCurrent); const response = yield call(queryCurrent);
yield put({ yield put({
type: 'saveCurrentUser', type: 'save',
payload: response, payload: {
currentUser: response,
},
}); });
}, },
*fetchProjectNotice(_, { call, put }) { *fetchProjectNotice(_, { call, put }) {
const response = yield call(queryProjectNotice); const response = yield call(queryProjectNotice);
yield put({ yield put({
type: 'saveNotice', type: 'save',
payload: Array.isArray(response) ? response : [], payload: {
projectNotice: Array.isArray(response) ? response : [],
}
}); });
}, },
*fetchActivitiesList(_, { call, put }) { *fetchActivitiesList(_, { call, put }) {
const response = yield call(queryActivities); const response = yield call(queryActivities);
yield put({ yield put({
type: 'saveList', type: 'save',
payload: Array.isArray(response) ? response : [], payload: {
activities: Array.isArray(response) ? response : [],
}
}); });
}, },
*fetchChart(_, { call, put }) { *fetchChart(_, { call, put }) {
const response = yield call(fakeChartData); const { radarData } = yield call(fakeChartData);
yield put({ yield put({
type: 'saveChart', type: 'save',
payload: response, payload: {
radarData,
},
}); });
}, },
}, },
reducers: {
save(state, { payload }) {
return {
...state,
...payload,
};
},
clear() {
return {
currentUser: {},
projectNotice: [],
activities: [],
radarData: [],
};
},
},
}; };
export default Model;
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