mirror of
https://github.com/YMFE/yapi.git
synced 2025-01-30 13:20:24 +08:00
fix: 为log添加头像
This commit is contained in:
commit
679642ce53
@ -1,8 +1,39 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { AutoComplete } from 'antd';
|
||||
import axios from 'axios'
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* 用户名输入框自动完成组件
|
||||
*
|
||||
* @component UsernameAutoComplete
|
||||
* @examplelanguage js
|
||||
*
|
||||
* * 用户名输入框自动完成组件
|
||||
* * 用户名输入框自动完成组件
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取自动输入的用户信息
|
||||
*
|
||||
* 获取子组件state
|
||||
* @property callbackState
|
||||
* @type function
|
||||
* @description 类型提示:支持数组传值;也支持用函数格式化字符串:函数有两个参数(scale, index);
|
||||
* 受控属性:滑块滑到某一刻度时所展示的刻度文本信息。如果不需要标签,请将该属性设置为 [] 空列表来覆盖默认转换函数。
|
||||
* @returns {object} {uid: xxx, username: xxx}
|
||||
* @examplelanguage js
|
||||
* @example
|
||||
* onUserSelect(childState) {
|
||||
* this.setState({
|
||||
* uid: childState.uid,
|
||||
* username: childState.username
|
||||
* })
|
||||
* }
|
||||
*
|
||||
*/
|
||||
class UsernameAutoComplete extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -2,10 +2,10 @@ import React, { Component } from 'react';
|
||||
import { Table } from 'antd';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Select, Button, Modal, Row, Col, message } from 'antd';
|
||||
import { Select, Button, Modal, Row, Col, message, Popconfirm } from 'antd';
|
||||
import './MemberList.scss';
|
||||
import { autobind } from 'core-decorators';
|
||||
import { fetchGroupMemberList, fetchGroupMsg, addMember } from '../../../reducer/modules/group.js'
|
||||
import { fetchGroupMemberList, fetchGroupMsg, addMember, delMember, changeMemberRole } from '../../../reducer/modules/group.js'
|
||||
import UsernameAutoComplete from '../../../components/UsernameAutoComplete/UsernameAutoComplete.js';
|
||||
const Option = Select.Option;
|
||||
|
||||
@ -29,7 +29,9 @@ const arrayAddKey = (arr) => {
|
||||
{
|
||||
fetchGroupMemberList,
|
||||
fetchGroupMsg,
|
||||
addMember
|
||||
addMember,
|
||||
delMember,
|
||||
changeMemberRole
|
||||
}
|
||||
)
|
||||
class MemberList extends Component {
|
||||
@ -50,20 +52,31 @@ class MemberList extends Component {
|
||||
fetchGroupMemberList: PropTypes.func,
|
||||
fetchGroupMsg: PropTypes.func,
|
||||
addMember: PropTypes.func,
|
||||
delMember: PropTypes.func,
|
||||
changeMemberRole: PropTypes.func,
|
||||
role: PropTypes.string
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleChange(value) {
|
||||
console.log(`selected ${value}`);
|
||||
}
|
||||
|
||||
showModal = () => {
|
||||
@autobind
|
||||
showAddMemberModal() {
|
||||
this.setState({
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
|
||||
// 重新获取列表
|
||||
@autobind
|
||||
reFetchList() {
|
||||
this.props.fetchGroupMemberList(this.props.currGroup._id).then((res) => {
|
||||
this.setState({
|
||||
userInfo: arrayAddKey(res.payload.data.data),
|
||||
visible: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 增 - 添加成员
|
||||
@autobind
|
||||
handleOk() {
|
||||
console.log(this.props.currGroup._id, this.state.inputUid);
|
||||
@ -74,29 +87,55 @@ class MemberList extends Component {
|
||||
console.log(res);
|
||||
if (!res.payload.data.errcode) {
|
||||
message.success('添加成功!');
|
||||
// 添加成功后重新获取分组成员列表
|
||||
this.props.fetchGroupMemberList(this.props.currGroup._id).then((res) => {
|
||||
this.setState({
|
||||
userInfo: arrayAddKey(res.payload.data.data),
|
||||
visible: false
|
||||
});
|
||||
});
|
||||
this.reFetchList(); // 添加成功后重新获取分组成员列表
|
||||
}
|
||||
});
|
||||
}
|
||||
// 添加成员时 选择新增成员权限
|
||||
@autobind
|
||||
changeNewMemberRole(value) {
|
||||
return () => {
|
||||
console.log(this.props.currGroup._id, value);
|
||||
}
|
||||
}
|
||||
|
||||
// 删 - 删除分组成员
|
||||
@autobind
|
||||
deleteConfirm(member_uid) {
|
||||
return () => {
|
||||
const id = this.props.currGroup._id;
|
||||
this.props.delMember({ id, member_uid }).then((res) => {
|
||||
if (!res.payload.data.errcode) {
|
||||
message.success(res.payload.data.errmsg);
|
||||
this.reFetchList(); // 添加成功后重新获取分组成员列表
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 改 - 修改成员权限
|
||||
@autobind
|
||||
changeUserRole(e) {
|
||||
console.log(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) => {
|
||||
if (!res.payload.data.errcode) {
|
||||
message.success(res.payload.data.errmsg);
|
||||
this.reFetchList(); // 添加成功后重新获取分组成员列表
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭模态框
|
||||
@autobind
|
||||
handleCancel() {
|
||||
// 取消模态框的时候重置模态框中的值
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeMemberRole(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.currGroup !== nextProps.currGroup) {
|
||||
@ -136,7 +175,6 @@ class MemberList extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log(this.state);
|
||||
const columns = [{
|
||||
title: this.props.currGroup.group_name + ' 分组成员 ('+this.state.userInfo.length + ') 人',
|
||||
dataIndex: 'username',
|
||||
@ -148,18 +186,20 @@ class MemberList extends Component {
|
||||
</div>);
|
||||
}
|
||||
}, {
|
||||
title: (this.state.role === 'owner' || this.state.role === 'admin') ? <div className="btn-container"><Button className="btn" type="primary" icon="plus" onClick={this.showModal}>添加成员</Button></div> : '',
|
||||
title: (this.state.role === 'owner' || this.state.role === 'admin') ? <div className="btn-container"><Button className="btn" type="primary" icon="plus" 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 defaultValue={record.role} className="select" onChange={this.handleChange}>
|
||||
<Option value="owner">组长</Option>
|
||||
<Option value="dev">开发者</Option>
|
||||
<Select defaultValue={record.role+'-'+record.uid} className="select" onChange={this.changeUserRole}>
|
||||
<Option value={'owner-'+record.uid}>组长</Option>
|
||||
<Option value={'dev-'+record.uid}>开发者</Option>
|
||||
</Select>
|
||||
<Button type="danger" icon="minus" className="btn-danger" />
|
||||
<Popconfirm placement="topRight" title="你确定要删除吗? " onConfirm={this.deleteConfirm(record.uid)} okText="确定" cancelText="">
|
||||
<Button type="danger" icon="minus" className="btn-danger" />
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
@ -184,7 +224,7 @@ class MemberList extends Component {
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">权限: </div></Col>
|
||||
<Col span="15">
|
||||
<Select size="large" defaultValue="dev" className="select" onChange={this.changeMemberRole}>
|
||||
<Select size="large" defaultValue="dev" className="select" onChange={this.changeNewMemberRole}>
|
||||
<Option value="owner">组长</Option>
|
||||
<Option value="dev">开发者</Option>
|
||||
</Select>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { message, Row, Col } from 'antd';
|
||||
import { message, Row, Col, Icon } from 'antd';
|
||||
import { addProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project';
|
||||
import ProjectCard from '../../../components/ProjectCard/ProjectCard.js';
|
||||
// import variable from '../../../constants/variable';
|
||||
@ -180,12 +180,15 @@ class ProjectList extends Component {
|
||||
return (
|
||||
<div className="m-panel">
|
||||
<Row gutter={16}>
|
||||
{projectData.map((item, index) => {
|
||||
{projectData.length ? projectData.map((item, index) => {
|
||||
return (
|
||||
<Col span={8} key={index}>
|
||||
<ProjectCard projectData={item} />
|
||||
</Col>);
|
||||
})}
|
||||
}) : (<div className="empty-tip">
|
||||
<p><Icon type="frown-o" /> 该分组还没有项目呢</p>
|
||||
<p>请点击右上角 “<Icon type="plus-circle" />” 按钮添加项目</p>
|
||||
</div>)}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
|
@ -31,3 +31,8 @@
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
font-size: .14rem;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Row, Col, Tabs } from 'antd';
|
||||
import { Route } from 'react-router-dom';
|
||||
|
||||
import './interface.scss'
|
||||
|
||||
import InterfaceMenu from './InterfaceList/InterfaceMenu.js'
|
||||
@ -9,37 +11,46 @@ import InterfaceContent from './InterfaceList/InterfaceContent.js'
|
||||
import InterfaceColMenu from './InterfaceCol/InterfaceColMenu.js'
|
||||
import InterfaceColContent from './InterfaceCol/InterfaceColContent.js'
|
||||
|
||||
const InterfaceRoute = (props) => {
|
||||
let C;
|
||||
if (props.match.params.action === 'api') {
|
||||
C = InterfaceContent;
|
||||
} else if (props.match.params.action === 'col') {
|
||||
C = InterfaceColContent;
|
||||
}
|
||||
return <C />
|
||||
}
|
||||
|
||||
InterfaceRoute.propTypes = {
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
|
||||
class Interface extends Component {
|
||||
static propTypes = {
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
super(props)
|
||||
this.state = {
|
||||
contentView: 'list'
|
||||
curkey: this.props.match.params.action
|
||||
}
|
||||
}
|
||||
|
||||
handleTab = (key) => {
|
||||
onChange = (key) => {
|
||||
this.setState({
|
||||
contentView: key
|
||||
curkey: key
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {contentView} = this.state;
|
||||
let content;
|
||||
content = contentView === 'list' ?
|
||||
<InterfaceContent />
|
||||
:
|
||||
<InterfaceColContent />
|
||||
return <div className="web-content g-row" style={{ marginBottom: "15px" }}>
|
||||
<Row gutter={16} >
|
||||
<Col span={6}>
|
||||
<div className="left-menu">
|
||||
<Tabs defaultActiveKey="list" type="card" onChange={this.handleTab}>
|
||||
<Tabs.TabPane tab="接口列表" key="list">
|
||||
<Tabs type="card" activeKey={this.state.curkey} onChange={this.onChange}>
|
||||
<Tabs.TabPane tab="接口列表" key="api">
|
||||
<InterfaceMenu projectId={this.props.match.params.id} />
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab="接口集合" key="col" >
|
||||
@ -48,10 +59,11 @@ class Interface extends Component {
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
|
||||
</Col>
|
||||
<Col span={18} >
|
||||
<div className="right-content">
|
||||
{content}
|
||||
<Route path="/project/:id/interface/:action/:actionId" component={InterfaceRoute} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -59,4 +71,6 @@ class Interface extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default Interface
|
@ -56,6 +56,8 @@ export default class InterfaceColMenu extends Component {
|
||||
});
|
||||
message.success('添加集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +92,7 @@ export default class InterfaceColMenu extends Component {
|
||||
onTitleClick={(key, e) => this.selectCol(key, e, col)}
|
||||
>
|
||||
{
|
||||
col.interfaceCaseList && col.interfaceCaseList.map((interfaceCase, index) => (
|
||||
col.caseList && col.caseList.map((interfaceCase, index) => (
|
||||
<Menu.Item key={index}>{interfaceCase.name}</Menu.Item>
|
||||
))
|
||||
}
|
||||
|
@ -44,6 +44,30 @@ class InterfaceEdit extends Component{
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount(){
|
||||
let s = new WebSocket('ws://yapi.local.qunar.com:3000/api/interface/solve_conflict?id=1');
|
||||
s.onopen = (e)=>{
|
||||
console.log('open',e)
|
||||
s.send('abc')
|
||||
//s.close()
|
||||
s.send('aaaaa')
|
||||
}
|
||||
|
||||
s.onclose = (e)=>{
|
||||
console.log('close',e)
|
||||
}
|
||||
|
||||
s.onmessage = (e)=>{
|
||||
console.log('message',e)
|
||||
}
|
||||
|
||||
s.onerror = (e)=>{
|
||||
console.log('error',e)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
render(){
|
||||
return <div className="interface-edit">
|
||||
<InterfaceEditForm mockUrl={this.state.mockUrl} basepath={this.props.currProject.basepath} onSubmit={this.onSubmit} curdata={this.props.curdata} />
|
||||
|
@ -1,25 +1,93 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types'
|
||||
import { Tabs } from 'antd';
|
||||
import Edit from './Edit.js'
|
||||
import View from './View.js'
|
||||
import Run from './Run.js'
|
||||
|
||||
import { fetchInterfaceData } from '../../../../reducer/modules/interface.js';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import Run from './Run/Run.js'
|
||||
|
||||
|
||||
const TabPane = Tabs.TabPane;
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
curdata: state.inter.curdata,
|
||||
list: state.inter.list
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceData
|
||||
}
|
||||
)
|
||||
class Content extends Component {
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
list: PropTypes.array,
|
||||
curdata: PropTypes.object,
|
||||
fetchInterfaceData: PropTypes.func
|
||||
}
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
curtab: 'view'
|
||||
}
|
||||
this._actionId = 0;
|
||||
}
|
||||
|
||||
const Content = () => {
|
||||
return <div className="interface-content">
|
||||
<Tabs defaultActiveKey="1" >
|
||||
<TabPane tab="预览" key="1">
|
||||
<View />
|
||||
componentWillReceiveProps(nextProps){
|
||||
this.handleRequest(nextProps)
|
||||
}
|
||||
|
||||
handleRequest(nextProps){
|
||||
let matchParams = nextProps.match.params;
|
||||
let _actionId;
|
||||
_actionId = matchParams.actionId;
|
||||
_actionId = parseInt(matchParams.actionId, 10);
|
||||
if(!nextProps.curdata)return;
|
||||
if(this._actionId !== _actionId){
|
||||
this._actionId = _actionId;
|
||||
this.props.fetchInterfaceData(_actionId)
|
||||
}
|
||||
this.setState({
|
||||
curtab: 'view'
|
||||
})
|
||||
}
|
||||
|
||||
onChange = (key)=>{
|
||||
this.setState({
|
||||
curtab: key
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const tabs = <Tabs onChange={this.onChange} activeKey={this.state.curtab} defaultActiveKey="view" >
|
||||
<TabPane tab="预览" key="view">
|
||||
{/* <View /> */}
|
||||
</TabPane>
|
||||
<TabPane tab="编辑" key="2">
|
||||
<Edit />
|
||||
<TabPane tab="编辑" key="edit">
|
||||
|
||||
</TabPane>
|
||||
<TabPane tab="运行" key="3">
|
||||
<Run />
|
||||
<TabPane tab="运行" key="run">
|
||||
{/* <Run /> */}
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Tabs>;
|
||||
let tabContent;
|
||||
if (this.state.curtab === 'view') {
|
||||
tabContent = <View />;
|
||||
} else if (this.state.curtab === 'edit') {
|
||||
tabContent = <Edit />
|
||||
} else if (this.state.curtab === 'run') {
|
||||
tabContent = <Run />
|
||||
}
|
||||
|
||||
return <div className="interface-content">
|
||||
{tabs}
|
||||
{tabContent}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default Content
|
||||
export default withRouter(Content)
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types'
|
||||
import { fetchInterfaceList, fetchInterfaceData, changeInterfaceId, addInterfaceData, deleteInterfaceData } from '../../../../reducer/modules/interface.js';
|
||||
import { fetchInterfaceList, fetchInterfaceData, addInterfaceData, deleteInterfaceData } from '../../../../reducer/modules/interface.js';
|
||||
import { Menu, Input, Icon, Tag, Modal, message } from 'antd';
|
||||
import AddInterfaceForm from './AddInterfaceForm';
|
||||
import axios from 'axios'
|
||||
import { Link,withRouter } from 'react-router-dom';
|
||||
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
@ -14,29 +15,27 @@ const confirm = Modal.confirm;
|
||||
state => {
|
||||
return {
|
||||
list: state.inter.list,
|
||||
curProject: state.project.curProject,
|
||||
interfaceId: state.inter.interfaceId
|
||||
curProject: state.project.curProject
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceList,
|
||||
fetchInterfaceData,
|
||||
changeInterfaceId,
|
||||
addInterfaceData,
|
||||
deleteInterfaceData
|
||||
}
|
||||
)
|
||||
class InterfaceMenu extends Component {
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
projectId: PropTypes.string,
|
||||
interfaceId: PropTypes.number,
|
||||
list: PropTypes.array,
|
||||
fetchInterfaceList: PropTypes.func,
|
||||
curProject: PropTypes.object,
|
||||
fetchInterfaceData: PropTypes.func,
|
||||
changeInterfaceId: PropTypes.func,
|
||||
addInterfaceData: PropTypes.func,
|
||||
deleteInterfaceData: PropTypes.func
|
||||
deleteInterfaceData: PropTypes.func,
|
||||
history: PropTypes.object
|
||||
}
|
||||
|
||||
showModal = () => {
|
||||
@ -59,26 +58,21 @@ class InterfaceMenu extends Component {
|
||||
delIcon: null,
|
||||
filter: ''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async handleRequest() {
|
||||
let result = await this.props.fetchInterfaceList(this.props.projectId);
|
||||
let interfaces = result.payload.data;
|
||||
if (interfaces.length > 0) {
|
||||
this.props.changeInterfaceId(interfaces[0]._id)
|
||||
await this.props.fetchInterfaceData(interfaces[0]._id)
|
||||
let params = this.props.match.params;
|
||||
if(!params.actionId){
|
||||
this.props.history.replace('/project/'+params.id + '/interface/api/' + result.payload.data[0]._id)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.handleRequest()
|
||||
}
|
||||
|
||||
onSelect = (item) => {
|
||||
this.props.changeInterfaceId(parseInt(item.key, 10))
|
||||
this.props.fetchInterfaceData(parseInt(item.key, 10))
|
||||
}
|
||||
|
||||
|
||||
handleAddInterface = (data) => {
|
||||
data.project_id = this.props.projectId;
|
||||
axios.post('/api/interface/add', data).then((res) => {
|
||||
@ -127,6 +121,7 @@ class InterfaceMenu extends Component {
|
||||
|
||||
render() {
|
||||
const items = [];
|
||||
const matchParams = this.props.match.params;
|
||||
this.props.list.forEach((item) => {
|
||||
let color, filter = this.state.filter;
|
||||
if(filter && item.title.indexOf(filter) === -1 && item.path.indexOf(filter) === -1){
|
||||
@ -141,9 +136,10 @@ class InterfaceMenu extends Component {
|
||||
}
|
||||
|
||||
items.push(
|
||||
|
||||
<Menu.Item onMouseEnter={this.enterItem} onMouseLeave={this.leaveItem} key={"" + item._id}>
|
||||
<Tag className="btn-http" color={color}>{item.method} </Tag>
|
||||
{item.title}
|
||||
<Link className="interface-item" to={"/project/" + matchParams.id + "/interface/api/" + item._id} >{item.title}</Link>
|
||||
<Icon type="delete" onClick={()=> {this.showConfirm(item._id)}} style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} className="interface-delete-icon" />
|
||||
</Menu.Item>
|
||||
)
|
||||
@ -163,7 +159,7 @@ class InterfaceMenu extends Component {
|
||||
<AddInterfaceForm onCancel={this.handleCancel} onSubmit={this.handleAddInterface} />
|
||||
</Modal>
|
||||
</div>
|
||||
<Menu selectedKeys={[this.props.interfaceId + ""]} className="interface-list" onSelect={this.onSelect}>
|
||||
<Menu selectedKeys={[this.props.match.params.actionId + ""]} className="interface-list">
|
||||
{items}
|
||||
</Menu>
|
||||
</div>
|
||||
@ -171,4 +167,4 @@ class InterfaceMenu extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default InterfaceMenu
|
||||
export default withRouter(InterfaceMenu)
|
@ -0,0 +1,130 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Modal, Collapse, Row, Col, Input, message, Button, Icon } from 'antd';
|
||||
import PropTypes from 'prop-types';
|
||||
import axios from 'axios';
|
||||
import { withRouter } from 'react-router'
|
||||
import { fetchInterfaceColList } from '../../../../../reducer/modules/interfaceCol'
|
||||
|
||||
const { TextArea } = Input;
|
||||
const Panel = Collapse.Panel;
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
interfaceColList: state.interfaceCol.interfaceColList
|
||||
}),
|
||||
{
|
||||
fetchInterfaceColList
|
||||
}
|
||||
)
|
||||
@withRouter
|
||||
export default class AddColModal extends Component {
|
||||
static propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
interfaceColList: PropTypes.array,
|
||||
fetchInterfaceColList: PropTypes.func,
|
||||
match: PropTypes.object,
|
||||
onOk: PropTypes.func,
|
||||
onCancel: PropTypes.func
|
||||
}
|
||||
|
||||
state = {
|
||||
visible: false,
|
||||
addColName: '',
|
||||
addColDesc: '',
|
||||
id: 0,
|
||||
caseName: ''
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchInterfaceColList(this.props.match.params.id)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({id: nextProps.interfaceColList[0]._id})
|
||||
}
|
||||
|
||||
addCol = async () => {
|
||||
const { addColName: name, addColDesc: desc } = this.state;
|
||||
const project_id = this.props.match.params.id
|
||||
const res = await axios.post('/api/col/add_col', { name, desc, project_id })
|
||||
if (!res.data.errcode) {
|
||||
message.success('添加集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
select = (id) => {
|
||||
this.setState({id})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { interfaceColList = [] } = this.props;
|
||||
const { id } = this.state;
|
||||
return (
|
||||
<Modal
|
||||
className="add-col-modal"
|
||||
title="添加到集合"
|
||||
visible={this.props.visible}
|
||||
onOk={() => this.props.onOk(id, this.state.caseName)}
|
||||
onCancel={this.props.onCancel}
|
||||
>
|
||||
<Row gutter={6}>
|
||||
<Col span="5"><div className="label">接口用例名:</div></Col>
|
||||
<Col span="15">
|
||||
<Input
|
||||
placeholder="请输入接口用例名称"
|
||||
value={this.state.caseName}
|
||||
onChange={e => this.setState({caseName: e.target.value})}></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
<p>请选择添加到的集合:</p>
|
||||
<ul className="col-list">
|
||||
{
|
||||
interfaceColList.length ? interfaceColList.map(col =>
|
||||
<li
|
||||
key={col._id}
|
||||
className={`col-item ${col._id === id ? 'selected' : ''}`}
|
||||
onClick={() => this.select(col._id)}
|
||||
>
|
||||
<Icon type="folder-open" style={{marginRight: 6}} />{col.name}
|
||||
</li>
|
||||
) : <span>暂无集合,请添加!</span>
|
||||
}
|
||||
</ul>
|
||||
<Collapse>
|
||||
<Panel header="添加新集合">
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">集合名:</div></Col>
|
||||
<Col span="15">
|
||||
<Input
|
||||
placeholder="请输入集合名称"
|
||||
value={this.state.addColName}
|
||||
onChange={e => this.setState({addColName: e.target.value})}></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">简介:</div></Col>
|
||||
<Col span="15">
|
||||
<TextArea
|
||||
rows={3}
|
||||
placeholder="请输入集合描述"
|
||||
value={this.state.addColDesc}
|
||||
onChange={e => this.setState({addColDesc: e.target.value})}></TextArea>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row type="flex" justify="end">
|
||||
<Button style={{float: 'right'}} type="primary" onClick={this.addCol}>添 加</Button>
|
||||
</Row>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Radio } from 'antd'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Radio, Tooltip, message } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import crossRequest from 'cross-request';
|
||||
import { withRouter } from 'react-router';
|
||||
// import axios from 'axios';
|
||||
import axios from 'axios';
|
||||
import URL from 'url';
|
||||
import AddColModal from './AddColModal'
|
||||
|
||||
// import {
|
||||
// } from '../../../reducer/modules/group.js'
|
||||
@ -47,7 +48,8 @@ export default class Run extends Component {
|
||||
headers: [],
|
||||
currDomain: '',
|
||||
bodyType: '',
|
||||
bodyOther: ''
|
||||
bodyOther: '',
|
||||
addColModalVisible: false
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@ -355,6 +357,42 @@ export default class Run extends Component {
|
||||
console.log(index)
|
||||
}
|
||||
|
||||
saveToCol = async (colId, caseName) => {
|
||||
const project_id = this.props.match.params.id;
|
||||
const {
|
||||
currDomain: domain,
|
||||
pathname: path,
|
||||
method,
|
||||
pathParam: req_params,
|
||||
query: req_query,
|
||||
headers: req_headers,
|
||||
bodyType: req_body_type,
|
||||
bodyForm: req_body_form,
|
||||
bodyOther: req_body_other
|
||||
} = this.state;
|
||||
const res = await axios.post('/api/col/add_case', {
|
||||
casename: caseName,
|
||||
col_id: colId,
|
||||
project_id,
|
||||
env: '',
|
||||
domain,
|
||||
path,
|
||||
method,
|
||||
req_params,
|
||||
req_query,
|
||||
req_headers,
|
||||
req_body_type,
|
||||
req_body_form,
|
||||
req_body_other
|
||||
});
|
||||
if (res.data.errcode) {
|
||||
message.error(res.data.errmsg)
|
||||
} else {
|
||||
message.success('添加成功')
|
||||
this.setState({addColModalVisible: false})
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
const { method, domains, pathParam, pathname, query, headers, bodyForm, bodyOther, currDomain, bodyType } = this.state;
|
||||
@ -399,17 +437,21 @@ export default class Run extends Component {
|
||||
</Select>
|
||||
<Input value={path + search} onChange={this.changePath} spellCheck="false" style={{flexBasis: 180, flexGrow: 1}} />
|
||||
</InputGroup>
|
||||
<Button
|
||||
onClick={this.reqRealInterface}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
loading={this.state.loading}
|
||||
>发送</Button>
|
||||
<Button
|
||||
onClick={this.reqRealInterface}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
>保存</Button>
|
||||
<Tooltip placement="bottom" title="请求真实接口">
|
||||
<Button
|
||||
onClick={this.reqRealInterface}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
loading={this.state.loading}
|
||||
>发送</Button>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom" title="保存到集合">
|
||||
<Button
|
||||
onClick={() => this.setState({addColModalVisible: true})}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
>保存</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Collapse defaultActiveKey={['0', '1', '2', '3']} bordered={true}>
|
||||
@ -541,6 +583,11 @@ export default class Run extends Component {
|
||||
</div>
|
||||
</Spin>
|
||||
</Card>
|
||||
<AddColModal
|
||||
visible={this.state.addColModalVisible}
|
||||
onCancel={() => this.setState({addColModalVisible: false})}
|
||||
onOk={this.saveToCol}
|
||||
></AddColModal>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -28,3 +28,20 @@
|
||||
color: #108ee9;
|
||||
}
|
||||
}
|
||||
.add-col-modal {
|
||||
.col-list {
|
||||
height: 200px;
|
||||
overflow: auto;
|
||||
margin: 7px 0 15px 0;
|
||||
background: #eaeaea;
|
||||
.col-item {
|
||||
padding: 7px 10px 7px 10px;
|
||||
}
|
||||
.col-item:hover {
|
||||
background: #fa0;
|
||||
}
|
||||
.col-item.selected {
|
||||
background: #108ee9;
|
||||
}
|
||||
}
|
||||
}
|
@ -45,6 +45,9 @@
|
||||
padding: 0 5px;
|
||||
width: 40px;
|
||||
}
|
||||
.interface-item{
|
||||
display: inline
|
||||
}
|
||||
|
||||
.interface-delete-icon{
|
||||
position: absolute;
|
||||
|
@ -6,7 +6,7 @@ import { Subnav } from '../../components/index'
|
||||
import { getProject } from '../../reducer/modules/project';
|
||||
import Interface from './Interface/Interface.js'
|
||||
import Activity from './Activity/Activity.js'
|
||||
import { Setting } from './Setting/Setting.js'
|
||||
import Setting from './Setting/Setting.js'
|
||||
|
||||
|
||||
@connect(
|
||||
@ -43,7 +43,7 @@ export default class Project extends Component {
|
||||
default={'动态'}
|
||||
data={[{
|
||||
name: '接口',
|
||||
path: `/project/${match.params.id}/interface`
|
||||
path: `/project/${match.params.id}/interface/api`
|
||||
}, {
|
||||
name: '设置',
|
||||
path: `/project/${match.params.id}/setting`
|
||||
@ -54,7 +54,7 @@ export default class Project extends Component {
|
||||
<Switch>
|
||||
<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/interface/:action" component={Interface} />
|
||||
<Route path="/project/:id/setting" component={Setting} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
@ -0,0 +1,17 @@
|
||||
import React, { Component } from 'react'
|
||||
|
||||
class Setting extends Component {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<div className="g-row">
|
||||
<section className="news-box">
|
||||
t额st
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Setting
|
@ -1,6 +1,7 @@
|
||||
import { message } from 'antd';
|
||||
|
||||
export default () => next => action => {
|
||||
if(!action) return;
|
||||
if (action.error) {
|
||||
message.error((action.payload && action.payload.message) || '服务器错误');
|
||||
} else if (action.payload && action.payload.data && action.payload.data.errcode && action.payload.data.errcode !== 40011) {
|
||||
|
@ -5,7 +5,9 @@ const FETCH_GROUP_LIST = 'yapi/group/FETCH_GROUP_LIST';
|
||||
const SET_CURR_GROUP = 'yapi/group/SET_CURR_GROUP';
|
||||
const FETCH_GROUP_MEMBER = 'yapi/group/FETCH_GROUP_MEMBER';
|
||||
const FETCH_GROUP_MSG = 'yapi/group/FETCH_GROUP_MSG';
|
||||
const ADD_FROUP_MEMBER = 'yapi/group/ADD_FROUP_MEMBER';
|
||||
const ADD_GROUP_MEMBER = 'yapi/group/ADD_GROUP_MEMBER';
|
||||
const DEL_GROUP_MEMBER = 'yapi/group/DEL_GROUP_MEMBER';
|
||||
const CHANGE_GROUP_MEMBER = 'yapi/group/CHANGE_GROUP_MEMBER';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
@ -57,14 +59,30 @@ export function fetchGroupMsg(id) {
|
||||
}
|
||||
}
|
||||
|
||||
// 添加项目分组成员
|
||||
// 添加分组成员
|
||||
export function addMember(param) {
|
||||
return {
|
||||
type: ADD_FROUP_MEMBER,
|
||||
type: ADD_GROUP_MEMBER,
|
||||
payload: axios.post('/api/group/add_member', param)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分组成员
|
||||
export function delMember(param) {
|
||||
return {
|
||||
type: DEL_GROUP_MEMBER,
|
||||
payload: axios.post('/api/group/del_member', param)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改分组成员权限
|
||||
export function changeMemberRole(param) {
|
||||
return {
|
||||
type: CHANGE_GROUP_MEMBER,
|
||||
payload: axios.post('/api/group/change_member_role', param)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分组成员列表
|
||||
export function fetchGroupMemberList(id) {
|
||||
return {
|
||||
|
@ -2,7 +2,6 @@ import axios from 'axios'
|
||||
// Actions
|
||||
const FETCH_INTERFACE_DATA = 'yapi/interface/FETCH_INTERFACE_DATA';
|
||||
const FETCH_INTERFACE_LIST = 'yapi/interface/FETCH_INTERFACE_LIST';
|
||||
const CHANGE_INTERFACE_ID = 'yapi/interface/CHANGE_INTERFACE_ID';
|
||||
const ADD_INTERFACE_DATA = 'yapi/interface/ADD_INTERFACE_DATA';
|
||||
const DELETE_INTERFACE_DATA = 'yapi/interface/DELETE_INTERFACE_DATA';
|
||||
const UPDATE_INTERFACE_DATA = 'yapi/interface/UPDATE_INTERFACE_DATA';
|
||||
@ -11,7 +10,6 @@ const UPDATE_INTERFACE_DATA = 'yapi/interface/UPDATE_INTERFACE_DATA';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
interfaceId: 0,
|
||||
curdata: {},
|
||||
list: []
|
||||
}
|
||||
@ -26,20 +24,17 @@ export default (state = initialState, action) => {
|
||||
case DELETE_INTERFACE_DATA:
|
||||
return (() => {
|
||||
|
||||
let newlist = state.list.filter(data => data._id !== action.payload), newid, curdata;
|
||||
let newlist = state.list.filter(data => data._id !== action.payload), curdata;
|
||||
|
||||
if (state.interfaceId === action.payload && state.list.length > 0) {
|
||||
newid = state.list[0]._id
|
||||
if (state.list.length > 0) {
|
||||
curdata = state.list[0]
|
||||
} else if (state.list.length == 0) {
|
||||
newid = 0;
|
||||
curdata = {}
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
curdata: curdata,
|
||||
interfaceId: newid,
|
||||
list: newlist
|
||||
}
|
||||
})()
|
||||
@ -48,13 +43,7 @@ export default (state = initialState, action) => {
|
||||
return {
|
||||
...state,
|
||||
curdata: action.payload,
|
||||
list: [].concat(state.list, action.payload),
|
||||
interfaceId: action.payload._id
|
||||
}
|
||||
case CHANGE_INTERFACE_ID:
|
||||
return {
|
||||
...state,
|
||||
interfaceId: action.payload
|
||||
list: [].concat(state.list, action.payload)
|
||||
}
|
||||
case FETCH_INTERFACE_DATA:
|
||||
return {
|
||||
@ -65,20 +54,13 @@ export default (state = initialState, action) => {
|
||||
return {
|
||||
...state,
|
||||
list: action.payload.data,
|
||||
curdata: action.payload.data.length > 0 ? action.payload.data[0] : {}
|
||||
curdata: {}
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export function changeInterfaceId(id) {
|
||||
return {
|
||||
type: CHANGE_INTERFACE_ID,
|
||||
payload: id
|
||||
}
|
||||
}
|
||||
|
||||
export function updateInterfaceData(updata) {
|
||||
|
||||
return {
|
||||
@ -94,13 +76,14 @@ export async function deleteInterfaceData(id) {
|
||||
await axios.post('/api/interface/del', { id: id })
|
||||
return {
|
||||
type: DELETE_INTERFACE_DATA,
|
||||
payload: id
|
||||
payload: true
|
||||
}
|
||||
}
|
||||
|
||||
// Action Creators
|
||||
export async function fetchInterfaceData(interfaceId) {
|
||||
let result = await axios.get('/api/interface/get?id=' + interfaceId);
|
||||
|
||||
return {
|
||||
type: FETCH_INTERFACE_DATA,
|
||||
payload: result.data
|
||||
|
@ -59,11 +59,13 @@
|
||||
"koa-bodyparser": "^3.2.0",
|
||||
"koa-logger": "^3.0.0",
|
||||
"koa-mysql-session": "0.0.2",
|
||||
"koa-route": "^3.2.0",
|
||||
"koa-router": "^7.0.1",
|
||||
"koa-send": "^3.2.0",
|
||||
"koa-session-minimal": "^3.0.3",
|
||||
"koa-static": "^3.0.0",
|
||||
"koa-views": "^5.2.0",
|
||||
"koa-websocket": "^4.0.0",
|
||||
"mock": "^0.1.1",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"moment": "^2.18.1",
|
||||
|
@ -7,9 +7,12 @@ import Koa from 'koa';
|
||||
import koaStatic from 'koa-static';
|
||||
import bodyParser from 'koa-bodyparser';
|
||||
import router from './router.js';
|
||||
import websockify from 'koa-websocket';
|
||||
import websocket from './websocket.js'
|
||||
|
||||
|
||||
yapi.connect = dbModule.connect();
|
||||
const app = new Koa();
|
||||
const app = websockify(new Koa());
|
||||
let indexFile = process.argv[2] === 'dev' ? 'dev.html' : 'index.html';
|
||||
|
||||
|
||||
@ -18,7 +21,7 @@ app.use(bodyParser());
|
||||
app.use(router.routes());
|
||||
app.use(router.allowedMethods());
|
||||
|
||||
|
||||
websocket(app);
|
||||
|
||||
app.use( async (ctx, next) => {
|
||||
if( /^\/(?!api)[a-zA-Z0-9\/\-]*$/.test(ctx.path) ){
|
||||
|
@ -127,6 +127,7 @@ class groupController extends baseController {
|
||||
* @foldnumber 10
|
||||
* @param {String} id 项目分组id
|
||||
* @param {String} member_uid 项目分组成员uid
|
||||
* @param {String} role 成员角色,owner or dev
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
@ -144,11 +145,13 @@ class groupController extends baseController {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '分组id不能为空');
|
||||
}
|
||||
|
||||
params.role = params.role === 'owner' ? 'owner' : '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);
|
||||
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
|
||||
if (groupUserdata === null) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '组长uid不存在')
|
||||
}
|
||||
|
@ -304,6 +304,21 @@ class interfaceController extends baseController {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
async solveConflict(ctx) {
|
||||
let id = parseInt(ctx.query.id, 10);
|
||||
if(!id) return ctx.websocket.send("id 参数有误");
|
||||
|
||||
ctx.websocket.send('Hello World');
|
||||
ctx.websocket.on('message', function (message) {
|
||||
// do something with the message from client
|
||||
console.log(message);
|
||||
});
|
||||
|
||||
ctx.websocket.on('close', function(){
|
||||
console.log('websocket: close')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = interfaceController;
|
@ -147,7 +147,9 @@ class projectController extends baseController {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员已存在');
|
||||
}
|
||||
|
||||
let userdata = await this.getUserdata(params.member_uid);
|
||||
params.role = params.role === 'owner' ? 'owner' : 'dev';
|
||||
|
||||
let userdata = await this.getUserdata(params.member_uid, params.role);
|
||||
if(userdata === null){
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '成员uid不存在')
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ class interfaceModel extends baseModel {
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
project_id: { type: Number, required: true },
|
||||
edit_uid: {type: Number, default: 0},
|
||||
status: {type: String, enum: ['undone', 'done'], default: 'undone'},
|
||||
desc: String,
|
||||
add_time: Number,
|
||||
|
@ -19,6 +19,9 @@ class interfaceCase extends baseModel {
|
||||
domain: {type: String },
|
||||
path: { type: String },
|
||||
method: { type: String },
|
||||
req_params: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_query: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
|
23
server/websocket.js
Normal file
23
server/websocket.js
Normal file
@ -0,0 +1,23 @@
|
||||
import koaRouter from 'koa-router';
|
||||
const route = require('koa-route');
|
||||
import interfaceController from './controllers/interface.js';
|
||||
|
||||
|
||||
function websocket(app) {
|
||||
console.log('load websocket...')
|
||||
app.ws.use(function (ctx, next) {
|
||||
return next(ctx);
|
||||
});
|
||||
app.ws.use(route.all('/api/interface/solve_conflict', async function (ctx) {
|
||||
let inst = new interfaceController(ctx);
|
||||
await inst.init(ctx);
|
||||
if (inst.$auth === true) {
|
||||
await inst.solveConflict.call(inst, ctx);
|
||||
} else {
|
||||
ctx.ws.send('请登录...');
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
module.exports = websocket
|
@ -40,13 +40,21 @@ var _router = require('./router.js');
|
||||
|
||||
var _router2 = _interopRequireDefault(_router);
|
||||
|
||||
var _koaWebsocket = require('koa-websocket');
|
||||
|
||||
var _koaWebsocket2 = _interopRequireDefault(_koaWebsocket);
|
||||
|
||||
var _websocket = require('./websocket.js');
|
||||
|
||||
var _websocket2 = _interopRequireDefault(_websocket);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
_yapi2.default.commons = _commons2.default;
|
||||
|
||||
|
||||
_yapi2.default.connect = _db2.default.connect();
|
||||
var app = new _koa2.default();
|
||||
var app = (0, _koaWebsocket2.default)(new _koa2.default());
|
||||
var indexFile = process.argv[2] === 'dev' ? 'dev.html' : 'index.html';
|
||||
|
||||
app.use(_mockServer2.default);
|
||||
@ -54,6 +62,8 @@ app.use((0, _koaBodyparser2.default)());
|
||||
app.use(_router2.default.routes());
|
||||
app.use(_router2.default.allowedMethods());
|
||||
|
||||
(0, _websocket2.default)(app);
|
||||
|
||||
app.use(function () {
|
||||
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx, next) {
|
||||
return _regenerator2.default.wrap(function _callee$(_context) {
|
||||
|
@ -325,6 +325,7 @@ var groupController = function (_baseController) {
|
||||
* @foldnumber 10
|
||||
* @param {String} id 项目分组id
|
||||
* @param {String} member_uid 项目分组成员uid
|
||||
* @param {String} role 成员角色,owner or dev
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
@ -357,66 +358,69 @@ var groupController = function (_baseController) {
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '分组id不能为空'));
|
||||
|
||||
case 6:
|
||||
_context4.next = 8;
|
||||
|
||||
params.role = params.role === 'owner' ? 'owner' : 'dev';
|
||||
|
||||
_context4.next = 9;
|
||||
return groupInst.checkMemberRepeat(params.id, params.member_uid);
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
check = _context4.sent;
|
||||
|
||||
if (!(check > 0)) {
|
||||
_context4.next = 11;
|
||||
_context4.next = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '成员已存在'));
|
||||
|
||||
case 11:
|
||||
_context4.next = 13;
|
||||
return this.getUserdata(params.member_uid);
|
||||
case 12:
|
||||
_context4.next = 14;
|
||||
return this.getUserdata(params.member_uid, params.role);
|
||||
|
||||
case 13:
|
||||
case 14:
|
||||
groupUserdata = _context4.sent;
|
||||
|
||||
if (!(groupUserdata === null)) {
|
||||
_context4.next = 16;
|
||||
_context4.next = 17;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '组长uid不存在'));
|
||||
|
||||
case 16:
|
||||
case 17:
|
||||
if (!(groupUserdata._role === 'admin')) {
|
||||
_context4.next = 18;
|
||||
_context4.next = 19;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '不能邀请管理员'));
|
||||
|
||||
case 18:
|
||||
case 19:
|
||||
delete groupUserdata._role;
|
||||
_context4.prev = 19;
|
||||
_context4.next = 22;
|
||||
_context4.prev = 20;
|
||||
_context4.next = 23;
|
||||
return groupInst.addMember(params.id, groupUserdata);
|
||||
|
||||
case 22:
|
||||
case 23:
|
||||
result = _context4.sent;
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context4.next = 29;
|
||||
_context4.next = 30;
|
||||
break;
|
||||
|
||||
case 26:
|
||||
_context4.prev = 26;
|
||||
_context4.t0 = _context4['catch'](19);
|
||||
case 27:
|
||||
_context4.prev = 27;
|
||||
_context4.t0 = _context4['catch'](20);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context4.t0.message);
|
||||
|
||||
case 29:
|
||||
case 30:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this, [[19, 26]]);
|
||||
}, _callee4, this, [[20, 27]]);
|
||||
}));
|
||||
|
||||
function addMember(_x5) {
|
||||
|
@ -589,6 +589,50 @@ var interfaceController = function (_baseController) {
|
||||
|
||||
return del;
|
||||
}()
|
||||
}, {
|
||||
key: 'solveConflict',
|
||||
value: function () {
|
||||
var _ref6 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee6(ctx) {
|
||||
var id;
|
||||
return _regenerator2.default.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
id = parseInt(ctx.query.id, 10);
|
||||
|
||||
if (id) {
|
||||
_context6.next = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context6.abrupt('return', ctx.websocket.send("id 参数有误"));
|
||||
|
||||
case 3:
|
||||
|
||||
ctx.websocket.send('Hello World');
|
||||
ctx.websocket.on('message', function (message) {
|
||||
// do something with the message from client
|
||||
console.log(message);
|
||||
});
|
||||
|
||||
ctx.websocket.on('close', function () {
|
||||
console.log('websocket: close');
|
||||
});
|
||||
|
||||
case 6:
|
||||
case 'end':
|
||||
return _context6.stop();
|
||||
}
|
||||
}
|
||||
}, _callee6, this);
|
||||
}));
|
||||
|
||||
function solveConflict(_x6) {
|
||||
return _ref6.apply(this, arguments);
|
||||
}
|
||||
|
||||
return solveConflict;
|
||||
}()
|
||||
}]);
|
||||
return interfaceController;
|
||||
}(_base2.default);
|
||||
|
@ -319,31 +319,34 @@ var projectController = function (_baseController) {
|
||||
return _context2.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '项目成员已存在'));
|
||||
|
||||
case 15:
|
||||
_context2.next = 17;
|
||||
return this.getUserdata(params.member_uid);
|
||||
|
||||
case 17:
|
||||
params.role = params.role === 'owner' ? 'owner' : 'dev';
|
||||
|
||||
_context2.next = 18;
|
||||
return this.getUserdata(params.member_uid, params.role);
|
||||
|
||||
case 18:
|
||||
userdata = _context2.sent;
|
||||
|
||||
if (!(userdata === null)) {
|
||||
_context2.next = 20;
|
||||
_context2.next = 21;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context2.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '成员uid不存在'));
|
||||
|
||||
case 20:
|
||||
_context2.prev = 20;
|
||||
_context2.next = 23;
|
||||
case 21:
|
||||
_context2.prev = 21;
|
||||
_context2.next = 24;
|
||||
return this.Model.addMember(params.id, userdata);
|
||||
|
||||
case 23:
|
||||
case 24:
|
||||
result = _context2.sent;
|
||||
username = this.getUsername();
|
||||
_context2.next = 27;
|
||||
_context2.next = 28;
|
||||
return this.Model.get(params.id);
|
||||
|
||||
case 27:
|
||||
case 28:
|
||||
project = _context2.sent;
|
||||
|
||||
_yapi2.default.commons.saveLog({
|
||||
@ -356,21 +359,21 @@ var projectController = function (_baseController) {
|
||||
icon: project.icon
|
||||
});
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context2.next = 35;
|
||||
_context2.next = 36;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
_context2.prev = 32;
|
||||
_context2.t1 = _context2['catch'](20);
|
||||
case 33:
|
||||
_context2.prev = 33;
|
||||
_context2.t1 = _context2['catch'](21);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context2.t1.message);
|
||||
|
||||
case 35:
|
||||
case 36:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, this, [[20, 32]]);
|
||||
}, _callee2, this, [[21, 33]]);
|
||||
}));
|
||||
|
||||
function addMember(_x2) {
|
||||
|
@ -52,6 +52,7 @@ var interfaceModel = function (_baseModel) {
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
project_id: { type: Number, required: true },
|
||||
edit_uid: { type: Number, default: 0 },
|
||||
status: { type: String, enum: ['undone', 'done'], default: 'undone' },
|
||||
desc: String,
|
||||
add_time: Number,
|
||||
|
@ -58,6 +58,9 @@ var interfaceCase = function (_baseModel) {
|
||||
domain: { type: String },
|
||||
path: { type: String },
|
||||
method: { type: String },
|
||||
req_params: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_query: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
|
70
server_dist/websocket.js
Normal file
70
server_dist/websocket.js
Normal file
@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
|
||||
var _regenerator = require('babel-runtime/regenerator');
|
||||
|
||||
var _regenerator2 = _interopRequireDefault(_regenerator);
|
||||
|
||||
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
|
||||
|
||||
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
|
||||
|
||||
var _koaRouter = require('koa-router');
|
||||
|
||||
var _koaRouter2 = _interopRequireDefault(_koaRouter);
|
||||
|
||||
var _interface = require('./controllers/interface.js');
|
||||
|
||||
var _interface2 = _interopRequireDefault(_interface);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var route = require('koa-route');
|
||||
|
||||
|
||||
function websocket(app) {
|
||||
console.log('load websocket...');
|
||||
app.ws.use(function (ctx, next) {
|
||||
return next(ctx);
|
||||
});
|
||||
app.ws.use(route.all('/api/interface/solve_conflict', function () {
|
||||
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx) {
|
||||
var inst;
|
||||
return _regenerator2.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
inst = new _interface2.default(ctx);
|
||||
_context.next = 3;
|
||||
return inst.init(ctx);
|
||||
|
||||
case 3:
|
||||
if (!(inst.$auth === true)) {
|
||||
_context.next = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 6;
|
||||
return inst.solveConflict.call(inst, ctx);
|
||||
|
||||
case 6:
|
||||
_context.next = 9;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ctx.ws.send('请登录...');
|
||||
|
||||
case 9:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this);
|
||||
}));
|
||||
|
||||
return function (_x) {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
}()));
|
||||
}
|
||||
|
||||
module.exports = websocket;
|
Loading…
Reference in New Issue
Block a user