| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- import React, { PureComponent as Component } from 'react';
- import { connect } from 'react-redux';
- import PropTypes from 'prop-types';
- import {
- fetchInterfaceListMenu,
- fetchInterfaceList,
- fetchInterfaceCatList,
- fetchInterfaceData,
- deleteInterfaceData,
- deleteInterfaceCatData,
- initInterface
- } from '../../../../reducer/modules/interface.js';
- import { getProject } from '../../../../reducer/modules/project.js';
- import { Input, Icon, Button, Modal, message, Tree, Tooltip } from 'antd';
- import AddInterfaceForm from './AddInterfaceForm';
- import AddInterfaceCatForm from './AddInterfaceCatForm';
- import axios from 'axios';
- import { Link, withRouter } from 'react-router-dom';
- import produce from 'immer';
- import { arrayChangeIndex } from '../../../../common.js';
- import './interfaceMenu.scss';
- const confirm = Modal.confirm;
- const TreeNode = Tree.TreeNode;
- const headHeight = 240; // menu顶部到网页顶部部分的高度
- @connect(
- state => {
- return {
- list: state.inter.list,
- inter: state.inter.curdata,
- curProject: state.project.currProject,
- expands: []
- };
- },
- {
- fetchInterfaceListMenu,
- fetchInterfaceData,
- deleteInterfaceCatData,
- deleteInterfaceData,
- initInterface,
- getProject,
- fetchInterfaceCatList,
- fetchInterfaceList
- }
- )
- class InterfaceMenu extends Component {
- static propTypes = {
- match: PropTypes.object,
- inter: PropTypes.object,
- projectId: PropTypes.string,
- list: PropTypes.array,
- fetchInterfaceListMenu: PropTypes.func,
- curProject: PropTypes.object,
- fetchInterfaceData: PropTypes.func,
- addInterfaceData: PropTypes.func,
- deleteInterfaceData: PropTypes.func,
- initInterface: PropTypes.func,
- history: PropTypes.object,
- router: PropTypes.object,
- getProject: PropTypes.func,
- fetchInterfaceCatList: PropTypes.func,
- fetchInterfaceList: PropTypes.func
- };
- /**
- * @param {String} key
- */
- 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
- });
- };
- constructor(props) {
- super(props);
- this.state = {
- curKey: null,
- visible: false,
- delIcon: null,
- curCatid: null,
- add_cat_modal_visible: false,
- change_cat_modal_visible: false,
- del_cat_modal_visible: false,
- curCatdata: {},
- expands: null,
- list: []
- };
- }
- handleRequest() {
- this.props.initInterface();
- this.getList();
- }
- async getList() {
- let r = await this.props.fetchInterfaceListMenu(this.props.projectId);
- this.setState({
- list: r.payload.data.data
- });
- }
- componentWillMount() {
- this.handleRequest();
- }
- componentWillReceiveProps(nextProps) {
- if (this.props.list !== nextProps.list) {
- // console.log('next', nextProps.list)
- this.setState({
- list: nextProps.list
- });
- }
- }
- onSelect = selectedKeys => {
- const { history, match } = this.props;
- let curkey = selectedKeys[0];
- if (!curkey || !selectedKeys) {
- return false;
- }
- let basepath = '/project/' + match.params.id + '/interface/api';
- if (curkey === 'root') {
- history.push(basepath);
- } else {
- history.push(basepath + '/' + curkey);
- }
- this.setState({
- expands: null
- });
- };
- changeExpands = () => {
- this.setState({
- expands: null
- });
- };
- 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('接口添加成功');
- let interfaceId = res.data.data._id;
- this.props.history.push('/project/' + this.props.projectId + '/interface/api/' + interfaceId);
- this.getList();
- this.setState({
- visible: false
- });
- if (cb) {
- cb();
- }
- });
- };
- 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('接口分类添加成功');
- this.getList();
- this.props.getProject(data.project_id);
- this.setState({
- add_cat_modal_visible: false
- });
- });
- };
- handleChangeInterfaceCat = data => {
- data.project_id = this.props.projectId;
- let params = {
- catid: this.state.curCatdata._id,
- name: data.name,
- desc: data.desc
- };
- axios.post('/api/interface/up_cat', params).then(res => {
- if (res.data.errcode !== 0) {
- return message.error(res.data.errmsg);
- }
- message.success('接口分类更新成功');
- this.getList();
- this.props.getProject(data.project_id);
- this.setState({
- change_cat_modal_visible: false
- });
- });
- };
- showConfirm = data => {
- let that = this;
- let id = data._id;
- let catid = data.catid;
- const ref = confirm({
- title: '您确认删除此接口????',
- content: '温馨提示:接口删除后,无法恢复',
- okText: '确认',
- cancelText: '取消',
- async onOk() {
- await that.props.deleteInterfaceData(id, that.props.projectId);
- await that.getList();
- await that.props.fetchInterfaceCatList({ catid });
- ref.destroy();
- that.props.history.push(
- '/project/' + that.props.match.params.id + '/interface/api/cat_' + catid
- );
- },
- onCancel() {
- ref.destroy();
- }
- });
- };
- showDelCatConfirm = catid => {
- let that = this;
- const ref = confirm({
- title: '确定删除此接口分类吗?',
- content: '温馨提示:该操作会删除该分类下所有接口,接口删除后无法恢复',
- okText: '确认',
- cancelText: '取消',
- async onOk() {
- await that.props.deleteInterfaceCatData(catid, that.props.projectId);
- await that.getList();
- // await that.props.getProject(that.props.projectId)
- await that.props.fetchInterfaceList({ project_id: that.props.projectId });
- that.props.history.push('/project/' + that.props.match.params.id + '/interface/api');
- ref.destroy();
- },
- onCancel() {}
- });
- };
- copyInterface = async id => {
- let interfaceData = await this.props.fetchInterfaceData(id);
- // let data = JSON.parse(JSON.stringify(interfaceData.payload.data.data));
- // data.title = data.title + '_copy';
- // data.path = data.path + '_' + Date.now();
- let data = interfaceData.payload.data.data;
- let newData = produce(data, draftData => {
- draftData.title = draftData.title + '_copy';
- draftData.path = draftData.path + '_' + Date.now();
- });
- axios.post('/api/interface/add', newData).then(async res => {
- if (res.data.errcode !== 0) {
- return message.error(res.data.errmsg);
- }
- message.success('接口添加成功');
- let interfaceId = res.data.data._id;
- await this.getList();
- this.props.history.push('/project/' + this.props.projectId + '/interface/api/' + interfaceId);
- this.setState({
- visible: false
- });
- });
- };
- 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))
- });
- };
- onExpand = e => {
- this.setState({
- expands: e
- });
- };
- onDrop = async e => {
- const dropCatIndex = e.node.props.pos.split('-')[1] - 1;
- const dragCatIndex = e.dragNode.props.pos.split('-')[1] - 1;
- if (dropCatIndex < 0 || dragCatIndex < 0) {
- return;
- }
- const { list } = this.props;
- const dropCatId = this.props.list[dropCatIndex]._id;
- const id = e.dragNode.props.eventKey;
- const dragCatId = this.props.list[dragCatIndex]._id;
- const dropPos = e.node.props.pos.split('-');
- const dropIndex = Number(dropPos[dropPos.length - 1]);
- const dragPos = e.dragNode.props.pos.split('-');
- const dragIndex = Number(dragPos[dragPos.length - 1]);
- if (id.indexOf('cat') === -1) {
- if (dropCatId === dragCatId) {
- // 同一个分类下的接口交换顺序
- let colList = list[dropCatIndex].list;
- let changes = arrayChangeIndex(colList, dragIndex, dropIndex);
- axios.post('/api/interface/up_index', changes).then();
- } else {
- await axios.post('/api/interface/up', { id, catid: dropCatId });
- }
- const { projectId, router } = this.props;
- this.props.fetchInterfaceListMenu(projectId);
- this.props.fetchInterfaceList({ project_id: projectId });
- if (router && isNaN(router.params.actionId)) {
- // 更新分类list下的数据
- let catid = router.params.actionId.substr(4);
- this.props.fetchInterfaceCatList({ catid });
- }
- } else {
- // 分类之间拖动
- let changes = arrayChangeIndex(list, dragIndex - 1, dropIndex - 1);
- axios.post('/api/interface/up_cat_index', changes).then();
- this.props.fetchInterfaceListMenu(this.props.projectId);
- }
- };
- // 数据过滤
- filterList = list => {
- let that = this;
- let arr = [];
- let menuList = produce(list, draftList => {
- draftList.filter(item => {
- let interfaceFilter = false;
- // arr = [];
- if (item.name.indexOf(that.state.filter) === -1) {
- item.list = item.list.filter(inter => {
- if (
- inter.title.indexOf(that.state.filter) === -1 &&
- inter.path.indexOf(that.state.filter) === -1
- ) {
- return false;
- }
- //arr.push('cat_' + inter.catid)
- interfaceFilter = true;
- return true;
- });
- arr.push('cat_' + item._id);
- return interfaceFilter === true;
- }
- arr.push('cat_' + item._id);
- return true;
- });
- });
- return { menuList, arr };
- };
- render() {
- const matchParams = this.props.match.params;
- // let menuList = this.state.list;
- const searchBox = (
- <div className="interface-filter">
- <Input onChange={this.onFilter} value={this.state.filter} placeholder="搜索接口" />
- <Button
- type="primary"
- onClick={() => this.changeModal('add_cat_modal_visible', true)}
- className="btn-filter"
- >
- 添加分类
- </Button>
- {this.state.visible ? (
- <Modal
- title="添加接口"
- visible={this.state.visible}
- onCancel={() => this.changeModal('visible', false)}
- footer={null}
- className="addcatmodal"
- >
- <AddInterfaceForm
- catdata={this.props.curProject.cat}
- catid={this.state.curCatid}
- onCancel={() => this.changeModal('visible', false)}
- onSubmit={this.handleAddInterface}
- />
- </Modal>
- ) : (
- ''
- )}
- {this.state.add_cat_modal_visible ? (
- <Modal
- title="添加分类"
- visible={this.state.add_cat_modal_visible}
- onCancel={() => this.changeModal('add_cat_modal_visible', false)}
- footer={null}
- className="addcatmodal"
- >
- <AddInterfaceCatForm
- onCancel={() => this.changeModal('add_cat_modal_visible', false)}
- onSubmit={this.handleAddInterfaceCat}
- />
- </Modal>
- ) : (
- ''
- )}
- {this.state.change_cat_modal_visible ? (
- <Modal
- title="修改分类"
- visible={this.state.change_cat_modal_visible}
- onCancel={() => this.changeModal('change_cat_modal_visible', false)}
- footer={null}
- className="addcatmodal"
- >
- <AddInterfaceCatForm
- catdata={this.state.curCatdata}
- onCancel={() => this.changeModal('change_cat_modal_visible', false)}
- onSubmit={this.handleChangeInterfaceCat}
- />
- </Modal>
- ) : (
- ''
- )}
- </div>
- );
- const defaultExpandedKeys = () => {
- const { router, inter, list } = this.props,
- rNull = { expands: [], selects: [] };
- if (list.length === 0) {
- return rNull;
- }
- if (router) {
- if (!isNaN(router.params.actionId)) {
- if (!inter || !inter._id) {
- return rNull;
- }
- return {
- expands: this.state.expands ? this.state.expands : ['cat_' + inter.catid],
- selects: [inter._id + '']
- };
- } else {
- let catid = router.params.actionId.substr(4);
- return {
- expands: this.state.expands ? this.state.expands : ['cat_' + catid],
- selects: ['cat_' + catid]
- };
- }
- } else {
- return {
- expands: this.state.expands ? this.state.expands : ['cat_' + list[0]._id],
- selects: ['root']
- };
- }
- };
- const itemInterfaceCreate = item => {
- return (
- <TreeNode
- title={
- <div
- className="container-title"
- onMouseEnter={() => this.enterItem(item._id)}
- onMouseLeave={this.leaveItem}
- >
- <Link
- className="interface-item"
- onClick={e => e.stopPropagation()}
- 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);
- }}
- 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._id);
- }}
- style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }}
- />
- </Tooltip>
- </div>
- {/*<Dropdown overlay={menu(item)} trigger={['click']} onClick={e => e.stopPropagation()}>
- <Icon type='ellipsis' className="interface-delete-icon" style={{ opacity: this.state.delIcon == item._id ? 1 : 0 }}/>
- </Dropdown>*/}
- </div>
- }
- key={'' + item._id}
- />
- );
- };
- let currentKes = defaultExpandedKeys();
- let menuList;
- if (this.state.filter) {
- let res = this.filterList(this.state.list);
- menuList = res.menuList;
- currentKes.expands = res.arr;
- } else {
- menuList = this.state.list;
- }
- return (
- <div>
- {searchBox}
- {menuList.length > 0 ? (
- <div
- className="tree-wrappper"
- style={{ maxHeight: parseInt(document.body.clientHeight) - headHeight + 'px' }}
- >
- <Tree
- className="interface-list"
- defaultExpandedKeys={currentKes.expands}
- defaultSelectedKeys={currentKes.selects}
- expandedKeys={currentKes.expands}
- selectedKeys={currentKes.selects}
- onSelect={this.onSelect}
- onExpand={this.onExpand}
- draggable
- onDrop={this.onDrop}
- >
- <TreeNode
- className="item-all-interface"
- title={
- <Link
- onClick={e => {
- e.stopPropagation();
- this.changeExpands();
- }}
- to={'/project/' + matchParams.id + '/interface/api'}
- >
- <Icon type="folder" style={{ marginRight: 5 }} />
- 全部接口
- </Link>
- }
- key="root"
- />
- {menuList.map(item => {
- return (
- <TreeNode
- title={
- <div
- className="container-title"
- onMouseEnter={() => this.enterItem(item._id)}
- onMouseLeave={this.leaveItem}
- >
- <Link
- className="interface-item"
- onClick={e => {
- e.stopPropagation();
- this.changeExpands();
- }}
- 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()}>
- <Icon type='ellipsis' className="interface-delete-icon" />
- </Dropdown>*/}
- </div>
- }
- key={'cat_' + item._id}
- className={`interface-item-nav ${item.list.length ? '' : 'cat_switch_hidden'}`}
- >
- {item.list.map(itemInterfaceCreate)}
- </TreeNode>
- );
- })}
- </Tree>
- </div>
- ) : null}
- </div>
- );
- }
- }
- export default withRouter(InterfaceMenu);
|