前端页面我是用vue.js搭了个脚手架。
下载了网上的demo:https://github.com/PanJiaChen/vue-admin-template,然后再修改。
实现方式
1、使用Vue CLI搭建脚手架
npm install -g @vue/cli
vue create 项目名
npm run serve
(node版本最新版会有一系列问题,建议版本不要太高)
2、使用组件实现上传、对话框
https://element.eleme.cn/#/
zh-CN/component/upload
3、调后端服务接口实现相应逻辑
页面介绍
做了两个菜单,一个菜单是配置性能测试参数与上传脚本文件;另一个就是在线修改脚本
性能测试菜单
在线修改脚本
代码介绍
涉及到修改的文件如下图所示
\vue-admin-template-master\src\router\index.js文件修改
删掉多余的目录菜单,修改留下两个菜单。
性能测试菜单就是对应/views/table/index,想要修改这个菜单就要修改\vue-admin-template-master\src\views\table\index.vue文件。
在线修改脚本菜单就是对应/views/tree/index,则修改\vue-admin-template-master\src\views\tree\index.vue文件。
{
path: '/example',
component: Layout,
redirect: '/example/table',
name: 'Example',
meta: { title: '菜单', icon: 'el-icon-s-help' },
children: [
{
path: 'table',
name: '性能测试',
component: () => import('@/views/table/index'),
meta: { title: '性能测试', icon: 'table' }
},
{
path: 'tree',
name: '在线修改脚本',
component: () => import('@/views/tree/index'),
meta: { title: '在线修改脚本', icon: 'tree' }
}
]
},
\vue-admin-template-master\src\views\tree\index.vue文件
<template>
<div class="app-container">
<el-form
:inline="true"
:model="formInline"
class="demo-form-inline"
>
<el-form-item label="脚本名称">
<el-input
v-model="formInline.user"
placeholder="脚本名称"
></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="onSubmit(formInline.user)"
>查询</el-button>
</el-form-item>
</el-form>
<!-- 脚本名称:
<el-input
placeholder="请输入内容"
prefix-icon="el-icon-search"
v-model="input2"
clearable
>
</el-input>
<el-button
type="primary"
icon="el-icon-search"
>搜索</el-button> -->
<el-table
:data="tableData"
border
fit
highlight-current-row
style="width: 100%"
>
<el-table-column
fixed
prop="id"
label="序号"
width="200"
>
</el-table-column>
<el-table-column
prop="jmxname"
label="脚本名称"
width="1000"
>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="400"
>
<template slot-scope="scope">
<el-button
@click="handleClickget(scope.row)"
type="primary"
>查看</el-button>
<!-- <el-button
@click="handleClickupdate(scope.row)"
type="primary"
>编辑</el-button> -->
<el-button
type="primary"
@click="handleClickupdate(scope.row)"
>编辑</el-button>
<el-button
@click="handleClickupload"
type="primary"
>上传</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog
title="提示"
:visible.sync="jmxdialogVisible"
width="30%"
:before-close="jmxhandleClose"
>
<span>无此脚本,请输入正确的脚本名称。</span>
<span
slot="footer"
class="dialog-footer"
>
<el-button @click="jmxdialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="jmxdialogVisible = false"
>确 定</el-button>
</span>
</el-dialog>
<el-dialog
title="脚本内容"
:visible.sync="jmxdatadialogFormVisible"
>
<el-input v-model="input"></el-input>
<!-- <el-form :model="form">
<el-form-item
label="脚本内容"
:label-width="formLabelWidth"
>
<el-input
v-model="form.jmx_data"
autocomplete="off"
></el-input>
</el-form-item>
</el-form> -->
</el-dialog>
<el-dialog
title="修改与调试脚本"
:visible.sync="dialogFormVisible"
>
<el-form :model="form">
<el-form-item
label="脚本内容"
:label-width="formLabelWidth"
>
<el-input
type="textarea"
autosize
v-model="form.name"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div
slot="footer"
class="dialog-footer"
>
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button
type="primary"
@click="savejmeterdata(form.name)"
>保存</el-button>
<el-button
type="primary"
@click="runjmeter"
>调试</el-button>
<!-- <el-button
type="primary"
@click="runjmeterresult"
>查看调试结果</el-button> -->
<!-- <el-button
type="primary"
@click="dialogFormVisible = false"
>确定修改</el-button> -->
<el-button
type="primary"
onclick="window.location.href='http://localhost:8091/HTTPrequest/'"
>查看调试结果</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
getjmxdata,
getjmxfile,
runjmetercmd,
savejmeter,
uploadtogit,
} from "@/api/table";
export default {
data() {
return {
// input2: "",
tableData: [],
formInline: {
user: "",
},
jmxdialogVisible: false,
jmxdatadialogFormVisible: false,
dialogFormVisible: false,
// form: [],
input: "",
form: {
name: "",
},
formLabelWidth: "120px",
};
},
watch: {
filterText(val) {
this.$refs.tree2.filter(val);
},
},
methods: {
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
onSubmit(user) {
const params = {
jmx_name: user,
};
console.log(params);
getjmxfile(params).then((res) => {
console.log(res);
if (res == "000") {
this.jmxdialogVisible = true;
} else {
//要展示脚本名称与序号
this.tableData = [{ id: "1", jmxname: user }];
}
});
},
jmxhandleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
})
.catch((_) => {});
},
handleClickget(row) {
const params = {
jmx_name: row.jmxname,
};
getjmxdata(params).then((res) => {
this.$msgbox(res, "脚本内容", {
type: "info",
});
});
},
handleClickupdate(row) {
this.dialogFormVisible = true;
const params = {
jmx_name: row.jmxname,
};
getjmxdata(params).then((res) => {
this.form.name = res;
});
},
runjmeter() {
runjmetercmd().then((res) => {
console.log(res);
const h = this.$createElement;
this.$notify({
title: "调试结果",
message: h("i", { style: "color: teal" }, res),
type: "success",
});
});
},
savejmeterdata(name) {
console.log(name, "121221");
const params = {
jmx_data: name,
};
savejmeter(params).then((res) => {
const h = this.$createElement;
this.$notify({
title: "保存结果",
message: h("i", { style: "color: teal" }, res),
type: "success",
});
});
},
handleClickupload() {
uploadtogit().then((res) => {
const h = this.$createElement;
this.$notify({
title: "上传结果",
message: h("i", { style: "color: teal" }, res),
type: "success",
});
});
},
},
};
</script>
<style lang="scss">
.el-message-box__wrapper .el-message-box {
width: 1280px;
}
.el-message-box__message p {
margin: 0;
line-height: 24px;
height: 817px;
overflow-y: scroll;
}
</style>
\vue-admin-template-master\src\views\table\index.vue文件
<template>
<div class="app-container">
<el-button
type="primary"
@click="dialogFormVisible = true"
>新增性能测试场景</el-button>
<el-dialog
title="新增性能测试场景"
:visible.sync="dialogFormVisible"
>
<el-form :model="form">
<el-form-item
label="脚本名称"
:label-width="formLabelWidth"
>
<el-input
v-model="form.jmx_name"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="测试工号"
:label-width="formLabelWidth"
>
<!-- <el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select> -->
<el-input
v-model="form.author_id"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="定时任务时间"
:label-width="formLabelWidth"
>
<el-input
v-model="form.time"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="总线程数"
:label-width="formLabelWidth"
>
<el-input
v-model="form.thread"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="开始线程数"
:label-width="formLabelWidth"
>
<el-input
v-model="form.start_thread"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="多少秒内增加多少线程之多少秒"
:label-width="formLabelWidth"
>
<el-input
v-model="form.seconds"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="多少秒内增加多少线程之多少线程"
:label-width="formLabelWidth"
>
<el-input
v-model="form.add_thread"
autocomplete="off"
></el-input>
</el-form-item>
<el-upload
class="upload-demo"
action="后端暴露出来的上传接口"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList"
>
<el-button
size="small"
type="primary"
>点击上传</el-button>
<div
slot="tip"
class="el-upload__tip"
>请上传脚本文件</div>
</el-upload>
</el-form>
<div
slot="footer"
class="dialog-footer"
>
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button
type="primary"
@click="handleSave"
>确 定</el-button>
</div>
</el-dialog>
<el-table
v-loading="listLoading"
:data="list"
element-loading-text="Loading"
border
fit
highlight-current-row
style="width: 100%"
>
<!--
<el-table-column align="center" label="ID" width="95">
<template slot-scope="scope">
{{ scope.$index }}
</template>
</el-table-column> -->
<el-table-column
label="脚本名称"
width="150"
prop="jmx_name"
>
<!-- <el-input v-model="jmx_name" autocomplete="off" /> -->
</el-table-column>
<el-table-column
label="测试工号"
width="150"
align="center"
prop="author_id"
>
<!-- <template slot-scope="scope">
<span>{{ author_id }}</span>
</template> -->
</el-table-column>
<el-table-column
label="定时任务时间"
width="210"
align="center"
prop="time"
>
<!-- <template slot-scope="scope">
{{ time }}
</template> -->
</el-table-column>
<el-table-column
label="线程数"
width="210"
align="center"
prop="thread"
>
<!-- <template slot-scope="scope">
{{ time }}
</template> -->
</el-table-column>
<el-table-column
label="开始线程数"
width="210"
align="center"
prop="start_thread"
>
<!-- <template slot-scope="scope">
{{ start_thread }}
</template> -->
</el-table-column>
<el-table-column
label="开始线程数"
width="210"
align="center"
prop="seconds"
>
<!-- <template slot-scope="scope">
{{ start_thread }}
</template> -->
</el-table-column>
<el-table-column
label="开始线程数"
width="210"
align="center"
prop="add_thread"
>
<!-- <template slot-scope="scope">
{{ start_thread }}
</template> -->
</el-table-column>
<el-table-column
class-name="status-col"
label="测试报告"
width="210"
align="center"
>
<template slot-scope="scope">
<el-button
@click="handleClick(scope.row)"
type="primary"
>测试报告</el-button>
</template>
<!-- <el-button
type="primary"
onclick="window.location.href='http://localhost:8091/result0108/'"
>测试报告</el-button> -->
<!-- <button onclick="window.location.href='http://localhost:8091/result0108/'">按钮</button> -->
<!-- <template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
</template> -->
</el-table-column>
</el-table>
<!-- <el-button
type="text"
@click="dialogVisible = false"
>点击打开 Dialog</el-button> -->
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<span>脚本还未执行完成,报告未生成,请稍后再来。</span>
<span
slot="footer"
class="dialog-footer"
>
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="dialogVisible = false"
>确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getList, getreport, updateJekins } from "@/api/table";
export default {
filters: {
statusFilter(status) {
const statusMap = {
published: "success",
draft: "gray",
deleted: "danger",
};
return statusMap[status];
},
},
data() {
return {
list: [],
listLoading: false,
// fileList: [{name:file.name,url:'',}]
dialogTableVisible: false,
dialogFormVisible: false,
dialogVisible: false,
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
formLabelWidth: "120px",
};
},
created() {
this.fetchData();
},
methods: {
fetchData() {
// this.listLoading = true
const cacheData = JSON.parse(localStorage.getItem("storage_name"));
if (cacheData) {
this.list = cacheData;
}
console.log(this.list, "xxx");
// this.time = cacheData?.time ?? ''
// this.jmx_name = cacheData?.jmx_name ?? ''
// this.author_id = cacheData?.author_id ?? ''
// this.thread = cacheData?.thread ?? ''
// this.start_thread = cacheData?.start_thread ?? ''
// this.seconds = cacheData?.seconds ?? ''
// this.add_thread = cacheData?.add_thread ?? ''
// getList().then(response => {
// this.list = response.data.items
// this.listLoading = false
// })
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
files.length + fileList.length
} 个文件`
);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
handleSave() {
const params = {
jmx_name: this.form.jmx_name,
time: this.form.time,
author_id: this.form.author_id,
thread: this.form.thread,
start_thread: this.form.start_thread,
seconds: this.form.seconds,
add_thread: this.form.add_thread,
};
console.log(this.list, "111212");
this.list.push(params);
console.log(this.list, "111");
const storage = window.localStorage;
storage.setItem("storage_name", JSON.stringify(this.list));
updateJekins(params).then((res) => {
this.dialogFormVisible = false;
});
},
handleClick(row) {
const params = {
jmx_name: row.jmx_name,
};
getreport(params).then((res) => {
console.log(res);
if (res == "000") {
this.dialogVisible = true;
} else {
window.location.href = "http://localhost:8091/" + row.jmx_name;
}
});
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
})
.catch((_) => {});
},
},
};
</script>
\vue-admin-template-master\src\api\table.js文件
import request from '@/utils/request'
export function getList(params) {
return request({
url: '/vue-admin-template/table/list',
method: 'get',
params
})
}
export function updateJekins(params) {
return request({
url: '后端暴露出来的更新Jenkins接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: params
})
}
export function getreport(params) {
return request({
url: '后端暴露出来的匹配测试报告文件接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: params
})
}
export function getjmxfile(params) {
return request({
url: '后端暴露出来的匹配jmx文件接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: params
})
}
export function getjmxdata(params) {
return request({
url: '后端暴露出来的读取jmx文件接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: params
})
}
export function runjmetercmd() {
return request({
url: '后端暴露出来的执行jmeter接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
// data: params
})
}
export function savejmeter(params) {
return request({
url: '后端暴露出来的保存jmx文件接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: params
})
}
export function uploadtogit() {
return request({
url: '后端暴露出来的上传文件到git的接口',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
})
}