mirror of
https://github.com/YMFE/yapi.git
synced 2024-12-15 05:10:47 +08:00
feat: 接口运行高级参数输入功能
This commit is contained in:
parent
5034b4d20c
commit
0ac47cf6fa
106
client/components/ModalPostman/MethodsList.js
Normal file
106
client/components/ModalPostman/MethodsList.js
Normal file
@ -0,0 +1,106 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Row, Input, Radio, Icon } from 'antd';
|
||||
import common from 'common/power-string.js'
|
||||
import { autobind } from 'core-decorators';
|
||||
|
||||
const RadioButton = Radio.Button;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Search = Input.Search;
|
||||
|
||||
const METHODS_LIST = [
|
||||
{ name: 'md5', type: false },
|
||||
{ name: 'lower', type: false },
|
||||
{ name: 'length', type: false },
|
||||
{ name: 'substr', type: true },
|
||||
{ name: 'sha', type: false, subname: ['sha1', 'sha224', 'sha256', 'sha384', 'sha512'] },
|
||||
{ name: 'base64', type: false },
|
||||
{ name: 'unbase64', type: false },
|
||||
{ name: 'concat', type: true },
|
||||
{ name: 'lconcat', type: true },
|
||||
{ name: 'upper', type: false }
|
||||
|
||||
]
|
||||
|
||||
// const list = METHODS_LIST.slice(0,4);
|
||||
|
||||
|
||||
class MethodsList extends Component {
|
||||
static propTypes = {
|
||||
show: PropTypes.bool,
|
||||
click: PropTypes.func,
|
||||
clickValue: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
filter: '',
|
||||
list: METHODS_LIST.slice(0, 4),
|
||||
moreFlag: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log('common', common);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// console.log("nextProps",nextProps);
|
||||
if(this.props.show !==nextProps.show){
|
||||
this.unshowMore();
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
onFilter() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@autobind
|
||||
showMore() {
|
||||
this.setState({
|
||||
list: METHODS_LIST,
|
||||
moreFlag: false
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@autobind
|
||||
unshowMore() {
|
||||
this.setState({
|
||||
list: METHODS_LIST.slice(0, 4),
|
||||
moreFlag: true
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list, moreFlag } = this.state;
|
||||
const {click, clickValue} = this.props;
|
||||
return (
|
||||
<div className="modal-postman-form-method">
|
||||
<h3 className="methods-title title">方法</h3>
|
||||
<RadioGroup onChange={click} value={clickValue}>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
return <Row key={index} type="flex" align="middle" className="row methods-row" >
|
||||
<RadioButton value={item.name}>{item.name}</RadioButton>
|
||||
</Row>
|
||||
})
|
||||
}
|
||||
</RadioGroup>
|
||||
{
|
||||
moreFlag && <div className="show-more" onClick={this.showMore}><Icon type="down" /><span style={{ paddingLeft: '4px' }}>更多</span></div>
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MethodsList;
|
81
client/components/ModalPostman/MockList.js
Normal file
81
client/components/ModalPostman/MockList.js
Normal file
@ -0,0 +1,81 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Row, Input, Radio } from 'antd';
|
||||
import constants from '../../constants/variable.js'
|
||||
import { autobind } from 'core-decorators';
|
||||
const wordList = constants.MOCK_SOURCE;
|
||||
const RadioButton = Radio.Button;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Search = Input.Search;
|
||||
|
||||
|
||||
class MockList extends Component {
|
||||
static propTypes = {
|
||||
click: PropTypes.func,
|
||||
clickValue: PropTypes.string
|
||||
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
filter: '',
|
||||
list: []
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
list: wordList
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
onFilter(e) {
|
||||
|
||||
const list = wordList.filter(item => {
|
||||
return item.mock.indexOf(e.target.value) !== -1
|
||||
});
|
||||
this.setState({
|
||||
filter: e.target.value,
|
||||
list: list
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
onSearch(v){
|
||||
console.log(v);
|
||||
this.props.click();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list, filter} = this.state;
|
||||
const {click, clickValue} = this.props;
|
||||
return (
|
||||
<div className="modal-postman-form-mock">
|
||||
<h3 className="mock-title title">mock数据</h3>
|
||||
<Search
|
||||
onChange={this.onFilter}
|
||||
onSearch={this.onSearch}
|
||||
value={filter}
|
||||
placeholder="搜索mock数据"
|
||||
className="mock-search"
|
||||
/>
|
||||
<RadioGroup onChange={click} value={clickValue}>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
return <Row key={index} type="flex" align="middle" className="row" >
|
||||
<RadioButton value={item.mock}>{item.mock}</RadioButton>
|
||||
</Row>
|
||||
})
|
||||
}
|
||||
</RadioGroup>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MockList;
|
122
client/components/ModalPostman/index.js
Normal file
122
client/components/ModalPostman/index.js
Normal file
@ -0,0 +1,122 @@
|
||||
import React, { Component } from 'react'
|
||||
// import { connect } from 'react-redux'
|
||||
// import axios from 'axios'
|
||||
import PropTypes from 'prop-types'
|
||||
import './index.scss'
|
||||
// import { withRouter } from 'react-router-dom';
|
||||
import { Modal, Row, Col, Icon } from 'antd';
|
||||
import { autobind } from 'core-decorators';
|
||||
import MockList from './MockList.js';
|
||||
import MethodsList from './MethodsList.js'
|
||||
|
||||
|
||||
class ModalPostman extends Component {
|
||||
static propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
handleCancel: PropTypes.func,
|
||||
handleOk: PropTypes.func
|
||||
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
clickValue: '',
|
||||
methodsShow: false,
|
||||
methodsShowMore: false,
|
||||
arr: [],
|
||||
count: []
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mockClick(index) {
|
||||
|
||||
return (e) => {
|
||||
this.setState({
|
||||
clickValue: e.target.value
|
||||
})
|
||||
if (index === -1) {
|
||||
this.setState({
|
||||
arr: []
|
||||
})
|
||||
this.createArrList([]);
|
||||
} else {
|
||||
let newArr = [].concat(this.state.arr);
|
||||
newArr.splice(index + 1, newArr.length - index - 1)
|
||||
this.setState({
|
||||
arr: newArr
|
||||
})
|
||||
this.createArrList(newArr)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
createArrList(arr) {
|
||||
// let arr = [];
|
||||
const ListSource = (props) => {
|
||||
console.log(props)
|
||||
return <MethodsList
|
||||
show={this.state.methodsShowMore}
|
||||
click={this.mockClick(props.index)}
|
||||
clickValue={this.state.clickValue}
|
||||
/>
|
||||
}
|
||||
// this.state.arr.push(ListSource)
|
||||
this.setState({
|
||||
arr: [].concat(arr, ListSource)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { visible, handleCancel, handleOk } = this.props
|
||||
const { clickValue, count } = this.state;
|
||||
console.log('count', count);
|
||||
return (
|
||||
<Modal
|
||||
title={<p><Icon type="edit" /> 高级参数设置</p>}
|
||||
visible={visible}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
wrapClassName="modal-postman"
|
||||
width={800}
|
||||
>
|
||||
|
||||
<Row className="modal-postman-form" type="flex" flex-flow="row nowrap">
|
||||
<Col span={8} className="modal-postman-col">
|
||||
<MockList click={this.mockClick(-1)} clickValue={clickValue}></MockList>
|
||||
<h3>变量</h3>
|
||||
</Col>
|
||||
{
|
||||
this.state.arr.map((ListSourceComponent, index) => {
|
||||
return <Col span={8} className="modal-postman-col" key={index}>
|
||||
<ListSourceComponent index={index} />
|
||||
</Col>
|
||||
})
|
||||
|
||||
}
|
||||
{/* <Col span={8} className="modal-postman-col">
|
||||
{
|
||||
methodsShow ? <MethodsList show={methodsShowMore} click={this.mockClick} clickValue={clickValue}></MethodsList> : <div>没有值</div>
|
||||
}
|
||||
</Col> */}
|
||||
</Row>
|
||||
<Row className="modal-postman-expression">
|
||||
<Col span={6}><h3 className="title">输入值</h3></Col>
|
||||
<Col span={18}><h3>{clickValue}</h3></Col>
|
||||
</Row>
|
||||
<Row className="modal-postman-preview">
|
||||
<Col span={6}><h3 className="title">预览</h3></Col>
|
||||
<Col span={18}><h3>输入值</h3></Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ModalPostman;
|
87
client/components/ModalPostman/index.scss
Normal file
87
client/components/ModalPostman/index.scss
Normal file
@ -0,0 +1,87 @@
|
||||
.modal-postman {
|
||||
.ant-modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.modal-postman-form {
|
||||
padding: 16px;
|
||||
padding-top: 0;
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
.ant-radio-group{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.mock-search {
|
||||
padding-right: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.mock-checked{
|
||||
color:#fff;
|
||||
background-color:#2395f1;
|
||||
width:100%
|
||||
|
||||
|
||||
}
|
||||
.row {
|
||||
margin-bottom: 8px;
|
||||
width:100%;
|
||||
.ant-radio-button-wrapper{
|
||||
border :0
|
||||
}
|
||||
.ant-radio-button-wrapper-checked{
|
||||
color:#fff;
|
||||
background-color:#2395f1;
|
||||
width:100%
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-postman-expression, .modal-postman-preview {
|
||||
border-top: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.modal-postman-expression {
|
||||
}
|
||||
.modal-postman-preview {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.title {
|
||||
border-left: 3px solid #2395f1;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.modal-postman-form-mock{
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.mock-title, .methods-title{
|
||||
margin-bottom: 8px
|
||||
}
|
||||
.modal-postman-form-method{
|
||||
margin-left: 8px;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.methods-row{
|
||||
// border-bottom: 1px solid #e9e9e9;
|
||||
}
|
||||
|
||||
.modal-postman-col{
|
||||
border-right: 1px solid #e9e9e9;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.show-more{
|
||||
color: #2395f1;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.ant-row-flex {
|
||||
flex-wrap: nowrap
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Mock from 'mockjs'
|
||||
|
||||
import { Button, Input, Checkbox, Select, Alert, Spin, Icon, Collapse, Tooltip, message, Switch, Modal, Row, Col } from 'antd'
|
||||
import { Button, Input, Checkbox, Select, Alert, Spin, Icon, Collapse, Tooltip, message, Switch } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import constants from '../../constants/variable.js'
|
||||
|
||||
@ -11,8 +11,9 @@ import URL from 'url';
|
||||
const MockExtra = require('common/mock-extra.js')
|
||||
import './Postman.scss';
|
||||
import json5 from 'json5'
|
||||
import { isJson, handleJson, handleParamsValue } from '../../common.js'
|
||||
import { isJson, handleJson, handleParamsValue } from '../../common.js'
|
||||
import _ from "underscore"
|
||||
import ModalPostman from '../ModalPostman/index.js'
|
||||
|
||||
function json_parse(data) {
|
||||
try {
|
||||
@ -33,7 +34,7 @@ function isJsonData(headers) {
|
||||
return isResJson;
|
||||
}
|
||||
|
||||
const wordList = constants.MOCK_SOURCE;
|
||||
// const wordList = constants.MOCK_SOURCE;
|
||||
|
||||
// const mockDataSource = wordList.map(item => {
|
||||
// return <AutoComplete.Option key={item.mock} value={item.mock}>
|
||||
@ -41,12 +42,12 @@ const wordList = constants.MOCK_SOURCE;
|
||||
// </AutoComplete.Option>
|
||||
// });
|
||||
|
||||
const MockModalList = wordList.map((item, index) => {
|
||||
return <Row key={index} type="flex" align="middle" className="row">
|
||||
<Col span={6}><label>{item.mock}</label></Col>
|
||||
<Col span={18}><Input /></Col>
|
||||
</Row>
|
||||
})
|
||||
// const MockModalList = wordList.map((item, index) => {
|
||||
// return <Row key={index} type="flex" align="middle" className="row">
|
||||
// <Col span={6}><label>{item.mock}</label></Col>
|
||||
// <Col span={18}><Input /></Col>
|
||||
// </Row>
|
||||
// })
|
||||
|
||||
|
||||
|
||||
@ -130,7 +131,7 @@ export default class Run extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleValue (val) {
|
||||
handleValue(val) {
|
||||
return handleParamsValue(val, {});
|
||||
}
|
||||
|
||||
@ -211,18 +212,18 @@ export default class Run extends Component {
|
||||
return;
|
||||
}
|
||||
const { headers, bodyForm, pathParam, bodyOther, caseEnv, domains, method, pathname, query, bodyType } = this.state;
|
||||
|
||||
|
||||
let path = pathname;
|
||||
|
||||
|
||||
pathParam.forEach(item => {
|
||||
path = path.replace(`:${item.name}`, this.handleValue(item.value) || `:${item.name}`);
|
||||
});
|
||||
|
||||
|
||||
const urlObj = URL.parse(URL.resolve(_.find(domains, item => item.name === caseEnv).domain, '.' + path));
|
||||
|
||||
let pathQuery = {};
|
||||
urlObj.query && urlObj.query.split('&').forEach(item=>{
|
||||
if(item){
|
||||
urlObj.query && urlObj.query.split('&').forEach(item => {
|
||||
if (item) {
|
||||
item = item.split('=');
|
||||
pathQuery[item[0]] = item[1];
|
||||
}
|
||||
@ -235,16 +236,16 @@ export default class Run extends Component {
|
||||
query: Object.assign(pathQuery, this.getQueryObj(query))
|
||||
});
|
||||
let reqBody;
|
||||
if(bodyType === 'form'){
|
||||
if (bodyType === 'form') {
|
||||
reqBody = this.arrToObj(bodyForm)
|
||||
}else{
|
||||
} else {
|
||||
reqBody = isJson(bodyOther);
|
||||
if(reqBody === false){
|
||||
if(bodyType === 'json'){
|
||||
if (reqBody === false) {
|
||||
if (bodyType === 'json' && HTTP_METHOD[method].request_body) {
|
||||
return message.error('请求 Body 的 json 格式有误')
|
||||
}
|
||||
}
|
||||
reqBody = bodyOther;
|
||||
}else{
|
||||
} else {
|
||||
reqBody = handleJson(reqBody, this.handleValue)
|
||||
}
|
||||
|
||||
@ -368,8 +369,8 @@ export default class Run extends Component {
|
||||
|
||||
@autobind
|
||||
changeQuery(v, index, key) {
|
||||
v = v.target.value
|
||||
key = key || 'value';
|
||||
v = v.target.value;
|
||||
const query = json_parse(JSON.stringify(this.state.query));
|
||||
if (key == 'enable') {
|
||||
query[index].enable = v;
|
||||
@ -600,8 +601,8 @@ export default class Run extends Component {
|
||||
const pathObj = URL.parse(path);
|
||||
path = pathObj.pathname;
|
||||
let pathQuery = {};
|
||||
pathObj.query && pathObj.query.split('&').forEach(item=>{
|
||||
if(item){
|
||||
pathObj.query && pathObj.query.split('&').forEach(item => {
|
||||
if (item) {
|
||||
item = item.split('=');
|
||||
pathQuery[item[0]] = item[1];
|
||||
}
|
||||
@ -618,7 +619,13 @@ export default class Run extends Component {
|
||||
|
||||
return (
|
||||
<div className="interface-test postman">
|
||||
<Modal
|
||||
<ModalPostman
|
||||
visible={this.state.modalVisible}
|
||||
handleCancel={this.handleCancel}
|
||||
handleOk={this.handleOk}
|
||||
>
|
||||
</ModalPostman>
|
||||
{/* <Modal
|
||||
title={<p><Icon type="bulb" /> Basic Modal</p>}
|
||||
visible={this.state.modalVisible}
|
||||
onOk={this.handleOk}
|
||||
@ -636,7 +643,7 @@ export default class Run extends Component {
|
||||
<Col span={6}><h3 className="title">预览</h3></Col>
|
||||
<Col span={18}><h3>输入值</h3></Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
</Modal> */}
|
||||
<div className={hasPlugin ? null : 'has-plugin'} >
|
||||
{hasPlugin ? '' : <Alert
|
||||
message={
|
||||
@ -720,7 +727,7 @@ export default class Run extends Component {
|
||||
<div key={index} className="key-value-wrap">
|
||||
<Input disabled value={item.name} onChange={e => this.changePathParam(e, index, true)} className="key" />
|
||||
<span className="eq-symbol">=</span>
|
||||
<Input addonAfter={<Icon type="setting" />} defaultValue={item.value} />
|
||||
<Input addonAfter={<Icon type="setting" />} defaultValue={item.value} onChange={e => this.changePathParam(e, index, false)} />
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deletePathParam(index)} />
|
||||
</div>
|
||||
)
|
||||
@ -731,10 +738,10 @@ export default class Run extends Component {
|
||||
<Panel header="QUERY PARAMETERS" key="1" className={query.length === 0 ? 'hidden' : ''}>
|
||||
{
|
||||
query.map((item, index) => {
|
||||
console.log(item.value);
|
||||
console.log(item.value);
|
||||
return (
|
||||
<div key={index} className="key-value-wrap">
|
||||
<Input disabled value={item.name} className="key" />
|
||||
<Input disabled value={item.name} className="key" />
|
||||
|
||||
{item.required == 1 ?
|
||||
<Checkbox checked={true} disabled >enable</Checkbox> :
|
||||
@ -747,9 +754,9 @@ export default class Run extends Component {
|
||||
className="value"
|
||||
onChange={e => this.changeQuery(e, index)}
|
||||
placeholder="参数值"
|
||||
addonAfter={<Icon type="bulb" onClick={this.showModal}/>}
|
||||
addonAfter={<Icon type="edit" onClick={this.showModal} />}
|
||||
/>
|
||||
|
||||
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteQuery(index)} />
|
||||
</div>
|
||||
)
|
||||
|
@ -21,32 +21,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
.modal-postman {
|
||||
.ant-modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.modal-postman-form {
|
||||
padding: 16px;
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
.row {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.modal-postman-expression, .modal-postman-preview {
|
||||
border-top: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.modal-postman-expression {
|
||||
}
|
||||
.modal-postman-preview {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.title {
|
||||
border-left: 3px solid #2395f1;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
// .modal-postman {
|
||||
// .ant-modal-body {
|
||||
// padding: 0;
|
||||
// }
|
||||
// .ant-modal-footer {
|
||||
// background-color: #f5f5f5;
|
||||
// }
|
||||
// .modal-postman-form {
|
||||
// padding: 16px;
|
||||
// max-height: 300px;
|
||||
// overflow-y: scroll;
|
||||
// .row {
|
||||
// margin-bottom: 8px;
|
||||
// }
|
||||
// }
|
||||
// .modal-postman-expression, .modal-postman-preview {
|
||||
// border-top: 1px solid #e9e9e9;
|
||||
// padding: 8px 16px;
|
||||
// }
|
||||
// .modal-postman-expression {
|
||||
// }
|
||||
// .modal-postman-preview {
|
||||
// background-color: #f5f5f5;
|
||||
// }
|
||||
// .title {
|
||||
// border-left: 3px solid #2395f1;
|
||||
// padding-left: 8px;
|
||||
// }
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user