Commit a1b9d9b2 authored by 陈帅's avatar 陈帅

CardList finish

parent e1843dd8
import React from 'react'; import React from 'react';
import { RouteContext } from '@ant-design/pro-layout'; import { RouteContext } from '@ant-design/pro-layout';
import { PageHeader } from 'antd'; import { PageHeader, Typography } from 'antd';
import styles from './index.less'; import styles from './index.less';
interface IPageHeaderWrapperProps { interface IPageHeaderWrapperProps {
...@@ -10,13 +10,27 @@ interface IPageHeaderWrapperProps { ...@@ -10,13 +10,27 @@ interface IPageHeaderWrapperProps {
const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({ const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({
children, children,
title,
content, content,
...restProps ...restProps
}) => ( }) => (
<RouteContext.Consumer> <RouteContext.Consumer>
{value => ( {value => (
<div style={{ margin: '-24px -24px 0' }}> <div style={{ margin: '-24px -24px 0' }}>
<PageHeader {...restProps} {...value}> <PageHeader
title={
<Typography.Title
level={4}
style={{
margin: 0,
}}
>
{title}
</Typography.Title>
}
{...restProps}
{...value}
>
{content} {content}
</PageHeader> </PageHeader>
{children ? <div className={styles.content}>{children}</div> : null} {children ? <div className={styles.content}>{children}</div> : null}
......
...@@ -57,7 +57,11 @@ function fakeList(count: number): BasicListItemDataType[] { ...@@ -57,7 +57,11 @@ function fakeList(count: number): BasicListItemDataType[] {
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], status: ['active', 'exception', 'normal'][i % 3] as
| 'normal'
| 'exception'
| 'active'
| 'success',
percent: Math.ceil(Math.random() * 50) + 50, percent: Math.ceil(Math.random() * 50) + 50,
logo: avatars[i % 8], logo: avatars[i % 8],
href: 'https://ant.design', href: 'https://ant.design',
......
import React from 'react'; import React from 'react';
import { RouteContext } from '@ant-design/pro-layout'; import { RouteContext } from '@ant-design/pro-layout';
import { PageHeader } from 'antd'; import { PageHeader, Typography } from 'antd';
import styles from './index.less'; import styles from './index.less';
interface IPageHeaderWrapperProps { interface IPageHeaderWrapperProps {
...@@ -8,15 +8,23 @@ interface IPageHeaderWrapperProps { ...@@ -8,15 +8,23 @@ interface IPageHeaderWrapperProps {
title: React.ReactNode; title: React.ReactNode;
} }
const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({ const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({ children, content, title }) => (
children,
content,
...restProps
}) => (
<RouteContext.Consumer> <RouteContext.Consumer>
{value => ( {value => (
<div style={{ margin: '-24px -24px 0' }}> <div style={{ margin: '-24px -24px 0' }}>
<PageHeader {...restProps} {...value}> <PageHeader
title={
<Typography.Title
level={4}
style={{
margin: 0,
}}
>
{title}
</Typography.Title>
}
{...value}
>
{content} {content}
</PageHeader> </PageHeader>
{children ? <div className={styles.content}>{children}</div> : null} {children ? <div className={styles.content}>{children}</div> : null}
......
import { CardListItemDataType } from './data';
const titles = [ const titles = [
'Alipay', 'Alipay',
'Angular', 'Angular',
...@@ -32,6 +34,7 @@ const desc = [ ...@@ -32,6 +34,7 @@ const desc = [
'城镇中有那么多的酒馆,她却偏偏走进了我的酒馆', '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
'那时候我只会想自己想要什么,从不想自己拥有什么', '那时候我只会想自己想要什么,从不想自己拥有什么',
]; ];
const user = [ const user = [
'付小小', '付小小',
'曲丽丽', '曲丽丽',
...@@ -45,7 +48,7 @@ const user = [ ...@@ -45,7 +48,7 @@ const user = [
'仲尼', '仲尼',
]; ];
function fakeList(count) { function fakeList(count: number): CardListItemDataType[] {
const list = []; const list = [];
for (let i = 0; i < count; i += 1) { for (let i = 0; i < count; i += 1) {
list.push({ list.push({
...@@ -53,13 +56,17 @@ function fakeList(count) { ...@@ -53,13 +56,17 @@ function fakeList(count) {
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], status: ['active', 'exception', 'normal'][i % 3] as
| 'normal'
| 'exception'
| 'active'
| 'success',
percent: Math.ceil(Math.random() * 50) + 50, percent: Math.ceil(Math.random() * 50) + 50,
logo: avatars[i % 8], logo: avatars[i % 8],
href: 'https://ant.design', href: 'https://ant.design',
updatedAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i), updatedAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i).getTime(),
createdAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i), createdAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i).getTime(),
subDescription: desc[i % 5], subDescription: desc[i % 5],
description: description:
'在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。', '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。',
...@@ -93,7 +100,7 @@ function fakeList(count) { ...@@ -93,7 +100,7 @@ function fakeList(count) {
return list; return list;
} }
function getFakeList(req, res) { function getFakeList(req: { query: any }, res: { json: (arg0: CardListItemDataType[]) => void }) {
const params = req.query; const params = req.query;
const count = params.count * 1 || 20; const count = params.count * 1 || 20;
......
import React from 'react';
import { FormattedMessage } from 'umi-plugin-react/locale';
import Link from 'umi/link';
import { PageHeader } from 'ant-design-pro';
import styles from './index.less';
const PageHeaderWrapper = ({ children, wrapperClassName, ...restProps }) => (
<div style={{ margin: '-24px -24px 0' }} className={wrapperClassName}>
<PageHeader
home={<FormattedMessage id="BLOCK_NAME.menu.home" defaultMessage="Home" />}
key="pageheader"
{...restProps}
linkElement={Link}
itemRender={item => {
if (item.locale) {
return <FormattedMessage id={item.locale} defaultMessage={item.title} />;
}
return item.title;
}}
/>
{children ? <div className={styles.content}>{children}</div> : null}
</div>
);
export default PageHeaderWrapper;
@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 { RouteContext } from '@ant-design/pro-layout';
import { PageHeader, Typography } from 'antd';
import styles from './index.less';
import { GridContent } from '@ant-design/pro-layout';
interface IPageHeaderWrapperProps {
content?: React.ReactNode;
title: React.ReactNode;
extraContent?: React.ReactNode;
}
const PageHeaderWrapper: React.SFC<IPageHeaderWrapperProps> = ({
children,
title,
content,
extraContent,
...restProps
}) => (
<RouteContext.Consumer>
{value => (
<div style={{ margin: '-24px -24px 0' }}>
<PageHeader
title={
<Typography.Title
level={4}
style={{
margin: 0,
}}
>
{title}
</Typography.Title>
}
{...restProps}
{...value}
>
<div className={styles.detail}>
<div className={styles.main}>
<div className={styles.row}>
{content && <div className={styles.content}>{content}</div>}
{extraContent && <div className={styles.extraContent}>{extraContent}</div>}
</div>
</div>
</div>
</PageHeader>
{children ? (
<GridContent>
<div className={styles['children-content']}>{children}</div>
</GridContent>
) : null}
</div>
)}
</RouteContext.Consumer>
);
export default PageHeaderWrapper;
export interface Member {
avatar: string;
name: string;
id: string;
}
export interface CardListItemDataType {
id: string;
owner: string;
title: string;
avatar: string;
cover: string;
status: 'normal' | 'exception' | 'active' | 'success';
percent: number;
logo: string;
href: string;
body?: any;
updatedAt: number;
createdAt: number;
subDescription: string;
description: string;
activeUser: number;
newUser: number;
star: number;
like: number;
message: number;
content: string;
members: Member[];
}
import React, { PureComponent } from 'react'; import React, { Component } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { Card, Button, Icon, List } from 'antd'; import { Dispatch } from 'redux';
import { IStateType } from './model';
import { Ellipsis } from 'ant-design-pro'; import { CardListItemDataType } from './data';
import { Card, Button, Typography, Icon, List } from 'antd';
import PageHeaderWrapper from './components/PageHeaderWrapper'; import PageHeaderWrapper from './components/PageHeaderWrapper';
const { Paragraph } = Typography;
import styles from './style.less'; import styles from './style.less';
@connect(({ BLOCK_NAME_CAMEL_CASE, loading }) => ({ interface PAGE_NAME_UPPER_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE: IStateType;
dispatch: Dispatch;
loading: boolean;
}
interface PAGE_NAME_UPPER_CAMEL_CASEState {
visible: boolean;
done: boolean;
current?: Partial<CardListItemDataType>;
}
@connect(
({
BLOCK_NAME_CAMEL_CASE,
loading,
}: {
BLOCK_NAME_CAMEL_CASE: IStateType;
loading: {
models: { [key: string]: boolean };
};
}) => ({
BLOCK_NAME_CAMEL_CASE, BLOCK_NAME_CAMEL_CASE,
loading: loading.models.list, loading: loading.models.list,
})) })
class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { )
class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
PAGE_NAME_UPPER_CAMEL_CASEProps,
PAGE_NAME_UPPER_CAMEL_CASEState
> {
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch({ dispatch({
...@@ -59,7 +86,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -59,7 +86,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
/> />
</div> </div>
); );
const nullData = {} as CardListItemDataType;
return ( return (
<PageHeaderWrapper title="卡片列表" content={content} extraContent={extraContent}> <PageHeaderWrapper title="卡片列表" content={content} extraContent={extraContent}>
<div className={styles.cardList}> <div className={styles.cardList}>
...@@ -67,7 +94,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -67,7 +94,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
rowKey="id" rowKey="id"
loading={loading} loading={loading}
grid={{ gutter: 24, lg: 3, md: 2, sm: 1, xs: 1 }} grid={{ gutter: 24, lg: 3, md: 2, sm: 1, xs: 1 }}
dataSource={['', ...list]} dataSource={[nullData, ...list]}
renderItem={item => renderItem={item =>
item ? ( item ? (
<List.Item key={item.id}> <List.Item key={item.id}>
...@@ -76,9 +103,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent { ...@@ -76,9 +103,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
avatar={<img alt="" className={styles.cardAvatar} src={item.avatar} />} avatar={<img alt="" className={styles.cardAvatar} src={item.avatar} />}
title={<a>{item.title}</a>} title={<a>{item.title}</a>}
description={ description={
<Ellipsis className={styles.item} lines={3}> <Paragraph className={styles.item} ellipsis={{ rows: 3 }}>
{item.description} {item.description}
</Ellipsis> </Paragraph>
} }
/> />
</Card> </Card>
......
import { queryFakeList } from './service'; import { queryFakeList } from './service';
import { CardListItemDataType } from './data';
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
export default { export interface IStateType {
list: CardListItemDataType[];
}
export type Effect = (
action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: IStateType) => T) => T }
) => void;
export interface ModelType {
namespace: string;
state: IStateType;
effects: {
fetch: Effect;
};
reducers: {
queryList: Reducer<IStateType>;
};
}
const Model: ModelType = {
namespace: 'BLOCK_NAME_CAMEL_CASE', namespace: 'BLOCK_NAME_CAMEL_CASE',
state: { state: {
...@@ -26,3 +50,5 @@ export default { ...@@ -26,3 +50,5 @@ export default {
}, },
}, },
}; };
export default Model;
import request from 'umi-request'; import request from 'umi-request';
export async function queryFakeList(params) { export async function queryFakeList(params: { count: number }) {
return request(`/api/BLOCK_NAME/fake_list`, { return request(`/api/BLOCK_NAME/fake_list`, {
params, params,
}); });
......
...@@ -36,9 +36,9 @@ ...@@ -36,9 +36,9 @@
} }
.extraImg { .extraImg {
margin-top: -60px; margin-top: -20px;
text-align: center; text-align: center;
width: 195px; width: 155px;
img { img {
width: 100%; width: 100%;
} }
......
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "cross-env PAGES_PATH='BasicProfile/src' umi dev", "dev": "cross-env PAGES_PATH='CardList/src' umi dev",
"lint:style": "stylelint \"src/**/*.less\" --syntax less", "lint:style": "stylelint \"src/**/*.less\" --syntax less",
"lint": "eslint --ext .js src mock tests && npm run lint:style", "lint": "eslint --ext .js src mock tests && npm run lint:style",
"lint:fix": "eslint --fix --ext .js src mock tests && npm run lint:style", "lint:fix": "eslint --fix --ext .js src mock tests && npm run lint:style",
......
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