mirror of
https://github.com/YMFE/yapi.git
synced 2024-12-15 05:10:47 +08:00
opti: postman 交互
This commit is contained in:
parent
49c9178ea2
commit
38d4e360dd
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Mock from 'mockjs'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Tooltip, message } from 'antd'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import constants from '../../constants/variable.js'
|
||||
|
||||
@ -20,7 +20,6 @@ function json_parse(data) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isJsonData(headers) {
|
||||
if (!headers || typeof headers !== 'object') return false;
|
||||
let isResJson = false;
|
||||
@ -32,6 +31,15 @@ function isJsonData(headers) {
|
||||
return isResJson;
|
||||
}
|
||||
|
||||
const wordList = constants.MOCK_SOURCE;
|
||||
|
||||
const mockDataSource = wordList.map(item => {
|
||||
return <AutoComplete.Option key={item.mock} value={item.mock}>
|
||||
{item.mock} 随机{item.name}
|
||||
</AutoComplete.Option>
|
||||
});
|
||||
|
||||
|
||||
const { TextArea } = Input;
|
||||
const InputGroup = Input.Group;
|
||||
const Option = Select.Option;
|
||||
@ -127,7 +135,7 @@ export default class Run extends Component {
|
||||
test_status = '',
|
||||
test_res_body = '',
|
||||
test_report = [],
|
||||
test_res_header=''
|
||||
test_res_header = ''
|
||||
} = data;
|
||||
|
||||
// case 任意编辑 pathname,不管项目的 basepath
|
||||
@ -169,12 +177,12 @@ export default class Run extends Component {
|
||||
if (req_body_type && req_body_type !== 'file' && req_body_type !== 'form') {
|
||||
this.loadBodyEditor()
|
||||
}
|
||||
if(test_res_body){
|
||||
if (test_res_body) {
|
||||
this.bindAceEditor();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -278,9 +286,8 @@ export default class Run extends Component {
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeHeader(e, index, isName) {
|
||||
changeHeader(v, index, isName) {
|
||||
const headers = json_parse(JSON.stringify(this.state.headers));
|
||||
const v = e.target.value;
|
||||
if (isName) {
|
||||
headers[index].name = v;
|
||||
} else {
|
||||
@ -306,9 +313,8 @@ export default class Run extends Component {
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeQuery(e, index, isKey) {
|
||||
changeQuery(v, index, isKey) {
|
||||
const query = json_parse(JSON.stringify(this.state.query));
|
||||
const v = e.target.value;
|
||||
if (isKey) {
|
||||
query[index].name = v;
|
||||
} else {
|
||||
@ -328,9 +334,8 @@ export default class Run extends Component {
|
||||
}
|
||||
|
||||
@autobind
|
||||
changePathParam(e, index, isKey) {
|
||||
changePathParam(v, index, isKey) {
|
||||
const pathParam = JSON.parse(JSON.stringify(this.state.pathParam));
|
||||
const v = e.target.value;
|
||||
const name = pathParam[index].name;
|
||||
let newPathname = this.state.pathname;
|
||||
if (isKey) {
|
||||
@ -359,27 +364,12 @@ export default class Run extends Component {
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeBody(e, index, type) {
|
||||
changeBody(v, index) {
|
||||
const bodyForm = json_parse(JSON.stringify(this.state.bodyForm));
|
||||
switch (type) {
|
||||
case 'key':
|
||||
bodyForm[index].name = e.target.value
|
||||
break;
|
||||
case 'type':
|
||||
bodyForm[index].type = e
|
||||
break;
|
||||
case 'value':
|
||||
if (bodyForm[index].type === 'file') {
|
||||
bodyForm[index].value = e.target.id
|
||||
} else {
|
||||
bodyForm[index].value = e.target.value
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (type === 'type' && e === 'file') {
|
||||
//this.setContentType('multipart/form-data')
|
||||
if (bodyForm[index].type === 'file') {
|
||||
bodyForm[index].value = 'file_' + index
|
||||
} else {
|
||||
bodyForm[index].value = v
|
||||
}
|
||||
this.setState({ bodyForm });
|
||||
}
|
||||
@ -603,7 +593,14 @@ 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 value={item.value} onChange={e => this.changePathParam(e, index)} className="value" />
|
||||
<AutoComplete
|
||||
value={item.value}
|
||||
onChange={e => this.changePathParam(e, index)}
|
||||
className="value"
|
||||
dataSource={mockDataSource}
|
||||
placeholder="参数值"
|
||||
optionLabelProp="value"
|
||||
/>
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deletePathParam(index)} />
|
||||
</div>
|
||||
)
|
||||
@ -618,7 +615,14 @@ export default class Run extends Component {
|
||||
<div key={index} className="key-value-wrap">
|
||||
<Input disabled value={item.name} onChange={e => this.changeQuery(e, index, true)} className="key" />
|
||||
<span className="eq-symbol">=</span>
|
||||
<Input value={item.value} onChange={e => this.changeQuery(e, index)} className="value" />
|
||||
<AutoComplete
|
||||
value={item.value}
|
||||
onChange={e => this.changeQuery(e, index)}
|
||||
className="value"
|
||||
dataSource={mockDataSource}
|
||||
placeholder="参数值"
|
||||
optionLabelProp="value"
|
||||
/>
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteQuery(index)} />
|
||||
</div>
|
||||
)
|
||||
@ -633,7 +637,14 @@ export default class Run extends Component {
|
||||
<div key={index} className="key-value-wrap">
|
||||
<Input disabled value={item.name} onChange={e => this.changeHeader(e, index, true)} className="key" />
|
||||
<span className="eq-symbol">=</span>
|
||||
<Input value={item.value} onChange={e => this.changeHeader(e, index)} className="value" />
|
||||
<AutoComplete
|
||||
value={item.value}
|
||||
onChange={e => this.changeHeader(e, index)}
|
||||
className="value"
|
||||
dataSource={mockDataSource}
|
||||
placeholder="参数值"
|
||||
optionLabelProp="value"
|
||||
/>
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteHeader(index)} />
|
||||
</div>
|
||||
)
|
||||
@ -662,7 +673,7 @@ export default class Run extends Component {
|
||||
bodyForm.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className="key-value-wrap">
|
||||
<Input disabled value={item.name} onChange={e => this.changeBody(e, index, 'key')} className="key" />
|
||||
<Input disabled value={item.name} onChange={e => this.changeBody(e, index, 'key')} className="key" />
|
||||
<span>[</span>
|
||||
<Select disabled value={item.type} onChange={e => this.changeBody(e, index, 'type')}>
|
||||
<Option value="file">File</Option>
|
||||
@ -672,7 +683,15 @@ export default class Run extends Component {
|
||||
<span className="eq-symbol">=</span>
|
||||
{item.type === 'file' ?
|
||||
<Input type="file" id={'file_' + index} onChange={e => this.changeBody(e, index, 'value')} multiple className="value" /> :
|
||||
<Input value={item.value} onChange={e => this.changeBody(e, index, 'value')} className="value" />
|
||||
<AutoComplete
|
||||
value={item.value}
|
||||
onChange={e => this.changeBody(e, index, 'value')}
|
||||
className="value"
|
||||
dataSource={mockDataSource}
|
||||
placeholder="参数值"
|
||||
optionLabelProp="value"
|
||||
/>
|
||||
|
||||
}
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteBody(index)} />
|
||||
</div>
|
||||
|
@ -115,5 +115,53 @@ export default {
|
||||
bac: "#fff3cf",
|
||||
color: "#ffbf00"
|
||||
}
|
||||
}
|
||||
},
|
||||
MOCK_SOURCE: [
|
||||
{ name: '字符串', mock: '@string' },
|
||||
{ name: '自然数', mock: '@natural' },
|
||||
{ name: '浮点数', mock: '@float' },
|
||||
{ name: '字符', mock: '@character' },
|
||||
{ name: '布尔', mock: '@boolean' },
|
||||
{ name: 'url', mock: '@url' },
|
||||
{ name: '域名', mock: '@domain' },
|
||||
{ name: 'ip地址', mock: '@ip' },
|
||||
{ name: 'id', mock: '@id' },
|
||||
{ name: 'guid', mock: '@guid' },
|
||||
{ name: '当前时间', mock: '@now' },
|
||||
{ name: '日期', mock: '@date' },
|
||||
{ name: '时间', mock: '@time' },
|
||||
{ name: '日期时间', mock: '@datetime' },
|
||||
{ name: '图片连接', mock: '@image' },
|
||||
{ name: '图片data', mock: "@imageData" },
|
||||
{ name: '颜色', mock: '@color' },
|
||||
{ name: '颜色hex', mock: '@hex' },
|
||||
{ name: '颜色rgba', mock: '@rgba' },
|
||||
{ name: '颜色rgb', mock: '@rgb' },
|
||||
{ name: '颜色hsl', mock: '@hsl' },
|
||||
{ name: '整数', mock: '@integer' },
|
||||
{ name: 'email', mock: '@email' },
|
||||
{ name: '大段文本', mock: '@paragraph' },
|
||||
{ name: '句子', mock: '@sentence' },
|
||||
{ name: '单词', mock: '@word' },
|
||||
{ name: '大段中文文本', mock: '@cparagraph' },
|
||||
{ name: '中文标题', mock: '@ctitle' },
|
||||
{ name: '标题', mock: '@title' },
|
||||
{ name: '姓名', mock: '@name' },
|
||||
{ name: '中文姓名', mock: '@cname' },
|
||||
{ name: '中文姓', mock: '@cfirst' },
|
||||
{ name: '中文名', mock: '@clast' },
|
||||
{ name: '英文姓', mock: '@first' },
|
||||
{ name: '英文名', mock: '@last' },
|
||||
{ name: '中文句子', mock: '@csentence' },
|
||||
{ name: '中文词组', mock: '@cword' },
|
||||
{ name: '地址', mock: '@region' },
|
||||
{ name: '省份', mock: '@province' },
|
||||
{ name: '城市', mock: '@city' },
|
||||
{ name: '地区', mock: '@county' },
|
||||
{ name: '转换为大写', mock: '@upper' },
|
||||
{ name: '转换为小写', mock: '@lower' },
|
||||
{ name: '挑选(枚举)', mock: '@pick' },
|
||||
{ name: '打乱数组', mock: '@shuffle' },
|
||||
{ name: '协议', mock: '@protocol' }
|
||||
]
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ class InterfaceColContent extends Component {
|
||||
|
||||
if (validRes.length === 0) {
|
||||
result.code = 0;
|
||||
result.validRes = [{message: '验证通过'}];
|
||||
result.validRes = [{ message: '验证通过' }];
|
||||
resolve(result);
|
||||
} else if (validRes.length > 0) {
|
||||
result.code = 1;
|
||||
@ -207,23 +207,23 @@ class InterfaceColContent extends Component {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
handleVarWord(val){
|
||||
|
||||
handleVarWord(val) {
|
||||
return simpleJsonPathParse(val, this.records)
|
||||
}
|
||||
|
||||
handleValue(val){
|
||||
if(!val || typeof val !== 'string'){
|
||||
handleValue(val) {
|
||||
if (!val || typeof val !== 'string') {
|
||||
return val;
|
||||
}else if(val[0] === '@'){
|
||||
} else if (val[0] === '@') {
|
||||
return handleMockWord(val);
|
||||
}else if(val.indexOf('$.') === 0){
|
||||
} else if (val.indexOf('$.') === 0) {
|
||||
return this.handleVarWord(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
arrToObj =(arr) =>{
|
||||
arrToObj = (arr) => {
|
||||
arr = arr || [];
|
||||
const obj = {};
|
||||
arr.forEach(item => {
|
||||
@ -234,7 +234,7 @@ class InterfaceColContent extends Component {
|
||||
return obj;
|
||||
}
|
||||
|
||||
getQueryObj =(query)=> {
|
||||
getQueryObj = (query) => {
|
||||
query = query || [];
|
||||
const queryObj = {};
|
||||
query.forEach(item => {
|
||||
@ -244,7 +244,7 @@ class InterfaceColContent extends Component {
|
||||
})
|
||||
return queryObj;
|
||||
}
|
||||
getHeadersObj = (headers) =>{
|
||||
getHeadersObj = (headers) => {
|
||||
headers = headers || [];
|
||||
const headersObj = {};
|
||||
headers.forEach(item => {
|
||||
@ -409,7 +409,9 @@ class InterfaceColContent extends Component {
|
||||
|
||||
return (
|
||||
<div className="interface-col">
|
||||
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合</h2>
|
||||
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合 <a target="_blank" rel="noopener noreferrer" href="https://yapi.ymfe.org/case.html" >
|
||||
<Tooltip title="点击查看文档"><Icon type="question-circle-o" /></Tooltip>
|
||||
</a></h2>
|
||||
<Button type="primary" style={{ float: 'right' }} onClick={this.executeTests}>开始测试</Button>
|
||||
<Table.Provider
|
||||
components={components}
|
||||
|
@ -30,7 +30,6 @@ var langTools = ace.acequire("ace/ext/language_tools"),
|
||||
{ name: '颜色rgb', mock: '@rgb' },
|
||||
{ name: '颜色hsl', mock: '@hsl' },
|
||||
{ name: '整数', mock: '@integer' },
|
||||
{ name: '浮点数', mock: '@float' },
|
||||
{ name: 'email', mock: '@email' },
|
||||
{ name: '大段文本', mock: '@paragraph' },
|
||||
{ name: '句子', mock: '@sentence' },
|
||||
|
Loading…
Reference in New Issue
Block a user