|
@@ -0,0 +1,213 @@
|
|
|
|
|
+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>
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+}
|