Commit 27d50044 authored by 陈帅's avatar 陈帅

SearchListArticles finish

parent 18e249b4
import { ListItemDataType } from './data';
const titles = [ const titles = [
'Alipay', 'Alipay',
'Angular', 'Angular',
...@@ -45,7 +47,7 @@ const user = [ ...@@ -45,7 +47,7 @@ const user = [
'仲尼', '仲尼',
]; ];
function fakeList(count) { function fakeList(count: number): ListItemDataType[] {
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 +55,17 @@ function fakeList(count) { ...@@ -53,13 +55,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 +99,7 @@ function fakeList(count) { ...@@ -93,7 +99,7 @@ function fakeList(count) {
return list; return list;
} }
function getFakeList(req, res) { function getFakeList(req: { query: any }, res: { json: (arg0: any[]) => void }) {
const params = req.query; const params = req.query;
const count = params.count * 1 || 20; const count = params.count * 1 || 20;
......
...@@ -53,9 +53,9 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> { ...@@ -53,9 +53,9 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> {
static defaultProps = { static defaultProps = {
hideCheckAll: false, hideCheckAll: false,
actionsText: { actionsText: {
expandText: 'Expand', expandText: '展开',
collapseText: 'Collapse', collapseText: '收起',
selectAllText: 'All', selectAllText: '全部',
}, },
}; };
static Option: TagSelectOption = TagSelectOption; static Option: TagSelectOption = TagSelectOption;
...@@ -130,7 +130,7 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> { ...@@ -130,7 +130,7 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> {
const { value, expand } = this.state; const { value, expand } = this.state;
const { children, hideCheckAll, className, style, expandable, actionsText = {} } = this.props; const { children, hideCheckAll, className, style, expandable, actionsText = {} } = this.props;
const checkedAll = this.getAllTags().length === value.length; const checkedAll = this.getAllTags().length === value.length;
const { expandText = 'Expand', collapseText = 'Collapse', selectAllText = 'All' } = actionsText; const { expandText = '展开', collapseText = '收起', selectAllText = '全部' } = actionsText;
const cls = classNames(styles.tagSelect, className, { const cls = classNames(styles.tagSelect, className, {
[styles.hasExpandTag]: expandable, [styles.hasExpandTag]: expandable,
...@@ -145,6 +145,7 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> { ...@@ -145,6 +145,7 @@ class TagSelect extends Component<TagSelectProps, TagSelectState> {
</CheckableTag> </CheckableTag>
)} )}
{value && {value &&
children &&
React.Children.map(children, (child: React.ReactElement<TagSelectOption>) => { React.Children.map(children, (child: React.ReactElement<TagSelectOption>) => {
if (this.isTagSelectOption(child)) { if (this.isTagSelectOption(child)) {
return React.cloneElement(child, { return React.cloneElement(child, {
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import numeral from 'numeral'; import numeral from 'numeral';
import { connect } from 'dva'; import { connect } from 'dva';
import { import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Dropdown, Menu } from 'antd';
Row,
Col,
Form,
Card,
Select,
Icon,
Avatar,
List,
Tooltip,
Dropdown,
Menu,
Input,
} from 'antd';
import TagSelect from './components/TagSelect'; import TagSelect from './components/TagSelect';
import StandardFormRow from './components/StandardFormRow'; import StandardFormRow from './components/StandardFormRow';
import PageHeaderWrapper from './components/PageHeaderWrapper';
import { formatWan } from './utils/utils'; import { formatWan } from './utils/utils';
import styles from './style.less'; import styles from './style.less';
import { IStateType } from './model'; import { IStateType } from './model';
...@@ -34,18 +20,6 @@ interface PAGE_NAME_UPPER_CAMEL_CASEProps extends FormComponentProps { ...@@ -34,18 +20,6 @@ interface PAGE_NAME_UPPER_CAMEL_CASEProps extends FormComponentProps {
loading: boolean; loading: boolean;
} }
@connect(
({
BLOCK_NAME_CAMEL_CASE,
loading,
}: {
BLOCK_NAME_CAMEL_CASE: IStateType;
loading: { models: { [key: string]: boolean } };
}) => ({
BLOCK_NAME_CAMEL_CASE,
loading: loading.models.BLOCK_NAME_CAMEL_CASE,
})
)
class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEProps> { class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEProps> {
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
...@@ -115,7 +89,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro ...@@ -115,7 +89,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro
<StandardFormRow title="所属类目" block style={{ paddingBottom: 11 }}> <StandardFormRow title="所属类目" block style={{ paddingBottom: 11 }}>
<FormItem> <FormItem>
{getFieldDecorator('category')( {getFieldDecorator('category')(
<TagSelect expandable> <TagSelect expandable={true}>
<TagSelect.Option value="cat1">类目一</TagSelect.Option> <TagSelect.Option value="cat1">类目一</TagSelect.Option>
<TagSelect.Option value="cat2">类目二</TagSelect.Option> <TagSelect.Option value="cat2">类目二</TagSelect.Option>
<TagSelect.Option value="cat3">类目三</TagSelect.Option> <TagSelect.Option value="cat3">类目三</TagSelect.Option>
...@@ -157,6 +131,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro ...@@ -157,6 +131,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro
</StandardFormRow> </StandardFormRow>
</Form> </Form>
</Card> </Card>
<br />
<List<ListItemDataType> <List<ListItemDataType>
rowKey="id" rowKey="id"
grid={{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }} grid={{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }}
...@@ -198,7 +173,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro ...@@ -198,7 +173,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEPro
} }
} }
export default Form.create({ const WarpForm = Form.create({
onValuesChange({ dispatch }: PAGE_NAME_UPPER_CAMEL_CASEProps, changedValues, allValues) { onValuesChange({ dispatch }: PAGE_NAME_UPPER_CAMEL_CASEProps, changedValues, allValues) {
// 表单项变化时请求数据 // 表单项变化时请求数据
// 模拟查询表单生效 // 模拟查询表单生效
...@@ -210,3 +185,16 @@ export default Form.create({ ...@@ -210,3 +185,16 @@ export default Form.create({
}); });
}, },
})(PAGE_NAME_UPPER_CAMEL_CASE); })(PAGE_NAME_UPPER_CAMEL_CASE);
export default connect(
({
BLOCK_NAME_CAMEL_CASE,
loading,
}: {
BLOCK_NAME_CAMEL_CASE: IStateType;
loading: { models: { [key: string]: boolean } };
}) => ({
BLOCK_NAME_CAMEL_CASE,
loading: loading.models.BLOCK_NAME_CAMEL_CASE,
})
)(WarpForm);
import request from 'umi-request'; import request from 'umi-request';
import { ListItemDataType } from './data';
export async function queryFakeList(params) { export async function queryFakeList(params: ListItemDataType) {
return request(`/api/BLOCK_NAME/fake_list`, { return request(`/api/BLOCK_NAME/fake_list`, {
params, params,
}); });
......
import { ListItemDataType } from './data';
const titles = [ const titles = [
'Alipay', 'Alipay',
'Angular', 'Angular',
...@@ -45,7 +47,7 @@ const user = [ ...@@ -45,7 +47,7 @@ const user = [
'仲尼', '仲尼',
]; ];
function fakeList(count) { function fakeList(count: number): ListItemDataType[] {
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 +55,17 @@ function fakeList(count) { ...@@ -53,13 +55,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 +99,7 @@ function fakeList(count) { ...@@ -93,7 +99,7 @@ function fakeList(count) {
return list; return list;
} }
function getFakeList(req, res) { function getFakeList(req: { query: any }, res: { json: (arg0: any[]) => void }) {
const params = req.query; const params = req.query;
const count = params.count * 1 || 20; const count = params.count * 1 || 20;
......
...@@ -3,7 +3,19 @@ import moment from 'moment'; ...@@ -3,7 +3,19 @@ import moment from 'moment';
import { Avatar } from 'antd'; import { Avatar } from 'antd';
import styles from './index.less'; import styles from './index.less';
const ArticleListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => ( interface ArticleListContentProps {
data: {
content: React.ReactNode;
updatedAt: number;
avatar: string;
owner: string;
href: string;
};
}
const ArticleListContent: React.SFC<ArticleListContentProps> = ({
data: { content, updatedAt, avatar, owner, href },
}) => (
<div className={styles.listContent}> <div className={styles.listContent}>
<div className={styles.description}>{content}</div> <div className={styles.description}>{content}</div>
<div className={styles.extra}> <div className={styles.extra}>
......
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';
.content {
margin: 24px 24px 0;
}
@media screen and (max-width: @screen-sm) {
.content {
margin: 24px 0 0;
}
}
...@@ -2,7 +2,22 @@ import React from 'react'; ...@@ -2,7 +2,22 @@ import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
const StandardFormRow = ({ title, children, last, block, grid, ...rest }) => { interface StandardFormRowProps {
title?: string;
last?: boolean;
block?: boolean;
grid?: boolean;
style?: React.CSSProperties;
}
const StandardFormRow: React.SFC<StandardFormRowProps> = ({
title,
children,
last,
block,
grid,
...rest
}) => {
const cls = classNames(styles.standardFormRow, { const cls = classNames(styles.standardFormRow, {
[styles.standardFormRowBlock]: block, [styles.standardFormRowBlock]: block,
[styles.standardFormRowLast]: last, [styles.standardFormRowLast]: last,
......
@import '~antd/lib/style/themes/default.less';
.tagSelect {
position: relative;
max-height: 32px;
margin-left: -8px;
overflow: hidden;
line-height: 32px;
transition: all 0.3s;
user-select: none;
:global {
.ant-tag {
margin-right: 24px;
padding: 0 8px;
font-size: @font-size-base;
}
}
&.expanded {
max-height: 200px;
transition: all 0.3s;
}
.trigger {
position: absolute;
top: 0;
right: 0;
i {
font-size: 12px;
}
}
&.hasExpandTag {
padding-right: 50px;
}
}
import React, { Component } from 'react';
import classNames from 'classnames';
import { Tag, Icon } from 'antd';
import styles from './index.less';
const { CheckableTag } = Tag;
export interface TagSelectOptionProps {
value?: string | number;
style?: React.CSSProperties;
checked?: boolean;
onChange?: (value: string | number | undefined, state: boolean) => void;
}
export interface TagSelectProps {
onChange?: (value: (string | number)[]) => void;
expandable?: boolean;
value?: (string | number)[];
defaultValue?: (string | number)[];
style?: React.CSSProperties;
hideCheckAll?: boolean;
actionsText?: {
expandText?: React.ReactNode;
collapseText?: React.ReactNode;
selectAllText?: React.ReactNode;
};
className?: string;
Option?: TagSelectOptionProps;
children?: React.ReactElement<TagSelectOption> | Array<React.ReactElement<TagSelectOption>>;
}
const TagSelectOption: React.SFC<TagSelectOptionProps> & {
isTagSelectOption: boolean;
} = ({ children, checked, onChange, value }) => (
<CheckableTag
checked={!!checked}
key={value}
onChange={state => onChange && onChange(value, state)}
>
{children}
</CheckableTag>
);
TagSelectOption.isTagSelectOption = true;
interface TagSelectState {
expand: boolean;
value: (string | number)[];
}
class TagSelect extends Component<TagSelectProps, TagSelectState> {
static defaultProps = {
hideCheckAll: false,
actionsText: {
expandText: '展开',
collapseText: '收起',
selectAllText: '全部',
},
};
static Option: TagSelectOption = TagSelectOption;
constructor(props: TagSelectProps) {
super(props);
this.state = {
expand: false,
value: props.value || props.defaultValue || [],
};
}
static getDerivedStateFromProps(nextProps: TagSelectProps) {
if ('value' in nextProps) {
return { value: nextProps.value || [] };
}
return null;
}
onChange = (value: (string | number)[]) => {
const { onChange } = this.props;
if (!('value' in this.props)) {
this.setState({ value });
}
if (onChange) {
onChange(value);
}
};
onSelectAll = (checked: boolean) => {
let checkedTags: (string | number)[] = [];
if (checked) {
checkedTags = this.getAllTags();
}
this.onChange(checkedTags);
};
getAllTags() {
let { children } = this.props;
const childrenArray = React.Children.toArray(children) as React.ReactElement<TagSelectOption>[];
const checkedTags = childrenArray
.filter(child => this.isTagSelectOption(child))
.map(child => child.props.value);
return checkedTags || [];
}
handleTagChange = (value: string | number, checked: boolean) => {
const { value: StateValue } = this.state;
const checkedTags: (string | number)[] = [...StateValue];
const index = checkedTags.indexOf(value);
if (checked && index === -1) {
checkedTags.push(value);
} else if (!checked && index > -1) {
checkedTags.splice(index, 1);
}
this.onChange(checkedTags);
};
handleExpand = () => {
const { expand } = this.state;
this.setState({
expand: !expand,
});
};
isTagSelectOption = (node: React.ReactElement<TagSelectOption, TagSelectOption>) =>
node &&
node.type &&
(node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption');
render() {
const { value, expand } = this.state;
const { children, hideCheckAll, className, style, expandable, actionsText = {} } = this.props;
const checkedAll = this.getAllTags().length === value.length;
const { expandText = '展开', collapseText = '收起', selectAllText = '全部' } = actionsText;
const cls = classNames(styles.tagSelect, className, {
[styles.hasExpandTag]: expandable,
[styles.expanded]: expand,
});
return (
<div className={cls} style={style}>
{hideCheckAll ? null : (
<CheckableTag checked={checkedAll} key="tag-select-__all__" onChange={this.onSelectAll}>
{selectAllText}
</CheckableTag>
)}
{value &&
children &&
React.Children.map(children, (child: React.ReactElement<TagSelectOption>) => {
if (this.isTagSelectOption(child)) {
return React.cloneElement(child, {
key: `tag-select-${child.props.value}`,
value: child.props.value,
checked: value.indexOf(child.props.value) > -1,
onChange: this.handleTagChange,
});
}
return child;
})}
{expandable && (
<a className={styles.trigger} onClick={this.handleExpand}>
{expand ? collapseText : expandText} <Icon type={expand ? 'up' : 'down'} />
</a>
)}
</div>
);
}
}
export default TagSelect;
export interface Member {
avatar: string;
name: string;
id: string;
}
export interface ListItemDataType {
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[];
}
...@@ -6,31 +6,23 @@ import TagSelect from './components/TagSelect'; ...@@ -6,31 +6,23 @@ import TagSelect from './components/TagSelect';
import StandardFormRow from './components/StandardFormRow'; import StandardFormRow from './components/StandardFormRow';
import ArticleListContent from './components/ArticleListContent'; import ArticleListContent from './components/ArticleListContent';
import styles from './style.less'; import styles from './style.less';
import { Dispatch } from 'redux';
import { FormComponentProps } from 'antd/lib/form';
import { ListItemDataType } from './data';
import { IStateType } from './model';
const { Option } = Select; const { Option } = Select;
const FormItem = Form.Item; const FormItem = Form.Item;
const pageSize = 5; const pageSize = 5;
@connect(({ BLOCK_NAME_CAMEL_CASE, loading }) => ({ interface PAGE_NAME_UPPER_CAMEL_CASEProps extends FormComponentProps {
BLOCK_NAME_CAMEL_CASE, dispatch: Dispatch;
loading: loading.models.BLOCK_NAME_CAMEL_CASE, BLOCK_NAME_CAMEL_CASE: IStateType;
})) loading: boolean;
@Form.create({ }
onValuesChange({ dispatch }, changedValues, allValues) {
// 表单项变化时请求数据 class PAGE_NAME_UPPER_CAMEL_CASE extends Component<PAGE_NAME_UPPER_CAMEL_CASEProps> {
// eslint-disable-next-line
console.log(changedValues, allValues);
// 模拟查询表单生效
dispatch({
type: 'BLOCK_NAME_CAMEL_CASE/fetch',
payload: {
count: 5,
},
});
},
})
class SearchList extends Component {
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch({ dispatch({
...@@ -89,7 +81,10 @@ class SearchList extends Component { ...@@ -89,7 +81,10 @@ class SearchList extends Component {
}, },
]; ];
const IconText = ({ type, text }) => ( const IconText: React.SFC<{
type: string;
text: React.ReactNode;
}> = ({ type, text }) => (
<span> <span>
<Icon type={type} style={{ marginRight: 8 }} /> <Icon type={type} style={{ marginRight: 8 }} />
{text} {text}
...@@ -145,8 +140,8 @@ class SearchList extends Component { ...@@ -145,8 +140,8 @@ class SearchList extends Component {
</StandardFormRow> </StandardFormRow>
<StandardFormRow title="owner" grid> <StandardFormRow title="owner" grid>
<Row> <Row>
<Col lg={16} md={24} sm={24} xs={24}> <Col>
<FormItem> <FormItem {...formItemLayout}>
{getFieldDecorator('owner', { {getFieldDecorator('owner', {
initialValue: ['wjh', 'zxx'], initialValue: ['wjh', 'zxx'],
})( })(
...@@ -198,7 +193,7 @@ class SearchList extends Component { ...@@ -198,7 +193,7 @@ class SearchList extends Component {
bordered={false} bordered={false}
bodyStyle={{ padding: '8px 32px 32px 32px' }} bodyStyle={{ padding: '8px 32px 32px 32px' }}
> >
<List <List<ListItemDataType>
size="large" size="large"
loading={list.length === 0 ? loading : false} loading={list.length === 0 ? loading : false}
rowKey="id" rowKey="id"
...@@ -239,4 +234,28 @@ class SearchList extends Component { ...@@ -239,4 +234,28 @@ class SearchList extends Component {
} }
} }
export default SearchList; const WarpForm = Form.create({
onValuesChange({ dispatch }: PAGE_NAME_UPPER_CAMEL_CASEProps, changedValues, allValues) {
// 表单项变化时请求数据
// 模拟查询表单生效
dispatch({
type: 'BLOCK_NAME_CAMEL_CASE/fetch',
payload: {
count: 8,
},
});
},
})(PAGE_NAME_UPPER_CAMEL_CASE);
export default connect(
({
BLOCK_NAME_CAMEL_CASE,
loading,
}: {
BLOCK_NAME_CAMEL_CASE: IStateType;
loading: { models: { [key: string]: boolean } };
}) => ({
BLOCK_NAME_CAMEL_CASE,
loading: loading.models.BLOCK_NAME_CAMEL_CASE,
})
)(WarpForm);
import { queryFakeList } from './service'; import { queryFakeList } from './service';
import { ListItemDataType } from './data';
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
export default { export interface IStateType {
list: ListItemDataType[];
}
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;
appendFetch: Effect;
};
reducers: {
queryList: Reducer<IStateType>;
appendList: Reducer<IStateType>;
};
}
const Model: ModelType = {
namespace: 'BLOCK_NAME_CAMEL_CASE', namespace: 'BLOCK_NAME_CAMEL_CASE',
state: { state: {
...@@ -34,8 +60,10 @@ export default { ...@@ -34,8 +60,10 @@ export default {
appendList(state, action) { appendList(state, action) {
return { return {
...state, ...state,
list: state.list.concat(action.payload), list: state!.list.concat(action.payload),
}; };
}, },
}, },
}; };
export default Model;
import request from 'umi-request'; import request from 'umi-request';
import { ListItemDataType } from './data';
export async function queryFakeList(params) { export async function queryFakeList(params: ListItemDataType) {
return request(`/api/BLOCK_NAME/fake_list`, { return request(`/api/BLOCK_NAME/fake_list`, {
params, params,
}); });
......
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "cross-env PAGES_PATH='ResultFail/src' umi dev", "dev": "cross-env PAGES_PATH='SearchListArticles/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