一、demo代码
body tab页下,选择不同的radio展示不同的页面:
<a-radio-group defaultValue="none" :select="body_type" name="radioGroup" @change="onChange" style="width: 100%" >
<a-radio value="none">none</a-radio>
<a-radio value="form-data">form-data</a-radio>
<a-radio value="x-www-form-urlencoded">x-www-form-urlencoded</a-radio>
<a-radio value="raw">raw</a-radio>
<a-radio value="binary">binary</a-radio>
<a-radio value="GraphQL">GraphQL</a-radio>
<a-card style="width: 100%" >
<p v-if="body_type=='none'">This request does not have a body</p>
<div v-else-if="body_type=='form-data'">
<a-table :columns="columns" :dataSource="data" :pagination="false" bordered>
<template v-for="col in ['KEY', 'VALUE', 'DESCRIPTION']" :slot="col" slot-scope="text, record, index">
<div :key="col">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChanged(e.target.value, record.key, col,index)"
/>
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">
<a-space>
<a @click="() => save(record.key,index)">Save</a>
<a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key,index)">
<a>Cancel</a>
</a-popconfirm>
</a-space>
</span>
<span v-else>
<a @click="() => edit(record.key,index)">Edit</a>
</span>
</div>
</template>
</a-table>
<a-button class="editable-add-btn" style="width: 100%" @click="handleAdd">+ 添加一行数据</a-button>
</div>
<codemirror v-else
ref="myCmGenerate"
class="code-mirror"
v-model="code"
:options="options"
@changes="changes"
@ready="onCmReady"
@focus="onCmFocus"
@input="onCmCodeChange"
@scroll="onScrollFn"
/>
</a-card>
</a-radio-group>
二、完整代码
<template>
<div>
<a-card title="在线HTTP测试工具" style="width: 100%">
<a-row>
<a-col :span="4">
<a-space>
<a-select
ref="select"
defaultValue="get"
style="width: 150px"
@focus="focus"
@change="handleChange"
>
<a-select-option value="get">GET</a-select-option>
<a-select-option value="post">POST</a-select-option>
<a-select-option value="put" >PUT</a-select-option>
<a-select-option value="delete">DELETE</a-select-option>
</a-select>
</a-space>
</a-col>
<a-col :span="20">
<a-input style="width: calc(100% - 250px)" />
<a-space>
<a-button type="primary" @click="onSubmit" >请求此API</a-button>
<a-popconfirm
title="确定将请求转为case?"
ok-text="确定"
cancel-text="取消"
@confirm="confirm"
@cancel="cancel"
>
<a-button type="primary" >保存为case</a-button>
</a-popconfirm>
</a-space>
</a-col>
</a-row>
<br />
<a-row>
<a-col :span="24">
<!-- activeKey属性通过“v-model”实现表单与data数据的双向绑定, 需在data中定义该属性-->
<a-tabs v-model="activeKey">
<a-tab-pane key="1" tab="Params">
<a-table :columns="columns" :dataSource="data" :pagination="false" bordered>
<template v-for="col in ['KEY', 'VALUE', 'DESCRIPTION']" :slot="col" slot-scope="text, record, index">
<div :key="col">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChanged(e.target.value, record.key, col,index)"
/>
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">
<a-space>
<a @click="() => save(record.key,index)">Save</a>
<a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key,index)">
<a>Cancel</a>
</a-popconfirm>
</a-space>
</span>
<span v-else>
<a @click="() => edit(record.key,index)">Edit</a>
</span>
</div>
</template>
</a-table>
<a-button class="editable-add-btn" style="width: 100%" @click="handleAdd">+ 添加一行数据</a-button>
</a-tab-pane>
<a-tab-pane key="2" tab="Headers" force-render>
<a-table :columns="columns" :dataSource="data" :pagination="false" bordered>
<template v-for="col in ['KEY', 'VALUE', 'DESCRIPTION']" :slot="col" slot-scope="text, record, index">
<div :key="col">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChanged(e.target.value, record.key, col,index)"
/>
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">
<a-space>
<a @click="() => save(record.key,index)">Save</a>
<a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key,index)">
<a>Cancel</a>
</a-popconfirm>
</a-space>
</span>
<span v-else>
<a @click="() => edit(record.key,index)">Edit</a>
</span>
</div>
</template>
</a-table>
<a-button class="editable-add-btn" style="width: 100%" @click="handleAdd">+ 添加一行数据</a-button>
</a-tab-pane>
<a-tab-pane key="3" tab="Body">
<a-col :span="24">
<a-radio-group defaultValue="none" :select="body_type" name="radioGroup" @change="onChange" style="width: 100%" >
<a-radio value="none">none</a-radio>
<a-radio value="form-data">form-data</a-radio>
<a-radio value="x-www-form-urlencoded">x-www-form-urlencoded</a-radio>
<a-radio value="raw">raw</a-radio>
<a-radio value="binary">binary</a-radio>
<a-radio value="GraphQL">GraphQL</a-radio>
<a-card style="width: 100%" >
<p v-if="body_type=='none'">This request does not have a body</p>
<div v-else-if="body_type=='form-data'">
<a-table :columns="columns" :dataSource="data" :pagination="false" bordered>
<template v-for="col in ['KEY', 'VALUE', 'DESCRIPTION']" :slot="col" slot-scope="text, record, index">
<div :key="col">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChanged(e.target.value, record.key, col,index)"
/>
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">
<a-space>
<a @click="() => save(record.key,index)">Save</a>
<a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key,index)">
<a>Cancel</a>
</a-popconfirm>
</a-space>
</span>
<span v-else>
<a @click="() => edit(record.key,index)">Edit</a>
</span>
</div>
</template>
</a-table>
<a-button class="editable-add-btn" style="width: 100%" @click="handleAdd">+ 添加一行数据</a-button>
</div>
<codemirror v-else
ref="myCmGenerate"
class="code-mirror"
v-model="code"
:options="options"
@changes="changes"
@ready="onCmReady"
@focus="onCmFocus"
@input="onCmCodeChange"
@scroll="onScrollFn"
/>
</a-card>
</a-radio-group>
</a-col>
</a-tab-pane>
<a-tab-pane key="4" tab="Assert">
<codemirror
ref="myCmGenerate"
class="code-mirror"
v-model="code"
:options="options"
@changes="changes"
@ready="onCmReady"
@focus="onCmFocus"
@input="onCmCodeChange"
@scroll="onScrollFn"
/>
</a-tab-pane>
</a-tabs>
</a-col>
</a-row>
<br />
<a-row>
<a-card title="Response" style="width: 100%">
<p>{{ rev_data }}</p>
</a-card>
</a-row>
</a-card>
</div>
</template>
<script>
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/material.css'
import 'codemirror/mode/python/python.js'
import 'codemirror/mode/javascript/javascript'
import {postman_send} from "@/services/postman";
const columns = [
{
title : 'KEY',
dataIndex: 'KEY',
scopedSlots: { customRender: 'KEY' },
width: '25%',
},
{
title: 'VALUE',
dataIndex: 'VALUE',
scopedSlots: { customRender: 'VALUE' },
width: '25%',
},
{
title: 'DESCRIPTION',
dataIndex: 'DESCRIPTION',
scopedSlots: { customRender: 'DESCRIPTION' },
width: '25%',
},
{
title : 'operation',
dataIndex: 'operation',
scopedSlots: { customRender: 'operation' },
width: '25%',
},
];
export default {
name: "Postman",
data() {
return {
api_url: "http://localhost:7777/auth/hello",
rev_data: "",
activeKey: '1',
data:[],
dataSource:[],
columns:columns,
body_type:'none',
editableData:{},
code: '',
options: {
tabSize: 4,
theme: 'material',
lineNumbers: true,
line: true,
autocorrect: true,
spellcheck: true,
mode: {
name: 'python',
json: true
},
styleActiveLine: true,
hintOptions: {
completeSingle: true
},
}
}
},
methods: {
onSubmit() {
this.loading = true;
postman_send(this.api_url)
.then((result) => {
this.loading = false;
this.rev_data = result;
})
.catch((err) => {
this.rev_data = err;
});
},
focus(key) {
console.log(key)
},
handleChange(key) {
console.log(key)
},
onChange(e){
if (e.target.value === 'none') {
this.body_type = 'none'
console.log('radio-----',e)
} else if (e.target.value === 'form-data') {
this.body_type = 'form-data'
} else if (e.target.value === 'x-www-form-urlencoded') {
this.body_type = 'x-www-form-urlencoded'
} else if (e.target.value === 'raw') {
this.body_type = 'raw'
}
},
onCmReady() {
this.$refs.myCmGenerate.codemirror.setSize('100%', '600px')
},
onCmFocus(instance, event) {
console.log(instance,event)
},
onCmCodeChange(instance, obj) {
console.log(instance,obj)
},
changes() {},
onScrollFn() {},
confirm() {},
handleChanged (value, key, column, index) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[index]
if (target) {
target[column] = value
this.data = newData
}
},
edit(key,index) {
const newData = [...this.data]
console.log('newData----',newData)
const target = newData.filter(item => key === item.key)[index]
if (target) {
target.editable = true
this.data = newData
}
},
save(key,index) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[index]
if (target) {
delete target.editable
this.data = newData
this.cacheData = newData.map(item => ({ ...item }))
}
},
cancel(key,index) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[index]
if (target) {
Object.assign(target, this.cacheData.filter(item => key === item.key)[index])
delete target.editable
this.data = newData
}
},
handleAdd() {
const { count } = this
this.data.push( {
KEY: '',
VALUE: '',
DESCRIPTION: '',
})
this.count = count + 1
},
},
components: {
codemirror
},
}
</script>
<style scoped>
</style>
三、效果
四、遗留问题
重复组件未封装,代码冗余
|