yapi/client/containers/Project/Interface/InterfaceList/InterfaceMenu.js

472 lines
15 KiB
JavaScript
Raw Normal View History

2017-08-11 18:57:58 +08:00
import React, { Component } from 'react'
import { connect } from 'react-redux';
import PropTypes from 'prop-types'
2017-08-19 19:06:09 +08:00
import { fetchInterfaceList, fetchInterfaceData, deleteInterfaceData, deleteInterfaceCatData, initInterface } from '../../../../reducer/modules/interface.js';
2017-08-22 19:46:00 +08:00
import { getProject } from '../../../../reducer/modules/project.js';
import { Input, Icon, Button, Modal, message, Tree, Tooltip } from 'antd';
import AddInterfaceForm from './AddInterfaceForm';
2017-08-19 19:06:09 +08:00
import AddInterfaceCatForm from './AddInterfaceCatForm';
import axios from 'axios'
2017-08-18 11:05:33 +08:00
import { Link, withRouter } from 'react-router-dom';
const confirm = Modal.confirm;
2017-08-18 20:35:31 +08:00
const TreeNode = Tree.TreeNode;
2017-08-11 18:57:58 +08:00
@connect(
2017-09-14 16:58:54 +08:00
2017-08-11 18:57:58 +08:00
state => {
return {
list: state.inter.list,
2017-08-18 11:05:33 +08:00
inter: state.inter.curdata,
2017-08-31 20:43:38 +08:00
curProject: state.project.currProject,
expands: []
2017-08-11 18:57:58 +08:00
}
},
{
fetchInterfaceList,
fetchInterfaceData,
2017-08-19 19:06:09 +08:00
deleteInterfaceCatData,
deleteInterfaceData,
2017-08-22 19:46:00 +08:00
initInterface,
getProject
2017-08-11 18:57:58 +08:00
}
)
class InterfaceMenu extends Component {
static propTypes = {
2017-08-16 18:04:16 +08:00
match: PropTypes.object,
2017-08-18 11:05:33 +08:00
inter: PropTypes.object,
2017-08-11 18:57:58 +08:00
projectId: PropTypes.string,
list: PropTypes.array,
fetchInterfaceList: PropTypes.func,
curProject: PropTypes.object,
fetchInterfaceData: PropTypes.func,
addInterfaceData: PropTypes.func,
2017-08-16 18:04:16 +08:00
deleteInterfaceData: PropTypes.func,
2017-08-19 19:06:09 +08:00
initInterface: PropTypes.func,
history: PropTypes.object,
2017-08-22 19:46:00 +08:00
router: PropTypes.object,
getProject: PropTypes.func
}
2017-08-19 19:06:09 +08:00
/**
* @param {String} key
2017-08-19 19:06:09 +08:00
*/
changeModal = (key, status) => {
//visible add_cat_modal_visible change_cat_modal_visible del_cat_modal_visible
let newState = {}
newState[key] = status
this.setState(newState);
}
handleCancel = () => {
this.setState({
visible: false
});
}
2017-08-11 18:57:58 +08:00
constructor(props) {
super(props)
this.state = {
curKey: null,
visible: false,
delIcon: null,
2017-08-19 19:06:09 +08:00
curCatid: null,
add_cat_modal_visible: false,
change_cat_modal_visible: false,
del_cat_modal_visible: false,
2017-08-31 20:43:38 +08:00
curCatdata: {},
expands: null,
list: []
}
}
2017-09-07 15:48:24 +08:00
handleRequest() {
2017-08-19 19:06:09 +08:00
this.props.initInterface()
2017-09-07 15:48:24 +08:00
this.getList()
}
async getList(){
let r = await this.props.fetchInterfaceList(this.props.projectId);
this.setState({
2017-09-07 15:48:24 +08:00
list: JSON.parse(JSON.stringify(r.payload.data))
})
}
componentWillMount() {
this.handleRequest()
}
2017-08-17 16:10:34 +08:00
componentWillReceiveProps(nextProps){
if (this.props.list !== nextProps.list) {
this.setState({
list: nextProps.list
})
}
}
2017-08-17 16:10:34 +08:00
2017-08-21 21:18:29 +08:00
onSelect = (selectedKeys) => {
2017-08-24 12:16:43 +08:00
const { history, match } = this.props;
2017-08-21 21:18:29 +08:00
let curkey = selectedKeys[0];
2017-08-24 12:16:43 +08:00
if (!curkey || !selectedKeys) return false;
2017-08-21 21:18:29 +08:00
let basepath = "/project/" + match.params.id + "/interface/api";
2017-08-24 12:16:43 +08:00
if (curkey === 'root') {
2017-08-21 21:18:29 +08:00
history.push(basepath)
2017-08-24 12:16:43 +08:00
} else {
2017-08-21 21:18:29 +08:00
history.push(basepath + '/' + curkey)
}
2017-08-31 20:43:38 +08:00
this.setState({
expands: null
})
2017-08-18 20:35:31 +08:00
}
2017-09-15 12:03:22 +08:00
handleAddInterface = (data,cb) => {
data.project_id = this.props.projectId;
axios.post('/api/interface/add', data).then((res) => {
if (res.data.errcode !== 0) {
return message.error(res.data.errmsg);
}
message.success('接口添加成功')
2017-08-25 11:18:29 +08:00
let interfaceId = res.data.data._id;
this.props.history.push("/project/" + this.props.projectId + "/interface/api/" + interfaceId)
2017-09-07 15:48:24 +08:00
this.getList()
this.setState({
visible: false
});
2017-09-15 12:03:22 +08:00
if(cb){
cb();
}
})
2017-08-11 18:57:58 +08:00
}
2017-08-19 19:06:09 +08:00
handleAddInterfaceCat = (data) => {
data.project_id = this.props.projectId;
axios.post('/api/interface/add_cat', data).then((res) => {
if (res.data.errcode !== 0) {
return message.error(res.data.errmsg);
}
message.success('接口分类添加成功')
2017-09-07 15:48:24 +08:00
this.getList()
2017-08-22 19:46:00 +08:00
this.props.getProject(data.project_id)
2017-08-19 19:06:09 +08:00
this.setState({
add_cat_modal_visible: false
});
})
}
handleChangeInterfaceCat = (data) => {
let params = {
catid: this.state.curCatdata._id,
name: data.name
}
axios.post('/api/interface/up_cat', params).then((res) => {
if (res.data.errcode !== 0) {
return message.error(res.data.errmsg);
}
message.success('接口分类更新成功')
2017-09-07 15:48:24 +08:00
this.getList()
2017-08-19 19:06:09 +08:00
this.setState({
change_cat_modal_visible: false
});
})
}
2017-08-18 11:05:33 +08:00
showConfirm = (id) => {
let that = this;
2017-08-21 21:18:29 +08:00
const ref = confirm({
title: '您确认删除此接口',
content: '温馨提示:接口删除后,无法恢复',
2017-08-19 19:06:09 +08:00
async onOk() {
2017-09-14 16:58:54 +08:00
2017-08-19 19:06:09 +08:00
await that.props.deleteInterfaceData(id, that.props.projectId)
2017-09-07 15:48:24 +08:00
await that.getList()
2017-08-21 21:18:29 +08:00
ref.destroy()
2017-09-07 15:48:24 +08:00
that.props.history.push('/project/' + that.props.match.params.id + '/interface/api')
2017-09-14 16:58:54 +08:00
},
2017-09-25 16:07:44 +08:00
onCancel() {
2017-08-21 21:18:29 +08:00
ref.destroy()
}
});
}
2017-08-19 19:06:09 +08:00
showDelCatConfirm = (catid) => {
let that = this;
2017-08-21 21:18:29 +08:00
const ref = confirm({
2017-08-19 19:06:09 +08:00
title: '您确认删除此接口分类',
content: '温馨提示:该操作会删除该分类下所有接口,接口删除后无法恢复',
async onOk() {
await that.props.deleteInterfaceCatData(catid, that.props.projectId)
2017-09-07 15:48:24 +08:00
await that.getList()
2017-08-21 21:18:29 +08:00
that.props.history.push('/project/' + that.props.match.params.id + '/interface/api')
ref.destroy()
2017-08-19 19:06:09 +08:00
},
onCancel() { }
});
}
2017-09-19 20:32:53 +08:00
copyInterface = (data) => {
data.title = data.title + '_copy';
data.path = data.path + '_' + Date.now();
axios.post('/api/interface/add', data).then((res) => {
if (res.data.errcode !== 0) {
return message.error(res.data.errmsg);
}
message.success('接口添加成功')
let interfaceId = res.data.data._id;
this.props.history.push("/project/" + this.props.projectId + "/interface/api/" + interfaceId)
this.getList()
this.setState({
visible: false
});
})
}
2017-08-18 20:35:31 +08:00
enterItem = (id) => {
this.setState({ delIcon: id })
}
leaveItem = () => {
this.setState({ delIcon: null })
}
onFilter = (e) => {
this.setState({
filter: e.target.value,
list: JSON.parse(JSON.stringify(this.props.list))
})
2017-08-11 18:57:58 +08:00
}
2017-08-31 20:43:38 +08:00
onExpand = (e)=>{
this.setState({
expands: e
})
}
2017-08-18 11:05:33 +08:00
2017-08-11 18:57:58 +08:00
render() {
2017-08-16 18:04:16 +08:00
const matchParams = this.props.match.params;
let menuList = this.state.list;
const searchBox = <div className="interface-filter">
2017-09-20 21:20:20 +08:00
<Input onChange={this.onFilter} value={this.state.filter} placeholder="搜索接口" />
2017-09-21 10:24:52 +08:00
<Button type="primary" onClick={() => this.changeModal('add_cat_modal_visible', true)} className="btn-filter" >添加分类</Button>
<Modal
title="添加接口"
visible={this.state.visible}
onCancel={() => this.changeModal('visible', false)}
footer={null}
>
<AddInterfaceForm catdata={this.props.curProject.cat} catid={this.state.curCatid} onCancel={() => this.changeModal('visible', false)} onSubmit={this.handleAddInterface} />
</Modal>
<Modal
title="添加分类"
visible={this.state.add_cat_modal_visible}
onCancel={() => this.changeModal('add_cat_modal_visible', false)}
footer={null}
>
<AddInterfaceCatForm onCancel={() => this.changeModal('add_cat_modal_visible', false)} onSubmit={this.handleAddInterfaceCat} />
</Modal>
<Modal
title="修改分类"
visible={this.state.change_cat_modal_visible}
2017-09-14 16:58:54 +08:00
onCancel={() => this.changeModal('change_cat_modal_visible', false)}
footer={null}
>
<AddInterfaceCatForm catdata={this.state.curCatdata} onCancel={() => this.changeModal('change_cat_modal_visible', false)} onSubmit={this.handleChangeInterfaceCat} />
</Modal>
</div>
2017-08-31 20:43:38 +08:00
if(menuList.length === 0){
return searchBox;
2017-08-31 20:43:38 +08:00
}
2017-08-24 12:16:43 +08:00
const defaultExpandedKeys = () => {
const { router, inter, list } = this.props, rNull = { expands: [], selects: [] };
2017-08-31 20:43:38 +08:00
if (list.length === 0){
return rNull;
}
2017-08-24 12:16:43 +08:00
if (router) {
if (!isNaN(router.params.actionId)) {
if (!inter || !inter._id) {
2017-08-31 20:43:38 +08:00
return rNull;
}
2017-08-24 12:16:43 +08:00
return {
2017-08-31 20:43:38 +08:00
expands: this.state.expands ?this.state.expands : ['cat_' + inter.catid],
2017-08-24 12:16:43 +08:00
selects: [inter._id + ""]
}
} else {
let catid = router.params.actionId.substr(4);
return {
2017-08-31 20:43:38 +08:00
expands: this.state.expands ?this.state.expands :['cat_' + catid],
2017-08-24 12:16:43 +08:00
selects: ['cat_' + catid]
}
}
} else {
return {
2017-08-31 20:43:38 +08:00
expands: this.state.expands ?this.state.expands :['cat_' + list[0]._id],
2017-08-24 12:16:43 +08:00
selects: ['root']
}
}
2017-08-24 12:16:43 +08:00
}
const item_interface_create = (item) => {
2017-09-04 13:44:38 +08:00
// let color;
// switch (item.method) {
// case 'GET': color = "green"; break;
// case 'POST': color = "blue"; break;
// case 'PUT': color = "yellow"; break;
// case 'DELETE': color = 'red'; break;
// default: color = "yellow";
// }
// const menu = (item) => {
// return <Menu>
// <Menu.Item>
// <span onClick={() => { this.showConfirm(item._id) }}>删除接口</span>
// </Menu.Item>
// <Menu.Item>
// <span onClick={() => {
// this.copyInterface(item)
// }}>复制接口</span>
// </Menu.Item>
// </Menu>
// };
2017-09-19 20:32:53 +08:00
2017-09-14 16:58:54 +08:00
return <TreeNode
title={<div className="container-title" onMouseEnter={() => this.enterItem(item._id)} onMouseLeave={this.leaveItem} >
2017-09-04 13:44:38 +08:00
<Link className="interface-item" to={"/project/" + matchParams.id + "/interface/api/" + item._id} >{item.title}</Link>
<div className="btns">
<Tooltip title="删除接口">
<Icon type='delete' className="interface-delete-icon" onClick={(e) => { e.stopPropagation();this.showConfirm(item._id) }} style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} />
</Tooltip>
<Tooltip title="复制接口">
<Icon type='copy' className="interface-delete-icon" onClick={(e) => { e.stopPropagation();this.copyInterface(item) }} style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} />
</Tooltip>
</div>
{/*<Dropdown overlay={menu(item)} trigger={['click']} onClick={e => e.stopPropagation()}>
2017-09-19 20:32:53 +08:00
<Icon type='ellipsis' className="interface-delete-icon" style={{ opacity: this.state.delIcon == item._id ? 1 : 0 }}/>
</Dropdown>*/}
2017-08-18 20:35:31 +08:00
</div>}
key={'' + item._id} />
2017-08-18 20:35:31 +08:00
}
2017-08-16 18:04:16 +08:00
// const menu = (item) => {
// return <Menu>
// <Menu.Item>
// <span onClick={() => {
// this.changeModal('visible', true);
// this.setState({
// curCatid: item._id
// })
// }}>添加接口</span>
// </Menu.Item>
// <Menu.Item>
// <span onClick={() => {
// this.changeModal('change_cat_modal_visible', true);
// this.setState({
// curCatdata: item
// })
// }}>修改分类</span>
// </Menu.Item>
// <Menu.Item>
// <span onClick={() => {
// this.showDelCatConfirm(item._id)
// }}>删除分类</span>
// </Menu.Item>
// </Menu>
// };
2017-08-19 19:06:09 +08:00
2017-08-24 12:16:43 +08:00
let currentKes = defaultExpandedKeys();
2017-09-14 16:58:54 +08:00
2017-08-24 12:16:43 +08:00
if (this.state.filter) {
let arr = [];
menuList = menuList.filter( (item) => {
let interfaceFilter = false;
if (item.name.indexOf(this.state.filter) === -1) {
item.list = item.list.filter(inter=>{
if(inter.title.indexOf(this.state.filter) === -1 && inter.path.indexOf(this.state.filter)){
2017-09-14 16:58:54 +08:00
return false;
}
//arr.push('cat_' + inter.catid)
interfaceFilter = true;
return true;
2017-09-14 16:58:54 +08:00
})
return interfaceFilter === true
2017-08-19 19:06:09 +08:00
}
2017-08-24 12:16:43 +08:00
arr.push('cat_' + item._id)
return true;
})
if(arr.length > 0){
currentKes.expands = arr;
2017-08-19 19:06:09 +08:00
}
}
2017-08-11 18:57:58 +08:00
return <div>
{searchBox}
2017-08-24 12:16:43 +08:00
{menuList.length > 0 ?
2017-08-18 20:35:31 +08:00
<Tree
className="interface-list"
2017-08-24 20:58:30 +08:00
defaultExpandedKeys={currentKes.expands}
defaultSelectedKeys={currentKes.selects}
2017-08-31 20:43:38 +08:00
expandedKeys={currentKes.expands}
selectedKeys={currentKes.selects}
2017-08-18 20:35:31 +08:00
onSelect={this.onSelect}
2017-08-31 20:43:38 +08:00
onExpand={this.onExpand}
2017-08-18 20:35:31 +08:00
>
<TreeNode className="item-all-interface" title={<Link style={{ fontSize: '14px' }} to={"/project/" + matchParams.id + "/interface/api"}><Icon type="folder" style={{ marginRight: 5 }} />全部接口</Link>} key="root" />
2017-08-24 12:16:43 +08:00
{menuList.map((item) => {
return <TreeNode title={<div className="container-title" onMouseEnter={() => this.enterItem(item._id)} onMouseLeave={this.leaveItem} >
2017-08-19 19:06:09 +08:00
<Link className="interface-item" to={"/project/" + matchParams.id + "/interface/api/cat_" + item._id} ><Icon type="folder-open" style={{ marginRight: 5 }} />{item.name}</Link>
<div className="btns">
<Tooltip title="删除集合">
<Icon type='delete' className="interface-delete-icon" onClick={(e) => { e.stopPropagation();this.showDelCatConfirm(item._id) }} style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }}/>
</Tooltip>
<Tooltip title="编辑集合">
<Icon type='edit' className="interface-delete-icon" style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} onClick={(e) => {
e.stopPropagation();
this.changeModal('change_cat_modal_visible', true);
this.setState({
curCatdata: item
})
}} />
</Tooltip>
<Tooltip title="添加集合">
<Icon type='plus' className="interface-delete-icon" style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} onClick={(e) => {
e.stopPropagation();
this.changeModal('visible', true);
this.setState({
curCatid: item._id
});
}} />
</Tooltip>
</div>
{/*<Dropdown overlay={menu(item)} trigger={['click']} onClick={e => e.stopPropagation()}>
2017-09-19 17:59:36 +08:00
<Icon type='ellipsis' className="interface-delete-icon" />
</Dropdown>*/}
2017-08-31 14:37:43 +08:00
</div>}
2017-09-14 16:58:54 +08:00
key={'cat_' + item._id}
className={`interface-item-nav ${item.list.length?"":"cat_switch_hidden"}`}
2017-08-31 14:37:43 +08:00
>
2017-08-18 20:35:31 +08:00
{item.list.map(item_interface_create)}
</TreeNode>
})}
</Tree>
: null}
2017-08-11 18:57:58 +08:00
</div>
2017-08-11 17:25:57 +08:00
2017-08-11 18:57:58 +08:00
}
}
2017-08-11 17:25:57 +08:00
2017-08-17 16:10:34 +08:00
export default withRouter(InterfaceMenu)