Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
c91ef4b982
|
@ -6,11 +6,11 @@ ARG MS_VERSION=dev
|
||||||
|
|
||||||
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter
|
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter
|
||||||
|
|
||||||
ADD backend/target/backend-1.1.jar /opt/apps
|
ADD backend/target/backend-1.3.jar /opt/apps
|
||||||
|
|
||||||
ADD backend/target/classes/jmeter/ /opt/jmeter/
|
ADD backend/target/classes/jmeter/ /opt/jmeter/
|
||||||
|
|
||||||
ENV JAVA_APP_JAR=/opt/apps/backend-1.1.jar
|
ENV JAVA_APP_JAR=/opt/apps/backend-1.3.jar
|
||||||
|
|
||||||
ENV AB_OFF=true
|
ENV AB_OFF=true
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 321c869938357e8c2253e5bd86c963828664ae23
|
Subproject commit d5b4969642fd8d10cc2f949d7377e0a0e5217a3a
|
|
@ -30,7 +30,9 @@
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"sha.js": "^2.4.11",
|
"sha.js": "^2.4.11",
|
||||||
"js-base64": "^3.4.4",
|
"js-base64": "^3.4.4",
|
||||||
"json-bigint": "^1.0.0"
|
"json-bigint": "^1.0.0",
|
||||||
|
"html2canvas": "^1.0.0-rc.7",
|
||||||
|
"jspdf": "^2.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.1.0",
|
"@vue/cli-plugin-babel": "^4.1.0",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -96,8 +96,7 @@
|
||||||
<div>{{ $t('load_test.response_timeout') }}</div>
|
<div>{{ $t('load_test.response_timeout') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-input-number :disabled="readOnly" size="mini" v-model="responseTimeout" :min="10"
|
<el-input-number :disabled="readOnly" size="mini" v-model="responseTimeout"></el-input-number>
|
||||||
:max="100000"></el-input-number>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
ms
|
ms
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
|
|
||||||
<!--报告-->
|
<!--报告-->
|
||||||
<div v-if="metric">
|
<div v-if="metric">
|
||||||
<base-info-component :report-info="metric" v-if="preview.id == 1"/>
|
<base-info-component id="baseInfoComponent" :report-info="metric" v-if="preview.id == 1"/>
|
||||||
<test-result-component :test-results="metric.moduleExecuteResult" v-if="preview.id == 2"/>
|
<test-result-component id="testResultComponent" :test-results="metric.moduleExecuteResult" v-if="preview.id == 2"/>
|
||||||
<test-result-chart-component :execute-result="metric.executeResult" v-if="preview.id == 3"/>
|
<test-result-chart-component id="resultChartComponent" :execute-result="metric.executeResult" v-if="preview.id == 3"/>
|
||||||
<failure-result-component :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>
|
<failure-result-component id="failureResultComponent" :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>
|
||||||
<defect-list-component :defect-list="metric.issues" v-if="preview.id == 5"/>
|
<defect-list-component id="defectListComponent" :defect-list="metric.issues" v-if="preview.id == 5"/>
|
||||||
<rich-text-component :is-report-view="isReportView" :preview="preview" v-if="preview.type != 'system'"/>
|
<rich-text-component id="richTextComponent" :is-report-view="isReportView" :preview="preview" v-if="preview.type != 'system'"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,8 @@
|
||||||
import RichTextComponent from "./RichTextComponent";
|
import RichTextComponent from "./RichTextComponent";
|
||||||
import FailureResultComponent from "./FailureResultComponent";
|
import FailureResultComponent from "./FailureResultComponent";
|
||||||
import DefectListComponent from "./DefectListComponent";
|
import DefectListComponent from "./DefectListComponent";
|
||||||
|
import html2canvas from 'html2canvas';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TemplateComponent",
|
name: "TemplateComponent",
|
||||||
components: {
|
components: {
|
||||||
|
@ -51,6 +53,41 @@
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getCanvas(canvasList) {
|
||||||
|
let index = this.index;
|
||||||
|
let componentId = this.getComponentId();
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
html2canvas(document.getElementById(componentId), {
|
||||||
|
scale: 2
|
||||||
|
}).then(function(canvas) {
|
||||||
|
//排序
|
||||||
|
canvasList.splice(index, 0, canvas);
|
||||||
|
resolve('success');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getComponentId() {
|
||||||
|
switch (this.preview.id) {
|
||||||
|
case 1:
|
||||||
|
return "baseInfoComponent";
|
||||||
|
case 2:
|
||||||
|
return "testResultComponent";
|
||||||
|
case 3:
|
||||||
|
return "resultChartComponent";
|
||||||
|
case 4:
|
||||||
|
return "failureResultComponent";
|
||||||
|
case 5:
|
||||||
|
return "defectListComponent";
|
||||||
|
default:
|
||||||
|
return "richTextComponent";
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,38 +25,33 @@
|
||||||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleEdit">
|
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleEdit">
|
||||||
{{$t('test_track.plan_view.edit_component')}}
|
{{$t('test_track.plan_view.edit_component')}}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!--<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExport(report.name)">
|
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExport(report.name)">
|
||||||
{{$t('test_track.plan_view.export_report')}}
|
{{$t('test_track.plan_view.export_report')}}
|
||||||
</el-button>-->
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<div class="container" ref="resume" id="app">
|
<div class="container" ref="resume" id="app">
|
||||||
<el-main>
|
<el-main>
|
||||||
<div class="preview" v-for="item in previews" :key="item.id">
|
<div v-for="(item, index) in previews" :key="item.id" id="reportViewpp">
|
||||||
<template-component :isReportView="true" :metric="metric" :preview="item"/>
|
<template-component :isReportView="true" :metric="metric" :preview="item" :index="index" ref="templateComponent"/>
|
||||||
</div>
|
</div>
|
||||||
</el-main>
|
</el-main>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<test-case-report-template-edit :metric="metric" ref="templateEdit" @refresh="getReport"/>
|
<test-case-report-template-edit :metric="metric" ref="templateEdit" @refresh="getReport"/>
|
||||||
<!-- <script>
|
|
||||||
|
|
||||||
</script>-->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {checkoutTestManagerOrTestUser, jsonToMap, mapToJson} from "../../../../../../../common/js/utils";
|
import {checkoutTestManagerOrTestUser, exportPdf, jsonToMap, mapToJson} from "../../../../../../../common/js/utils";
|
||||||
import BaseInfoComponent from "./TemplateComponent/BaseInfoComponent";
|
import BaseInfoComponent from "./TemplateComponent/BaseInfoComponent";
|
||||||
import TestResultChartComponent from "./TemplateComponent/TestResultChartComponent";
|
import TestResultChartComponent from "./TemplateComponent/TestResultChartComponent";
|
||||||
import TestResultComponent from "./TemplateComponent/TestResultComponent";
|
import TestResultComponent from "./TemplateComponent/TestResultComponent";
|
||||||
import RichTextComponent from "./TemplateComponent/RichTextComponent";
|
import RichTextComponent from "./TemplateComponent/RichTextComponent";
|
||||||
import TestCaseReportTemplateEdit from "./TestCaseReportTemplateEdit";
|
import TestCaseReportTemplateEdit from "./TestCaseReportTemplateEdit";
|
||||||
import TemplateComponent from "./TemplateComponent/TemplateComponent";
|
import TemplateComponent from "./TemplateComponent/TemplateComponent";
|
||||||
import writer from 'file-writer'
|
|
||||||
import ReportStyle from "../../../../../../../common/css/report.css.js";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseReportView",
|
name: "TestCaseReportView",
|
||||||
|
@ -178,7 +173,7 @@
|
||||||
},
|
},
|
||||||
getMetric() {
|
getMetric() {
|
||||||
this.result = this.$get('/test/plan/get/metric/' + this.planId, response => {
|
this.result = this.$get('/test/plan/get/metric/' + this.planId, response => {
|
||||||
this.metric = response.data
|
this.metric = response.data;
|
||||||
|
|
||||||
if (!this.metric.failureTestCases) {
|
if (!this.metric.failureTestCases) {
|
||||||
this.metric.failureTestCases = [];
|
this.metric.failureTestCases = [];
|
||||||
|
@ -205,31 +200,22 @@
|
||||||
},
|
},
|
||||||
/*导出报告*/
|
/*导出报告*/
|
||||||
handleExport(name) {
|
handleExport(name) {
|
||||||
let html = this.getHtml();
|
|
||||||
writer(`${name}.html`, html, 'utf-8');
|
|
||||||
console.log(html)
|
|
||||||
},
|
|
||||||
getHtml() {
|
|
||||||
let template = this.$refs.resume.innerHTML;
|
|
||||||
let html = `<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<title>html</title>
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
|
||||||
<style>${ReportStyle}</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div style="margin:0 auto;width:1200px">
|
|
||||||
${template}
|
|
||||||
</div>
|
|
||||||
<script src="https://cdn.bootcss.com/element-ui/2.4.11/index.js"/>
|
|
||||||
</body>
|
|
||||||
</html>`
|
|
||||||
return html
|
|
||||||
},
|
|
||||||
|
|
||||||
|
let result = this.result;
|
||||||
|
result.loading = true;
|
||||||
|
|
||||||
|
let promises = [];
|
||||||
|
let canvasList = new Array(this.previews.length);
|
||||||
|
|
||||||
|
for (let item of this.$refs.templateComponent) {
|
||||||
|
promises.push(item.getCanvas(canvasList));
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(promises).then(function (info) {
|
||||||
|
exportPdf(canvasList);
|
||||||
|
result.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f2d5a342c82e629f510550d5778d752bb73bf5e7
|
Subproject commit 0a375848d034d20eaf05caf11769e1c75c39235c
|
|
@ -9,6 +9,7 @@ import {
|
||||||
LicenseKey
|
LicenseKey
|
||||||
} from "./constants";
|
} from "./constants";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import {jsPDF} from "jspdf";
|
||||||
|
|
||||||
export function hasRole(role) {
|
export function hasRole(role) {
|
||||||
let user = getCurrentUser();
|
let user = getCurrentUser();
|
||||||
|
@ -203,3 +204,57 @@ export function getUUID() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function exportPdf(canvasList) {
|
||||||
|
|
||||||
|
let pdf = new jsPDF('', 'pt', 'a4');
|
||||||
|
|
||||||
|
// 当前页面的当前高度
|
||||||
|
let currentHeight = 0;
|
||||||
|
for (let canvas of canvasList) {
|
||||||
|
if (canvas) {
|
||||||
|
let contentWidth = canvas.width;
|
||||||
|
let contentHeight = canvas.height;
|
||||||
|
|
||||||
|
//a4纸的尺寸[595.28,841.89]
|
||||||
|
let a4Width = 592.28;
|
||||||
|
let a4Height = 841.89;
|
||||||
|
|
||||||
|
// html页面生成的canvas在pdf中图片的宽高
|
||||||
|
let imgWidth = a4Width;
|
||||||
|
let imgHeight = a4Width/contentWidth * contentHeight;
|
||||||
|
|
||||||
|
let pageData = canvas.toDataURL('image/jpeg', 1.0);
|
||||||
|
|
||||||
|
// 当前图片的剩余高度
|
||||||
|
let leftHeight = imgHeight;
|
||||||
|
|
||||||
|
// 当前页面的剩余高度
|
||||||
|
let blankHeight = a4Height - currentHeight;
|
||||||
|
|
||||||
|
if (leftHeight > blankHeight) {
|
||||||
|
//页面偏移
|
||||||
|
let position = 0;
|
||||||
|
while(leftHeight > 0) {
|
||||||
|
// 本次添加占用的高度
|
||||||
|
let occupation = a4Height - currentHeight;
|
||||||
|
pdf.addImage(pageData, 'JPEG', 0, position + currentHeight, imgWidth, imgHeight);
|
||||||
|
currentHeight = leftHeight;
|
||||||
|
leftHeight -= occupation;
|
||||||
|
position -= occupation;
|
||||||
|
//避免添加空白页
|
||||||
|
if(leftHeight > 0) {
|
||||||
|
pdf.addPage();
|
||||||
|
currentHeight = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pdf.addImage(pageData, 'JPEG', 0, currentHeight, imgWidth, imgHeight);
|
||||||
|
currentHeight += imgHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf.save('stone.pdf');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>io.metersphere</groupId>
|
<groupId>io.metersphere</groupId>
|
||||||
<artifactId>metersphere-server</artifactId>
|
<artifactId>metersphere-server</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
|
|
Loading…
Reference in New Issue