mirror of
https://github.com/YMFE/yapi.git
synced 2025-01-30 13:20:24 +08:00
feat: add interface and col route
This commit is contained in:
parent
cfdf623f1c
commit
dd06dfe5fc
@ -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,50 @@ import InterfaceContent from './InterfaceList/InterfaceContent.js'
|
||||
import InterfaceColMenu from './InterfaceCol/InterfaceColMenu.js'
|
||||
import InterfaceColContent from './InterfaceCol/InterfaceColContent.js'
|
||||
|
||||
class InterfaceRoute extends Component {
|
||||
static propTypes = {
|
||||
match: PropTypes.object
|
||||
}
|
||||
constructor(props){
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
let C, props = this.props;
|
||||
if (props.match.params.action === 'api') {
|
||||
C = InterfaceContent;
|
||||
} else if (props.match.params.action === 'col') {
|
||||
C = InterfaceColContent;
|
||||
}
|
||||
return <C />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 +63,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 +75,6 @@ class Interface extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default Interface
|
@ -1,25 +1,92 @@
|
||||
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';
|
||||
|
||||
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)
|
@ -45,6 +45,9 @@
|
||||
padding: 0 5px;
|
||||
width: 40px;
|
||||
}
|
||||
.interface-item{
|
||||
display: inline
|
||||
}
|
||||
|
||||
.interface-delete-icon{
|
||||
position: absolute;
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user