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

This commit is contained in:
wenbo.dong 2017-09-27 21:29:25 +08:00
commit 35b8718b1e
18 changed files with 27698 additions and 98 deletions

View File

@ -21,7 +21,7 @@ module.exports = {
"rules": {
"indent": [
"error",
2,
4,
{
"SwitchCase": 1
}

View File

@ -1,8 +1,10 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { AutoComplete } from 'antd';
import { Select } from 'antd';
import axios from 'axios';
const Option = Select.Option;
/**
* 用户名输入框自动完成组件
*
@ -12,7 +14,7 @@ import axios from 'axios';
* * 用户名输入框自动完成组件
* * 用户名输入框自动完成组件
*
*
*s
*/
/**
@ -37,12 +39,14 @@ import axios from 'axios';
class UsernameAutoComplete extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
uid: 0,
username: '',
changeName: ''
}
}
state = {
dataSource: []
// value: []
// uid: 0,
// username: ''
// changeName: ''
}
static propTypes = {
@ -50,27 +54,38 @@ class UsernameAutoComplete extends Component {
}
// 改变本组件 state并回调给父组件
changeState = (uid, username) => {
// 设置本组件 state
this.setState({ uid, username });
// 回调 将当前选中的uid和username回调给父组件
this.props.callbackState({ uid, username });
}
// changeState = (value) => {
// // 设置本组件 state
// // this.setState({ value });
// // 回调 将当前选中的uid和username回调给父组件
// this.props.callbackState({ value });
// }
// 输入框中的值改变时
onChange = (userName) => {
this.setState({
changeName: userName
});
}
// onChange = (userName) => {
// this.setState({
// changeName: userName
// });
// }
// process(value) {
// return value.map(item => {
// const index = item.index('_')
// const id = item.substring(0, index);
// const username = item.substring(index + 1);
// return { id, username }
// });
// }
// 选中候选词时
onSelect = (userName) => {
this.state.dataSource.forEach((item) => {
if (item.username === userName) {
this.changeState(item.id, item.username);
}
});
handleChange = (value) => {
// this.state.dataSource.forEach((item) => {
// if (item.username === userName) {
// this.changeState(item.id, item.username);
// }
// });
// this.changeState({ value: this.process(value) })
this.props.callbackState(value);
}
// 搜索回调
@ -90,28 +105,45 @@ class UsernameAutoComplete extends Component {
this.setState({
dataSource: userList
});
if (userList.length) {
// 每次取回搜索值后,没选择时默认选择第一位
this.changeState(userList[0].id, userList[0].username);
} else {
// 如果没有搜索结果,则清空候选 uid 和 username
this.changeState(-1, '');
}
// if (userList.length) {
// // 每次取回搜索值后,没选择时默认选择第一位
// // this.changeState(userList[0].id, userList[0].username);
// } else {
// // 如果没有搜索结果,则清空候选 uid 和 username
// // this.changeState(-1, '');
// this.changeState([]);
// }
}
});
}
render () {
const { dataSource } = this.state;
return (
<AutoComplete
dataSource={this.state.dataSource.map(i => i.username)}
// <AutoComplete
// dataSource={this.state.dataSource.map(i => i.username)}
// style={{ width: '100%' }}
// onChange={this.onChange}
// onSelect={this.onSelect}
// onSearch={this.handleSearch}
// placeholder="请输入用户名"
// size="large"
// />
<Select
mode="multiple"
style={{ width: '100%' }}
onChange={this.onChange}
onSelect={this.onSelect}
onSearch={this.handleSearch}
placeholder="请输入用户名"
onSearch={this.handleSearch}
onChange={this.handleChange}
onBlur={() => this.setState({dataSource: []})}
size="large"
/>
>
{dataSource.map((item, index) => (
<Option key={index} value={'' + item.id}>{item.username}</Option>
))}
</Select>
)
}
}

View File

@ -55,7 +55,7 @@ export default class GroupList extends Component {
currGroupName: '',
currGroupDesc: '',
groupList: [],
owner_uid: 0
owner_uids: []
}
constructor(props) {
@ -106,20 +106,20 @@ export default class GroupList extends Component {
this.setState({
newGroupName: '',
group_name: '',
owner_uid: 0,
owner_uids: [],
addGroupModalVisible: false
});
}
}
@autobind
async addGroup() {
const { newGroupName: group_name, newGroupDesc: group_desc, owner_uid } = this.state;
const res = await axios.post('/api/group/add', { group_name, group_desc, owner_uid })
const { newGroupName: group_name, newGroupDesc: group_desc, owner_uids } = this.state;
const res = await axios.post('/api/group/add', { group_name, group_desc, owner_uids })
if (!res.data.errcode) {
this.setState({
newGroupName: '',
group_name: '',
owner_uid: 0,
owner_uids: [],
addGroupModalVisible: false
});
await this.props.fetchGroupList();
@ -174,9 +174,9 @@ export default class GroupList extends Component {
}
@autobind
onUserSelect(childState) {
onUserSelect(uids) {
this.setState({
owner_uid: childState.uid
owner_uids: uids
})
}

View File

@ -43,7 +43,7 @@ class MemberList extends Component {
role: '',
visible: false,
dataSource: [],
inputUid: 0,
inputUids: [],
inputRole: 'dev'
}
}
@ -82,7 +82,7 @@ class MemberList extends Component {
handleOk() {
this.props.addMember({
id: this.props.currGroup._id,
member_uid: this.state.inputUid,
member_uids: this.state.inputUids,
role: this.state.inputRole
}).then((res) => {
if (!res.payload.data.errcode) {
@ -169,9 +169,9 @@ class MemberList extends Component {
}
@autobind
onUserSelect(childState) {
onUserSelect(uids) {
this.setState({
inputUid: childState.uid
inputUids: uids
})
}

View File

@ -0,0 +1,41 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// import { connect } from 'react-redux'
// import { Table } from 'antd'
// import { fetchInterfaceList } from '../../../../reducer/modules/interface.js';
// @connect(
// state => {
// return {
// list: state.inter.list
// }
// },
// {
// fetchInterfaceList
// }
// )
export default class ImportInterface extends Component {
constructor(props) {
super(props)
}
static propTypes = {
// colId: PropTypes.number,
// fetchInterfaceList: PropTypes.func,
// projectId: PropTypes.number,
list: PropTypes.array
}
// componentWillMount() {
// this.props.fetchInterfaceList(this.props.projectId);
// }
render() {
console.log(this.props.list)
return (
<div>
<div>{this.props.list}</div>
</div>
)
}
}

View File

@ -3,8 +3,11 @@ import { connect } from 'react-redux';
import { withRouter } from 'react-router'
import PropTypes from 'prop-types'
import { fetchInterfaceColList, fetchInterfaceCaseList, setColData } from '../../../../reducer/modules/interfaceCol'
import { fetchInterfaceList } from '../../../../reducer/modules/interface.js';
import { autobind } from 'core-decorators';
import axios from 'axios';
// import { Input, Icon, Button, Modal, message, Tooltip, Tree, Dropdown, Menu, Form } from 'antd';
import ImportInterface from './ImportInterface'
import { Input, Icon, Button, Modal, message, Tooltip, Tree, Form } from 'antd';
const TreeNode = Tree.TreeNode;
@ -45,12 +48,14 @@ const ColModalForm = Form.create()((props) => {
interfaceColList: state.interfaceCol.interfaceColList,
currColId: state.interfaceCol.currColId,
currCaseId: state.interfaceCol.currCaseId,
isShowCol: state.interfaceCol.isShowCol
isShowCol: state.interfaceCol.isShowCol,
list: state.inter.list
}
},
{
fetchInterfaceColList,
fetchInterfaceCaseList,
fetchInterfaceList,
setColData
}
)
@ -62,11 +67,13 @@ export default class InterfaceColMenu extends Component {
interfaceColList: PropTypes.array,
fetchInterfaceColList: PropTypes.func,
fetchInterfaceCaseList: PropTypes.func,
fetchInterfaceList: PropTypes.func,
setColData: PropTypes.func,
history: PropTypes.object,
currColId: PropTypes.number,
currCaseId: PropTypes.number,
isShowCol: PropTypes.bool
isShowCol: PropTypes.bool,
list: PropTypes.array
}
state = {
@ -74,7 +81,9 @@ export default class InterfaceColMenu extends Component {
colModalType: '',
colModalVisible: false,
editColId: 0,
filterValue: ''
filterValue: '',
// importInterVisible: false,
importInterIds: []
}
constructor(props) {
@ -188,6 +197,25 @@ export default class InterfaceColMenu extends Component {
this.form = form;
}
selectInterface = (importInterIds) => {
this.setState({ importInterIds })
}
showImportInterface = async (colId) => {
const projectId = this.props.match.params.id;
await fetchInterfaceList(projectId)
confirm({
title: '请选择添加到集合的接口',
content: <ImportInterface onSelect={this.selectInterface} list={this.props.list} />,
onOk() {
console.log(colId);
},
onCancel() {
console.log('Cancel');
}
});
}
filterCol = (e) => {
const value = e.target.value;
this.setState({filterValue: value})
@ -208,6 +236,9 @@ export default class InterfaceColMenu extends Component {
// this.showDelColConfirm(col._id)
// }}>删除集合</span>
// </Menu.Item>
// <Menu.Item>
// <span onClick={() => this.showImportInterface(col._id)}>导入接口</span>
// </Menu.Item>
// </Menu>
// )
// };
@ -251,6 +282,7 @@ export default class InterfaceColMenu extends Component {
<div className="btns">
<Icon type='delete' className="interface-delete-icon" onClick={() => {this.showDelColConfirm(col._id)}} />
<Icon type='edit' className="interface-delete-icon" onClick={() => {this.showColModal('edit', col)}} />
<Icon type='plus' className="interface-delete-icon" onClick={() => this.showImportInterface(col._id)} />
</div>
{/*<Dropdown overlay={menu(col)} trigger={['click']} onClick={e => e.stopPropagation()}>
<Icon className="opts-icon" type='ellipsis'/>

View File

@ -49,7 +49,7 @@ class ProjectMember extends Component {
role: '',
visible: false,
dataSource: [],
inputUid: 0,
inputUids: [],
inputRole: 'dev'
}
}
@ -90,7 +90,7 @@ class ProjectMember extends Component {
handleOk() {
this.props.addMember({
id: this.props.match.params.id,
member_uid: this.state.inputUid,
member_uids: this.state.inputUids,
role: this.state.inputRole
}).then((res) => {
if (!res.payload.data.errcode) {
@ -144,9 +144,9 @@ class ProjectMember extends Component {
}
@autobind
onUserSelect(childState) {
onUserSelect(uids) {
this.setState({
inputUid: childState.uid
inputUids: uids
})
}

View File

@ -49,7 +49,7 @@ class groupController extends baseController {
* @foldnumber 10
* @param {String} group_name 项目分组名称不能为空
* @param {String} [group_desc] 项目分组描述
* @param {String} owner_uid 组长uid
* @param {String} [owner_uids] 组长[uid]
* @returns {Object}
* @example ./api/group/add.json
*/
@ -70,17 +70,22 @@ class groupController extends baseController {
return ctx.body = yapi.commons.resReturn(null, 400, '项目分组名不能为空');
}
// if (!params.owner_uid) {
// return ctx.body = yapi.commons.resReturn(null, 400, '项目分组必须添加一个组长');
// }
if (!params.owner_uids || !params.owner_uids.length) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目分组必须添加一个组长');
}
let groupUserdata = null;
if (params.owner_uid) {
groupUserdata = await this.getUserdata(params.owner_uid, 'owner');
if (groupUserdata === null) {
return ctx.body = yapi.commons.resReturn(null, 400, '组长uid不存在')
let owners = [];
for(let i = 0, len = params.owner_uids.length; i < len; i++) {
let id = params.owner_uids[i]
let groupUserdata = await this.getUserdata(id, 'owner');
if (groupUserdata) {
owners.push(groupUserdata)
}
}
// groupUserdata = await this.getUserdata(params.owner_uid, 'owner');
// if (!owners.length) {
// return ctx.body = yapi.commons.resReturn(null, 400, '组长uid不存在')
// }
let groupInst = yapi.getInst(groupModel);
@ -96,7 +101,7 @@ class groupController extends baseController {
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time(),
members: groupUserdata ? [groupUserdata] : []
members: owners
};
try {
@ -141,7 +146,7 @@ class groupController extends baseController {
* @category group
* @foldnumber 10
* @param {String} id 项目分组id
* @param {String} member_uid 项目分组成员uid
* @param {String} member_uids 项目分组成员[uid]
* @param {String} role 成员角色owner or dev or guest
* @returns {Object}
* @example
@ -153,7 +158,7 @@ class groupController extends baseController {
let params = ctx.request.body;
let groupInst = yapi.getInst(groupModel);
if (!params.member_uid) {
if (!params.member_uids || !params.member_uids.length) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组成员uid不能为空');
}
if (!params.id) {
@ -161,21 +166,39 @@ class groupController extends baseController {
}
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let add_members = [];
let exist_members = [];
let no_members = []
for(let i = 0, len = params.member_uids.length; i < len; i++) {
let id = params.member_uids[i];
let check = await groupInst.checkMemberRepeat(params.id, id);
let userdata = await this.getUserdata(id, params.role);
if (check > 0) {
exist_members.push(userdata)
} else if (!userdata) {
no_members.push(id)
} else {
userdata.role !== 'admin' && add_members.push(userdata);
delete userdata._role;
}
}
var check = await groupInst.checkMemberRepeat(params.id, params.member_uid);
if (check > 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '成员已存在');
}
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
if (groupUserdata === null) {
return ctx.body = yapi.commons.resReturn(null, 400, '组长uid不存在')
}
if (groupUserdata._role === 'admin') {
return ctx.body = yapi.commons.resReturn(null, 400, '不能邀请管理员')
}
delete groupUserdata._role;
// params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
// var check = await groupInst.checkMemberRepeat(params.id, params.member_uid);
// if (check > 0) {
// return ctx.body = yapi.commons.resReturn(null, 400, '成员已存在');
// }
// let groupUserdata = await this.getUserdata(params.member_uid, params.role);
// if (groupUserdata === null) {
// return ctx.body = yapi.commons.resReturn(null, 400, '组长uid不存在')
// }
// if (groupUserdata._role === 'admin') {
// return ctx.body = yapi.commons.resReturn(null, 400, '不能邀请管理员')
// }
// delete groupUserdata._role;
try {
let result = await groupInst.addMember(params.id, groupUserdata);
let result = await groupInst.addMember(params.id, add_members);
let username = this.getUsername();
let rolename = {
owner: "组长",
@ -183,13 +206,18 @@ class groupController extends baseController {
guest: "访客"
};
yapi.commons.saveLog({
content: `用户 "${username}" 新增了分组成员 "${groupUserdata.username}" 为 "${rolename[params.role]}"`,
content: `用户 "${username}" 新增了分组成员 "${add_members.reduce((str, item) => (str ? str + '、' : '') + item.username, '')}" 为 "${rolename[params.role]}"`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: params.id
});
ctx.body = yapi.commons.resReturn(result);
ctx.body = yapi.commons.resReturn({
result,
add_members,
exist_members,
no_members
});
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}

View File

@ -159,7 +159,7 @@ class projectController extends baseController {
*/
async addMember(ctx) {
let params = ctx.request.body;
if (!params.member_uid) {
if (!params.member_uids || !params.member_uids.length) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员uid不能为空');
}
if (!params.id) {
@ -170,30 +170,53 @@ class projectController extends baseController {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
var check = await this.Model.checkMemberRepeat(params.id, params.member_uid);
if (check > 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员已存在');
}
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let userdata = await this.getUserdata(params.member_uid, params.role);
if (userdata === null) {
return ctx.body = yapi.commons.resReturn(null, 400, '成员uid不存在')
let add_members = [];
let exist_members = [];
let no_members = []
for(let i = 0, len = params.member_uids.length; i < len; 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)
} else if (!userdata) {
no_members.push(id)
} else {
add_members.push(userdata)
}
}
// var check = await this.Model.checkMemberRepeat(params.id, params.member_uids);
// if (check > 0) {
// // return ctx.body = yapi.commons.resReturn(null, 400, '项目成员已存在');
// }
// params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
// let userdata = await this.getUserdata(params.member_uid, params.role);
// if (!add_members.length) {
// return ctx.body = yapi.commons.resReturn(null, 400, '成员uid不存在')
// }
try {
let result = await this.Model.addMember(params.id, userdata);
let result = await this.Model.addMember(params.id, add_members);
let username = this.getUsername();
yapi.commons.saveLog({
content: `用户 "${username}" 添加了项目成员 "${userdata.username}"`,
content: `用户 "${username}" 添加了项目成员 "${add_members.reduce((str, item) => (str ? str + '、' : '') + item.username, '')}"`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.id
});
ctx.body = yapi.commons.resReturn(result);
ctx.body = yapi.commons.resReturn({
result,
add_members,
exist_members,
no_members
});
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}

View File

@ -60,7 +60,8 @@ class groupModel extends baseModel {
{
_id: id
}, {
$push: { members: data }
// $push: { members: data },
$push: { members: { $each: data } }
}
);
}

View File

@ -118,7 +118,8 @@ class projectModel extends baseModel {
{
_id: id
}, {
$push: { members: data }
// $push: { members: data }
$push: { members: { $each: data } }
}
);
}

18928
static/prd/index.css Normal file

File diff suppressed because it is too large Load Diff

5331
static/prd/index.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3019
static/prd/lib.js Normal file

File diff suppressed because one or more lines are too long

48
static/prd/lib2.js Normal file

File diff suppressed because one or more lines are too long

94
static/prd/manifest.js Normal file
View File

@ -0,0 +1,94 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window["webpackJsonp"];
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, callbacks = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId])
/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]);
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
/******/ while(callbacks.length)
/******/ callbacks.shift().call(null, __webpack_require__);
/******/ if(moreModules[0]) {
/******/ installedModules[0] = 0;
/******/ return __webpack_require__(0);
/******/ }
/******/ };
/******/ // The module cache
/******/ var installedModules = {};
/******/ // object to store loaded and loading chunks
/******/ // "0" means "already loaded"
/******/ // Array means "loading", array contains callbacks
/******/ var installedChunks = {
/******/ 3:0
/******/ };
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/ // "0" is the signal for "already loaded"
/******/ if(installedChunks[chunkId] === 0)
/******/ return callback.call(null, __webpack_require__);
/******/ // an array means "currently loading".
/******/ if(installedChunks[chunkId] !== undefined) {
/******/ installedChunks[chunkId].push(callback);
/******/ } else {
/******/ // start chunk loading
/******/ installedChunks[chunkId] = [callback];
/******/ var head = document.getElementsByTagName('head')[0];
/******/ var script = document.createElement('script');
/******/ script.type = 'text/javascript';
/******/ script.charset = 'utf-8';
/******/ script.async = true;
/******/ script.src = __webpack_require__.p + "" + chunkId + ".chunk.js";
/******/ head.appendChild(script);
/******/ }
/******/ };
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ })
/************************************************************************/
/******/ ([]);