Merge remote-tracking branch 'origin/master'

This commit is contained in:
song.tianyang 2021-03-24 20:20:49 +08:00
commit 9d134f85a4
26 changed files with 257 additions and 118 deletions

View File

@ -6,11 +6,11 @@ ARG MS_VERSION=dev
RUN mkdir -p /opt/apps && mkdir -p /opt/jmeter/lib/junit
COPY backend/target/backend-1.7.jar /opt/apps
COPY backend/target/backend-1.8.jar /opt/apps
COPY backend/target/classes/jmeter/ /opt/jmeter/
ENV JAVA_APP_JAR=/opt/apps/backend-1.7.jar
ENV JAVA_APP_JAR=/opt/apps/backend-1.8.jar
ENV AB_OFF=true

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>metersphere-server</artifactId>
<groupId>io.metersphere</groupId>
<version>1.7</version>
<version>1.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -201,7 +201,7 @@ public class MsLoopController extends MsTestElement {
jsr223PreProcessor.setName("循环超时处理");
jsr223PreProcessor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
jsr223PreProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
jsr223PreProcessor.setProperty("cacheKey", "true");
/*jsr223PreProcessor.setProperty("cacheKey", "true");*/
jsr223PreProcessor.setProperty("scriptLanguage", "beanshell");
jsr223PreProcessor.setProperty("script", script());
hashTree.add(jsr223PreProcessor);

View File

@ -48,7 +48,7 @@ public class MsJSR223Processor extends MsTestElement {
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
processor.setProperty("cacheKey", "true");
/*processor.setProperty("cacheKey", "true");*/
processor.setProperty("scriptLanguage", this.getScriptLanguage());
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
processor.setProperty("scriptLanguage", "nashorn");

View File

@ -42,7 +42,7 @@ public class MsJSR223PostProcessor extends MsTestElement {
}
processor.setProperty(TestElement.TEST_CLASS, JSR223PostProcessor.class.getName());
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
processor.setProperty("cacheKey", "true");
/*processor.setProperty("cacheKey", "true");*/
processor.setProperty("scriptLanguage", this.getScriptLanguage());
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
processor.setProperty("scriptLanguage", "nashorn");

View File

@ -54,7 +54,7 @@ public class MsJSR223PreProcessor extends MsTestElement {
}
processor.setProperty(TestElement.TEST_CLASS, JSR223PreProcessor.class.getName());
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
processor.setProperty("cacheKey", "true");
/*processor.setProperty("cacheKey", "true");*/
processor.setProperty("scriptLanguage", this.getScriptLanguage());
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
processor.setProperty("scriptLanguage", "nashorn");

View File

@ -5,6 +5,7 @@ import io.metersphere.api.service.*;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.domain.ApiScenarioReport;
import io.metersphere.base.domain.ApiTestReport;
import io.metersphere.base.domain.TestPlanReport;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
@ -14,6 +15,7 @@ import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.service.TestPlanReportService;
import io.metersphere.track.service.TestPlanService;
import io.metersphere.track.service.TestPlanTestCaseService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

View File

@ -403,17 +403,24 @@ public class ApiDefinitionService {
private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) {
List<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
List<String> caseNames = apiTestCaseService.listPorjectAllCaseName(SessionUtils.getCurrentProjectId());
Set<String> existCaseName = new HashSet<>();
caseNames.forEach(item -> {
existCaseName.add(item);
});
if (CollectionUtils.isNotEmpty(cases)) {
int batchCount = 0;
cases.forEach(item -> {
item.setId(UUID.randomUUID().toString());
item.setCreateTime(System.currentTimeMillis());
item.setUpdateTime(System.currentTimeMillis());
item.setCreateUserId(SessionUtils.getUserId());
item.setUpdateUserId(SessionUtils.getUserId());
item.setProjectId(SessionUtils.getCurrentProjectId());
item.setNum(getNextNum(item.getApiDefinitionId()));
apiTestCaseMapper.insert(item);
if(!existCaseName.contains(item.getName())) {
item.setId(UUID.randomUUID().toString());
item.setCreateTime(System.currentTimeMillis());
item.setUpdateTime(System.currentTimeMillis());
item.setCreateUserId(SessionUtils.getUserId());
item.setUpdateUserId(SessionUtils.getUserId());
item.setProjectId(SessionUtils.getCurrentProjectId());
item.setNum(getNextNum(item.getApiDefinitionId()));
apiTestCaseMapper.insert(item);
}
});
if (batchCount % 300 == 0) {
sqlSession.flushStatements();
@ -628,12 +635,7 @@ public class ApiDefinitionService {
}
if (!CollectionUtils.isEmpty(apiImport.getCases())) {
for (int i = 0; i < apiImport.getCases().size(); i++) {
importMsCase(apiImport, sqlSession, apiTestCaseMapper);
if (i % 300 == 0) {
sqlSession.flushStatements();
}
}
importMsCase(apiImport, sqlSession, apiTestCaseMapper);
}
sqlSession.flushStatements();
}

View File

@ -80,6 +80,10 @@ public class ApiTestCaseService {
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
public List<String> listPorjectAllCaseName(String projectId) {
return extApiTestCaseMapper.listPorjectAllCaseName(projectId);
}
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);

View File

@ -12,6 +12,8 @@ import java.util.List;
public interface ExtApiTestCaseMapper {
List<String> listPorjectAllCaseName(@Param("projectId") String projectId);
List<ApiTestCaseResult> list(@Param("request") ApiTestCaseRequest request);
List<ApiTestCaseDTO> listSimple(@Param("request") ApiTestCaseRequest request);

View File

@ -391,6 +391,8 @@
<select id="getNextNum" resultType="io.metersphere.base.domain.ApiTestCase">
SELECT * FROM api_test_case WHERE api_test_case.api_definition_id = #{definitionId} ORDER BY num DESC LIMIT 1;
</select>
<select id="listPorjectAllCaseName" resultType="java.lang.String">
select name from api_test_case where project_id = #{projectId}
</select>
</mapper>

View File

@ -120,8 +120,8 @@ public class TestCaseController {
@PostMapping(value = "/add", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void addTestCase(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file") List<MultipartFile> files) {
testCaseService.save(request, files);
public String addTestCase(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file") List<MultipartFile> files) {
return testCaseService.save(request, files);
}
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})

View File

@ -192,3 +192,6 @@ CREATE TABLE IF NOT EXISTS test_case_test
alter table test_case
modify test_id varchar(2000) null;
-- update history data
update test_case set review_status = 'Prepare' where review_status is null;

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>metersphere-server</artifactId>
<groupId>io.metersphere</groupId>
<version>1.7</version>
<version>1.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -37,14 +37,19 @@
</div>
<!--最大化不显示具体内容-->
<div class="header" v-if="!isMax">
<fieldset :disabled="data.disabled" class="ms-fieldset">
<el-collapse-transition>
<div v-if="data.active && showCollapse" :draggable="draggable">
<el-divider></el-divider>
<el-collapse-transition>
<div v-if="data.active && showCollapse" :draggable="draggable">
<el-divider></el-divider>
<fieldset :disabled="data.disabled" class="ms-fieldset">
<!--四种协议请求内容-->
<slot name="request"></slot>
<!--其他模版内容比如断言提取等-->
<slot></slot>
</div>
</el-collapse-transition>
</fieldset>
</fieldset>
<!--四种协议执行结果内容-->
<slot name="result"></slot>
</div>
</el-collapse-transition>
</div>
</el-card>

View File

@ -27,48 +27,58 @@
</el-tooltip>
</template>
<customize-req-info :is-customize-req="isCustomizeReq" :request="request"/>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :isShowEnable="true" :referenced="true" :headers="request.headers " :request="request"
v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"/>
<esb-definition v-xpack :request="request" :showScript="false" v-if="this.showXpackCompnent&&request.esbDataStruct!=null" ref="esbDefinition"/>
<ms-tcp-basis-parameters :request="request" v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&&request.esbDataStruct==null " :showScript="false"/>
<ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
:showScript="false"/>
<ms-dubbo-basis-parameters :request="request"
v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
<!--请求内容-->
<template v-slot:request>
<customize-req-info :is-customize-req="isCustomizeReq" :request="request"/>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"
:isShowEnable="true"
:referenced="true"
:headers="request.headers "
:request="request"/>
<esb-definition v-if="showXpackCompnent&&request.esbDataStruct!=null"
v-xpack
:request="request"
:showScript="false"
ref="esbDefinition"/>
<ms-tcp-basis-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&&request.esbDataStruct==null "
:request="request"
:showScript="false"/>
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<div v-if="request.result">
<el-tabs v-model="request.activeName" closable class="ms-tabs">
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in request.result.scenarios" :key="index">
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
<api-response-component v-if="result.name===request.name" :result="result"/>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div v-else-if="showXpackCompnent&&request.backEsbDataStruct != null">
<esb-definition-response :currentProtocol="request.protocol" :request="request" :is-api-component="false"
:show-options-button="false" :show-header="true" :result="request.requestResult"/>
</div>
<div v-else>
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult"/>
</div>
<!-- 保存操作 -->
<el-button type="primary" size="small" class="ms-btn-flot" @click="saveTestCase(item)"
v-if="!request.referenced">
{{ $t('commons.save') }}
</el-button>
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
:request="request"
:showScript="false"/>
<ms-dubbo-basis-parameters v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
:request="request"
:showScript="false"/>
</template>
<!-- 执行结果内容 -->
<template v-slot:result>
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<div v-if="request.result">
<el-tabs v-model="request.activeName" closable class="ms-tabs">
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in request.result.scenarios" :key="index">
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
<api-response-component v-if="result.name===request.name" :result="result"/>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div v-else-if="showXpackCompnent&&request.backEsbDataStruct != null">
<esb-definition-response :currentProtocol="request.protocol" :request="request" :is-api-component="false"
:show-options-button="false" :show-header="true" :result="request.requestResult"/>
</div>
<div v-else>
<api-response-component :currentProtocol="request.protocol" :result="request.requestResult"/>
</div>
<!-- 保存操作 -->
<el-button type="primary" size="small" class="ms-btn-flot" @click="saveTestCase(item)" v-if="!request.referenced">
{{ $t('commons.save') }}
</el-button>
</template>
</api-base-component>
<ms-run :debug="true" :reportId="reportId" :run-data="runData" :env-map="envMap"
@runRefresh="runRefresh" ref="runTest"/>
</div>
</template>

View File

@ -122,6 +122,9 @@ export default {
this.$nextTick(() => {
this.isActive = true;
})
},
setJsonImport(data) {
this.importJson = data;
}
}
}

View File

@ -8,6 +8,7 @@
@setTreeNodes="setTreeNodes"
@exportTestCase="exportTestCase"
@saveAsEdit="editTestCase"
@createCase="handleCaseSimpleCreate($event, 'add')"
@refreshAll="refreshAll"
:type="'edit'"
ref="nodeTree"
@ -44,7 +45,7 @@
:tree-nodes="treeNodes"
:project-id="projectId"
v-if="activeDom === 'right'"
ref="testCaseList"/>
ref="minder"/>
</ms-tab-button>
</el-tab-pane>
<el-tab-pane
@ -58,6 +59,8 @@
:currentTestCaseInfo="item.testCaseInfo"
@refresh="refreshTable"
@setModuleOptions="setModuleOptions"
@caseEdit="handleCaseCreateOrEdit($event,'edit')"
@caseCreate="handleCaseCreateOrEdit($event,'add')"
:read-only="testCaseReadOnly"
:tree-nodes="treeNodes"
:select-node="selectNode"
@ -155,6 +158,11 @@ export default {
}
}
},
activeName(newVal, oldVal) {
if (oldVal !== 'default' && newVal === 'default' && this.$refs.minder) {
this.$refs.minder.refresh();
}
}
},
computed: {
checkRedirectID: function () {
@ -282,7 +290,9 @@ export default {
this.selectParentNodes = pNodes;
},
refreshTable() {
this.$refs.testCaseList.initTableData();
if ( this.$refs.testCaseList) {
this.$refs.testCaseList.initTableData();
}
},
editTestCase(testCase) {
this.type="edit"
@ -293,11 +303,20 @@ export default {
}
this.addTab({name: 'edit', testCaseInfo: testCase});
},
handleCaseCreateOrEdit(data, type) {
if (this.$refs.minder) {
this.$refs.minder.addCase(data, type);
}
},
handleCaseSimpleCreate(data, type) {
this.handleCaseCreateOrEdit(data, type);
if (this.$refs.minder) {
this.$refs.minder.refresh();
}
},
copyTestCase(testCase) {
this.type="copy"
this.testCaseReadOnly = false;
let item = {};
testCase.isCopy = true;
this.addTab({name: 'edit', testCaseInfo: testCase});
},

View File

@ -125,6 +125,7 @@ export default {
this.$emit('saveAsEdit', this.testCaseForm);
} else {
this.$emit('refresh');
this.$emit('createCase', this.testCaseForm);
}
})
} else {

View File

@ -109,7 +109,6 @@
class="ms-case" @change="clearInput" ref="cascade"></el-cascader>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="关联需求" :label-width="formLabelWidth" prop="demandId">
<el-select filterable :disabled="readOnly" v-model="form.demandId" @visible-change="visibleChange"
@ -404,7 +403,7 @@ export default {
type: String
},
computed: {
projectId() {
projectIds() {
return this.$store.state.projectId
},
},
@ -456,6 +455,7 @@ export default {
},
getTestOptions(val) {
this.form.type = val
this.projectId = this.projectIds
this.testOptions = [];
let url = '';
if (this.form.type === 'testcase' || this.form.type === 'automation') {
@ -556,6 +556,7 @@ export default {
/*
this.form.selected=[["automation", "3edaaf31-3fa4-4a53-9654-320205c2953a"],["automation", "3aa58bd1-c986-448c-8060-d32713dbd4eb"]]
*/
this.projectId = this.projectIds;
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', this.close);
@ -717,7 +718,7 @@ export default {
let param = this.buildParam();
if (this.validate(param)) {
let option = this.getOption(param);
this.result = this.$request(option, () => {
this.result = this.$request(option, (response) => {
this.$success(this.$t('commons.save_success'));
if (this.operationType == 'add' && this.isCreateContinue) {
this.form.name = '';
@ -736,6 +737,13 @@ export default {
}
this.dialogFormVisible = false;
this.$emit("refresh");
if (this.type === 'add' || this.type === 'copy') {
param.id = response.data;
this.$emit("caseCreate", param);
this.close();
} else {
this.$emit("caseEdit", param);
}
});
}
} else {

View File

@ -35,6 +35,7 @@
<test-case-create
:tree-nodes="treeNodes"
@saveAsEdit="saveAsEdit"
@createCase="createCase"
@refresh="refresh"
ref="testCaseCreate"
></test-case-create>
@ -98,6 +99,9 @@ export default {
saveAsEdit(data) {
this.$emit('saveAsEdit', data);
},
createCase(data) {
this.$emit('createCase', data);
},
refresh() {
this.$emit("refreshTable");
},

View File

@ -6,12 +6,17 @@
:tags="tags"
:distinct-tags="tags"
@save="save"
ref="minder"
/>
</template>
<script>
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
import {getTestCaseDataMap} from "@/business/components/track/common/minder/minderUtils";
import {
appendChild,
getTestCaseDataMap,
parseCase, updateNode
} from "@/business/components/track/common/minder/minderUtils";
export default {
name: "TestCaseMinder",
components: {MsModuleMinder},
@ -48,6 +53,7 @@ name: "TestCaseMinder",
}
},
save(data) {
console.log(data);
let saveCases = [];
let deleteCases = [];
this.buildSaveCase(data.root, saveCases, deleteCases, undefined);
@ -130,7 +136,22 @@ name: "TestCaseMinder",
throw new Error(tip);
}
},
addCase(data, type) {
let nodeData = parseCase(data, new Map());
let minder = window.minder;
let jsonImport = minder.exportJson();
if (type === 'edit') {
updateNode(jsonImport.root, nodeData);
} else {
appendChild(data.nodeId, jsonImport.root, nodeData);
}
this.$refs.minder.setJsonImport(jsonImport);
},
refresh() {
if (this.$refs.minder) {
this.$refs.minder.reload();
}
}
}
}
</script>

View File

@ -47,13 +47,13 @@ name: "TestPlanMinder",
if (this.projectId) {
this.result = this.$get('/test/plan/case/list/minder/' + this.planId, response => {
this.dataMap = getTestCaseDataMap(response.data, true, (data, item) => {
if (item.stats === 'Pass') {
if (item.status === 'Pass') {
data.resource.push(this.$t('test_track.plan_view.pass'));
} else if (item.reviewStatus === 'Failure') {
} else if (item.status === 'Failure') {
data.resource.push(this.$t('test_track.plan_view.failure'));
} else if (item.reviewStatus === 'Blocking') {
} else if (item.status === 'Blocking') {
data.resource.push(this.$t('test_track.plan_view.blocking'));
} else if (item.reviewStatus === 'Skip') {
} else if (item.status === 'Skip') {
data.resource.push(this.$t('test_track.plan_view.skip'));
} else {
data.resource.push(this.$t('test_track.plan.plan_status_prepare'));

View File

@ -1,44 +1,55 @@
import {getUUID} from "@/common/js/utils";
export function getTestCaseDataMap(testCase, isDisable, setParamCallback) {
let dataMap = new Map();
if (testCase) {
testCase.forEach(item => {
item.steps = JSON.parse(item.steps);
// if (item.tags && item.tags.length > 0) {
// item.tags = JSON.parse(item.tags);
// }
let mapItem = dataMap.get(item.nodeId);
let nodeItem = {
data: {
id: item.id,
text: item.name,
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
resource: ["用例"],
type: item.type,
method: item.method,
maintainer: item.maintainer
}
}
if (setParamCallback) {
setParamCallback(nodeItem.data, item);
}
if (isDisable) {
nodeItem.data.disable = true;
// 用例节点可以打标签
nodeItem.data.allowDisabledTag = true;
}
parseChildren(nodeItem, item, isDisable);
if (mapItem) {
mapItem.push(nodeItem);
} else {
mapItem = [];
mapItem.push(nodeItem);
dataMap.set(item.nodeId, mapItem);
}
parseCase(item, dataMap, isDisable, setParamCallback);
})
}
return dataMap;
}
export function parseCase(item, dataMap, isDisable, setParamCallback) {
if (item.steps) {
item.steps = JSON.parse(item.steps);
} else {
item.steps = [];
}
// if (item.tags && item.tags.length > 0) {
// item.tags = JSON.parse(item.tags);
// }
let mapItem = dataMap.get(item.nodeId);
let nodeItem = {
data: {
id: item.id,
text: item.name,
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
resource: ["用例"],
type: item.type,
method: item.method,
maintainer: item.maintainer
}
}
if (setParamCallback) {
setParamCallback(nodeItem.data, item);
}
if (isDisable) {
nodeItem.data.disable = true;
// 用例节点可以打标签
nodeItem.data.allowDisabledTag = true;
}
parseChildren(nodeItem, item, isDisable);
if (mapItem) {
mapItem.push(nodeItem);
} else {
mapItem = [];
mapItem.push(nodeItem);
dataMap.set(item.nodeId, mapItem);
}
return nodeItem;
}
function parseChildren(nodeItem, item, isDisable) {
nodeItem.children = [];
let children = [];
@ -63,7 +74,8 @@ function _parseChildren(children, k, v, isDisable) {
data: {
text: k,
resource: v ? [v] : []
}
},
children: []
}
if (isDisable) {
node.data.disable = true;
@ -72,3 +84,40 @@ function _parseChildren(children, k, v, isDisable) {
return node;
}
}
export function appendChild(appendPid, root, node) {
if (root.data.id === appendPid) {
root.children.push(node);
return;
}
if (!root.children) {
root.children = [];
}
let children = root.children;
for (const index in children) {
let item = children[index];
if (item.data.id === appendPid) {
item.data.expandState = "expand";
item.children.push(node);
return;
} else {
appendChild(appendPid, item, node);
}
}
}
export function updateNode(root, node) {
if (!root.children) {
root.children = [];
}
let children = root.children;
for (const index in children) {
let item = children[index];
if (item.data.id === node.data.id) {
children[index] = node;
return;
} else {
updateNode(item, node);
}
}
}

View File

@ -86,7 +86,7 @@
show-overflow-tooltip
:key="index">
<template v-slot:default="scope">
<el-progress :percentage="scope.row.passRate.substring(0, scope.row.passRate.length-1)"></el-progress>
<el-progress :percentage="calPassRate(scope)"></el-progress>
</template>
</el-table-column>
<el-table-column
@ -293,6 +293,10 @@ export default {
this.initTableData();
},
methods: {
calPassRate(scope) {
let passRate = scope.row.passRate.substring(0, scope.row.passRate.length-1);
return Number.parseInt(passRate, 10);
},
customHeader() {
this.$refs.headerCustom.open(this.tableLabel)
},

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.metersphere</groupId>
<artifactId>metersphere-server</artifactId>
<version>1.7</version>
<version>1.8</version>
<packaging>pom</packaging>
<parent>