Commit 522ec422 authored by ddcat1115's avatar ddcat1115 Committed by jim

individual url #1072

parent f87d7371
...@@ -164,7 +164,16 @@ export const getRouterData = (app) => { ...@@ -164,7 +164,16 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')), component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')),
}, },
'/account/center': { '/account/center': {
component: dynamicWrapper(app, ['list', 'user', 'project'], () => import('../routes/Account/Center')), component: dynamicWrapper(app, ['list', 'user', 'project'], () => import('../routes/Account/Center/Center')),
},
'/account/center/articles': {
component: dynamicWrapper(app, [], () => import('../routes/Account/Center/Articles')),
},
'/account/center/applications': {
component: dynamicWrapper(app, [], () => import('../routes/Account/Center/Applications')),
},
'/account/center/projects': {
component: dynamicWrapper(app, [], () => import('../routes/Account/Center/Projects')),
}, },
'/account/settings': { '/account/settings': {
component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/Info')), component: dynamicWrapper(app, ['geographic'], () => import('../routes/Account/Settings/Info')),
......
import React from 'react';
import { List, Card, Icon, Dropdown, Menu, Avatar, Tooltip } from 'antd';
import numeral from 'numeral';
import { formatWan } from '../../../utils/utils';
import stylesApplications from '../../List/Applications.less';
export default (props) => {
const { list } = props;
const itemMenu = (
<Menu>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">1st menu item</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">2nd menu item</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">3d menu item</a>
</Menu.Item>
</Menu>
);
const CardInfo = ({ activeUser, newUser }) => (
<div className={stylesApplications.cardInfo}>
<div>
<p>活跃用户</p>
<p>{activeUser}</p>
</div>
<div>
<p>新增用户</p>
<p>{newUser}</p>
</div>
</div>
);
return (
<List
rowKey="id"
className={stylesApplications.filterCardList}
grid={{ gutter: 24, xxl: 3, xl: 2, lg: 2, md: 2, sm: 2, xs: 1 }}
dataSource={list}
renderItem={item => (
<List.Item key={item.id}>
<Card
hoverable
bodyStyle={{ paddingBottom: 20 }}
actions={[
<Tooltip title="下载"><Icon type="download" /></Tooltip>,
<Tooltip title="编辑"><Icon type="edit" /></Tooltip>,
<Tooltip title="分享"><Icon type="share-alt" /></Tooltip>,
<Dropdown overlay={itemMenu}><Icon type="ellipsis" /></Dropdown>,
]}
>
<Card.Meta
avatar={<Avatar size="small" src={item.avatar} />}
title={item.title}
/>
<div className={stylesApplications.cardItemContent}>
<CardInfo
activeUser={formatWan(item.activeUser)}
newUser={numeral(item.newUser).format('0,0')}
/>
</div>
</Card>
</List.Item>
)}
/>
);
};
import React from 'react';
import { List, Icon, Avatar, Tag } from 'antd';
import moment from 'moment';
import stylesArticles from '../../List/Articles.less';
import styles from './Articles.less';
export default (props) => {
const { list } = props;
const IconText = ({ type, text }) => (
<span>
<Icon type={type} style={{ marginRight: 8 }} />
{text}
</span>
);
const ListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => (
<div className={stylesArticles.listContent}>
<div className={stylesArticles.description}>{content}</div>
<div className={stylesArticles.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>
);
return (
<List
size="large"
className={styles.articleList}
rowKey="id"
itemLayout="vertical"
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} />,
]}
>
<List.Item.Meta
title={(
<a className={stylesArticles.listItemMetaTitle} href={item.href}>{item.title}</a>
)}
description={
<span>
<Tag>Ant Design</Tag>
<Tag>设计语言</Tag>
<Tag>蚂蚁金服</Tag>
</span>
}
/>
<ListContent data={item} />
</List.Item>
)}
/>
);
};
.articleList {
:global {
.ant-list-item:first-child {
padding-top: 0;
}
}
}
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Link, routerRedux, Route, Switch, Redirect } from 'dva/router';
import { Card, Row, Col, Icon, Avatar, Tag, Divider, Spin, Input } from 'antd';
import { getRoutes } from '../../../utils/utils';
import styles from './Center.less';
@connect(({ list, loading, user, project }) => ({
list,
listLoading: loading.effects['list/fetch'],
currentUser: user.currentUser,
currentUserLoading: loading.effects['user/fetchCurrent'],
project,
projectLoading: loading.effects['project/fetchNotice'],
}))
export default class Center extends PureComponent {
state = {
newTags: [],
inputVisible: false,
inputValue: '',
}
componentDidMount() {
const { dispatch } = this.props;
this.props.dispatch({
type: 'user/fetchCurrent',
});
dispatch({
type: 'list/fetch',
payload: {
count: 8,
},
});
dispatch({
type: 'project/fetchNotice',
});
}
onTabChange = (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;
}
}
showInput = () => {
this.setState({ inputVisible: true }, () => this.input.focus());
}
saveInputRef = (input) => {
this.input = input;
}
handleInputChange = (e) => {
this.setState({ inputValue: e.target.value });
}
handleInputConfirm = () => {
const { state } = this;
const { inputValue } = state;
let { newTags } = state;
if (inputValue && newTags.filter(tag => tag.label === inputValue).length === 0) {
newTags = [...newTags, { key: `new-${newTags.length}`, label: inputValue }];
}
this.setState({
newTags,
inputVisible: false,
inputValue: '',
});
}
render() {
const { newTags, inputVisible, inputValue } = this.state;
const { list: { list }, listLoading, currentUser, currentUserLoading,
project: { notice }, projectLoading, match, routerData, location } = this.props;
const routes = getRoutes(match.path, routerData);
const operationTabList = [{
key: 'articles',
tab: <span>文章 <span style={{ fontSize: 14 }}>(8)</span></span>,
}, {
key: 'applications',
tab: <span>应用 <span style={{ fontSize: 14 }}>(8)</span></span>,
}, {
key: 'projects',
tab: <span>项目 <span style={{ fontSize: 14 }}>(8)</span></span>,
}];
return (
<div className={styles.userCenter}>
<Row gutter={24}>
<Col lg={7} md={24}>
<Card
bordered={false}
style={{ marginBottom: 24 }}
loading={currentUserLoading}
>
{
currentUser && Object.keys(currentUser).length ?
(
<div>
<div className={styles.avatarHolder}>
<img alt="" src={currentUser.avatar} />
<div className={styles.name}>{currentUser.name}</div>
<div>{currentUser.signature}</div>
</div>
<div className={styles.detail}>
<p><i className={styles.title} />{currentUser.title}</p>
<p><i className={styles.group} />{currentUser.group}</p>
<p><i className={styles.address} />
{currentUser.geographic.province.label}
{currentUser.geographic.city.label}
</p>
</div>
<Divider dashed />
<div className={styles.tags}>
<div className={styles.tagsTitle}>标签</div>
{
currentUser.tags.concat(newTags).map(item =>
<Tag key={item.key}>{item.label}</Tag>)
}
{inputVisible && (
<Input
ref={this.saveInputRef}
type="text"
size="small"
style={{ width: 78 }}
value={inputValue}
onChange={this.handleInputChange}
onBlur={this.handleInputConfirm}
onPressEnter={this.handleInputConfirm}
/>
)}
{!inputVisible && (
<Tag
onClick={this.showInput}
style={{ background: '#fff', borderStyle: 'dashed' }}
>
<Icon type="plus" />
</Tag>
)}
</div>
<Divider style={{ marginTop: 16 }} dashed />
<div className={styles.team}>
<div className={styles.teamTitle}>团队</div>
<Spin spinning={projectLoading}>
<Row gutter={36}>
{
notice.map(item => (
<Col key={item.id} lg={24} xl={12}>
<Link to={item.href}>
<Avatar size="small" src={item.logo} />
{item.member}
</Link>
</Col>
))
}
</Row>
</Spin>
</div>
</div>
) : 'loading...'
}
</Card>
</Col>
<Col lg={17} md={24}>
<Card
className={styles.tabsCard}
bordered={false}
tabList={operationTabList}
activeTabKey={location.pathname.replace(`${match.path}/`, '')}
onTabChange={this.onTabChange}
loading={listLoading}
>
<Switch>
{
routes.map(item =>
(
<Route
key={item.key}
path={item.path}
render={props => (
<item.component {...props} list={list} />
)}
exact={item.exact}
/>
)
)
}
<Redirect
exact
from="/account/center"
to="/account/center/articles"
/>
<Redirect to="/exception/404" />
</Switch>
</Card>
</Col>
</Row>
</div>
);
}
}
@import '~antd/lib/style/themes/default.less';
@import "../../../utils/utils.less";
.avatarHolder {
text-align: center;
margin-bottom: 24px;
& > img {
width: 104px;
height: 104px;
margin-bottom: 20px;
}
.name {
font-size: 20px;
line-height: 28px;
font-weight: 500;
color: @heading-color;
margin-bottom: 4px;
}
}
.detail {
p {
margin-bottom: 8px;
padding-left: 26px;
position: relative;
&:last-child {
margin-bottom: 0;
}
}
i {
position: absolute;
height: 14px;
width: 14px;
left: 0;
top: 4px;
background: url(https://gw.alipayobjects.com/zos/rmsportal/pBjWzVAHnOOtAUvZmZfy.svg);
&.title {
background-position: 0 0;
}
&.group {
background-position: 0 -22px;
}
&.address {
background-position: 0 -44px;
}
}
}
.tagsTitle, .teamTitle {
font-weight: 500;
color: @heading-color;
margin-bottom: 12px;
}
.tags {
:global {
.ant-tag {
margin-bottom: 8px;
}
}
}
.team {
:global {
.ant-avatar {
margin-right: 12px;
}
}
a {
display: block;
margin-bottom: 24px;
color: @text-color;
transition: color .3s;
.textOverflow();
&:hover {
color: @primary-color;
}
}
}
.tabsCard {
:global {
.ant-card-head {
padding: 0 16px;
}
}
}
import React from 'react';
import { List, Card } from 'antd';
import moment from 'moment';
import AvatarList from '../../../components/AvatarList';
import stylesProjects from '../../List/Projects.less';
export default (props) => {
const { list } = props;
return (
<List
className={stylesProjects.coverCardList}
rowKey="id"
grid={{ gutter: 24, xxl: 3, xl: 2, lg: 2, md: 2, sm: 2, xs: 1 }}
dataSource={list}
renderItem={item => (
<List.Item>
<Card
className={stylesProjects.card}
hoverable
cover={<img alt={item.title} src={item.cover} />}
>
<Card.Meta
title={<a href="#">{item.title}</a>}
description={item.subDescription}
/>
<div className={stylesProjects.cardItemContent}>
<span>{moment(item.updatedAt).fromNow()}</span>
<div className={stylesProjects.avatarList}>
<AvatarList size="mini">
{
item.members.map(member => (
<AvatarList.Item
key={`${item.id}-avatar-${member.id}`}
src={member.avatar}
tips={member.name}
/>
))
}
</AvatarList>
</div>
</div>
</Card>
</List.Item>
)}
/>
);
};
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