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

This commit is contained in:
zwjamnsss 2017-07-25 09:27:29 +08:00
commit fa0cc83cae
30 changed files with 474 additions and 229 deletions

View File

@ -6,7 +6,6 @@ import {
DELETE_INTERFACE_SEQ_HEADER,
GET_INTERFACE_REQ_PARAMS,
GET_INTERFACE_RES_PARAMS,
SAVE_INTERFACE_FORMS,
PUSH_INTERFACE_NAME,
PUSH_INTERFACE_METHOD
} from '../constants/action-types.js'
@ -60,13 +59,6 @@ export function getResParams (value) {
};
}
export function saveForms (value) {
return {
type: SAVE_INTERFACE_FORMS,
payload: value
};
}
export function pushInterfaceName (value) {
return {
type: PUSH_INTERFACE_NAME,
@ -80,5 +72,3 @@ export function pushInterfaceMethod (value) {
payload: value
}
}

View File

@ -6,7 +6,6 @@ import {
DELETE_INTERFACE_SEQ_HEADER,
GET_INTERFACE_REQ_PARAMS,
GET_INTERFACE_RES_PARAMS,
SAVE_INTERFACE_FORMS,
PUSH_INTERFACE_NAME,
PUSH_INTERFACE_METHOD
} from '../constants/action-types.js'
@ -60,13 +59,6 @@ export function getResParams (value) {
};
}
export function saveForms (value) {
return {
type: SAVE_INTERFACE_FORMS,
payload: value
};
}
export function pushInterfaceName (value) {
return {
type: PUSH_INTERFACE_NAME,
@ -80,5 +72,3 @@ export function pushInterfaceMethod (value) {
payload: value
}
}

View File

@ -1,33 +1,11 @@
import {
FETCH_INTERFACE_DATA,
LIST_INTERFACE_CLICK,
PROJECT_MEMBER_INTERFACE
PROJECT_MEMBER_INTERFACE,
DELETE_INTERFACE_DATA
} from '../constants/action-types.js'
export function fetchInterfaceData (value) {
// const data = [{
// key: '1',
// name: 'John Brown',
// age: 32,
// address: 'New York No. 1 Lake Park',
// date: '2015-11-11 13:00:15',
// features: '3'
// }, {
// key: '2',
// name: 'Jim Green',
// age: 42,
// address: 'London No. 1 Lake Park',
// date: '2015-11-11 13:00:15',
// features: '3'
// }, {
// key: '3',
// name: 'Joe Black',
// age: 32,
// address: 'Sidney No. 1 Lake Park',
// date: '2015-11-11 13:00:15',
// features: '3'
// }]
return {
type: FETCH_INTERFACE_DATA,
payload: value
@ -45,3 +23,10 @@ export function closeProjectMember () {
type: PROJECT_MEMBER_INTERFACE
}
}
export function deleteInterfaceData (value) {
return {
type: DELETE_INTERFACE_DATA,
payload: value
}
}

View File

@ -2,7 +2,6 @@ import './Footer.scss'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Icon } from 'antd'
class Footer extends Component {
constructor(props) {
super(props)
@ -11,8 +10,12 @@ class Footer extends Component {
footList: PropTypes.array
}
render () {
const style = {
'background': 'url(./image/footer-bac.jpg)'
}
return (
<div className = 'footer'>
<div className = 'footer' style = {style}>
<div className = 'footContent'>
{ this.props.footList.map(function(item,i){
return <FootItem key = { i } linkList = { item.linkList } title = { item.title } iconType = { item.iconType } ></FootItem>
@ -22,6 +25,7 @@ class Footer extends Component {
YMFF出品 @ YMFF
</div>
</div>
<div className='footerMask'></div>
</div>
)
}
@ -56,14 +60,7 @@ Footer.defaultProps = {
linkList: [
{
itemTitle: '源码仓库',
itemLink: 'http://www.baidu.com'
},
{
itemTitle: '源码仓库1',
itemLink: 'http://www.baidu.com'
},{
itemTitle: '源码仓库2',
itemLink: 'www.baidu.com'
itemLink: 'http://gitlab.corp.qunar.com/mfe/yapi.git'
}
]
@ -73,33 +70,36 @@ Footer.defaultProps = {
iconType: 'link',
linkList: [
{
itemTitle: '源码仓库',
itemLink: 'www.baidu.com'
itemTitle: 'YMFE',
itemLink: 'http://ued.qunar.com/ymfe/about'
},
{
itemTitle: '源码仓库1',
itemLink: 'www.baidu.com'
itemTitle: 'UED',
itemLink: 'http://ued.qunar.com/'
},{
itemTitle: '源码仓库2',
itemLink: 'www.baidu.com'
itemTitle: '去哪儿网',
itemLink: 'http://www.qunar.com/'
}
]
},
{
title: '社区',
iconType: 'customer-service',
title: '其他项目',
iconType: 'layout',
linkList: [
{
itemTitle: '源码仓库',
itemLink: 'www.baidu.com'
itemTitle: 'Yo',
itemLink: 'http://ued.qunar.com/hy2/yo/'
},
{
itemTitle: '源码仓库1',
itemLink: 'www.baidu.com'
itemTitle: 'YIcon',
itemLink: 'http://ued.qunar.com/yicon/'
},{
itemTitle: '源码仓库2',
itemLink: 'www.baidu.com'
itemTitle: 'YKit',
itemLink: 'http://ued.qunar.com/ykit/'
},{
itemTitle: 'YDoc',
itemLink: 'http://ued.qunar.com/ydoc/'
}
]

View File

@ -10,7 +10,9 @@
z-index: 1;
color: rgba(255,255,255,.65);
box-shadow: 0 1000px 0 1000px #fff;
// background-image: url('image/footer-bac.jpg');
background-repeat: no-repeat;
background-position: center center;
h4{
margin-bottom: 20px;
color: #FFF;
@ -19,23 +21,38 @@
}
}
}
.footerMask{
position: absolute;
top: 0px;
height: 100%;
width: 100%;
background-color: #404040;
opacity: .65;
z-index: 1;
}
.footContent{
max-width: 11rem;
width:90%;
margin:0px auto;
overflow: hidden;
position: relative;
z-index: 2;
}
.footItem{
padding: 24px 2%;
width: 25%;
float: left;
a{
div{
margin: 6px 0px;
display: block;
}
a{
font-weight: 200;
color: #108ee9;
&:hover{
color: white;
}
}
}
.copyRight{
padding: 24px 2%;

View File

@ -187,4 +187,4 @@ export default connect(
checkLoginState,
changeMenuItem
}
)(HeaderCom)
)(HeaderCom)

View File

@ -3,6 +3,7 @@ export const FETCH_INTERFACE_DATA = 'FETCH_INTERFACE_DATA'
export const LIST_INTERFACE_CLICK = 'LIST_INTERFACE_CLICK'
export const PROJECT_MEMBER_INTERFACE = 'PROJECT_MEMBER_INTERFACE'
export const PUSH_INTERFACE_NAME = 'PUSH_INTERFACE_NAME'
export const DELETE_INTERFACE_DATA = 'DELETE_INTERFACE_DATA'
// addInterFace
export const FETCH_ADD_INTERFACE_INPUT = 'FETCH_ADD_INTERFACE_INPUT'
@ -12,7 +13,6 @@ export const ADD_INTERFACE_SEQ_HEADER = 'ADD_INTERFACE_SEQ_HEADER'
export const DELETE_INTERFACE_SEQ_HEADER = 'DELETE_INTERFACE_SEQ_HEADER'
export const GET_INTERFACE_REQ_PARAMS = 'GET_INTERFACE_REQ_PARAMS'
export const GET_INTERFACE_RES_PARAMS = 'GET_INTERFACE_RES_PARAMS'
export const SAVE_INTERFACE_FORMS = 'SAVE_INTERFACE_FORMS'
export const PUSH_INTERFACE_METHOD = 'PUSH_INTERFACE_METHOD'
// group

View File

@ -10,62 +10,175 @@ import ReqHeader from './ReqHeader/ReqHeader.js'
import ReqParams from './ReqParams/ReqParams.js'
import ResParams from './ResParams/ResParams.js'
import Result from './Result/Result.js'
import { saveForms } from '../../actions/addInterface.js'
import {
saveForms,
getResParams,
getReqParams,
addReqHeader,
pushInputValue,
pushInterfaceName
} from '../../actions/addInterface.js'
@connect(
state => {
return {
reqParams: state.addInterface.reqParams,
methode: state.addInterface.method
resParams: state.addInterface.resParams,
method: state.addInterface.method,
url: state.addInterface.url,
seqGroup: state.addInterface.seqGroup,
interfaceName: state.addInterface.interfaceName
}
},
{
saveForms
saveForms,
getReqParams,
getResParams,
addReqHeader,
pushInputValue,
pushInterfaceName
}
)
class AddInterface extends Component {
static propTypes = {
url: PropTypes.string,
method: PropTypes.string,
reqParams: PropTypes.string,
methode: PropTypes.string,
saveForms: PropTypes.func
resParams: PropTypes.string,
seqGroup: PropTypes.array,
interfaceName: PropTypes.string,
saveForms: PropTypes.func,
addReqHeader: PropTypes.func,
getReqParams: PropTypes.func,
getResParams: PropTypes.func,
pushInputValue: PropTypes.func,
pushInterfaceName: PropTypes.func
}
constructor (props) {
super(props)
this.state = {
isLoading: ''
}
}
componentDidMount () {
const ifTrue = this.verificationURL()
let interfaceId = undefined
if (ifTrue) {
interfaceId = this.getInterfaceId()
this.initInterfaceData(interfaceId)
} else {
const props = this.props
props.pushInputValue('')
props.pushInterfaceName('')
props.getReqParams('')
props.getResParams('')
props.addReqHeader([
{
id: 0,
name: '',
value: ''
}
])
}
}
getInterfaceId () {
const value = location.hash.match(/\d+/g)
return value ? value[0] : ''
}
verificationURL () {
const dir = 'AddInterface/edit'
const url = location.href
if (url.includes(dir)) {
return true
}
}
editState (data) {
const props = this.props
const { path, title, req_params_other, res_body, req_headers} = data
props.pushInputValue(path)
props.pushInterfaceName(title)
props.getReqParams(req_params_other)
props.getResParams(res_body)
props.addReqHeader(req_headers)
}
editState2 () {
const props = this.props
props.pushInputValue(props.url)
// props.pushInterfaceName(title)
// props.getReqParams(req_params_other)
props.getResParams(props.resParams)
// props.addReqHeader(req_headers)
}
initInterfaceData (interfaceId) {
const params = { id: interfaceId }
axios.get('/interface/get', {params: params})
.then(result => {
result = result.data.data
result.req_headers.map((value, key) => {
value.id = key
return value
})
this.editState(result)
})
.catch(e => {
console.log(e)
})
}
setLoading (boolean) {
this.setState({
isLoading: boolean ? 'is-loading' : ''
})
}
routerPage () {
const origin = location.origin
const pathname = location.pathname
location.href = `${origin}${pathname}#/interface`
}
@autobind
saveForms () {
// const config = {
// url: '/interface/add',
// method: 'POST',
// headers: {'Content-Type': 'application/json'},
// params: {
// method: 'POST',
// project_id: 8,
// req_headers: [],
// req_params_type: 'json',
// req_params: this.props.reqParams
// }
// }
let postURL = undefined
const { interfaceName, url, seqGroup, reqParams, resParams } = this.props
const ifTrue = this.verificationURL()
const interfaceId = this.getInterfaceId()
const params = {
url: '/interface/add',
title: interfaceName,
path: url,
method: 'POST',
params: {
method: 'POST',
project_id: 558,
req_headers: [],
req_params_type: 'json',
req_params: this.props.reqParams,
title: '接口文档1'
}
req_headers: seqGroup,
project_id: 558,
req_params_type: 'json',
req_params_other: reqParams,
res_body_type: 'json',
res_body: resParams
}
axios.post('/interface/add', params)
if (ifTrue) {
params.id = interfaceId
postURL = '/interface/up'
} else {
postURL = '/interface/add'
}
this.setLoading(true)
axios.post(postURL, params)
.then(data => {
console.log(data)
console.log(this.props.methode)
this.setLoading()
this.editState2()
// this.routerPage()
})
.catch(e => {
console.log(e)
@ -74,6 +187,7 @@ class AddInterface extends Component {
render () {
const TabPane = Tabs.TabPane
const isLoading = this.state.isLoading
return (
<section className="add-interface-box">
@ -83,7 +197,7 @@ class AddInterface extends Component {
<Button type="primary" className="save" onClick={this.saveForms}>保存</Button>
<ReqMethod />
<ReqHeader />
<ReqParams />
<ReqParams data={this.props} />
<ResParams />
<Result />
</TabPane>
@ -91,6 +205,7 @@ class AddInterface extends Component {
<TabPane tab="测试" key="3">测试</TabPane>
</Tabs>
</div>
<div className={`loading ${isLoading}`}></div>
</section>
)
}

View File

@ -8,7 +8,7 @@
max-width: 11rem;
margin: 0 auto;
background: #FFF;
padding: 10px 20px;
padding: 10px 20px 50px 20px;
.save {
float: right;
@ -131,13 +131,45 @@
textarea {
width: 100%;
border: 1px #CCC solid;
height: 200px;
height: 300px;
}
pre {
padding: 10px;
box-sizing: border-box;
width: 100%;
border: 1px #CCC solid;
height: 300px;
overflow-x: hidden;
overflow-y: auto;
line-height: 1.2;
}
.ant-tabs {
-webkit-box-flex: 1;
}
}
.dynamic-delete-button {
margin: 0 0 0 10px;
color: #CCC;
}
}
.loading {
display: none;
width: 100%;
height: 100px;
position: fixed;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
background-size: 30%;
z-index: 10000;
}
.is-loading {
display: block;
}
}

View File

@ -11,8 +11,9 @@ import {
// 重新渲染页面
const getReqList = function (self) {
const [reqList, seqGroup] = [[], self.props.seqGroup]
console.log('seqGroup', seqGroup)
seqGroup.map((value, key) => {
reqList.push(<ReqList key={key} dataNum={value.id} />)
reqList.push(<ReqList key={key} value={value} dataNum={value.id} />)
})
return reqList
}
@ -45,8 +46,8 @@ class ReqHeader extends Component {
let id = seqGroup[seqGroup.length-1].id
let list = {
id: ++id,
tag: '',
content: ''
value: '',
name: ''
}
seqGroup.push(list)
newSeqGroup.push(...seqGroup)

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react'
import { Select, Input } from 'antd'
import { Select, Input, Icon } from 'antd'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { autobind } from 'core-decorators'
@ -13,8 +13,6 @@ import {
state => {
return {
seqGroup: state.addInterface.seqGroup,
tagValue: state.addInterface.tagValue,
headerValue: state.addInterface.headerValue,
reqTagValue: state.addInterface.reqTagValue,
reqHeaderValue: state.addInterface.reqHeaderValue
}
@ -28,13 +26,13 @@ import {
class ReqList extends Component {
static propTypes = {
headerValue: PropTypes.string,
seqGroup: PropTypes.array,
tagValue: PropTypes.string,
reqTagValue: PropTypes.func,
reqHeaderValue: PropTypes.func,
deleteReqHeader: PropTypes.func,
dataNum: PropTypes.number
_id: PropTypes.number,
dataNum: PropTypes.number,
value: PropTypes.object
}
constructor(props) {
@ -43,22 +41,32 @@ class ReqList extends Component {
@autobind
handleChange (value) {
this.props.reqTagValue(value)
const dir = 'AddInterface/edit'
const url = location.href
if (url.includes(dir)) {
const { seqGroup, value: { id } } = this.props
seqGroup[id].name = value
} else {
const { seqGroup, dataNum } = this.props
seqGroup[dataNum].name = value
}
}
@autobind
handleBlur (e) {
const value = e.target.value
this.props.reqHeaderValue(value)
const { seqGroup, value: { id } } = this.props
seqGroup[id].value = value
}
@autobind
deleteReqHeader (e) {
deleteReqHeader () {
let newSeqGroup = []
let seqGroup = this.props.seqGroup
let dataNum = e.target.getAttribute('data-num')
let id = this.props.value.id
seqGroup.map(value => {
if (+dataNum !== value.id) {
if (+id !== value.id) {
newSeqGroup.push(value)
}
})
@ -66,22 +74,24 @@ class ReqList extends Component {
}
render () {
const propsValue = this.props.value
const Option = Select.Option
const dataNum = this.props.dataNum
const value = propsValue.value
const name = propsValue.name || 'Accept'
return (
<li>
<em className="title">头部标签 {this.props.tagValue} {this.props.headerValue}</em>
<Select defaultValue="HTTP" style={{ width: 220 }} onChange={this.handleChange} size="large">
<Option value="HTTP">Accept</Option>
<em className="title">头部标签</em>
<Select defaultValue={name} style={{ width: 220 }} onChange={this.handleChange} size="large">
<Option value="Accept">Accept</Option>
<Option value="Accept-Charset">Accept-Charset</Option>
<Option value="Accept-Encoding">Accept-Encoding</Option>
<Option value="Accept-Language">Accept-Language</Option>
<Option value="Accept-Ranges">Accept-Ranges</Option>
</Select>
<em className="title">头部内容</em>
<Input placeholder="Basic usage" className="req-content" size="large" onBlur={this.handleBlur} />
<span className="close" onClick={this.deleteReqHeader} data-num={dataNum}>×</span>
<Input defaultValue={value} placeholder="Basic usage" className="req-content" size="large" onBlur={this.handleBlur} />
<Icon className="dynamic-delete-button" type="minus-circle-o" onClick={this.deleteReqHeader} />
</li>
)
}

View File

@ -13,7 +13,7 @@ import {
state => {
return {
method: state.addInterface.method,
reqInputVal: state.addInterface.inputValue,
url: state.addInterface.url,
interfaceName: state.addInterface.interfaceName
}
},
@ -29,7 +29,7 @@ class ReqMethod extends Component {
pushInputValue: PropTypes.func,
pushInterfaceName: PropTypes.func,
pushInterfaceMethod: PropTypes.func,
inputValue: PropTypes.string,
url: PropTypes.string,
method: PropTypes.string,
interfaceName: PropTypes.string
}
@ -40,15 +40,13 @@ class ReqMethod extends Component {
@autobind
handleChange (value) {
this.props.pushInterfaceMethod(value)
}
@autobind
getInputVal (e) {
const inputVal = e.target.value
console.log(this.props.pushInputValue)
this.props.pushInputValue(inputVal)
const url = e.target.value
this.props.pushInputValue(url)
}
@autobind
@ -59,14 +57,14 @@ class ReqMethod extends Component {
render () {
const { Option } = Select
console.log(this.props.method)
const { url, interfaceName } = this.props
return (
<table>
<tbody>
<tr>
<th>协议 :</th>
<td>
<span className="h3">请求协议 {this.props.inputValue}</span>
<span className="h3">请求协议</span>
<Select defaultValue="HTTP" style={{ width: 220}} onChange={this.handleChange} size="large">
<Option value="HTTP">HTTP</Option>
<Option value="HTTPS">HTTPS</Option>
@ -82,11 +80,27 @@ class ReqMethod extends Component {
</tr>
<tr>
<th>URL :</th>
<td><Input placeholder="填写 URL" className="url" size="large" onBlur={this.getInputVal} /></td>
<td>
<Input
placeholder="填写 URL"
className="url"
size="large"
onInput={this.getInputVal}
value={url}
/>
</td>
</tr>
<tr>
<th>名称 :</th>
<td><Input placeholder="接口名称" className="url" size="large" onBlur={this.getInterfaceValue} /></td>
<td>
<Input
placeholder="接口名称"
className="url"
size="large"
value={interfaceName}
onInput={this.getInterfaceValue}
/>
</td>
</tr>
</tbody>
</table>

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import wangEditor from 'wangeditor'
import { getReqParams } from '../../../actions/addInterface.js'
const editor = new wangEditor('#req-cover')
@connect(
state => {
return {
@ -25,15 +25,23 @@ class ReqParams extends Component {
super(props)
}
initParams () {
const { reqParams } = this.props
if (reqParams) {
editor.txt.html(reqParams)
}
}
componentDidMount () {
const reg = /(<p>)|(<\/p>)|&nbsp;|(<br>)|\s+/g
const E = wangEditor
const editor = new E('#req-cover')
editor.customConfig.menus = []
editor.customConfig.onchange = html => {
html = html.replace(reg, '')
this.props.getReqParams(html)
}
setTimeout(() => {
this.initParams()
}, 200)
editor.create()
}

View File

@ -4,6 +4,8 @@ import { connect } from 'react-redux'
import wangEditor from 'wangeditor'
import { getResParams } from '../../../actions/addInterface.js'
const editor = new wangEditor('#res-cover')
@connect(
state => {
return {
@ -25,13 +27,25 @@ class ResParams extends Component {
super(props)
}
initResParams () {
const { resParams } = this.props
if (resParams) {
editor.txt.html(resParams)
}
}
componentDidMount () {
var E = wangEditor
var editor = new E('#res-cover')
const reg = /(<p>)|(<\/p>)|&nbsp;|(<br>)|\s+|<div>|<\/div>/g
editor.customConfig.menus = []
editor.customConfig.onchange = html => {
html = html.match(/{.*}/g)[0]
html = html.replace(reg, '')
console.log(html)
this.props.getResParams(html)
}
setTimeout(() => {
this.initResParams()
}, 400)
editor.create()
}
@ -47,4 +61,4 @@ class ResParams extends Component {
}
}
export default ResParams
export default ResParams

View File

@ -1,24 +1,45 @@
import React, { Component } from 'react'
import { Tabs } from 'antd'
import Mock from 'mockjs'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
@connect(
state => {
return {
resParams: state.addInterface.resParams,
reqParams: state.addInterface.reqParams
}
}
)
class Result extends Component {
static propTypes = {
resParams: PropTypes.string,
reqParams: PropTypes.string
}
constructor(props) {
super(props)
}
callback () {
}
render () {
const TabPane = Tabs.TabPane
render () {
console.log(1)
let TabPane = Tabs.TabPane
let resParams = ''
let json = ''
if(this.props.resParams){
console.log(this.props.resParams)
resParams = JSON.parse(this.props.resParams)
json = JSON.stringify(Mock.mock(resParams), null, 2)
}
return (
<div className="result">
<strong className="res-h3">返回示例 :</strong>
<Tabs defaultActiveKey="1" onChange={this.callback}>
<Tabs defaultActiveKey="1">
<TabPane tab="成功结果" key="1">
<textarea></textarea>
<pre>{json}</pre>
</TabPane>
</Tabs>
</div>
@ -26,4 +47,4 @@ class Result extends Component {
}
}
export default Result
export default Result

View File

@ -6,7 +6,7 @@ import axios from 'axios'
import InterfaceList from './InterfaceList/InterfaceList.js'
import InterfaceTable from './InterfaceTable/InterfaceTable.js'
import InterfaceMode from './InterfaceMode/InterfaceMode.js'
import moment from 'moment'
import {
fetchInterfaceData,
projectMember,
@ -43,7 +43,6 @@ class Interface extends Component {
componentWillMount () {
// 558 665 704 743
this.props.fetchInterfaceData()
const params = {
params: {
project_id: 558
@ -51,8 +50,13 @@ class Interface extends Component {
}
axios.get('/interface/list', params)
.then(data => {
console.log(data)
.then(result => {
result = result.data.data
result.map(value => {
value.add_time = moment(value.add_time).format('YYYY-MM-DD HH:mm:ss')
return value
})
this.props.fetchInterfaceData(result)
})
.catch(e => {
console.log(e)
@ -61,7 +65,6 @@ class Interface extends Component {
render () {
const { interfaceData, projectMember, modalVisible } = this.props
return (
<div>
<section className="interface-box">
@ -74,4 +77,4 @@ class Interface extends Component {
}
}
export default Interface
export default Interface

View File

@ -1,41 +1,81 @@
import React, { Component } from 'react'
import { Table, Button } from 'antd'
import PropTypes from 'prop-types'
import axios from 'axios'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { deleteInterfaceData } from '../../../actions/interfaceAction.js'
@connect(
state => {
return {
interfaceData: state.Interface.interfaceData
}
},
{
deleteInterfaceData
}
)
class InterfaceTable extends Component {
static propTypes = {
data: PropTypes.array
interfaceData: PropTypes.array,
data: PropTypes.array,
deleteInterfaceData: PropTypes.func
}
constructor(props) {
super(props)
}
deleteInterfaceData (interfaceId) {
let interfaceArr = []
let { interfaceData } = this.props
interfaceData.forEach(value => {
if (value._id !== interfaceId) {
interfaceArr.push(value)
}
})
this.props.deleteInterfaceData(interfaceArr)
}
deleteInterface (interfaceId) {
const params = {
id: interfaceId
}
axios.post('/interface/del', params)
.then(() => {
this.deleteInterfaceData(interfaceId)
})
.catch(err => {
console.log(err)
})
}
render () {
const columns = [{
title: '接口名称',
dataIndex: 'name',
key: 'name'
dataIndex: 'title',
key: 'title'
}, {
title: '接口URL',
dataIndex: 'age',
key: 'age'
}, {
title: '操作者',
dataIndex: 'address',
key: 'address'
}, {
dataIndex: 'path',
key: 'path'
},{
title: '更新日期',
dataIndex: 'date',
key: 'date'
dataIndex: 'add_time',
key: 'add_time'
}, {
title: '功能',
'key': 'action',
render: () => {
render: (data) => {
const deleteInterface = this.deleteInterface.bind(this, data._id)
return (
<span>
<Button type="primary">编辑</Button>
<Button type="danger">删除</Button>
<Button type="primary">
<Link to={`/AddInterface/edit/${data._id}`}>编辑</Link>
</Button>
<Button type="danger" onClick={deleteInterface}>删除</Button>
</span>
)
}

View File

@ -1,7 +1,7 @@
import './index.scss'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Route} from 'react-router-dom'
import { Route } from 'react-router-dom'
import LeftMenu from './LeftMenu.js'
import List from './List.js'
import PropTypes from 'prop-types'

BIN
client/images/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,11 +1,12 @@
import {
FETCH_INTERFACE_DATA,
LIST_INTERFACE_CLICK,
PROJECT_MEMBER_INTERFACE
PROJECT_MEMBER_INTERFACE,
DELETE_INTERFACE_DATA
} from '../../constants/action-types.js'
const initialState = {
interfaceData: null,
interfaceData: [],
modalVisible: false,
interfaceName: ''
}
@ -27,6 +28,11 @@ export default (state = initialState, action) => {
...state,
modalVisible: false
}
case DELETE_INTERFACE_DATA:
return {
...state,
interfaceData: action.payload
}
default:
return state
}

View File

@ -6,22 +6,20 @@ import {
DELETE_INTERFACE_SEQ_HEADER,
GET_INTERFACE_REQ_PARAMS,
GET_INTERFACE_RES_PARAMS,
SAVE_INTERFACE_FORMS,
PUSH_INTERFACE_NAME,
PUSH_INTERFACE_METHOD
} from '../../constants/action-types.js'
const initialState = {
inputValue: '',
tagValue: '',
headerValue: '',
methode: '',
interfaceName: '',
url: '',
method: '',
// 默认请求头部有一条数据
seqGroup: [
{
id: 0,
tag: '',
content: ''
name: '',
value: ''
}
],
reqParams: '',
@ -33,7 +31,7 @@ export default (state = initialState, action) => {
case FETCH_ADD_INTERFACE_INPUT:
return {
...state,
inputValue: action.payload
url: action.payload
}
case FETCH_ADD_INTERFACE_TAG_VALUE:
return {
@ -65,20 +63,15 @@ export default (state = initialState, action) => {
...state,
resParams: action.payload
}
case SAVE_INTERFACE_FORMS:
return {
...state,
resParams: action.payload
}
case PUSH_INTERFACE_NAME:
return {
...state,
resParams: action.payload
interfaceName: action.payload
}
case PUSH_INTERFACE_METHOD:
return {
...state,
methode: action.payload
method: action.payload
}
default:
return state

View File

@ -1,11 +1,12 @@
import {
FETCH_INTERFACE_DATA,
LIST_INTERFACE_CLICK,
PROJECT_MEMBER_INTERFACE
PROJECT_MEMBER_INTERFACE,
DELETE_INTERFACE_DATA
} from '../../constants/action-types.js'
const initialState = {
interfaceData: null,
interfaceData: [],
modalVisible: false,
interfaceName: ''
}
@ -27,6 +28,11 @@ export default (state = initialState, action) => {
...state,
modalVisible: false
}
case DELETE_INTERFACE_DATA:
return {
...state,
interfaceData: action.payload
}
default:
return state
}

View File

@ -17,7 +17,6 @@ export default (state = initialState, action) => {
};
}
case FETCH_MORE_NEWS: {
// console.log(action.payload);
return {
newsData: {
...state.newsData,

View File

@ -10,4 +10,4 @@
<div id="yapi" style="height: 100%;"></div>
<script src="prd/index@dev.js"></script>
</body>
</html>
</html>

View File

@ -30,6 +30,7 @@
"koa-session-minimal": "^3.0.3",
"koa-static": "^3.0.0",
"koa-views": "^5.2.0",
"mock": "^0.1.1",
"mockjs": "^1.0.1-beta3",
"moment": "^2.18.1",
"mongoose": "4.10.8",

View File

@ -223,7 +223,7 @@ class interfaceController extends baseController{
return ctx.body = yapi.commons.resReturn(null, 400, '接口id不能为空');
}
let data = await this.Model.get(params.id);
let data = await this.Model.get(ctx.request.body.id);
if(data.uid != this.getUid()){
if(await this.jungeProjectAuth(data.project_id) !== true){
@ -235,7 +235,7 @@ class interfaceController extends baseController{
let result = await this.Model.del(id);
ctx.body = yapi.commons.resReturn(result)
}catch(err){
ctx.body = yapi.commons.resReturn(null, 402, e.message)
ctx.body = yapi.commons.resReturn(null, 402, err.message)
}
}
}

View File

@ -18,7 +18,7 @@ class projectController extends baseController {
if(!basepath) return false;
if(basepath[0] !== '/') basepath = '/' + basepath;
if(basepath[basepath.length -1] === '/') basepath = basepath.substr(0, basepath.length -1)
if(yapi.commons.verifyPath(basepath)){
if(!yapi.commons.verifyPath(basepath)){
return false;
}
return basepath;
@ -43,8 +43,8 @@ class projectController extends baseController {
* @param {String} prd_host 项目线上域名不能为空可通过配置的域名访问到mock数据
* @param {String} protocol 线上域名协议不能为空
* @param {Number} group_id 项目分组id不能为空
* @param {String} [desc] 项目描述
* @returns {Object}
* @param {String} [desc] 项目描述
* @returns {Object}
* @example ./api/project/add.json
*/
async add(ctx) {
@ -82,7 +82,7 @@ class projectController extends baseController {
if(checkRepeatDomain > 0){
return ctx.body = yapi.commons.resReturn(null, 401, '已存在domain和basepath');
}
let data = {
name: params.name,
desc: params.desc,
@ -97,12 +97,12 @@ class projectController extends baseController {
}
try{
let result = await this.Model.save(data);
let result = await this.Model.save(data);
ctx.body = yapi.commons.resReturn(result);
}catch(e){
ctx.body = yapi.commons.resReturn(null, 402, e.message)
}
}
/**
* 添加项目
@ -112,7 +112,7 @@ class projectController extends baseController {
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {String} member_uid 项目成员uid,不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/add_member.json
*/
async addMember(ctx){
@ -144,7 +144,7 @@ class projectController extends baseController {
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {member_uid} uid 项目成员uid,不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/del_member.json
*/
@ -204,7 +204,7 @@ class projectController extends baseController {
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/get.json
*/
@ -230,7 +230,7 @@ class projectController extends baseController {
* @param {Number} group_id 项目group_id不能为空
* @param {Number} [page] 分页页码
* @param {Number} [limit] 每页数据条目默认为10
* @returns {Object}
* @returns {Object}
* @example ./api/project/list.json
*/
@ -251,7 +251,7 @@ class projectController extends baseController {
if(uids.indexOf(item.uid) === -1){
uids.push(item.uid)
}
} )
let _users = {}, users = await yapi.getInst(userModel).findByUids(uids);
users.forEach((item)=> {
@ -274,11 +274,11 @@ class projectController extends baseController {
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/del.json
*/
async del(ctx){
async del(ctx){
try{
let id = ctx.request.body.id;
if(!id){
@ -310,16 +310,16 @@ class projectController extends baseController {
* @param {String} name 项目名称不能为空
* @param {String} basepath 项目基本路径不能为空
* @param {String} prd_host 项目线上域名不能为空可通过配置的域名访问到mock数据
* @param {String} [desc] 项目描述
* @param {String} [desc] 项目描述
* @param {Array} [env] 项目环境配置
* @param {String} [env[].name] 环境名称
* @param {String} [env[].domain] 环境域名
* @returns {Object}
* @returns {Object}
* @example ./api/project/up.json
*/
async up(ctx){
try{
try{
let id = ctx.request.body.id;
let params = ctx.request.body;
if(!id){
@ -329,7 +329,7 @@ class projectController extends baseController {
if(await this.jungeMemberAuth(id, this.getUid()) !== true){
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
let projectData = await this.Model.get(id);
if(params.basepath = (this.handleBasepath(params.basepath)) === false){
@ -339,7 +339,7 @@ class projectController extends baseController {
if(!this.verifyDomain(params.prd_host)){
return ctx.body = yapi.commons.resReturn(null, 401, '线上域名格式有误')
}
if(projectData.name === params.name){
delete params.name;
}
@ -426,7 +426,7 @@ class projectController extends baseController {
{ key: 'add_time', alias: 'addTime' },
{ key: 'up_time', alias: 'upTime' }
];
projectList = commons.filterRes(projectList, projectRules);
groupList = commons.filterRes(groupList, groupRules);
@ -434,9 +434,9 @@ class projectController extends baseController {
project: projectList,
group: groupList
};
return ctx.body = yapi.commons.resReturn(queryList, 0, 'ok')
}
}
module.exports = projectController;
module.exports = projectController;

View File

@ -476,7 +476,7 @@ var interfaceController = function (_baseController) {
case 4:
_context5.next = 6;
return this.Model.get(params.id);
return this.Model.get(ctx.request.body.id);
case 6:
data = _context5.sent;
@ -514,7 +514,7 @@ var interfaceController = function (_baseController) {
_context5.prev = 19;
_context5.t1 = _context5['catch'](0);
ctx.body = _yapi2.default.commons.resReturn(null, 402, e.message);
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context5.t1.message);
case 22:
case 'end':

View File

@ -77,7 +77,7 @@ var projectController = function (_baseController) {
if (!basepath) return false;
if (basepath[0] !== '/') basepath = '/' + basepath;
if (basepath[basepath.length - 1] === '/') basepath = basepath.substr(0, basepath.length - 1);
if (_yapi2.default.commons.verifyPath(basepath)) {
if (!_yapi2.default.commons.verifyPath(basepath)) {
return false;
}
return basepath;
@ -103,8 +103,8 @@ var projectController = function (_baseController) {
* @param {String} prd_host 项目线上域名不能为空可通过配置的域名访问到mock数据
* @param {String} protocol 线上域名协议不能为空
* @param {Number} group_id 项目分组id不能为空
* @param {String} [desc] 项目描述
* @returns {Object}
* @param {String} [desc] 项目描述
* @returns {Object}
* @example ./api/project/add.json
*/
@ -246,7 +246,7 @@ var projectController = function (_baseController) {
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {String} member_uid 项目成员uid,不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/add_member.json
*/
@ -330,7 +330,7 @@ var projectController = function (_baseController) {
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {member_uid} uid 项目成员uid,不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/del_member.json
*/
@ -483,7 +483,7 @@ var projectController = function (_baseController) {
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/get.json
*/
@ -547,7 +547,7 @@ var projectController = function (_baseController) {
* @param {Number} group_id 项目group_id不能为空
* @param {Number} [page] 分页页码
* @param {Number} [limit] 每页数据条目默认为10
* @returns {Object}
* @returns {Object}
* @example ./api/project/list.json
*/
@ -635,7 +635,7 @@ var projectController = function (_baseController) {
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @returns {Object}
* @example ./api/project/del.json
*/
@ -729,11 +729,11 @@ var projectController = function (_baseController) {
* @param {String} name 项目名称不能为空
* @param {String} basepath 项目基本路径不能为空
* @param {String} prd_host 项目线上域名不能为空可通过配置的域名访问到mock数据
* @param {String} [desc] 项目描述
* @param {String} [desc] 项目描述
* @param {Array} [env] 项目环境配置
* @param {String} [env[].name] 环境名称
* @param {String} [env[].domain] 环境域名
* @returns {Object}
* @returns {Object}
* @example ./api/project/up.json
*/

BIN
static/image/footer-bac.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB