diff --git a/src/common/nav.js b/src/common/nav.js index 6595b4d20f9b8e4f21d84c85cb2450ef7e8df338..8c2ba424053b0f828445b0cd878910ef34c0c009 100644 --- a/src/common/nav.js +++ b/src/common/nav.js @@ -90,19 +90,22 @@ export const getNavData = app => [ component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')), }, { - name: '搜索列表(项目)', - path: 'cover-card-list', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/CoverCardList')), - }, - { - name: '搜索列表(应用)', - path: 'filter-card-list', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/FilterCardList')), - }, - { - name: '搜索列表(文章)', + name: '搜索列表', path: 'search', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/SearchList')), + component: dynamicWrapper(app, [], () => import('../routes/List/List')), + children: [{ + name: '搜索列表(项目)', + path: 'projects', + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')), + }, { + name: '搜索列表(应用)', + path: 'applications', + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')), + }, { + name: '搜索列表(文章)', + path: 'articles', + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')), + }], }, ], }, diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js index cf7aeb6634eeaadc88650c8525e1cb9b1577c1f0..70453cc2f0ca8681c17e2f5d9bea301cce705dc3 100644 --- a/src/layouts/BasicLayout.js +++ b/src/layouts/BasicLayout.js @@ -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}`)); } }); diff --git a/src/routes/List/Applications.js b/src/routes/List/Applications.js new file mode 100644 index 0000000000000000000000000000000000000000..41b45310d7d16efee516ac06d4acbdff88ce5c3e --- /dev/null +++ b/src/routes/List/Applications.js @@ -0,0 +1,199 @@ +import React, { PureComponent } from 'react'; +import numeral from 'numeral'; +import { connect } from 'dva'; +import { Row, Col, Form, Card, Select, Icon, Avatar, List, Tooltip, Dropdown, Menu } from 'antd'; + +import StandardFormRow from '../../components/StandardFormRow'; +import TagSelect from '../../components/TagSelect'; + +import styles from './Projects.less'; + +const { Option } = Select; +const FormItem = Form.Item; + +const formatWan = (val) => { + const v = val * 1; + if (!v || isNaN(v)) return ''; + + let result = val; + if (val > 10000) { + result = Math.floor(val / 10000); + result = {result}; + } + return result; +}; + +/* eslint react/no-array-index-key: 0 */ +@Form.create() +@connect(state => ({ + list: state.list, +})) +export default class FilterCardList extends PureComponent { + componentDidMount() { + this.props.dispatch({ + type: 'list/fetch', + payload: { + count: 8, + }, + }); + } + + handleFormSubmit = () => { + const { form, dispatch } = this.props; + // setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候 + setTimeout(() => { + form.validateFields((err) => { + if (!err) { + // eslint-disable-next-line + dispatch({ + type: 'list/fetch', + payload: { + count: 8, + }, + }); + } + }); + }, 0); + } + + render() { + const { list: { list, loading }, form } = this.props; + const { getFieldDecorator } = form; + + const CardInfo = ({ activeUser, newUser }) => ( +
+
+

活跃用户

+

{activeUser}

+
+
+

新增用户

+

{newUser}

+
+
+ ); + + const formItemLayout = { + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + }; + + const itemMenu = ( + + + 1st menu item + + + 2nd menu item + + + 3d menu item + + + ); + + return ( +
+ +
+ + + {getFieldDecorator('category')( + + 类目一 + 类目二 + 类目三 + 类目四 + 类目五 + 类目六 + 类目七 + 类目八 + 类目九 + 类目十 + 类目十一 + 类目十二 + + )} + + + + + + + {getFieldDecorator('author', {})( + + )} + + + + + {getFieldDecorator('rate', {})( + + )} + + + + +
+
+ ( + + , + , + , + , + ]} + > + } + title={item.title} + /> +
+ +
+
+
+ )} + /> +
+ ); + } +} diff --git a/src/routes/List/FilterCardList.less b/src/routes/List/Applications.less similarity index 100% rename from src/routes/List/FilterCardList.less rename to src/routes/List/Applications.less diff --git a/src/routes/List/Articles.js b/src/routes/List/Articles.js new file mode 100644 index 0000000000000000000000000000000000000000..3103ab01a6f87ca6eec735031ec00521927121da --- /dev/null +++ b/src/routes/List/Articles.js @@ -0,0 +1,241 @@ +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 }) => ( + + + {text} + + ); + + const ListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => ( +
+
{content}
+
+ {owner} 发布在 {href} + {moment(updatedAt).format('YYYY-MM-DD hh:mm')} +
+
+ ); + + const formItemLayout = { + wrapperCol: { + xs: { span: 24 }, + sm: { span: 24 }, + md: { span: 12 }, + }, + }; + + const loadMore = list.length > 0 ? ( +
+ +
+ ) : null; + + return ( +
+ +
+ + + {getFieldDecorator('category')( + + 类目一 + 类目二 + 类目三 + 类目四 + 类目五 + 类目六 + 类目七 + 类目八 + 类目九 + 类目十 + 类目十一 + 类目十二 + + )} + + + + + + + {getFieldDecorator('owner', { + initialValue: ['wjh', 'zxx'], + })( + + )} + 只看自己的 + + + + + + + + + {getFieldDecorator('user', {})( + + )} + + + + + {getFieldDecorator('rate', {})( + + {getFieldDecorator('rate', {})( + + )} + + )} + + + + +
+
+ + ( + , + , + , + ]} + extra={
} + > + {item.title} + )} + description={ + + Ant Design + 设计语言 + 蚂蚁金服 + + } + /> + + + )} + /> + +
+ ); + } +} diff --git a/src/routes/List/SearchList.less b/src/routes/List/Articles.less similarity index 100% rename from src/routes/List/SearchList.less rename to src/routes/List/Articles.less diff --git a/src/routes/List/CoverCardList.js b/src/routes/List/CoverCardList.js deleted file mode 100644 index e6887c369e1ab6a65a8025c00b715c1c671ced1f..0000000000000000000000000000000000000000 --- a/src/routes/List/CoverCardList.js +++ /dev/null @@ -1,225 +0,0 @@ -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 PageHeaderLayout from '../../layouts/PageHeaderLayout'; -import StandardFormRow from '../../components/StandardFormRow'; -import TagSelect from '../../components/TagSelect'; -import AvatarList from '../../components/AvatarList'; - -import styles from './CoverCardList.less'; - -const { Option } = Select; -const FormItem = Form.Item; - -/* eslint react/no-array-index-key: 0 */ -@Form.create() -@connect(state => ({ - list: state.list, -})) -export default class CoverCardList extends PureComponent { - componentDidMount() { - this.props.dispatch({ - type: 'list/fetch', - payload: { - count: 8, - }, - }); - } - - handleFormSubmit = () => { - const { form, dispatch } = this.props; - // setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候 - setTimeout(() => { - form.validateFields((err) => { - if (!err) { - // eslint-disable-next-line - dispatch({ - type: 'list/fetch', - payload: { - count: 8, - }, - }); - } - }); - }, 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 cardList = list ? ( - ( - - } - > - {item.title}} - description={item.subDescription} - /> -
- {moment(item.updatedAt).fromNow()} -
- - { - item.members.map((member, i) => ( - - )) - } - -
-
-
-
- )} - /> - ) : null; - - const tabList = [ - { - key: 'doc', - tab: '文章', - }, - { - key: 'app', - tab: '应用', - }, - { - key: 'project', - tab: '项目', - default: true, - }, - ]; - - const pageHeaderContent = ( -
- -
- ); - - const formItemLayout = { - wrapperCol: { - xs: { span: 24 }, - sm: { span: 16 }, - }, - }; - - return ( - -
- -
- - - {getFieldDecorator('category')( - - 类目一 - 类目二 - 类目三 - 类目四 - 类目五 - 类目六 - 类目七 - 类目八 - 类目九 - 类目十 - 类目十一 - 类目十二 - - )} - - - - - - - {getFieldDecorator('author', {})( - - )} - - - - - {getFieldDecorator('rate', {})( - - )} - - - - -
-
-
- {cardList} -
-
-
- ); - } -} diff --git a/src/routes/List/FilterCardList.js b/src/routes/List/FilterCardList.js deleted file mode 100644 index 51b2ae50e39223d1c099d029d903672f9a796efd..0000000000000000000000000000000000000000 --- a/src/routes/List/FilterCardList.js +++ /dev/null @@ -1,253 +0,0 @@ -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 PageHeaderLayout from '../../layouts/PageHeaderLayout'; -import StandardFormRow from '../../components/StandardFormRow'; -import TagSelect from '../../components/TagSelect'; - -import styles from './FilterCardList.less'; - -const { Option } = Select; -const FormItem = Form.Item; - -const formatWan = (val) => { - const v = val * 1; - if (!v || isNaN(v)) return ''; - - let result = val; - if (val > 10000) { - result = Math.floor(val / 10000); - result = {result}; - } - return result; -}; - -/* eslint react/no-array-index-key: 0 */ -@Form.create() -@connect(state => ({ - list: state.list, -})) -export default class FilterCardList extends PureComponent { - componentDidMount() { - this.props.dispatch({ - type: 'list/fetch', - payload: { - count: 8, - }, - }); - } - - handleFormSubmit = () => { - const { form, dispatch } = this.props; - // setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候 - setTimeout(() => { - form.validateFields((err) => { - if (!err) { - // eslint-disable-next-line - dispatch({ - type: 'list/fetch', - payload: { - count: 8, - }, - }); - } - }); - }, 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 }) => ( -
-
-

活跃用户

-

{activeUser}

-
-
-

新增用户

-

{newUser}

-
-
- ); - - const pageHeaderContent = ( -
- -
- ); - - const formItemLayout = { - wrapperCol: { - xs: { span: 24 }, - sm: { span: 16 }, - }, - }; - - const itemMenu = ( - - - 1st menu item - - - 2nd menu item - - - 3d menu item - - - ); - - return ( - -
- -
- - - {getFieldDecorator('category')( - - 类目一 - 类目二 - 类目三 - 类目四 - 类目五 - 类目六 - 类目七 - 类目八 - 类目九 - 类目十 - 类目十一 - 类目十二 - - )} - - - - - - - {getFieldDecorator('author', {})( - - )} - - - - - {getFieldDecorator('rate', {})( - - )} - - - - -
-
- ( - - , - , - , - , - ]} - > - } - title={item.title} - /> -
- -
-
-
- )} - /> -
-
- ); - } -} diff --git a/src/routes/List/List.js b/src/routes/List/List.js new file mode 100644 index 0000000000000000000000000000000000000000..24c622d3ab11af55bd5e5e975957f8373396c46d --- /dev/null +++ b/src/routes/List/List.js @@ -0,0 +1,82 @@ +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 = ( +
+ +
+ ); + + const { match } = this.props; + const { routeData } = this.context; + const routes = routeData.filter(item => item.path === match.path)[0].children; + + return ( + + + { + routes.map(item => + ( + + ) + ) + } + + + ); + } +} diff --git a/src/routes/List/Projects.js b/src/routes/List/Projects.js new file mode 100644 index 0000000000000000000000000000000000000000..b70eab5db9a26f001d775b1c4606936c075c5df5 --- /dev/null +++ b/src/routes/List/Projects.js @@ -0,0 +1,171 @@ +import React, { PureComponent } from 'react'; +import moment from 'moment'; +import { connect } from 'dva'; +import { Row, Col, Form, Card, Select, List } from 'antd'; + +import StandardFormRow from '../../components/StandardFormRow'; +import TagSelect from '../../components/TagSelect'; +import AvatarList from '../../components/AvatarList'; + +import styles from './Projects.less'; + +const { Option } = Select; +const FormItem = Form.Item; + +/* eslint react/no-array-index-key: 0 */ +@Form.create() +@connect(state => ({ + list: state.list, +})) +export default class CoverCardList extends PureComponent { + componentDidMount() { + this.props.dispatch({ + type: 'list/fetch', + payload: { + count: 8, + }, + }); + } + + handleFormSubmit = () => { + const { form, dispatch } = this.props; + // setTimeout 用于保证获取表单值是在所有表单字段更新完毕的时候 + setTimeout(() => { + form.validateFields((err) => { + if (!err) { + // eslint-disable-next-line + dispatch({ + type: 'list/fetch', + payload: { + count: 8, + }, + }); + } + }); + }, 0); + } + + render() { + const { list: { list = [], loading }, form } = this.props; + const { getFieldDecorator } = form; + + const cardList = list ? ( + ( + + } + > + {item.title}} + description={item.subDescription} + /> +
+ {moment(item.updatedAt).fromNow()} +
+ + { + item.members.map((member, i) => ( + + )) + } + +
+
+
+
+ )} + /> + ) : null; + + const formItemLayout = { + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + }; + + return ( +
+ +
+ + + {getFieldDecorator('category')( + + 类目一 + 类目二 + 类目三 + 类目四 + 类目五 + 类目六 + 类目七 + 类目八 + 类目九 + 类目十 + 类目十一 + 类目十二 + + )} + + + + + + + {getFieldDecorator('author', {})( + + )} + + + + + {getFieldDecorator('rate', {})( + + )} + + + + +
+
+
+ {cardList} +
+
+ ); + } +} diff --git a/src/routes/List/CoverCardList.less b/src/routes/List/Projects.less similarity index 100% rename from src/routes/List/CoverCardList.less rename to src/routes/List/Projects.less diff --git a/src/routes/List/SearchList.js b/src/routes/List/SearchList.js deleted file mode 100644 index 910bbee04d04a0e1afd8c8c7ca8786bf35c1c6f3..0000000000000000000000000000000000000000 --- a/src/routes/List/SearchList.js +++ /dev/null @@ -1,294 +0,0 @@ -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 }) => ( - - - {text} - - ); - - const ListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => ( -
-
{content}
-
- {owner} 发布在 {href} - {moment(updatedAt).format('YYYY-MM-DD hh:mm')} -
-
- ); - - const pageHeaderContent = ( -
- -
- ); - - const formItemLayout = { - wrapperCol: { - xs: { span: 24 }, - sm: { span: 24 }, - md: { span: 12 }, - }, - }; - - const loadMore = list.length > 0 ? ( -
- -
- ) : null; - - return ( - -
- -
- - - {getFieldDecorator('category')( - - 类目一 - 类目二 - 类目三 - 类目四 - 类目五 - 类目六 - 类目七 - 类目八 - 类目九 - 类目十 - 类目十一 - 类目十二 - - )} - - - - - - - {getFieldDecorator('owner', { - initialValue: ['wjh', 'zxx'], - })( - - )} - 只看自己的 - - - - - - - - - {getFieldDecorator('user', {})( - - )} - - - - - {getFieldDecorator('rate', {})( - - {getFieldDecorator('rate', {})( - - )} - - )} - - - - -
-
- - ( - , - , - , - ]} - extra={
} - > - {item.title} - )} - description={ - - Ant Design - 设计语言 - 蚂蚁金服 - - } - /> - - - )} - /> - -
- - ); - } -}