feat: 项目复制

This commit is contained in:
gaoxiaolin.gao 2018-04-20 11:49:30 +08:00
parent c8e13ce7e3
commit 21bb99b240
9 changed files with 725 additions and 351 deletions

View File

@ -1,22 +1,31 @@
import './ProjectCard.scss';
import React, { PureComponent as Component } from 'react';
import { Card, Icon, Tooltip } from 'antd';
import { connect } from 'react-redux'
import { delFollow, addFollow } from '../../reducer/modules/follow';
import { Card, Icon, Tooltip, Modal, Alert, Input, message } from 'antd';
import { connect } from 'react-redux';
import { delFollow, addFollow } from '../../reducer/modules/follow';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router';
import { debounce } from '../../common';
import constants from '../../constants/variable.js';
import produce from 'immer';
import { getProject, checkProjectName, copyProjectMsg } from '../../reducer/modules/project';
import { trim } from '../../common.js';
const confirm = Modal.confirm;
@connect(
state => {
return {
uid: state.user.uid
}
uid: state.user.uid,
currPage: state.project.currPage
};
},
{
delFollow,
addFollow
addFollow,
getProject,
checkProjectName,
copyProjectMsg
}
)
@withRouter
@ -25,6 +34,7 @@ class ProjectCard extends Component {
super(props);
this.add = debounce(this.add, 400);
this.del = debounce(this.del, 400);
}
static propTypes = {
@ -34,18 +44,79 @@ class ProjectCard extends Component {
callbackResult: PropTypes.func,
history: PropTypes.object,
delFollow: PropTypes.func,
addFollow: PropTypes.func
}
addFollow: PropTypes.func,
isShow: PropTypes.bool,
getProject: PropTypes.func,
checkProjectName: PropTypes.func,
copyProjectMsg: PropTypes.func,
currPage: PropTypes.number
};
copy = async (projectName) => {
const id = this.props.projectData._id;
let projectData = await this.props.getProject(id);
let data = projectData.payload.data.data;
let newData = produce(data, draftData => {
draftData.preName = draftData.name;
draftData.name = projectName;
})
await this.props.copyProjectMsg(newData);
message.success('项目复制成功')
this.props.callbackResult();
};
// 复制项目的二次确认
showConfirm = () => {
const that = this;
confirm({
title: '确认复制 ' + that.props.projectData.name + ' 项目吗?',
okText: '确认',
cancelText: '取消',
content: (
<div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
<Alert
message={`该操作将会复制 ${
that.props.projectData.name
} 下的所有接口集合但不包括测试集合中的接口`}
type="info"
/>
<div style={{ marginTop: '16px' }}>
<p>
<b>分组名称:</b>
</p>
<Input id="project_name" placeholder="项目名称"/>
</div>
</div>
),
async onOk() {
const projectName = trim(document.getElementById('project_name').value);
// 查询项目名称是否重复
const group_id = that.props.projectData.group_id
await that.props.checkProjectName(projectName, group_id)
that.copy(projectName)
},
iconType: 'copy',
onCancel() {}
});
};
del = () => {
const id = this.props.projectData.projectid || this.props.projectData._id;
this.props.delFollow(id).then((res) => {
this.props.delFollow(id).then(res => {
if (res.payload.data.errcode === 0) {
this.props.callbackResult();
// message.success('已取消关注!'); // 星号已做出反馈 无需重复提醒用户
}
});
}
};
add = () => {
const { uid, projectData } = this.props;
@ -55,32 +126,60 @@ class ProjectCard extends Component {
projectname: projectData.name,
icon: projectData.icon || constants.PROJECT_ICON[0],
color: projectData.color || constants.PROJECT_COLOR.blue
}
this.props.addFollow(param).then((res) => {
};
this.props.addFollow(param).then(res => {
if (res.payload.data.errcode === 0) {
this.props.callbackResult();
// message.success('已添加关注!'); // 星号已做出反馈 无需重复提醒用户
}
});
}
};
render() {
const { projectData, inFollowPage } = this.props;
const { projectData, inFollowPage, isShow } = this.props;
return (
<div className="card-container">
<Card bordered={false} className="m-card" onClick={() => this.props.history.push('/project/' + (projectData.projectid || projectData._id))}>
<Icon type={projectData.icon || 'star-o'} className="ui-logo" style={{ backgroundColor: constants.PROJECT_COLOR[projectData.color] || constants.PROJECT_COLOR.blue }} />
<Card
bordered={false}
className="m-card"
onClick={() =>
this.props.history.push('/project/' + (projectData.projectid || projectData._id))
}
>
<Icon
type={projectData.icon || 'star-o'}
className="ui-logo"
style={{
backgroundColor:
constants.PROJECT_COLOR[projectData.color] || constants.PROJECT_COLOR.blue
}}
/>
<h4 className="ui-title">{projectData.name || projectData.projectname}</h4>
</Card>
<div className="card-btns" onClick={projectData.follow || inFollowPage ? this.del : this.add}>
<Tooltip placement="rightTop" title={projectData.follow || inFollowPage ? '取消关注' : '添加关注'}>
<Icon type={projectData.follow || inFollowPage ? 'star' : 'star-o'} className={'icon ' + (projectData.follow || inFollowPage ? 'active' : '')}/>
</Card>
<div
className="card-btns"
onClick={projectData.follow || inFollowPage ? this.del : this.add}
>
<Tooltip
placement="rightTop"
title={projectData.follow || inFollowPage ? '取消关注' : '添加关注'}
>
<Icon
type={projectData.follow || inFollowPage ? 'star' : 'star-o'}
className={'icon ' + (projectData.follow || inFollowPage ? 'active' : '')}
/>
</Tooltip>
</div>
{isShow && (
<div className="copy-btns" onClick={this.showConfirm}>
<Tooltip placement="rightTop" title="复制项目">
<Icon type="copy" className="icon" />
</Tooltip>
</div>
)}
</div>
)
);
}
}
export default ProjectCard
export default ProjectCard;

View File

@ -8,22 +8,26 @@
transition: all .2s;
}
&:hover {
.m-card, .card-btns {
.m-card, .card-btns , .copy-btns {
transform: translateY(-4px);
}
.m-card .ant-card-body {
background-color: $color-bg-gray;
box-shadow: 0 4px 8px rgba(50, 50, 93, 0.11), 0 4px 6px rgba(0, 0, 0, 0.08);
}
.card-btns .icon {
.card-btns .icon {
color: rgba(39, 56, 72, 0.85);
}
.card-btns .icon.active {
.copy-btns .icon {
color: #2395f1
}
.card-btns .icon.active , .copy-btns .icon.active {
color: #fac200;
}
}
&:active {
.m-card, .card-btns {
.m-card, .card-btns, .copy-btns {
transform: translateY(4px);
}
}
@ -52,6 +56,31 @@
.icon.active {
color: #fff;
}
}
// 卡片昨上角按钮
.copy-btns {
position: absolute;
top: 0;
left: 0;
width: .48rem;
height: .48rem;
// background: linear-gradient(225deg, #ccc, #ccc 50%, transparent 0);
border-top-right-radius: 4px;
.icon {
cursor: pointer;
font-size: .16rem;
padding: .06rem;
position: absolute;
right: 0;
top: 3px;
color: #fff;
}
.icon.active {
color: #fff;
}
}
}
.m-card {

View File

@ -43,6 +43,7 @@ export default class Group extends Component {
// // }
// }
render() {
const GroupContent = (
<Layout style={{ minHeight: 'calc(100vh - 100px)', marginLeft: '24px', marginTop: '24px' }}>
<Sider style={{ height: '100%' }} width={300}>

View File

@ -2,10 +2,16 @@ import React, { PureComponent as Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Table, Select, Button, Modal, Row, Col, message, Popconfirm } from 'antd';
import { Link } from 'react-router-dom'
import { Link } from 'react-router-dom';
import './MemberList.scss';
import { autobind } from 'core-decorators';
import { fetchGroupMemberList, fetchGroupMsg, addMember, delMember, changeMemberRole } from '../../../reducer/modules/group.js'
import {
fetchGroupMemberList,
fetchGroupMsg,
addMember,
delMember,
changeMemberRole
} from '../../../reducer/modules/group.js';
import ErrMsg from '../../../components/ErrMsg/ErrMsg.js';
import UsernameAutoComplete from '../../../components/UsernameAutoComplete/UsernameAutoComplete.js';
const Option = Select.Option;
@ -15,7 +21,7 @@ function arrayAddKey(arr) {
return {
...item,
key: index
}
};
});
}
@ -25,7 +31,7 @@ function arrayAddKey(arr) {
currGroup: state.group.currGroup,
uid: state.user.uid,
role: state.group.role
}
};
},
{
fetchGroupMemberList,
@ -45,7 +51,7 @@ class MemberList extends Component {
dataSource: [],
inputUids: [],
inputRole: 'dev'
}
};
}
static propTypes = {
currGroup: PropTypes.object,
@ -56,20 +62,18 @@ class MemberList extends Component {
delMember: PropTypes.func,
changeMemberRole: PropTypes.func,
role: PropTypes.string
}
};
@autobind
showAddMemberModal() {
showAddMemberModal = () => {
this.setState({
visible: true
});
}
// 重新获取列表
@autobind
reFetchList() {
this.props.fetchGroupMemberList(this.props.currGroup._id).then((res) => {
reFetchList = () => {
this.props.fetchGroupMemberList(this.props.currGroup._id).then(res => {
this.setState({
userInfo: arrayAddKey(res.payload.data.data),
visible: false
@ -78,55 +82,56 @@ class MemberList extends Component {
}
// 增 - 添加成员
@autobind
handleOk() {
this.props.addMember({
id: this.props.currGroup._id,
member_uids: this.state.inputUids,
role: this.state.inputRole
}).then((res) => {
if (!res.payload.data.errcode) {
const { add_members, exist_members } = res.payload.data.data;
const addLength = add_members.length;
const existLength = exist_members.length;
this.setState({
inputRole: 'dev',
inputUids: []
});
message.success(`添加成功! 已成功添加 ${addLength} 人,其中 ${existLength} 人已存在`);
this.reFetchList(); // 添加成功后重新获取分组成员列表
}
});
handleOk = () => {
this.props
.addMember({
id: this.props.currGroup._id,
member_uids: this.state.inputUids,
role: this.state.inputRole
})
.then(res => {
if (!res.payload.data.errcode) {
const { add_members, exist_members } = res.payload.data.data;
const addLength = add_members.length;
const existLength = exist_members.length;
this.setState({
inputRole: 'dev',
inputUids: []
});
message.success(`添加成功! 已成功添加 ${addLength} 人,其中 ${existLength} 人已存在`);
this.reFetchList(); // 添加成功后重新获取分组成员列表
}
});
}
// 添加成员时 选择新增成员权限
@autobind
changeNewMemberRole(value) {
changeNewMemberRole = (value) => {
this.setState({
inputRole: value
});
}
// 删 - 删除分组成员
@autobind
deleteConfirm(member_uid) {
deleteConfirm = (member_uid) => {
return () => {
const id = this.props.currGroup._id;
this.props.delMember({ id, member_uid }).then((res) => {
this.props.delMember({ id, member_uid }).then(res => {
if (!res.payload.data.errcode) {
message.success(res.payload.data.errmsg);
this.reFetchList(); // 添加成功后重新获取分组成员列表
}
});
}
};
}
// 改 - 修改成员权限
@autobind
changeUserRole(e) {
changeUserRole = (e) => {
const id = this.props.currGroup._id;
const role = e.split('-')[0];
const member_uid = e.split('-')[1];
this.props.changeMemberRole({ id, member_uid, role }).then((res) => {
this.props.changeMemberRole({ id, member_uid, role }).then(res => {
if (!res.payload.data.errcode) {
message.success(res.payload.data.errmsg);
this.reFetchList(); // 添加成功后重新获取分组成员列表
@ -135,40 +140,41 @@ class MemberList extends Component {
}
// 关闭模态框
@autobind
handleCancel() {
handleCancel = () => {
this.setState({
visible: false
});
}
};
componentWillReceiveProps(nextProps) {
if (this._groupId !== this._groupId) {
return null;
}
if (this.props.currGroup !== nextProps.currGroup) {
this.props.fetchGroupMemberList(nextProps.currGroup._id).then((res) => {
if (this.props.currGroup._id !== nextProps.currGroup._id) {
this.props.fetchGroupMemberList(nextProps.currGroup._id).then(res => {
this.setState({
userInfo: arrayAddKey(res.payload.data.data)
});
});
this.props.fetchGroupMsg(nextProps.currGroup._id).then((res) => {
this.props.fetchGroupMsg(nextProps.currGroup._id).then(res => {
this.setState({
role: res.payload.data.data.role
});
})
});
}
}
componentDidMount() {
const currGroupId = this._groupId = this.props.currGroup._id;
this.props.fetchGroupMsg(currGroupId).then((res) => {
const currGroupId = (this._groupId = this.props.currGroup._id);
this.props.fetchGroupMsg(currGroupId).then(res => {
this.setState({
role: res.payload.data.data.role
});
})
this.props.fetchGroupMemberList(currGroupId).then((res) => {
});
this.props.fetchGroupMemberList(currGroupId).then(res => {
this.setState({
userInfo: arrayAddKey(res.payload.data.data)
});
@ -179,101 +185,144 @@ class MemberList extends Component {
onUserSelect(uids) {
this.setState({
inputUids: uids
})
});
}
render() {
const columns = [{
title: this.props.currGroup.group_name + ' 分组成员 (' + this.state.userInfo.length + ') 人',
dataIndex: 'username',
key: 'username',
render: (text, record) => {
return (<div className="m-user">
<Link to={`/user/profile/${record.uid}`}>
<img src={location.protocol + '//' + location.host + '/api/user/avatar?uid=' + record.uid} className="m-user-img" />
</Link>
<Link to={`/user/profile/${record.uid}`}>
<p className="m-user-name">{text}</p>
</Link>
</div>);
}
}, {
title: (this.state.role === 'owner' || this.state.role === 'admin') ? <div className="btn-container"><Button className="btn" type="primary" onClick={this.showAddMemberModal}>添加成员</Button></div> : '',
key: 'action',
className: 'member-opration',
render: (text, record) => {
if (this.state.role === 'owner' || this.state.role === 'admin') {
const columns = [
{
title:
this.props.currGroup.group_name + ' 分组成员 (' + this.state.userInfo.length + ') 人',
dataIndex: 'username',
key: 'username',
render: (text, record) => {
return (
<div>
<Select value={record.role + '-' + record.uid} className="select" onChange={this.changeUserRole}>
<Option value={'owner-' + record.uid}>组长</Option>
<Option value={'dev-' + record.uid}>开发者</Option>
<Option value={'guest-' + record.uid}>访客</Option>
</Select>
<Popconfirm placement="topRight" title="你确定要删除吗? " onConfirm={this.deleteConfirm(record.uid)} okText="确定" cancelText="">
<Button type="danger" icon="delete" className="btn-danger" />
{/* <Icon type="delete" className="btn-danger"/> */}
</Popconfirm>
<div className="m-user">
<Link to={`/user/profile/${record.uid}`}>
<img
src={
location.protocol + '//' + location.host + '/api/user/avatar?uid=' + record.uid
}
className="m-user-img"
/>
</Link>
<Link to={`/user/profile/${record.uid}`}>
<p className="m-user-name">{text}</p>
</Link>
</div>
)
} else {
// 非管理员可以看到权限 但无法修改
if (record.role === 'owner') {
return '组长';
} else if (record.role === 'dev') {
return '开发者';
} else if (record.role === 'guest') {
return '访客';
);
}
},
{
title:
this.state.role === 'owner' || this.state.role === 'admin' ? (
<div className="btn-container">
<Button className="btn" type="primary" onClick={this.showAddMemberModal}>
添加成员
</Button>
</div>
) : (
''
),
key: 'action',
className: 'member-opration',
render: (text, record) => {
if (this.state.role === 'owner' || this.state.role === 'admin') {
return (
<div>
<Select
value={record.role + '-' + record.uid}
className="select"
onChange={this.changeUserRole}
>
<Option value={'owner-' + record.uid}>组长</Option>
<Option value={'dev-' + record.uid}>开发者</Option>
<Option value={'guest-' + record.uid}>访客</Option>
</Select>
<Popconfirm
placement="topRight"
title="你确定要删除吗? "
onConfirm={this.deleteConfirm(record.uid)}
okText="确定"
cancelText=""
>
<Button type="danger" icon="delete" className="btn-danger" />
{/* <Icon type="delete" className="btn-danger"/> */}
</Popconfirm>
</div>
);
} else {
return '';
// 非管理员可以看到权限 但无法修改
if (record.role === 'owner') {
return '组长';
} else if (record.role === 'dev') {
return '开发者';
} else if (record.role === 'guest') {
return '访客';
} else {
return '';
}
}
}
}
}];
];
let userinfo = this.state.userInfo;
let ownerinfo = [];
let devinfo = [];
let guestinfo = [];
for (let i = 0; i < userinfo.length; i++) {
if (userinfo[i].role === "owner") {
if (userinfo[i].role === 'owner') {
ownerinfo.push(userinfo[i]);
}
if (userinfo[i].role === "dev") {
if (userinfo[i].role === 'dev') {
devinfo.push(userinfo[i]);
}
if (userinfo[i].role === "guest") {
if (userinfo[i].role === 'guest') {
guestinfo.push(userinfo[i]);
}
}
userinfo = [...ownerinfo, ...devinfo, ...guestinfo];
return (
<div className="m-panel">
{this.state.visible ? <Modal
title="添加成员"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
okText="确认"
cancelText="取消"
>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label usernamelabel">用户名: </div></Col>
<Col span="15">
<UsernameAutoComplete callbackState={this.onUserSelect} />
</Col>
</Row>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label usernameauth">权限: </div></Col>
<Col span="15">
<Select defaultValue="dev" className="select" onChange={this.changeNewMemberRole}>
<Option value="owner">组长</Option>
<Option value="dev">开发者</Option>
<Option value="guest">访客</Option>
</Select>
</Col>
</Row>
</Modal> : ""}
<Table columns={columns} dataSource={userinfo} pagination={false} locale={{ emptyText: <ErrMsg type="noMemberInGroup" /> }} />
{this.state.visible ? (
<Modal
title="添加成员"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
okText="确认"
cancelText="取消"
>
<Row gutter={6} className="modal-input">
<Col span="5">
<div className="label usernamelabel">用户名: </div>
</Col>
<Col span="15">
<UsernameAutoComplete callbackState={this.onUserSelect} />
</Col>
</Row>
<Row gutter={6} className="modal-input">
<Col span="5">
<div className="label usernameauth">权限: </div>
</Col>
<Col span="15">
<Select defaultValue="dev" className="select" onChange={this.changeNewMemberRole}>
<Option value="owner">组长</Option>
<Option value="dev">开发者</Option>
<Option value="guest">访客</Option>
</Select>
</Col>
</Row>
</Modal>
) : (
''
)}
<Table
columns={columns}
dataSource={userinfo}
pagination={false}
locale={{ emptyText: <ErrMsg type="noMemberInGroup" /> }}
/>
</div>
);
}

View File

@ -72,8 +72,8 @@ class ProjectList extends Component {
}
// 获取 ProjectCard 组件的关注事件回调,收到后更新数据
@autobind
receiveRes() {
receiveRes = () => {
this.props.fetchProjectList(this.props.currGroup._id, this.props.currPage);
}
@ -119,6 +119,9 @@ class ProjectList extends Component {
})
projectData = [...followProject, ...noFollow]
const isShow = /(admin)|(owner)|(dev)/.test(this.props.currGroup.role)
const Follow = () => {
return followProject.length ? <Row>
<h3 className="owner-type">我的关注</h3>
@ -139,7 +142,7 @@ class ProjectList extends Component {
noFollow.map((item, index) => {
return (
<Col xs={8} lg={6} xxl={4} key={index}>
<ProjectCard projectData={item} callbackResult={this.receiveRes} />
<ProjectCard projectData={item} callbackResult={this.receiveRes} isShow={isShow} />
</Col>)
})
}
@ -155,7 +158,7 @@ class ProjectList extends Component {
: <ErrMsg type="noProject" />)
}
return (
<div style={{ paddingTop: '24px' }} className="m-panel card-panel card-panel-s project-list" >
<Row className="project-list-header">
@ -163,7 +166,7 @@ class ProjectList extends Component {
{this.props.currGroup.group_name} 分组共 ({projectData.length}) 个项目
</Col>
<Col span={8}>
{/(admin)|(owner)|(dev)/.test(this.props.currGroup.role) ?
{isShow?
<Link to="/add-project"><Button type="primary">添加项目</Button></Link> :
<Tooltip title="您没有权限,请联系该分组组长或管理员">
<Button type="primary" disabled >添加项目</Button>
@ -181,7 +184,7 @@ class ProjectList extends Component {
this.props.currGroup.type === 'private' ? <OwnerSpace /> : projectData.length ? projectData.map((item, index) => {
return (
<Col xs={8} lg={6} xxl={4} key={index}>
<ProjectCard projectData={item} callbackResult={this.receiveRes} />
<ProjectCard projectData={item} callbackResult={this.receiveRes} isShow={isShow} />
</Col>);
}) : <ErrMsg type="noProject" />
}

View File

@ -16,6 +16,9 @@ const DEL_PROJECT_MEMBER = 'yapi/project/DEL_PROJECT_MEMBER';
const CHANGE_PROJECT_MEMBER = 'yapi/project/CHANGE_PROJECT_MEMBER';
const GET_TOKEN = 'yapi/project/GET_TOKEN';
const UPDATE_TOKEN = 'yapi/project/UPDATE_TOKEN';
const CHECK_PROJECT_NAME = 'yapi/project/CHECK_PROJECT_NAME';
const COPY_PROJECT_MSG = 'yapi/project/COPY_PROJECT_MSG';
// Reducer
const initialState = {
@ -70,6 +73,18 @@ export default (state = initialState, action) => {
token: action.payload.data.data.token
}
}
case CHECK_PROJECT_NAME: {
return{
...state
}
}
case COPY_PROJECT_MSG: {
return {
...state
}
}
default:
return state;
}
@ -89,15 +104,13 @@ export function fetchProjectList(id, pageNum) {
};
}
// // 获取项目信息
// export function getProjectMsg(id) {
// return {
// type: GET_PROJECT_MSG,
// payload: axios.get('/api/project/get', {
// params: { id }
// })
// };
// }
// 复制项目
export function copyProjectMsg(params) {
return {
type: COPY_PROJECT_MSG,
payload: axios.post('/api/project/copy', params)
};
}
// 添加项目成员
export function addMember(param) {
@ -245,3 +258,12 @@ export async function updateToken(project_id){
}
}
export async function checkProjectName(name, group_id){
return {
type: CHECK_PROJECT_NAME,
payload: axios.get('/api/project/check_project_name', {
params: { name, group_id }
})
}
}

View File

@ -191,7 +191,7 @@ class baseController {
*/
async checkAuth(id, type, action) {
let role = await this.getProjectRole(id, type);
console.log(role);
if (action === 'danger') {
if (role === 'admin' || role === 'owner') {
return true;

View File

@ -1,6 +1,6 @@
const projectModel = require('../models/project.js');
const yapi = require('../yapi.js');
const _ = require("underscore");
const _ = require('underscore');
const baseController = require('./base.js');
const interfaceModel = require('../models/interface.js');
const interfaceColModel = require('../models/interfaceCol.js');
@ -12,11 +12,10 @@ const userModel = require('../models/user.js');
const logModel = require('../models/log.js');
const followModel = require('../models/follow.js');
const tokenModel = require('../models/token.js');
const sha = require('sha.js');
class projectController extends baseController {
constructor(ctx) {
super(ctx);
this.Model = yapi.getInst(projectModel);
@ -24,6 +23,7 @@ class projectController extends baseController {
this.logModel = yapi.getInst(logModel);
this.followModel = yapi.getInst(followModel);
this.tokenModel = yapi.getInst(tokenModel);
this.interfaceModel = yapi.getInst(interfaceModel);
const id = 'number';
const member_uid = ['number'];
@ -32,73 +32,89 @@ class projectController extends baseController {
minLength: 1
};
const role = {
type: "string",
enum: ["owner", "dev", "guest"]
}
type: 'string',
enum: ['owner', 'dev', 'guest']
};
const basepath = {
type: 'string',
default: ''
};
const group_id = 'number';
const group_name = 'string'
const group_name = 'string';
const project_type = {
type: 'string',
enum: ['private', 'public'],
default: 'private'
}
const desc = 'string'
const icon = 'string'
const color = 'string'
};
const desc = 'string';
const icon = 'string';
const color = 'string';
const env = 'array';
const cat ='array';
this.schemaMap = {
add: {
"*name": name,
"basepath": basepath,
"*group_id": group_id,
'*name': name,
basepath: basepath,
'*group_id': group_id,
group_name,
desc: desc,
color,
icon,
project_type
},
copy: {
'*name': name,
'preName': name,
basepath: basepath,
'*group_id': group_id,
_id: id,
cat,
env,
group_name,
desc,
color,
icon,
project_type
},
addMember: {
"*id": id,
"*member_uids": member_uid,
"role": role
'*id': id,
'*member_uids': member_uid,
role: role
},
delMember: {
"*id": id,
"*member_uid": id
'*id': id,
'*member_uid': id
},
getMemberList: {
"*id": id
'*id': id
},
get: {
"*id": id
'*id': id
},
list: {
"*group_id": group_id
'*group_id': group_id
},
del: {
"*id": id
'*id': id
},
changeMemberRole: {
"*id": id,
"*member_uid": id,
'*id': id,
'*member_uid': id,
role
},
token: {
'*project_id':id
'*project_id': id
},
updateToken: {
'*project_id':id
'*project_id': id
}
}
};
}
handleBasepath(basepath) {
if (!basepath) return "";
if (basepath === '/') return "";
if (!basepath) return '';
if (basepath === '/') return '';
if (basepath[0] !== '/') basepath = '/' + basepath;
if (basepath[basepath.length - 1] === '/') basepath = basepath.substr(0, basepath.length - 1);
if (!/^\/[a-zA-Z0-9\-\/_]+$/.test(basepath)) {
@ -115,7 +131,27 @@ class projectController extends baseController {
return false;
}
/**
* 判断分组名称是否重复
* @interface /project/check_project_name
* @method get
*/
async checkProjectName(ctx) {
let name = ctx.request.query.name;
let group_id = ctx.request.query.group_id;
console.log(ctx.request.query);
if (!name) {
return (ctx.body = yapi.commons.resReturn(null, 401, '项目名不能为空'));
}
let checkRepeat = await this.Model.checkNameRepeat(name, group_id);
if (checkRepeat > 0) {
return (ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名'));
}
ctx.body = yapi.commons.resReturn({});
}
/**
* 添加项目分组
@ -135,21 +171,20 @@ class projectController extends baseController {
async add(ctx) {
let params = ctx.params;
if (await this.checkAuth(params.group_id, 'group', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(params.group_id, 'group', 'edit')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
let checkRepeat = await this.Model.checkNameRepeat(params.name, params.group_id);
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名');
return (ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名'));
}
params.basepath = params.basepath || '';
if ((params.basepath = this.handleBasepath(params.basepath)) === false) {
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
return (ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误'));
}
let data = {
@ -179,7 +214,7 @@ class projectController extends baseController {
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
})
});
await catInst.save({
name: '公共分类',
project_id: result._id,
@ -187,18 +222,19 @@ class projectController extends baseController {
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
})
});
}
let uid = this.getUid();
// 将项目添加者变成项目组长,除admin以外
if (this.getRole() !== 'admin') {
let userdata = await this.getUserdata(uid, 'owner')
await this.Model.addMember(result._id, [userdata])
let userdata = await this.getUserdata(uid, 'owner');
await this.Model.addMember(result._id, [userdata]);
}
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 添加了项目 <a href="/project/${result._id}">${params.name}</a>`,
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 添加了项目 <a href="/project/${
result._id
}">${params.name}</a>`,
type: 'project',
uid,
username: username,
@ -207,49 +243,167 @@ class projectController extends baseController {
ctx.body = yapi.commons.resReturn(result);
}
/**
* 拷贝项目分组
* @interface /project/copy
* @method POST
* @category project
* @foldnumber 10
* @param {String} name 项目名称不能为空
* @param {String} basepath 项目基本路径不能为空
* @param {Number} group_id 项目分组id不能为空
* @param {Number} group_name 项目分组名称不能为空
* @param {String} project_type private public
* @param {String} [desc] 项目描述
* @returns {Object}
* @example ./api/project/add.json
*/
async copy(ctx) {
let params = ctx.params;
// 拷贝项目的ID
let copyId = params._id;
if ((await this.checkAuth(params.group_id, 'group', 'edit')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
params.basepath = params.basepath || '';
let data = {
name: params.name,
desc: params.desc,
basepath: params.basepath,
members: params.members || [],
project_type: params.project_type || 'private',
uid: this.getUid(),
group_id: params.group_id,
group_name: params.group_name,
icon: params.icon,
color: params.color,
add_time: yapi.commons.time(),
up_time: yapi.commons.time(),
env: params.env || [{ name: 'local', domain: 'http://127.0.0.1' }]
};
let result = await this.Model.save(data);
let colInst = yapi.getInst(interfaceColModel);
let catInst = yapi.getInst(interfaceCatModel);
// 增加集合
if (result._id) {
await colInst.save({
name: '公共测试集',
project_id: result._id,
desc: '公共测试集',
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
});
// 拷贝接口列表
let cat = params.cat;
for (let i = 0; i < cat.length; i++) {
let item = cat[i];
let catDate = {
name: item.name,
project_id: result._id,
desc: item.desc,
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
};
let catResult = await catInst.save(catDate);
// 获取每个集合中的interface
let interfaceData = await this.interfaceModel.listByInterStatus(item._id)
// 将interfaceData存到新的catID中
for(let key =0 ; key < interfaceData.length ; key++){
let interfaceItem = interfaceData[key].toObject();
let data = Object.assign(interfaceItem, {
uid: this.getUid(),
catid: catResult._id,
project_id: result._id,
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
});
delete data._id;
await this.interfaceModel.save(data)
}
}
}
// 增加member
let copyProject = await this.Model.get(copyId);
let copyProjectMembers = copyProject.members;
let uid = this.getUid();
// 将项目添加者变成项目组长,除admin以外
if (this.getRole() !== 'admin') {
let userdata = await this.getUserdata(uid, 'owner');
copyProjectMembers.push(userdata)
}
await this.Model.addMember(result._id, copyProjectMembers);
// 在每个测试结合下添加interface
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 复制了项目 ${params.preName} 为 <a href="/project/${
result._id
}">${params.name}</a>`,
type: 'project',
uid,
username: username,
typeid: result._id
});
ctx.body = yapi.commons.resReturn(result);
}
/**
* 添加项目成员
* @interface /project/add_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {Array} member_uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/add_member.json
*/
* 添加项目成员
* @interface /project/add_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {Array} member_uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/add_member.json
*/
async addMember(ctx) {
let params = ctx.params;
if (await this.checkAuth(params.id, 'project', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(params.id, 'project', 'edit')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let add_members = [];
let exist_members = [];
let no_members = []
let no_members = [];
for (let i = 0, len = params.member_uids.length; i < len; i++) {
let id = params.member_uids[i]
let id = params.member_uids[i];
let check = await this.Model.checkMemberRepeat(params.id, id);
let userdata = await this.getUserdata(id, params.role);
if (check > 0) {
exist_members.push(userdata)
exist_members.push(userdata);
} else if (!userdata) {
no_members.push(id)
no_members.push(id);
} else {
add_members.push(userdata)
add_members.push(userdata);
}
}
let result = await this.Model.addMember(params.id, add_members);
if (add_members.length) {
let members = add_members.map((item) => {
return `<a href = "/user/profile/${item.uid}">${item.username}</a>`
})
members = members.join("、");
let members = add_members.map(item => {
return `<a href = "/user/profile/${item.uid}">${item.username}</a>`;
});
members = members.join('、');
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 添加了项目成员 ${members}`,
@ -265,48 +419,50 @@ class projectController extends baseController {
exist_members,
no_members
});
}
/**
* 删除项目成员
* @interface /project/del_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {member_uid} uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/del_member.json
*/
* 删除项目成员
* @interface /project/del_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {member_uid} uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/del_member.json
*/
async delMember(ctx) {
let params = ctx.params;
var check = await this.Model.checkMemberRepeat(params.id, params.member_uid);
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员不存在');
return (ctx.body = yapi.commons.resReturn(null, 400, '项目成员不存在'));
}
if (await this.checkAuth(params.id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(params.id, 'project', 'danger')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
let result = await this.Model.delMember(params.id, params.member_uid);
let username = this.getUsername();
yapi.getInst(userModel).findById(params.member_uid).then((member) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了项目中的成员 <a href="/user/profile/${params.member_uid}">${member.username}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.id
yapi
.getInst(userModel)
.findById(params.member_uid)
.then(member => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了项目中的成员 <a href="/user/profile/${
params.member_uid
}">${member.username}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.id
});
});
});
ctx.body = yapi.commons.resReturn(result);
}
async getUserdata(uid, role) {
role = role || 'dev';
let userInst = yapi.getInst(userModel);
@ -319,7 +475,7 @@ class projectController extends baseController {
uid: userData._id,
username: userData.username,
email: userData.email
}
};
}
/**
@ -336,43 +492,42 @@ class projectController extends baseController {
async getMemberList(ctx) {
let params = ctx.params;
if (!params.id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
return (ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空'));
}
let project = await this.Model.get(params.id);
ctx.body = yapi.commons.resReturn(project.members);
}
/**
* 获取项目信息
* @interface /project/get
* @method GET
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @example ./api/project/get.json
*/
* 获取项目信息
* @interface /project/get
* @method GET
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @example ./api/project/get.json
*/
async get(ctx) {
let params = ctx.params;
let result = await this.Model.getBaseInfo(params.id);
if (!result) {
return ctx.body = yapi.commons.resReturn(null, 400, '不存在的项目');
return (ctx.body = yapi.commons.resReturn(null, 400, '不存在的项目'));
}
if (result.project_type === 'private') {
if (await this.checkAuth(result._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
if ((await this.checkAuth(result._id, 'project', 'view')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 406, '没有权限'));
}
}
result = result.toObject();
let catInst = yapi.getInst(interfaceCatModel);
let cat = await catInst.list(params.id);
result.cat = cat;
if(result.env.length === 0) {
result.env.push({ name: 'local', domain: 'http://127.0.0.1' })
if (result.env.length === 0) {
result.env.push({ name: 'local', domain: 'http://127.0.0.1' });
}
result.role = await this.getProjectRole(params.id, 'project');
@ -392,14 +547,15 @@ class projectController extends baseController {
*/
async list(ctx) {
let group_id = ctx.params.group_id, project_list = [];
let group_id = ctx.params.group_id,
project_list = [];
let groupData = await this.groupModel.get(group_id);
let isPrivateGroup = false;
if (groupData.type === 'private' && this.getUid() === groupData.uid) {
isPrivateGroup = true;
}
let auth = await this.checkAuth(group_id, 'group', 'view')
let auth = await this.checkAuth(group_id, 'group', 'view');
let result = await this.Model.list(group_id);
let follow = await this.followModel.list(this.getUid());
if (isPrivateGroup === false) {
@ -412,9 +568,9 @@ class projectController extends baseController {
}
}
let f = _.find(follow, (fol) => {
return fol.projectid === item._id
})
let f = _.find(follow, fol => {
return fol.projectid === item._id;
});
// 排序:收藏的项目放前面
if (f) {
item.follow = true;
@ -429,14 +585,13 @@ class projectController extends baseController {
item = item.toObject();
item.follow = true;
return item;
})
project_list = _.uniq(follow.concat(result), item => item._id)
});
project_list = _.uniq(follow.concat(result), item => item._id);
}
ctx.body = yapi.commons.resReturn({
list: project_list
});
}
/**
@ -453,20 +608,19 @@ class projectController extends baseController {
async del(ctx) {
let id = ctx.params.id;
if (await this.checkAuth(id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(id, 'project', 'danger')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
let interfaceInst = yapi.getInst(interfaceModel);
let interfaceColInst = yapi.getInst(interfaceColModel);
let interfaceCaseInst = yapi.getInst(interfaceCaseModel);
await interfaceInst.delByProjectId(id)
await interfaceCaseInst.delByProjectId(id)
await interfaceColInst.delByProjectId(id)
await interfaceInst.delByProjectId(id);
await interfaceCaseInst.delByProjectId(id);
await interfaceColInst.delByProjectId(id);
yapi.emitHook('project_del', id).then();
let result = await this.Model.del(id);
ctx.body = yapi.commons.resReturn(result);
}
/**
@ -487,33 +641,37 @@ class projectController extends baseController {
var check = await projectInst.checkMemberRepeat(params.id, params.member_uid);
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员不存在');
return (ctx.body = yapi.commons.resReturn(null, 400, '项目成员不存在'));
}
if (await this.checkAuth(params.id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(params.id, 'project', 'danger')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let rolename = {
'owner': '组长',
'dev': '开发者',
'guest': '访客'
owner: '组长',
dev: '开发者',
guest: '访客'
};
let result = await projectInst.changeMemberRole(params.id, params.member_uid, params.role);
let username = this.getUsername();
yapi.getInst(userModel).findById(params.member_uid).then((member) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 修改了项目中的成员 <a href="/user/profile/${params.member_uid}">${member.username}</a> 的角色为 "${rolename[params.role]}"`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.id
yapi
.getInst(userModel)
.findById(params.member_uid)
.then(member => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 修改了项目中的成员 <a href="/user/profile/${
params.member_uid
}">${member.username}</a> 的角色为 "${rolename[params.role]}"`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.id
});
});
})
ctx.body = yapi.commons.resReturn(result);
}
/**
@ -531,13 +689,13 @@ class projectController extends baseController {
async upSet(ctx) {
let id = ctx.request.body.id;
let data = {};
if (await this.checkAuth(id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(id, 'project', 'danger')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
data.color = ctx.request.body.color;
data.icon = ctx.request.body.icon;
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空');
return (ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空'));
}
try {
let result = await this.Model.up(id, data);
@ -588,20 +746,19 @@ class projectController extends baseController {
after_script: 'string'
});
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空');
return (ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空'));
}
if (await this.checkAuth(id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(id, 'project', 'danger')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
let projectData = await this.Model.get(id);
if (params.basepath) {
if ((params.basepath = this.handleBasepath(params.basepath)) === false) {
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
return (ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误'));
}
}
@ -612,16 +769,15 @@ class projectController extends baseController {
if (params.name) {
let checkRepeat = await this.Model.checkNameRepeat(params.name, params.group_id);
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名');
return (ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名'));
}
}
let data = {
up_time: yapi.commons.time()
};
if (params.project_type) {
data.project_type = params.project_type
data.project_type = params.project_type;
}
if (!_.isUndefined(params.name)) data.name = params.name;
@ -633,11 +789,13 @@ class projectController extends baseController {
if (!_.isUndefined(params.icon)) data.icon = params.icon;
if (!_.isUndefined(params.pre_script)) data.pre_script = params.pre_script;
if (!_.isUndefined(params.after_script)) data.after_script = params.after_script;
let result = await this.Model.up(id, data);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了项目 <a href="/project/${id}/interface/api}">${projectData.name}</a>`,
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了项目 <a href="/project/${id}/interface/api}">${
projectData.name
}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
@ -649,7 +807,6 @@ class projectController extends baseController {
}
}
/**
* 编辑项目
* @interface /project/up_env
@ -662,22 +819,22 @@ class projectController extends baseController {
* @param {String} [env[].domain] 环境域名
* @param {Array} [env[].header] header
* @returns {Object}
* @example
* @example
*/
async upEnv(ctx) {
try {
let id = ctx.request.body.id;
let params = ctx.request.body;
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空');
return (ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空'));
}
if (await this.checkAuth(id, 'project', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
if ((await this.checkAuth(id, 'project', 'edit')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
if (!params.env || !Array.isArray(params.env)) {
return ctx.body = yapi.commons.resReturn(null, 405, 'env参数格式有误');
return (ctx.body = yapi.commons.resReturn(null, 405, 'env参数格式有误'));
}
let projectData = await this.Model.get(id);
@ -688,12 +845,14 @@ class projectController extends baseController {
data.env = params.env;
let isRepeat = this.arrRepeat(data.env, 'name');
if (isRepeat) {
return ctx.body = yapi.commons.resReturn(null, 405, '环境变量名重复');
return (ctx.body = yapi.commons.resReturn(null, 405, '环境变量名重复'));
}
let result = await this.Model.up(id, data);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了项目 <a href="/project/${id}/interface/api">${projectData.name}</a> 的环境`,
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了项目 <a href="/project/${id}/interface/api">${
projectData.name
}</a> `,
type: 'project',
uid: this.getUid(),
username: username,
@ -707,8 +866,8 @@ class projectController extends baseController {
arrRepeat(arr, key) {
const s = new Set();
arr.forEach(item => s.add(item[key]))
return s.size !== arr.length
arr.forEach(item => s.add(item[key]));
return s.size !== arr.length;
}
/**
@ -720,16 +879,19 @@ class projectController extends baseController {
* @param {Number} id 项目id不能为空
* @param {String} q
* @return {Object}
*/
*/
async token(ctx) {
try {
let project_id = ctx.params.project_id ;
try {
let project_id = ctx.params.project_id;
let data = await this.tokenModel.get(project_id);
let token;
if (!data ) {
if (!data) {
let passsalt = yapi.commons.randStr();
token = sha('sha1').update(passsalt).digest('hex').substr(0, 20);
await this.tokenModel.save({project_id, token})
token = sha('sha1')
.update(passsalt)
.digest('hex')
.substr(0, 20);
await this.tokenModel.save({ project_id, token });
} else {
token = data.token;
}
@ -749,28 +911,29 @@ class projectController extends baseController {
* @param {Number} id 项目id不能为空
* @param {String} q
* @return {Object}
*/
*/
async updateToken(ctx) {
try {
let project_id = ctx.params.project_id ;
let data = await this.tokenModel.get(project_id);
let token, result;
if (data && data.token ) {
let passsalt = yapi.commons.randStr();
token = sha('sha1').update(passsalt).digest('hex').substr(0, 20);
result = await this.tokenModel.up(project_id, token)
result.token = token
} else {
ctx.body = yapi.commons.resReturn(null, 402, '没有查到token信息');
}
ctx.body = yapi.commons.resReturn(result);
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
let project_id = ctx.params.project_id;
let data = await this.tokenModel.get(project_id);
let token, result;
if (data && data.token) {
let passsalt = yapi.commons.randStr();
token = sha('sha1')
.update(passsalt)
.digest('hex')
.substr(0, 20);
result = await this.tokenModel.up(project_id, token);
result.token = token;
} else {
ctx.body = yapi.commons.resReturn(null, 402, '没有查到token信息');
}
ctx.body = yapi.commons.resReturn(result);
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
/**
* 模糊搜索项目名称或者组名称
@ -781,16 +944,16 @@ class projectController extends baseController {
* @param {String} q
* @return {Object}
* @example ./api/project/search.json
*/
*/
async search(ctx) {
const { q } = ctx.request.query;
if (!q) {
return ctx.body = yapi.commons.resReturn(void 0, 400, 'No keyword.');
return (ctx.body = yapi.commons.resReturn(void 0, 400, 'No keyword.'));
}
if (!yapi.commons.validateSearchKeyword(q)) {
return ctx.body = yapi.commons.resReturn(void 0, 400, 'Bad query.');
return (ctx.body = yapi.commons.resReturn(void 0, 400, 'Bad query.'));
}
let projectList = await this.Model.search(q);
@ -823,7 +986,7 @@ class projectController extends baseController {
group: groupList
};
return ctx.body = yapi.commons.resReturn(queryList, 0, 'ok');
return (ctx.body = yapi.commons.resReturn(queryList, 0, 'ok'));
}
}

View File

@ -249,6 +249,14 @@ let routerConfig = {
"action": "updateToken",
"path": "update_token",
"method": "get"
},{
action: 'checkProjectName',
path: 'check_project_name',
method: 'get'
},{
action: 'copy',
path: 'copy',
method:'post'
}