Merge branch 'dev' of gitlab.corp.qunar.com:mfe/yapi into dev

This commit is contained in:
sean 2017-08-14 13:44:55 +08:00
commit 1a2e1dbfc0
19 changed files with 215 additions and 329 deletions

View File

@ -96,6 +96,9 @@ $color-black-light : #404040;
.ant-avatar-image{ .ant-avatar-image{
margin-bottom: -10px; margin-bottom: -10px;
} }
.ant-avatar > img{
height: auto;
}
} }
&:hover{ &:hover{
.dropdown-link { .dropdown-link {

View File

@ -1,28 +0,0 @@
import './ProjectBox.scss'
import React, { Component } from 'react'
// import PropTypes from 'prop-types'
class ProjectBox extends Component {
constructor(props) {
super(props);
this.state = {
};
}
static propTypes = {
}
render() {
return (
<div className="p-box">
<div className="p-container"></div>
</div>
)
}
}
export default ProjectBox

View File

@ -1,21 +0,0 @@
@import '../../styles/mixin.scss';
.p-box{
min-width: 150px;
min-height: 200px;
// background-color: #dbd;
.p-container{
width: 100%;
height: 100%;
background: #fff;
border-radius: 2px;
font-size: 12px;
position: relative;
-webkit-transition: all .3s;
transition: all .3s;
&:hover{
box-shadow: 0 1px 6px rgba(0,0,0,.2);
border-color: transparent;
}
}
}

View File

@ -0,0 +1,37 @@
import './ProjectCard.scss';
import React, { Component } from 'react';
import { Card, Icon } from 'antd';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
class ProjectCard extends Component {
constructor(props) {
super(props);
this.state = {
};
}
static propTypes = {
projectData: PropTypes.object
}
render() {
const { projectData } = this.props;
console.log(projectData);
return (
<Link to={`/project/${projectData._id}`}>
<Card bordered={false} bodyStyle={{padding: 16}} className="m-card">
<div className="m-card-logo">
<Icon type="area-chart" className="icon" />
<p className="name">{projectData.name}</p>
</div>
<div className="m-card-btns" style={{display: 'none'}}>btns</div>
</Card>
</Link>
)
}
}
export default ProjectCard

View File

@ -0,0 +1,22 @@
@import '../../styles/mixin.scss';
.m-card {
cursor: pointer;
text-align: center;
margin-bottom: .16rem;
background-color: #fff;
transition: all .4s;
color: rgba(0, 0, 0, 0.65);
&:hover {
background-color: #efefef;
}
.m-card-logo {
.icon {
font-size: .8rem;
}
.name {
font-size: .18rem;
margin-top: .16rem;
}
}
}

View File

@ -4,7 +4,7 @@ import Header from './Header/Header.js'
import Intro from './Intro/Intro.js' import Intro from './Intro/Intro.js'
import Loading from './Loading/Loading.js' import Loading from './Loading/Loading.js'
import MockDoc from './MockDoc/MockDoc.js' import MockDoc from './MockDoc/MockDoc.js'
import ProjectBox from './ProjectBox/ProjectBox.js' import ProjectCard from './ProjectCard/ProjectCard.js'
import Subnav from './Subnav/Subnav.js' import Subnav from './Subnav/Subnav.js'
export { export {
@ -14,6 +14,6 @@ export {
Intro, Intro,
Loading, Loading,
MockDoc, MockDoc,
ProjectBox, ProjectCard,
Subnav Subnav
} }

View File

@ -3,6 +3,7 @@
.m-container { .m-container {
margin: .24rem auto !important; margin: .24rem auto !important;
padding: .24rem !important; padding: .24rem !important;
background-color: #fff;
} }
.form-item { .form-item {

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import './Follows.scss'; import './Follows.scss';
import Subnav from '../../components/Subnav/Subnav.js'; import Subnav from '../../components/Subnav/Subnav.js';
import ProjectBox from '../../components/ProjectBox/ProjectBox.js'; import ProjectCard from '../../components/ProjectCard/ProjectCard.js';
class Follows extends Component { class Follows extends Component {
render () { render () {
@ -19,10 +19,10 @@ class Follows extends Component {
<div className="g-row"> <div className="g-row">
<div className="follow-box"> <div className="follow-box">
<div className="follow-container"> <div className="follow-container">
<ProjectBox /> <ProjectCard />
<ProjectBox /> <ProjectCard />
<ProjectBox /> <ProjectCard />
<ProjectBox /> <ProjectCard />
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,9 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import GroupList from './GroupList/GroupList.js'; import GroupList from './GroupList/GroupList.js';
import ProjectList from './ProjectList/ProjectList.js'; import ProjectList from './ProjectList/ProjectList.js';
import MemberList from './MemberList/MemberList.js';
import Subnav from '../../components/Subnav/Subnav.js'; import Subnav from '../../components/Subnav/Subnav.js';
import { Route, Switch, Redirect } from 'react-router-dom'; import { Route, Switch, Redirect } from 'react-router-dom';
import { Row, Col } from 'antd'; import { Row, Col, Tabs } from 'antd';
const TabPane = Tabs.TabPane;
import './Group.scss' import './Group.scss'
@ -21,7 +23,10 @@ export default class Group extends Component {
<GroupList></GroupList> <GroupList></GroupList>
</Col> </Col>
<Col span={18}> <Col span={18}>
<ProjectList/> <Tabs type="card" className="m-tab">
<TabPane tab="项目列表" key="1"><ProjectList/></TabPane>
<TabPane tab="成员列表" key="2"><MemberList/></TabPane>
</Tabs>
</Col> </Col>
</Row> </Row>
</div> </div>

View File

@ -0,0 +1,16 @@
import React, { Component } from 'react';
import './MemberList.scss'
class MemberList extends Component {
render() {
return (
<div className="m-panel">
chengyuan 列表 成员
</div>
);
}
}
export default MemberList;

View File

@ -0,0 +1,8 @@
.m-panel{
background-color: #fff;
padding: 24px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
border-radius: 4px;
min-height: 5rem;
margin-top: 0;
}

View File

@ -1,93 +1,77 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Table, Button, Modal, Form, Input, Icon, Tooltip, Select, Popconfirm, message } from 'antd'; import { message, Row, Col } from 'antd';
import { addProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project'; import { addProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project';
import UpDateModal from './UpDateModal'; import ProjectCard from '../../../components/ProjectCard/ProjectCard.js';
import { Link } from 'react-router-dom' // import variable from '../../../constants/variable';
import variable from '../../../constants/variable';
import common from '../../../common';
import { autobind } from 'core-decorators'; import { autobind } from 'core-decorators';
const { TextArea } = Input;
const FormItem = Form.Item;
const Option = Select.Option;
import './ProjectList.scss' import './ProjectList.scss'
// 确认删除项目 handleDelete, currGroup._id, fetchProjectList // 确认删除项目 handleDelete, currGroup._id, fetchProjectList
const deleteConfirm = (id, props) => { // const deleteConfirm = (id, props) => {
const { delProject, currGroup, fetchProjectList } = props; // const { delProject, currGroup, fetchProjectList } = props;
const handle = () => { // const handle = () => {
delProject(id).then((res) => { // delProject(id).then((res) => {
if (res.payload.data.errcode == 0) { // if (res.payload.data.errcode == 0) {
message.success('删除成功!') // message.success('删除成功!')
fetchProjectList(currGroup._id).then(() => { // fetchProjectList(currGroup._id).then(() => {
}); // });
} else { // } else {
message.error(res.payload.data.errmsg); // message.error(res.payload.data.errmsg);
} // }
}); // });
} // }
return handle; // return handle;
}; // };
const getColumns = (data, props) => { // const getColumns = (data, props) => {
const { changeUpdateModal, userInfo } = props; // const { changeUpdateModal, userInfo } = props;
return [{ // return [{
title: '项目名称', // title: '项目名称',
dataIndex: 'name', // dataIndex: 'name',
key: 'name', // key: 'name',
render: (text, record) => { // render: (text, record) => {
return <Link to={`/project/${record._id}`}>{text}</Link> // return <Link to={`/project/${record._id}`}>{text}</Link>
} // }
},{ // },{
title: 'Mock基本URL', // title: 'Mock基本URL',
key: 'domain', // key: 'domain',
render: (item) => { // render: (item) => {
return 'http://'+ item.prd_host + item.basepath; // return 'http://'+ item.prd_host + item.basepath;
} // }
//
}, { // }, {
title: '创建人', // title: '创建人',
dataIndex: 'owner', // dataIndex: 'owner',
key: 'owner', // key: 'owner',
render: (text, record, index) => { // render: (text, record, index) => {
// data是projectList的列表值 // // data是projectList的列表值
// 根据序号找到对应项的uid根据uid获取对应项目的创建人 // // 根据序号找到对应项的uid根据uid获取对应项目的创建人
return <span>{userInfo[data[index].uid] ? userInfo[data[index].uid].username : ''}</span>; // return <span>{userInfo[data[index].uid] ? userInfo[data[index].uid].username : ''}</span>;
} // }
}, { // }, {
title: '创建时间', // title: '创建时间',
dataIndex: 'add_time', // dataIndex: 'add_time',
key: 'add_time', // key: 'add_time',
render: time => <span>{common.formatTime(time)}</span> // render: time => <span>{common.formatTime(time)}</span>
}, { // }, {
title: '操作', // title: '操作',
key: 'action', // key: 'action',
render: (text, record, index) => { // render: (text, record, index) => {
const id = record._id; // const id = record._id;
return ( // return (
<span> // <span>
<a onClick={() => changeUpdateModal(true, index)}>修改</a> // <a onClick={() => changeUpdateModal(true, index)}>修改</a>
<span className="ant-divider" /> // <span className="ant-divider" />
<Popconfirm title="你确定要删除项目吗?" onConfirm={deleteConfirm(id, props)} okText="确定" cancelText="取消"> // <Popconfirm title="你确定要删除项目吗?" onConfirm={deleteConfirm(id, props)} okText="确定" cancelText="取消">
<a href="#">删除</a> // <a href="#">删除</a>
</Popconfirm> // </Popconfirm>
</span> // </span>
)} // )}
}]; // }];
} // }
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 }
}
};
@connect( @connect(
state => { state => {
@ -132,49 +116,6 @@ class ProjectList extends Component {
currPage: PropTypes.number currPage: PropTypes.number
} }
// 显示模态框 - 创建项目
@autobind
showAddProjectModal() {
this.setState({
visible: true
});
}
// 确认添加项目
@autobind
handleOk(e) {
const { form, currGroup, changeTableLoading, addProject, fetchProjectList } = this.props;
const that = this;
e.preventDefault();
form.validateFields((err, values) => {
if (!err) {
values.protocol = this.state.protocol.split(':')[0];
// 获取当前分组id传入values
values.group_id = currGroup._id;
changeTableLoading(true);
addProject(values).then((res) => {
// 添加项目成功后再次请求列表
if (res.payload.data.errcode == 0) {
that.setState({
visible: false
});
form.resetFields();
message.success('创建成功! ');
fetchProjectList(currGroup._id, this.props.currPage).then(() => {
changeTableLoading(false);
});
} else {
changeTableLoading(false);
message.error(res.payload.data.errmsg);
}
}).catch(() => {
changeTableLoading(false);
});
}
});
}
// 取消修改 // 取消修改
@autobind @autobind
handleCancel() { handleCancel() {
@ -235,109 +176,20 @@ class ProjectList extends Component {
} }
render() { render() {
const { getFieldDecorator } = this.props.form; const projectData = this.state.projectData;
return ( return (
<div className="m-container"> <div className="m-panel">
<Modal <Row gutter={16}>
title="创建项目" {projectData.map((item, index) => {
visible={this.state.visible} return (
onOk={this.handleOk} <Col span={8} key={index}>
onCancel={this.handleCancel} <ProjectCard projectData={item} />
> </Col>);
<Form> })}
</Row>
<FormItem
{...formItemLayout}
label="项目名称"
>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入项目名称!'
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
线上域名&nbsp;
<Tooltip title="将根据配置的线上域名访问mock数据">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('prd_host', {
rules: [{
required: true,
message: '请输入项目线上域名!'
}]
})(
<Input addonBefore={(
<Select defaultValue="http://" onChange={this.protocolChange}>
<Option value="http://">{'http:\/\/'}</Option>
<Option value="https://">{'https:\/\/'}</Option>
</Select>)} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
基本路径&nbsp;
<Tooltip title="基本路径为空是根路径">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('basepath', {
rules: [{
required: false, message: '请输入项目基本路径'
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="描述"
>
{getFieldDecorator('desc', {
rules: [{
required: false, message: '请输入描述!'
}]
})(
<TextArea rows={4} />
)}
</FormItem>
</Form>
</Modal>
<UpDateModal/>
<Button className="m-btn" icon="plus" type="primary"
onClick={this.showAddProjectModal}
disabled={this.props.currGroup._id ? false : true}>创建项目</Button>
<Table
className="m-table"
bordered={true}
loading={this.props.tableLoading}
columns={getColumns(this.state.projectData, this.props)}
dataSource={this.state.projectData}
pagination={{
total: this.props.total * variable.PAGE_LIMIT,
defaultPageSize: variable.PAGE_LIMIT,
onChange: this.paginationChange
}}
/>
</div> </div>
); );
} }
} }
export default Form.create()(ProjectList); export default ProjectList;

View File

@ -1,14 +1,15 @@
.m-container{ .ant-tabs-bar {
border-bottom: 1px solid transparent;
margin-bottom: 0;
}
.m-panel{
background-color: #fff; background-color: #fff;
padding: 24px; padding: 24px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20); box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
border-radius: 4px; border-radius: 4px;
min-height: 5rem; min-height: 5rem;
} margin-top: 0;
.m-table {
text-align: left;
margin-top: .16rem;
} }
.ant-input-group-wrapper { .ant-input-group-wrapper {

View File

@ -1,10 +1,5 @@
@import '../../styles/common.scss'; @import '../../styles/common.scss';
.ant-tabs-nav-wrap {
font-size: .16rem;
text-align: center;
}
.login-form-button { .login-form-button {
// background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%) !important; // background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%) !important;
// border: none !important; // border: none !important;

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { Row, Col, Input, Button, Select, message, Upload, Icon ,Avatar} from 'antd' import { Row, Col, Input, Button, Select, message, Upload} from 'antd'
import axios from 'axios'; import axios from 'axios';
import {formatTime} from '../../common.js' import {formatTime} from '../../common.js'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
@ -273,7 +273,6 @@ class AvatarUpload extends Component {
uploadAvatar(basecode){ uploadAvatar(basecode){
axios.post("/api/user/upload_avatar",{basecode: basecode}).then(()=>{ axios.post("/api/user/upload_avatar",{basecode: basecode}).then(()=>{
this.setState({ imageUrl: basecode }); this.setState({ imageUrl: basecode });
}).catch((e)=>{ }).catch((e)=>{
console.log(e); console.log(e);
}) })
@ -284,22 +283,20 @@ class AvatarUpload extends Component {
getBase64(info.file.originFileObj, basecode=>{this.uploadAvatar(basecode)}); getBase64(info.file.originFileObj, basecode=>{this.uploadAvatar(basecode)});
} }
} }
render() { render() {
let imageUrl = this.state.imageUrl?this.state.imageUrl:`/api/user/avatar?uid=${this.props.uid}`; let imageUrl = this.state.imageUrl?this.state.imageUrl:`/api/user/avatar?uid=${this.props.uid}`;
// console.log(this.props.uid);
return <div className="avatar-box"> return <div className="avatar-box">
<Upload <Upload
className="avatar-uploader" className="avatar-uploader"
name="basecode" name="basecode"
showUploadList={true} showUploadList={false}
action="/api/user/upload_avatar" action="/api/user/upload_avatar"
beforeUpload={beforeUpload} beforeUpload={beforeUpload}
onChange={this.handleChange.bind(this)} > onChange={this.handleChange.bind(this)} >
{ {/*<Avatar size="large" src={imageUrl} />*/}
imageUrl ? <img className = "avatar" src = {imageUrl} />
<Avatar size="large" src={imageUrl} />:
<Icon type="plus" className="avatar-uploader-trigger" />
}
</Upload> </Upload>
<span className="avatarChange">点击头像更换</span> <span className="avatarChange">点击头像更换</span>
</div> </div>

View File

@ -113,22 +113,19 @@
border: none; border: none;
} }
.avatar-uploader, .avatar-uploader,
.avatar-uploader-trigger, .avatar-uploader-trigger{
.avatar { width: 100px;
// width: 100px; height: 100px;
// height: 100px;
overflow: hidden; overflow: hidden;
// border-radius: 50px; border-radius: 50px;
}
.avatar{
width: 100px;
} }
.avatar-uploader { .avatar-uploader {
display: block; display: block;
cursor: pointer; cursor: pointer;
} }
.ant-avatar-lg{
width: 100px;
height: 100px;
border-radius: 50px;
}
.ant-upload-list{ .ant-upload-list{
display: none; display: none;
} }

View File

@ -249,11 +249,11 @@
</li> </li>
<li > <li >
<a href="#-follow-list">/follow/list</a> <a href="#-follow-del">/follow/del</a>
</li> </li>
<li > <li >
<a href="#-follow-list">/follow/list</a> <a href="#-follow-add">/follow/add</a>
</li> </li>
</ul> </ul>
@ -3468,13 +3468,13 @@
<div class="con-list-item"> <div class="con-list-item">
<blockquote class="api"> <blockquote class="api">
<h3 id="-follow-list" class="page-header subject"> <h3 id="-follow-del" class="page-header subject">
/follow/list /follow/del
<span class="ui-badge">POST</span> <span class="ui-badge">POST</span>
<a class="hashlink" href="#-follow-list">#</a> <a class="hashlink" href="#-follow-del">#</a>
</h3> </h3>
</blockquote> </blockquote>
<p> <p>
@ -3533,13 +3533,13 @@
<div class="con-list-item"> <div class="con-list-item">
<blockquote class="api"> <blockquote class="api">
<h3 id="-follow-list" class="page-header subject"> <h3 id="-follow-add" class="page-header subject">
/follow/list /follow/add
<span class="ui-badge">POST</span> <span class="ui-badge">POST</span>
<a class="hashlink" href="#-follow-list">#</a> <a class="hashlink" href="#-follow-add">#</a>
</h3> </h3>
</blockquote> </blockquote>
<p> <p>

View File

@ -87,7 +87,7 @@ class followController extends baseController {
/** /**
* 取消关注 * 取消关注
* @interface /follow/list * @interface /follow/del
* @method POST * @method POST
* @category follow * @category follow
* @foldnumber 10 * @foldnumber 10
@ -113,7 +113,7 @@ class followController extends baseController {
/** /**
* 添加关注 * 添加关注
* @interface /follow/list * @interface /follow/add
* @method POST * @method POST
* @category follow * @category follow
* @foldnumber 10 * @foldnumber 10
@ -173,6 +173,7 @@ class followController extends baseController {
} }
module.exports = followController; module.exports = followController;
</pre> </pre>
</div> </div>
</div> </div>