fix(测试跟踪): 功能用例批量编辑性能优化
--bug=1014258 --user=陈建星 【测试跟踪】功能列表用例条数过多时,批量编辑接口性能需要优化 https://www.tapd.cn/55049933/s/1187303
This commit is contained in:
parent
bf0b53bfb1
commit
5f1f8c2730
|
@ -157,4 +157,6 @@ public interface ExtTestCaseMapper {
|
|||
List<CustomFieldResourceCompatibleDTO> getForCompatibleCustomField(String projectId, int offset, int pageSize);
|
||||
|
||||
List<Map<String, Object>> moduleExtraNodeCount(@Param("nodeIds") List<String> nodeIds);
|
||||
|
||||
int bathUpdateByCondition(@Param("request") QueryTestCaseRequest condition, @Param("record") TestCaseWithBLOBs testCaseWithBLOBs);
|
||||
}
|
||||
|
|
|
@ -1094,6 +1094,124 @@
|
|||
WHERE ref_id = #{refId,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
||||
<update id="bathUpdateByCondition">
|
||||
update test_case
|
||||
<set>
|
||||
<if test="record.id != null">
|
||||
id = #{record.id,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.nodeId != null">
|
||||
node_id = #{record.nodeId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.testId != null">
|
||||
test_id = #{record.testId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.nodePath != null">
|
||||
node_path = #{record.nodePath,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.projectId != null">
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.name != null">
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.type != null">
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.maintainer != null">
|
||||
maintainer = #{record.maintainer,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.priority != null">
|
||||
priority = #{record.priority,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.method != null">
|
||||
`method` = #{record.method,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.updateTime != null">
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.sort != null">
|
||||
sort = #{record.sort,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.num != null">
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.otherTestName != null">
|
||||
other_test_name = #{record.otherTestName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.reviewStatus != null">
|
||||
review_status = #{record.reviewStatus,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.tags != null">
|
||||
tags = #{record.tags,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.demandId != null">
|
||||
demand_id = #{record.demandId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.demandName != null">
|
||||
demand_name = #{record.demandName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.status != null">
|
||||
`status` = #{record.status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.stepModel != null">
|
||||
step_model = #{record.stepModel,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.customNum != null">
|
||||
custom_num = #{record.customNum,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createUser != null">
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.originalStatus != null">
|
||||
original_status = #{record.originalStatus,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.deleteTime != null">
|
||||
delete_time = #{record.deleteTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.deleteUserId != null">
|
||||
delete_user_id = #{record.deleteUserId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.order != null">
|
||||
`order` = #{record.order,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.casePublic != null">
|
||||
case_public = #{record.casePublic,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.versionId != null">
|
||||
version_id = #{record.versionId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.refId != null">
|
||||
ref_id = #{record.refId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.latest != null">
|
||||
latest = #{record.latest,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.prerequisite != null">
|
||||
prerequisite = #{record.prerequisite,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.remark != null">
|
||||
remark = #{record.remark,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.steps != null">
|
||||
steps = #{record.steps,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.stepDescription != null">
|
||||
step_description = #{record.stepDescription,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.expectedResult != null">
|
||||
expected_result = #{record.expectedResult,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.customFields != null">
|
||||
custom_fields = #{record.customFields,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<include refid="queryWhereCondition"/>
|
||||
</update>
|
||||
|
||||
<select id="moduleExtraNodeCount" resultType="java.util.Map">
|
||||
select parent_id as moduleId, count(id) as countNum from minder_extra_node
|
||||
where parent_id in
|
||||
|
|
|
@ -677,12 +677,17 @@ public class TestCaseService {
|
|||
}
|
||||
|
||||
public List<TestCaseDTO> listTestCase(QueryTestCaseRequest request) {
|
||||
return listTestCase(request, false);
|
||||
}
|
||||
|
||||
public List<TestCaseDTO> listTestCase(QueryTestCaseRequest request, boolean isSampleInfo) {
|
||||
this.initRequest(request, true);
|
||||
setDefaultOrder(request);
|
||||
if (request.getFilters() != null && !request.getFilters().containsKey("status")) {
|
||||
request.getFilters().put("status", new ArrayList<>(0));
|
||||
}
|
||||
List<TestCaseDTO> list = extTestCaseMapper.list(request);
|
||||
if (!isSampleInfo) {
|
||||
buildUserInfo(list);
|
||||
if (StringUtils.isNotBlank(request.getProjectId())) {
|
||||
buildProjectInfo(request.getProjectId(), list);
|
||||
|
@ -691,6 +696,7 @@ public class TestCaseService {
|
|||
}
|
||||
buildCustomField(list);
|
||||
list = this.parseStatus(list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -1494,20 +1500,7 @@ public class TestCaseService {
|
|||
}
|
||||
|
||||
public List<TestCaseDTO> findByBatchRequest(TestCaseBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
QueryTestCaseRequest condition = request.getCondition();
|
||||
List<OrderRequest> orderList = new ArrayList<>();
|
||||
if (condition != null) {
|
||||
orderList = ServiceUtils.getDefaultSortOrder(condition.getOrders());
|
||||
}
|
||||
OrderRequest order = new OrderRequest();
|
||||
order.setName("sort");
|
||||
order.setType("desc");
|
||||
orderList.add(order);
|
||||
request.setOrders(orderList);
|
||||
List<TestCaseDTO> testCaseList = extTestCaseMapper.listByTestCaseIds(request);
|
||||
return testCaseList;
|
||||
return listTestCase(request.getCondition(), true);
|
||||
}
|
||||
|
||||
private List<TestCaseExcelData> generateTestCaseExcel(TestCaseBatchRequest request) {
|
||||
|
@ -1672,42 +1665,29 @@ public class TestCaseService {
|
|||
* @param request
|
||||
*/
|
||||
public void editTestCaseBath(TestCaseBatchRequest request) {
|
||||
if (request.getCustomField() != null) {
|
||||
batchEditField(request);
|
||||
} else if (StringUtils.equals("tags", request.getType())) {
|
||||
batchEditTag(request);
|
||||
} else {
|
||||
// 批量移动
|
||||
TestCaseWithBLOBs batchEdit = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(batchEdit, request);
|
||||
batchEdit.setUpdateTime(System.currentTimeMillis());
|
||||
bathUpdateByCondition(request, batchEdit);
|
||||
}
|
||||
}
|
||||
|
||||
private void batchEditTag(TestCaseBatchRequest request) {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
List<String> ids = request.getIds();
|
||||
if (CollectionUtils.isEmpty(ids)) {
|
||||
return;
|
||||
}
|
||||
if (request.getCustomField() != null) {
|
||||
List<TestCaseWithBLOBs> testCases = extTestCaseMapper.getCustomFieldsByIds(ids);
|
||||
testCases.forEach((testCase) -> {
|
||||
CustomFieldResourceDTO customField = request.getCustomField();
|
||||
if (StringUtils.equals(customField.getName(), "用例等级")) {
|
||||
testCase.setPriority(JSONObject.parse(customField.getValue()).toString());
|
||||
} else if (StringUtils.equals(request.getCustomField().getName(), "用例状态")) {
|
||||
testCase.setStatus(JSONObject.parse(customField.getValue()).toString());
|
||||
} else if (StringUtils.equals(customField.getName(), "责任人")) {
|
||||
testCase.setMaintainer(JSONObject.parse(customField.getValue()).toString());
|
||||
} else {
|
||||
customField.setResourceId(testCase.getId());
|
||||
int row = customFieldTestCaseService.updateByPrimaryKeySelective(customField);
|
||||
if (row < 1) {
|
||||
customFieldTestCaseService.insert(customField);
|
||||
}
|
||||
}
|
||||
testCase.setUpdateTime(System.currentTimeMillis());
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdEqualTo(testCase.getId());
|
||||
testCaseMapper.updateByExampleSelective(testCase, example);
|
||||
});
|
||||
} else if (StringUtils.equals("tags", request.getType())) {
|
||||
if (request.getTagList().isEmpty()) {
|
||||
if (CollectionUtils.isEmpty(request.getIds()) || request.getTagList().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class);
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
List<TestCase> testCaseList = testCaseMapper.selectByExample(example);
|
||||
for (TestCase tc : testCaseList) {
|
||||
String tags = tc.getTags();
|
||||
|
@ -1730,15 +1710,55 @@ public class TestCaseService {
|
|||
if (sqlSession != null && sqlSessionFactory != null) {
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
} else {
|
||||
// 批量移动
|
||||
TestCaseWithBLOBs batchEdit = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(batchEdit, request);
|
||||
batchEdit.setUpdateTime(System.currentTimeMillis());
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
testCaseMapper.updateByExampleSelective(batchEdit, example);
|
||||
}
|
||||
|
||||
private void batchEditField(TestCaseBatchRequest request) {
|
||||
CustomFieldResourceDTO customField = request.getCustomField();
|
||||
String name = customField.getName();
|
||||
String value = JSONObject.parse(customField.getValue()).toString();
|
||||
TestCaseWithBLOBs testCaseWithBLOBs = new TestCaseWithBLOBs();
|
||||
|
||||
if (StringUtils.equalsAnyIgnoreCase(name, "用例等级")) {
|
||||
testCaseWithBLOBs.setPriority(value);
|
||||
bathUpdateByCondition(request, testCaseWithBLOBs);
|
||||
} else if (StringUtils.equals(name, "用例状态")) {
|
||||
testCaseWithBLOBs.setStatus(value);
|
||||
bathUpdateByCondition(request, testCaseWithBLOBs);
|
||||
} else if (StringUtils.equals(name, "责任人")) {
|
||||
testCaseWithBLOBs.setMaintainer(value);
|
||||
bathUpdateByCondition(request, testCaseWithBLOBs);
|
||||
} else {
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
if (CollectionUtils.isEmpty(request.getIds())) {
|
||||
return;
|
||||
}
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class);
|
||||
List<TestCaseWithBLOBs> testCases = extTestCaseMapper.getCustomFieldsByIds(request.getIds());
|
||||
for (int i = 0; i < testCases.size(); i++) {
|
||||
TestCaseWithBLOBs testCase = testCases.get(i);
|
||||
customField.setResourceId(testCase.getId());
|
||||
int row = customFieldTestCaseService.updateByPrimaryKeySelective(customField);
|
||||
if (row < 1) {
|
||||
customFieldTestCaseService.insert(customField);
|
||||
}
|
||||
testCase.setUpdateTime(System.currentTimeMillis());
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdEqualTo(testCase.getId());
|
||||
mapper.updateByExampleSelective(testCase, example);
|
||||
if (i % 1000 == 0) {
|
||||
sqlSession.flushStatements();
|
||||
}
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int bathUpdateByCondition(TestCaseBatchRequest request, TestCaseWithBLOBs testCaseWithBLOBs) {
|
||||
return extTestCaseMapper.bathUpdateByCondition(request.getCondition(), testCaseWithBLOBs);
|
||||
}
|
||||
|
||||
public void copyTestCaseBathPublic(TestCaseBatchRequest request) {
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
@close="handleClose"
|
||||
v-loading="result.loading"
|
||||
>
|
||||
<el-form :model="form" label-position="right" label-width="150px" size="medium" ref="form" :rules="rules">
|
||||
<el-form :model="form" label-position="right" label-width="180px" size="medium" ref="form" :rules="rules">
|
||||
|
||||
<el-form-item :label="$t('test_track.case.batch_update', [size])" prop="type">
|
||||
<el-select v-model="form.type" style="width: 80%" @change="changeType">
|
||||
<el-select v-model="form.type" style="width: 100%" @change="changeType">
|
||||
<el-option v-for="(type, index) in typeArr" :key="index" :value="type.custom ? type.custom : type.id" :label="type.name"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.type === 'projectEnv'" :label="$t('test_track.case.updated_attr_value')">
|
||||
<env-popover :env-map="projectEnvMap"
|
||||
:project-ids="projectIds"
|
||||
|
@ -27,10 +29,12 @@
|
|||
@setEnvGroup="setEnvGroup"
|
||||
ref="envPopover"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-else-if="fieldType === 'custom'" :label="$t('test_track.case.updated_attr_value')">
|
||||
|
||||
<el-form-item v-else-if="fieldType === 'custom'" prop="customFieldValue" :label="$t('test_track.case.updated_attr_value')">
|
||||
<custom-filed-component :data="customField" prop="defaultValue"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-else-if="form.type === 'tags'" :label="$t('test_track.case.updated_attr_value')">
|
||||
|
||||
<el-form-item v-else-if="form.type === 'tags'" prop="tags" :label="$t('test_track.case.updated_attr_value')">
|
||||
<ms-input-tag :currentScenario="form" v-if="showInputTag" ref="tag" class="ms-case-input"></ms-input-tag>
|
||||
<el-checkbox v-model="form.appendTag">
|
||||
追加标签
|
||||
|
@ -39,8 +43,9 @@
|
|||
</el-tooltip>
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-else :label="$t('test_track.case.updated_attr_value')" prop="value">
|
||||
<el-select v-model="form.value" style="width: 80%" :filterable="filterable">
|
||||
<el-select v-model="form.value" style="width: 100%" :filterable="filterable">
|
||||
<el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name">
|
||||
<div v-if="option.email">
|
||||
<span>{{option.id}}({{option.name}})</span>
|
||||
|
@ -48,6 +53,7 @@
|
|||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer
|
||||
|
@ -89,12 +95,17 @@ export default {
|
|||
dialogVisible: false,
|
||||
showConfigButtonWithOutPermission:false,
|
||||
form: {
|
||||
appendTag: true
|
||||
appendTag: true,
|
||||
customFieldValue: null,
|
||||
tags: null,
|
||||
value: null
|
||||
},
|
||||
size: 0,
|
||||
rules: {
|
||||
type: {required: true, message: this.$t('test_track.case.please_select_attr'), trigger: ['blur','change']},
|
||||
value: {required: true, message: this.$t('test_track.case.please_select_attr_value'), trigger: ['blur','change']}
|
||||
value: {required: true, message: this.$t('test_track.case.please_select_attr_value'), trigger: ['blur','change']},
|
||||
tags: {required: true, message: this.$t('test_track.case.please_select_attr_value'), trigger: ['blur','change']},
|
||||
customFieldValue: {required: true, message: this.$t('test_track.case.please_select_attr_value'), trigger: ['blur','change']}
|
||||
},
|
||||
options: [],
|
||||
filterable: false,
|
||||
|
@ -118,6 +129,11 @@ export default {
|
|||
return ENV_TYPE;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'customField.defaultValue'() {
|
||||
this.$set(this.form, 'customFieldValue', this.customField.defaultValue);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit(form) {
|
||||
this.$refs[form].validate(async (valid) => {
|
||||
|
|
|
@ -675,7 +675,7 @@ export default {
|
|||
if (field.name === '用例等级') {
|
||||
return row.priority;
|
||||
} else if (field.name === '责任人') {
|
||||
return row.maintainer;
|
||||
return row.maintainerName;
|
||||
} else if (field.name === '用例状态') {
|
||||
return row.status;
|
||||
}
|
||||
|
@ -990,6 +990,7 @@ export default {
|
|||
},
|
||||
refresh() {
|
||||
this.$refs.table.clear();
|
||||
this.condition.selectAll = false;
|
||||
this.$emit('refresh');
|
||||
},
|
||||
refreshAll() {
|
||||
|
|
|
@ -130,6 +130,7 @@ import MsTablePagination from "@/business/components/common/pagination/TablePagi
|
|||
import MsDialogHeader from "@/business/components/common/components/MsDialogHeader";
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import TableSelectCountBar from "@/business/components/api/automation/scenario/api/TableSelectCountBar";
|
||||
import {getVersionFilters} from "@/network/project";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const VersionSelect = requireComponent.keys().length > 0 ? requireComponent("./version/VersionSelect.vue") : {};
|
||||
|
@ -215,6 +216,7 @@ export default {
|
|||
},
|
||||
projectId() {
|
||||
this.condition.projectId = this.projectId;
|
||||
this.getVersionOptions();
|
||||
this.getProjectNode();
|
||||
}
|
||||
},
|
||||
|
@ -366,13 +368,9 @@ export default {
|
|||
this.selectNodeIds = [];
|
||||
},
|
||||
getVersionOptions() {
|
||||
if (hasLicense()) {
|
||||
this.$get('/project/version/get-project-versions/' + getCurrentProjectID(), response => {
|
||||
this.versionFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id};
|
||||
getVersionFilters(this.projectId, (data) => {
|
||||
this.versionFilters = data;
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
changeVersion(version) {
|
||||
this.condition.versionId = version || null;
|
||||
|
|
Loading…
Reference in New Issue