feat: add project

This commit is contained in:
sean 2017-08-11 17:25:57 +08:00
commit d32742ac80
28 changed files with 497 additions and 178 deletions

2
.gitignore vendored
View File

@ -37,3 +37,5 @@ node_modules/
runtime/
prd/
dev/
.tags
.tags1

View File

@ -56,7 +56,7 @@ export default class App extends Component {
<div className="router-main">
<Header />
<div className="router-container">
<Route path="/" component={Home} exact />
<Route exact path="/" component={Home} />
<Route path="/group" component={requireAuthentication(Group)} />
<Route path="/project/:id" component={requireAuthentication(Project)} />
<Route path="/user" component={requireAuthentication(User)} />

View File

@ -10,18 +10,8 @@ import { withRouter } from 'react-router';
import Srch from './Search/Search'
const { Header } = Layout;
const headerStyle = {
'height': '.56rem',
'lineHeight': '.56rem',
'padding': 0
};
const MenuUser = (props) => (
<Menu
style={{
"boxShadow":"0 1px 6px rgba(0, 0, 0, 0.3)"
}}
>
<Menu className="user-menu" >
<Menu.Item key="0">
<Link to={`/user/profile/${props.uid}`} onClick={props.relieveLink}><Icon type="user"/>个人中心</Link>
</Menu.Item>
@ -171,7 +161,7 @@ export default class HeaderCom extends Component {
render () {
const { login, user, msg, uid } = this.props;
return (
<Header className="header-box" style={headerStyle}>
<Header className="header-box m-header">
<div className="content g-row">
<div className="logo">
<Link to="/" onClick={this.relieveLink} className="href">

View File

@ -13,6 +13,9 @@ $color-black-light : #404040;
/* .header-box.css */
.header-box {
height: .56rem;
line-height: .56rem;
padding: 0;
.logo {
position: relative;
float: left;
@ -46,6 +49,24 @@ $color-black-light : #404040;
from { background-position: 0px; }
to { background-position: -240px; }
}
&:before, &:after {
content: '';
display: block;
width: 2px;
height: .56rem;
background-color: #222;
border-left: 1px solid #575D67;
position: relative;
top: 0;
}
&:before {
float: left;
left: -.08rem;
}
&:after {
float: right;
right: -.27rem;
}
}
.nav-toolbar {

View File

@ -2,10 +2,8 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Button, Form, Input, Icon, Tooltip, Select, message, Row, Col, Radio } from 'antd';
import { addProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project';
// import { Link } from 'react-router-dom'
// import variable from '../../../constants/variable';
// import common from '../../../common';
import { addProject } from '../../reducer/modules/project.js';
import { fetchGroupList } from '../../reducer/modules/group.js'
import { autobind } from 'core-decorators';
const { TextArea } = Input;
const FormItem = Form.Item;
@ -30,77 +28,46 @@ const formItemLayout = {
@connect(
state => {
return {
projectList: state.project.projectList,
userInfo: state.project.userInfo,
tableLoading: state.project.tableLoading,
currGroup: state.group.currGroup,
total: state.project.total,
currPage: state.project.currPage
groupList: state.group.groupList
}
},
{
fetchProjectList,
addProject,
delProject,
changeUpdateModal,
changeTableLoading
fetchGroupList,
addProject
}
)
class ProjectList extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
protocol: 'http:\/\/',
projectData: []
groupList: []
}
}
static propTypes = {
groupList: PropTypes.array,
form: PropTypes.object,
fetchProjectList: PropTypes.func,
addProject: PropTypes.func,
delProject: PropTypes.func,
changeUpdateModal: PropTypes.func,
changeTableLoading: PropTypes.func,
projectList: PropTypes.array,
userInfo: PropTypes.object,
tableLoading: PropTypes.bool,
currGroup: PropTypes.object,
total: PropTypes.number,
currPage: PropTypes.number
fetchGroupList: PropTypes.func
}
// 确认添加项目
@autobind
handleOk(e) {
const { form, currGroup, changeTableLoading, addProject, fetchProjectList } = this.props;
const that = this;
const { form, addProject } = this.props;
e.preventDefault();
form.validateFields((err, values) => {
// console.log(values);
console.log(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);
});
}
});
@ -114,18 +81,9 @@ class ProjectList extends Component {
})
}
componentWillReceiveProps(nextProps) {
// 切换项目列表
if (this.props.projectList !== nextProps.projectList) {
// console.log(nextProps.projectList);
const data = nextProps.projectList.map((item, index) => {
item.key = index;
return item;
});
this.setState({
projectData: data
});
}
async componentWillMount() {
await this.props.fetchGroupList();
this.setState({groupList: this.props.groupList});
}
render() {
@ -157,8 +115,7 @@ class ProjectList extends Component {
}]
})(
<Select>
<Option value="china">China</Option>
<Option value="use">U.S.A</Option>
{this.state.groupList.map((item, index) => <Option value={item._id.toString()} key={index}>{item.group_name}</Option>)}
</Select>
)}
</FormItem>
@ -227,18 +184,18 @@ class ProjectList extends Component {
{...formItemLayout}
label="权限"
>
{getFieldDecorator('radio-group', {
{getFieldDecorator('project_type', {
rules: [{
required: true
}],
initialValue: 1
initialValue: 'private'
})(
<RadioGroup>
<Radio value={1} className="radio">
<Radio value="private" className="radio">
<Icon type="lock" />私有<br /><span className="radio-desc">只有组长和项目开发者可以索引并查看项目信息</span>
</Radio>
<br />
<Radio value={2} className="radio">
<Radio value="public" className="radio">
<Icon type="unlock" />公开<br /><span className="radio-desc">任何人都可以索引并查看项目信息</span>
</Radio>
</RadioGroup>

View File

@ -1,4 +1,4 @@
@import '../../../styles/common.scss';
@import '../../styles/common.scss';
.m-container {
margin: .24rem auto !important;

View File

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import GroupList from './GroupList/GroupList.js';
import ProjectList from './ProjectList/ProjectList.js';
import Subnav from '../../components/Subnav/Subnav.js';
import { Route, Switch, Redirect } from 'react-router-dom';
import { Row, Col } from 'antd';
import './Group.scss'
@ -12,6 +13,19 @@ export default class Group extends Component {
}
render () {
const GroupContent = (
<div className="g-row">
<Row gutter={16}>
<Col span={6}>
<GroupList></GroupList>
</Col>
<Col span={18}>
<ProjectList/>
</Col>
</Row>
</div>
)
return (
<div>
<Subnav
@ -23,16 +37,10 @@ export default class Group extends Component {
name: '我的关注',
path: '/follow'
}]}/>
<div className="g-row">
<Row gutter={16}>
<Col span={6}>
<GroupList></GroupList>
</Col>
<Col span={18}>
<ProjectList/>
</Col>
</Row>
</div>
<Switch>
<Redirect exact from='/group' to='/group/0' />
<Route path="/group/:groupId" render={() => GroupContent} />
</Switch>
</div>
)
}

View File

@ -0,0 +1,4 @@
import React from 'react'
export default () => {
return <h1>hello colContent</h1>
}

View File

@ -0,0 +1,4 @@
import React from 'react'
export default () => {
return <h1>hello colContent</h1>
}

View File

@ -0,0 +1,5 @@
import React from 'react'
export default () => {
return <h1>接口Edit</h1>
}

View File

@ -0,0 +1,25 @@
import React from 'react'
import { Tabs } from 'antd';
import Edit from './Edit.js'
import View from './View.js'
import Run from './Run.js'
const TabPane = Tabs.TabPane;
const Content = () => {
return <div className="interface-content">
<Tabs defaultActiveKey="1" >
<TabPane tab="预览" key="1">
<View />
</TabPane>
<TabPane tab="编辑" key="2">
<Edit />
</TabPane>
<TabPane tab="运行" key="3">
<Run />
</TabPane>
</Tabs>
</div>
}
export default Content

View File

@ -0,0 +1,17 @@
import React from 'react'
import { Menu, Button, Input, Icon, Tag } from 'antd';
export default () => {
return <div>
<div className="interface-filter">
<Input placeholder="Filter by name" style={{width:"70%"}} />
<Tag color="#108ee9" style={{marginLeft:"15px"}} ><Icon type="plus" /></Tag>
</div>
<Menu className="interface-list">
<Menu.Item><Button className="btn-http" type="primary">POST </Button></Menu.Item>
<Menu.Item><Button className="btn-http btn-http-get" type="primary">GET</Button></Menu.Item>
</Menu>
</div>
}

View File

@ -0,0 +1,5 @@
import React from 'react'
export default () => {
return <h1>接口Run</h1>
}

View File

@ -0,0 +1,6 @@
import React from 'react'
export default () => {
return <h1>接口预览</h1>
}

View File

@ -0,0 +1,70 @@
.web-content{
.left-menu{
min-height: 5rem;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
background: #FFF;
border-radius:4px;
margin: 3px;
.ant-tabs-bar{
border-bottom: none;
margin-bottom: 0
}
.ant-tabs-nav{
width:100%;
background-color: #ececec
}
.ant-tabs-tab{
min-width: 50%;
}
.ant-tabs.ant-tabs-card > .ant-tabs-bar .ant-tabs-tab{
background-color: #fff
}
.ant-tabs.ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active{
background-color: #efefef
}
.interface-filter{
padding-left: 10px;
height:45px;
line-height: 32px;
padding-top:7px;
background-color: #efefef
}
.interface-list{
.btn-http{
height: 23px;
font-size: 10px;
margin-right: 7px;
padding: 0 5px;
width: 40px;
}
.btn-http-get{
background-color: #00a854;
border-color: #00a854
}
}
}
.right-content{
margin:3px;
min-height: 5rem;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
background: #FFF;
border-radius:4px;
.interface-content{
.ant-tabs-nav{
width:100%
}
.ant-tabs-nav-wrap{
text-align: left;
}
}
}
}

View File

@ -3,8 +3,11 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types'
import { Route, Switch, Redirect } from 'react-router-dom';
import { Subnav } from '../../components/index'
import Interface from './Interface/Interface.js'
import { getProject } from '../../reducer/modules/project';
import { Interface } from './Interface/Interface.js'
import { Activity } from './Activity/Activity.js'
import { Setting } from './Setting/Setting.js'
@connect(
state => {
@ -39,6 +42,7 @@ export default class Project extends Component {
render () {
const { match } = this.props;
console.log('project')
return (
<div>
<Subnav
@ -54,10 +58,10 @@ export default class Project extends Component {
path: `/project/${match.params.id}/activity`
}]}/>
<Switch>
<Redirect exact from='/project/:id' to={`/project/${match.params.id}/interface`} />
<Route path="/project/:id/activity" component={null} />
<Redirect exact from ="/project/:id" to={`/project/${match.params.id}/activity`}/>
<Route path="/project/:id/activity" component={Activity} />
<Route path="/project/:id/interface" component={Interface} />
<Route path="/project/:id/setting" component={null} />
<Route path="/project/:id/setting" component={Setting} />
</Switch>
</div>
)

View File

@ -3,11 +3,23 @@ import { Row, Col, Input, Button, Select, message, Upload, Icon } from 'antd'
import axios from 'axios';
import {formatTime} from '../../common.js'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
@connect(state=>{
return {
curUid: state.user.uid,
userType: state.user.type
}
},{
})
class Profile extends Component {
static propTypes = {
match: PropTypes.object
match: PropTypes.object,
curUid: PropTypes.number,
userType: PropTypes.string
}
constructor(props) {
@ -126,12 +138,21 @@ class Profile extends Component {
const Option = Select.Option;
let userinfo = this.state.userinfo;
let _userinfo = this.state._userinfo;
let roles = { admin: '管理员', member: '会员' }
let roles = { admin: '管理员', member: '会员' };
let userType = "";
if(this.props.userType === "third"){
userType = false;
}else if(this.props.userType === "site"){
userType = true;
}else{
userType = false;
}
if (this.state.usernameEdit === false) {
userNameEditHtml = <div >
<span className="text">{userinfo.username}</span>&nbsp;&nbsp;
{/*<span className="text-button" onClick={() => { this.handleEdit('usernameEdit', true) }}><Icon type="edit" />修改</span>*/}
<Button icon="edit" onClick={() => { this.handleEdit('usernameEdit', true) }}>修改</Button>
{userType?<Button icon="edit" onClick={() => { this.handleEdit('usernameEdit', true) }}>修改</Button>:""}
</div>
} else {
userNameEditHtml = <div>
@ -147,7 +168,7 @@ class Profile extends Component {
emailEditHtml = <div >
<span className="text">{userinfo.email}</span>&nbsp;&nbsp;
{/*<span className="text-button" onClick={() => { this.handleEdit('emailEdit', true) }} ><Icon type="edit" />修改</span>*/}
<Button icon="edit" onClick={() => { this.handleEdit('emailEdit', true) }}>修改</Button>
{userType?<Button icon="edit" onClick={() => { this.handleEdit('emailEdit', true) }}>修改</Button>:""}
</div>
} else {
emailEditHtml = <div>
@ -163,7 +184,7 @@ class Profile extends Component {
roleEditHtml = <div>
<span className="text">{roles[userinfo.role]}</span>&nbsp;&nbsp;
{/*<span className="text-button" onClick={() => { this.handleEdit('roleEdit', true) }} ><Icon type="edit" />修改</span>*/}
<Button icon="edit" onClick={() => { this.handleEdit('roleEdit', true) }}>修改</Button>
{userType?<Button icon="edit" onClick={() => { this.handleEdit('roleEdit', true) }}>修改</Button>:""}
</div>
} else {
roleEditHtml = <Select defaultValue={_userinfo.role} onChange={ this.changeRole} style={{ width: 150 }} >
@ -227,12 +248,12 @@ class Profile extends Component {
</Col>
</Row>
<Row className="user-item" type="flex" justify="start">
{userType?<Row className="user-item" type="flex" justify="start">
<Col span={4}>密码</Col>
<Col span={12}>
{secureEditHtml}
</Col>
</Row>
</Row>:""}
</div>
}
}
@ -243,15 +264,16 @@ class Avatar extends Component {
constructor(props) {
super(props);
this.state = {
imageUrl:""
imageUrl: ""
}
}
static propTypes = {
uid: PropTypes.number
}
uploadAvatar(basecode){
axios.post("/user/upload_avatar",{basecode: basecode}).then(()=>{
this.setState({ imageUrl: basecode })
axios.post("/api/user/upload_avatar",{basecode: basecode}).then(()=>{
this.setState({ imageUrl: basecode });
}).catch((e)=>{
console.log(e);
})
@ -264,18 +286,13 @@ class Avatar extends Component {
}
render() {
let imageUrl = "";
if(this.props.uid && !this.state.imageUrl){
imageUrl = `/user/avatar?uid=${this.props.uid}`;
}else{
imageUrl = this.state.imageUrl;
}
let imageUrl = this.state.imageUrl?this.state.imageUrl:`/api/user/avatar?uid=${this.props.uid}`;
return <div className="avatar-box">
<Upload
className="avatar-uploader"
name="basecode"
showUploadList={true}
action="/user/upload_avatar"
action="/api/user/upload_avatar"
beforeUpload={beforeUpload}
onChange={this.handleChange.bind(this)} >
{
@ -284,6 +301,7 @@ class Avatar extends Component {
<Icon type="plus" className="avatar-uploader-trigger" />
}
</Upload>
<span className="avatarChange">点击头像更换</span>
</div>
}
}
@ -294,7 +312,7 @@ function beforeUpload(file) {
if (!isJPG && !isPNG) {
message.error('图片的格式只能为 jpg、png');
}
const isLt2M = file.size / 1024 / 1024 < 2;
const isLt2M = file.size / 1024 / 1024 < 0.2;
if (!isLt2M) {
message.error('图片必须小于 200kb!');
}

View File

@ -8,10 +8,22 @@ import PropTypes from 'prop-types'
import Profile from './Profile.js'
import { Row } from 'antd';
import Subnav from '../../components/Subnav/Subnav.js';
@connect()
@connect(state=>{
console.log(state);
return {
curUid: state.user.uid,
userType: state.user.type,
role: state.user.role
}
},{
})
class User extends Component {
static propTypes = {
match: PropTypes.object
match: PropTypes.object,
curUid: PropTypes.number,
userType: PropTypes.string,
role: PropTypes.string
}
constructor(props) {
@ -23,19 +35,22 @@ class User extends Component {
}
render () {
let navData = [{
name: '个人资料',
path: `/user/profile/${this.props.curUid}`
}];
if(this.props.role === "admin"){
navData.push({
name: '成员管理',
path: '/user/list'
})
}
return (
<div>
<Subnav
default={'我的关注'}
data={[{
name: '项目广场',
path: '/group'
}, {
name: '我的关注',
path: '/follow'
}]}/>
default={'个人资料'}
data={navData}/>
<div className="g-doc">
<Row gutter={16} className="user-box">
<Route path={this.props.match.path + '/list'} component={List} />

View File

@ -109,22 +109,23 @@
border-bottom-left-radius: .04rem;
border-bottom-right-radius: .04rem;
}
.avatar-uploader{
border: none;
}
.avatar-uploader,
.avatar-uploader-trigger,
.avatar {
width: 150px;
height: 150px;
width: 100px;
height: 100px;
overflow: hidden;
border-radius: 50px;
img{
height: auto;
}
}
.avatar-uploader {
display: block;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
}
.avatar-uploader {
display: block;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
}
.avatar-uploader-trigger {
@ -133,4 +134,10 @@
font-size: 28px;
color: #999;
}
.avatarChange{
display: block;
width: 100px;
text-align: center;
padding-bottom: 8px;
}
}

View File

@ -8,7 +8,7 @@ import News from './News/News.js'
import AddInterface from './AddInterface/AddInterface.js'
import DevTools from './DevTools/DevTools.js'
import Follows from './Follows/Follows.js'
import AddProject from './Project/AddProject/AddProject.js'
import AddProject from './AddProject/AddProject.js'
export {
Header,

View File

@ -65,3 +65,7 @@ em {
margin: .24rem auto;
padding: .24rem;
}
.ant-dropdown .user-menu {
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
}

View File

@ -138,12 +138,20 @@
<a href="#-user-update">/user/update</a>
</li>
<li >
<a href="#-user-upload_avatar">/user/upload_avatar</a>
</li>
<li >
<a href="#-user-avatar">/user/avatar</a>
</li>
<li >
<a href="#-user-search">/user/search</a>
</li>
<li >
<a href="#-user-nav">/user/nav</a>
<a href="#-user-project">/user/project</a>
</li>
</ul>
@ -1242,6 +1250,130 @@
</div>
<div class="con-list-item">
<blockquote class="api">
<h3 id="-user-upload_avatar" class="page-header subject">
/user/upload_avatar
<span class="ui-badge">POST</span>
<a class="hashlink" href="#-user-upload_avatar">#</a>
</h3>
</blockquote>
<p>
<small class="text-muted">描述:</small>
上传用户头像
</p>
<p>
<small class="text-muted">源码位置:</small>
<a href="./static/server/controllers/user.js.html#452" target="_blank">./server/controllers/user.js:452</a>
</p>
<p>
<small class="text-muted">参数:</small>
</p>
<div class="docs-table">
<table class="yo-table yo-table-border">
<colgroup>
<col class="c1">
<col class="c2">
<col class="c3">
<col class="c4">
</colgroup>
<thead>
<tr class="active">
<th>参数名</th>
<th>类型</th>
<th>描述</th>
<th>必选</th>
<th>支持版本</th>
</tr>
</thead>
<tr>
<td>basecode</td>
<td>*</td>
<td>base64编码通过h5 api传给后端</td>
<td>
<i class="yo-ico glyphicon glyphicon-ok text-success"></i>
</td>
<td></td>
</tr>
</table>
</div>
</div>
<div class="con-list-item">
<blockquote class="api">
<h3 id="-user-avatar" class="page-header subject">
/user/avatar
<span class="ui-badge">GET</span>
<a class="hashlink" href="#-user-avatar">#</a>
</h3>
</blockquote>
<p>
<small class="text-muted">描述:</small>
根据用户uid头像
</p>
<p>
<small class="text-muted">源码位置:</small>
<a href="./static/server/controllers/user.js.html#495" target="_blank">./server/controllers/user.js:495</a>
</p>
<p>
<small class="text-muted">参数:</small>
</p>
<div class="docs-table">
<table class="yo-table yo-table-border">
<colgroup>
<col class="c1">
<col class="c2">
<col class="c3">
<col class="c4">
</colgroup>
<thead>
<tr class="active">
<th>参数名</th>
<th>类型</th>
<th>描述</th>
<th>必选</th>
<th>支持版本</th>
</tr>
</thead>
<tr>
<td>uid</td>
<td>*</td>
<td></td>
<td>
<i class="yo-ico glyphicon glyphicon-ok text-success"></i>
</td>
<td></td>
</tr>
</table>
</div>
</div>
<div class="con-list-item">
@ -1262,7 +1394,7 @@
<p>
<small class="text-muted">源码位置:</small>
<a href="./static/server/controllers/user.js.html#511" target="_blank">./server/controllers/user.js:511</a>
<a href="./static/server/controllers/user.js.html#527" target="_blank">./server/controllers/user.js:527</a>
</p>
@ -1324,23 +1456,23 @@
<div class="con-list-item">
<blockquote class="api">
<h3 id="-user-nav" class="page-header subject">
/user/nav
<h3 id="-user-project" class="page-header subject">
/user/project
<span class="ui-badge">GET</span>
<a class="hashlink" href="#-user-nav">#</a>
<a class="hashlink" href="#-user-project">#</a>
</h3>
</blockquote>
<p>
<small class="text-muted">描述:</small>
根据路由id获取面包屑数据
根据路由id初始化项目数据
</p>
<p>
<small class="text-muted">源码位置:</small>
<a href="./static/server/controllers/user.js.html#556" target="_blank">./server/controllers/user.js:556</a>
<a href="./static/server/controllers/user.js.html#572" target="_blank">./server/controllers/user.js:572</a>
</p>
@ -1393,20 +1525,6 @@
</div>
<div>示例:</div>
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token string">"interface_id"</span><span class="token punctuation">:</span> <span class="token number">2746</span><span class="token punctuation">,</span>
<span class="token string">"interface_name"</span><span class="token punctuation">:</span> <span class="token string">"/a/c"</span><span class="token punctuation">,</span>
<span class="token string">"project_id"</span><span class="token punctuation">:</span> <span class="token number">2481</span><span class="token punctuation">,</span>
<span class="token string">"project_name"</span><span class="token punctuation">:</span> <span class="token string">"www.xxx.com/api"</span><span class="token punctuation">,</span>
<span class="token string">"group_id"</span><span class="token punctuation">:</span> <span class="token number">181</span><span class="token punctuation">,</span>
<span class="token string">"group_name"</span><span class="token punctuation">:</span> <span class="token string">"YMFE"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
</div>

View File

@ -47,13 +47,13 @@ class baseController {
async init(ctx) {
this.$user = null;
let ignoreRouter = [
'/user/login_by_token',
'/user/login',
'/user/reg',
'/user/status',
'/user/logout'
'/api/user/login_by_token',
'/api/user/login',
'/api/user/reg',
'/api/user/status',
'/api/user/logout'
];
if (ignoreRouter.indexOf(ctx.path) > -1) {
if (ignoreRouter.indexOf(ctx.path) > -1) {
this.$auth = true;
} else {
await this.checkLogin(ctx);
@ -88,10 +88,14 @@ class baseController {
}
}
/**
*
* @param {*} ctx
*/
async getLoginStatus(ctx) {
if (await this.checkLogin(ctx) === true) {
let result = yapi.commons.fieldSelect(this.$user, ['_id', 'username', 'email', 'up_time', 'add_time', 'role']);
let result = yapi.commons.fieldSelect(this.$user, ['_id', 'username', 'email', 'up_time', 'add_time', 'role', 'type']);
result.server_ip = yapi.WEBCONFIG.server_ip;
return ctx.body = yapi.commons.resReturn(result);
}

View File

@ -603,7 +603,7 @@ class projectController extends baseController {
}, 500);
});
}
module.exports = run;`;
module.exports = run;`
.trim();
return ctx.body = res;
}

View File

@ -81,8 +81,8 @@ class userController extends baseController {
email: result.email,
add_time: result.add_time,
up_time: result.up_time,
server_ip: yapi.WEBCONFIG.server_ip
server_ip: yapi.WEBCONFIG.server_ip,
type: 'site'
}, 0, 'logout success...');
} else {
return ctx.body = yapi.commons.resReturn(null, 405, '密码错误');
@ -478,8 +478,13 @@ class userController extends baseController {
}
/**
*
* 上传用户头像
* @interface /user/upload_avatar
* @method POST
* @param {*} basecode base64编码通过h5 api传给后端
* @category user
* @returns {Object}
* @example
*/
async uploadAvatar(ctx) {
@ -515,11 +520,22 @@ class userController extends baseController {
}
/**
* 根据用户uid头像
* @interface /user/avatar
* @method GET
* @param {*} uid
* @category user
* @returns {Object}
* @example
*/
async avatar(ctx) {
try{
let uid = ctx.query.uid ? ctx.query.uid: this.getUid();
let avatarInst = yapi.getInst(avatarModel);
let data = await avatarInst.get(this.getUid());
let data = await avatarInst.get(uid);
let dataBuffer, type;
if(!data || !data.basecode){
dataBuffer = yapi.fs.readFileSync(yapi.path.join(yapi.WEBROOT, 'static/image/avatar.png'));
@ -582,26 +598,24 @@ class userController extends baseController {
}
/**
* 根据路由id获取面包屑数据
* @interface /user/nav
* 根据路由id初始化项目数据
* @interface /user/project
* @method GET
* @category user
* @foldnumber 10
* @param {String} type 可选group|interface|project
* @param {Number} id
* @return {Object}
* @example ./api/user/nav.json
* @example
*/
async nav(ctx) {
async project(ctx) {
let { id, type } = ctx.request.query;
let result = {};
try {
if (type === 'interface') {
let interfaceInst = yapi.getInst(interfaceModel);
let interfaceData = await interfaceInst.get(id)
result["interface_id"] = interfaceData._id;
result["interface_name"] = interfaceData.path;
result.interface = interfaceData;
type = 'project';
id = interfaceData.project_id;
}
@ -609,17 +623,38 @@ class userController extends baseController {
if (type === 'project') {
let projectInst = yapi.getInst(projectModel);
let projectData = await projectInst.get(id);
result["project_id"] = projectData._id;
result["project_name"] = projectData.prd_host + projectData.basepath;
result.project = projectData.toObject();
let ownerAuth = await this.checkAuth(id, 'project', 'danger'), devAuth;
if(ownerAuth){
result.project.role = 'owner'
}else{
devAuth = await this.checkAuth(id, 'project', 'site');
if(devAuth){
result.project.role = 'dev'
}else{
result.project.role = 'member'
}
}
type = 'group';
id = projectData.group_id
id = projectData.group_id;
}
if (type === 'group') {
let groupInst = yapi.getInst(groupModel);
let groupData = await groupInst.get(id);
result["group_id"] = groupData._id;
result["group_name"] = groupData.group_name;
result.group = groupData.toObject();
let ownerAuth = await this.checkAuth(id, 'group', 'danger'), devAuth;
if(ownerAuth){
result.group.role = 'owner'
}else{
devAuth = await this.checkAuth(id, 'group', 'site');
if(devAuth){
result.group.role = 'dev'
}else{
result.group.role = 'member'
}
}
}
return ctx.body = yapi.commons.resReturn(result)

View File

@ -73,7 +73,7 @@
"description": "高效、易用、功能强大、的api管理平台旨在为开发、产品、测试人员提供更优雅的接口管理服务。"
},
"content": "./README/README-mock.md" // (markdown)
},{
"name": "api",
"title": "",
@ -85,8 +85,8 @@
"options": {
"type": "interface", // component lib component
"source": true, // false
"categories":["group","user","project", "interface"]
"categories":["group","user","project", "interface","follow"]
}
}]
}