This commit is contained in:
喻希里 2017-09-26 17:17:28 +08:00
commit 715cd2e012
11 changed files with 187 additions and 41 deletions

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Mock from 'mockjs'
import { Button, Input, Select, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete } from 'antd'
import { Button, Input, Select, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete, Switch } from 'antd'
import { autobind } from 'core-decorators';
import constants from '../../constants/variable.js'
@ -40,7 +40,7 @@ const mockDataSource = wordList.map(item => {
});
const { TextArea } = Input;
// const { TextArea } = Input;
const InputGroup = Input.Group;
const Option = Select.Option;
const Panel = Collapse.Panel;
@ -71,7 +71,10 @@ export default class Run extends Component {
loading: false,
validRes: [],
hasPlugin: true,
test_status: null
test_status: null,
resTest: false,
resStatusCode: null,
resStatusText: ''
}
constructor(props) {
@ -214,7 +217,12 @@ export default class Run extends Component {
data: bodyType === 'form' ? this.arrToObj(bodyForm) : bodyOther,
files: bodyType === 'form' ? this.getFiles(bodyForm) : {},
file: bodyType === 'file' ? 'single-file' : null,
success: (res, header) => {
success: (res, header, third) => {
console.log('suc',third);
this.setState({
resStatusCode: third.res.status,
resStatusText: third.res.statusText
})
try {
if (isJsonData(header)) {
res = json_parse(res);
@ -259,7 +267,12 @@ export default class Run extends Component {
console.error(e.message)
}
},
error: (err, header) => {
error: (err, header, third) => {
console.log('err',third);
this.setState({
resStatusCode: third.res.status,
resStatusText: third.res.statusText
})
try {
err = json_parse(err);
} catch (e) {
@ -496,6 +509,13 @@ export default class Run extends Component {
console.log(index)
}
@autobind
onTestSwitched(checked) {
this.setState({
resTest: checked
});
}
render() {
const { method, domains, pathParam, pathname, query, headers, bodyForm, caseEnv, bodyType, resHeader, loading, validRes } = this.state;
HTTP_METHOD[method] = HTTP_METHOD[method] || {}
@ -722,30 +742,59 @@ export default class Run extends Component {
</Collapse>
<h2 className="interface-title">返回结果</h2>
<Spin spinning={this.state.loading}>
<div className="res-code"></div>
<Collapse defaultActiveKey={['0', '1']} bordered={true}>
{this.state.resStatusCode ?
<Spin spinning={this.state.loading}>
<h2 className={'res-code ' + ((this.state.resStatusCode >= 200 && this.state.resStatusCode < 400 && !this.state.loading) ? 'success' : 'fail')}>{this.state.resStatusCode + ' ' + this.state.resStatusText}</h2>
<div className="container-header-body">
<div className="header">
<div className="container-title">
<h4>Headers</h4>
</div>
<div id="res-headers-pretty" className="pretty-editor-header"></div>
</div>
<div className="resizer">
<div className="container-title">
<h4 style={{visibility: 'hidden'}}>1</h4>
</div>
</div>
<div className="body">
<div className="container-title">
<h4>Body</h4>
</div>
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>
<div
style={{display: isResJson ? 'none' : ''}}
className="res-body-text"
>{this.state.res && this.state.res.toString()}</div>
</div>
</div>
</Spin> : <p></p>}
{/*<Collapse defaultActiveKey={['0', '1']} bordered={true}>
<Panel header="BODY" key="0" >
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>
<TextArea
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>*/}
{/*<TextArea
style={{ display: isResJson ? 'none' : '' }}
value={this.state.res && this.state.res.toString()}
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
></TextArea>*/}
{/*</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-header"></div>
{/*<div id="res-headers-pretty" className="pretty-editor-header"></div>
</Panel>
</Collapse>
</Spin>
</Collapse>*/}
<h2 className="interface-title">数据结构验证
<Switch style={{verticalAlign: 'text-bottom', marginLeft: '8px'}} checked={this.state.resTest} onChange={this.onTestSwitched} />
</h2>
<div className={(isResJson && this.state.resTest) ? '' : 'none' }>
{(isResJson && this.state.resTest) ? validResView : <div><p>若开启此功能则发送请求后在这里查看验证结果</p><p>YApi Response body </p></div>}
</div>
</div>
)
}

View File

@ -127,9 +127,9 @@ class InterfaceColContent extends Component {
status = 'ok';
} else if (result.code === 1) {
status = 'invalid'
}
}
} catch (e) {
status = 'error';
status = 'error';
result = e;
}
this.reports[curitem._id] = result;
@ -177,7 +177,7 @@ class InterfaceColContent extends Component {
headers: that.getHeadersObj(interfaceData.req_headers),
data: interfaceData.req_body_type === 'form' ? that.arrToObj(interfaceData.req_body_form) : interfaceData.req_body_other,
success: (res, header) => {
res = json_parse(res);
res = json_parse(res);
result.res_header = header;
result.res_body = res;
if (res && typeof res === 'object') {
@ -206,7 +206,7 @@ class InterfaceColContent extends Component {
} catch (e) {
console.log(e)
}
err = err || '请求异常';
result.code = 400;
result.res_header = header;
@ -442,7 +442,7 @@ class InterfaceColContent extends Component {
return (
<div className="interface-col">
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合&nbsp;<a target="_blank" rel="noopener noreferrer" href="https://yapi.ymfe.org/case.html" >
<h2 className="interface-title" style={{ display: 'inline-block', margin: 0, marginBottom: '16px' }}>测试集合&nbsp;<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>
@ -478,4 +478,4 @@ class InterfaceColContent extends Component {
}
}
export default InterfaceColContent
export default InterfaceColContent

View File

@ -89,12 +89,11 @@
}
.interface-col{
padding: 16px;
padding: 24px;
.interface-col-table-header{
background-color: rgb(238, 238, 238);
height: 50px;
line-height: 50px;
font-size:14px;
text-align: left;
}

View File

@ -1,3 +1,5 @@
@import '../../../../styles/mixin.scss';
.interface-edit{
padding: 24px;
.interface-edit-item{
@ -61,3 +63,71 @@
white-space: normal;
word-break: break-all;
}
// 容器左侧是header 右侧是body
.container-header-body {
display: flex;
padding-bottom: .36rem;
.header, .body {
flex: 1 0 300px;
.pretty-editor-header, .pretty-editor-body {
height: 100%;
}
.postman .pretty-editor-body {
min-height: 200px;
}
.ace_print-margin {
display: none;
}
}
.header {
max-width: 400px;
}
.container-title {
padding: .08rem 0;
}
.resizer {
flex: 0 0 21px;
position: relative;
&:after {
content: '';
display: block;
width: 1px;
height: 100%;
background-color: $color-text-dark;
opacity: .8;
position: absolute;
left: 10px;
}
}
// res body 无返回json时显示text信息
.res-body-text {
height: 100%;
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 8px;
}
}
.ant-spin-blur {
.res-code.success {
background-color: transparent;
}
.res-code.fail {
background-color: transparent;
}
}
.res-code {
padding: .08rem .28rem;
color: #fff;
margin-left: -.28rem;
margin-right: -.28rem;
transition: all .2s;
position: relative;
border-radius: 2px;
}
.res-code.success {
background-color: $color-antd-green;
}
.res-code.fail {
background-color: $color-antd-red;
}

View File

@ -277,7 +277,7 @@ class View extends Component {
return <p style={{whiteSpace: 'pre-wrap'}}>{item.example}</p>;
}
}, {
title: '备注',
title: '备注',
dataIndex: 'desc',
key: 'desc',
render(_, item) {
@ -304,11 +304,11 @@ class View extends Component {
<Row className="row">
<Col span={4} className="colKey">接口名称</Col>
<Col span={8}>{this.props.curData.title}</Col>
<Col span={4} className="colKey">建人</Col>
<Col span={4} className="colKey">&ensp;&ensp;</Col>
<Col span={8} className="colValue"><Link className="user-name" to={"/user/profile/" + this.props.curData.uid} ><img src={'/api/user/avatar?uid=' + this.props.curData.uid} className="user-img" />{this.props.curData.username}</Link></Col>
</Row>
<Row className="row">
<Col span={4} className="colKey"> </Col>
<Col span={4} className="colKey">&emsp;&emsp;</Col>
<Col span={8} className={'tag-status ' + this.props.curData.status}>{status[this.props.curData.status]}</Col>
<Col span={4} className="colKey">更新时间</Col>
<Col span={8}>{formatTime(this.props.curData.up_time)}</Col>

View File

@ -149,6 +149,17 @@
.right-content{
min-height: 5rem;
background: #fff;
.caseContainer {
table {
border-radius: 4px;
// border-collapse: collapse;
}
.ant-table-small .ant-table-thead > tr > th {
text-align: left;
background-color: #f8f8f8;
}
tr:nth-child(even){background: #f8f8f8;}
}
.interface-content{
.ant-tabs-nav{
width:100%;
@ -195,11 +206,17 @@
}
th {
text-align: left;
font-weight: normal;
background-color: #f8f8f8;
text-indent: .4em;
}
tr {
text-indent: .4em;
}
th, td {
border: 1px solid #e9e9e9;
padding: 8px;
}
tr:nth-child(odd){background: rgba(236, 238, 241, 0.67);}
tr:nth-child(odd){background: #f8f8f8;}
tr:nth-child(even){background: #fff;}
}
}

View File

@ -234,7 +234,7 @@ class ProjectMember extends Component {
</Row>
</Modal>
<Table columns={columns} dataSource={this.state.projectMemberList} pagination={false} locale={{emptyText: <ErrMsg type="noMemberInProject"/>}} className="setting-project-member"/>
<Card title={this.state.groupName + ' 分组成员 ' + '(' + this.state.groupMemberList.length + ') 人'} noHovering className="setting-group">
<Card bordered={false} title={this.state.groupName + ' 分组成员 ' + '(' + this.state.groupMemberList.length + ') 人'} noHovering className="setting-group">
{this.state.groupMemberList.length ? this.state.groupMemberList.map((item, index) => {
return (<div key={index} className="card-item">
<img src={location.protocol + '//' + location.host + '/api/user/avatar?uid=' + item.uid} className="item-img" />

View File

@ -25,14 +25,15 @@
}
}
.setting-project-member {
border: 1px solid #e9e9e9;
border-radius: 2px;
}
// .setting-project-member {
// border: 1px solid #e9e9e9;
// border-radius: 4px;
// }
.setting-group {
margin-top: .48rem;
border-radius: 2px;
border-bottom: 1px solid #eee;
.ant-card-head {
background-color: #eee;
padding: 0 .08rem !important;

View File

@ -8,6 +8,16 @@ $color-black-light: #404040;
$color-bg-dark: #32363a; // 背景色 - header 用的深蓝色
$box-shadow-panel: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
$color-text-dark: rgba(13, 27, 62, 0.65);
$color-antd-green: #00a854;
$color-antd-yellow: #ffbf00;
$color-antd-red: #f56a00;
$color-antd-pink: #f5317f;
$color-antd-cyan: #00a2ae;
$color-antd-gray: #bfbfbf;
$color-antd-purple: #7265e6;
@mixin row-width-limit {
max-width: 12.2rem;
min-width: 10.2rem;

View File

@ -8,7 +8,7 @@
"install-server": " node server/install.js",
"dev-client": "ykit s -p 4000",
"dev": "npm run dev-server & npm run dev-client",
"server": " node server/app.js"
"start": " node server/app.js"
},
"repository": {
"type": "git",

View File

@ -14,7 +14,7 @@ const WEBCONFIG = config;
fs.ensureDirSync(WEBROOT_LOG);
if (WEBCONFIG.mail) {
if (WEBCONFIG.mail && WEBCONFIG.mail.enable ) {
mail = nodemailer.createTransport(WEBCONFIG.mail);
}