diff --git a/client/common.js b/client/common.js index be2a00a9..327f0267 100755 --- a/client/common.js +++ b/client/common.js @@ -185,6 +185,23 @@ function handleMockWord(word) { return Mock.mock(word); } +/** + * 合并后新的对象属性与 Obj 一致,nextObj 有对应属性则取 nextObj 属性值,否则取 Obj 属性值 + * @param {Object} Obj 旧对象 + * @param {Object} nextObj 新对象 + * @return {Object} 合并后的对象 + */ +exports.safeAssign = (Obj, nextObj) => { + let keys = Object.keys(nextObj); + return Object.keys(Obj).reduce((result, value) => { + if (keys.indexOf(value) >= 0) { + result[value] = nextObj[value]; + } else { + result[value] = Obj[value]; + } + return result; + }, {}); +}; exports.simpleJsonPathParse = simpleJsonPathParse; exports.handleMockWord = handleMockWord; diff --git a/client/reducer/modules/mockCol.js b/client/reducer/modules/mockCol.js new file mode 100644 index 00000000..4305890e --- /dev/null +++ b/client/reducer/modules/mockCol.js @@ -0,0 +1,30 @@ +import axios from 'axios' + +// Actions +const FETCH_MOCK_COL = 'yapi/mockCol/FETCH_MOCK_COL'; + +// Reducer +const initialState = { + list: [] +} + +export default (state = initialState, action) => { + switch (action.type) { + case FETCH_MOCK_COL: + return { + ...state, + list: action.payload.data.data + } + default: + return state + } +} + +// Action Creators +export async function fetchMockCol(interfaceId) { + let result = await axios.get('/api/plugin/advmock/case/list?interface_id=' + interfaceId); + return { + type: FETCH_MOCK_COL, + payload: result.data + } +} diff --git a/client/reducer/modules/reducer.js b/client/reducer/modules/reducer.js index 3b08a46b..e891faec 100755 --- a/client/reducer/modules/reducer.js +++ b/client/reducer/modules/reducer.js @@ -8,6 +8,7 @@ import news from './news.js' import addInterface from './addInterface.js' import menu from './menu.js' import follow from './follow.js' +import mockCol from './mockCol.js' export default combineReducers({ group, @@ -18,5 +19,6 @@ export default combineReducers({ news, addInterface, menu, - follow + follow, + mockCol }) diff --git a/exts/yapi-plugin-advanced-mock/MockCol/CaseDesModal.js b/exts/yapi-plugin-advanced-mock/MockCol/CaseDesModal.js new file mode 100644 index 00000000..728f3a8e --- /dev/null +++ b/exts/yapi-plugin-advanced-mock/MockCol/CaseDesModal.js @@ -0,0 +1,258 @@ +import React, { Component } from 'react' +// import axios from 'axios' +import PropTypes from 'prop-types' +import { Button, Form, Input, Switch, Select, Icon, Modal } from 'antd'; +import { safeAssign } from '../../../client/common.js'; +import { httpCodes } from '../index.js'; + +const Option = Select.Option; +const FormItem = Form.Item; +const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 5 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 12 } + } +}; + +@Form.create() +export default class CaseDesModal extends Component { + static propTypes = { + form: PropTypes.object, + caseData: PropTypes.object, + onCancel: PropTypes.func, + onOk: PropTypes.func, + isAdd: PropTypes.bool, + visible: PropTypes.bool + } + + constructor(props) { + super(props); + } + + preProcess = caseData => { + // const a = { + // interface_id: { type: Number, required: true }, + // project_id: {type: Number, required: true}, + // ip: {type: String}, + // ip_enable: {type: Boolean, default: false}, + // name: {type: String, required: true}, + // code: {type: Number, default: 200}, + // deplay: {type: Number, default: 0}, + // headers: [{ + // name: {type: String, required: true}, + // value: {type: String} + // }], + // params: mongoose.Schema.Types.Mixed, + // uid: String, + // up_time: Number, + // res_body: {type: String, required: true} + // } + const initCaseData = { + ip: '', + ip_enable: false, + name: '', + code: '200', + deplay: 0, + headers: [{name: '', value: ''}], + paramsArr: [{name: '', value: ''}], + res_body: '' + } + caseData.paramsArr = caseData.params && caseData.params.length ? Object.keys(caseData.params).map(key => { + return { name: key, value: caseData.params[key] } + }) : [{name: '', value: ''}]; + caseData.headers = caseData.headers && caseData.headers.length ? caseData.headers : [{name: '', value: ''}]; + caseData = safeAssign(initCaseData, caseData); + return caseData; + } + + endProcess = caseData => { + const headers = []; + const params = {}; + caseData.headers.forEach(item => { + if (item.name) { + headers.push({ + name: item.name, + value: item.value + }) + } + }); + caseData.paramsArr.forEach(item => { + if (item.name) { + params[item.name] = item.value + } + }) + caseData.headers = headers; + caseData.params = params; + delete caseData.paramsArr; + return caseData; + } + + componentDidMount() { + this.props.form.setFieldsValue(this.preProcess(this.props.caseData)) + } + + componentWillReceiveProps(nextProps) { + if (this.props.caseData !== nextProps.caseData) { + this.props.form.setFieldsValue(this.preProcess(this.props.caseData)) + } + } + + handleOk = () => { + const form = this.props.form; + this.props.onOk(this.endProcess(form.getFieldsValue())); + } + + render() { + const { getFieldDecorator, getFieldValue } = this.props.form; + const { isAdd, visible, onCancel } = this.props; + // const { caseData } = this.props; + // const headers = caseData.headers || [{name: '', value: ''}]; + // const params = caseData.params || {'': ''}; + // const paramsArr = Object.keys(params).map(key => { + // return { name: key, value: params[key] } + // }) + + return ( + onCancel()} + > +
+ + {getFieldDecorator('name', { + rules: [{ required: true, message: '请输入期望名称!' }] + })( + + )} + + + {getFieldDecorator('ip_enable', { + valuePropName: 'checked', + rules: [{ type: 'boolean' }] + })( + + )} + + + {getFieldDecorator('ip')( + + )} + + + {getFieldDecorator('code')( + + )} + + + {getFieldDecorator('deplay', { + initialValue: 0, + rules: [{ required: true, message: '请输入延时时间!', type: 'integer' }] + })( + + )} + + { + getFieldDecorator('headers', { initialValue: [] }) && + getFieldValue('headers').map((item, index) => ( +
+ + {getFieldDecorator(`headers[${index}].name`)( + + )} + + + {getFieldDecorator(`headers[${index}].value`)( + + )} + +
+ )) + } + + + + + { + getFieldDecorator('paramsArr', { initialValue: [] }) && + getFieldValue('paramsArr').map((item, index) => ( +
+ + {getFieldDecorator(`paramsArr[${index}].name`)( + + )} + {getFieldValue('paramsArr').length > 1 ? ( + this.remove(index)} + /> + ) : null} + + + {getFieldDecorator(`paramsArr[${index}].value`)( + + )} + {getFieldValue('paramsArr').length > 1 ? ( + this.remove(index)} + /> + ) : null} + +
+ )) + } + + + + + + {getFieldDecorator('res_body', { + rules: [{ required: true, message: '请输入期望名称!' }] + })( + + )} + +
+
+ ) + } +} diff --git a/exts/yapi-plugin-advanced-mock/MockCol/MockCol.js b/exts/yapi-plugin-advanced-mock/MockCol/MockCol.js new file mode 100644 index 00000000..5cc3d60c --- /dev/null +++ b/exts/yapi-plugin-advanced-mock/MockCol/MockCol.js @@ -0,0 +1,106 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +// import axios from 'axios' +import PropTypes from 'prop-types' +import { withRouter } from 'react-router-dom'; +import { Table, Button } from 'antd'; +import { fetchMockCol } from '../../../client/reducer/modules/mockCol' +import { formatTime } from '../../../client/common.js'; +import CaseDesModal from './CaseDesModal'; + +@connect( + state => { + return { + list: state.mockCol.list + } + }, + { + fetchMockCol + } +) +@withRouter +export default class MockCol extends Component { + static propTypes = { + list: PropTypes.array, + match: PropTypes.object, + fetchMockCol: PropTypes.func + } + + state = { + caseData: {}, + caseDesModalVisible: false, + isAdd: false + } + + constructor(props) { + super(props); + } + + componentWillMount() { + const interfaceId = this.props.match.params.actionId + this.props.fetchMockCol(interfaceId); + } + + handleOk = (caseData) => { + if (this.state.isAdd) { + caseData = Object.assign({ + ...caseData, + interface_id: 0, + project_id: 0, + uid: 0 + }) + // addCase() + } else { + // saveCase() + } + console.log(caseData) + } + + saveFormRef = (form) => { + this.form = form; + } + + render() { + + const data = this.props.list; + const { isAdd, caseData, caseDesModalVisible } = this.state; + + const columns = [{ + title: '期望名称', + dataIndex: 'name', + key: 'name', + render: text => {text} + }, { + title: 'ip', + dataIndex: 'ip', + key: 'ip' + }, { + title: '创建人', + dataIndex: 'username', + key: 'username' + }, { + title: '编辑时间', + key: 'action', + render: text => formatTime(text) + }, { + title: '操作', + dataIndex: 'address', + key: 'address' + }]; + + return ( +
+ + + this.setState({caseDesModalVisible: false})} + ref={this.saveFormRef} + > + + ) + } +} diff --git a/exts/yapi-plugin-advanced-mock/client.js b/exts/yapi-plugin-advanced-mock/client.js index 26a7d7db..a763b467 100644 --- a/exts/yapi-plugin-advanced-mock/client.js +++ b/exts/yapi-plugin-advanced-mock/client.js @@ -1,4 +1,4 @@ -import AdvMock from './AdvMock.js' +import AdvMock from './MockCol/MockCol.js' module.exports = function(){ this.bindHook('interface_tab', function(tabs){