mirror of
https://github.com/YMFE/yapi.git
synced 2025-01-30 13:20:24 +08:00
feat: 增加个人空间分组
This commit is contained in:
parent
2e3410ec5f
commit
eb8bead6a6
@ -14,7 +14,8 @@ import './Group.scss';
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
curGroupId: state.group.currGroup._id
|
||||
curGroupId: state.group.currGroup._id,
|
||||
currGroup: state.group.currGroup
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -27,7 +28,8 @@ export default class Group extends Component {
|
||||
}
|
||||
static propTypes = {
|
||||
fetchNewsData: PropTypes.func,
|
||||
curGroupId: PropTypes.number
|
||||
curGroupId: PropTypes.number,
|
||||
currGroup: PropTypes.object
|
||||
}
|
||||
onTabClick(key){
|
||||
if(key == 3){
|
||||
@ -35,7 +37,7 @@ export default class Group extends Component {
|
||||
}
|
||||
}
|
||||
render () {
|
||||
|
||||
console.log(this.props.currGroup)
|
||||
const GroupContent = (
|
||||
<Layout style={{minHeight: 'calc(100vh - 100px)', marginLeft: '24px', marginTop: '24px'}}>
|
||||
<Sider style={{ height: '100%' }} width={300}>
|
||||
@ -46,7 +48,9 @@ export default class Group extends Component {
|
||||
<Content style={{ height: '100%', margin: '0 24px 0 16px', overflow: 'initial',backgroundColor: '#fff'}}>
|
||||
<Tabs onTabClick={this.onTabClick.bind(this)} type="card" className="m-tab" style={{height: '100%'}}>
|
||||
<TabPane tab="项目列表" key="1"><ProjectList/></TabPane>
|
||||
<TabPane tab="成员列表" key="2"><MemberList/></TabPane>
|
||||
{
|
||||
this.props.currGroup.type === 'public'?<TabPane tab="成员列表" key="2"><MemberList/></TabPane>:null
|
||||
}
|
||||
<TabPane tab="分组动态" key="3"><GroupLog/></TabPane>
|
||||
</Tabs>
|
||||
</Content>
|
||||
|
@ -240,38 +240,42 @@ export default class GroupList extends Component {
|
||||
const delmark = <Menu.Item>
|
||||
<span onClick={() => this.showModal(TYPE_EDIT)}>编辑分组</span>
|
||||
</Menu.Item>
|
||||
// <Icon className="edit-group" type="edit" title="编辑分组" onClick={() => this.showModal(TYPE_EDIT)} />
|
||||
const editmark = <Menu.Item>
|
||||
<span onClick={() => { this.showConfirm() }}>删除分组</span>
|
||||
</Menu.Item>
|
||||
// <Icon className="delete-group" onClick={() => { this.showConfirm() }} type="delete" title="删除分组" />
|
||||
</Menu.Item>
|
||||
const addmark = <Menu.Item>
|
||||
<span onClick={this.showModal}>添加分组</span>
|
||||
</Menu.Item>
|
||||
// <Icon className="edit-group" onClick={this.showModal} type="plus" title="添加分组" />
|
||||
|
||||
let menu = <Menu>
|
||||
{
|
||||
this.props.curUserRole === "admin" ? (editmark) : ''
|
||||
this.props.curUserRole === "admin" ? (editmark) : ''
|
||||
}
|
||||
{
|
||||
this.props.curUserRole === "admin" || currGroup.role ==='owner' ? (delmark) : ''
|
||||
this.props.curUserRole === "admin" || currGroup.role === 'owner' ? (delmark) : ''
|
||||
}
|
||||
{
|
||||
this.props.curUserRole === 'admin' ? (addmark) : ''
|
||||
}
|
||||
</Menu>;
|
||||
menu = currGroup.role ==='owner'?<a className="editSet"><Icon type="setting" onClick={() => this.showModal(TYPE_EDIT)} /></a>:<Dropdown overlay={menu}>
|
||||
menu = currGroup.role === 'owner' ? <a className="editSet"><Icon type="setting" onClick={() => this.showModal(TYPE_EDIT)} /></a> : <Dropdown overlay={menu}>
|
||||
<a className="ant-dropdown-link" href="#">
|
||||
<Icon type="setting" />
|
||||
</a>
|
||||
</Dropdown>;
|
||||
|
||||
if( this.props.currGroup.type==='private'){
|
||||
menu = null;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="m-group">
|
||||
<div className="group-bar">
|
||||
<div className="curr-group">
|
||||
<div className="curr-group-name">
|
||||
<span className="name">{currGroup.group_name}</span>
|
||||
{ this.props.curUserRole === "admin" || currGroup.role ==='owner' ? (menu) : '' }
|
||||
{this.props.curUserRole === "admin" || currGroup.role === 'owner' ? (menu) : ''}
|
||||
</div>
|
||||
<div className="curr-group-desc">简介: {currGroup.group_desc}</div>
|
||||
</div>
|
||||
@ -290,14 +294,17 @@ export default class GroupList extends Component {
|
||||
{
|
||||
this.state.groupList.map((group) => (
|
||||
<Menu.Item key={`${group._id}`} className="group-item">
|
||||
<Icon type="folder-open" />{group.group_name}
|
||||
{group.type === 'private' ?
|
||||
<Icon type="user" /> :
|
||||
<Icon type="folder-open" />
|
||||
}{group.group_name}
|
||||
</Menu.Item>
|
||||
))
|
||||
}
|
||||
</Menu>
|
||||
</div>
|
||||
{
|
||||
this.state.addGroupModalVisible?<Modal
|
||||
this.state.addGroupModalVisible ? <Modal
|
||||
title="添加分组"
|
||||
visible={this.state.addGroupModalVisible}
|
||||
onOk={this.addGroup}
|
||||
@ -322,7 +329,7 @@ export default class GroupList extends Component {
|
||||
<UsernameAutoComplete callbackState={this.onUserSelect} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>:''
|
||||
</Modal> : ''
|
||||
}
|
||||
|
||||
<Modal
|
||||
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
||||
import { Route, Switch, Redirect, matchPath } from 'react-router-dom';
|
||||
import { Subnav } from '../../components/index';
|
||||
import { fetchGroupMsg } from '../../reducer/modules/group';
|
||||
import { setBreadcrumb } from '../../reducer/modules/user';
|
||||
import { setBreadcrumb } from '../../reducer/modules/user';
|
||||
import { getProject } from '../../reducer/modules/project';
|
||||
import Interface from './Interface/Interface.js'
|
||||
import Activity from './Activity/Activity.js'
|
||||
@ -38,14 +38,20 @@ export default class Project extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
currGroup: {}
|
||||
}
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
await this.props.getProject(this.props.match.params.id);
|
||||
const groupMsg = await this.props.fetchGroupMsg(this.props.curProject.group_id);
|
||||
this.setState({
|
||||
currGroup: groupMsg.payload.data.data
|
||||
})
|
||||
this.props.setBreadcrumb([{
|
||||
name: groupMsg.payload.data.data.group_name,
|
||||
href: '/group/'+groupMsg.payload.data.data._id
|
||||
href: '/group/' + groupMsg.payload.data.data._id
|
||||
}, {
|
||||
name: this.props.curProject.name
|
||||
}]);
|
||||
@ -53,7 +59,7 @@ export default class Project extends Component {
|
||||
|
||||
render() {
|
||||
const { match, location } = this.props;
|
||||
const routers = {
|
||||
let routers = {
|
||||
activity: { name: '动态', path: "/project/:id/activity" },
|
||||
interface: { name: '接口', path: "/project/:id/interface/:action" },
|
||||
setting: { name: '设置', path: "/project/:id/setting" },
|
||||
@ -71,32 +77,43 @@ export default class Project extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
let subnavData = [{
|
||||
name: routers.interface.name,
|
||||
path: `/project/${match.params.id}/interface/api`
|
||||
}, {
|
||||
name: routers.activity.name,
|
||||
path: `/project/${match.params.id}/activity`
|
||||
}, {
|
||||
name: routers.data.name,
|
||||
path: `/project/${match.params.id}/data`
|
||||
}, {
|
||||
name: routers.members.name,
|
||||
path: `/project/${match.params.id}/members`
|
||||
}, {
|
||||
name: routers.setting.name,
|
||||
path: `/project/${match.params.id}/setting`
|
||||
}];
|
||||
if(this.state.currGroup.type === 'private'){
|
||||
subnavData = subnavData.filter(item=>{
|
||||
return item.name != '成员管理'
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Subnav
|
||||
default={defaultName}
|
||||
data={[{
|
||||
name: routers.interface.name,
|
||||
path: `/project/${match.params.id}/interface/api`
|
||||
}, {
|
||||
name: routers.activity.name,
|
||||
path: `/project/${match.params.id}/activity`
|
||||
}, {
|
||||
name: routers.data.name,
|
||||
path: `/project/${match.params.id}/data`
|
||||
},{
|
||||
name: routers.members.name,
|
||||
path: `/project/${match.params.id}/members`
|
||||
}, {
|
||||
name: routers.setting.name,
|
||||
path: `/project/${match.params.id}/setting`
|
||||
}]} />
|
||||
data={subnavData} />
|
||||
<Switch>
|
||||
<Redirect exact from="/project/:id" to={`/project/${match.params.id}/interface/api`} />
|
||||
<Route path={routers.activity.path} component={Activity} />
|
||||
<Route path={routers.interface.path} component={Interface} />
|
||||
<Route path={routers.setting.path} component={Setting} />
|
||||
<Route path={routers.members.path} component={ProjectMember} />
|
||||
{this.state.currGroup.type !== 'private' ?
|
||||
<Route path={routers.members.path} component={ProjectMember} />
|
||||
: null
|
||||
}
|
||||
|
||||
<Route path={routers.data.path} component={ProjectData} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
@ -83,6 +83,11 @@ class baseController {
|
||||
getUsername() {
|
||||
return this.$user.username;
|
||||
}
|
||||
|
||||
getEmail(){
|
||||
return this.$user.email;
|
||||
}
|
||||
|
||||
async getProjectRole(id, type) {
|
||||
let result = {};
|
||||
try {
|
||||
|
@ -31,6 +31,9 @@ class groupController extends baseController {
|
||||
let result = await groupInst.getGroupById(params.id);
|
||||
result = result.toObject();
|
||||
result.role = await this.getProjectRole(params.id, 'group');
|
||||
if(result.type === 'private'){
|
||||
result.group_name = '个人空间';
|
||||
}
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 400, e.message)
|
||||
@ -335,8 +338,28 @@ class groupController extends baseController {
|
||||
try {
|
||||
var groupInst = yapi.getInst(groupModel);
|
||||
let projectInst = yapi.getInst(projectModel);
|
||||
let userInst = yapi.getInst(userModel);
|
||||
let result = await groupInst.list();
|
||||
let privateGroup = await groupInst.getByPrivateUid(this.getUid())
|
||||
let newResult = [];
|
||||
|
||||
if(!privateGroup){
|
||||
privateGroup = await groupInst.save({
|
||||
uid: this.getUid(),
|
||||
group_name: 'User-' + this.getUid(),
|
||||
add_time: yapi.commons.time(),
|
||||
up_time: yapi.commons.time(),
|
||||
type: 'private',
|
||||
members: [{
|
||||
uid: this.getUid(),
|
||||
role: 'owner',
|
||||
username: this.getUsername(),
|
||||
email: this.getEmail()
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if(result && result.length > 0){
|
||||
for(let i=0; i< result.length; i++){
|
||||
result[i] = result[i].toObject();
|
||||
@ -352,7 +375,13 @@ class groupController extends baseController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(privateGroup){
|
||||
privateGroup = privateGroup.toObject();
|
||||
privateGroup.group_name = '个人空间';
|
||||
privateGroup.role = 'owner';
|
||||
newResult.push(privateGroup);
|
||||
}
|
||||
|
||||
ctx.body = yapi.commons.resReturn(newResult);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
|
@ -151,6 +151,7 @@ class userController extends baseController {
|
||||
}
|
||||
|
||||
this.setLoginCookie(user._id, user.passsalt);
|
||||
await handlePrivateGroup(user._id);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('third_login:', e.message); // eslint-disable-line
|
||||
@ -210,6 +211,24 @@ class userController extends baseController {
|
||||
}
|
||||
}
|
||||
|
||||
async handlePrivateGroup(uid){
|
||||
var groupInst = yapi.getInst(groupModel);
|
||||
await groupInst.save({
|
||||
uid: uid,
|
||||
group_name: 'User-' + uid,
|
||||
add_time: yapi.commons.time(),
|
||||
up_time: yapi.commons.time(),
|
||||
type: 'public',
|
||||
members: [{
|
||||
uid: uid,
|
||||
role: 'owner',
|
||||
username: this.getUsername(),
|
||||
email: this.getEmail()
|
||||
}]
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
setLoginCookie(uid, passsalt) {
|
||||
let token = jwt.sign({ uid: uid }, passsalt, { expiresIn: '7 days' });
|
||||
|
||||
@ -279,6 +298,7 @@ class userController extends baseController {
|
||||
let user = await userInst.save(data);
|
||||
|
||||
this.setLoginCookie(user._id, user.passsalt);
|
||||
await handlePrivateGroup(user._id);
|
||||
ctx.body = yapi.commons.resReturn({
|
||||
uid: user._id,
|
||||
email: user.email,
|
||||
|
@ -13,6 +13,7 @@ class groupModel extends baseModel {
|
||||
group_desc: String,
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
type: {type:String,default: 'private', enum: ['public', 'private']},
|
||||
members: [
|
||||
{
|
||||
uid: Number,
|
||||
@ -35,10 +36,17 @@ class groupModel extends baseModel {
|
||||
}).exec();
|
||||
}
|
||||
|
||||
getByPrivateUid(uid){
|
||||
return this.model.findOne({
|
||||
uid: uid,
|
||||
type: 'private'
|
||||
}).select('group_name _id group_desc add_time up_time type').exec();
|
||||
}
|
||||
|
||||
getGroupById(id) {
|
||||
return this.model.findOne({
|
||||
_id: id
|
||||
}).select("uid group_name group_desc add_time up_time").exec();
|
||||
}).select("uid group_name group_desc add_time up_time type").exec();
|
||||
}
|
||||
|
||||
checkRepeat(name) {
|
||||
@ -86,7 +94,9 @@ class groupModel extends baseModel {
|
||||
}
|
||||
|
||||
list() {
|
||||
return this.model.find().select('group_name _id group_desc add_time up_time').exec();
|
||||
return this.model.find({
|
||||
type: 'public'
|
||||
}).select('group_name _id group_desc add_time up_time type').exec();
|
||||
}
|
||||
|
||||
del(id) {
|
||||
|
Loading…
Reference in New Issue
Block a user