fix: method 为空

This commit is contained in:
zwjamnsss 2017-09-08 11:09:17 +08:00
commit 09069c6df4
13 changed files with 222 additions and 192 deletions

View File

@ -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();
}
}
}]
}

View File

@ -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>
温馨提示当前正在使用接口测试服务请安装我们为您免费提供的测试增强插件&nbsp;该插件可支持任何 chrome 内核的浏览器
<div>
温馨提示当前正在使用接口测试服务请安装我们为您免费提供的测试增强插件&nbsp;该插件可支持任何 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>

View File

@ -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;
}
}

View File

@ -1,5 +1,6 @@
export default {
PAGE_LIMIT: 10, // 默认每页展示10条数据
NAME_LIMIT: 20, // 限制名称的字符长度(中文算两个长度)
HTTP_METHOD: {
'GET': {
request_body: false

View File

@ -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 />
)}

View File

@ -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="接口名称" />
)}

View File

@ -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.')
}

View File

@ -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="接口名称" />
)}

View File

@ -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 {

View File

@ -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

View File

@ -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 />
)}

View File

@ -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(

View File

@ -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;