Unverified Commit e111d7bf authored by 偏右's avatar 偏右 Committed by GitHub

Refactor search list routes (#440)

* refactor search list

* Fix third level breadcrumb name, close #304

* use match.url

* use match.url

* use match.path

* fix match url & path
parent 69a9d9bb
......@@ -90,19 +90,22 @@ export const getNavData = app => [
component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')),
},
{
name: '搜索列表',
path: 'search',
component: dynamicWrapper(app, [], () => import('../routes/List/List')),
children: [{
name: '搜索列表(项目)',
path: 'cover-card-list',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/CoverCardList')),
},
{
path: 'projects',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')),
}, {
name: '搜索列表(应用)',
path: 'filter-card-list',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/FilterCardList')),
},
{
path: 'applications',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')),
}, {
name: '搜索列表(文章)',
path: 'search',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/SearchList')),
path: 'articles',
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')),
}],
},
],
},
......
......@@ -38,6 +38,7 @@ class BasicLayout extends React.PureComponent {
static childContextTypes = {
location: PropTypes.object,
breadcrumbNameMap: PropTypes.object,
routeData: PropTypes.array,
}
getChildContext() {
const { location, navData, getRouteData } = this.props;
......@@ -52,7 +53,7 @@ class BasicLayout extends React.PureComponent {
component: item.component,
};
});
return { location, breadcrumbNameMap };
return { location, breadcrumbNameMap, routeData };
}
getPageTitle() {
const { location, getRouteData } = this.props;
......@@ -68,8 +69,10 @@ class BasicLayout extends React.PureComponent {
getMenuData = (data, parentPath) => {
let arr = [];
data.forEach((item) => {
if (item.children) {
if (item.name) {
arr.push({ path: `${parentPath}/${item.path}`, name: item.name });
}
if (item.children) {
arr = arr.concat(this.getMenuData(item.children, `${parentPath}/${item.path}`));
}
});
......
import React, { PureComponent } from 'react';
import numeral from 'numeral';
import { connect } from 'dva';
import { routerRedux } from 'dva/router';
import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Input, Dropdown, Menu } from 'antd';
import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Dropdown, Menu } from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import StandardFormRow from '../../components/StandardFormRow';
import TagSelect from '../../components/TagSelect';
import styles from './FilterCardList.less';
import styles from './Projects.less';
const { Option } = Select;
const FormItem = Form.Item;
......@@ -58,43 +56,10 @@ export default class FilterCardList extends PureComponent {
}, 0);
}
handleTabChange = (key) => {
const { dispatch } = this.props;
switch (key) {
case 'doc':
dispatch(routerRedux.push('/list/search'));
break;
case 'app':
dispatch(routerRedux.push('/list/filter-card-list'));
break;
case 'project':
dispatch(routerRedux.push('/list/cover-card-list'));
break;
default:
break;
}
}
render() {
const { list: { list, loading }, form } = this.props;
const { getFieldDecorator } = form;
const tabList = [
{
key: 'doc',
tab: '文章',
},
{
key: 'app',
tab: '应用',
default: true,
},
{
key: 'project',
tab: '项目',
},
];
const CardInfo = ({ activeUser, newUser }) => (
<div className={styles.cardInfo}>
<div>
......@@ -108,18 +73,6 @@ export default class FilterCardList extends PureComponent {
</div>
);
const pageHeaderContent = (
<div style={{ textAlign: 'center' }}>
<Input.Search
placeholder="请输入"
enterButton="搜索"
size="large"
onSearch={this.handleFormSubmit}
style={{ width: 522 }}
/>
</div>
);
const formItemLayout = {
wrapperCol: {
xs: { span: 24 },
......@@ -142,12 +95,6 @@ export default class FilterCardList extends PureComponent {
);
return (
<PageHeaderLayout
title="搜索列表"
content={pageHeaderContent}
tabList={tabList}
onTabChange={this.handleTabChange}
>
<div className={styles.filterCardList}>
<Card bordered={false}>
<Form layout="inline">
......@@ -247,7 +194,6 @@ export default class FilterCardList extends PureComponent {
)}
/>
</div>
</PageHeaderLayout>
);
}
}
import React, { Component } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import { Form, Card, Select, List, Tag, Icon, Avatar, Row, Col, Button } from 'antd';
import StandardFormRow from '../../components/StandardFormRow';
import TagSelect from '../../components/TagSelect';
import styles from './Articles.less';
const { Option } = Select;
const FormItem = Form.Item;
const pageSize = 5;
@Form.create()
@connect(state => ({
list: state.list,
}))
export default class SearchList extends Component {
componentDidMount() {
this.fetchMore();
}
setOwner = () => {
const { form } = this.props;
form.setFieldsValue({
owner: ['wzj'],
});
}
fetchMore = () => {
this.props.dispatch({
type: 'list/appendFetch',
payload: {
count: pageSize,
},
});
}
render() {
const { form, list: { list, loading } } = this.props;
const { getFieldDecorator } = form;
const owners = [
{
id: 'wzj',
name: '我自己',
},
{
id: 'wjh',
name: '吴家豪',
},
{
id: 'zxx',
name: '周星星',
},
{
id: 'zly',
name: '赵丽颖',
},
{
id: 'ym',
name: '姚明',
},
];
const IconText = ({ type, text }) => (
<span>
<Icon type={type} style={{ marginRight: 8 }} />
{text}
</span>
);
const ListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => (
<div className={styles.listContent}>
<div className={styles.description}>{content}</div>
<div className={styles.extra}>
<Avatar src={avatar} size="small" /><a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
<em>{moment(updatedAt).format('YYYY-MM-DD hh:mm')}</em>
</div>
</div>
);
const formItemLayout = {
wrapperCol: {
xs: { span: 24 },
sm: { span: 24 },
md: { span: 12 },
},
};
const loadMore = list.length > 0 ? (
<div style={{ textAlign: 'center', marginTop: 16 }}>
<Button onClick={this.fetchMore} style={{ paddingLeft: 48, paddingRight: 48 }}>
{loading ? <span><Icon type="loading" /> 加载中...</span> : '加载更多'}
</Button>
</div>
) : null;
return (
<div>
<Card bordered={false}>
<Form layout="inline">
<StandardFormRow title="所属类目" block style={{ paddingBottom: 11 }}>
<FormItem>
{getFieldDecorator('category')(
<TagSelect onChange={this.handleFormSubmit} expandable>
<TagSelect.Option value="cat1">类目一</TagSelect.Option>
<TagSelect.Option value="cat2">类目二</TagSelect.Option>
<TagSelect.Option value="cat3">类目三</TagSelect.Option>
<TagSelect.Option value="cat4">类目四</TagSelect.Option>
<TagSelect.Option value="cat5">类目五</TagSelect.Option>
<TagSelect.Option value="cat6">类目六</TagSelect.Option>
<TagSelect.Option value="cat7">类目七</TagSelect.Option>
<TagSelect.Option value="cat8">类目八</TagSelect.Option>
<TagSelect.Option value="cat9">类目九</TagSelect.Option>
<TagSelect.Option value="cat10">类目十</TagSelect.Option>
<TagSelect.Option value="cat11">类目十一</TagSelect.Option>
<TagSelect.Option value="cat12">类目十二</TagSelect.Option>
</TagSelect>
)}
</FormItem>
</StandardFormRow>
<StandardFormRow
title="owner"
grid
>
<Row>
<Col lg={16} md={24} sm={24} xs={24}>
<FormItem>
{getFieldDecorator('owner', {
initialValue: ['wjh', 'zxx'],
})(
<Select
mode="multiple"
style={{ maxWidth: 286, width: '100%' }}
placeholder="选择 owner"
>
{
owners.map(owner =>
<Option key={owner.id} value={owner.id}>{owner.name}</Option>
)
}
</Select>
)}
<a className={styles.selfTrigger} onClick={this.setOwner}>只看自己的</a>
</FormItem>
</Col>
</Row>
</StandardFormRow>
<StandardFormRow
title="其它选项"
grid
last
>
<Row gutter={16}>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="活跃用户"
>
{getFieldDecorator('user', {})(
<Select
onChange={this.handleFormSubmit}
placeholder="不限"
style={{ maxWidth: 200, width: '100%' }}
>
<Option value="lisa">李三</Option>
</Select>
)}
</FormItem>
</Col>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="好评度"
>
{getFieldDecorator('rate', {})(
<FormItem
label="好评度"
>
{getFieldDecorator('rate', {})(
<Select
onChange={this.handleFormSubmit}
placeholder="不限"
style={{ maxWidth: 200, width: '100%' }}
>
<Option value="good">优秀</Option>
</Select>
)}
</FormItem>
)}
</FormItem>
</Col>
</Row>
</StandardFormRow>
</Form>
</Card>
<Card
style={{ marginTop: 24 }}
bordered={false}
bodyStyle={{ padding: '8px 32px 32px 32px' }}
>
<List
size="large"
loading={list.length === 0 ? loading : false}
rowKey="id"
itemLayout="vertical"
loadMore={loadMore}
dataSource={list}
renderItem={item => (
<List.Item
key={item.id}
actions={[
<IconText type="star-o" text={item.star} />,
<IconText type="like-o" text={item.like} />,
<IconText type="message" text={item.message} />,
]}
extra={<div className={styles.listItemExtra} />}
>
<List.Item.Meta
title={(
<a className={styles.listItemMetaTitle} href={item.href}>{item.title}</a>
)}
description={
<span>
<Tag>Ant Design</Tag>
<Tag>设计语言</Tag>
<Tag>蚂蚁金服</Tag>
</span>
}
/>
<ListContent data={item} />
</List.Item>
)}
/>
</Card>
</div>
);
}
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { routerRedux, Route, Switch } from 'dva/router';
import { connect } from 'dva';
import { Input } from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
@connect()
export default class SearchList extends Component {
static contextTypes = {
routeData: PropTypes.array,
};
handleTabChange = (key) => {
const { dispatch, match } = this.props;
switch (key) {
case 'articles':
dispatch(routerRedux.push(`${match.url}/articles`));
break;
case 'applications':
dispatch(routerRedux.push(`${match.url}/applications`));
break;
case 'projects':
dispatch(routerRedux.push(`${match.url}/projects`));
break;
default:
break;
}
}
render() {
const tabList = [{
key: 'articles',
tab: '文章',
}, {
key: 'applications',
tab: '应用',
}, {
key: 'projects',
tab: '项目',
}];
const mainSearch = (
<div style={{ textAlign: 'center' }}>
<Input.Search
placeholder="请输入"
enterButton="搜索"
size="large"
onSearch={this.handleFormSubmit}
style={{ width: 522 }}
/>
</div>
);
const { match } = this.props;
const { routeData } = this.context;
const routes = routeData.filter(item => item.path === match.path)[0].children;
return (
<PageHeaderLayout
title="搜索列表"
content={mainSearch}
tabList={tabList}
onTabChange={this.handleTabChange}
>
<Switch>
{
routes.map(item =>
(
<Route
key={item.path}
path={`${match.path}/${item.path}`}
component={item.component}
/>
)
)
}
</Switch>
</PageHeaderLayout>
);
}
}
import React, { PureComponent } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import { routerRedux } from 'dva/router';
import { Row, Col, Form, Card, Select, List, Input } from 'antd';
import { Row, Col, Form, Card, Select, List } from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import StandardFormRow from '../../components/StandardFormRow';
import TagSelect from '../../components/TagSelect';
import AvatarList from '../../components/AvatarList';
import styles from './CoverCardList.less';
import styles from './Projects.less';
const { Option } = Select;
const FormItem = Form.Item;
......@@ -47,23 +45,6 @@ export default class CoverCardList extends PureComponent {
}, 0);
}
handleTabChange = (key) => {
const { dispatch } = this.props;
switch (key) {
case 'doc':
dispatch(routerRedux.push('/list/search'));
break;
case 'app':
dispatch(routerRedux.push('/list/filter-card-list'));
break;
case 'project':
dispatch(routerRedux.push('/list/cover-card-list'));
break;
default:
break;
}
}
render() {
const { list: { list = [], loading }, form } = this.props;
const { getFieldDecorator } = form;
......@@ -107,34 +88,6 @@ export default class CoverCardList extends PureComponent {
/>
) : null;
const tabList = [
{
key: 'doc',
tab: '文章',
},
{
key: 'app',
tab: '应用',
},
{
key: 'project',
tab: '项目',
default: true,
},
];
const pageHeaderContent = (
<div style={{ textAlign: 'center' }}>
<Input.Search
placeholder="请输入"
enterButton="搜索"
size="large"
onSearch={this.handleFormSubmit}
style={{ width: 522 }}
/>
</div>
);
const formItemLayout = {
wrapperCol: {
xs: { span: 24 },
......@@ -143,12 +96,6 @@ export default class CoverCardList extends PureComponent {
};
return (
<PageHeaderLayout
title="搜索列表"
content={pageHeaderContent}
tabList={tabList}
onTabChange={this.handleTabChange}
>
<div className={styles.coverCardList}>
<Card bordered={false}>
<Form layout="inline">
......@@ -219,7 +166,6 @@ export default class CoverCardList extends PureComponent {
{cardList}
</div>
</div>
</PageHeaderLayout>
);
}
}
import React, { Component } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import { routerRedux } from 'dva/router';
import { Form, Card, Select, List, Tag, Icon, Avatar, Row, Col, Button, Input } from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import StandardFormRow from '../../components/StandardFormRow';
import TagSelect from '../../components/TagSelect';
import styles from './SearchList.less';
const { Option } = Select;
const FormItem = Form.Item;
const pageSize = 5;
@Form.create()
@connect(state => ({
list: state.list,
}))
export default class SearchList extends Component {
componentDidMount() {
this.fetchMore();
}
setOwner = () => {
const { form } = this.props;
form.setFieldsValue({
owner: ['wzj'],
});
}
fetchMore = () => {
this.props.dispatch({
type: 'list/appendFetch',
payload: {
count: pageSize,
},
});
}
handleTabChange = (key) => {
const { dispatch } = this.props;
switch (key) {
case 'docs':
dispatch(routerRedux.push('/list/search'));
break;
case 'app':
dispatch(routerRedux.push('/list/filter-card-list'));
break;
case 'project':
dispatch(routerRedux.push('/list/cover-card-list'));
break;
default:
break;
}
}
render() {
const { form, list: { list, loading } } = this.props;
const { getFieldDecorator } = form;
const owners = [
{
id: 'wzj',
name: '我自己',
},
{
id: 'wjh',
name: '吴家豪',
},
{
id: 'zxx',
name: '周星星',
},
{
id: 'zly',
name: '赵丽颖',
},
{
id: 'ym',
name: '姚明',
},
];
const tabList = [
{
key: 'doc',
tab: '文章',
},
{
key: 'app',
tab: '应用',
},
{
key: 'project',
tab: '项目',
},
];
const IconText = ({ type, text }) => (
<span>
<Icon type={type} style={{ marginRight: 8 }} />
{text}
</span>
);
const ListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => (
<div className={styles.listContent}>
<div className={styles.description}>{content}</div>
<div className={styles.extra}>
<Avatar src={avatar} size="small" /><a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
<em>{moment(updatedAt).format('YYYY-MM-DD hh:mm')}</em>
</div>
</div>
);
const pageHeaderContent = (
<div style={{ textAlign: 'center' }}>
<Input.Search
placeholder="请输入"
enterButton="搜索"
size="large"
onSearch={this.handleFormSubmit}
style={{ width: 522 }}
/>
</div>
);
const formItemLayout = {
wrapperCol: {
xs: { span: 24 },
sm: { span: 24 },
md: { span: 12 },
},
};
const loadMore = list.length > 0 ? (
<div style={{ textAlign: 'center', marginTop: 16 }}>
<Button onClick={this.fetchMore} style={{ paddingLeft: 48, paddingRight: 48 }}>
{loading ? <span><Icon type="loading" /> 加载中...</span> : '加载更多'}
</Button>
</div>
) : null;
return (
<PageHeaderLayout
title="搜索列表"
content={pageHeaderContent}
tabList={tabList}
onTabChange={this.handleTabChange}
>
<div>
<Card bordered={false}>
<Form layout="inline">
<StandardFormRow title="所属类目" block style={{ paddingBottom: 11 }}>
<FormItem>
{getFieldDecorator('category')(
<TagSelect onChange={this.handleFormSubmit} expandable>
<TagSelect.Option value="cat1">类目一</TagSelect.Option>
<TagSelect.Option value="cat2">类目二</TagSelect.Option>
<TagSelect.Option value="cat3">类目三</TagSelect.Option>
<TagSelect.Option value="cat4">类目四</TagSelect.Option>
<TagSelect.Option value="cat5">类目五</TagSelect.Option>
<TagSelect.Option value="cat6">类目六</TagSelect.Option>
<TagSelect.Option value="cat7">类目七</TagSelect.Option>
<TagSelect.Option value="cat8">类目八</TagSelect.Option>
<TagSelect.Option value="cat9">类目九</TagSelect.Option>
<TagSelect.Option value="cat10">类目十</TagSelect.Option>
<TagSelect.Option value="cat11">类目十一</TagSelect.Option>
<TagSelect.Option value="cat12">类目十二</TagSelect.Option>
</TagSelect>
)}
</FormItem>
</StandardFormRow>
<StandardFormRow
title="owner"
grid
>
<Row>
<Col lg={16} md={24} sm={24} xs={24}>
<FormItem>
{getFieldDecorator('owner', {
initialValue: ['wjh', 'zxx'],
})(
<Select
mode="multiple"
style={{ maxWidth: 286, width: '100%' }}
placeholder="选择 owner"
>
{
owners.map(owner =>
<Option key={owner.id} value={owner.id}>{owner.name}</Option>
)
}
</Select>
)}
<a className={styles.selfTrigger} onClick={this.setOwner}>只看自己的</a>
</FormItem>
</Col>
</Row>
</StandardFormRow>
<StandardFormRow
title="其它选项"
grid
last
>
<Row gutter={16}>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="活跃用户"
>
{getFieldDecorator('user', {})(
<Select
onChange={this.handleFormSubmit}
placeholder="不限"
style={{ maxWidth: 200, width: '100%' }}
>
<Option value="lisa">李三</Option>
</Select>
)}
</FormItem>
</Col>
<Col xl={8} lg={10} md={12} sm={24} xs={24}>
<FormItem
{...formItemLayout}
label="好评度"
>
{getFieldDecorator('rate', {})(
<FormItem
label="好评度"
>
{getFieldDecorator('rate', {})(
<Select
onChange={this.handleFormSubmit}
placeholder="不限"
style={{ maxWidth: 200, width: '100%' }}
>
<Option value="good">优秀</Option>
</Select>
)}
</FormItem>
)}
</FormItem>
</Col>
</Row>
</StandardFormRow>
</Form>
</Card>
<Card
style={{ marginTop: 24 }}
bordered={false}
bodyStyle={{ padding: '8px 32px 32px 32px' }}
>
<List
size="large"
loading={list.length === 0 ? loading : false}
rowKey="id"
itemLayout="vertical"
loadMore={loadMore}
dataSource={list}
renderItem={item => (
<List.Item
key={item.id}
actions={[
<IconText type="star-o" text={item.star} />,
<IconText type="like-o" text={item.like} />,
<IconText type="message" text={item.message} />,
]}
extra={<div className={styles.listItemExtra} />}
>
<List.Item.Meta
title={(
<a className={styles.listItemMetaTitle} href={item.href}>{item.title}</a>
)}
description={
<span>
<Tag>Ant Design</Tag>
<Tag>设计语言</Tag>
<Tag>蚂蚁金服</Tag>
</span>
}
/>
<ListContent data={item} />
</List.Item>
)}
/>
</Card>
</div>
</PageHeaderLayout>
);
}
}
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