mirror of
https://github.com/YMFE/yapi.git
synced 2025-03-07 14:16:52 +08:00
fix: method 为空
This commit is contained in:
commit
09069c6df4
@ -86,11 +86,28 @@ exports.handlePath = (path) => {
|
||||
return path;
|
||||
}
|
||||
|
||||
// 返回字符串长度,汉字计数为2
|
||||
exports.strLength = (str) => {
|
||||
let length = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
str.charCodeAt(i) > 255 ? length += 2 : length++;
|
||||
// 名称限制 20 字符
|
||||
exports.nameLengthLimit = (type) => {
|
||||
// 返回字符串长度,汉字计数为2
|
||||
const strLength = (str) => {
|
||||
let length = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
str.charCodeAt(i) > 255 ? length += 2 : length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
return length;
|
||||
// 返回 form中的 rules 校验规则
|
||||
return [{
|
||||
required: true,
|
||||
validator(rule, value, callback) {
|
||||
const len = value ? strLength(value) : 0;
|
||||
if (len > 20) {
|
||||
callback('请输入' + type + '名称,长度不超过20字符(中文算作2字符)!');
|
||||
} else if (len === 0) {
|
||||
callback('请输入' + type + '名称,长度不超过20字符(中文算作2字符)!');
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
@ -1,19 +1,30 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Mock from 'mockjs'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Radio, Tooltip, message } from 'antd'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Tooltip, message } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import constants from '../../constants/variable.js'
|
||||
|
||||
import mockEditor from '../../containers/Project/Interface/InterfaceList/mockEditor'
|
||||
import URL from 'url';
|
||||
const MockExtra = require('common/mock-extra.js')
|
||||
import './Postman.scss';
|
||||
import json5 from 'json5'
|
||||
|
||||
function json_parse(data) {
|
||||
try {
|
||||
return json5.parse(data)
|
||||
} catch (e) {
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
const { TextArea } = Input;
|
||||
const InputGroup = Input.Group;
|
||||
const Option = Select.Option;
|
||||
const Panel = Collapse.Panel;
|
||||
const RadioButton = Radio.Button;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
const HTTP_METHOD = constants.HTTP_METHOD;
|
||||
|
||||
export default class Run extends Component {
|
||||
|
||||
@ -47,17 +58,17 @@ export default class Run extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
let startTime = 0;
|
||||
this.interval = setInterval(()=>{
|
||||
this.interval = setInterval(() => {
|
||||
startTime += 500;
|
||||
if(startTime > 5000){
|
||||
if (startTime > 5000) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
if(window.crossRequest){
|
||||
if (window.crossRequest) {
|
||||
clearInterval(this.interval);
|
||||
this.setState({
|
||||
hasPlugin: true
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
this.setState({
|
||||
hasPlugin: false
|
||||
})
|
||||
@ -66,7 +77,7 @@ export default class Run extends Component {
|
||||
this.getInterfaceState()
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
|
||||
@ -78,7 +89,7 @@ export default class Run extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
const { bodyType } = this.state;
|
||||
if(bodyType && bodyType !== 'file' && bodyType !== 'form') {
|
||||
if (bodyType && bodyType !== 'file' && bodyType !== 'form') {
|
||||
this.loadBodyEditor()
|
||||
}
|
||||
}
|
||||
@ -132,7 +143,7 @@ export default class Run extends Component {
|
||||
bodyType: req_body_type || 'form',
|
||||
loading: false
|
||||
}, () => {
|
||||
if(req_body_type && req_body_type !== 'file' && req_body_type !== 'form') {
|
||||
if (req_body_type && req_body_type !== 'file' && req_body_type !== 'form') {
|
||||
this.loadBodyEditor()
|
||||
}
|
||||
});
|
||||
@ -142,7 +153,7 @@ export default class Run extends Component {
|
||||
reqRealInterface() {
|
||||
if (this.state.loading) {
|
||||
this.setState({ loading: false })
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
const { headers, bodyForm, pathParam, bodyOther, caseEnv, domains, method, pathname, query, bodyType } = this.state;
|
||||
const urlObj = URL.parse(domains.find(item => item.name === caseEnv).domain);
|
||||
@ -159,7 +170,7 @@ export default class Run extends Component {
|
||||
});
|
||||
|
||||
this.setState({ loading: true })
|
||||
|
||||
let that = this;
|
||||
window.crossRequest({
|
||||
url: href,
|
||||
method,
|
||||
@ -169,62 +180,61 @@ export default class Run extends Component {
|
||||
success: (res, header) => {
|
||||
try {
|
||||
if (header && header['content-type'] && header['content-type'].indexOf('application/json') !== -1) {
|
||||
res = typeof res === 'object' ? res : JSON.parse(res)
|
||||
res = typeof res !== 'string' ? res : json_parse(res)
|
||||
}
|
||||
if (header) {
|
||||
header = typeof header === 'object' ? header : JSON.parse(header)
|
||||
header = typeof header !== 'string' ? header : json_parse(header)
|
||||
}
|
||||
|
||||
const { res_body, res_body_type } = that.props.data;
|
||||
let validRes = '';
|
||||
let query = {};
|
||||
that.state.query.forEach(item => {
|
||||
query[item.name] = item.value;
|
||||
})
|
||||
let body = {};
|
||||
if (that.state.bodyType === 'form') {
|
||||
that.state.bodyForm.forEach(item => {
|
||||
body[item.name] = item.value;
|
||||
})
|
||||
} else if (that.state.bodyType === 'json') {
|
||||
try {
|
||||
body = json_parse(that.state.bodyOther);
|
||||
} catch (e) {
|
||||
body = ''
|
||||
}
|
||||
}
|
||||
if (res_body && res_body_type === 'json' && typeof res === 'object') {
|
||||
let tpl = MockExtra(json_parse(res_body), {
|
||||
query: query,
|
||||
body: body
|
||||
})
|
||||
validRes = Mock.valid(tpl, res)
|
||||
}
|
||||
|
||||
message.success('请求完成')
|
||||
that.setState({ res, resHeader: header, validRes })
|
||||
that.setState({ loading: false })
|
||||
that.bindAceEditor()
|
||||
} catch (e) {
|
||||
message.error(e.message)
|
||||
console.error(e.message)
|
||||
}
|
||||
const { res_body, res_body_type } = this.props.data;
|
||||
let validRes = '';
|
||||
let query = {};
|
||||
this.state.query.forEach(item=>{
|
||||
query[item.name] = item.value;
|
||||
})
|
||||
let body = {};
|
||||
if(this.state.bodyType === 'form'){
|
||||
this.state.bodyForm.forEach(item=>{
|
||||
body[item.name] = item.value;
|
||||
})
|
||||
}else if(this.state.bodyType === 'json'){
|
||||
try{
|
||||
body = JSON.parse(this.state.bodyOther);
|
||||
}catch(e){
|
||||
body = {}
|
||||
}
|
||||
}
|
||||
if (res_body && res_body_type === 'json' && typeof res === 'object') {
|
||||
let tpl = MockExtra(JSON.parse(res_body), {
|
||||
query: query,
|
||||
body: body
|
||||
})
|
||||
console.log(tpl, this.state)
|
||||
validRes = Mock.valid(tpl, res)
|
||||
console.log(validRes)
|
||||
}
|
||||
|
||||
message.success('请求完成')
|
||||
this.setState({res, resHeader: header, validRes})
|
||||
this.setState({ loading: false })
|
||||
this.bindAceEditor()
|
||||
},
|
||||
error: (err, header) => {
|
||||
try {
|
||||
if (header && header['content-type'] && header['content-type'].indexOf('application/json') !== -1) {
|
||||
err = typeof err === 'object' ? err : JSON.parse(err)
|
||||
err = typeof err === 'object' ? err : json_parse(err)
|
||||
}
|
||||
if (header) {
|
||||
header = typeof header === 'object' ? header : JSON.parse(header)
|
||||
header = typeof header === 'object' ? header : json_parse(header)
|
||||
}
|
||||
} catch (e) {
|
||||
message.error(e.message)
|
||||
}
|
||||
message.success('请求完成')
|
||||
this.setState({res: err || '请求失败', resHeader: header, validRes: null})
|
||||
this.setState({ loading: false })
|
||||
this.bindAceEditor()
|
||||
that.setState({ res: err || '请求失败', resHeader: header, validRes: null })
|
||||
that.setState({ loading: false })
|
||||
that.bindAceEditor()
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -241,7 +251,7 @@ export default class Run extends Component {
|
||||
|
||||
@autobind
|
||||
changeHeader(e, index, isName) {
|
||||
const headers = JSON.parse(JSON.stringify(this.state.headers));
|
||||
const headers = json_parse(JSON.stringify(this.state.headers));
|
||||
const v = e.target.value;
|
||||
if (isName) {
|
||||
headers[index].name = v;
|
||||
@ -253,23 +263,23 @@ export default class Run extends Component {
|
||||
@autobind
|
||||
addHeader() {
|
||||
const { headers } = this.state;
|
||||
this.setState({headers: headers.concat([{name: '', value: ''}])})
|
||||
this.setState({ headers: headers.concat([{ name: '', value: '' }]) })
|
||||
}
|
||||
@autobind
|
||||
deleteHeader(index) {
|
||||
const { headers } = this.state;
|
||||
this.setState({headers: headers.filter((item, i) => +index !== +i)});
|
||||
this.setState({ headers: headers.filter((item, i) => +index !== +i) });
|
||||
}
|
||||
@autobind
|
||||
setContentType(type) {
|
||||
const headersObj = this.getHeadersObj(this.state.headers);
|
||||
headersObj['Content-Type'] = type;
|
||||
this.setState({headers: this.objToArr(headersObj)})
|
||||
this.setState({ headers: this.objToArr(headersObj) })
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeQuery(e, index, isKey) {
|
||||
const query = JSON.parse(JSON.stringify(this.state.query));
|
||||
const query = json_parse(JSON.stringify(this.state.query));
|
||||
const v = e.target.value;
|
||||
if (isKey) {
|
||||
query[index].name = v;
|
||||
@ -281,12 +291,12 @@ export default class Run extends Component {
|
||||
@autobind
|
||||
addQuery() {
|
||||
const { query } = this.state;
|
||||
this.setState({query: query.concat([{name: '', value: ''}])})
|
||||
this.setState({ query: query.concat([{ name: '', value: '' }]) })
|
||||
}
|
||||
@autobind
|
||||
deleteQuery(index) {
|
||||
const { query } = this.state;
|
||||
this.setState({query: query.filter((item, i) => +index !== +i)});
|
||||
this.setState({ query: query.filter((item, i) => +index !== +i) });
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -310,19 +320,19 @@ export default class Run extends Component {
|
||||
@autobind
|
||||
addPathParam() {
|
||||
const { pathParam } = this.state;
|
||||
this.setState({pathParam: pathParam.concat([{name: '', value: ''}])})
|
||||
this.setState({ pathParam: pathParam.concat([{ name: '', value: '' }]) })
|
||||
}
|
||||
@autobind
|
||||
deletePathParam(index) {
|
||||
const { pathParam } = this.state;
|
||||
const name = pathParam[index].name;
|
||||
const newPathname = this.state.pathname.replace(`/:${name}`, '');
|
||||
this.setState({pathParam: pathParam.filter((item, i) => +index !== +i), pathname: newPathname});
|
||||
this.setState({ pathParam: pathParam.filter((item, i) => +index !== +i), pathname: newPathname });
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeBody(e, index, type) {
|
||||
const bodyForm = JSON.parse(JSON.stringify(this.state.bodyForm));
|
||||
const bodyForm = json_parse(JSON.stringify(this.state.bodyForm));
|
||||
switch (type) {
|
||||
case 'key':
|
||||
bodyForm[index].name = e.target.value
|
||||
@ -348,12 +358,12 @@ export default class Run extends Component {
|
||||
@autobind
|
||||
addBody() {
|
||||
const { bodyForm } = this.state;
|
||||
this.setState({bodyForm: bodyForm.concat([{name: '', value: '', type: 'text'}])})
|
||||
this.setState({ bodyForm: bodyForm.concat([{ name: '', value: '', type: 'text' }]) })
|
||||
}
|
||||
@autobind
|
||||
deleteBody(index) {
|
||||
const { bodyForm } = this.state;
|
||||
this.setState({bodyForm: bodyForm.filter((item, i) => +index !== +i)});
|
||||
this.setState({ bodyForm: bodyForm.filter((item, i) => +index !== +i) });
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -373,8 +383,8 @@ export default class Run extends Component {
|
||||
|
||||
@autobind
|
||||
changeBodyType(value) {
|
||||
this.setState({bodyType: value}, () => {
|
||||
if(value !== 'file' && value !== 'form') {
|
||||
this.setState({ bodyType: value }, () => {
|
||||
if (value !== 'file' && value !== 'form') {
|
||||
this.loadBodyEditor()
|
||||
}
|
||||
})
|
||||
@ -391,7 +401,7 @@ export default class Run extends Component {
|
||||
const arr = []
|
||||
Object.keys(obj).forEach((_key) => {
|
||||
if (_key) {
|
||||
arr.push({[keyName]: _key, [valueName]: obj[_key]});
|
||||
arr.push({ [keyName]: _key, [valueName]: obj[_key] });
|
||||
}
|
||||
})
|
||||
return arr;
|
||||
@ -437,19 +447,19 @@ export default class Run extends Component {
|
||||
mockEditor({
|
||||
container: 'res-body-pretty',
|
||||
data: JSON.stringify(this.state.res, null, 2),
|
||||
readOnly:true,
|
||||
onChange: function () {}
|
||||
readOnly: true,
|
||||
onChange: function () { }
|
||||
})
|
||||
mockEditor({
|
||||
container: 'res-headers-pretty',
|
||||
data: JSON.stringify(this.state.resHeader, null, 2),
|
||||
readOnly:true,
|
||||
onChange: function () {}
|
||||
data: JSON.stringify(this.state.resHeader, null, 2),
|
||||
readOnly: true,
|
||||
onChange: function () { }
|
||||
})
|
||||
}
|
||||
loadBodyEditor = () => {
|
||||
const that = this;
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
mockEditor({
|
||||
container: 'body-other-edit',
|
||||
data: that.state.bodyOther,
|
||||
@ -469,75 +479,89 @@ export default class Run extends Component {
|
||||
console.log(index)
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
render() {
|
||||
const { method, domains, pathParam, pathname, query, headers, bodyForm, caseEnv, bodyType, resHeader, loading, validRes } = this.state;
|
||||
HTTP_METHOD[method] = HTTP_METHOD[method] || {}
|
||||
const hasPlugin = this.state.hasPlugin;
|
||||
let isResJson = false;
|
||||
resHeader && Object.keys(resHeader).map(key => {
|
||||
if (/content-type/i.test(key) && /application\/json/i.test(resHeader[key])) {
|
||||
isResJson = true;
|
||||
}
|
||||
})
|
||||
if (resHeader && typeof resHeader === 'object') {
|
||||
Object.keys(resHeader).map(key => {
|
||||
if (/content-type/i.test(key) && /application\/json/i.test(resHeader[key])) {
|
||||
isResJson = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
let path = pathname;
|
||||
pathParam.forEach(item => {
|
||||
path = path.replace(`:${item.name}`, item.value || `:${item.name}`);
|
||||
});
|
||||
const search = decodeURIComponent(URL.format({query: this.getQueryObj(query)}));
|
||||
const search = decodeURIComponent(URL.format({ query: this.getQueryObj(query) }));
|
||||
|
||||
let validResView;
|
||||
if (!validRes) {
|
||||
validResView = '请定义返回json'
|
||||
}
|
||||
if (Array.isArray(validRes) && validRes.length > 0) {
|
||||
validResView = validRes.map((item, index) => {
|
||||
return <div key={index}>{item.message}</div>
|
||||
})
|
||||
} else if (Array.isArray(validRes)) {
|
||||
validResView = <p>验证通过</p>
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="interface-test postman">
|
||||
<div className="has-plugin">
|
||||
{
|
||||
hasPlugin ? '' :
|
||||
<Alert
|
||||
message={
|
||||
<div className="has-plugin">
|
||||
{hasPlugin ? '' : <Alert
|
||||
message={
|
||||
<div>
|
||||
温馨提示:当前正在使用接口测试服务,请安装我们为您免费提供的测试增强插件 (该插件可支持任何 chrome 内核的浏览器)
|
||||
<div>
|
||||
温馨提示:当前正在使用接口测试服务,请安装我们为您免费提供的测试增强插件 (该插件可支持任何 chrome 内核的浏览器)
|
||||
<div>
|
||||
<a
|
||||
target="blank"
|
||||
href="https://chrome.google.com/webstore/detail/cross-request/cmnlfmgbjmaciiopcgodlhpiklaghbok?hl=en-US"
|
||||
> [Google 商店获取(需翻墙)]</a>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
target="blank"
|
||||
href="/attachment/cross-request.zip"
|
||||
> [手动下载] </a>
|
||||
<span> zip 文件解压后将 crx 文件拖入到 chrome://extensions/ </span>
|
||||
<a
|
||||
target="blank"
|
||||
href="http://www.jianshu.com/p/12ca04c61fc6"
|
||||
> [详细安装教程] </a>
|
||||
</div>
|
||||
<a
|
||||
target="blank"
|
||||
href="https://chrome.google.com/webstore/detail/cross-request/cmnlfmgbjmaciiopcgodlhpiklaghbok?hl=en-US"
|
||||
> [Google 商店获取(需翻墙)]</a>
|
||||
</div>
|
||||
}
|
||||
type="warning"
|
||||
/>
|
||||
<div>
|
||||
<a
|
||||
target="blank"
|
||||
href="/attachment/cross-request.zip"
|
||||
> [手动下载] </a>
|
||||
<span> zip 文件解压后将 crx 文件拖入到 chrome://extensions/ </span>
|
||||
<a
|
||||
target="blank"
|
||||
href="http://www.jianshu.com/p/12ca04c61fc6"
|
||||
> [详细安装教程] </a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
type="warning"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<Card title="请求部分" noHovering className="req-part">
|
||||
<div className="url">
|
||||
<InputGroup compact style={{display: 'flex'}}>
|
||||
<Select disabled value={method} style={{flexBasis: 60}} onChange={this.changeMethod} >
|
||||
<InputGroup compact style={{ display: 'flex' }}>
|
||||
<Select disabled value={method} style={{ flexBasis: 60 }} onChange={this.changeMethod} >
|
||||
<Option value="GET">GET</Option>
|
||||
<Option value="POST">POST</Option>
|
||||
</Select>
|
||||
<Select value={caseEnv} style={{flexBasis: 180, flexGrow: 1}} onSelect={this.selectDomain}>
|
||||
<Select value={caseEnv} style={{ flexBasis: 180, flexGrow: 1 }} onSelect={this.selectDomain}>
|
||||
{
|
||||
domains.map((item, index) => (<Option value={item.name} key={index}>{item.name + ':' + item.domain}</Option>))
|
||||
}
|
||||
</Select>
|
||||
<Input disabled value={path + search} onChange={this.changePath} spellCheck="false" style={{flexBasis: 180, flexGrow: 1}} />
|
||||
<Input disabled value={path + search} onChange={this.changePath} spellCheck="false" style={{ flexBasis: 180, flexGrow: 1 }} />
|
||||
</InputGroup>
|
||||
<Tooltip placement="bottom" title="请求真实接口">
|
||||
<Button
|
||||
disabled={!hasPlugin}
|
||||
onClick={this.reqRealInterface}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
style={{ marginLeft: 10 }}
|
||||
icon={loading ? 'loading' : ''}
|
||||
>{loading ? '取消' : '发送'}</Button>
|
||||
</Tooltip>
|
||||
@ -545,7 +569,7 @@ export default class Run extends Component {
|
||||
<Button
|
||||
onClick={this.props.save}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
style={{ marginLeft: 10 }}
|
||||
>{this.props.type === 'inter' ? '保存' : '更新'}</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@ -559,12 +583,12 @@ export default class Run extends Component {
|
||||
<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" />
|
||||
<Icon style={{display: 'none'}} type="delete" className="icon-btn" onClick={() => this.deletePathParam(index)} />
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deletePathParam(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button style={{display: 'none'}} type="primary" icon="plus" onClick={this.addPathParam}>添加Path参数</Button>
|
||||
<Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addPathParam}>添加Path参数</Button>
|
||||
</Panel>
|
||||
<Panel header="QUERY PARAMETERS" key="1" className={query.length === 0 ? 'hidden' : ''}>
|
||||
{
|
||||
@ -574,12 +598,12 @@ export default class Run extends Component {
|
||||
<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" />
|
||||
<Icon style={{display: 'none'}} type="delete" className="icon-btn" onClick={() => this.deleteQuery(index)} />
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteQuery(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button style={{display: 'none'}} type="primary" icon="plus" onClick={this.addQuery}>添加Query参数</Button>
|
||||
<Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addQuery}>添加Query参数</Button>
|
||||
</Panel>
|
||||
<Panel header="HEADERS" key="2" className={headers.length === 0 ? 'hidden' : ''}>
|
||||
{
|
||||
@ -589,43 +613,31 @@ export default class Run extends Component {
|
||||
<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" />
|
||||
<Icon style={{display: 'none'}} type="delete" className="icon-btn" onClick={() => this.deleteHeader(index)} />
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteHeader(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button style={{display: 'none'}} type="primary" icon="plus" onClick={this.addHeader}>添加Header</Button>
|
||||
<Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addHeader}>添加Header</Button>
|
||||
</Panel>
|
||||
<Panel
|
||||
header={
|
||||
<div style={{display: 'flex', justifyContent: 'space-between'}}>
|
||||
<div>BODY</div>
|
||||
<div onClick={e => e.stopPropagation()} style={{marginRight: 5}}>
|
||||
<Select disabled value={bodyType !== 'form' && bodyType !== 'file' ? 'text' : bodyType} onChange={this.changeBodyType} className={method === 'POST' ? '' : 'none'}>
|
||||
<Option value="text">Text</Option>
|
||||
<Option value="file">File</Option>
|
||||
<Option value="form">Form</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<div>BODY</div>
|
||||
</div>
|
||||
}
|
||||
key="3"
|
||||
className={method === 'POST' ? '' : 'hidden'}
|
||||
className={HTTP_METHOD[method].request_body?'POST':'hidden'}
|
||||
>
|
||||
{ method === 'POST' && bodyType !== 'form' && bodyType !== 'file' &&
|
||||
<div>
|
||||
<RadioGroup disabled value={bodyType} onChange={(e) => this.changeBodyType(e.target.value)}>
|
||||
<RadioButton value="json">JSON</RadioButton>
|
||||
<RadioButton value="text">TEXT</RadioButton>
|
||||
<RadioButton value="xml">XML</RadioButton>
|
||||
</RadioGroup>
|
||||
<div id="body-other-edit" style={{marginTop: 10}} className="pretty-editor"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div style={{ display: HTTP_METHOD[method].request_body && bodyType !== 'form' && bodyType !== 'file'? 'block': 'none' }}>
|
||||
<div id="body-other-edit" style={{ marginTop: 10 }} className="pretty-editor"></div>
|
||||
</div>
|
||||
|
||||
{
|
||||
method === 'POST' && bodyType === 'form' &&
|
||||
HTTP_METHOD[method].request_body && bodyType === 'form' &&
|
||||
<div>
|
||||
{
|
||||
{
|
||||
bodyForm.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className="key-value-wrap">
|
||||
@ -637,16 +649,16 @@ export default class Run extends Component {
|
||||
</Select>
|
||||
<span>]</span>
|
||||
<span className="eq-symbol">=</span>
|
||||
{
|
||||
item.type === 'file' ? <Input type="file" id={'file_' + index} onChange={e => this.changeBody(e, index, 'value')} multiple className="value" /> :
|
||||
{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" />
|
||||
}
|
||||
<Icon style={{display: 'none'}} type="delete" className="icon-btn" onClick={() => this.deleteBody(index)} />
|
||||
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteBody(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button style={{display: 'none'}} type="primary" icon="plus" onClick={this.addBody}>添加Form参数</Button>
|
||||
<Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addBody}>添加Form参数</Button>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
@ -668,25 +680,23 @@ export default class Run extends Component {
|
||||
<div className="res-code"></div>
|
||||
<Collapse defaultActiveKey={['0', '1']} bordered={true}>
|
||||
<Panel header="BODY" key="0" >
|
||||
<div id="res-body-pretty" className="pretty-editor" style={{display: isResJson ? '' : 'none'}}></div>
|
||||
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>
|
||||
<TextArea
|
||||
style={{display: isResJson ? 'none' : ''}}
|
||||
style={{ display: isResJson ? 'none' : '' }}
|
||||
value={this.state.res && this.state.res.toString()}
|
||||
autosize={{ minRows: 2, maxRows: 10 }}
|
||||
></TextArea>
|
||||
<div style={{display: validRes ? '' : 'none', marginTop: 6, fontWeight: 'bold'}}>返回 Body 验证结果:</div>
|
||||
<TextArea
|
||||
style={{display: validRes ? '' : 'none'}}
|
||||
value={validRes && (validRes.length ? JSON.stringify(validRes.map(item => item.message), null, 2) : '恭喜:验证通过!')}
|
||||
autosize={{ minRows: 2, maxRows: 10 }}
|
||||
autosize={{ minRows: 10, maxRows: 20 }}
|
||||
></TextArea>
|
||||
<h3 style={{ marginTop: '15px', display: isResJson ? '' : 'none' }}>返回 Body 验证结果:</h3>
|
||||
<div style={{ display: isResJson ? '' : 'none' }}>
|
||||
{validResView}
|
||||
</div>
|
||||
</Panel>
|
||||
<Panel header="HEADERS" key="1" >
|
||||
{/*<TextArea
|
||||
value={typeof this.state.resHeader === 'object' ? JSON.stringify(this.state.resHeader, null, 2) : this.state.resHeader.toString()}
|
||||
autosize={{ minRows: 2, maxRows: 10 }}
|
||||
></TextArea>*/}
|
||||
<div id="res-headers-pretty" className="pretty-editor"></div>
|
||||
<div id="res-headers-pretty" className="pretty-editor-header"></div>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
</Spin>
|
||||
|
@ -2,6 +2,15 @@
|
||||
.pretty-editor {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
height: 200px;
|
||||
}
|
||||
.pretty-editor-body {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
min-height: 300px;
|
||||
}
|
||||
.pretty-editor-header {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
export default {
|
||||
PAGE_LIMIT: 10, // 默认每页展示10条数据
|
||||
NAME_LIMIT: 20, // 限制名称的字符长度(中文算两个长度)
|
||||
HTTP_METHOD: {
|
||||
'GET': {
|
||||
request_body: false
|
||||
|
@ -10,7 +10,7 @@ const { TextArea } = Input;
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RadioGroup = Radio.Group;
|
||||
import { pickRandomProperty, handlePath } from '../../common';
|
||||
import { pickRandomProperty, handlePath, nameLengthLimit } from '../../common';
|
||||
import constants from '../../constants/variable.js';
|
||||
import { withRouter } from 'react-router';
|
||||
import './Addproject.scss';
|
||||
@ -103,9 +103,7 @@ class ProjectList extends Component {
|
||||
label="项目名称"
|
||||
>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [{
|
||||
required: true, message: '请输入项目名称!'
|
||||
}]
|
||||
rules: nameLengthLimit('项目')
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||
import { Form, Input, Select, Button } from 'antd';
|
||||
|
||||
import constants from '../../../../constants/variable.js'
|
||||
import { handlePath } from '../../../../common.js'
|
||||
import { handlePath, nameLengthLimit } from '../../../../common.js'
|
||||
const HTTP_METHOD = constants.HTTP_METHOD;
|
||||
const HTTP_METHOD_KEYS = Object.keys(HTTP_METHOD);
|
||||
|
||||
@ -83,9 +83,7 @@ class AddInterfaceForm extends Component {
|
||||
label="接口名称"
|
||||
>
|
||||
{getFieldDecorator('title', {
|
||||
rules: [{
|
||||
required: true, message: '清输入接口名称!'
|
||||
}]
|
||||
rules: nameLengthLimit('接口')
|
||||
})(
|
||||
<Input placeholder="接口名称" />
|
||||
)}
|
||||
|
@ -65,6 +65,10 @@ class InterfaceEdit extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
let domain = location.hostname + (location.port !== "" ? ":" + location.port : "");
|
||||
this.setState({
|
||||
curdata: this.props.curdata,
|
||||
status: 1
|
||||
})
|
||||
|
||||
let s = new WebSocket('ws://' + domain + '/api/interface/solve_conflict?id=' + this.props.match.params.actionId);
|
||||
s.onopen = () => {
|
||||
@ -87,11 +91,8 @@ class InterfaceEdit extends Component {
|
||||
|
||||
}
|
||||
|
||||
s.onerror = () => {
|
||||
this.setState({
|
||||
curdata: this.props.curdata,
|
||||
status: 1
|
||||
})
|
||||
s.onerror = () => {
|
||||
console.error('websocket connect failed.')
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import _ from 'underscore'
|
||||
import constants from '../../../../constants/variable.js'
|
||||
import { handlePath } from '../../../../common.js'
|
||||
import { handlePath, nameLengthLimit } from '../../../../common.js'
|
||||
import json5 from 'json5'
|
||||
import {message} from 'antd'
|
||||
|
||||
@ -96,7 +96,7 @@ class InterfaceEditForm extends Component {
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
if (values.res_body_type === 'json') {
|
||||
@ -111,9 +111,9 @@ class InterfaceEditForm extends Component {
|
||||
}
|
||||
values.req_body_other = this.state.req_body_other;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
values.method = this.state.method;
|
||||
values.req_params = values.req_params || [];
|
||||
let isfile = false, isHavaContentType = false;
|
||||
@ -168,7 +168,7 @@ class InterfaceEditForm extends Component {
|
||||
mockEditor({
|
||||
container: 'req_body_json',
|
||||
data: that.state.req_body_other,
|
||||
onChange: function (d) {
|
||||
onChange: function (d) {
|
||||
that.setState({
|
||||
req_body_other: d.text
|
||||
})
|
||||
@ -181,7 +181,7 @@ class InterfaceEditForm extends Component {
|
||||
onChange: function (d) {
|
||||
if (d.format === true){
|
||||
mockPreview.editor.setValue(d.mockText)
|
||||
}
|
||||
}
|
||||
that.setState({
|
||||
res_body: d.text,
|
||||
res_body_mock: d.mockText
|
||||
@ -392,9 +392,7 @@ class InterfaceEditForm extends Component {
|
||||
>
|
||||
{getFieldDecorator('title', {
|
||||
initialValue: this.state.title,
|
||||
rules: [{
|
||||
required: true, message: '请输入接口名称!'
|
||||
}]
|
||||
rules: nameLengthLimit('接口')
|
||||
})(
|
||||
<Input placeholder="接口名称" />
|
||||
)}
|
||||
|
@ -89,7 +89,6 @@ class InterfaceMenu extends Component {
|
||||
|
||||
async getList(){
|
||||
let r = await this.props.fetchInterfaceList(this.props.projectId);
|
||||
console.log(r.payload.data)
|
||||
this.setState({
|
||||
list: JSON.parse(JSON.stringify(r.payload.data))
|
||||
})
|
||||
@ -267,7 +266,7 @@ class InterfaceMenu extends Component {
|
||||
}
|
||||
if (router) {
|
||||
if (!isNaN(router.params.actionId)) {
|
||||
if (!inter._id) {
|
||||
if (!inter || !inter._id) {
|
||||
return rNull;
|
||||
}
|
||||
return {
|
||||
|
@ -106,7 +106,7 @@ function run(options) {
|
||||
if (typeof data === 'string') {
|
||||
editor.setValue(data);
|
||||
} else if (typeof data === 'object') {
|
||||
editor.setValue(json5(data, null, " "))
|
||||
editor.setValue(JSON.stringify(data, null, " "))
|
||||
}
|
||||
},
|
||||
editor: editor
|
||||
|
@ -12,6 +12,7 @@ const RadioGroup = Radio.Group;
|
||||
const RadioButton = Radio.Button;
|
||||
import constants from '../../../../constants/variable.js';
|
||||
const confirm = Modal.confirm;
|
||||
import { nameLengthLimit } from '../../../../common';
|
||||
import '../Setting.scss';
|
||||
// layout
|
||||
const formItemLayout = {
|
||||
@ -345,9 +346,7 @@ class ProjectMessage extends Component {
|
||||
>
|
||||
{getFieldDecorator('name', {
|
||||
initialValue: initFormValues.name,
|
||||
rules: [{
|
||||
required: true, message: '请输入项目名称!'
|
||||
}]
|
||||
rules: nameLengthLimit('项目')
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
|
@ -5,7 +5,6 @@ import App from './Application'
|
||||
import { Provider } from 'react-redux'
|
||||
import createStore from './reducer/create';
|
||||
import './styles/theme.less'
|
||||
console.log('index.js')
|
||||
const store = createStore();
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
ReactDOM.render(
|
||||
|
@ -323,6 +323,7 @@ class interfaceColController extends baseController{
|
||||
value[item.name] = item;
|
||||
})
|
||||
params.forEach((item, index)=>{
|
||||
if(!value[item.name] || typeof value[item.name] !== 'object') return null;
|
||||
params[index].value = value[item.name].value;
|
||||
})
|
||||
return params;
|
||||
|
Loading…
Reference in New Issue
Block a user