mirror of
https://github.com/YMFE/yapi.git
synced 2024-12-09 05:00:30 +08:00
Merge branch 'dev-1.3.0' of gitlab.corp.qunar.com:mfe/yapi into dev-1.3.0
This commit is contained in:
commit
1b9c4ccf73
@ -4,8 +4,11 @@
|
||||
|
||||
1. Api 路径兼容 postman {varible}
|
||||
2. View Response Height 问题
|
||||
|
||||
#### Feature
|
||||
1. 新增克隆测试集功能
|
||||
2. 高级 Mock 期望支持 mockjs
|
||||
3. pathname 允许只有一个 /
|
||||
4. 高级 Mock 期望支持 mockjs
|
||||
|
||||
### v1.2.8
|
||||
|
||||
|
@ -45,7 +45,9 @@ YApi 是<strong>高效</strong>、<strong>易用</strong>、<strong>功能强大
|
||||
密码: ymfe.org
|
||||
```
|
||||
### YApi 资源
|
||||
* [yapi docker](https://github.com/branchzero/yapi-docker) By branchzero
|
||||
* [yapi sso 登录插件](https://github.com/YMFE/yapi-plugin-qsso)
|
||||
* [yapi docker 部署](https://github.com/branchzero/yapi-docker) By branchzero
|
||||
|
||||
|
||||
|
||||
### YApi 的一些客户
|
||||
|
@ -5,7 +5,7 @@ import PropTypes from 'prop-types'
|
||||
/**
|
||||
* @author suxiaoxin
|
||||
* @demo
|
||||
* <EasyDragSort data={this.state.list} onChange={this.handleChange} >
|
||||
* <EasyDragSort data={()=>this.state.list} onChange={this.handleChange} >
|
||||
* {list}
|
||||
* </EasyDragSot>
|
||||
*/
|
||||
@ -13,16 +13,19 @@ let curDragIndex = null;
|
||||
|
||||
EasyDragSort.propTypes = {
|
||||
children: PropTypes.array,
|
||||
data: PropTypes.array,
|
||||
onChange: PropTypes.func,
|
||||
onDragEnd: PropTypes.func
|
||||
onDragEnd: PropTypes.func,
|
||||
data: PropTypes.func
|
||||
}
|
||||
|
||||
export default function EasyDragSort(props){
|
||||
let container = props.children;
|
||||
function onChange(from, to){
|
||||
const onChange = (from, to)=>{
|
||||
if(from === to ) return ;
|
||||
let curValue = props.data;
|
||||
let curValue;
|
||||
|
||||
curValue = props.data();
|
||||
|
||||
let newValue = arrMove(curValue, from, to);
|
||||
if(typeof props.onChange === 'function'){
|
||||
return props.onChange(newValue, from ,to);
|
||||
|
@ -1,430 +1,475 @@
|
||||
import React, { PureComponent as Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router'
|
||||
import PropTypes from 'prop-types'
|
||||
import { fetchInterfaceColList, fetchInterfaceCaseList, setColData, fetchCaseList } from '../../../../reducer/modules/interfaceCol'
|
||||
import { fetchInterfaceList } from '../../../../reducer/modules/interface.js';
|
||||
import axios from 'axios';
|
||||
// import { Input, Icon, Button, Modal, message, Tooltip, Tree, Dropdown, Menu, Form } from 'antd';
|
||||
import ImportInterface from './ImportInterface'
|
||||
import { Input, Icon, Button, Modal, message, Tooltip, Tree, Form } from 'antd';
|
||||
|
||||
const TreeNode = Tree.TreeNode;
|
||||
const FormItem = Form.Item;
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
import './InterfaceColMenu.scss'
|
||||
|
||||
const ColModalForm = Form.create()((props) => {
|
||||
const { visible, onCancel, onCreate, form, title } = props;
|
||||
const { getFieldDecorator } = form;
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
title={title}
|
||||
onCancel={onCancel}
|
||||
onOk={onCreate}
|
||||
>
|
||||
<Form layout="vertical">
|
||||
<FormItem label="集合名">
|
||||
{getFieldDecorator('colName', {
|
||||
rules: [{ required: true, message: '请输入集合命名!' }]
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem label="简介">
|
||||
{getFieldDecorator('colDesc')(<Input type="textarea" />)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
});
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
interfaceColList: state.interfaceCol.interfaceColList,
|
||||
currColId: state.interfaceCol.currColId,
|
||||
currCaseId: state.interfaceCol.currCaseId,
|
||||
isShowCol: state.interfaceCol.isShowCol,
|
||||
isRander: state.interfaceCol.isRander,
|
||||
list: state.inter.list
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceColList,
|
||||
fetchInterfaceCaseList,
|
||||
fetchInterfaceList,
|
||||
fetchCaseList,
|
||||
setColData
|
||||
}
|
||||
)
|
||||
@withRouter
|
||||
export default class InterfaceColMenu extends Component {
|
||||
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
interfaceColList: PropTypes.array,
|
||||
fetchInterfaceColList: PropTypes.func,
|
||||
fetchInterfaceCaseList: PropTypes.func,
|
||||
fetchInterfaceList: PropTypes.func,
|
||||
fetchCaseList: PropTypes.func,
|
||||
setColData: PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
currColId: PropTypes.number,
|
||||
currCaseId: PropTypes.number,
|
||||
isShowCol: PropTypes.bool,
|
||||
isRander: PropTypes.bool,
|
||||
list: PropTypes.array
|
||||
}
|
||||
|
||||
state = {
|
||||
expandedKeys: [],
|
||||
colModalType: '',
|
||||
colModalVisible: false,
|
||||
editColId: 0,
|
||||
filterValue: '',
|
||||
importInterVisible: false,
|
||||
importInterIds: [],
|
||||
importColId: 0
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
const { isShowCol, currColId, currCaseId } = this.props;
|
||||
const action = isShowCol ? 'col' : 'case';
|
||||
const actionId = isShowCol ? currColId : currCaseId;
|
||||
this.setState({ expandedKeys: [action + '_' + actionId] })
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
const { currColId } = nextProps;
|
||||
let expandedKeys = this.state.expandedKeys;
|
||||
if (expandedKeys.indexOf('col_' + currColId) === -1) {
|
||||
expandedKeys = expandedKeys.concat(['col_' + currColId])
|
||||
}
|
||||
this.setState({ expandedKeys })
|
||||
}
|
||||
|
||||
addorEditCol = async () => {
|
||||
const { colName: name, colDesc: desc } = this.form.getFieldsValue();
|
||||
const { colModalType, editColId: col_id } = this.state;
|
||||
const project_id = this.props.match.params.id;
|
||||
let res = {};
|
||||
if (colModalType === 'add') {
|
||||
res = await axios.post('/api/col/add_col', { name, desc, project_id })
|
||||
} else if (colModalType === 'edit') {
|
||||
res = await axios.post('/api/col/up_col', { name, desc, col_id })
|
||||
}
|
||||
if (!res.data.errcode) {
|
||||
this.setState({
|
||||
colModalVisible: false
|
||||
});
|
||||
message.success(colModalType === 'edit' ? '修改集合成功' : '添加集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
onExpand = (keys) => {
|
||||
this.setState({ expandedKeys: keys })
|
||||
}
|
||||
|
||||
onSelect = (keys) => {
|
||||
if (keys.length) {
|
||||
const type = keys[0].split('_')[0];
|
||||
const id = keys[0].split('_')[1];
|
||||
const project_id = this.props.match.params.id
|
||||
if (type === 'col') {
|
||||
this.props.setColData({
|
||||
isShowCol: true,
|
||||
isRander: false,
|
||||
currColId: +id
|
||||
})
|
||||
this.props.history.push('/project/' + project_id + '/interface/col/' + id)
|
||||
} else {
|
||||
this.props.setColData({
|
||||
isShowCol: false,
|
||||
isRander: false,
|
||||
currCaseId: +id
|
||||
})
|
||||
this.props.history.push('/project/' + project_id + '/interface/case/' + id)
|
||||
}
|
||||
}
|
||||
}
|
||||
showDelColConfirm = (colId) => {
|
||||
let that = this;
|
||||
const params = this.props.match.params;
|
||||
confirm({
|
||||
title: '您确认删除此测试集合',
|
||||
content: '温馨提示:该操作会删除该集合下所有测试用例,用例删除后无法恢复',
|
||||
async onOk() {
|
||||
const res = await axios.get('/api/col/del_col?col_id=' + colId)
|
||||
if (!res.data.errcode) {
|
||||
message.success('删除集合成功');
|
||||
const result = await that.props.fetchInterfaceColList(that.props.match.params.id);
|
||||
const nextColId = result.payload.data.data[0]._id;
|
||||
|
||||
that.props.history.push('/project/' + params.id + '/interface/col/' + nextColId);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showNoDelColConfirm = () => {
|
||||
confirm({
|
||||
title: '此测试集合为最后一个集合',
|
||||
content: '温馨提示:建议不要删除'
|
||||
});
|
||||
}
|
||||
showDelCaseConfirm = (caseId) => {
|
||||
let that = this;
|
||||
const params = this.props.match.params;
|
||||
confirm({
|
||||
title: '您确认删除此测试用例',
|
||||
content: '温馨提示:用例删除后无法恢复',
|
||||
async onOk() {
|
||||
const res = await axios.get('/api/col/del_case?caseid=' + caseId)
|
||||
if (!res.data.errcode) {
|
||||
message.success('删除用例成功');
|
||||
// 如果删除当前选中 case,切换路由到集合
|
||||
if (+caseId === +that.props.currCaseId) {
|
||||
that.props.history.push('/project/' + params.id + '/interface/col/')
|
||||
} else {
|
||||
that.props.fetchInterfaceColList(that.props.match.params.id);
|
||||
that.props.setColData({ currColId: +that.props.currColId, isRander: true })
|
||||
}
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
showColModal = (type, col) => {
|
||||
const editCol = type === 'edit' ? { colName: col.name, colDesc: col.desc } : { colName: '', colDesc: '' };
|
||||
this.setState({
|
||||
colModalVisible: true,
|
||||
colModalType: type || 'add',
|
||||
editColId: col && col._id
|
||||
})
|
||||
this.form.setFieldsValue(editCol)
|
||||
}
|
||||
saveFormRef = (form) => {
|
||||
this.form = form;
|
||||
}
|
||||
|
||||
selectInterface = (importInterIds) => {
|
||||
// console.log(importInterIds)
|
||||
this.setState({ importInterIds })
|
||||
}
|
||||
|
||||
showImportInterfaceModal = async (colId) => {
|
||||
const projectId = this.props.match.params.id;
|
||||
await this.props.fetchInterfaceList(projectId)
|
||||
this.setState({ importInterVisible: true, importColId: colId })
|
||||
}
|
||||
handleImportOk = async () => {
|
||||
const project_id = this.props.match.params.id;
|
||||
const { importColId, importInterIds } = this.state;
|
||||
const res = await axios.post('/api/col/add_case_list', {
|
||||
interface_list: importInterIds,
|
||||
col_id: importColId,
|
||||
project_id
|
||||
})
|
||||
if (!res.data.errcode) {
|
||||
this.setState({ importInterVisible: false })
|
||||
message.success('导入集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
this.props.setColData({ currColId: +this.props.currColId, isRander: true })
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
handleImportCancel = () => {
|
||||
this.setState({ importInterVisible: false })
|
||||
}
|
||||
|
||||
filterCol = (e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({ filterValue: value })
|
||||
}
|
||||
|
||||
onDrop = async (e) => {
|
||||
console.log('e', e);
|
||||
const projectId = this.props.match.params.id;
|
||||
const dropColIndex = e.node.props.pos.split('-')[1];
|
||||
|
||||
const dropColId = this.props.interfaceColList[dropColIndex]._id;
|
||||
const id = e.dragNode.props.eventKey;
|
||||
const dragColIndex = e.dragNode.props.pos.split('-')[1];
|
||||
|
||||
const dragColId = this.props.interfaceColList[dragColIndex]._id;
|
||||
|
||||
if (id.indexOf('col') === -1 && dropColId !== dragColId) {
|
||||
// if (dropColId !== dragColId) {
|
||||
//
|
||||
// }
|
||||
// else {
|
||||
// let caseList = this.props.interfaceColList[dropColIndex].caseList;
|
||||
// const dropIndex = e.node.props.pos.split('-')[2];
|
||||
// const dragIndex = e.dragNode.props.pos.split('-')[2];
|
||||
// // caseList[dropIndex] = [caseList[dragIndex], caseList[dragIndex] = caseList[dropIndex]][0]
|
||||
// let newArr = [].concat(caseList);
|
||||
// newArr[dragIndex] = caseList[dropIndex];
|
||||
// newArr[dropIndex] = caseList[dragIndex];
|
||||
// let changes = [];
|
||||
// newArr.forEach((item, index) => {
|
||||
// changes.push({
|
||||
// id: item._id,
|
||||
// index: index
|
||||
// })
|
||||
// })
|
||||
// axios.post('/api/col/up_col_index', changes).then()
|
||||
// }
|
||||
await axios.post('/api/col/up_case', { id: id.split('_')[1], col_id: dropColId });
|
||||
this.props.fetchInterfaceColList(projectId);
|
||||
this.props.setColData({ currColId: +this.props.currColId, isShowCol: true, isRander: true })
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currColId, currCaseId, isShowCol } = this.props;
|
||||
const { colModalType, colModalVisible, filterValue, importInterVisible } = this.state;
|
||||
|
||||
// const menu = (col) => {
|
||||
// return (
|
||||
// <Menu>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => this.showColModal('edit', col)}>修改集合</span>
|
||||
// </Menu.Item>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => {
|
||||
// this.showDelColConfirm(col._id)
|
||||
// }}>删除集合</span>
|
||||
// </Menu.Item>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => this.showImportInterface(col._id)}>导入接口</span>
|
||||
// </Menu.Item>
|
||||
// </Menu>
|
||||
// )
|
||||
// };
|
||||
|
||||
let isFilterCat = false;
|
||||
// console.log();
|
||||
// let caseList = this.props.interfaceColList.caseList;
|
||||
// if(caseList&&caseList.length>1){
|
||||
// caseList = caseList.sort((a,b)=>{
|
||||
// return a.index-b.index;
|
||||
// });
|
||||
// this.props.interfaceColList.caseList = caseList;
|
||||
// }
|
||||
const list = this.props.interfaceColList.filter(col => {
|
||||
if (col.name.indexOf(filterValue) !== -1) {
|
||||
isFilterCat = true;
|
||||
return true;
|
||||
}
|
||||
isFilterCat = false;
|
||||
|
||||
let caseList = col.caseList.filter(item => {
|
||||
return item.casename.indexOf(filterValue) !== -1
|
||||
})
|
||||
|
||||
return caseList.length > 0;
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="interface-filter">
|
||||
<Input placeholder="搜索测试集合" onChange={this.filterCol} />
|
||||
<Tooltip placement="bottom" title="添加集合">
|
||||
<Button type="primary" style={{ marginLeft: "16px" }} onClick={() => this.showColModal('add')} className="btn-filter" >添加集合</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Tree
|
||||
className="col-list-tree"
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
selectedKeys={[isShowCol ? 'col_' + currColId : 'case_' + currCaseId]}
|
||||
onSelect={this.onSelect}
|
||||
autoExpandParent
|
||||
onExpand={this.onExpand}
|
||||
ondragstart={() => { return false }}
|
||||
>
|
||||
{
|
||||
list.map((col) => (
|
||||
<TreeNode
|
||||
key={'col_' + col._id}
|
||||
title={
|
||||
<div className="menu-title">
|
||||
<span><Icon type="folder-open" style={{ marginRight: 5 }} /><span>{col.name}</span></span>
|
||||
<div className="btns">
|
||||
<Tooltip title="删除集合">
|
||||
<Icon type='delete' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); list.length > 1 ? this.showDelColConfirm(col._id) : this.showNoDelColConfirm() }} />
|
||||
</Tooltip>
|
||||
<Tooltip title="编辑集合">
|
||||
<Icon type='edit' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); this.showColModal('edit', col) }} />
|
||||
</Tooltip>
|
||||
<Tooltip title="导入接口">
|
||||
<Icon type='plus' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); this.showImportInterfaceModal(col._id) }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/*<Dropdown overlay={menu(col)} trigger={['click']} onClick={e => e.stopPropagation()}>
|
||||
<Icon className="opts-icon" type='ellipsis'/>
|
||||
</Dropdown>*/}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{
|
||||
col.caseList && col.caseList.filter((item) => {
|
||||
if (isFilterCat) {
|
||||
return true;
|
||||
}
|
||||
return item.casename.indexOf(filterValue) !== -1
|
||||
}).sort((a, b) => {
|
||||
return a.index - b.index;
|
||||
}).map((interfaceCase) => (
|
||||
<TreeNode
|
||||
style={{ width: '100%' }}
|
||||
key={'case_' + interfaceCase._id}
|
||||
title={
|
||||
<div className="menu-title" title={interfaceCase.casename}>
|
||||
<span className="casename">{interfaceCase.casename}</span>
|
||||
<Tooltip title="删除用例">
|
||||
<Icon type='delete' className="case-delete-icon" onClick={(e) => { e.stopPropagation(); this.showDelCaseConfirm(interfaceCase._id) }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
></TreeNode>
|
||||
))
|
||||
}
|
||||
</TreeNode>
|
||||
))
|
||||
}
|
||||
</Tree>
|
||||
<ColModalForm
|
||||
ref={this.saveFormRef}
|
||||
type={colModalType}
|
||||
visible={colModalVisible}
|
||||
onCancel={() => { this.setState({ colModalVisible: false }) }}
|
||||
onCreate={this.addorEditCol}
|
||||
></ColModalForm>
|
||||
<Modal
|
||||
title="导入接口到集合"
|
||||
visible={importInterVisible}
|
||||
onOk={this.handleImportOk}
|
||||
onCancel={this.handleImportCancel}
|
||||
width={800}
|
||||
>
|
||||
<ImportInterface onChange={this.selectInterface} list={this.props.list} />
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
import React, { PureComponent as Component } from 'react'
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router'
|
||||
import PropTypes from 'prop-types'
|
||||
import { fetchInterfaceColList, fetchInterfaceCaseList, setColData, fetchCaseList } from '../../../../reducer/modules/interfaceCol'
|
||||
import { fetchInterfaceList } from '../../../../reducer/modules/interface.js';
|
||||
import axios from 'axios';
|
||||
// import { Input, Icon, Button, Modal, message, Tooltip, Tree, Dropdown, Menu, Form } from 'antd';
|
||||
import ImportInterface from './ImportInterface'
|
||||
import { Input, Icon, Button, Modal, message, Tooltip, Tree, Form } from 'antd';
|
||||
|
||||
const TreeNode = Tree.TreeNode;
|
||||
const FormItem = Form.Item;
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
import './InterfaceColMenu.scss'
|
||||
|
||||
const ColModalForm = Form.create()((props) => {
|
||||
const { visible, onCancel, onCreate, form, title } = props;
|
||||
const { getFieldDecorator } = form;
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
title={title}
|
||||
onCancel={onCancel}
|
||||
onOk={onCreate}
|
||||
>
|
||||
<Form layout="vertical">
|
||||
<FormItem label="集合名">
|
||||
{getFieldDecorator('colName', {
|
||||
rules: [{ required: true, message: '请输入集合命名!' }]
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem label="简介">
|
||||
{getFieldDecorator('colDesc')(<Input type="textarea" />)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
});
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
interfaceColList: state.interfaceCol.interfaceColList,
|
||||
currColId: state.interfaceCol.currColId,
|
||||
currCaseId: state.interfaceCol.currCaseId,
|
||||
isShowCol: state.interfaceCol.isShowCol,
|
||||
isRander: state.interfaceCol.isRander,
|
||||
list: state.inter.list
|
||||
}
|
||||
},
|
||||
{
|
||||
fetchInterfaceColList,
|
||||
fetchInterfaceCaseList,
|
||||
fetchInterfaceList,
|
||||
fetchCaseList,
|
||||
setColData
|
||||
}
|
||||
)
|
||||
@withRouter
|
||||
export default class InterfaceColMenu extends Component {
|
||||
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
interfaceColList: PropTypes.array,
|
||||
fetchInterfaceColList: PropTypes.func,
|
||||
fetchInterfaceCaseList: PropTypes.func,
|
||||
fetchInterfaceList: PropTypes.func,
|
||||
fetchCaseList: PropTypes.func,
|
||||
setColData: PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
currColId: PropTypes.number,
|
||||
currCaseId: PropTypes.number,
|
||||
isShowCol: PropTypes.bool,
|
||||
isRander: PropTypes.bool,
|
||||
list: PropTypes.array
|
||||
}
|
||||
|
||||
state = {
|
||||
expandedKeys: [],
|
||||
colModalType: '',
|
||||
colModalVisible: false,
|
||||
editColId: 0,
|
||||
filterValue: '',
|
||||
importInterVisible: false,
|
||||
importInterIds: [],
|
||||
importColId: 0
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
const { isShowCol, currColId, currCaseId } = this.props;
|
||||
const action = isShowCol ? 'col' : 'case';
|
||||
const actionId = isShowCol ? currColId : currCaseId;
|
||||
this.setState({ expandedKeys: [action + '_' + actionId] })
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
const { currColId } = nextProps;
|
||||
let expandedKeys = this.state.expandedKeys;
|
||||
if (expandedKeys.indexOf('col_' + currColId) === -1) {
|
||||
expandedKeys = expandedKeys.concat(['col_' + currColId])
|
||||
}
|
||||
this.setState({ expandedKeys })
|
||||
}
|
||||
|
||||
addorEditCol = async () => {
|
||||
const { colName: name, colDesc: desc } = this.form.getFieldsValue();
|
||||
const { colModalType, editColId: col_id } = this.state;
|
||||
const project_id = this.props.match.params.id;
|
||||
let res = {};
|
||||
if (colModalType === 'add') {
|
||||
res = await axios.post('/api/col/add_col', { name, desc, project_id })
|
||||
} else if (colModalType === 'edit') {
|
||||
res = await axios.post('/api/col/up_col', { name, desc, col_id })
|
||||
}
|
||||
if (!res.data.errcode) {
|
||||
this.setState({
|
||||
colModalVisible: false
|
||||
});
|
||||
message.success(colModalType === 'edit' ? '修改集合成功' : '添加集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
onExpand = (keys) => {
|
||||
this.setState({ expandedKeys: keys })
|
||||
}
|
||||
|
||||
onSelect = (keys) => {
|
||||
if (keys.length) {
|
||||
const type = keys[0].split('_')[0];
|
||||
const id = keys[0].split('_')[1];
|
||||
const project_id = this.props.match.params.id
|
||||
if (type === 'col') {
|
||||
this.props.setColData({
|
||||
isShowCol: true,
|
||||
isRander: false,
|
||||
currColId: +id
|
||||
})
|
||||
this.props.history.push('/project/' + project_id + '/interface/col/' + id)
|
||||
} else {
|
||||
this.props.setColData({
|
||||
isShowCol: false,
|
||||
isRander: false,
|
||||
currCaseId: +id
|
||||
})
|
||||
this.props.history.push('/project/' + project_id + '/interface/case/' + id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showDelColConfirm = (colId) => {
|
||||
let that = this;
|
||||
const params = this.props.match.params;
|
||||
confirm({
|
||||
title: '您确认删除此测试集合',
|
||||
content: '温馨提示:该操作会删除该集合下所有测试用例,用例删除后无法恢复',
|
||||
async onOk() {
|
||||
const res = await axios.get('/api/col/del_col?col_id=' + colId)
|
||||
if (!res.data.errcode) {
|
||||
message.success('删除集合成功');
|
||||
const result = await that.props.fetchInterfaceColList(that.props.match.params.id);
|
||||
const nextColId = result.payload.data.data[0]._id;
|
||||
|
||||
that.props.history.push('/project/' + params.id + '/interface/col/' + nextColId);
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 复制测试集合
|
||||
copyInterface = async (item) => {
|
||||
if(this._copyInterfaceSign === true){
|
||||
return ;
|
||||
}
|
||||
this._copyInterfaceSign = true;
|
||||
const { desc, project_id, _id: col_id } = item;
|
||||
let { name } = item;
|
||||
name = `${name} copy`;
|
||||
|
||||
// 添加集合
|
||||
const add_col_res = await axios.post('/api/col/add_col', { name, desc, project_id });
|
||||
|
||||
if (add_col_res.data.errcode) {
|
||||
message.error(add_col_res.data.errmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
const new_col_id = add_col_res.data.data._id;
|
||||
|
||||
// 克隆集合
|
||||
const add_case_list_res = await axios.post('/api/col/clone_case_list', {
|
||||
new_col_id,
|
||||
col_id,
|
||||
project_id
|
||||
})
|
||||
this._copyInterfaceSign = false;
|
||||
|
||||
if (add_case_list_res.data.errcode) {
|
||||
message.error(add_case_list_res.data.errmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 刷新接口列表
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
this.props.setColData({ currColId: + new_col_id, isRander: true })
|
||||
message.success('克隆测试集成功')
|
||||
|
||||
}
|
||||
|
||||
showNoDelColConfirm = () => {
|
||||
confirm({
|
||||
title: '此测试集合为最后一个集合',
|
||||
content: '温馨提示:建议不要删除'
|
||||
});
|
||||
}
|
||||
showDelCaseConfirm = (caseId) => {
|
||||
let that = this;
|
||||
const params = this.props.match.params;
|
||||
confirm({
|
||||
title: '您确认删除此测试用例',
|
||||
content: '温馨提示:用例删除后无法恢复',
|
||||
async onOk() {
|
||||
const res = await axios.get('/api/col/del_case?caseid=' + caseId)
|
||||
if (!res.data.errcode) {
|
||||
message.success('删除用例成功');
|
||||
// 如果删除当前选中 case,切换路由到集合
|
||||
if (+caseId === +that.props.currCaseId) {
|
||||
that.props.history.push('/project/' + params.id + '/interface/col/')
|
||||
} else {
|
||||
that.props.fetchInterfaceColList(that.props.match.params.id);
|
||||
that.props.setColData({ currColId: +that.props.currColId, isRander: true })
|
||||
}
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
showColModal = (type, col) => {
|
||||
const editCol = type === 'edit' ? { colName: col.name, colDesc: col.desc } : { colName: '', colDesc: '' };
|
||||
this.setState({
|
||||
colModalVisible: true,
|
||||
colModalType: type || 'add',
|
||||
editColId: col && col._id
|
||||
})
|
||||
this.form.setFieldsValue(editCol)
|
||||
}
|
||||
saveFormRef = (form) => {
|
||||
this.form = form;
|
||||
}
|
||||
|
||||
selectInterface = (importInterIds) => {
|
||||
// console.log(importInterIds)
|
||||
this.setState({ importInterIds })
|
||||
}
|
||||
|
||||
showImportInterfaceModal = async (colId) => {
|
||||
const projectId = this.props.match.params.id;
|
||||
await this.props.fetchInterfaceList(projectId)
|
||||
this.setState({ importInterVisible: true, importColId: colId })
|
||||
}
|
||||
handleImportOk = async () => {
|
||||
const project_id = this.props.match.params.id;
|
||||
const { importColId, importInterIds } = this.state;
|
||||
const res = await axios.post('/api/col/add_case_list', {
|
||||
interface_list: importInterIds,
|
||||
col_id: importColId,
|
||||
project_id
|
||||
})
|
||||
if (!res.data.errcode) {
|
||||
this.setState({ importInterVisible: false })
|
||||
message.success('导入集合成功');
|
||||
await this.props.fetchInterfaceColList(project_id);
|
||||
this.props.setColData({ currColId: +this.props.currColId, isRander: true })
|
||||
} else {
|
||||
message.error(res.data.errmsg);
|
||||
}
|
||||
}
|
||||
handleImportCancel = () => {
|
||||
this.setState({ importInterVisible: false })
|
||||
}
|
||||
|
||||
filterCol = (e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({ filterValue: value })
|
||||
}
|
||||
|
||||
onDrop = async (e) => {
|
||||
const projectId = this.props.match.params.id;
|
||||
const dropColIndex = e.node.props.pos.split('-')[1];
|
||||
|
||||
const dropColId = this.props.interfaceColList[dropColIndex]._id;
|
||||
const id = e.dragNode.props.eventKey;
|
||||
const dragColIndex = e.dragNode.props.pos.split('-')[1];
|
||||
|
||||
const dragColId = this.props.interfaceColList[dragColIndex]._id;
|
||||
|
||||
if (id.indexOf('col') === -1 && dropColId !== dragColId) {
|
||||
// if (dropColId !== dragColId) {
|
||||
//
|
||||
// }
|
||||
// else {
|
||||
// let caseList = this.props.interfaceColList[dropColIndex].caseList;
|
||||
// const dropIndex = e.node.props.pos.split('-')[2];
|
||||
// const dragIndex = e.dragNode.props.pos.split('-')[2];
|
||||
// // caseList[dropIndex] = [caseList[dragIndex], caseList[dragIndex] = caseList[dropIndex]][0]
|
||||
// let newArr = [].concat(caseList);
|
||||
// newArr[dragIndex] = caseList[dropIndex];
|
||||
// newArr[dropIndex] = caseList[dragIndex];
|
||||
// let changes = [];
|
||||
// newArr.forEach((item, index) => {
|
||||
// changes.push({
|
||||
// id: item._id,
|
||||
// index: index
|
||||
// })
|
||||
// })
|
||||
// axios.post('/api/col/up_col_index', changes).then()
|
||||
// }
|
||||
await axios.post('/api/col/up_case', { id: id.split('_')[1], col_id: dropColId });
|
||||
this.props.fetchInterfaceColList(projectId);
|
||||
this.props.setColData({ currColId: +this.props.currColId, isShowCol: true, isRander: true })
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currColId, currCaseId, isShowCol } = this.props;
|
||||
const { colModalType, colModalVisible, filterValue, importInterVisible } = this.state;
|
||||
|
||||
// const menu = (col) => {
|
||||
// return (
|
||||
// <Menu>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => this.showColModal('edit', col)}>修改集合</span>
|
||||
// </Menu.Item>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => {
|
||||
// this.showDelColConfirm(col._id)
|
||||
// }}>删除集合</span>
|
||||
// </Menu.Item>
|
||||
// <Menu.Item>
|
||||
// <span onClick={() => this.showImportInterface(col._id)}>导入接口</span>
|
||||
// </Menu.Item>
|
||||
// </Menu>
|
||||
// )
|
||||
// };
|
||||
|
||||
let isFilterCat = false;
|
||||
// console.log();
|
||||
// let caseList = this.props.interfaceColList.caseList;
|
||||
// if(caseList&&caseList.length>1){
|
||||
// caseList = caseList.sort((a,b)=>{
|
||||
// return a.index-b.index;
|
||||
// });
|
||||
// this.props.interfaceColList.caseList = caseList;
|
||||
// }
|
||||
const list = this.props.interfaceColList.filter(col => {
|
||||
if (col.name.indexOf(filterValue) !== -1) {
|
||||
isFilterCat = true;
|
||||
return true;
|
||||
}
|
||||
isFilterCat = false;
|
||||
|
||||
let caseList = col.caseList.filter(item => {
|
||||
return item.casename.indexOf(filterValue) !== -1
|
||||
})
|
||||
|
||||
return caseList.length > 0;
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="interface-filter">
|
||||
<Input placeholder="搜索测试集合" onChange={this.filterCol} />
|
||||
<Tooltip placement="bottom" title="添加集合">
|
||||
<Button type="primary" style={{ marginLeft: "16px" }} onClick={() => this.showColModal('add')} className="btn-filter" >添加集合</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Tree
|
||||
className="col-list-tree"
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
selectedKeys={[isShowCol ? 'col_' + currColId : 'case_' + currCaseId]}
|
||||
onSelect={this.onSelect}
|
||||
autoExpandParent
|
||||
onExpand={this.onExpand}
|
||||
ondragstart={() => { return false }}
|
||||
>
|
||||
{
|
||||
list.map((col) => (
|
||||
<TreeNode
|
||||
key={'col_' + col._id}
|
||||
title={
|
||||
<div className="menu-title">
|
||||
<span><Icon type="folder-open" style={{ marginRight: 5 }} /><span>{col.name}</span></span>
|
||||
<div className="btns">
|
||||
|
||||
<Tooltip title="删除集合">
|
||||
<Icon type='delete' style={{display:list.length > 1 ? '': 'none' }} className="interface-delete-icon" onClick={() => { this.showDelColConfirm(col._id) }} />
|
||||
</Tooltip>
|
||||
<Tooltip title="编辑集合">
|
||||
<Icon type='edit' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); this.showColModal('edit', col) }} />
|
||||
</Tooltip>
|
||||
<Tooltip title="导入接口">
|
||||
<Icon type='plus' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); this.showImportInterfaceModal(col._id) }} />
|
||||
</Tooltip>
|
||||
<Tooltip title="克隆集合">
|
||||
<Icon type='copy' className="interface-delete-icon" onClick={(e) => { e.stopPropagation(); this.copyInterface(col) }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/*<Dropdown overlay={menu(col)} trigger={['click']} onClick={e => e.stopPropagation()}>
|
||||
<Icon className="opts-icon" type='ellipsis'/>
|
||||
</Dropdown>*/}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{
|
||||
col.caseList && col.caseList.filter((item) => {
|
||||
if (isFilterCat) {
|
||||
return true;
|
||||
}
|
||||
return item.casename.indexOf(filterValue) !== -1
|
||||
}).sort((a, b) => {
|
||||
return a.index - b.index;
|
||||
}).map((interfaceCase) => (
|
||||
<TreeNode
|
||||
style={{ width: '100%' }}
|
||||
key={'case_' + interfaceCase._id}
|
||||
title={
|
||||
<div className="menu-title" title={interfaceCase.casename}>
|
||||
<span className="casename">{interfaceCase.casename}</span>
|
||||
<Tooltip title="删除用例">
|
||||
<Icon type='delete' className="case-delete-icon" onClick={(e) => { e.stopPropagation(); this.showDelCaseConfirm(interfaceCase._id) }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
></TreeNode>
|
||||
))
|
||||
}
|
||||
</TreeNode>
|
||||
))
|
||||
}
|
||||
</Tree>
|
||||
<ColModalForm
|
||||
ref={this.saveFormRef}
|
||||
type={colModalType}
|
||||
visible={colModalVisible}
|
||||
onCancel={() => { this.setState({ colModalVisible: false }) }}
|
||||
onCreate={this.addorEditCol}
|
||||
></ColModalForm>
|
||||
<Modal
|
||||
title="导入接口到集合"
|
||||
visible={importInterVisible}
|
||||
onOk={this.handleImportOk}
|
||||
onCancel={this.handleImportCancel}
|
||||
width={800}
|
||||
>
|
||||
<ImportInterface onChange={this.selectInterface} list={this.props.list} />
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ class InterfaceEdit extends Component {
|
||||
if (result.data.errcode === 0) {
|
||||
this.props.updateInterfaceData(params);
|
||||
message.success('保存成功');
|
||||
this.props.switchToView()
|
||||
} else {
|
||||
message.error(result.data.errmsg)
|
||||
}
|
||||
|
@ -214,6 +214,7 @@ class InterfaceEditForm extends Component {
|
||||
values.req_body_form = []
|
||||
}
|
||||
this.props.onSubmit(values)
|
||||
EditFormContext.props.changeEditStatus(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -725,7 +726,7 @@ class InterfaceEditForm extends Component {
|
||||
|
||||
<Row className={'interface-edit-item ' + this.state.hideTabs.req.query}>
|
||||
<Col>
|
||||
<EasyDragSort data={this.props.form.getFieldValue('req_query')} onChange={this.handleDragMove('req_query')} >
|
||||
<EasyDragSort data={()=>this.props.form.getFieldValue('req_query')} onChange={this.handleDragMove('req_query')} >
|
||||
{QueryList}
|
||||
</EasyDragSort>
|
||||
</Col>
|
||||
@ -740,7 +741,7 @@ class InterfaceEditForm extends Component {
|
||||
|
||||
<Row className={'interface-edit-item ' + this.state.hideTabs.req.headers}>
|
||||
<Col>
|
||||
<EasyDragSort data={this.props.form.getFieldValue('req_headers')} onChange={this.handleDragMove('req_headers')} >
|
||||
<EasyDragSort data={()=>this.props.form.getFieldValue('req_headers')} onChange={this.handleDragMove('req_headers')} >
|
||||
{headerList}
|
||||
</EasyDragSort>
|
||||
</Col>
|
||||
@ -773,7 +774,7 @@ class InterfaceEditForm extends Component {
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
<EasyDragSort data={this.props.form.getFieldValue('req_body_form')} onChange={this.handleDragMove('req_body_form')} >
|
||||
<EasyDragSort data={() => this.props.form.getFieldValue('req_body_form')} onChange={this.handleDragMove('req_body_form')} >
|
||||
{requestBodyList}
|
||||
</EasyDragSort>
|
||||
|
||||
@ -798,7 +799,7 @@ class InterfaceEditForm extends Component {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{this.props.form.getFieldValue('req_body_type') === 'file' ?
|
||||
{this.props.form.getFieldValue('req_body_type') === 'file' && this.state.hideTabs.req.body !== 'hide' ?
|
||||
<Row className="interface-edit-item" >
|
||||
<Col className="interface-edit-item-other-body">
|
||||
{getFieldDecorator('req_body_other', { initialValue: this.state.req_body_other })(
|
||||
@ -811,7 +812,7 @@ class InterfaceEditForm extends Component {
|
||||
:
|
||||
null
|
||||
}
|
||||
{this.props.form.getFieldValue('req_body_type') === 'raw' ?
|
||||
{this.props.form.getFieldValue('req_body_type') === 'raw' && this.state.hideTabs.req.body !== 'hide'?
|
||||
<Row>
|
||||
<Col>
|
||||
{getFieldDecorator('req_body_other', { initialValue: this.state.req_body_other })(
|
||||
|
@ -11,5 +11,7 @@ module.exports = {
|
||||
name: 'statistics'
|
||||
},{
|
||||
name: 'export-data'
|
||||
}, {
|
||||
name: 'api-history'
|
||||
}]
|
||||
}
|
10
exts/yapi-plugin-api-history/client.js
Normal file
10
exts/yapi-plugin-api-history/client.js
Normal file
@ -0,0 +1,10 @@
|
||||
import InterfaceHistory from './client/InterfaceHistory.js';
|
||||
|
||||
module.exports = function(){
|
||||
this.bindHook('interface_tab', function(tabs){
|
||||
tabs.advMock = {
|
||||
name: '历史',
|
||||
component: InterfaceHistory
|
||||
}
|
||||
})
|
||||
}
|
38
exts/yapi-plugin-api-history/client/InterfaceHistory.js
Normal file
38
exts/yapi-plugin-api-history/client/InterfaceHistory.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react'
|
||||
import axios from 'axios'
|
||||
import PropTypes from 'prop-types'
|
||||
//import { Form, Switch, Button, message, Icon, Tooltip, Radio } from 'antd';
|
||||
|
||||
|
||||
|
||||
|
||||
class AdvMock extends Component {
|
||||
// static propTypes = {
|
||||
// form: PropTypes.object,
|
||||
// match: PropTypes.object
|
||||
// }
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return <div >
|
||||
Hello, World.
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AdvMock;
|
4
exts/yapi-plugin-api-history/index.js
Normal file
4
exts/yapi-plugin-api-history/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
server: true,
|
||||
client: true
|
||||
}
|
3
exts/yapi-plugin-api-history/server.js
Normal file
3
exts/yapi-plugin-api-history/server.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = function(){
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,114 +1,114 @@
|
||||
const yapi = require('../yapi.js');
|
||||
const baseModel = require('./base.js');
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
class interfaceCase extends baseModel {
|
||||
getName() {
|
||||
return 'interface_case';
|
||||
}
|
||||
|
||||
getSchema() {
|
||||
return {
|
||||
casename: { type: String, required: true },
|
||||
uid: { type: Number, required: true },
|
||||
col_id: { type: Number, required: true },
|
||||
index: { type: Number, default: 0 },
|
||||
project_id: { type: Number, required: true },
|
||||
interface_id: { type: Number, required: true },
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
case_env: { type: String },
|
||||
req_params: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_headers: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_query: [{
|
||||
name: String, value: String, enable: {type: Boolean, default: true}
|
||||
}],
|
||||
|
||||
req_body_form: [{
|
||||
name: String, value: String, enable: {type: Boolean, default: true}
|
||||
}],
|
||||
req_body_other: String,
|
||||
test_res_body: String,
|
||||
test_status: {type: String, enum: ['ok', 'invalid', 'error', '']},
|
||||
test_res_header: Schema.Types.Mixed,
|
||||
mock_verify: {type: Boolean, default: false},
|
||||
enable_script: {type: Boolean, default: false},
|
||||
test_script: String
|
||||
};
|
||||
}
|
||||
|
||||
save(data) {
|
||||
let m = new this.model(data);
|
||||
return m.save();
|
||||
}
|
||||
|
||||
//获取全部测试接口信息
|
||||
getInterfaceCaseListCount() {
|
||||
return this.model.count({});
|
||||
}
|
||||
|
||||
get(id) {
|
||||
return this.model.findOne({
|
||||
_id: id
|
||||
}).exec();
|
||||
}
|
||||
|
||||
list(col_id, select) {
|
||||
select = select || 'casename uid col_id _id index'
|
||||
if (select === 'all') {
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).exec();
|
||||
}
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).select("casename uid col_id _id index").exec();
|
||||
}
|
||||
|
||||
del(id) {
|
||||
return this.model.remove({
|
||||
_id: id
|
||||
});
|
||||
}
|
||||
|
||||
delByProjectId(id) {
|
||||
return this.model.remove({
|
||||
project_id: id
|
||||
})
|
||||
}
|
||||
|
||||
delByInterfaceId(id){
|
||||
return this.model.remove({
|
||||
interface_id: id
|
||||
})
|
||||
}
|
||||
|
||||
delByCol(id) {
|
||||
return this.model.remove({
|
||||
col_id: id
|
||||
})
|
||||
}
|
||||
|
||||
up(id, data) {
|
||||
data.up_time = yapi.commons.time()
|
||||
return this.model.update(
|
||||
{ _id: id },
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
upCaseIndex(id, index) {
|
||||
return this.model.update({
|
||||
_id: id
|
||||
}, {
|
||||
index: index
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = interfaceCase;
|
||||
const yapi = require('../yapi.js');
|
||||
const baseModel = require('./base.js');
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
class interfaceCase extends baseModel {
|
||||
getName() {
|
||||
return 'interface_case';
|
||||
}
|
||||
|
||||
getSchema() {
|
||||
return {
|
||||
casename: { type: String, required: true },
|
||||
uid: { type: Number, required: true },
|
||||
col_id: { type: Number, required: true },
|
||||
index: { type: Number, default: 0 },
|
||||
project_id: { type: Number, required: true },
|
||||
interface_id: { type: Number, required: true },
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
case_env: { type: String },
|
||||
req_params: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_headers: [{
|
||||
name: String, value: String
|
||||
}],
|
||||
req_query: [{
|
||||
name: String, value: String, enable: { type: Boolean, default: true }
|
||||
}],
|
||||
|
||||
req_body_form: [{
|
||||
name: String, value: String, enable: { type: Boolean, default: true }
|
||||
}],
|
||||
req_body_other: String,
|
||||
test_res_body: String,
|
||||
test_status: { type: String, enum: ['ok', 'invalid', 'error', ''] },
|
||||
test_res_header: Schema.Types.Mixed,
|
||||
mock_verify: { type: Boolean, default: false },
|
||||
enable_script: { type: Boolean, default: false },
|
||||
test_script: String
|
||||
};
|
||||
}
|
||||
|
||||
save(data) {
|
||||
let m = new this.model(data);
|
||||
return m.save();
|
||||
}
|
||||
|
||||
//获取全部测试接口信息
|
||||
getInterfaceCaseListCount() {
|
||||
return this.model.count({});
|
||||
}
|
||||
|
||||
get(id) {
|
||||
return this.model.findOne({
|
||||
_id: id
|
||||
}).exec();
|
||||
}
|
||||
|
||||
list(col_id, select) {
|
||||
select = select || 'casename uid col_id _id index interface_id'
|
||||
if (select === 'all') {
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).exec();
|
||||
}
|
||||
return this.model.find({
|
||||
col_id: col_id
|
||||
}).select("casename uid col_id _id index interface_id").exec();
|
||||
}
|
||||
|
||||
del(id) {
|
||||
return this.model.remove({
|
||||
_id: id
|
||||
});
|
||||
}
|
||||
|
||||
delByProjectId(id) {
|
||||
return this.model.remove({
|
||||
project_id: id
|
||||
})
|
||||
}
|
||||
|
||||
delByInterfaceId(id) {
|
||||
return this.model.remove({
|
||||
interface_id: id
|
||||
})
|
||||
}
|
||||
|
||||
delByCol(id) {
|
||||
return this.model.remove({
|
||||
col_id: id
|
||||
})
|
||||
}
|
||||
|
||||
up(id, data) {
|
||||
data.up_time = yapi.commons.time()
|
||||
return this.model.update(
|
||||
{ _id: id },
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
upCaseIndex(id, index) {
|
||||
return this.model.update({
|
||||
_id: id
|
||||
}, {
|
||||
index: index
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = interfaceCase;
|
||||
|
@ -328,6 +328,11 @@ let routerConfig = {
|
||||
path: 'add_case_list',
|
||||
method: 'post'
|
||||
|
||||
}, {
|
||||
action: 'cloneCaseList',
|
||||
path: 'clone_case_list',
|
||||
method: 'post'
|
||||
|
||||
}, {
|
||||
action: "list",
|
||||
path: "list",
|
||||
@ -415,7 +420,7 @@ let routerConfig = {
|
||||
path: "http/code",
|
||||
method: "post"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
let pluginsRouterPath = [];
|
||||
@ -430,7 +435,7 @@ function addPluginRouter(config) {
|
||||
throw new Error('Plugin Route path conflict, please try rename the path')
|
||||
}
|
||||
pluginsRouterPath.push(routerPath);
|
||||
createAction(router, "/api", config.controller, config.action, routerPath, method,false);
|
||||
createAction(router, "/api", config.controller, config.action, routerPath, method, false);
|
||||
}
|
||||
|
||||
yapi.emitHookSync('add_router', addPluginRouter);
|
||||
|
@ -1 +1,21 @@
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@773f87ecdd1b72f9076c.js","css":"index@773f87ecdd1b72f9076c.css"},"lib":{"js":"lib.min.js"},"lib2":{"js":"lib2.min.js"},"manifest":{"js":"manifest.min.js"}}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@cd86ca67ec83cf50bf7f.js","css":"index@cd86ca67ec83cf50bf7f.css"},"lib":{"js":"lib@440c1fc133fa194fb5a7.js"},"lib2":{"js":"lib2@2b54ffd5cfd140edb818.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@5d0172e1e8d025077c6d.js","css":"index@5d0172e1e8d025077c6d.css"},"lib":{"js":"lib@9f81ac11019b0fb44526.js"},"lib2":{"js":"lib2@d45c8b21cd152647ed17.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
=======
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@1c90318cffcd9226f4ca.js","css":"index@1c90318cffcd9226f4ca.css"},"lib":{"js":"lib@b527656c385f817c6379.js"},"lib2":{"js":"lib2@89ae3d589a0377410eb8.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
>>>>>>> dev-1.2.0
|
||||
>>>>>>> dev
|
||||
=======
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@2749a62173cb051bd43a.js","css":"index@2749a62173cb051bd43a.css"},"lib":{"js":"lib@5ca86296ff97fbf15aa9.js"},"lib2":{"js":"lib2@4e246d55b157fd90cbd6.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
>>>>>>> dev
|
||||
=======
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@61638219be6877d986cc.js","css":"index@61638219be6877d986cc.css"},"lib":{"js":"lib@d8397632ca19f2cbfc57.js"},"lib2":{"js":"lib2@7552d509ada57b7aecab.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
>>>>>>> dev
|
||||
=======
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@773f87ecdd1b72f9076c.js","css":"index@773f87ecdd1b72f9076c.css"},"lib":{"js":"lib.min.js"},"lib2":{"js":"lib2.min.js"},"manifest":{"js":"manifest.min.js"}}
|
||||
>>>>>>> e0633fd4cd88abe7a577250d3fb4a4d4a47e497f
|
||||
|
1
static/prd/index@61638219be6877d986cc.css
Normal file
1
static/prd/index@61638219be6877d986cc.css
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/index@61638219be6877d986cc.css.gz
Normal file
BIN
static/prd/index@61638219be6877d986cc.css.gz
Normal file
Binary file not shown.
1
static/prd/index@61638219be6877d986cc.js
Normal file
1
static/prd/index@61638219be6877d986cc.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/index@61638219be6877d986cc.js.gz
Normal file
BIN
static/prd/index@61638219be6877d986cc.js.gz
Normal file
Binary file not shown.
1
static/prd/lib2@7552d509ada57b7aecab.js
Normal file
1
static/prd/lib2@7552d509ada57b7aecab.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/lib2@7552d509ada57b7aecab.js.gz
Normal file
BIN
static/prd/lib2@7552d509ada57b7aecab.js.gz
Normal file
Binary file not shown.
1
static/prd/lib@d8397632ca19f2cbfc57.js
Normal file
1
static/prd/lib@d8397632ca19f2cbfc57.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/lib@d8397632ca19f2cbfc57.js.gz
Normal file
BIN
static/prd/lib@d8397632ca19f2cbfc57.js.gz
Normal file
Binary file not shown.
@ -85,20 +85,22 @@ module.exports = {
|
||||
'redux-promise',
|
||||
'react-router',
|
||||
'react-router-dom',
|
||||
'prop-types',
|
||||
'axios',
|
||||
'moment',
|
||||
'prop-types',
|
||||
'react-dnd-html5-backend',
|
||||
'react-dnd',
|
||||
'reactabular-table',
|
||||
'reactabular-dnd',
|
||||
'table-resolver'
|
||||
'table-resolver',
|
||||
'recharts'
|
||||
],
|
||||
lib2: [
|
||||
'brace',
|
||||
'mockjs',
|
||||
'json5',
|
||||
'url'
|
||||
'url',
|
||||
'wangeditor',
|
||||
'axios',
|
||||
'moment'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user