Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
5a385c6d34
|
@ -6,11 +6,11 @@ ARG MS_VERSION=dev
|
|||
|
||||
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/
|
||||
|
||||
ENV JAVA_APP_JAR=/opt/apps/backend-1.1.jar
|
||||
ENV JAVA_APP_JAR=/opt/apps/backend-1.3.jar
|
||||
|
||||
ENV AB_OFF=true
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>metersphere-server</artifactId>
|
||||
<groupId>io.metersphere</groupId>
|
||||
<version>1.1</version>
|
||||
<version>1.3</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestCaseReviewMapper">
|
||||
|
||||
<select id="list" resultType="io.metersphere.track.dto.TestCaseReviewDTO" parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
|
||||
select distinct test_case_review.*
|
||||
from test_case_review, project, test_case_review_project
|
||||
<select id="list" resultType="io.metersphere.track.dto.TestCaseReviewDTO"
|
||||
parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
|
||||
select distinct test_case_review.id, test_case_review.name, user.name as creator, test_case_review.status,
|
||||
test_case_review.create_time, test_case_review.update_time, test_case_review.end_time,
|
||||
test_case_review.description
|
||||
from test_case_review, project, test_case_review_project, user
|
||||
<where>
|
||||
test_case_review.id = test_case_review_project.review_id
|
||||
and test_case_review_project.project_id = project.id
|
||||
and user.id = test_case_review.creator
|
||||
<if test="request.name != null">
|
||||
and test_case_review.name like CONCAT('%', #{request.name},'%')
|
||||
</if>
|
||||
|
@ -21,7 +25,8 @@
|
|||
</if>
|
||||
</select>
|
||||
|
||||
<select id="listByWorkspaceId" resultType="io.metersphere.track.dto.TestCaseReviewDTO" parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
|
||||
<select id="listByWorkspaceId" resultType="io.metersphere.track.dto.TestCaseReviewDTO"
|
||||
parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
|
||||
select distinct test_case_review.*
|
||||
from test_case_review, project, test_case_review_project
|
||||
where test_case_review.id = test_case_review_project.review_id
|
||||
|
|
|
@ -67,7 +67,7 @@ public class TestCaseReviewController {
|
|||
|
||||
@PostMapping("/edit")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public void editCaseReview(@RequestBody TestCaseReview testCaseReview) {
|
||||
public void editCaseReview(@RequestBody SaveTestCaseReviewRequest testCaseReview) {
|
||||
testCaseReviewService.editCaseReview(testCaseReview);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.apache.ibatis.session.SqlSession;
|
|||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -54,6 +56,10 @@ public class TestCaseReviewService {
|
|||
ExtProjectMapper extProjectMapper;
|
||||
@Resource
|
||||
UserService userService;
|
||||
@Resource
|
||||
TestCaseMapper testCaseMapper;
|
||||
@Resource
|
||||
TestCaseReviewTestCaseMapper testCaseReviewTestCaseMapper;
|
||||
|
||||
public void saveTestCaseReview(SaveTestCaseReviewRequest reviewRequest) {
|
||||
checkCaseReviewExist(reviewRequest);
|
||||
|
@ -119,20 +125,87 @@ public class TestCaseReviewService {
|
|||
.collect(Collectors.toList());
|
||||
|
||||
UserExample userExample = new UserExample();
|
||||
userExample.createCriteria().andIdIn(userIds);
|
||||
return userMapper.selectByExample(userExample);
|
||||
UserExample.Criteria criteria = userExample.createCriteria();
|
||||
if (!CollectionUtils.isEmpty(userIds)) {
|
||||
criteria.andIdIn(userIds);
|
||||
return userMapper.selectByExample(userExample);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<TestCaseReviewDTO> recent(String currentWorkspaceId) {
|
||||
return extTestCaseReviewMapper.listByWorkspaceId(currentWorkspaceId);
|
||||
}
|
||||
|
||||
public void editCaseReview(TestCaseReview testCaseReview) {
|
||||
public void editCaseReview(SaveTestCaseReviewRequest testCaseReview) {
|
||||
editCaseReviewer(testCaseReview);
|
||||
editCaseReviewProject(testCaseReview);
|
||||
testCaseReview.setUpdateTime(System.currentTimeMillis());
|
||||
checkCaseReviewExist(testCaseReview);
|
||||
testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview);
|
||||
}
|
||||
|
||||
private void editCaseReviewer(SaveTestCaseReviewRequest testCaseReview) {
|
||||
// 要更新的reviewerIds
|
||||
List<String> reviewerIds = testCaseReview.getUserIds();
|
||||
|
||||
String id = testCaseReview.getId();
|
||||
TestCaseReviewUsersExample testCaseReviewUsersExample = new TestCaseReviewUsersExample();
|
||||
testCaseReviewUsersExample.createCriteria().andReviewIdEqualTo(id);
|
||||
List<TestCaseReviewUsers> testCaseReviewUsers = testCaseReviewUsersMapper.selectByExample(testCaseReviewUsersExample);
|
||||
List<String> dbReviewIds = testCaseReviewUsers.stream().map(TestCaseReviewUsers::getUserId).collect(Collectors.toList());
|
||||
|
||||
reviewerIds.forEach(reviewerId -> {
|
||||
if (!dbReviewIds.contains(reviewerId)) {
|
||||
TestCaseReviewUsers caseReviewUser = new TestCaseReviewUsers();
|
||||
caseReviewUser.setUserId(reviewerId);
|
||||
caseReviewUser.setReviewId(id);
|
||||
testCaseReviewUsersMapper.insertSelective(caseReviewUser);
|
||||
}
|
||||
});
|
||||
|
||||
TestCaseReviewUsersExample example = new TestCaseReviewUsersExample();
|
||||
example.createCriteria().andReviewIdEqualTo(id).andUserIdNotIn(reviewerIds);
|
||||
testCaseReviewUsersMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
private void editCaseReviewProject(SaveTestCaseReviewRequest testCaseReview) {
|
||||
List<String> projectIds = testCaseReview.getProjectIds();
|
||||
String id = testCaseReview.getId();
|
||||
if (!CollectionUtils.isEmpty(projectIds)) {
|
||||
TestCaseReviewProjectExample testCaseReviewProjectExample = new TestCaseReviewProjectExample();
|
||||
testCaseReviewProjectExample.createCriteria().andReviewIdEqualTo(id);
|
||||
List<TestCaseReviewProject> testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(testCaseReviewProjectExample);
|
||||
List<String> dbProjectIds = testCaseReviewProjects.stream().map(TestCaseReviewProject::getProjectId).collect(Collectors.toList());
|
||||
projectIds.forEach(projectId -> {
|
||||
if (!dbProjectIds.contains(projectId)) {
|
||||
TestCaseReviewProject testCaseReviewProject = new TestCaseReviewProject();
|
||||
testCaseReviewProject.setReviewId(id);
|
||||
testCaseReviewProject.setProjectId(projectId);
|
||||
testCaseReviewProjectMapper.insert(testCaseReviewProject);
|
||||
}
|
||||
});
|
||||
|
||||
TestCaseReviewProjectExample example = new TestCaseReviewProjectExample();
|
||||
example.createCriteria().andReviewIdEqualTo(id).andProjectIdNotIn(projectIds);
|
||||
testCaseReviewProjectMapper.deleteByExample(example);
|
||||
|
||||
|
||||
// 关联的项目下的用例idList
|
||||
TestCaseExample testCaseExample = new TestCaseExample();
|
||||
testCaseExample.createCriteria().andProjectIdIn(projectIds);
|
||||
List<TestCase> caseList = testCaseMapper.selectByExample(testCaseExample);
|
||||
List<String> caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList());
|
||||
|
||||
TestCaseReviewTestCaseExample testCaseReviewTestCaseExample = new TestCaseReviewTestCaseExample();
|
||||
TestCaseReviewTestCaseExample.Criteria criteria = testCaseReviewTestCaseExample.createCriteria().andReviewIdEqualTo(id);
|
||||
if (!CollectionUtils.isEmpty(caseIds)) {
|
||||
criteria.andCaseIdNotIn(caseIds);
|
||||
}
|
||||
testCaseReviewTestCaseMapper.deleteByExample(testCaseReviewTestCaseExample);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCaseReviewExist(TestCaseReview testCaseReview) {
|
||||
if (testCaseReview.getName() != null) {
|
||||
TestCaseReviewExample example = new TestCaseReviewExample();
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 321c869938357e8c2253e5bd86c963828664ae23
|
||||
Subproject commit d5b4969642fd8d10cc2f949d7377e0a0e5217a3a
|
|
@ -30,7 +30,9 @@
|
|||
"md5": "^2.3.0",
|
||||
"sha.js": "^2.4.11",
|
||||
"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": {
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>metersphere-server</artifactId>
|
||||
<groupId>io.metersphere</groupId>
|
||||
<version>1.1</version>
|
||||
<version>1.3</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -96,8 +96,7 @@
|
|||
<div>{{ $t('load_test.response_timeout') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number :disabled="readOnly" size="mini" v-model="responseTimeout" :min="10"
|
||||
:max="100000"></el-input-number>
|
||||
<el-input-number :disabled="readOnly" size="mini" v-model="responseTimeout"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
ms
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
|
||||
<!--报告-->
|
||||
<div v-if="metric">
|
||||
<base-info-component :report-info="metric" v-if="preview.id == 1"/>
|
||||
<test-result-component :test-results="metric.moduleExecuteResult" v-if="preview.id == 2"/>
|
||||
<test-result-chart-component :execute-result="metric.executeResult" v-if="preview.id == 3"/>
|
||||
<failure-result-component :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>
|
||||
<defect-list-component :defect-list="metric.issues" v-if="preview.id == 5"/>
|
||||
<rich-text-component :is-report-view="isReportView" :preview="preview" v-if="preview.type != 'system'"/>
|
||||
<base-info-component id="baseInfoComponent" :report-info="metric" v-if="preview.id == 1"/>
|
||||
<test-result-component id="testResultComponent" :test-results="metric.moduleExecuteResult" v-if="preview.id == 2"/>
|
||||
<test-result-chart-component id="resultChartComponent" :execute-result="metric.executeResult" v-if="preview.id == 3"/>
|
||||
<failure-result-component id="failureResultComponent" :failure-test-cases="metric.failureTestCases" v-if="preview.id == 4"/>
|
||||
<defect-list-component id="defectListComponent" :defect-list="metric.issues" v-if="preview.id == 5"/>
|
||||
<rich-text-component id="richTextComponent" :is-report-view="isReportView" :preview="preview" v-if="preview.type != 'system'"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -31,6 +31,8 @@
|
|||
import RichTextComponent from "./RichTextComponent";
|
||||
import FailureResultComponent from "./FailureResultComponent";
|
||||
import DefectListComponent from "./DefectListComponent";
|
||||
import html2canvas from 'html2canvas';
|
||||
|
||||
export default {
|
||||
name: "TemplateComponent",
|
||||
components: {
|
||||
|
@ -51,6 +53,41 @@
|
|||
type: Boolean,
|
||||
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>
|
||||
|
|
|
@ -25,38 +25,33 @@
|
|||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleEdit">
|
||||
{{$t('test_track.plan_view.edit_component')}}
|
||||
</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')}}
|
||||
</el-button>-->
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="container" ref="resume" id="app">
|
||||
<el-main>
|
||||
<div class="preview" v-for="item in previews" :key="item.id">
|
||||
<template-component :isReportView="true" :metric="metric" :preview="item"/>
|
||||
<div v-for="(item, index) in previews" :key="item.id" id="reportViewpp">
|
||||
<template-component :isReportView="true" :metric="metric" :preview="item" :index="index" ref="templateComponent"/>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
<test-case-report-template-edit :metric="metric" ref="templateEdit" @refresh="getReport"/>
|
||||
<!-- <script>
|
||||
|
||||
</script>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {checkoutTestManagerOrTestUser, jsonToMap, mapToJson} from "../../../../../../../common/js/utils";
|
||||
import {checkoutTestManagerOrTestUser, exportPdf, jsonToMap, mapToJson} from "../../../../../../../common/js/utils";
|
||||
import BaseInfoComponent from "./TemplateComponent/BaseInfoComponent";
|
||||
import TestResultChartComponent from "./TemplateComponent/TestResultChartComponent";
|
||||
import TestResultComponent from "./TemplateComponent/TestResultComponent";
|
||||
import RichTextComponent from "./TemplateComponent/RichTextComponent";
|
||||
import TestCaseReportTemplateEdit from "./TestCaseReportTemplateEdit";
|
||||
import TemplateComponent from "./TemplateComponent/TemplateComponent";
|
||||
import writer from 'file-writer'
|
||||
import ReportStyle from "../../../../../../../common/css/report.css.js";
|
||||
|
||||
export default {
|
||||
name: "TestCaseReportView",
|
||||
|
@ -178,7 +173,7 @@
|
|||
},
|
||||
getMetric() {
|
||||
this.result = this.$get('/test/plan/get/metric/' + this.planId, response => {
|
||||
this.metric = response.data
|
||||
this.metric = response.data;
|
||||
|
||||
if (!this.metric.failureTestCases) {
|
||||
this.metric.failureTestCases = [];
|
||||
|
@ -205,31 +200,22 @@
|
|||
},
|
||||
/*导出报告*/
|
||||
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>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<el-col :span="11" :offset="2">
|
||||
<el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectIds">
|
||||
<el-select
|
||||
:disabled="(form.status == null) ? false : true"
|
||||
v-model="form.projectIds"
|
||||
:placeholder="$t('test_track.plan.input_plan_project')"
|
||||
multiple
|
||||
|
@ -45,13 +44,12 @@
|
|||
|
||||
<el-row>
|
||||
<el-col :span="10" :offset="1">
|
||||
<el-form-item label="评审人" :label-width="formLabelWidth" prop="principal">
|
||||
<el-form-item label="评审人" :label-width="formLabelWidth" prop="userIds">
|
||||
<el-select
|
||||
v-model="form.userIds"
|
||||
placeholder="请选择评审人"
|
||||
filterable multiple
|
||||
collapse-tags
|
||||
:disabled="(form.status == null) ? false : true"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in reviewerOptions"
|
||||
|
@ -132,6 +130,7 @@ export default {
|
|||
description: '',
|
||||
endTime: ''
|
||||
},
|
||||
dbProjectIds: [],
|
||||
rules: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.plan.input_plan_name'), trigger: 'blur'},
|
||||
|
@ -161,6 +160,7 @@ export default {
|
|||
let tmp = {};
|
||||
Object.assign(tmp, caseReview);
|
||||
Object.assign(this.form, tmp);
|
||||
this.dbProjectIds = JSON.parse(JSON.stringify(this.form.projectIds));
|
||||
}
|
||||
listenGoBack(this.close);
|
||||
this.dialogFormVisible = true;
|
||||
|
@ -178,16 +178,44 @@ export default {
|
|||
if (this.operationType === 'save') {
|
||||
this.compareTime(new Date().getTime(), this.form.endTime);
|
||||
}
|
||||
this.$post('/test/case/review/' + this.operationType, param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.dialogFormVisible = false;
|
||||
this.$emit("refresh");
|
||||
});
|
||||
|
||||
if (this.operationType === 'edit') {
|
||||
const nowIds = param.projectIds;
|
||||
let sign = true;
|
||||
this.dbProjectIds.forEach(dbId => {
|
||||
if (nowIds.indexOf(dbId) === -1 && sign) {
|
||||
sign = false;
|
||||
this.$confirm('取消项目关联会同时取消该项目下已关联的测试用例', '提示', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.editTestReview(param);
|
||||
}).catch(() => {
|
||||
this.$info(this.$t('commons.cancel'))
|
||||
});
|
||||
}
|
||||
});
|
||||
if (sign) {
|
||||
this.editTestReview(param);
|
||||
}
|
||||
} else {
|
||||
this.editTestReview(param);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
editTestReview(param) {
|
||||
this.$post('/test/case/review/' + this.operationType, param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.dialogFormVisible = false;
|
||||
this.$emit("refresh");
|
||||
});
|
||||
},
|
||||
getProjects() {
|
||||
this.result = this.$get("/project/listAll", (response) => {
|
||||
if (response.success) {
|
||||
|
@ -204,7 +232,8 @@ export default {
|
|||
});
|
||||
},
|
||||
statusChange(status) {
|
||||
|
||||
this.form.status = status;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
close() {
|
||||
removeGoBackListener(this.close);
|
||||
|
|
|
@ -37,42 +37,14 @@
|
|||
<el-table-column
|
||||
prop="status"
|
||||
column-key="status"
|
||||
:filters="statusFilters"
|
||||
:label="$t('test_track.plan.plan_status')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span @click.stop="clickt = 'stop'">
|
||||
<el-dropdown class="test-case-status" @command="statusChange">
|
||||
<span class="el-dropdown-link">
|
||||
<plan-status-table-item :value="scope.row.status"/>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown" chang>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Prepare'}">
|
||||
{{ $t('test_track.plan.plan_status_prepare') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Underway'}">
|
||||
{{ $t('test_track.plan.plan_status_running') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Completed'}">
|
||||
{{ $t('test_track.plan.plan_status_completed') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
<plan-status-table-item :value="scope.row.status"/>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="reviewerSize"-->
|
||||
<!-- label="已评"-->
|
||||
<!-- show-overflow-tooltip>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="resultMap"-->
|
||||
<!-- label="结果分布"-->
|
||||
<!-- show-overflow-tooltip>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
|
@ -94,10 +66,10 @@
|
|||
<template v-slot:default="scope">
|
||||
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
||||
@deleteClick="handleDelete(scope.row)">
|
||||
<template v-slot:middle>
|
||||
<ms-table-operator-button :isTesterPermission="true" type="success" tip="重新发起" icon="el-icon-document"
|
||||
@exec="reCreate(scope.row)"/>
|
||||
</template>
|
||||
<!-- <template v-slot:middle>-->
|
||||
<!-- <ms-table-operator-button :isTesterPermission="true" type="success" tip="重新发起" icon="el-icon-document"-->
|
||||
<!-- @exec="reCreate(scope.row)"/>-->
|
||||
<!-- </template>-->
|
||||
</ms-table-operator>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -105,7 +77,7 @@
|
|||
|
||||
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
<ms-delete-confirm title="删除用例评审" @delete="_handleDelete" ref="deleteConfirm"/>
|
||||
<ms-delete-confirm title="取消用例关联" @delete="_handleDelete" ref="deleteConfirm"/>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
|
@ -217,9 +189,6 @@ export default {
|
|||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
reCreate() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -95,37 +95,6 @@
|
|||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
:label="$t('test_track.issue.issue')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="right"
|
||||
width="400"
|
||||
trigger="hover">
|
||||
<el-table border class="adjust-table" :data="scope.row.issuesContent" style="width: 100%">
|
||||
<el-table-column prop="title" :label="$t('test_track.issue.title')" show-overflow-tooltip/>
|
||||
<el-table-column prop="description" :label="$t('test_track.issue.description')">
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="left"
|
||||
width="400"
|
||||
trigger="hover"
|
||||
>
|
||||
<ckeditor :editor="editor" disabled :config="editorConfig"
|
||||
v-model="scope.row.description"/>
|
||||
<el-button slot="reference" type="text">{{$t('test_track.issue.preview')}}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
||||
</el-table>
|
||||
<el-button slot="reference" type="text">{{scope.row.issuesSize}}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
<el-table-column
|
||||
prop="reviewerName"
|
||||
label="评审人"
|
||||
|
@ -139,20 +108,8 @@
|
|||
column-key="status"
|
||||
:label="$t('test_track.plan_view.execute_result')">
|
||||
<template v-slot:default="scope">
|
||||
<span @click.stop="clickt = 'stop'">
|
||||
<el-dropdown class="test-case-status" @command="statusChange">
|
||||
<span class="el-dropdown-link">
|
||||
<status-table-item :value="scope.row.status"/>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown" chang>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Pass'}">
|
||||
{{$t('test_track.plan_view.pass')}}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'UnPass'}">
|
||||
未通过
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
<status-table-item :value="scope.row.status"/>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -320,18 +277,6 @@ export default {
|
|||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", 0);
|
||||
this.$get("/issues/get/" + this.tableData[i].caseId, response => {
|
||||
let issues = response.data;
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", issues.length);
|
||||
this.$set(this.tableData[i], "issuesContent", issues);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
this.selectRows.clear();
|
||||
});
|
||||
}
|
||||
|
@ -502,6 +447,7 @@ export default {
|
|||
},
|
||||
startReview() {
|
||||
if (this.tableData.length !== 0) {
|
||||
this.isReadOnly = false;
|
||||
this.$refs.testReviewTestCaseEdit.openTestCaseEdit(this.tableData[0]);
|
||||
} else {
|
||||
this.$warning("没有关联的评审!");
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f2d5a342c82e629f510550d5778d752bb73bf5e7
|
||||
Subproject commit 0a375848d034d20eaf05caf11769e1c75c39235c
|
|
@ -9,6 +9,7 @@ import {
|
|||
LicenseKey
|
||||
} from "./constants";
|
||||
import axios from "axios";
|
||||
import {jsPDF} from "jspdf";
|
||||
|
||||
export function hasRole(role) {
|
||||
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');
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue