mirror of
https://github.com/YMFE/yapi.git
synced 2025-02-17 13:49:43 +08:00
fix: 添加接口view页
This commit is contained in:
parent
ae39da3fe5
commit
acdbd3837c
@ -165,7 +165,7 @@ export default class HeaderCom extends Component {
|
||||
<Header className="header-box m-header">
|
||||
<div className="content g-row">
|
||||
<div className="logo">
|
||||
<Link to="/" onClick={this.relieveLink} className="href">
|
||||
<Link to="/group" onClick={this.relieveLink} className="href">
|
||||
<img className="img" src="/image/logo_header@1x.png" /><span className="logo-name">YAPI<span className="ui-badge"></span></span>
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -7,9 +7,6 @@ import PropTypes from 'prop-types';
|
||||
class ProjectCard extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
@ -18,13 +15,12 @@ class ProjectCard extends Component {
|
||||
|
||||
render() {
|
||||
const { projectData } = this.props;
|
||||
console.log(projectData);
|
||||
return (
|
||||
<Link to={`/project/${projectData._id}`}>
|
||||
<Card bordered={false} bodyStyle={{padding: 16}} className="m-card">
|
||||
<div className="m-card-logo">
|
||||
<Icon type="area-chart" className="icon" />
|
||||
<p className="name">{projectData.name}</p>
|
||||
<p className="name">{projectData.name || projectData.projectname}</p>
|
||||
</div>
|
||||
<div className="m-card-btns" style={{display: 'none'}}>btns</div>
|
||||
</Card>
|
||||
|
@ -58,7 +58,6 @@ class ProjectList extends Component {
|
||||
const { form, addProject } = this.props;
|
||||
e.preventDefault();
|
||||
form.validateFields((err, values) => {
|
||||
console.log(values);
|
||||
if (!err) {
|
||||
values.protocol = this.state.protocol.split(':')[0];
|
||||
|
||||
@ -110,6 +109,7 @@ class ProjectList extends Component {
|
||||
label="所属分组"
|
||||
>
|
||||
{getFieldDecorator('group_id', {
|
||||
initialValue: this.state.groupList.length > 0? this.state.groupList[0]._id.toString() : null ,
|
||||
rules: [{
|
||||
required: true, message: '请选择项目所属的分组!'
|
||||
}]
|
||||
@ -122,37 +122,12 @@ class ProjectList extends Component {
|
||||
|
||||
<hr className="breakline" />
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={(
|
||||
<span>
|
||||
线上域名
|
||||
<Tooltip title="将根据配置的线上域名访问mock数据">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
>
|
||||
{getFieldDecorator('prd_host', {
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入项目线上域名!'
|
||||
}]
|
||||
})(
|
||||
<Input addonBefore={(
|
||||
<Select defaultValue="http://" onChange={this.protocolChange}>
|
||||
<Option value="http://">{'http:\/\/'}</Option>
|
||||
<Option value="https://">{'https:\/\/'}</Option>
|
||||
</Select>)} />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={(
|
||||
<span>
|
||||
基本路径
|
||||
<Tooltip title="基本路径为空是根路径">
|
||||
<Tooltip title="接口基本路径,为空是根路径">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
@ -1,10 +1,48 @@
|
||||
import React, { Component } from 'react';
|
||||
import './Follows.scss';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Row, Col } from 'antd';
|
||||
import { getFollowList } from '../../reducer/modules/follow';
|
||||
import Subnav from '../../components/Subnav/Subnav.js';
|
||||
import ProjectCard from '../../components/ProjectCard/ProjectCard.js';
|
||||
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
data: state.follow.data
|
||||
}
|
||||
},
|
||||
{
|
||||
getFollowList
|
||||
}
|
||||
)
|
||||
class Follows extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: []
|
||||
}
|
||||
}
|
||||
static propTypes = {
|
||||
getFollowList: PropTypes.func
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.getFollowList(107).then((res) => {
|
||||
console.log(res);
|
||||
if (res.payload.data.errcode === 0) {
|
||||
this.setState({
|
||||
data: res.payload.data.data.list
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const data = this.state.data;
|
||||
console.log(data);
|
||||
return (
|
||||
<div>
|
||||
<Subnav
|
||||
@ -17,14 +55,15 @@ class Follows extends Component {
|
||||
path: '/follow'
|
||||
}]}/>
|
||||
<div className="g-row">
|
||||
<div className="follow-box">
|
||||
<div className="follow-container">
|
||||
<ProjectCard />
|
||||
<ProjectCard />
|
||||
<ProjectCard />
|
||||
<ProjectCard />
|
||||
</div>
|
||||
</div>
|
||||
<Row gutter={16} className="follow-box">
|
||||
{data.map((item, index) => {
|
||||
console.log(item);
|
||||
return (
|
||||
<Col span={6} key={index}>
|
||||
<ProjectCard projectData={item} />
|
||||
</Col>);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -3,10 +3,5 @@
|
||||
|
||||
.follow-box{
|
||||
padding: 24px;
|
||||
background-color: #FFF;
|
||||
.follow-container{
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
}
|
||||
|
||||
}
|
||||
background-color: #fff;
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ class MemberList extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="m-panel">
|
||||
chengyuan 列表 成员
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -133,17 +133,17 @@ class ProjectList extends Component {
|
||||
})
|
||||
}
|
||||
|
||||
// 分页逻辑
|
||||
@autobind
|
||||
paginationChange(pageNum) {
|
||||
this.props.fetchProjectList(this.props.currGroup._id, pageNum).then((res) => {
|
||||
if (res.payload.data.errcode) {
|
||||
message.error(res.payload.data.errmsg);
|
||||
} else {
|
||||
this.props.changeTableLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
// // 分页逻辑 取消分页
|
||||
// @autobind
|
||||
// paginationChange(pageNum) {
|
||||
// this.props.fetchProjectList(this.props.currGroup._id, pageNum).then((res) => {
|
||||
// if (res.payload.data.errcode) {
|
||||
// message.error(res.payload.data.errmsg);
|
||||
// } else {
|
||||
// this.props.changeTableLoading(false);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// 切换分组
|
||||
|
@ -54,7 +54,7 @@ class Login extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.QSSO.attach('qsso-login','/api/user/login_by_token')
|
||||
if(window.QSSO) window.QSSO.attach('qsso-login','/api/user/login_by_token')
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,11 @@
|
||||
import React from 'react'
|
||||
export default () => {
|
||||
return <h1>hello colContent</h1>
|
||||
}
|
||||
import React, { Component } from 'react'
|
||||
|
||||
export default class InterfaceColContent extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
render() {
|
||||
return <h1>hello colContent</h1>
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,131 @@
|
||||
import React from 'react'
|
||||
export default () => {
|
||||
return <h1>hello colContent</h1>
|
||||
}
|
||||
import React, { Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router'
|
||||
import PropTypes from 'prop-types'
|
||||
import { fetchInterfaceColList, fetchInterfaceCaseList } from '../../../../reducer/modules/interfaceCol'
|
||||
import { autobind } from 'core-decorators';
|
||||
import axios from 'axios';
|
||||
import { Menu, Input, Icon, Tag, Modal, Row, Col, message, Tooltip } from 'antd';
|
||||
|
||||
const SubMenu = Menu.SubMenu;
|
||||
const { TextArea } = Input;
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
interfaceColList: state.interfaceCol.interfaceColList
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceColList,
|
||||
fetchInterfaceCaseList
|
||||
}
|
||||
)
|
||||
@withRouter
|
||||
export default class InterfaceColMenu extends Component {
|
||||
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
interfaceColList: PropTypes.array,
|
||||
fetchInterfaceColList: PropTypes.func,
|
||||
fetchInterfaceCaseList: PropTypes.func
|
||||
}
|
||||
|
||||
state = {
|
||||
addColModalVisible: false,
|
||||
addColName: '',
|
||||
addColDesc: ''
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchInterfaceColList(this.props.match.params.id)
|
||||
}
|
||||
|
||||
@autobind
|
||||
async addCol() {
|
||||
const { addColName: name, addColDesc: desc } = this.state;
|
||||
const project_id = this.props.match.params.id
|
||||
const res = await axios.post('/api/col/add_col', { name, desc, project_id })
|
||||
if (!res.data.errcode) {
|
||||
this.setState({
|
||||
addColModalVisible: false
|
||||
});
|
||||
message.success('添加集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
async selectCol(key, e, col) {
|
||||
if (!col.interfaceCaseList) {
|
||||
await this.props.fetchInterfaceCaseList(col._id)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className="interface-filter">
|
||||
<Input placeholder="Filter by name" style={{ width: "70%" }} />
|
||||
<Tooltip placement="bottom" title="添加集合">
|
||||
<Tag color="#108ee9" style={{ marginLeft: "15px" }} onClick={() => this.setState({addColModalVisible: true})} ><Icon type="plus" /></Tag>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Menu
|
||||
onClick={this.handleClick}
|
||||
style={{ width: 240 }}
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub0']}
|
||||
mode="inline"
|
||||
>
|
||||
{
|
||||
this.props.interfaceColList.map((col, index) => (
|
||||
<SubMenu
|
||||
key={`sub${index}`}
|
||||
title={<span><Icon type="folder-open" /><span>{col.name}</span></span>}
|
||||
onTitleClick={(key, e) => this.selectCol(key, e, col)}
|
||||
>
|
||||
{
|
||||
col.interfaceCaseList && col.interfaceCaseList.map((interfaceCase, index) => (
|
||||
<Menu.Item key={index}>{interfaceCase.name}</Menu.Item>
|
||||
))
|
||||
}
|
||||
</SubMenu>
|
||||
))
|
||||
}
|
||||
</Menu>
|
||||
<Modal
|
||||
title="添加集合"
|
||||
visible={this.state.addColModalVisible}
|
||||
onOk={this.addCol}
|
||||
onCancel={() => { this.setState({ addColModalVisible: false }) }}
|
||||
className="add-col-modal"
|
||||
>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">集合名:</div></Col>
|
||||
<Col span="15">
|
||||
<Input
|
||||
placeholder="请输入集合名称"
|
||||
value={this.state.addColName}
|
||||
onChange={e => this.setState({addColName: e.target.value})}></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">简介:</div></Col>
|
||||
<Col span="15">
|
||||
<TextArea
|
||||
rows={3}
|
||||
placeholder="请输入集合描述"
|
||||
value={this.state.addColDesc}
|
||||
onChange={e => this.setState({addColDesc: e.target.value})}></TextArea>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
import React,{Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form, Input, Select, Button } from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
function hasErrors(fieldsError) {
|
||||
return Object.keys(fieldsError).some(field => fieldsError[field]);
|
||||
}
|
||||
class AddInterfaceForm extends Component {
|
||||
static propTypes = {
|
||||
form: PropTypes.object,
|
||||
onSubmit: PropTypes.func,
|
||||
onCancel: PropTypes.func
|
||||
}
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.props.onSubmit(values)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator, getFieldsError } = this.props.form;
|
||||
const prefixSelector = getFieldDecorator('method', {
|
||||
initialValue: 'GET'
|
||||
})(
|
||||
<Select style={{ width: 75 }}>
|
||||
<Option value="GET">GET</Option>
|
||||
<Option value="POST">POST</Option>
|
||||
<Option value="PUT">PUT</Option>
|
||||
<Option value="DELETE">DELETE</Option>
|
||||
</Select>
|
||||
);
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 6 }
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 14 }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="接口名称"
|
||||
>
|
||||
{getFieldDecorator('title', {
|
||||
rules: [{
|
||||
required: true, message: '清输入接口名称!'
|
||||
}]
|
||||
})(
|
||||
<Input placeholder="接口名称" />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="接口路径"
|
||||
>
|
||||
{getFieldDecorator('path', {
|
||||
rules: [{
|
||||
required: true, message: '清输入接口路径!'
|
||||
}]
|
||||
})(
|
||||
<Input addonBefore={prefixSelector} placeholder="/path" />
|
||||
)}
|
||||
</FormItem>
|
||||
<br />
|
||||
<FormItem wrapperCol={{ span: 24, offset: 8 }} >
|
||||
<Button onClick={this.props.onCancel} style={{marginRight: "10px"}} >取消</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
disabled={hasErrors(getFieldsError())}
|
||||
>
|
||||
提交
|
||||
</Button>
|
||||
</FormItem>
|
||||
|
||||
</Form>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create()(AddInterfaceForm);
|
@ -1,5 +1,54 @@
|
||||
import React from 'react'
|
||||
import React,{Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux';
|
||||
import InterfaceEditForm from './InterfaceEditForm.js'
|
||||
import { updateInterfaceData } from '../../../../reducer/modules/interface.js';
|
||||
import axios from 'axios'
|
||||
import {message} from 'antd'
|
||||
import './Edit.scss'
|
||||
|
||||
export default () => {
|
||||
return <h1>接口Edit</h1>
|
||||
}
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
curdata: state.inter.curdata,
|
||||
currProject: state.project.currProject
|
||||
}
|
||||
},{
|
||||
updateInterfaceData
|
||||
}
|
||||
)
|
||||
|
||||
class InterfaceEdit extends Component{
|
||||
static propTypes = {
|
||||
curdata: PropTypes.object,
|
||||
currProject:PropTypes.object,
|
||||
updateInterfaceData: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
const {curdata, currProject} = this.props;
|
||||
this.state = {
|
||||
mockUrl: location.protocol + '//' + location.hostname + (location.port !== "" ? ":" + location.port : "") + `/mock/${currProject._id}${currProject.basepath}${curdata.path}`
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit =async (params)=>{
|
||||
params.id = params._id = this.props.curdata._id;
|
||||
let result =await axios.post('/api/interface/up', params);
|
||||
if(result.data.errcode === 0){
|
||||
this.props.updateInterfaceData(params);
|
||||
message.success('保存成功');
|
||||
}else{
|
||||
message.success(result.data.errmsg)
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
return <div className="interface-edit">
|
||||
<InterfaceEditForm mockUrl={this.state.mockUrl} basepath={this.props.currProject.basepath} onSubmit={this.onSubmit} curdata={this.props.curdata} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default InterfaceEdit;
|
11
client/containers/Project/Interface/InterfaceList/Edit.scss
Normal file
11
client/containers/Project/Interface/InterfaceList/Edit.scss
Normal file
@ -0,0 +1,11 @@
|
||||
.interface-edit{
|
||||
padding:10px;
|
||||
.interface-edit-item{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.interface-edit-del-icon{
|
||||
margin-top: 4px;
|
||||
margin-left: 5px;
|
||||
cursor: pointer
|
||||
}
|
||||
}
|
@ -0,0 +1,474 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {
|
||||
Form, Select, Input,
|
||||
Button, Row, Col, Radio, Icon
|
||||
} from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const InputGroup = Input.Group;
|
||||
const RadioGroup = Radio.Group;
|
||||
const dataTpl = {
|
||||
req_query: { name: "", required: "1", desc: "" },
|
||||
req_headers: { name: "", required: "1", desc: "" }
|
||||
}
|
||||
|
||||
const mockEditor = require('./mockEditor.js');
|
||||
|
||||
|
||||
class InterfaceEditForm extends Component {
|
||||
static propTypes = {
|
||||
form: PropTypes.object,
|
||||
curdata: PropTypes.object,
|
||||
mockUrl: PropTypes.string,
|
||||
onSubmit: PropTypes.func,
|
||||
basepath: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
const { curdata } = this.props;
|
||||
if (curdata.req_query && curdata.req_query.length === 0) delete curdata.req_query;
|
||||
if (curdata.req_headers && curdata.req_headers.length === 0) delete curdata.req_headers;
|
||||
if (curdata.req_body_form && curdata.req_body_form.length === 0) delete curdata.req_body_form;
|
||||
|
||||
this.state = Object.assign({
|
||||
title: '',
|
||||
path: '',
|
||||
status: 'undone',
|
||||
method: 'get',
|
||||
req_query: [{
|
||||
name: '',
|
||||
desc: '',
|
||||
required: "1"
|
||||
}],
|
||||
req_body_type: 'form',
|
||||
req_headers: [{
|
||||
name: '',
|
||||
value: '', required: "1"
|
||||
}],
|
||||
req_body_form: [{
|
||||
name: '',
|
||||
type: '',
|
||||
required: ''
|
||||
}],
|
||||
res_body_type: 'json',
|
||||
res_body: '',
|
||||
desc: '',
|
||||
res_body_mock: '',
|
||||
mockUrl: this.props.mockUrl
|
||||
}, curdata)
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
if (values.res_body_type === 'json') values.res_body = this.state.res_body;
|
||||
values.req_body_json = this.state.res_body;
|
||||
this.props.onSubmit(values)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let that = this;
|
||||
mockEditor({
|
||||
container: 'req_body_json',
|
||||
data: that.state.req_body_json,
|
||||
onChange: function (d) {
|
||||
that.setState({
|
||||
req_body_json: d.text
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let resBodyEditor = mockEditor({
|
||||
container: 'res_body_json',
|
||||
data: that.state.res_body,
|
||||
onChange: function (d) {
|
||||
|
||||
that.setState({
|
||||
res_body: d.text,
|
||||
res_body_mock: d.mockText
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
that.setState({
|
||||
res_body_mock: resBodyEditor.curData.mockText
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
addParams = (name) => {
|
||||
let newValue = {}
|
||||
newValue[name] = [].concat(this.state[name], dataTpl[name])
|
||||
this.setState(newValue)
|
||||
}
|
||||
|
||||
delParams = (key, name) => {
|
||||
|
||||
let curValue = this.props.form.getFieldValue(name);
|
||||
let newValue = {}
|
||||
newValue[name] = curValue.filter((val, index) => {
|
||||
return index !== key;
|
||||
})
|
||||
this.props.form.setFieldsValue(newValue)
|
||||
this.setState(newValue)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 18 }
|
||||
};
|
||||
|
||||
|
||||
const queryTpl = (data, index) => {
|
||||
return <Row key={index}>
|
||||
<Col span="4">
|
||||
{getFieldDecorator('req_query[' + index + '].name', {
|
||||
initialValue: data.name
|
||||
})(
|
||||
<Input placeholder="参数名称" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="4" >
|
||||
{getFieldDecorator('req_query[' + index + '].required', {
|
||||
initialValue: data.required
|
||||
})(
|
||||
<Select>
|
||||
<Option value="1">必需</Option>
|
||||
<Option value="0">非必需</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Col>
|
||||
<Col span="8" >
|
||||
{getFieldDecorator('req_query[' + index + '].desc', {
|
||||
initialValue: data.desc
|
||||
})(
|
||||
<Input placeholder="备注" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="2" >
|
||||
<Icon type="delete" className="interface-edit-del-icon" onClick={() => this.delParams(index, 'req_query')} />
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
}
|
||||
|
||||
const headerTpl = (data, index) => {
|
||||
return <Row key={index}>
|
||||
<Col span="4">
|
||||
{getFieldDecorator('req_headers[' + index + '].name', {
|
||||
initialValue: data.name
|
||||
})(
|
||||
<Input placeholder="参数名称" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="6" >
|
||||
{getFieldDecorator('req_headers[' + index + '].value', {
|
||||
initialValue: data.value
|
||||
})(
|
||||
<Input placeholder="参数值" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="8" >
|
||||
{getFieldDecorator('req_headers[' + index + '].desc', {
|
||||
initialValue: data.desc
|
||||
})(
|
||||
<Input placeholder="备注" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="2" >
|
||||
<Icon type="delete" className="interface-edit-del-icon" onClick={() => this.delParams(index, 'req_headers')} />
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
}
|
||||
|
||||
const requestBodyTpl = (data, index) => {
|
||||
return <Row key={index}>
|
||||
<Col span="8">
|
||||
{getFieldDecorator('req_body_form[' + index + '].name', {
|
||||
initialValue: data.name
|
||||
})(
|
||||
<Input placeholder="name" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="4" >
|
||||
{getFieldDecorator('req_body_form[' + index + '].type', {
|
||||
initialValue: data.type
|
||||
})(
|
||||
<Select>
|
||||
<Option value="text">文本</Option>
|
||||
<Option value="file">文件</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Col>
|
||||
<Col span="8">
|
||||
{getFieldDecorator('req_body_form[' + index + '].desc', {
|
||||
initialValue: data.desc
|
||||
})(
|
||||
<Input placeholder="备注" />
|
||||
)}
|
||||
</Col>
|
||||
<Col span="2" >
|
||||
<Icon type="delete" className="interface-edit-del-icon" onClick={() => this.delParams(index, 'req_body_form')} />
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
|
||||
const QueryList = this.state.req_query.map((item, index) => {
|
||||
return queryTpl(item, index)
|
||||
})
|
||||
|
||||
const headerList = this.state.req_headers.map((item, index) => {
|
||||
return headerTpl(item, index)
|
||||
})
|
||||
|
||||
const requestBodyList = this.state.req_body_form.map((item, index) => {
|
||||
return requestBodyTpl(item, index)
|
||||
})
|
||||
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="接口名称"
|
||||
>
|
||||
{getFieldDecorator('title', {
|
||||
initialValue: this.state.title,
|
||||
rules: [{
|
||||
required: true, message: '清输入接口名称!'
|
||||
}]
|
||||
})(
|
||||
<Input placeholder="接口名称" />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="接口路径"
|
||||
>
|
||||
{getFieldDecorator('path', {
|
||||
initialValue: this.state.path,
|
||||
rules: [{
|
||||
required: true, message: '清输入接口路径!'
|
||||
}]
|
||||
})(
|
||||
<InputGroup compact>
|
||||
{getFieldDecorator('method', {
|
||||
initialValue: 'GET'
|
||||
})(
|
||||
<Select style={{ width: "75px" }}>
|
||||
<Option value="GET">GET</Option>
|
||||
<Option value="POST">POST</Option>
|
||||
<Option value="PUT">PUT</Option>
|
||||
<Option value="DELETE">DELETE</Option>
|
||||
</Select>
|
||||
)}
|
||||
<Input value={this.props.basepath} readOnly onChange={() => { }} style={{ width: '100px', marginRight: "10px", marginLeft: "10px" }} />
|
||||
{getFieldDecorator('path', {
|
||||
initialValue: this.state.path
|
||||
})(
|
||||
<Input placeholder="/path" style={{ width: '350px' }} />
|
||||
)}
|
||||
</InputGroup>
|
||||
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="状态"
|
||||
>
|
||||
{getFieldDecorator('status', { initialValue: this.state.status })(
|
||||
<Select>
|
||||
<Option value="done">已完成</Option>
|
||||
<Option value="undone">未完成</Option>
|
||||
</Select>
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="接口描述"
|
||||
>
|
||||
{getFieldDecorator('desc', { initialValue: this.state.desc })(
|
||||
<Input.TextArea placeholder="接口描述" />
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="Query"
|
||||
>
|
||||
<Button size="small" type="primary" onClick={() => this.addParams('req_query')}>添加Query参数</Button>
|
||||
</FormItem>
|
||||
|
||||
<Row className="interface-edit-item">
|
||||
<Col span={18} offset={4}>
|
||||
{QueryList}
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="请求Headers"
|
||||
>
|
||||
<Button size="small" type="primary" onClick={() => this.addParams('req_headers')}>添加Header</Button>
|
||||
</FormItem>
|
||||
|
||||
<Row className="interface-edit-item">
|
||||
<Col span={18} offset={4}>
|
||||
{headerList}
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="请求Body"
|
||||
>
|
||||
{getFieldDecorator('req_body_type', {
|
||||
initialValue: this.state.req_body_type
|
||||
})(
|
||||
<RadioGroup>
|
||||
<Radio value="form">form</Radio>
|
||||
<Radio value="json">json</Radio>
|
||||
<Radio value="file">file</Radio>
|
||||
<Radio value="raw">raw</Radio>
|
||||
</RadioGroup>
|
||||
)}
|
||||
|
||||
</FormItem>
|
||||
{this.props.form.getFieldValue('req_body_type') === 'form' ?
|
||||
<Row className="interface-edit-item">
|
||||
<Col span={18} offset={4} style={{ minHeight: "50px" }}>
|
||||
<Row>
|
||||
<Col span="24" className="interface-edit-item">
|
||||
|
||||
<Button size="small" type="primary" onClick={() => this.addParams('req_body_form')}>添加form参数</Button>
|
||||
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
{requestBodyList}
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
:
|
||||
null
|
||||
}
|
||||
|
||||
|
||||
<Row className="interface-edit-item" style={{ display: this.props.form.getFieldValue('req_body_type') === 'json' ? 'block' : 'none' }}>
|
||||
<Col span={18} offset={4} id="req_body_json" style={{ minHeight: "300px" }}>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{this.props.form.getFieldValue('req_body_type') === 'file' ?
|
||||
<Row className="interface-edit-item" >
|
||||
<Col span={14} offset={6}>
|
||||
{getFieldDecorator('req_body_other', { initialValue: this.state.req_body_other })(
|
||||
<Input.TextArea placeholder="备注信息" />
|
||||
)}
|
||||
</Col>
|
||||
|
||||
|
||||
</Row>
|
||||
:
|
||||
null
|
||||
}
|
||||
{this.props.form.getFieldValue('req_body_type') === 'raw' ?
|
||||
<Row>
|
||||
<Col span={18} offset={4} >
|
||||
{getFieldDecorator('req_body_other', { initialValue: this.state.req_body_other })(
|
||||
<Input.TextArea placeholder="备注信息" />
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
: null
|
||||
}
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="响应Body"
|
||||
>
|
||||
{getFieldDecorator('res_body_type', {
|
||||
initialValue: this.state.res_body_type
|
||||
})(
|
||||
<RadioGroup>
|
||||
<Radio value="json">json</Radio>
|
||||
<Radio value="raw">raw</Radio>
|
||||
|
||||
</RadioGroup>
|
||||
)}
|
||||
|
||||
</FormItem>
|
||||
<Row className="interface-edit-item" style={{ display: this.props.form.getFieldValue('res_body_type') === 'json' ? 'block' : 'none' }}>
|
||||
|
||||
<Col span={18} offset={4} id="res_body_json" style={{ minHeight: "300px" }}>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<FormItem
|
||||
style={{ display: this.props.form.getFieldValue('res_body_type') === 'json' ? 'block' : 'none' }}
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="mock地址"
|
||||
>
|
||||
<Input onChange={() => { }} value={this.state.mockUrl} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
style={{ display: this.props.form.getFieldValue('res_body_type') === 'json' ? 'block' : 'none' }}
|
||||
className="interface-edit-item"
|
||||
{...formItemLayout}
|
||||
label="预览"
|
||||
>
|
||||
<pre style={{ backgroundColor: "#eee", lineHeight: "20px" }}>
|
||||
{this.state.res_body_mock || " "}
|
||||
</pre>
|
||||
</FormItem>
|
||||
|
||||
|
||||
<Row className="interface-edit-item" style={{ display: this.props.form.getFieldValue('res_body_type') === 'raw' ? 'block' : 'none' }}>
|
||||
<Col span={18} offset={4} >
|
||||
{getFieldDecorator('res_body', { initialValue: this.state.res_body })(
|
||||
<Input.TextArea placeholder="备注信息" />
|
||||
)}
|
||||
</Col>
|
||||
|
||||
|
||||
</Row>
|
||||
|
||||
|
||||
<FormItem
|
||||
className="interface-edit-item"
|
||||
wrapperCol={{ span: 12, offset: 6 }}
|
||||
>
|
||||
<Button type="primary" htmlType="submit">Submit</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create()(InterfaceEditForm);
|
@ -1,54 +1,174 @@
|
||||
import React, { Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types'
|
||||
import { fetchInterfaceList } from '../../../../reducer/modules/interface.js';
|
||||
import { Menu, Button, Input, Icon, Tag } from 'antd';
|
||||
import { fetchInterfaceList, fetchInterfaceData, changeInterfaceId, addInterfaceData, deleteInterfaceData } from '../../../../reducer/modules/interface.js';
|
||||
import { Menu, Input, Icon, Tag, Modal, message } from 'antd';
|
||||
import AddInterfaceForm from './AddInterfaceForm';
|
||||
import axios from 'axios'
|
||||
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
list: state.inter.list,
|
||||
curProject: state.project.curProject
|
||||
curProject: state.project.curProject,
|
||||
interfaceId: state.inter.interfaceId
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceList
|
||||
fetchInterfaceList,
|
||||
fetchInterfaceData,
|
||||
changeInterfaceId,
|
||||
addInterfaceData,
|
||||
deleteInterfaceData
|
||||
}
|
||||
)
|
||||
class InterfaceMenu extends Component {
|
||||
static propTypes = {
|
||||
projectId: PropTypes.string,
|
||||
interfaceId: PropTypes.number,
|
||||
list: PropTypes.array,
|
||||
fetchInterfaceList: PropTypes.func,
|
||||
curProject: PropTypes.object
|
||||
}
|
||||
curProject: PropTypes.object,
|
||||
fetchInterfaceData: PropTypes.func,
|
||||
changeInterfaceId: PropTypes.func,
|
||||
addInterfaceData: PropTypes.func,
|
||||
deleteInterfaceData: PropTypes.func
|
||||
}
|
||||
|
||||
showModal = () => {
|
||||
this.setState({
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
curKey: null,
|
||||
visible: false,
|
||||
delIcon: null,
|
||||
filter: ''
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount(){
|
||||
this.props.fetchInterfaceList(this.props.projectId)
|
||||
async handleRequest() {
|
||||
let result = await this.props.fetchInterfaceList(this.props.projectId);
|
||||
let interfaces = result.payload.data;
|
||||
if (interfaces.length > 0) {
|
||||
this.props.changeInterfaceId(interfaces[0]._id)
|
||||
await this.props.fetchInterfaceData(interfaces[0]._id)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.handleRequest()
|
||||
}
|
||||
|
||||
onSelect = (item) => {
|
||||
this.props.changeInterfaceId(parseInt(item.key, 10))
|
||||
this.props.fetchInterfaceData(parseInt(item.key, 10))
|
||||
}
|
||||
|
||||
handleAddInterface = (data) => {
|
||||
data.project_id = this.props.projectId;
|
||||
axios.post('/api/interface/add', data).then((res) => {
|
||||
if (res.data.errcode !== 0) {
|
||||
return message.error(res.data.errmsg);
|
||||
}
|
||||
message.success('接口添加成功')
|
||||
this.props.addInterfaceData(res.data.data)
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
showConfirm = (id)=> {
|
||||
let that = this;
|
||||
confirm({
|
||||
title: '您确认删除此接口',
|
||||
content: '温馨提示:接口删除后,无法恢复',
|
||||
onOk() {
|
||||
that.props.deleteInterfaceData(id)
|
||||
},
|
||||
onCancel() { }
|
||||
});
|
||||
}
|
||||
|
||||
delInterface = (id) => {
|
||||
|
||||
this.props.deleteInterfaceData(id)
|
||||
}
|
||||
|
||||
enterItem = (e) => {
|
||||
this.setState({ delIcon: e.key })
|
||||
}
|
||||
|
||||
leaveItem = () => {
|
||||
this.setState({ delIcon: null })
|
||||
}
|
||||
|
||||
onFilter = (e) => {
|
||||
this.setState({
|
||||
filter: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const items = [];
|
||||
this.props.list.forEach((item, index)=> {
|
||||
this.props.list.forEach((item) => {
|
||||
let color, filter = this.state.filter;
|
||||
if(filter && item.title.indexOf(filter) === -1 && item.path.indexOf(filter) === -1){
|
||||
return null;
|
||||
}
|
||||
switch (item.method) {
|
||||
case 'GET': color = "green"; break;
|
||||
case 'POST': color = "blue"; break;
|
||||
case 'PUT': color = "yellow"; break;
|
||||
case 'DELETE': color = 'red'; break;
|
||||
default: color = "green";
|
||||
}
|
||||
|
||||
items.push(
|
||||
<Menu.Item key={index}><Button className="btn-http" type="primary">{item.method} </Button>{item.title}</Menu.Item>
|
||||
<Menu.Item onMouseEnter={this.enterItem} onMouseLeave={this.leaveItem} key={"" + item._id}>
|
||||
<Tag className="btn-http" color={color}>{item.method} </Tag>
|
||||
{item.title}
|
||||
<Icon type="delete" onClick={()=> {this.showConfirm(item._id)}} style={{ display: this.state.delIcon == item._id ? 'block' : 'none' }} className="interface-delete-icon" />
|
||||
</Menu.Item>
|
||||
)
|
||||
} )
|
||||
})
|
||||
|
||||
return <div>
|
||||
<div className="interface-filter">
|
||||
<Input placeholder="Filter by name" style={{ width: "70%" }} />
|
||||
<Tag color="#108ee9" style={{ marginLeft: "15px" }} ><Icon type="plus" /></Tag>
|
||||
<Input onChange={this.onFilter} value={this.state.filter} placeholder="Filter by name" style={{ width: "70%" }} />
|
||||
<Tag onClick={this.showModal} color="#108ee9" style={{ marginLeft: "15px" }} ><Icon type="plus" /></Tag>
|
||||
<Modal
|
||||
title="添加接口"
|
||||
visible={this.state.visible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
footer={null}
|
||||
>
|
||||
<AddInterfaceForm onCancel={this.handleCancel} onSubmit={this.handleAddInterface} />
|
||||
</Modal>
|
||||
</div>
|
||||
<Menu className="interface-list">
|
||||
<Menu selectedKeys={[this.props.interfaceId + ""]} className="interface-list" onSelect={this.onSelect}>
|
||||
{items}
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default InterfaceMenu
|
@ -1,5 +1,512 @@
|
||||
import React from 'react'
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { Button, Input, Select, Card, Alert, Spin, Icon, message } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import crossRequest from 'cross-request';
|
||||
import { withRouter } from 'react-router';
|
||||
// import axios from 'axios';
|
||||
import URL from 'url';
|
||||
|
||||
export default () => {
|
||||
return <h1>接口Run</h1>
|
||||
}
|
||||
// import {
|
||||
// } from '../../../reducer/modules/group.js'
|
||||
|
||||
import './Run.scss'
|
||||
|
||||
const { TextArea } = Input;
|
||||
const InputGroup = Input.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
currInterface: state.inter.curdata,
|
||||
currProject: state.project.currProject
|
||||
// reqParams: state.addInterface.reqParams,
|
||||
// method: state.addInterface.method,
|
||||
// url: state.addInterface.url,
|
||||
// seqGroup: state.addInterface.seqGroup,
|
||||
// interfaceName: state.addInterface.interfaceName,
|
||||
})
|
||||
)
|
||||
@withRouter
|
||||
export default class InterfaceTest extends Component {
|
||||
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
currProject: PropTypes.object,
|
||||
currInterface: PropTypes.object,
|
||||
reqParams: PropTypes.string,
|
||||
// method: PropTypes.string,
|
||||
// url: PropTypes.string,
|
||||
interfaceName: PropTypes.string
|
||||
// seqGroup: PropTypes.array,
|
||||
}
|
||||
|
||||
state = {
|
||||
res: '',
|
||||
method: 'GET',
|
||||
domains: [],
|
||||
pathname: '',
|
||||
query: {},
|
||||
params: {},
|
||||
paramsNotJson: false,
|
||||
headers: {},
|
||||
currDomain: '',
|
||||
paramsType: 'from'
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getInterfaceState()
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.getInterfaceState(nextProps)
|
||||
}
|
||||
|
||||
@autobind
|
||||
getInterfaceState(nextProps) {
|
||||
const props = nextProps || this.props;
|
||||
const { currInterface, currProject } = props;
|
||||
console.log('currInterface', currInterface)
|
||||
console.log('currProject', currProject)
|
||||
const { method, path: url, req_headers } = currInterface;
|
||||
const { prd_host, basepath, protocol, env } = currProject;
|
||||
const pathname = (basepath + url).replace(/\/+/g, '/');
|
||||
|
||||
const domains = {prd: protocol + '://' + prd_host};
|
||||
env.forEach(item => {
|
||||
domains[item.name] = item.domain;
|
||||
})
|
||||
|
||||
const query = [];
|
||||
let params = [];
|
||||
let reqParams = this.props.reqParams ? this.props.reqParams : '{}';
|
||||
let paramsNotJson = false;
|
||||
try {
|
||||
reqParams = JSON.parse(reqParams);
|
||||
// paramsNotJson = false;
|
||||
} catch (e) {
|
||||
// paramsNotJson = true;
|
||||
reqParams = {};
|
||||
message.error('请求参数不是 JSON 格式');
|
||||
}
|
||||
if (method === 'GET') {
|
||||
Object.keys(reqParams).forEach(key => {
|
||||
const value = typeof reqParams[key] === 'object' ? JSON.stringify(reqParams[key]) : reqParams[key].toString();
|
||||
query.push({key, value})
|
||||
})
|
||||
} else if (method === 'POST') {
|
||||
// params = reqParams;
|
||||
Object.keys(reqParams).forEach(key => {
|
||||
const value = typeof reqParams[key] === 'object' ? JSON.stringify(reqParams[key]) : reqParams[key].toString();
|
||||
query.push({key, value, type: 'text'})
|
||||
})
|
||||
}
|
||||
|
||||
const headers = []
|
||||
let contentTypeIndex = -1;
|
||||
req_headers.forEach((headerItem, index) => {
|
||||
if (headerItem.name) {
|
||||
// TODO 'Content-Type' 排除大小写不同格式影响
|
||||
if (headerItem.name === 'Content-Type'){
|
||||
contentTypeIndex = index;
|
||||
headerItem.value = headerItem.value || 'application/x-www-form-urlencoded';
|
||||
}
|
||||
headers.push({name: headerItem.name, value: headerItem.value});
|
||||
}
|
||||
})
|
||||
if (contentTypeIndex === -1) {
|
||||
headers.push({name: 'Content-Type', value: 'application/x-www-form-urlencoded'});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
method,
|
||||
domains,
|
||||
pathname,
|
||||
query,
|
||||
params,
|
||||
paramsNotJson,
|
||||
headers,
|
||||
currDomain: domains.prd,
|
||||
loading: false,
|
||||
paramsType: 'form'
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
requestInterface() {
|
||||
const { headers, params, currDomain, method, pathname, query } = this.state;
|
||||
const urlObj = URL.parse(currDomain);
|
||||
|
||||
const href = URL.format({
|
||||
protocol: urlObj.protocol || 'http',
|
||||
host: urlObj.host,
|
||||
pathname,
|
||||
query: this.getQueryObj(query)
|
||||
});
|
||||
|
||||
this.setState({ loading: true })
|
||||
|
||||
crossRequest({
|
||||
url: href,
|
||||
method,
|
||||
headers: this.getHeadersObj(headers),
|
||||
data: this.arrToObj(params),
|
||||
files: this.getFiles(params),
|
||||
success: (res) => {
|
||||
try {
|
||||
res = JSON.parse(res)
|
||||
} catch (e) {
|
||||
null
|
||||
}
|
||||
this.setState({res})
|
||||
this.setState({ loading: false })
|
||||
},
|
||||
error: (err) => {
|
||||
this.setState({res: err || '请求失败'})
|
||||
this.setState({ loading: false })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeDomain(value) {
|
||||
this.setState({ currDomain: value });
|
||||
}
|
||||
|
||||
@autobind
|
||||
selectDomain(value) {
|
||||
this.setState({ currDomain: value });
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeHeader(e, index, isName) {
|
||||
const headers = JSON.parse(JSON.stringify(this.state.headers));
|
||||
const v = e.target.value;
|
||||
if (isName) {
|
||||
headers[index].name = v;
|
||||
} else {
|
||||
headers[index].value = v;
|
||||
}
|
||||
this.setState({ headers });
|
||||
}
|
||||
@autobind
|
||||
addHeader() {
|
||||
const { headers } = this.state;
|
||||
this.setState({headers: headers.concat([{name: '', value: ''}])})
|
||||
}
|
||||
@autobind
|
||||
deleteHeader(index) {
|
||||
const { headers } = this.state;
|
||||
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, 'name')})
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeQuery(e, index, isKey) {
|
||||
const query = JSON.parse(JSON.stringify(this.state.query));
|
||||
const v = e.target.value;
|
||||
if (isKey) {
|
||||
query[index].key = v;
|
||||
} else {
|
||||
query[index].value = v;
|
||||
}
|
||||
this.setState({ query });
|
||||
}
|
||||
@autobind
|
||||
addQuery() {
|
||||
const { query } = this.state;
|
||||
this.setState({query: query.concat([{key: '', value: ''}])})
|
||||
}
|
||||
@autobind
|
||||
deleteQuery(index) {
|
||||
const { query } = this.state;
|
||||
this.setState({query: query.filter((item, i) => +index !== +i)});
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeParams(e, index, type) {
|
||||
const params = JSON.parse(JSON.stringify(this.state.params));
|
||||
switch (type) {
|
||||
case 'key':
|
||||
params[index].key = e.target.value
|
||||
break;
|
||||
case 'type':
|
||||
params[index].type = e
|
||||
break;
|
||||
case 'value':
|
||||
if (params[index].type === 'file') {
|
||||
params[index].value = e.target.id
|
||||
} else {
|
||||
params[index].value = e.target.value
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (type === 'type' && e === 'file') {
|
||||
this.setContentType('multipart/form-data')
|
||||
}
|
||||
this.setState({ params });
|
||||
}
|
||||
@autobind
|
||||
addParams() {
|
||||
const { params } = this.state;
|
||||
this.setState({params: params.concat([{key: '', value: '', type: 'text'}])})
|
||||
}
|
||||
@autobind
|
||||
deleteParams(index) {
|
||||
const { params } = this.state;
|
||||
this.setState({params: params.filter((item, i) => +index !== +i)});
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeMethod(value) {
|
||||
this.setState({ method: value });
|
||||
}
|
||||
|
||||
@autobind
|
||||
changePath(e) {
|
||||
const path = e.target.value;
|
||||
const urlObj = URL.parse(path, true);
|
||||
this.setState({
|
||||
query: this.objToArr(urlObj.query),
|
||||
pathname: urlObj.pathname
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
changeParamsType(value) {
|
||||
this.setState({paramsType: value})
|
||||
}
|
||||
|
||||
hasCrossRequestPlugin() {
|
||||
const dom = document.getElementById('y-request');
|
||||
return dom.getAttribute('key') === 'yapi';
|
||||
}
|
||||
|
||||
objToArr(obj, key, value) {
|
||||
const keyName = key || 'key';
|
||||
const valueName = value || 'value';
|
||||
const arr = []
|
||||
Object.keys(obj).forEach((_key) => {
|
||||
if (_key) {
|
||||
arr.push({[keyName]: _key, [valueName]: obj[_key]});
|
||||
}
|
||||
})
|
||||
return arr;
|
||||
}
|
||||
arrToObj(arr) {
|
||||
const obj = {};
|
||||
arr.forEach(item => {
|
||||
if (item.key && item.type !== 'file') {
|
||||
obj[item.key] = item.value || '';
|
||||
}
|
||||
})
|
||||
return obj;
|
||||
}
|
||||
getFiles(params) {
|
||||
const files = {};
|
||||
params.forEach(item => {
|
||||
if (item.key && item.type === 'file') {
|
||||
files[item.key] = item.value
|
||||
}
|
||||
})
|
||||
return files;
|
||||
}
|
||||
getQueryObj(query) {
|
||||
const queryObj = {};
|
||||
query.forEach(item => {
|
||||
if (item.key) {
|
||||
queryObj[item.key] = item.value || '';
|
||||
}
|
||||
})
|
||||
return queryObj;
|
||||
}
|
||||
getHeadersObj(headers) {
|
||||
const headersObj = {};
|
||||
headers.forEach(item => {
|
||||
if (item.name && item.value) {
|
||||
headersObj[item.name] = item.value;
|
||||
}
|
||||
})
|
||||
return headersObj;
|
||||
}
|
||||
|
||||
@autobind
|
||||
fileChange(e, index) {
|
||||
console.log(e)
|
||||
console.log(index)
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
const { interfaceName } = this.props;
|
||||
const { method, domains, pathname, query, headers, params, currDomain, paramsType } = this.state;
|
||||
const hasPlugin = this.hasCrossRequestPlugin();
|
||||
const search = decodeURIComponent(URL.format({query: this.getQueryObj(query)}));
|
||||
|
||||
return (
|
||||
<div className="interface-test">
|
||||
<div style={{padding: '0 20%'}}>
|
||||
{ hasPlugin ? '' :
|
||||
<Alert
|
||||
message={
|
||||
<div>
|
||||
温馨提示:当前正在使用接口测试服务,请安装我们为您免费提供的
|
||||
<a
|
||||
target="blank"
|
||||
href="https://chrome.google.com/webstore/detail/cross-request/cmnlfmgbjmaciiopcgodlhpiklaghbok?hl=en-US"
|
||||
>
|
||||
测试增强插件 [点击获取]!
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
type="warning"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
<div className="interface-name">{interfaceName}</div>
|
||||
|
||||
{/* url */}
|
||||
<div className="req-part">
|
||||
<div className="req-row href">
|
||||
<InputGroup compact style={{display: 'inline-block', width: 680, border: 0, background: '#fff', marginBottom: -4}}>
|
||||
<Input value="Method" disabled style={{display: 'inline-block', width: 80, border: 0, background: '#fff'}} />
|
||||
<Input value="Domain" disabled style={{display: 'inline-block', width: 300, border: 0, background: '#fff'}} />
|
||||
<Input value="Basepath + Url + [Query]" disabled style={{display: 'inline-block', width: 300, border: 0, background: '#fff'}} />
|
||||
</InputGroup>
|
||||
<InputGroup compact style={{display: 'inline-block', width: 680}}>
|
||||
<Select value={method} style={{display: 'inline-block', width: 80}} onChange={this.changeMethod} >
|
||||
<Option value="GET">GET</Option>
|
||||
<Option value="POST">POST</Option>
|
||||
</Select>
|
||||
<Select value={currDomain} mode="combobox" filterOption={() => true} style={{display: 'inline-block', width: 300}} onChange={this.changeDomain} onSelect={this.selectDomain}>
|
||||
{
|
||||
Object.keys(domains).map((key, index) => (<Option value={domains[key]} key={index}>{key + ':' + domains[key]}</Option>))
|
||||
}
|
||||
</Select>
|
||||
<Input value={pathname + search} onChange={this.changePath} spellCheck="false" style={{display: 'inline-block', width: 300}} />
|
||||
</InputGroup>
|
||||
<Button
|
||||
onClick={this.requestInterface}
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
loading={this.state.loading}
|
||||
>发送</Button>
|
||||
<span style={{fontSize: 12, color: 'rgba(0, 0, 0, 0.25)'}}>(请求测试真实接口)</span>
|
||||
</div>
|
||||
|
||||
<Card title="Query" noHovering style={{marginTop: 10}}>
|
||||
{
|
||||
query.map((item, index) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Input value={item.key} onChange={e => this.changeQuery(e, index, true)} style={{display: 'inline-block', width: 200, margin: 10}} />{' = '}
|
||||
<Input value={item.value} onChange={e => this.changeQuery(e, index)} style={{display: 'inline-block', width: 200, margin: 10}} />
|
||||
<Icon type="close" className="icon-btn" onClick={() => this.deleteQuery(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button type="primary" icon="plus" onClick={this.addQuery} style={{margin: 10}}>Add query parameter</Button>
|
||||
</Card>
|
||||
<Card title="HEADERS" noHovering style={{marginTop: 10}} >
|
||||
<div className="req-row headers">
|
||||
{
|
||||
headers.map((item, index) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Input value={item.name} onChange={e => this.changeHeader(e, index, true)} style={{display: 'inline-block', width: 200, margin: 10}} />{' = '}
|
||||
<Input value={item.value} onChange={e => this.changeHeader(e, index)} style={{display: 'inline-block', width: 200, margin: 10}} />
|
||||
<Icon type="close" className="icon-btn" onClick={() => this.deleteHeader(index)} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button type="primary" icon="plus" onClick={this.addHeader} style={{margin: 10}}>Add header</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card title="Body" noHovering style={{marginTop: 10}}>
|
||||
<div className="req-row params">
|
||||
<div>
|
||||
<Select style={{margin: 10, float: 'right'}} defaultValue={paramsType} onChange={this.changeParamsType} className={method === 'POST' ? 'floatfix' : 'floatfix hidden'}>
|
||||
<Option value="text">Text</Option>
|
||||
<Option value="file">File</Option>
|
||||
<Option value="form">Form</Option>
|
||||
</Select>
|
||||
</div>
|
||||
{ method === 'POST' && paramsType !== 'form' && paramsType !== 'file' &&
|
||||
<div>
|
||||
<TextArea
|
||||
value={params}
|
||||
style={{margin: 10}}
|
||||
autosize={{ minRows: 2, maxRows: 6 }}
|
||||
></TextArea>
|
||||
<div>{paramsType}</div>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
method === 'POST' && paramsType === 'form' && (
|
||||
<div>
|
||||
{
|
||||
params.map((item, index) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Input value={item.key} onChange={e => this.changeParams(e, index, 'key')} style={{display: 'inline-block', width: 200, margin: 10}} />
|
||||
[<Select value={item.type} onChange={e => this.changeParams(e, index, 'type')}>
|
||||
<Option value="file">File</Option>
|
||||
<Option value="text">Text</Option>
|
||||
</Select>]{' = '}
|
||||
{item.type === 'file' ?
|
||||
<Input type="file" id={'file_' + index} onChange={e => this.changeParams(e, index, 'value')} multiple style={{display: 'inline-block', width: 200, margin: 10}} /> :
|
||||
<Input value={item.value} onChange={e => this.changeParams(e, index, 'value')} style={{display: 'inline-block', width: 200, margin: 10}} />
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Button type="primary" icon="plus" onClick={this.addParams} style={{margin: 10}}>Add form parameter</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
method === 'POST' && paramsType === 'file' && (
|
||||
<div>
|
||||
<Input type="file"></Input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
method !== 'POST' && (
|
||||
<div style={{margin: 10}}>GET 请求没有 Body。</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
<Card title="返回结果" noHovering style={{marginTop: 10}}>
|
||||
<Spin spinning={this.state.loading}>
|
||||
<div className="res-part">
|
||||
<div style={{padding: 10}}>
|
||||
<TextArea
|
||||
value={typeof this.state.res === 'object' ? JSON.stringify(this.state.res, null, 2) : this.state.res.toString()}
|
||||
autosize={{ minRows: 2, maxRows: 6 }}
|
||||
></TextArea>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
18
client/containers/Project/Interface/InterfaceList/Run.scss
Normal file
18
client/containers/Project/Interface/InterfaceList/Run.scss
Normal file
@ -0,0 +1,18 @@
|
||||
.interface-test {
|
||||
.interface-name {
|
||||
font-size: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.icon-btn {
|
||||
cursor: pointer;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.icon-btn:hover {
|
||||
color: #108ee9;
|
||||
}
|
||||
}
|
||||
.floatfix:after{
|
||||
content:"";
|
||||
display:table;
|
||||
clear:both;
|
||||
}
|
138
client/containers/Project/Interface/InterfaceList/mockEditor.js
Normal file
138
client/containers/Project/Interface/InterfaceList/mockEditor.js
Normal file
@ -0,0 +1,138 @@
|
||||
var ace = require('brace'),
|
||||
Mock = require('mockjs')
|
||||
require('brace/mode/javascript');
|
||||
require('brace/theme/xcode');
|
||||
require("brace/ext/language_tools.js");
|
||||
var json5 = require('json5');
|
||||
|
||||
var langTools = ace.acequire("ace/ext/language_tools"),
|
||||
editor,
|
||||
mockEditor,
|
||||
rhymeCompleter,
|
||||
wordList = [
|
||||
{ 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: '浮点数', mock: '@float' },
|
||||
{ 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' }
|
||||
];
|
||||
|
||||
function run(options) {
|
||||
options = options || {};
|
||||
var container, data;
|
||||
container = options.container || 'mock-editor';
|
||||
if (options.wordList && typeof options.wordList === 'object' && options.wordList.name && options.wordList.mock) {
|
||||
wordList.push(options.wordList);
|
||||
}
|
||||
data = options.data || '';
|
||||
|
||||
editor = ace.edit(container)
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setMode('ace/mode/javascript');
|
||||
editor.setTheme('ace/theme/xcode');
|
||||
editor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: false,
|
||||
enableLiveAutocompletion: true,
|
||||
useWorker: true
|
||||
});
|
||||
mockEditor = {
|
||||
curData: {},
|
||||
getValue: editor.getValue,
|
||||
setValue: function (data) {
|
||||
data = data || '';
|
||||
if (typeof data === 'string') {
|
||||
editor.setValue(data);
|
||||
} else if (typeof data === 'object') {
|
||||
editor.setValue(json5(data, null, " "))
|
||||
}
|
||||
},
|
||||
editor: editor
|
||||
}
|
||||
rhymeCompleter = {
|
||||
identifierRegexps: [/[@]/],
|
||||
getCompletions: function (editor, session, pos, prefix, callback) {
|
||||
if (prefix.length === 0) { callback(null, []); return }
|
||||
callback(null, wordList.map(function (ea) {
|
||||
return { name: ea.mock, value: ea.mock, score: ea.mock, meta: ea.name }
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
langTools.addCompleter(rhymeCompleter);
|
||||
mockEditor.setValue(data);
|
||||
handleJson(editor.getValue())
|
||||
|
||||
editor.clearSelection();
|
||||
|
||||
editor.getSession().on('change', () => {
|
||||
handleJson(editor.getValue())
|
||||
if (typeof options.onChange === 'function') {
|
||||
options.onChange.call(mockEditor, mockEditor.curData);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return mockEditor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function handleJson(json) {
|
||||
var curData = mockEditor.curData;
|
||||
try {
|
||||
var obj = json5.parse(json);
|
||||
curData.text = json;
|
||||
curData.format = true;
|
||||
curData.jsonData = obj;
|
||||
curData.mockData = Mock.mock(obj);
|
||||
curData.mockText = JSON.stringify(curData.mockData, null, " ");
|
||||
} catch (e) {
|
||||
curData.format = e.message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = run;
|
@ -3,7 +3,7 @@ import { message } from 'antd';
|
||||
export default () => next => action => {
|
||||
if (action.error) {
|
||||
message.error((action.payload && action.payload.message) || '服务器错误');
|
||||
} else if (action.payload && action.payload.data && action.payload.data.errcode) {
|
||||
} else if (action.payload && action.payload.data && action.payload.data.errcode && action.payload.data.errcode !== 40011) {
|
||||
message.error(action.payload.data.errmsg);
|
||||
}
|
||||
return next(action);
|
||||
|
34
client/reducer/modules/follow.js
Normal file
34
client/reducer/modules/follow.js
Normal file
@ -0,0 +1,34 @@
|
||||
import axios from 'axios';
|
||||
|
||||
// Actions
|
||||
const GET_FOLLOW_LIST = 'yapi/follow/GET_FOLLOW_LIST';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
data: []
|
||||
};
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GET_FOLLOW_LIST: {
|
||||
console.log(action);
|
||||
return {
|
||||
...state,
|
||||
data: action.payload.data.data
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Action Creators
|
||||
export function getFollowList(uid) {
|
||||
return {
|
||||
type: GET_FOLLOW_LIST,
|
||||
payload: axios.get('/api/follow/list', {
|
||||
params: { uid }
|
||||
})
|
||||
}
|
||||
}
|
@ -2,19 +2,60 @@ import axios from 'axios'
|
||||
// Actions
|
||||
const FETCH_INTERFACE_DATA = 'yapi/interface/FETCH_INTERFACE_DATA';
|
||||
const FETCH_INTERFACE_LIST = 'yapi/interface/FETCH_INTERFACE_LIST';
|
||||
|
||||
// const DELETE_INTERFACE_DATA = 'yapi/interface/DELETE_INTERFACE_DATA';
|
||||
const CHANGE_INTERFACE_ID = 'yapi/interface/CHANGE_INTERFACE_ID';
|
||||
const ADD_INTERFACE_DATA = 'yapi/interface/ADD_INTERFACE_DATA';
|
||||
const DELETE_INTERFACE_DATA = 'yapi/interface/DELETE_INTERFACE_DATA';
|
||||
const UPDATE_INTERFACE_DATA = 'yapi/interface/UPDATE_INTERFACE_DATA';
|
||||
// const SAVE_INTERFACE_PROJECT_ID = 'yapi/interface/SAVE_INTERFACE_PROJECT_ID';
|
||||
// const GET_INTERFACE_GROUP_LIST = 'yapi/interface/GET_INTERFACE_GROUP_LIST';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
interfaceId: 0,
|
||||
curdata: {},
|
||||
list: []
|
||||
}
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case UPDATE_INTERFACE_DATA:
|
||||
return {
|
||||
...state,
|
||||
curdata: action.updata
|
||||
}
|
||||
case DELETE_INTERFACE_DATA:
|
||||
return (() => {
|
||||
|
||||
let newlist = state.list.filter(data => data._id !== action.payload), newid, curdata;
|
||||
|
||||
if (state.interfaceId === action.payload && state.list.length > 0) {
|
||||
newid = state.list[0]._id
|
||||
curdata = state.list[0]
|
||||
} else if (state.list.length == 0) {
|
||||
newid = 0;
|
||||
curdata = {}
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
curdata: curdata,
|
||||
interfaceId: newid,
|
||||
list: newlist
|
||||
}
|
||||
})()
|
||||
|
||||
case ADD_INTERFACE_DATA:
|
||||
return {
|
||||
...state,
|
||||
curdata: action.payload,
|
||||
list: [].concat(state.list, action.payload),
|
||||
interfaceId: action.payload._id
|
||||
}
|
||||
case CHANGE_INTERFACE_ID:
|
||||
return {
|
||||
...state,
|
||||
interfaceId: action.payload
|
||||
}
|
||||
case FETCH_INTERFACE_DATA:
|
||||
return {
|
||||
...state,
|
||||
@ -23,32 +64,60 @@ export default (state = initialState, action) => {
|
||||
case FETCH_INTERFACE_LIST:
|
||||
return {
|
||||
...state,
|
||||
list: action.payload.data
|
||||
}
|
||||
list: action.payload.data,
|
||||
curdata: action.payload.data.length > 0 ? action.payload.data[0] : {}
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export function changeInterfaceId(id) {
|
||||
return {
|
||||
type: CHANGE_INTERFACE_ID,
|
||||
payload: id
|
||||
}
|
||||
}
|
||||
|
||||
export function updateInterfaceData(updata) {
|
||||
|
||||
return {
|
||||
type: UPDATE_INTERFACE_DATA,
|
||||
updata: updata,
|
||||
payload: true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export async function deleteInterfaceData(id) {
|
||||
await axios.post('/api/interface/del', { id: id })
|
||||
return {
|
||||
type: DELETE_INTERFACE_DATA,
|
||||
payload: id
|
||||
}
|
||||
}
|
||||
|
||||
// Action Creators
|
||||
export function fetchInterfaceData (interfaceId) {
|
||||
return async (dispatch) => {
|
||||
let result = await axios.get('/api/interface/get?id=' + interfaceId);
|
||||
dispatch({
|
||||
type: FETCH_INTERFACE_DATA,
|
||||
payload: result.data
|
||||
})
|
||||
export async function fetchInterfaceData(interfaceId) {
|
||||
let result = await axios.get('/api/interface/get?id=' + interfaceId);
|
||||
return {
|
||||
type: FETCH_INTERFACE_DATA,
|
||||
payload: result.data
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchInterfaceList(projectId){
|
||||
return async (dispatch) => {
|
||||
let result = await axios.get('/api/interface/list?project_id=' + projectId);
|
||||
dispatch({
|
||||
type: FETCH_INTERFACE_LIST,
|
||||
payload: result.data
|
||||
})
|
||||
export async function fetchInterfaceList(projectId) {
|
||||
let result = await axios.get('/api/interface/list?project_id=' + projectId);
|
||||
return {
|
||||
type: FETCH_INTERFACE_LIST,
|
||||
payload: result.data
|
||||
}
|
||||
}
|
||||
|
||||
export async function addInterfaceData(data) {
|
||||
return {
|
||||
type: ADD_INTERFACE_DATA,
|
||||
payload: data
|
||||
}
|
||||
}
|
63
client/reducer/modules/interfaceCol.js
Normal file
63
client/reducer/modules/interfaceCol.js
Normal file
@ -0,0 +1,63 @@
|
||||
import axios from 'axios'
|
||||
// Actions
|
||||
const FETCH_INTERFACE_COL_LIST = 'yapi/interfaceCol/FETCH_INTERFACE_COL_LIST';
|
||||
const FETCH_INTERFACE_CASE_LIST = 'yapi/interfaceCol/FETCH_INTERFACE_CASE_LIST';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
interfaceColList: [{
|
||||
_id: 0,
|
||||
name: '',
|
||||
uid: 0,
|
||||
project_id: 0,
|
||||
desc: '',
|
||||
add_time: 0,
|
||||
up_time: 0,
|
||||
interfaceCaseList: [
|
||||
{}
|
||||
]
|
||||
}],
|
||||
isShowCol: true,
|
||||
currInterfaceColId: 0,
|
||||
currInterfaceCaseId: 0
|
||||
}
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case FETCH_INTERFACE_COL_LIST:
|
||||
return {
|
||||
...state,
|
||||
interfaceColList: action.payload.data.data
|
||||
}
|
||||
case FETCH_INTERFACE_CASE_LIST: {
|
||||
const interfaceCaseList = state.interfaceColList.map(col => {
|
||||
if (col._id === state.currInterfaceColId) {
|
||||
return col.interfaceCaseList = action.payload.data.data;
|
||||
}
|
||||
return col;
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
interfaceCaseList
|
||||
}
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Action Creators
|
||||
export function fetchInterfaceColList (projectId) {
|
||||
return {
|
||||
type: FETCH_INTERFACE_COL_LIST,
|
||||
payload: axios.get('/api/col/list?project_id=' + projectId)
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchInterfaceCaseList(colId){
|
||||
return {
|
||||
type: FETCH_INTERFACE_CASE_LIST,
|
||||
payload: axios.get('/api/col/case_list?col_id=' + colId)
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ const PROJECT_DEL = 'yapi/project/PROJECT_DEL';
|
||||
const CHANGE_UPDATE_MODAL = 'yapi/project/CHANGE_UPDATE_MODAL';
|
||||
const CHANGE_TABLE_LOADING = 'yapi/project/CHANGE_TABLE_LOADING';
|
||||
const PROJECT_UPDATE = 'yapi/project/PROJECT_UPDATE';
|
||||
const GET_CUR_PROJECT = 'yapi/project/GET_CUR_PROJECT'
|
||||
const GET_CURR_PROJECT = 'yapi/project/GET_CURR_PROJECT'
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
@ -19,15 +19,15 @@ const initialState = {
|
||||
tableLoading: true,
|
||||
total: 0,
|
||||
currPage: 1,
|
||||
curProject: {}
|
||||
currProject: {}
|
||||
};
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GET_CUR_PROJECT: {
|
||||
case GET_CURR_PROJECT: {
|
||||
return {
|
||||
...state,
|
||||
curProject: action.payload.data
|
||||
currProject: action.payload.data
|
||||
}
|
||||
}
|
||||
case CHANGE_UPDATE_MODAL: {
|
||||
@ -132,12 +132,12 @@ export function delProject(id) {
|
||||
}
|
||||
|
||||
export function getProject(id){
|
||||
|
||||
return async (dispatch) => {
|
||||
|
||||
return async (dispatch) => {
|
||||
let result = await axios.get('/api/project/get?id=' + id);
|
||||
dispatch({
|
||||
type: GET_CUR_PROJECT,
|
||||
payload: result.data
|
||||
type: GET_CURR_PROJECT,
|
||||
payload: result.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,20 @@ import user from './user.js'
|
||||
import group from './group.js'
|
||||
import project from './project.js'
|
||||
import inter from './interface.js'
|
||||
import interfaceCol from './interfaceCol.js'
|
||||
import news from './news.js'
|
||||
import addInterface from './addInterface.js'
|
||||
import menu from './menu.js'
|
||||
import follow from './follow.js'
|
||||
|
||||
export default combineReducers({
|
||||
group,
|
||||
user,
|
||||
inter,
|
||||
interfaceCol,
|
||||
project,
|
||||
news,
|
||||
addInterface,
|
||||
menu
|
||||
menu,
|
||||
follow
|
||||
})
|
||||
|
@ -24,15 +24,13 @@ const initialState = {
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GET_LOGIN_STATE: {
|
||||
console.log(action.payload.data);
|
||||
return {
|
||||
...state,
|
||||
isLogin: (action.payload.data.errcode == 0),
|
||||
role: action.payload.data.data ? action.payload.data.data.role:null,
|
||||
loginState: (action.payload.data.errcode == 0)?MEMBER_STATUS:GUEST_STATUS,
|
||||
userName: action.payload.data.data ? action.payload.data.data.username : null,
|
||||
uid: action.payload.data.data ? action.payload.data.data._id : null,
|
||||
server_ip: action.payload.data.data ? action.payload.data.data.server_ip:null
|
||||
uid: action.payload.data.data ? action.payload.data.data._id : null
|
||||
};
|
||||
}
|
||||
case LOGIN: {
|
||||
@ -42,8 +40,7 @@ export default (state = initialState, action) => {
|
||||
isLogin: true,
|
||||
loginState: MEMBER_STATUS,
|
||||
uid: action.payload.data.data.uid,
|
||||
userName: action.payload.data.data.username,
|
||||
server_ip: action.payload.data.data.server_ip
|
||||
userName: action.payload.data.data.username
|
||||
};
|
||||
} else {
|
||||
return state;
|
||||
|
@ -52,6 +52,7 @@
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-watch": "^4.3.11",
|
||||
"json2html": "0.0.8",
|
||||
"json5": "^0.5.1",
|
||||
"jsoneditor": "^5.9.3",
|
||||
"jsonwebtoken": "^7.4.1",
|
||||
"koa": "^2.0.0",
|
||||
|
@ -72,7 +72,7 @@ class baseController {
|
||||
result.server_ip = yapi.WEBCONFIG.server_ip;
|
||||
return ctx.body = yapi.commons.resReturn(result);
|
||||
}
|
||||
return ctx.body = yapi.commons.resReturn(null, 300, 'Please login.');
|
||||
return ctx.body = yapi.commons.resReturn(null, 40011, '请登录...');
|
||||
}
|
||||
|
||||
getRole() {
|
||||
|
@ -23,12 +23,12 @@ class interfaceController extends baseController {
|
||||
* @param {String} [req_headers[].value] 请求的header信息值
|
||||
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
|
||||
* @param {String} [req_headers[].desc] header描述
|
||||
* @param {String} [req_params_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_params_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_params_form[].name] 请求参数名
|
||||
* @param {String} [req_params_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_params_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_params_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_body_form[].name] 请求参数名
|
||||
* @param {String} [req_body_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
|
||||
* @param {String} [res_body] 响应信息,可填写任意字符串,如果res_body_type是json,则会调用mock功能
|
||||
* @param {String} [desc] 接口描述
|
||||
@ -75,7 +75,7 @@ class interfaceController extends baseController {
|
||||
desc: params.desc,
|
||||
method: params.method,
|
||||
req_headers: params.req_headers,
|
||||
req_params_type: params.req_params_type,
|
||||
req_body_type: params.req_body_type,
|
||||
res_body: params.res_body,
|
||||
res_body_type: params.res_body_type,
|
||||
uid: this.getUid(),
|
||||
@ -83,11 +83,15 @@ class interfaceController extends baseController {
|
||||
up_time: yapi.commons.time()
|
||||
};
|
||||
|
||||
if (params.req_params_form) {
|
||||
data.req_params_form = params.req_params_form;
|
||||
if(params.req_query){
|
||||
data.req_query = params.req_query;
|
||||
}
|
||||
if (params.req_params_other) {
|
||||
data.req_params_other = params.req_params_other;
|
||||
|
||||
if (params.req_body_form) {
|
||||
data.req_body_form = params.req_body_form;
|
||||
}
|
||||
if (params.req_body_other) {
|
||||
data.req_body_other = params.req_body_other;
|
||||
}
|
||||
|
||||
let result = await this.Model.save(data);
|
||||
@ -161,12 +165,12 @@ class interfaceController extends baseController {
|
||||
* @param {String} [req_headers[].value] 请求的header信息值
|
||||
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
|
||||
* @param {String} [req_headers[].desc] header描述
|
||||
* @param {String} [req_params_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_params_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_params_form[].name] 请求参数名
|
||||
* @param {String} [req_params_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_params_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_params_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_body_form[].name] 请求参数名
|
||||
* @param {String} [req_body_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
|
||||
* @param {String} [res_body] 响应信息,可填写任意字符串,如果res_body_type是json,则会调用mock功能
|
||||
* @param {String} [desc] 接口描述
|
||||
@ -224,12 +228,15 @@ class interfaceController extends baseController {
|
||||
if (params.req_headers) {
|
||||
data.req_headers = params.req_headers;
|
||||
}
|
||||
|
||||
if (params.req_params_form) {
|
||||
data.req_params_form = params.req_params_form;
|
||||
|
||||
if (params.req_body_form) {
|
||||
data.req_body_form = params.req_body_form;
|
||||
}
|
||||
if (params.req_params_other) {
|
||||
data.req_params_other = params.req_params_other;
|
||||
if(params.req_query){
|
||||
data.req_query = params.req_query;
|
||||
}
|
||||
if (params.req_body_other) {
|
||||
data.req_body_other = params.req_body_other;
|
||||
}
|
||||
|
||||
if (params.res_body_type) {
|
||||
|
@ -17,14 +17,18 @@ class interfaceColController extends baseController{
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} project_id email名称,不能为空
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
async list(ctx){
|
||||
try {
|
||||
let id = ctx.query.project_id;
|
||||
let inst = this.colModel(interfaceColModel);
|
||||
let result = await inst.list(id);
|
||||
let result = await this.colModel.list(id);
|
||||
|
||||
for(let i=0; i< result.length;i++){
|
||||
result[i] = result[i].toObject();
|
||||
result[i].caseList = await this.caseModel.list(result[i]._id)
|
||||
}
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -40,8 +44,8 @@ class interfaceColController extends baseController{
|
||||
* @param {Number} project_id
|
||||
* @param {String} name
|
||||
* @param {String} desc
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async addCol(ctx){
|
||||
@ -52,14 +56,14 @@ class interfaceColController extends baseController{
|
||||
project_id: 'number',
|
||||
desc: 'string'
|
||||
});
|
||||
|
||||
|
||||
if (!params.project_id) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
|
||||
}
|
||||
if(!params.name){
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '名称不能为空');
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '名称不能为空');
|
||||
}
|
||||
|
||||
|
||||
let result = await this.colModel.save({
|
||||
name: params.name,
|
||||
project_id: params.project_id,
|
||||
@ -82,8 +86,8 @@ class interfaceColController extends baseController{
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} col_id 接口集id
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async getCaseList(ctx){
|
||||
@ -106,17 +110,17 @@ class interfaceColController extends baseController{
|
||||
* @param {String} casename
|
||||
* @param {Number} col_id
|
||||
* @param {Number} project_id
|
||||
* @param {String} env
|
||||
* @param {String} env
|
||||
* @param {String} domain
|
||||
* @param {String} path
|
||||
* @param {String} method
|
||||
* @param {Object} req_query
|
||||
* @param {Object} req_headers
|
||||
* @param {String} req_body_type
|
||||
* @param {Array} req_body_form
|
||||
* @param {Array} req_body_form
|
||||
* @param {String} req_body_other
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async addCase(ctx){
|
||||
@ -130,23 +134,17 @@ class interfaceColController extends baseController{
|
||||
domain: 'string',
|
||||
method: 'string'
|
||||
});
|
||||
|
||||
|
||||
if (!params.project_id) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
|
||||
}
|
||||
if (!params.col_id) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '接口集id不能为空');
|
||||
}
|
||||
if (!params.env) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '缺少环境配置');
|
||||
}
|
||||
if (!params.path) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, 'path 不能为空');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(!params.casename){
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '用例名称不能为空');
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '用例名称不能为空');
|
||||
}
|
||||
|
||||
params.uid = this.getUid();
|
||||
@ -154,7 +152,7 @@ class interfaceColController extends baseController{
|
||||
params.add_time = yapi.commons.time();
|
||||
params.up_time = yapi.commons.time();
|
||||
let result = await this.caseModel.save(params);
|
||||
|
||||
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
|
||||
}catch(e){
|
||||
@ -169,8 +167,8 @@ class interfaceColController extends baseController{
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} caseid
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async getCase(ctx){
|
||||
@ -191,8 +189,8 @@ class interfaceColController extends baseController{
|
||||
* @foldnumber 10
|
||||
* @param {String} name
|
||||
* @param {String} desc
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async upCol(ctx){
|
||||
@ -216,8 +214,8 @@ class interfaceColController extends baseController{
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {Array} [id, index]
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async upCaseIndex(ctx){
|
||||
@ -232,9 +230,9 @@ class interfaceColController extends baseController{
|
||||
yapi.commons.log(err.message, 'error')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
return ctx.body = yapi.commons.resReturn('success')
|
||||
}catch(e){
|
||||
ctx.body = yapi.commons.resReturn(null, 400, e.message)
|
||||
@ -247,9 +245,9 @@ class interfaceColController extends baseController{
|
||||
* @method GET
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String}
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @param {String}
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async delCol(ctx){
|
||||
@ -277,8 +275,8 @@ class interfaceColController extends baseController{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} ctx
|
||||
*
|
||||
* @param {*} ctx
|
||||
*/
|
||||
|
||||
async delCase(ctx){
|
||||
@ -308,4 +306,4 @@ class interfaceColController extends baseController{
|
||||
|
||||
}
|
||||
|
||||
module.exports = interfaceColController
|
||||
module.exports = interfaceColController
|
||||
|
@ -45,8 +45,6 @@ class projectController extends baseController {
|
||||
* @foldnumber 10
|
||||
* @param {String} name 项目名称,不能为空
|
||||
* @param {String} basepath 项目基本路径,不能为空
|
||||
* @param {String} prd_host 项目线上域名,不能为空。可通过配置的域名访问到mock数据
|
||||
* @param {String} protocol 线上域名协议,不能为空
|
||||
* @param {Number} group_id 项目分组id,不能为空
|
||||
* @param {String} project_type private public
|
||||
* @param {String} [desc] 项目描述
|
||||
@ -58,8 +56,6 @@ class projectController extends baseController {
|
||||
params = yapi.commons.handleParams(params, {
|
||||
name: 'string',
|
||||
basepath: 'string',
|
||||
prd_host: 'string',
|
||||
protocol: 'string',
|
||||
group_id: 'number',
|
||||
desc: 'string'
|
||||
});
|
||||
@ -82,35 +78,16 @@ class projectController extends baseController {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名');
|
||||
}
|
||||
|
||||
|
||||
if (!params.prd_host) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目domain不能为空');
|
||||
}
|
||||
|
||||
params.basepath = params.basepath || '';
|
||||
|
||||
if ((params.basepath = this.handleBasepath(params.basepath)) === false) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
|
||||
}
|
||||
|
||||
if (!this.verifyDomain(params.prd_host)) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, '线上域名格式有误');
|
||||
}
|
||||
|
||||
let checkRepeatDomain = await this.Model.checkDomainRepeat(params.prd_host, params.basepath);
|
||||
|
||||
if (checkRepeatDomain > 0) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, '已存在domain和basepath');
|
||||
}
|
||||
|
||||
|
||||
|
||||
let data = {
|
||||
name: params.name,
|
||||
desc: params.desc,
|
||||
prd_host: params.prd_host,
|
||||
basepath: params.basepath,
|
||||
protocol: params.protocol || 'http',
|
||||
members: [],
|
||||
project_type: params.project_type || 'private',
|
||||
uid: this.getUid(),
|
||||
@ -426,7 +403,6 @@ class projectController extends baseController {
|
||||
* @param {Number} id 项目id,不能为空
|
||||
* @param {String} name 项目名称,不能为空
|
||||
* @param {String} basepath 项目基本路径,不能为空
|
||||
* @param {String} prd_host 项目线上域名,不能为空。可通过配置的域名访问到mock数据
|
||||
* @param {String} [desc] 项目描述
|
||||
* @param {Array} [env] 项目环境配置
|
||||
* @param {String} [env[].name] 环境名称
|
||||
@ -443,8 +419,6 @@ class projectController extends baseController {
|
||||
params = yapi.commons.handleParams(params, {
|
||||
name: 'string',
|
||||
basepath: 'string',
|
||||
prd_host: 'string',
|
||||
protocol: 'string',
|
||||
group_id: 'number',
|
||||
desc: 'string'
|
||||
});
|
||||
@ -462,17 +436,9 @@ class projectController extends baseController {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
|
||||
}
|
||||
|
||||
if (!this.verifyDomain(params.prd_host)) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, '线上域名格式有误');
|
||||
}
|
||||
|
||||
if (projectData.name === params.name) {
|
||||
delete params.name;
|
||||
}
|
||||
if (projectData.basepath === params.basepath && projectData.prd_host === params.prd_host) {
|
||||
delete params.basepath;
|
||||
delete params.prd_host;
|
||||
}
|
||||
|
||||
if (params.name) {
|
||||
let checkRepeat = await this.Model.checkNameRepeat(params.name);
|
||||
@ -481,24 +447,15 @@ class projectController extends baseController {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.basepath && params.prd_host) {
|
||||
let checkRepeatDomain = await this.Model.checkDomainRepeat(params.prd_host, params.basepath);
|
||||
if (checkRepeatDomain > 0) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 401, '已存在domain和basepath');
|
||||
}
|
||||
}
|
||||
|
||||
let data = {
|
||||
up_time: yapi.commons.time()
|
||||
};
|
||||
|
||||
if (params.name) data.name = params.name;
|
||||
if (params.desc) data.desc = params.desc;
|
||||
if (params.prd_host ) {
|
||||
data.prd_host = params.prd_host;
|
||||
if (params.basepath ) {
|
||||
data.basepath = params.basepath;
|
||||
}
|
||||
if (params.protocol) data.protocol = params.protocol;
|
||||
if (params.env) data.env = params.env;
|
||||
|
||||
let result = await this.Model.up(id, data);
|
||||
@ -550,7 +507,6 @@ class projectController extends baseController {
|
||||
'members',
|
||||
{ key: 'group_id', alias: 'groupId' },
|
||||
{ key: 'up_time', alias: 'upTime' },
|
||||
{ key: 'prd_host', alias: 'prdHost' },
|
||||
{ key: 'add_time', alias: 'addTime' }
|
||||
];
|
||||
let groupRules = [
|
||||
@ -579,6 +535,7 @@ class projectController extends baseController {
|
||||
* @method GET
|
||||
* @category project
|
||||
* @foldnumber 10
|
||||
* @author wenbo.dong
|
||||
* @param {String} project_id
|
||||
*/
|
||||
async download(ctx) {
|
||||
|
@ -8,45 +8,39 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
let hostname = ctx.hostname;
|
||||
let config = yapi.WEBCONFIG;
|
||||
let path = ctx.path;
|
||||
|
||||
|
||||
if (ctx.hostname === config.webhost) {
|
||||
if (path.indexOf('/mock/') !== 0) {
|
||||
if (next) await next();
|
||||
return true;
|
||||
}
|
||||
|
||||
let paths = path.split("/");
|
||||
let projectId = paths[2];
|
||||
paths.splice(0, 3);
|
||||
path = "/" + paths.join("/");
|
||||
if(!projectId){
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, 'projectId不能为空');
|
||||
}
|
||||
|
||||
yapi.commons.log('MockServer Running...');
|
||||
let projectInst = yapi.getInst(projectModel), projects;
|
||||
let projectInst = yapi.getInst(projectModel), project;
|
||||
try {
|
||||
projects = await projectInst.getByDomain(hostname);
|
||||
project = await projectInst.get(projectId);
|
||||
} catch (e) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 403, e.message);
|
||||
}
|
||||
|
||||
let matchProject = [], maxBasepath = 0;
|
||||
|
||||
for (let i = 0, l = projects.length; i < l; i++) {
|
||||
let project = projects[i];
|
||||
if(ctx.path && project.basepath == ""){
|
||||
matchProject = project;
|
||||
}
|
||||
else if (ctx.path && ctx.path.indexOf(project.basepath) === 0) {
|
||||
if (project.basepath.length > maxBasepath) {
|
||||
maxBasepath = project.basepath.length;
|
||||
matchProject = project;
|
||||
}
|
||||
}
|
||||
if (project === false) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '不存在的项目');
|
||||
}
|
||||
|
||||
if (matchProject === false) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '不存在的domain');
|
||||
}
|
||||
|
||||
let project = matchProject, interfaceData;
|
||||
|
||||
let interfaceData;
|
||||
let interfaceInst = yapi.getInst(interfaceModel);
|
||||
|
||||
try {
|
||||
|
||||
interfaceData = await interfaceInst.getByPath(project._id, ctx.path.substr(project.basepath.length), ctx.method);
|
||||
interfaceData = await interfaceInst.getByPath(project._id, path.substr(project.basepath.length), ctx.method);
|
||||
if (!interfaceData || interfaceData.length === 0) {
|
||||
//非正常跨域预检请求回应
|
||||
if(ctx.method === 'OPTIONS'){
|
||||
|
@ -13,23 +13,36 @@ class interfaceModel extends baseModel {
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
project_id: { type: Number, required: true },
|
||||
status: {type: String, enum: ['undone', 'done'], default: 'undone'},
|
||||
desc: String,
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
req_query:[{
|
||||
name: String, value: String, desc: String, required: Boolean
|
||||
name: String, value: String, desc: String, required: {
|
||||
type:String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_headers: [{
|
||||
name: String, value: String, desc: String, required: Boolean
|
||||
name: String, value: String, desc: String, required: {
|
||||
type:String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_params_type: {
|
||||
req_body_type: {
|
||||
type: String,
|
||||
enum: ['form', 'json', 'text', 'xml']
|
||||
enum: ['form', 'json', 'text', 'file']
|
||||
},
|
||||
req_params_form: [{
|
||||
name: String, value: String, value_type: { type: String, enum: ['text', 'file'] }, desc: String, required: Boolean
|
||||
req_body_form: [{
|
||||
name: String, type: { type: String, enum: ['text', 'file'] }, desc: String, required: {
|
||||
type:String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_params_other: String,
|
||||
req_body_other: String,
|
||||
res_body_type: {
|
||||
type: String,
|
||||
enum: ['json', 'text', 'xml']
|
||||
|
@ -15,10 +15,10 @@ class interfaceCase extends baseModel {
|
||||
project_id: { type: Number, required: true },
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
env: { type: String, required: true },
|
||||
env: { type: String },
|
||||
domain: {type: String },
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
path: { type: String },
|
||||
method: { type: String },
|
||||
req_query: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
@ -48,8 +48,10 @@ class interfaceCase extends baseModel {
|
||||
}).exec();
|
||||
}
|
||||
|
||||
list() {
|
||||
return this.model.find().select("casename uid col_id _id index").exec();
|
||||
list(col_id) {
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).select("casename uid col_id _id index").exec();
|
||||
}
|
||||
|
||||
del(id) {
|
||||
|
@ -15,10 +15,8 @@ class projectModel extends baseModel {
|
||||
group_id: { type: Number, required: true },
|
||||
project_type: {type:String, required: true, enum: ['public', 'private']},
|
||||
members: [
|
||||
{uid: Number, role: {type: String, enum:['owner', 'dev'], username: String, email: String}}
|
||||
{uid: Number, role: {type: String, enum:['owner', 'dev']},username: String, email: String}
|
||||
],
|
||||
protocol: { type: String, required: true },
|
||||
prd_host: { type: String, required: true },
|
||||
env: [
|
||||
{ name: String, domain: String }
|
||||
],
|
||||
@ -60,7 +58,7 @@ class projectModel extends baseModel {
|
||||
list(group_id, auth) {
|
||||
let params = {group_id: group_id}
|
||||
if(!auth) params.project_type = 'public';
|
||||
return this.model.find(params).sort({ _id: -1 }).exec();
|
||||
return this.model.find(params).select("_id uid name basepath desc group_id project_type env add_time up_time").sort({ _id: -1 }).exec();
|
||||
}
|
||||
|
||||
listWithPaging(group_id, page, limit) {
|
||||
@ -111,7 +109,7 @@ class projectModel extends baseModel {
|
||||
{
|
||||
_id: id
|
||||
}, {
|
||||
$pull: { members: uid }
|
||||
$pull: { members: {uid: uid} }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ function createAction(controller, action, path, method) {
|
||||
if (inst.$auth === true) {
|
||||
await inst[action].call(inst, ctx);
|
||||
} else {
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, '请登录.');
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, '请登录...');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,10 +18,11 @@ function connect() {
|
||||
let config = yapi.WEBCONFIG;
|
||||
let options = {};
|
||||
|
||||
if (config.user) {
|
||||
if (config.db.user) {
|
||||
options.user = config.db.user;
|
||||
options.pass = config.db.pass;
|
||||
}
|
||||
|
||||
|
||||
let db = mongoose.connect(`mongodb://${config.db.servername}:${config.db.port}/${config.db.DATABASE}`, options);
|
||||
|
||||
|
@ -193,7 +193,7 @@ var baseController = function () {
|
||||
return _context3.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(result));
|
||||
|
||||
case 7:
|
||||
return _context3.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 300, 'Please login.'));
|
||||
return _context3.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 40011, '请登录...'));
|
||||
|
||||
case 8:
|
||||
case 'end':
|
||||
|
@ -69,12 +69,12 @@ var interfaceController = function (_baseController) {
|
||||
* @param {String} [req_headers[].value] 请求的header信息值
|
||||
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
|
||||
* @param {String} [req_headers[].desc] header描述
|
||||
* @param {String} [req_params_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_params_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_params_form[].name] 请求参数名
|
||||
* @param {String} [req_params_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_params_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_params_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_body_form[].name] 请求参数名
|
||||
* @param {String} [req_body_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
|
||||
* @param {String} [res_body] 响应信息,可填写任意字符串,如果res_body_type是json,则会调用mock功能
|
||||
* @param {String} [desc] 接口描述
|
||||
@ -152,7 +152,7 @@ var interfaceController = function (_baseController) {
|
||||
desc: params.desc,
|
||||
method: params.method,
|
||||
req_headers: params.req_headers,
|
||||
req_params_type: params.req_params_type,
|
||||
req_body_type: params.req_body_type,
|
||||
res_body: params.res_body,
|
||||
res_body_type: params.res_body_type,
|
||||
uid: this.getUid(),
|
||||
@ -161,35 +161,39 @@ var interfaceController = function (_baseController) {
|
||||
};
|
||||
|
||||
|
||||
if (params.req_params_form) {
|
||||
data.req_params_form = params.req_params_form;
|
||||
}
|
||||
if (params.req_params_other) {
|
||||
data.req_params_other = params.req_params_other;
|
||||
if (params.req_query) {
|
||||
data.req_query = params.req_query;
|
||||
}
|
||||
|
||||
_context.next = 22;
|
||||
if (params.req_body_form) {
|
||||
data.req_body_form = params.req_body_form;
|
||||
}
|
||||
if (params.req_body_other) {
|
||||
data.req_body_other = params.req_body_other;
|
||||
}
|
||||
|
||||
_context.next = 23;
|
||||
return this.Model.save(data);
|
||||
|
||||
case 22:
|
||||
case 23:
|
||||
result = _context.sent;
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context.next = 29;
|
||||
_context.next = 30;
|
||||
break;
|
||||
|
||||
case 26:
|
||||
_context.prev = 26;
|
||||
case 27:
|
||||
_context.prev = 27;
|
||||
_context.t0 = _context['catch'](16);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context.t0.message);
|
||||
|
||||
case 29:
|
||||
case 30:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this, [[16, 26]]);
|
||||
}, _callee, this, [[16, 27]]);
|
||||
}));
|
||||
|
||||
function add(_x) {
|
||||
@ -337,12 +341,12 @@ var interfaceController = function (_baseController) {
|
||||
* @param {String} [req_headers[].value] 请求的header信息值
|
||||
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
|
||||
* @param {String} [req_headers[].desc] header描述
|
||||
* @param {String} [req_params_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_params_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_params_form[].name] 请求参数名
|
||||
* @param {String} [req_params_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_params_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_params_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
|
||||
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form,参数是Array数组,其他格式请求参数是字符串
|
||||
* @param {String} [req_body_form[].name] 请求参数名
|
||||
* @param {String} [req_body_form[].value] 请求参数值,可填写生成规则(mock)。如@email,随机生成一条email
|
||||
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
|
||||
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
|
||||
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
|
||||
* @param {String} [res_body] 响应信息,可填写任意字符串,如果res_body_type是json,则会调用mock功能
|
||||
* @param {String} [desc] 接口描述
|
||||
@ -436,11 +440,14 @@ var interfaceController = function (_baseController) {
|
||||
data.req_headers = params.req_headers;
|
||||
}
|
||||
|
||||
if (params.req_params_form) {
|
||||
data.req_params_form = params.req_params_form;
|
||||
if (params.req_body_form) {
|
||||
data.req_body_form = params.req_body_form;
|
||||
}
|
||||
if (params.req_params_other) {
|
||||
data.req_params_other = params.req_params_other;
|
||||
if (params.req_query) {
|
||||
data.req_query = params.req_query;
|
||||
}
|
||||
if (params.req_body_other) {
|
||||
data.req_body_other = params.req_body_other;
|
||||
}
|
||||
|
||||
if (params.res_body_type) {
|
||||
@ -450,29 +457,29 @@ var interfaceController = function (_baseController) {
|
||||
data.res_body = params.res_body;
|
||||
}
|
||||
|
||||
_context4.prev = 28;
|
||||
_context4.next = 31;
|
||||
_context4.prev = 29;
|
||||
_context4.next = 32;
|
||||
return this.Model.up(id, data);
|
||||
|
||||
case 31:
|
||||
case 32:
|
||||
result = _context4.sent;
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context4.next = 38;
|
||||
_context4.next = 39;
|
||||
break;
|
||||
|
||||
case 35:
|
||||
_context4.prev = 35;
|
||||
_context4.t0 = _context4['catch'](28);
|
||||
case 36:
|
||||
_context4.prev = 36;
|
||||
_context4.t0 = _context4['catch'](29);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context4.t0.message);
|
||||
|
||||
case 38:
|
||||
case 39:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this, [[28, 35]]);
|
||||
}, _callee4, this, [[29, 36]]);
|
||||
}));
|
||||
|
||||
function up(_x4) {
|
||||
|
@ -66,8 +66,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} project_id email名称,不能为空
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
|
||||
@ -75,36 +75,55 @@ var interfaceColController = function (_baseController) {
|
||||
key: 'list',
|
||||
value: function () {
|
||||
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx) {
|
||||
var id, inst, result;
|
||||
var id, result, i;
|
||||
return _regenerator2.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.prev = 0;
|
||||
id = ctx.query.project_id;
|
||||
inst = this.colModel(_interfaceCol2.default);
|
||||
_context.next = 5;
|
||||
return inst.list(id);
|
||||
_context.next = 4;
|
||||
return this.colModel.list(id);
|
||||
|
||||
case 5:
|
||||
case 4:
|
||||
result = _context.sent;
|
||||
i = 0;
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context.next = 12;
|
||||
case 6:
|
||||
if (!(i < result.length)) {
|
||||
_context.next = 14;
|
||||
break;
|
||||
}
|
||||
|
||||
result[i] = result[i].toObject();
|
||||
_context.next = 10;
|
||||
return this.caseModel.list(result[i]._id);
|
||||
|
||||
case 10:
|
||||
result[i].caseList = _context.sent;
|
||||
|
||||
case 11:
|
||||
i++;
|
||||
_context.next = 6;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
_context.prev = 9;
|
||||
case 14:
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context.next = 20;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
_context.prev = 17;
|
||||
_context.t0 = _context['catch'](0);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context.t0.message);
|
||||
|
||||
case 12:
|
||||
case 20:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this, [[0, 9]]);
|
||||
}, _callee, this, [[0, 17]]);
|
||||
}));
|
||||
|
||||
function list(_x) {
|
||||
@ -123,8 +142,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @param {Number} project_id
|
||||
* @param {String} name
|
||||
* @param {String} desc
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -207,8 +226,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} col_id 接口集id
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -263,17 +282,17 @@ var interfaceColController = function (_baseController) {
|
||||
* @param {String} casename
|
||||
* @param {Number} col_id
|
||||
* @param {Number} project_id
|
||||
* @param {String} env
|
||||
* @param {String} env
|
||||
* @param {String} domain
|
||||
* @param {String} path
|
||||
* @param {String} method
|
||||
* @param {Object} req_query
|
||||
* @param {Object} req_headers
|
||||
* @param {String} req_body_type
|
||||
* @param {Array} req_body_form
|
||||
* @param {Array} req_body_form
|
||||
* @param {String} req_body_other
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -310,62 +329,46 @@ var interfaceColController = function (_baseController) {
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '项目id不能为空'));
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '接口集id不能为空'));
|
||||
|
||||
case 7:
|
||||
if (params.env) {
|
||||
_context4.next = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '缺少环境配置'));
|
||||
|
||||
case 9:
|
||||
if (params.path) {
|
||||
_context4.next = 11;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, 'path 不能为空'));
|
||||
|
||||
case 11:
|
||||
if (params.casename) {
|
||||
_context4.next = 13;
|
||||
_context4.next = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '用例名称不能为空'));
|
||||
|
||||
case 13:
|
||||
case 9:
|
||||
|
||||
params.uid = this.getUid();
|
||||
params.index = 0;
|
||||
params.add_time = _yapi2.default.commons.time();
|
||||
params.up_time = _yapi2.default.commons.time();
|
||||
_context4.next = 19;
|
||||
_context4.next = 15;
|
||||
return this.caseModel.save(params);
|
||||
|
||||
case 19:
|
||||
case 15:
|
||||
result = _context4.sent;
|
||||
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
|
||||
_context4.next = 26;
|
||||
_context4.next = 22;
|
||||
break;
|
||||
|
||||
case 23:
|
||||
_context4.prev = 23;
|
||||
case 19:
|
||||
_context4.prev = 19;
|
||||
_context4.t0 = _context4['catch'](0);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context4.t0.message);
|
||||
|
||||
case 26:
|
||||
case 22:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this, [[0, 23]]);
|
||||
}, _callee4, this, [[0, 19]]);
|
||||
}));
|
||||
|
||||
function addCase(_x4) {
|
||||
@ -382,8 +385,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String} caseid
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -436,8 +439,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @foldnumber 10
|
||||
* @param {String} name
|
||||
* @param {String} desc
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -493,8 +496,8 @@ var interfaceColController = function (_baseController) {
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {Array} [id, index]
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -551,9 +554,9 @@ var interfaceColController = function (_baseController) {
|
||||
* @method GET
|
||||
* @category col
|
||||
* @foldnumber 10
|
||||
* @param {String}
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* @param {String}
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
}, {
|
||||
@ -625,8 +628,8 @@ var interfaceColController = function (_baseController) {
|
||||
}()
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} ctx
|
||||
*
|
||||
* @param {*} ctx
|
||||
*/
|
||||
|
||||
}, {
|
||||
|
@ -116,8 +116,6 @@ var projectController = function (_baseController) {
|
||||
* @foldnumber 10
|
||||
* @param {String} name 项目名称,不能为空
|
||||
* @param {String} basepath 项目基本路径,不能为空
|
||||
* @param {String} prd_host 项目线上域名,不能为空。可通过配置的域名访问到mock数据
|
||||
* @param {String} protocol 线上域名协议,不能为空
|
||||
* @param {Number} group_id 项目分组id,不能为空
|
||||
* @param {String} project_type private public
|
||||
* @param {String} [desc] 项目描述
|
||||
@ -129,7 +127,7 @@ var projectController = function (_baseController) {
|
||||
key: 'add',
|
||||
value: function () {
|
||||
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx) {
|
||||
var params, checkRepeat, checkRepeatDomain, data, result, username;
|
||||
var params, checkRepeat, data, result, username;
|
||||
return _regenerator2.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
@ -139,8 +137,6 @@ var projectController = function (_baseController) {
|
||||
params = _yapi2.default.commons.handleParams(params, {
|
||||
name: 'string',
|
||||
basepath: 'string',
|
||||
prd_host: 'string',
|
||||
protocol: 'string',
|
||||
group_id: 'number',
|
||||
desc: 'string'
|
||||
});
|
||||
@ -189,53 +185,21 @@ var projectController = function (_baseController) {
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '已存在的项目名'));
|
||||
|
||||
case 16:
|
||||
if (params.prd_host) {
|
||||
_context.next = 18;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '项目domain不能为空'));
|
||||
|
||||
case 18:
|
||||
|
||||
params.basepath = params.basepath || '';
|
||||
|
||||
if (!((params.basepath = this.handleBasepath(params.basepath)) === false)) {
|
||||
_context.next = 21;
|
||||
_context.next = 19;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, 'basepath格式有误'));
|
||||
|
||||
case 21:
|
||||
if (this.verifyDomain(params.prd_host)) {
|
||||
_context.next = 23;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '线上域名格式有误'));
|
||||
|
||||
case 23:
|
||||
_context.next = 25;
|
||||
return this.Model.checkDomainRepeat(params.prd_host, params.basepath);
|
||||
|
||||
case 25:
|
||||
checkRepeatDomain = _context.sent;
|
||||
|
||||
if (!(checkRepeatDomain > 0)) {
|
||||
_context.next = 28;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '已存在domain和basepath'));
|
||||
|
||||
case 28:
|
||||
case 19:
|
||||
data = {
|
||||
name: params.name,
|
||||
desc: params.desc,
|
||||
prd_host: params.prd_host,
|
||||
basepath: params.basepath,
|
||||
protocol: params.protocol || 'http',
|
||||
members: [],
|
||||
project_type: params.project_type || 'private',
|
||||
uid: this.getUid(),
|
||||
@ -243,14 +207,14 @@ var projectController = function (_baseController) {
|
||||
add_time: _yapi2.default.commons.time(),
|
||||
up_time: _yapi2.default.commons.time()
|
||||
};
|
||||
_context.prev = 29;
|
||||
_context.next = 32;
|
||||
_context.prev = 20;
|
||||
_context.next = 23;
|
||||
return this.Model.save(data);
|
||||
|
||||
case 32:
|
||||
case 23:
|
||||
result = _context.sent;
|
||||
username = this.getUsername();
|
||||
_context.next = 36;
|
||||
_context.next = 27;
|
||||
return this.logModel.save({
|
||||
content: '\u7528\u6237' + username + '\u6DFB\u52A0\u4E86\u9879\u76EE' + params.name,
|
||||
type: 'project',
|
||||
@ -259,23 +223,23 @@ var projectController = function (_baseController) {
|
||||
typeid: params.group_id
|
||||
});
|
||||
|
||||
case 36:
|
||||
case 27:
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context.next = 42;
|
||||
_context.next = 33;
|
||||
break;
|
||||
|
||||
case 39:
|
||||
_context.prev = 39;
|
||||
_context.t1 = _context['catch'](29);
|
||||
case 30:
|
||||
_context.prev = 30;
|
||||
_context.t1 = _context['catch'](20);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context.t1.message);
|
||||
|
||||
case 42:
|
||||
case 33:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this, [[29, 39]]);
|
||||
}, _callee, this, [[20, 30]]);
|
||||
}));
|
||||
|
||||
function add(_x) {
|
||||
@ -1022,7 +986,6 @@ var projectController = function (_baseController) {
|
||||
* @param {Number} id 项目id,不能为空
|
||||
* @param {String} name 项目名称,不能为空
|
||||
* @param {String} basepath 项目基本路径,不能为空
|
||||
* @param {String} prd_host 项目线上域名,不能为空。可通过配置的域名访问到mock数据
|
||||
* @param {String} [desc] 项目描述
|
||||
* @param {Array} [env] 项目环境配置
|
||||
* @param {String} [env[].name] 环境名称
|
||||
@ -1035,7 +998,7 @@ var projectController = function (_baseController) {
|
||||
key: 'up',
|
||||
value: function () {
|
||||
var _ref10 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee10(ctx) {
|
||||
var _id2, params, projectData, checkRepeat, checkRepeatDomain, data, result, username;
|
||||
var _id2, params, projectData, checkRepeat, data, result, username;
|
||||
|
||||
return _regenerator2.default.wrap(function _callee10$(_context10) {
|
||||
while (1) {
|
||||
@ -1049,8 +1012,6 @@ var projectController = function (_baseController) {
|
||||
params = _yapi2.default.commons.handleParams(params, {
|
||||
name: 'string',
|
||||
basepath: 'string',
|
||||
prd_host: 'string',
|
||||
protocol: 'string',
|
||||
group_id: 'number',
|
||||
desc: 'string'
|
||||
});
|
||||
@ -1091,61 +1052,30 @@ var projectController = function (_baseController) {
|
||||
return _context10.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, 'basepath格式有误'));
|
||||
|
||||
case 17:
|
||||
if (this.verifyDomain(params.prd_host)) {
|
||||
_context10.next = 19;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context10.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '线上域名格式有误'));
|
||||
|
||||
case 19:
|
||||
|
||||
if (projectData.name === params.name) {
|
||||
delete params.name;
|
||||
}
|
||||
if (projectData.basepath === params.basepath && projectData.prd_host === params.prd_host) {
|
||||
delete params.basepath;
|
||||
delete params.prd_host;
|
||||
}
|
||||
|
||||
if (!params.name) {
|
||||
_context10.next = 27;
|
||||
_context10.next = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
_context10.next = 24;
|
||||
_context10.next = 21;
|
||||
return this.Model.checkNameRepeat(params.name);
|
||||
|
||||
case 24:
|
||||
case 21:
|
||||
checkRepeat = _context10.sent;
|
||||
|
||||
if (!(checkRepeat > 0)) {
|
||||
_context10.next = 27;
|
||||
_context10.next = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context10.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '已存在的项目名'));
|
||||
|
||||
case 27:
|
||||
if (!(params.basepath && params.prd_host)) {
|
||||
_context10.next = 33;
|
||||
break;
|
||||
}
|
||||
|
||||
_context10.next = 30;
|
||||
return this.Model.checkDomainRepeat(params.prd_host, params.basepath);
|
||||
|
||||
case 30:
|
||||
checkRepeatDomain = _context10.sent;
|
||||
|
||||
if (!(checkRepeatDomain > 0)) {
|
||||
_context10.next = 33;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context10.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 401, '已存在domain和basepath'));
|
||||
|
||||
case 33:
|
||||
case 24:
|
||||
data = {
|
||||
up_time: _yapi2.default.commons.time()
|
||||
};
|
||||
@ -1153,20 +1083,18 @@ var projectController = function (_baseController) {
|
||||
|
||||
if (params.name) data.name = params.name;
|
||||
if (params.desc) data.desc = params.desc;
|
||||
if (params.prd_host) {
|
||||
data.prd_host = params.prd_host;
|
||||
if (params.basepath) {
|
||||
data.basepath = params.basepath;
|
||||
}
|
||||
if (params.protocol) data.protocol = params.protocol;
|
||||
if (params.env) data.env = params.env;
|
||||
|
||||
_context10.next = 41;
|
||||
_context10.next = 31;
|
||||
return this.Model.up(_id2, data);
|
||||
|
||||
case 41:
|
||||
case 31:
|
||||
result = _context10.sent;
|
||||
username = this.getUsername();
|
||||
_context10.next = 45;
|
||||
_context10.next = 35;
|
||||
return this.logModel.save({
|
||||
content: '\u7528\u6237' + username + '\u66F4\u65B0\u4E86\u9879\u76EE' + params.name,
|
||||
type: 'project',
|
||||
@ -1175,24 +1103,24 @@ var projectController = function (_baseController) {
|
||||
typeid: _id2
|
||||
});
|
||||
|
||||
case 45:
|
||||
case 35:
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(result);
|
||||
_context10.next = 51;
|
||||
_context10.next = 41;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
_context10.prev = 48;
|
||||
case 38:
|
||||
_context10.prev = 38;
|
||||
_context10.t1 = _context10['catch'](0);
|
||||
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 402, _context10.t1.message);
|
||||
|
||||
case 51:
|
||||
case 41:
|
||||
case 'end':
|
||||
return _context10.stop();
|
||||
}
|
||||
}
|
||||
}, _callee10, this, [[0, 48]]);
|
||||
}, _callee10, this, [[0, 38]]);
|
||||
}));
|
||||
|
||||
function up(_x11) {
|
||||
@ -1250,7 +1178,7 @@ var projectController = function (_baseController) {
|
||||
|
||||
case 10:
|
||||
groupList = _context11.sent;
|
||||
projectRules = ['_id', 'name', 'basepath', 'uid', 'env', 'members', { key: 'group_id', alias: 'groupId' }, { key: 'up_time', alias: 'upTime' }, { key: 'prd_host', alias: 'prdHost' }, { key: 'add_time', alias: 'addTime' }];
|
||||
projectRules = ['_id', 'name', 'basepath', 'uid', 'env', 'members', { key: 'group_id', alias: 'groupId' }, { key: 'up_time', alias: 'upTime' }, { key: 'add_time', alias: 'addTime' }];
|
||||
groupRules = ['_id', 'uid', { key: 'group_name', alias: 'groupName' }, { key: 'group_desc', alias: 'groupDesc' }, { key: 'add_time', alias: 'addTime' }, { key: 'up_time', alias: 'upTime' }];
|
||||
|
||||
|
||||
@ -1284,6 +1212,7 @@ var projectController = function (_baseController) {
|
||||
* @method GET
|
||||
* @category project
|
||||
* @foldnumber 10
|
||||
* @author wenbo.dong
|
||||
* @param {String} project_id
|
||||
*/
|
||||
|
||||
|
@ -12,9 +12,9 @@ var _yapi = require('../yapi.js');
|
||||
|
||||
var _yapi2 = _interopRequireDefault(_yapi);
|
||||
|
||||
var _project2 = require('../models/project.js');
|
||||
var _project = require('../models/project.js');
|
||||
|
||||
var _project3 = _interopRequireDefault(_project2);
|
||||
var _project2 = _interopRequireDefault(_project);
|
||||
|
||||
var _interface = require('../models/interface.js');
|
||||
|
||||
@ -28,8 +28,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
||||
|
||||
module.exports = function () {
|
||||
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx, next) {
|
||||
var hostname, config, projectInst, projects, matchProject, maxBasepath, i, l, _project, project, interfaceData, interfaceInst, res;
|
||||
|
||||
var hostname, config, path, paths, projectId, projectInst, project, interfaceData, interfaceInst, res;
|
||||
return _regenerator2.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
@ -38,82 +37,81 @@ module.exports = function () {
|
||||
|
||||
hostname = ctx.hostname;
|
||||
config = _yapi2.default.WEBCONFIG;
|
||||
path = ctx.path;
|
||||
|
||||
if (!(ctx.hostname === config.webhost)) {
|
||||
_context.next = 8;
|
||||
if (!(path.indexOf('/mock/') !== 0)) {
|
||||
_context.next = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!next) {
|
||||
_context.next = 7;
|
||||
_context.next = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 7;
|
||||
_context.next = 8;
|
||||
return next();
|
||||
|
||||
case 7:
|
||||
case 8:
|
||||
return _context.abrupt('return', true);
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
paths = path.split("/");
|
||||
projectId = paths[2];
|
||||
|
||||
_yapi2.default.commons.log('MockServer Running...');
|
||||
projectInst = _yapi2.default.getInst(_project3.default), projects = void 0;
|
||||
_context.prev = 10;
|
||||
_context.next = 13;
|
||||
return projectInst.getByDomain(hostname);
|
||||
paths.splice(0, 3);
|
||||
path = "/" + paths.join("/");
|
||||
|
||||
case 13:
|
||||
projects = _context.sent;
|
||||
_context.next = 19;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
_context.prev = 16;
|
||||
_context.t0 = _context['catch'](10);
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 403, _context.t0.message));
|
||||
|
||||
case 19:
|
||||
matchProject = [], maxBasepath = 0;
|
||||
|
||||
|
||||
for (i = 0, l = projects.length; i < l; i++) {
|
||||
_project = projects[i];
|
||||
|
||||
if (ctx.path && _project.basepath == "") {
|
||||
matchProject = _project;
|
||||
} else if (ctx.path && ctx.path.indexOf(_project.basepath) === 0) {
|
||||
if (_project.basepath.length > maxBasepath) {
|
||||
maxBasepath = _project.basepath.length;
|
||||
matchProject = _project;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(matchProject === false)) {
|
||||
_context.next = 23;
|
||||
if (projectId) {
|
||||
_context.next = 15;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '不存在的domain'));
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, 'projectId不能为空'));
|
||||
|
||||
case 15:
|
||||
|
||||
_yapi2.default.commons.log('MockServer Running...');
|
||||
projectInst = _yapi2.default.getInst(_project2.default), project = void 0;
|
||||
_context.prev = 17;
|
||||
_context.next = 20;
|
||||
return projectInst.get(projectId);
|
||||
|
||||
case 20:
|
||||
project = _context.sent;
|
||||
_context.next = 26;
|
||||
break;
|
||||
|
||||
case 23:
|
||||
project = matchProject, interfaceData = void 0;
|
||||
interfaceInst = _yapi2.default.getInst(_interface2.default);
|
||||
_context.prev = 25;
|
||||
_context.next = 28;
|
||||
return interfaceInst.getByPath(project._id, ctx.path.substr(project.basepath.length), ctx.method);
|
||||
_context.prev = 23;
|
||||
_context.t0 = _context['catch'](17);
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 403, _context.t0.message));
|
||||
|
||||
case 26:
|
||||
if (!(project === false)) {
|
||||
_context.next = 28;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 400, '不存在的项目'));
|
||||
|
||||
case 28:
|
||||
interfaceData = void 0;
|
||||
interfaceInst = _yapi2.default.getInst(_interface2.default);
|
||||
_context.prev = 30;
|
||||
_context.next = 33;
|
||||
return interfaceInst.getByPath(project._id, path.substr(project.basepath.length), ctx.method);
|
||||
|
||||
case 33:
|
||||
interfaceData = _context.sent;
|
||||
|
||||
if (!(!interfaceData || interfaceData.length === 0)) {
|
||||
_context.next = 35;
|
||||
_context.next = 40;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(ctx.method === 'OPTIONS')) {
|
||||
_context.next = 34;
|
||||
_context.next = 39;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -121,54 +119,54 @@ module.exports = function () {
|
||||
ctx.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
|
||||
return _context.abrupt('return', ctx.body = 'ok');
|
||||
|
||||
case 34:
|
||||
case 39:
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 404, '不存在的api'));
|
||||
|
||||
case 35:
|
||||
case 40:
|
||||
if (!(interfaceData.length > 1)) {
|
||||
_context.next = 37;
|
||||
_context.next = 42;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 405, '存在多个api,请检查数据库'));
|
||||
|
||||
case 37:
|
||||
case 42:
|
||||
|
||||
interfaceData = interfaceData[0];
|
||||
ctx.set("Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (!(interfaceData.res_body_type === 'json')) {
|
||||
_context.next = 48;
|
||||
_context.next = 53;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.prev = 40;
|
||||
_context.prev = 45;
|
||||
res = _mockjs2.default.mock(_yapi2.default.commons.json_parse(interfaceData.res_body));
|
||||
return _context.abrupt('return', ctx.body = res);
|
||||
|
||||
case 45:
|
||||
_context.prev = 45;
|
||||
_context.t1 = _context['catch'](40);
|
||||
case 50:
|
||||
_context.prev = 50;
|
||||
_context.t1 = _context['catch'](45);
|
||||
return _context.abrupt('return', ctx.body = {
|
||||
errcode: 400,
|
||||
errmsg: 'mock json数据格式有误',
|
||||
data: interfaceData.res_body
|
||||
});
|
||||
|
||||
case 48:
|
||||
case 53:
|
||||
return _context.abrupt('return', ctx.body = interfaceData.res_body);
|
||||
|
||||
case 51:
|
||||
_context.prev = 51;
|
||||
_context.t2 = _context['catch'](25);
|
||||
case 56:
|
||||
_context.prev = 56;
|
||||
_context.t2 = _context['catch'](30);
|
||||
return _context.abrupt('return', ctx.body = _yapi2.default.commons.resReturn(null, 409, _context.t2.message));
|
||||
|
||||
case 54:
|
||||
case 59:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, undefined, [[10, 16], [25, 51], [40, 45]]);
|
||||
}, _callee, undefined, [[17, 23], [30, 56], [45, 50]]);
|
||||
}));
|
||||
|
||||
return function (_x, _x2) {
|
||||
|
@ -52,23 +52,36 @@ var interfaceModel = function (_baseModel) {
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
project_id: { type: Number, required: true },
|
||||
status: { type: String, enum: ['undone', 'done'], default: 'undone' },
|
||||
desc: String,
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
req_query: [{
|
||||
name: String, value: String, desc: String, required: Boolean
|
||||
name: String, value: String, desc: String, required: {
|
||||
type: String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_headers: [{
|
||||
name: String, value: String, desc: String, required: Boolean
|
||||
name: String, value: String, desc: String, required: {
|
||||
type: String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_params_type: {
|
||||
req_body_type: {
|
||||
type: String,
|
||||
enum: ['form', 'json', 'text', 'xml']
|
||||
enum: ['form', 'json', 'text', 'file']
|
||||
},
|
||||
req_params_form: [{
|
||||
name: String, value: String, value_type: { type: String, enum: ['text', 'file'] }, desc: String, required: Boolean
|
||||
req_body_form: [{
|
||||
name: String, type: { type: String, enum: ['text', 'file'] }, desc: String, required: {
|
||||
type: String,
|
||||
enum: ["1", "0"],
|
||||
default: "1"
|
||||
}
|
||||
}],
|
||||
req_params_other: String,
|
||||
req_body_other: String,
|
||||
res_body_type: {
|
||||
type: String,
|
||||
enum: ['json', 'text', 'xml']
|
||||
|
@ -54,10 +54,10 @@ var interfaceCase = function (_baseModel) {
|
||||
project_id: { type: Number, required: true },
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
env: { type: String, required: true },
|
||||
env: { type: String },
|
||||
domain: { type: String },
|
||||
path: { type: String, required: true },
|
||||
method: { type: String, required: true },
|
||||
path: { type: String },
|
||||
method: { type: String },
|
||||
req_query: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
@ -90,8 +90,10 @@ var interfaceCase = function (_baseModel) {
|
||||
}
|
||||
}, {
|
||||
key: 'list',
|
||||
value: function list() {
|
||||
return this.model.find().select("casename uid col_id _id index").exec();
|
||||
value: function list(col_id) {
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).select("casename uid col_id _id index").exec();
|
||||
}
|
||||
}, {
|
||||
key: 'del',
|
||||
|
@ -53,9 +53,7 @@ var projectModel = function (_baseModel) {
|
||||
desc: String,
|
||||
group_id: { type: Number, required: true },
|
||||
project_type: { type: String, required: true, enum: ['public', 'private'] },
|
||||
members: [{ uid: Number, role: { type: String, enum: ['owner', 'dev'], username: String, email: String } }],
|
||||
protocol: { type: String, required: true },
|
||||
prd_host: { type: String, required: true },
|
||||
members: [{ uid: Number, role: { type: String, enum: ['owner', 'dev'] }, username: String, email: String }],
|
||||
env: [{ name: String, domain: String }],
|
||||
add_time: Number,
|
||||
up_time: Number
|
||||
@ -101,7 +99,7 @@ var projectModel = function (_baseModel) {
|
||||
value: function list(group_id, auth) {
|
||||
var params = { group_id: group_id };
|
||||
if (!auth) params.project_type = 'public';
|
||||
return this.model.find(params).sort({ _id: -1 }).exec();
|
||||
return this.model.find(params).select("_id uid name basepath desc group_id project_type env add_time up_time").sort({ _id: -1 }).exec();
|
||||
}
|
||||
}, {
|
||||
key: 'listWithPaging',
|
||||
@ -156,7 +154,7 @@ var projectModel = function (_baseModel) {
|
||||
return this.model.update({
|
||||
_id: id
|
||||
}, {
|
||||
$pull: { members: uid }
|
||||
$pull: { members: { uid: uid } }
|
||||
});
|
||||
}
|
||||
}, {
|
||||
|
@ -339,7 +339,7 @@ function createAction(controller, action, path, method) {
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 40011, '请登录.');
|
||||
ctx.body = _yapi2.default.commons.resReturn(null, 40011, '请登录...');
|
||||
|
||||
case 9:
|
||||
case 'end':
|
||||
|
@ -30,7 +30,7 @@ function connect() {
|
||||
var config = _yapi2.default.WEBCONFIG;
|
||||
var options = {};
|
||||
|
||||
if (config.user) {
|
||||
if (config.db.user) {
|
||||
options.user = config.db.user;
|
||||
options.pass = config.db.pass;
|
||||
}
|
||||
|
@ -9,8 +9,6 @@
|
||||
<body>
|
||||
<div id="yapi" style="height: 100%;"></div>
|
||||
|
||||
|
||||
|
||||
<script src="http://127.0.0.1:4000/prd/manifest@dev.js"></script>
|
||||
<script src="http://127.0.0.1:4000/prd/lib2@dev.js"></script>
|
||||
<script src="http://127.0.0.1:4000/prd/lib@dev.js"></script>
|
||||
@ -20,7 +18,7 @@
|
||||
<script src="/lib/snippets-json.js"></script>
|
||||
<script src="/lib/ext-language.tools.js"></script>
|
||||
<script src="/lib/mode-json-1.2.8.js"></script>
|
||||
<script src="https://qsso.corp.qunar.com/lib/qsso-auth.js"></script>
|
||||
<script src="https://qsso.corp.qunar.com/lib/qsso-auth.js"></script>
|
||||
|
||||
|
||||
|
||||
|
@ -406,7 +406,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -443,7 +443,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>
|
||||
@ -541,7 +541,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -637,7 +637,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -725,7 +725,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"logout success..."</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -764,7 +764,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token string">"ok"</span>
|
||||
@ -855,7 +855,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" ><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" ><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -951,7 +951,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"logout success..."</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -1436,7 +1436,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"ok"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>
|
||||
@ -1549,7 +1549,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#37" target="_blank">./server/controllers/project.js:37</a>
|
||||
<a href="./static/server/controllers/project.js.html#39" target="_blank">./server/controllers/project.js:39</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -1661,7 +1661,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -1702,7 +1702,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#127" target="_blank">./server/controllers/project.js:127</a>
|
||||
<a href="./static/server/controllers/project.js.html#137" target="_blank">./server/controllers/project.js:137</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -1756,7 +1756,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -1786,7 +1786,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#170" target="_blank">./server/controllers/project.js:170</a>
|
||||
<a href="./static/server/controllers/project.js.html#188" target="_blank">./server/controllers/project.js:188</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -1840,7 +1840,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -1870,7 +1870,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#223" target="_blank">./server/controllers/project.js:223</a>
|
||||
<a href="./static/server/controllers/project.js.html#254" target="_blank">./server/controllers/project.js:254</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -1912,7 +1912,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>
|
||||
@ -1948,7 +1948,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#248" target="_blank">./server/controllers/project.js:248</a>
|
||||
<a href="./static/server/controllers/project.js.html#279" target="_blank">./server/controllers/project.js:279</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -1990,7 +1990,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -2031,7 +2031,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#272" target="_blank">./server/controllers/project.js:272</a>
|
||||
<a href="./static/server/controllers/project.js.html#303" target="_blank">./server/controllers/project.js:303</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -2073,7 +2073,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -2258,7 +2258,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#313" target="_blank">./server/controllers/project.js:313</a>
|
||||
<a href="./static/server/controllers/project.js.html#344" target="_blank">./server/controllers/project.js:344</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -2300,7 +2300,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -2330,7 +2330,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#373" target="_blank">./server/controllers/project.js:373</a>
|
||||
<a href="./static/server/controllers/project.js.html#419" target="_blank">./server/controllers/project.js:419</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -2448,7 +2448,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code">
|
||||
<span class="token comment" spellcheck="true">//请求示例</span>
|
||||
<span class="token punctuation">{</span>
|
||||
<span class="token string">"id"</span><span class="token punctuation">:</span> <span class="token number">8</span><span class="token punctuation">,</span>
|
||||
@ -2490,7 +2490,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#464" target="_blank">./server/controllers/project.js:464</a>
|
||||
<a href="./static/server/controllers/project.js.html#520" target="_blank">./server/controllers/project.js:520</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -2532,7 +2532,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"ok"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -2585,7 +2585,7 @@
|
||||
|
||||
<p>
|
||||
<small class="text-muted">源码位置:</small>
|
||||
<a href="./static/server/controllers/project.js.html#519" target="_blank">./server/controllers/project.js:519</a>
|
||||
<a href="./static/server/controllers/project.js.html#575" target="_blank">./server/controllers/project.js:575</a>
|
||||
</p>
|
||||
|
||||
|
||||
@ -2868,7 +2868,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code">
|
||||
<span class="token comment" spellcheck="true">//请求 /interface/add</span>
|
||||
<span class="token comment" spellcheck="true">//header Content-Type:application/json</span>
|
||||
|
||||
@ -3003,7 +3003,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">.</span><span class="token operator">/</span>api<span class="token operator">/</span><span class="token keyword">interface</span><span class="token operator">/</span><span class="token keyword">get</span><span class="token punctuation">.</span>json</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">.</span><span class="token operator">/</span>api<span class="token operator">/</span><span class="token keyword">interface</span><span class="token operator">/</span><span class="token keyword">get</span><span class="token punctuation">.</span>json</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -3068,7 +3068,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">.</span><span class="token operator">/</span>api<span class="token operator">/</span><span class="token keyword">interface</span><span class="token operator">/</span>list<span class="token punctuation">.</span>json</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">.</span><span class="token operator">/</span>api<span class="token operator">/</span><span class="token keyword">interface</span><span class="token operator">/</span>list<span class="token punctuation">.</span>json</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -3293,7 +3293,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -3366,7 +3366,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token punctuation">{</span>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token punctuation">{</span>
|
||||
<span class="token string">"errcode"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"errmsg"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
|
||||
<span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
|
||||
@ -3461,7 +3461,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token operator">/</span>follow<span class="token operator">/</span>list</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token operator">/</span>follow<span class="token operator">/</span>list</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -3526,7 +3526,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token operator">/</span>follow<span class="token operator">/</span>del</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token operator">/</span>follow<span class="token operator">/</span>del</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -3536,7 +3536,7 @@
|
||||
<h3 id="-follow-add" class="page-header subject">
|
||||
/follow/add
|
||||
|
||||
<span class="ui-badge">POST</span>
|
||||
<span class="ui-badge">GET</span>
|
||||
|
||||
|
||||
<a class="hashlink" href="#-follow-add">#</a>
|
||||
@ -3627,7 +3627,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token operator">/</span>follow<span class="token operator">/</span>add</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token operator">/</span>follow<span class="token operator">/</span>add</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -4344,9 +4344,9 @@
|
||||
</thead>
|
||||
|
||||
<tr>
|
||||
<td>uid</td>
|
||||
<td>typeid</td>
|
||||
<td>Number</td>
|
||||
<td>用户id, 不能为空</td>
|
||||
<td>动态类型id, 不能为空</td>
|
||||
<td>
|
||||
|
||||
<i class="yo-ico glyphicon glyphicon-ok text-success"></i>
|
||||
@ -4380,7 +4380,7 @@
|
||||
|
||||
|
||||
<div>示例:</div>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code><span class="token operator">/</span>log<span class="token operator">/</span>list</code></pre>
|
||||
<pre class="ydoc-example" data-foldnumber=10><code class="js-code"><span class="token operator">/</span>log<span class="token operator">/</span>list</code></pre>
|
||||
|
||||
|
||||
</div>
|
||||
@ -4435,8 +4435,8 @@
|
||||
var $this = $(this);
|
||||
$this.removeClass('extend').addClass('fold');
|
||||
$this.html('折叠代码');
|
||||
$this.prev().height('auto');
|
||||
$this.prev().parent().height('auto');
|
||||
$this.parent().children('.js-code').height('auto');
|
||||
$this.parent().height('auto');
|
||||
});
|
||||
$('.ydoc-example').delegate('.fold', 'click', function() {
|
||||
var $this = $(this);
|
||||
@ -4444,7 +4444,7 @@
|
||||
EXAMPLE_MAX_HEIGHT = lineHeight * (foldnumber || 6);
|
||||
$this.removeClass('fold').addClass('extend');
|
||||
$this.parent().height(EXAMPLE_MAX_HEIGHT); // pre
|
||||
$this.prev().height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.parent().children('.js-code').height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.html("展开更多……");
|
||||
});
|
||||
}
|
||||
|
@ -175,8 +175,8 @@
|
||||
var $this = $(this);
|
||||
$this.removeClass('extend').addClass('fold');
|
||||
$this.html('折叠代码');
|
||||
$this.prev().height('auto');
|
||||
$this.prev().parent().height('auto');
|
||||
$this.parent().children('.js-code').height('auto');
|
||||
$this.parent().height('auto');
|
||||
});
|
||||
$('.ydoc-example').delegate('.fold', 'click', function() {
|
||||
var $this = $(this);
|
||||
@ -184,7 +184,7 @@
|
||||
EXAMPLE_MAX_HEIGHT = lineHeight * (foldnumber || 6);
|
||||
$this.removeClass('fold').addClass('extend');
|
||||
$this.parent().height(EXAMPLE_MAX_HEIGHT); // pre
|
||||
$this.prev().height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.parent().children('.js-code').height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.html("展开更多……");
|
||||
});
|
||||
}
|
||||
|
@ -68,23 +68,23 @@
|
||||
<div class="ydoc-container-content " id="readme">
|
||||
|
||||
<article class="markdown-body">
|
||||
<h2 class="subject" id="快速开始">快速开始 <a class="hashlink" href="#快速开始">#</a></h2><h3 class="subject" id="1 接口管理架构">1 接口管理架构 <a class="hashlink" href="#1 接口管理架构">#</a></h3><p>平台以<strong>项目分组</strong> -> <strong>项目</strong> -> <strong>接口</strong>的划分进行接口组织管理。</p>
|
||||
<h2 class="subject" id="快速开始">快速开始 <a class="hashlink" href="#快速开始">#</a></h2><h3 class="subject" id="1_接口管理架构">1 接口管理架构 <a class="hashlink" href="#1_接口管理架构">#</a></h3><p>平台以<strong>项目分组</strong> -> <strong>项目</strong> -> <strong>接口</strong>的划分进行接口组织管理。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-305ba49a60ee1ff5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<h4 class="subject" id="1.1 项目分组">1.1 项目分组 <a class="hashlink" href="#1.1 项目分组">#</a></h4><p>登录之后进到项目首页,左边侧边栏显示的即分组列表。</p>
|
||||
<h4 class="subject" id="1.1_项目分组">1.1 项目分组 <a class="hashlink" href="#1.1_项目分组">#</a></h4><p>登录之后进到项目首页,左边侧边栏显示的即分组列表。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-d90ca4b3242fa760.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "200" style="margin-left:170px;display:block;" alt="图片名称" align=center /></p>
|
||||
<p>管理员有权限添加或删除分组。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-a0d4d9a98003896a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "500" style="margin-left:170px;display:block;" alt="图片名称" align=center /></p>
|
||||
<blockquote>
|
||||
<p>分组名称具有唯一性</p>
|
||||
</blockquote>
|
||||
<h4 class="subject" id="1.2 项目">1.2 项目 <a class="hashlink" href="#1.2 项目">#</a></h4><p>选中不同的分组,右边会显示该分组下的项目列表。</p>
|
||||
<h4 class="subject" id="1.2_项目">1.2 项目 <a class="hashlink" href="#1.2_项目">#</a></h4><p>选中不同的分组,右边会显示该分组下的项目列表。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-137bcae58b84715e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<p>创建项目需要填写项目名称,项目线上域名(添加完成后可配置项目其他环境域名),项目接口基本路径(接口路径前面相同的部分)以及项目描述。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-360a50ddb746f73d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<blockquote>
|
||||
<p>项目『线上域名 + 基本路径』具有唯一性</p>
|
||||
</blockquote>
|
||||
<h4 class="subject" id="1.3 接口">1.3 接口 <a class="hashlink" href="#1.3 接口">#</a></h4><p>点击项目名称,进入该项目接口列表。</p>
|
||||
<h4 class="subject" id="1.3_接口">1.3 接口 <a class="hashlink" href="#1.3_接口">#</a></h4><p>点击项目名称,进入该项目接口列表。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-e858005f714f4889.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<p>点击编辑,进入接口详情页(之后接口详情页和编辑也会分开),可以编辑接口或者请求测试真实接口。</p>
|
||||
<p><img src="http://upload-images.jianshu.io/upload_images/842107-78c0ea839619d068.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
@ -134,8 +134,8 @@
|
||||
var $this = $(this);
|
||||
$this.removeClass('extend').addClass('fold');
|
||||
$this.html('折叠代码');
|
||||
$this.prev().height('auto');
|
||||
$this.prev().parent().height('auto');
|
||||
$this.parent().children('.js-code').height('auto');
|
||||
$this.parent().height('auto');
|
||||
});
|
||||
$('.ydoc-example').delegate('.fold', 'click', function() {
|
||||
var $this = $(this);
|
||||
@ -143,7 +143,7 @@
|
||||
EXAMPLE_MAX_HEIGHT = lineHeight * (foldnumber || 6);
|
||||
$this.removeClass('fold').addClass('extend');
|
||||
$this.parent().height(EXAMPLE_MAX_HEIGHT); // pre
|
||||
$this.prev().height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.parent().children('.js-code').height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.html("展开更多……");
|
||||
});
|
||||
}
|
||||
|
@ -70,7 +70,7 @@
|
||||
<article class="markdown-body">
|
||||
<h2 class="subject" id="Mock功能">Mock功能 <a class="hashlink" href="#Mock功能">#</a></h2> <p style='text-indent:2em;line-height:1.8em'>yapi的Mock功能可以根据用户的输入接口信息如协议、URL、接口名、请求头、请求参数、mock规则(<a href="#mock">点击到Mock规则</a>)生成Mock接口,这些接口会自动生成模拟数据,支持复杂的生成逻辑,创建者可以自由构造需要的数据。而且与常见的Mock方式如将Mock写在代码里和JS拦截等相比yapi的Mock在使用场景和效率和复杂度上是相差甚远的,正是由于yapi的Mock是一个第三方平台那么在 团队开发时任何人都可以权限许可下创建、修改接口信息等操作,这对于团队开发是很有好处的。</p>
|
||||
|
||||
<h3 class="subject" id="1 Mock步骤">1 Mock步骤 <a class="hashlink" href="#1 Mock步骤">#</a></h3><h4 class="subject" id="1.1 创建接口">1.1 创建接口 <a class="hashlink" href="#1.1 创建接口">#</a></h4><p>通过点击页面上的"+添加接口"</p>
|
||||
<h3 class="subject" id="1_Mock步骤">1 Mock步骤 <a class="hashlink" href="#1_Mock步骤">#</a></h3><h4 class="subject" id="1.1_创建接口">1.1 创建接口 <a class="hashlink" href="#1.1_创建接口">#</a></h4><p>通过点击页面上的"+添加接口"</p>
|
||||
<p><img src="http://note.youdao.com/yws/api/personal/file/WEB613bd4f29db038f2b41c03dcfceda2b6?method=download&shareKey=29bfc2b855f6f26ce0079baf567e54cc" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<p> 输入协议、URL、接口名、请求头、请求参数、Mock规则(<a href="#mock">点击到Mock规则</a>)等信息。</p>
|
||||
<p><img src="http://note.youdao.com/yws/api/personal/file/WEB680a37ba304768804b23cf2cf36ed40d?method=download&shareKey=0d750695dce3a4c7abf697fa58d24c57" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
@ -84,14 +84,14 @@
|
||||
<p>取到上面的链接在浏览器中请求就可以得到如下结果。</p>
|
||||
<p><img src="http://note.youdao.com/yws/api/personal/file/WEB1d1f7dc7b83a8cd6f576953cf45e9719?method=download&shareKey=99b4af9baac527b969543dd0a909d2a1" width = "800" style="margin:0px auto;display:block;" alt="图片名称" align=center /></p>
|
||||
<p><span id = "mock"></span></p>
|
||||
<h3 class="subject" id="2.1 Mock语法规范">2.1 Mock语法规范 <a class="hashlink" href="#2.1 Mock语法规范">#</a></h3><blockquote>
|
||||
<h3 class="subject" id="2.1_Mock语法规范">2.1 Mock语法规范 <a class="hashlink" href="#2.1_Mock语法规范">#</a></h3><blockquote>
|
||||
<p>了解更多Mock详情:<a href="https://github.com/nuysoft/Mock/wiki/Syntax-Specification">Mock.js 官方文档</a></p>
|
||||
</blockquote>
|
||||
<p>Mock.js 的语法规范包括两部分:</p>
|
||||
<p><a href="#DTD">1. 数据模板定义规范(Data Template Definition,DTD)</a></p>
|
||||
<p><a href="#DPD">2. 数据占位符定义规范(Data Placeholder Definition,DPD)</a></p>
|
||||
<p><span id = "DTD"></span></p>
|
||||
<h3 class="subject" id="数据模板定义规范(Data Template Definition,DTD)">数据模板定义规范(Data Template Definition,DTD) <a class="hashlink" href="#数据模板定义规范(Data Template Definition,DTD)">#</a></h3><p>数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值:</p>
|
||||
<h3 class="subject" id="数据模板定义规范(Data_Template_Definition,DTD)">数据模板定义规范(Data Template Definition,DTD) <a class="hashlink" href="#数据模板定义规范(Data_Template_Definition,DTD)">#</a></h3><p>数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值:</p>
|
||||
<pre><code>// 属性名 name (与生成规则之间用 "|<span class="token string">" 隔开)
|
||||
// 生成规则 rule(生成规则有7种详见下面的生成规则)
|
||||
// 属性值 value(可以含有 "</span>@占位符" 同时也指定了最终值的初始值和类型)
|
||||
@ -107,14 +107,14 @@
|
||||
'name|count.dcount'<span class="token operator">:</span> value
|
||||
'name|+step'<span class="token operator">:</span> value
|
||||
</code></pre><p>下面提供了6种生成规则以及示例包括 String、Number、Boolean、Object、Array:</p>
|
||||
<h4 class="subject" id="1. 属性值是字符串 String">1. 属性值是字符串 String <a class="hashlink" href="#1. 属性值是字符串 String">#</a></h4><pre><code><span class="token number">1</span>. 'name|min-max'<span class="token operator">:</span> string
|
||||
<h4 class="subject" id="1._属性值是字符串_String">1. 属性值是字符串 String <a class="hashlink" href="#1._属性值是字符串_String">#</a></h4><pre><code><span class="token number">1</span>. 'name|min-max'<span class="token operator">:</span> string
|
||||
|
||||
通过重复 string 生成一个字符串,重复次数大于等于 min,小于等于 max。
|
||||
|
||||
<span class="token number">2</span>. 'name|count'<span class="token operator">:</span> string
|
||||
|
||||
通过重复 string 生成一个字符串,重复次数等于 count。
|
||||
</code></pre><h4 class="subject" id="2. 属性值是数字 Number">2. 属性值是数字 Number <a class="hashlink" href="#2. 属性值是数字 Number">#</a></h4><pre><code><span class="token number">1</span>. 'name|+<span class="token number">1</span>'<span class="token operator">:</span> number
|
||||
</code></pre><h4 class="subject" id="2._属性值是数字_Number">2. 属性值是数字 Number <a class="hashlink" href="#2._属性值是数字_Number">#</a></h4><pre><code><span class="token number">1</span>. 'name|+<span class="token number">1</span>'<span class="token operator">:</span> number
|
||||
|
||||
属性值自动加 <span class="token number">1</span>,初始值为 number。
|
||||
|
||||
@ -140,21 +140,21 @@ Mock.mock(<span class="token punctuation">{</span>
|
||||
<span class="token property">"number3"</span><span class="token operator">:</span> <span class="token number">123.777</span><span class="token punctuation">,</span>
|
||||
<span class="token property">"number4"</span><span class="token operator">:</span> <span class="token number">123.1231091814</span>
|
||||
<span class="token punctuation">}</span>
|
||||
</code></pre><h4 class="subject" id="3. 属性值是布尔型 Boolean">3. 属性值是布尔型 Boolean <a class="hashlink" href="#3. 属性值是布尔型 Boolean">#</a></h4><pre><code><span class="token number">1</span>. 'name|<span class="token number">1</span>'<span class="token operator">:</span> boolean
|
||||
</code></pre><h4 class="subject" id="3._属性值是布尔型_Boolean">3. 属性值是布尔型 Boolean <a class="hashlink" href="#3._属性值是布尔型_Boolean">#</a></h4><pre><code><span class="token number">1</span>. 'name|<span class="token number">1</span>'<span class="token operator">:</span> boolean
|
||||
|
||||
随机生成一个布尔值,值为 <span class="token boolean">true</span> 的概率是 <span class="token number">1</span>/<span class="token number">2</span>,值为 <span class="token boolean">false</span> 的概率同样是 <span class="token number">1</span>/<span class="token number">2</span>。
|
||||
|
||||
<span class="token number">2</span>. 'name|min-max'<span class="token operator">:</span> value
|
||||
|
||||
随机生成一个布尔值,值为 value 的概率是 min / (min + max<span class="token punctuation">)</span>,值为 !value 的概率是 max / (min + max<span class="token punctuation">)</span>。
|
||||
</code></pre><h4 class="subject" id="4. 属性值是对象 Object">4. 属性值是对象 Object <a class="hashlink" href="#4. 属性值是对象 Object">#</a></h4><pre><code><span class="token number">1</span>. 'name|count'<span class="token operator">:</span> object
|
||||
</code></pre><h4 class="subject" id="4._属性值是对象_Object">4. 属性值是对象 Object <a class="hashlink" href="#4._属性值是对象_Object">#</a></h4><pre><code><span class="token number">1</span>. 'name|count'<span class="token operator">:</span> object
|
||||
|
||||
从属性值 object 中随机选取 count 个属性。
|
||||
|
||||
<span class="token number">2</span>. 'name|min-max'<span class="token operator">:</span> object
|
||||
|
||||
从属性值 object 中随机选取 min 到 max 个属性。
|
||||
</code></pre><h4 class="subject" id="5. 属性值是数组 Array">5. 属性值是数组 Array <a class="hashlink" href="#5. 属性值是数组 Array">#</a></h4><pre><code><span class="token number">1</span>. 'name|<span class="token number">1</span>'<span class="token operator">:</span> array
|
||||
</code></pre><h4 class="subject" id="5._属性值是数组_Array">5. 属性值是数组 Array <a class="hashlink" href="#5._属性值是数组_Array">#</a></h4><pre><code><span class="token number">1</span>. 'name|<span class="token number">1</span>'<span class="token operator">:</span> array
|
||||
|
||||
从属性值 array 中随机选取 <span class="token number">1</span> 个元素,作为最终值。
|
||||
|
||||
@ -170,7 +170,7 @@ Mock.mock(<span class="token punctuation">{</span>
|
||||
|
||||
通过重复属性值 array 生成一个新数组,重复次数为 count。
|
||||
</code></pre><p><span id = "DPD"></span></p>
|
||||
<h3 class="subject" id="数据占位符定义规范(Data Placeholder Definition,DPD)">数据占位符定义规范(Data Placeholder Definition,DPD) <a class="hashlink" href="#数据占位符定义规范(Data Placeholder Definition,DPD)">#</a></h3><pre><code>占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。
|
||||
<h3 class="subject" id="数据占位符定义规范(Data_Placeholder_Definition,DPD)">数据占位符定义规范(Data Placeholder Definition,DPD) <a class="hashlink" href="#数据占位符定义规范(Data_Placeholder_Definition,DPD)">#</a></h3><pre><code>占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。
|
||||
|
||||
占位符 的格式为:
|
||||
|
||||
@ -240,8 +240,8 @@ name<span class="token operator">:</span> <span class="token punctuation">{</spa
|
||||
var $this = $(this);
|
||||
$this.removeClass('extend').addClass('fold');
|
||||
$this.html('折叠代码');
|
||||
$this.prev().height('auto');
|
||||
$this.prev().parent().height('auto');
|
||||
$this.parent().children('.js-code').height('auto');
|
||||
$this.parent().height('auto');
|
||||
});
|
||||
$('.ydoc-example').delegate('.fold', 'click', function() {
|
||||
var $this = $(this);
|
||||
@ -249,7 +249,7 @@ name<span class="token operator">:</span> <span class="token punctuation">{</spa
|
||||
EXAMPLE_MAX_HEIGHT = lineHeight * (foldnumber || 6);
|
||||
$this.removeClass('fold').addClass('extend');
|
||||
$this.parent().height(EXAMPLE_MAX_HEIGHT); // pre
|
||||
$this.prev().height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.parent().children('.js-code').height(EXAMPLE_MAX_HEIGHT); // code
|
||||
$this.html("展开更多……");
|
||||
});
|
||||
}
|
||||
|
@ -129,7 +129,8 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
$('.markdown-body pre').map(function(i, item) {
|
||||
$(item).addClass('ydoc-example');
|
||||
$(item).addClass('ydoc-example').append('<div class="ui-copy js-copy" data-clipboard-action="copy" data-clipboard-target=".js-code-' + i + '" data-copy-number="' + i + '">copy</div><div class="copy-tip copy-tip-' + i + '">已复制</div>');
|
||||
$(item).children('code').addClass('js-code-'+i);
|
||||
});
|
||||
|
||||
var winHeight = $(window).height() - 44,
|
||||
@ -213,4 +214,17 @@ $(document).ready(function() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 代码复制功能
|
||||
var clipboard = new Clipboard('.js-copy');
|
||||
|
||||
clipboard.on('success', function(e) {
|
||||
var copyNumber = $(e.trigger).attr('data-copy-number');
|
||||
$('.copy-tip-'+copyNumber).show();
|
||||
setTimeout(function() {
|
||||
$('.copy-tip-'+copyNumber).hide();
|
||||
}, 1000);
|
||||
e.clearSelection();
|
||||
});
|
||||
|
||||
});
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -106,6 +106,9 @@ class baseController {
|
||||
return this.$user.role;
|
||||
}
|
||||
|
||||
getUsername() {
|
||||
return this.$user.username;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {*} id type对应的id
|
||||
|
@ -114,7 +114,7 @@ class followController extends baseController {
|
||||
/**
|
||||
* 添加关注
|
||||
* @interface /follow/add
|
||||
* @method POST
|
||||
* @method GET
|
||||
* @category follow
|
||||
* @foldnumber 10
|
||||
* @param {Number} uid 用户id
|
||||
@ -131,7 +131,8 @@ class followController extends baseController {
|
||||
uid: 'number',
|
||||
projectid: 'number',
|
||||
projectname: 'string',
|
||||
icon: 'string'
|
||||
icon: 'string',
|
||||
color: 'string'
|
||||
});
|
||||
|
||||
if (!params.uid) {
|
||||
@ -153,17 +154,22 @@ class followController extends baseController {
|
||||
if (!params.icon) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目图标标志不能为空');
|
||||
}
|
||||
if (!params.color) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, '项目颜色不能为空');
|
||||
}
|
||||
|
||||
let data = {
|
||||
uid: params.uid,
|
||||
projectid: params.projectid,
|
||||
projectname: params.projectname,
|
||||
icon: params.icon
|
||||
icon: params.icon,
|
||||
color: params.color
|
||||
|
||||
};
|
||||
|
||||
try {
|
||||
let result = await this.Model.save(data);
|
||||
result = yapi.commons.fieldSelect(result, ['_id', 'uid', 'projectid', 'projectname', 'icon']);
|
||||
result = yapi.commons.fieldSelect(result, ['_id', 'uid', 'projectid', 'projectname', 'icon', 'color']);
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
|
14
static/doc/static/server/controllers/log.js.html
vendored
14
static/doc/static/server/controllers/log.js.html
vendored
@ -59,7 +59,7 @@ class logController extends baseController {
|
||||
* @method GET
|
||||
* @category log
|
||||
* @foldnumber 10
|
||||
* @param {Number} uid 用户id, 不能为空
|
||||
* @param {Number} typeid 动态类型id, 不能为空
|
||||
* @param {Number} [page] 分页页码
|
||||
* @param {Number} [limit] 分页大小
|
||||
* @returns {Object}
|
||||
@ -69,15 +69,17 @@ class logController extends baseController {
|
||||
async list(ctx) {
|
||||
let typeid = ctx.request.query.typeid,
|
||||
page = ctx.request.query.page || 1,
|
||||
limit = ctx.request.query.limit || 10;
|
||||
|
||||
limit = ctx.request.query.limit || 10,
|
||||
type = ctx.request.query.type;
|
||||
if (!typeid) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, 'typeid不能为空');
|
||||
}
|
||||
|
||||
if(!type) {
|
||||
return ctx.body = yapi.commons.resReturn(null, 400, 'type不能为空');
|
||||
}
|
||||
try {
|
||||
let result = await this.Model.listWithPaging(typeid, page, limit);
|
||||
let count = await this.Model.listCount(typeid);
|
||||
let result = await this.Model.listWithPaging(typeid,type, page, limit);
|
||||
let count = await this.Model.listCount(typeid,type);
|
||||
|
||||
ctx.body = yapi.commons.resReturn({
|
||||
total: Math.ceil(count / limit),
|
||||
|
@ -32,6 +32,7 @@ import interfaceModel from '../models/interface.js';
|
||||
import groupModel from '../models/group';
|
||||
import commons from '../utils/commons.js';
|
||||
import userModel from '../models/user.js';
|
||||
import logModel from '../models/log.js';
|
||||
import Mock from 'mockjs';
|
||||
const send = require('koa-send');
|
||||
|
||||
@ -41,6 +42,7 @@ class projectController extends baseController {
|
||||
super(ctx);
|
||||
this.Model = yapi.getInst(projectModel);
|
||||
this.groupModel = yapi.getInst(groupModel);
|
||||
this.logModel = yapi.getInst(logModel);
|
||||
}
|
||||
|
||||
handleBasepath(basepath) {
|
||||
@ -146,6 +148,14 @@ class projectController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await this.Model.save(data);
|
||||
let username = this.getUsername();
|
||||
await this.logModel.save({
|
||||
content: `用户${username}添加了项目${params.name}`,
|
||||
type: 'project',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.group_id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -189,6 +199,14 @@ class projectController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await this.Model.addMember(params.id, userdata);
|
||||
let username = this.getUsername();
|
||||
await this.logModel.save({
|
||||
content: `用户${username}添加了项目成员${userdata.username}`,
|
||||
type: 'project',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -226,6 +244,19 @@ class projectController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await this.Model.delMember(params.id, params.member_uid);
|
||||
let username = this.getUsername();
|
||||
let project = await this.Model.get(params.id);
|
||||
for(let i in project.members){
|
||||
if(i.uid === params.member_uid){
|
||||
await this.logModel.save({
|
||||
content: `用户${username}删除了项目${project.name}中的成员${i.username}`,
|
||||
type: 'project',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
}
|
||||
}
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -392,6 +423,21 @@ class projectController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await groupInst.changeMemberRole(params.id, params.member_uid, params.role);
|
||||
|
||||
let username = this.getUsername();
|
||||
let project = await this.Model.get(params.id);
|
||||
for(let i in project.members){
|
||||
if(i.uid === params.member_uid){
|
||||
await this.logModel.save({
|
||||
content: `用户${username}修改了项目${project.name}中成员${i.username}的角色为${params.role}`,
|
||||
type: 'project',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -483,6 +529,16 @@ class projectController extends baseController {
|
||||
if (params.env) data.env = params.env;
|
||||
|
||||
let result = await this.Model.up(id, data);
|
||||
|
||||
let username = this.getUsername();
|
||||
await this.logModel.save({
|
||||
content: `用户${username}更新了项目${params.name}`,
|
||||
type: 'project',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: id
|
||||
});
|
||||
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -550,6 +606,7 @@ class projectController extends baseController {
|
||||
* @method GET
|
||||
* @category project
|
||||
* @foldnumber 10
|
||||
* @author wenbo.dong
|
||||
* @param {String} project_id
|
||||
*/
|
||||
async download(ctx) {
|
||||
|
Loading…
Reference in New Issue
Block a user