|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div id="app">
|
|
|
+ <div class="site-test">
|
|
|
<h1>未迟 【站点测试工具】</h1>
|
|
|
|
|
|
<!-- 新增的下拉选择框 -->
|
|
@@ -49,82 +49,85 @@
|
|
|
// import { Terminal } from 'xterm';
|
|
|
// import 'xterm/css/xterm.css';
|
|
|
const metricLabelMap = {
|
|
|
- checks_total: '总检查数',
|
|
|
- checks_succeeded: '检查通过率',
|
|
|
- checks_failed: '检查失败率',
|
|
|
- browser_data_received: '浏览器接收数据量',
|
|
|
- browser_data_sent: '浏览器发送数据量',
|
|
|
- browser_http_req_duration: '浏览器 HTTP 请求耗时',
|
|
|
- browser_http_req_failed: '浏览器 HTTP 请求失败率',
|
|
|
- browser_web_vital_cls: '浏览器内容布局偏移(CLS)',
|
|
|
- browser_web_vital_fcp: '浏览器首次内容绘制(FCP)',
|
|
|
- browser_web_vital_ttfb: '浏览器首字节时间(TTFB)',
|
|
|
- checks: '检查通过率',
|
|
|
- data_received: '接收数据量',
|
|
|
- data_sent: '发送数据量',
|
|
|
- iteration_duration: '单次迭代耗时',
|
|
|
- iterations: '总迭代次数',
|
|
|
- vus: '虚拟用户数',
|
|
|
- vus_max: '最大虚拟用户数',
|
|
|
+ checks_total: "总检查数",
|
|
|
+ checks_succeeded: "检查通过率",
|
|
|
+ checks_failed: "检查失败率",
|
|
|
+ browser_data_received: "浏览器接收数据量",
|
|
|
+ browser_data_sent: "浏览器发送数据量",
|
|
|
+ browser_http_req_duration: "浏览器 HTTP 请求耗时",
|
|
|
+ browser_http_req_failed: "浏览器 HTTP 请求失败率",
|
|
|
+ browser_web_vital_cls: "浏览器内容布局偏移(CLS)",
|
|
|
+ browser_web_vital_fcp: "浏览器首次内容绘制(FCP)",
|
|
|
+ browser_web_vital_ttfb: "浏览器首字节时间(TTFB)",
|
|
|
+ checks: "检查通过率",
|
|
|
+ data_received: "接收数据量",
|
|
|
+ data_sent: "发送数据量",
|
|
|
+ iteration_duration: "单次迭代耗时",
|
|
|
+ iterations: "总迭代次数",
|
|
|
+ vus: "虚拟用户数",
|
|
|
+ vus_max: "最大虚拟用户数",
|
|
|
};
|
|
|
|
|
|
const fieldKeyMap = {
|
|
|
- avg: '平均',
|
|
|
- min: '最小',
|
|
|
- med: '中位数',
|
|
|
- max: '最大',
|
|
|
- 'p(90)': 'P90',
|
|
|
- 'p(95)': 'P95',
|
|
|
- value: '数值',
|
|
|
- rate: '速率'
|
|
|
+ avg: "平均",
|
|
|
+ min: "最小",
|
|
|
+ med: "中位数",
|
|
|
+ max: "最大",
|
|
|
+ "p(90)": "P90",
|
|
|
+ "p(95)": "P95",
|
|
|
+ value: "数值",
|
|
|
+ rate: "速率",
|
|
|
};
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
- targetUrl: '',
|
|
|
- title1: '',
|
|
|
- title2: '',
|
|
|
- message: '',
|
|
|
- testType: '1', // 新增的下拉框绑定值,默认选择负载测试
|
|
|
- protocal: 'http://',
|
|
|
- imgUrl: '',
|
|
|
- }
|
|
|
+ targetUrl: "",
|
|
|
+ title1: "",
|
|
|
+ title2: "",
|
|
|
+ message: "",
|
|
|
+ testType: "1", // 新增的下拉框绑定值,默认选择负载测试
|
|
|
+ protocal: "http://",
|
|
|
+ imgUrl: "",
|
|
|
+ };
|
|
|
},
|
|
|
methods: {
|
|
|
fetchData() {
|
|
|
// const term = new Terminal();
|
|
|
// term.open(this.$refs.terminalContainer);
|
|
|
- this.title2 = ''
|
|
|
- this.imgUrl = '';
|
|
|
- this.title1 = this.targetUrl + '测试结果:'
|
|
|
+ this.title2 = "";
|
|
|
+ this.imgUrl = "";
|
|
|
+ this.title1 = this.targetUrl + "测试结果:";
|
|
|
const timeStamp = new Date().getTime();
|
|
|
// 修改请求URL,包含测试类型参数
|
|
|
- fetch(`/api/k6?targetUrl=${this.protocal + this.targetUrl}&timeStamp=` + timeStamp)
|
|
|
- .then(res => res.json())
|
|
|
- .then(data => {
|
|
|
- this.imgUrl = '/static/screenshot_' + timeStamp + '.png';
|
|
|
- const tbody = document.getElementById('k6-metrics-tbody');
|
|
|
- tbody.innerHTML = '';
|
|
|
+ fetch(
|
|
|
+ `/api/k6?targetUrl=${this.protocal + this.targetUrl}&timeStamp=` +
|
|
|
+ timeStamp
|
|
|
+ )
|
|
|
+ .then((res) => res.json())
|
|
|
+ .then((data) => {
|
|
|
+ this.imgUrl = "/static/screenshot_" + timeStamp + ".png";
|
|
|
+ const tbody = document.getElementById("k6-metrics-tbody");
|
|
|
+ tbody.innerHTML = "";
|
|
|
|
|
|
Object.entries(data).forEach(([metricKey, metricVal]) => {
|
|
|
const metricLabel = metricLabelMap[metricKey] || metricKey;
|
|
|
|
|
|
- if (typeof metricVal === 'object' && !Array.isArray(metricVal)) {
|
|
|
+ if (typeof metricVal === "object" && !Array.isArray(metricVal)) {
|
|
|
const subKeys = Object.keys(metricVal);
|
|
|
subKeys.forEach((subKey, idx) => {
|
|
|
- const tr = document.createElement('tr');
|
|
|
+ const tr = document.createElement("tr");
|
|
|
|
|
|
if (idx === 0) {
|
|
|
- const nameTd = document.createElement('td');
|
|
|
+ const nameTd = document.createElement("td");
|
|
|
nameTd.textContent = metricLabel;
|
|
|
nameTd.rowSpan = subKeys.length;
|
|
|
tr.appendChild(nameTd);
|
|
|
}
|
|
|
|
|
|
- const subKeyTd = document.createElement('td');
|
|
|
+ const subKeyTd = document.createElement("td");
|
|
|
subKeyTd.textContent = fieldKeyMap[subKey] || subKey;
|
|
|
|
|
|
- const valTd = document.createElement('td');
|
|
|
+ const valTd = document.createElement("td");
|
|
|
valTd.textContent = metricVal[subKey];
|
|
|
|
|
|
tr.appendChild(subKeyTd);
|
|
@@ -133,12 +136,12 @@ export default {
|
|
|
tbody.appendChild(tr);
|
|
|
});
|
|
|
} else {
|
|
|
- const tr = document.createElement('tr');
|
|
|
- const nameTd = document.createElement('td');
|
|
|
+ const tr = document.createElement("tr");
|
|
|
+ const nameTd = document.createElement("td");
|
|
|
nameTd.textContent = metricLabel;
|
|
|
- const subKeyTd = document.createElement('td');
|
|
|
- subKeyTd.textContent = '';
|
|
|
- const valTd = document.createElement('td');
|
|
|
+ const subKeyTd = document.createElement("td");
|
|
|
+ subKeyTd.textContent = "";
|
|
|
+ const valTd = document.createElement("td");
|
|
|
valTd.textContent = metricVal;
|
|
|
|
|
|
tr.appendChild(nameTd);
|
|
@@ -147,10 +150,10 @@ export default {
|
|
|
tbody.appendChild(tr);
|
|
|
}
|
|
|
});
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
@@ -158,80 +161,84 @@ export default {
|
|
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
-moz-osx-font-smoothing: grayscale;
|
|
|
+}
|
|
|
+
|
|
|
+.site-test {
|
|
|
text-align: center;
|
|
|
color: #2c3e50;
|
|
|
margin-top: 60px;
|
|
|
+}
|
|
|
+.test-type-select {
|
|
|
+ padding: 8px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ width: 120px;
|
|
|
+ height: 40px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
|
|
|
- .test-type-select {
|
|
|
- padding: 8px;
|
|
|
- margin-bottom: 10px;
|
|
|
- width: 120px;
|
|
|
- height: 40px;
|
|
|
- border: 1px solid #ccc;
|
|
|
- border-radius: 4px;
|
|
|
- }
|
|
|
-
|
|
|
- .test-type-select1 {
|
|
|
- padding: 8px;
|
|
|
- margin-bottom: 10px;
|
|
|
- width: 80px;
|
|
|
- height: 40px;
|
|
|
- border: 1px solid #ccc;
|
|
|
- border-radius: 4px;
|
|
|
- margin-left: 20px;
|
|
|
- }
|
|
|
+.test-type-select1 {
|
|
|
+ padding: 8px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ width: 80px;
|
|
|
+ height: 40px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
|
|
|
- input {
|
|
|
- width: 400px;
|
|
|
- height: 23px;
|
|
|
- padding: 8px;
|
|
|
- border: 1px solid #ccc;
|
|
|
- border-radius: 4px;
|
|
|
- margin-left: 5px;
|
|
|
- }
|
|
|
+input {
|
|
|
+ width: 400px;
|
|
|
+ height: 23px;
|
|
|
+ padding: 8px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-left: 5px;
|
|
|
+}
|
|
|
|
|
|
- button {
|
|
|
- margin-left: 10px;
|
|
|
- padding: 8px 16px;
|
|
|
- background-color: #42b983;
|
|
|
- color: white;
|
|
|
- border: none;
|
|
|
- border-radius: 4px;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
+button {
|
|
|
+ margin-left: 10px;
|
|
|
+ padding: 8px 16px;
|
|
|
+ background-color: #42b983;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
|
|
|
- button:hover {
|
|
|
- background-color: #3aa876;
|
|
|
- }
|
|
|
+button:hover {
|
|
|
+ background-color: #3aa876;
|
|
|
+}
|
|
|
|
|
|
- .table-content {
|
|
|
- width: 100%;
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- }
|
|
|
+.table-content {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
|
|
|
- table.k6-table {
|
|
|
- width: 60%;
|
|
|
- border-collapse: collapse;
|
|
|
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial;
|
|
|
- font-size: 14px;
|
|
|
- margin-top: 20px;
|
|
|
- }
|
|
|
+table.k6-table {
|
|
|
+ width: 60%;
|
|
|
+ border-collapse: collapse;
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
|
+ "Helvetica Neue", Arial;
|
|
|
+ font-size: 14px;
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
|
|
|
- table.k6-table thead {
|
|
|
- background-color: #f7f7f7;
|
|
|
- }
|
|
|
+table.k6-table thead {
|
|
|
+ background-color: #f7f7f7;
|
|
|
+}
|
|
|
|
|
|
- table.k6-table th,
|
|
|
- table.k6-table td {
|
|
|
- border: 1px solid #ddd;
|
|
|
- padding: 10px 12px;
|
|
|
- color: #000;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
+table.k6-table th,
|
|
|
+table.k6-table td {
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ padding: 10px 12px;
|
|
|
+ color: #000;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
|
|
|
- /* table.k6-table th {
|
|
|
+/* table.k6-table th {
|
|
|
text-align: center;
|
|
|
font-weight: 600;
|
|
|
}
|
|
@@ -253,8 +260,7 @@ export default {
|
|
|
color: #000;
|
|
|
} */
|
|
|
|
|
|
- table.k6-table tbody tr:hover {
|
|
|
- background-color: #f0f8ff;
|
|
|
- }
|
|
|
+table.k6-table tbody tr:hover {
|
|
|
+ background-color: #f0f8ff;
|
|
|
}
|
|
|
</style>
|