feat: 接口定义和场景支持批量复制

This commit is contained in:
chenjianxing 2021-12-29 14:57:19 +08:00 committed by fit2-zhao
parent ec267cf8c9
commit 2c65f7110b
10 changed files with 119 additions and 100 deletions

View File

@ -247,6 +247,13 @@ public class ApiAutomationController {
apiAutomationService.bathEdit(request); apiAutomationService.bathEdit(request);
} }
@PostMapping("/batch/copy")
@RequiresPermissions(value = {PermissionConstants.PROJECT_API_SCENARIO_READ_CREATE, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
@MsAuditLog(module = "api_automation", type = OperLogConstants.BATCH_ADD, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = ApiAutomationService.class)
public void batchCopy(@RequestBody ApiScenarioBatchRequest request) {
apiAutomationService.batchCopy(request);
}
@PostMapping("/batch/update/env") @PostMapping("/batch/update/env")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT) @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT)
@MsAuditLog(module = "api_automation", type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = ApiAutomationService.class) @MsAuditLog(module = "api_automation", type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = ApiAutomationService.class)
@ -296,13 +303,6 @@ public class ApiAutomationController {
return apiAutomationService.batchGenPerformanceTestJmx(request); return apiAutomationService.batchGenPerformanceTestJmx(request);
} }
@PostMapping("/batchCopy")
public BatchOperaResponse batchCopy(@RequestBody ApiScenarioBatchRequest request) {
BatchOperaResponse response = apiAutomationService.batchCopy(request);
return response;
}
@PostMapping("/file/download") @PostMapping("/file/download")
public ResponseEntity<byte[]> download(@RequestBody FileOperationRequest fileOperationRequest) { public ResponseEntity<byte[]> download(@RequestBody FileOperationRequest fileOperationRequest) {
byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest); byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest);

View File

@ -280,6 +280,13 @@ public class ApiDefinitionController {
apiDefinitionService.editApiByParam(request); apiDefinitionService.editApiByParam(request);
} }
@PostMapping("/batch/copy")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_COPY_API)
@MsAuditLog(module = "api_definition", type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.getLogDetails(#request)", content = "#msClass.getLogDetails(#request)", msClass = ApiDefinitionService.class)
public void batchCopy(@RequestBody ApiBatchRequest request) {
apiDefinitionService.batchCopy(request);
}
@PostMapping("/relevance") @PostMapping("/relevance")
@MsAuditLog(module = "track_test_plan", type = OperLogConstants.ASSOCIATE_CASE, content = "#msClass.getLogDetails(#request)", msClass = ApiDefinitionService.class) @MsAuditLog(module = "track_test_plan", type = OperLogConstants.ASSOCIATE_CASE, content = "#msClass.getLogDetails(#request)", msClass = ApiDefinitionService.class)
public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) { public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) {

View File

@ -1748,65 +1748,35 @@ public class ApiAutomationService {
} }
} }
public BatchOperaResponse batchCopy(ApiScenarioBatchRequest batchRequest) { public void batchCopy(ApiScenarioBatchRequest request) {
ServiceUtils.getSelectAllIds(batchRequest, batchRequest.getCondition(), ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiScenarioMapper.selectIdsByQuery(query)); (query) -> extApiScenarioMapper.selectIdsByQuery(query));
List<ApiScenarioWithBLOBs> apiScenarioList = extApiScenarioMapper.selectIds(batchRequest.getIds()); List<String> ids = request.getIds();
StringBuffer stringBuffer = new StringBuffer(); if (CollectionUtils.isEmpty(ids)) return;
for (ApiScenarioWithBLOBs apiModel : apiScenarioList) { List<ApiScenarioWithBLOBs> apiScenarioList = extApiScenarioMapper.selectIds(ids);
long time = System.currentTimeMillis(); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioWithBLOBs newModel = apiModel; ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class);
newModel.setId(UUID.randomUUID().toString()); Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extApiScenarioMapper::getLastOrder);
newModel.setName("copy_" + apiModel.getName()); int nextNum = getNextNum(request.getProjectId());
newModel.setCreateTime(time);
newModel.setUpdateTime(time);
newModel.setNum(getNextNum(newModel.getProjectId()));
ApiScenarioExample example = new ApiScenarioExample(); try {
example.createCriteria().andNameEqualTo(newModel.getName()). for (int i = 0; i < apiScenarioList.size(); i++) {
andProjectIdEqualTo(newModel.getProjectId()).andStatusNotEqualTo("Trash").andIdNotEqualTo(newModel.getId()); ApiScenarioWithBLOBs api = apiScenarioList.get(i);
if (apiScenarioMapper.countByExample(example) > 0) { api.setId(UUID.randomUUID().toString());
stringBuffer.append(newModel.getName() + ";"); api.setName(ServiceUtils.getCopyName(api.getName()));
continue; api.setApiScenarioModuleId(request.getApiScenarioModuleId());
} else { api.setModulePath(request.getModulePath());
boolean insertFlag = true; api.setOrder(nextOrder += ServiceUtils.ORDER_STEP);
if (StringUtils.isNotBlank(newModel.getCustomNum())) { api.setNum(nextNum++);
insertFlag = false; mapper.insert(api);
String projectId = newModel.getProjectId(); if (i % 50 == 0)
Project project = projectMapper.selectByPrimaryKey(projectId); sqlSession.flushStatements();
if (project != null) {
Boolean customNum = project.getScenarioCustomNum();
// 未开启自定义ID
if (!customNum) {
insertFlag = true;
newModel.setCustomNum(null);
} else {
boolean isCustomNumExist = true;
try {
isCustomNumExist = this.isCustomNumExist(newModel);
} catch (Exception e) {
}
insertFlag = !isCustomNumExist;
}
}
}
if (insertFlag) {
apiScenarioMapper.insert(newModel);
apiScenarioReferenceIdService.saveByApiScenario(newModel);
}
} }
sqlSession.flushStatements();
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }
BatchOperaResponse result = new BatchOperaResponse();
if (stringBuffer.length() == 0) {
result.result = true;
} else {
result.result = false;
result.errorMsg = stringBuffer.substring(0, stringBuffer.length() - 1);
}
return result;
} }
public DeleteCheckResult checkBeforeDelete(ApiScenarioBatchRequest request) { public DeleteCheckResult checkBeforeDelete(ApiScenarioBatchRequest request) {

View File

@ -1782,4 +1782,41 @@ public class ApiDefinitionService {
example.createCriteria().andRefIdEqualTo(refId).andVersionIdEqualTo(version); example.createCriteria().andRefIdEqualTo(refId).andVersionIdEqualTo(version);
apiDefinitionMapper.deleteByExample(example); apiDefinitionMapper.deleteByExample(example);
} }
public List<ApiDefinitionWithBLOBs> getByIds(List<String> ids) {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(ids);
return apiDefinitionMapper.selectByExampleWithBLOBs(example);
}
public void batchCopy(ApiBatchRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiDefinitionMapper.selectIds(query));
List<String> ids = request.getIds();
if (CollectionUtils.isEmpty(ids)) return;
List<ApiDefinitionWithBLOBs> apis = getByIds(ids);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionMapper mapper = sqlSession.getMapper(ApiDefinitionMapper.class);
Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extApiDefinitionMapper::getLastOrder);
int nextNum = getNextNum(request.getProjectId());
try {
for (int i = 0; i < apis.size(); i++) {
ApiDefinitionWithBLOBs api = apis.get(i);
api.setId(UUID.randomUUID().toString());
api.setName(ServiceUtils.getCopyName(api.getName()));
api.setModuleId(request.getModuleId());
api.setModulePath(request.getModulePath());
api.setOrder(nextOrder += ServiceUtils.ORDER_STEP);
api.setNum(nextNum++);
mapper.insert(api);
if (i % 50 == 0)
sqlSession.flushStatements();
}
sqlSession.flushStatements();
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
} }

View File

@ -16,10 +16,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils; import org.mybatis.spring.SqlSessionUtils;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@ -239,4 +236,8 @@ public class ServiceUtils {
SqlSessionFactory sqlSessionFactory = CommonBeanFactory.getBean(SqlSessionFactory.class); SqlSessionFactory sqlSessionFactory = CommonBeanFactory.getBean(SqlSessionFactory.class);
return sqlSessionFactory.openSession(ExecutorType.BATCH); return sqlSessionFactory.openSession(ExecutorType.BATCH);
} }
public static String getCopyName(String name) {
return "copy_" + name + "_" + UUID.randomUUID().toString().substring(0, 4);
}
} }

View File

@ -314,10 +314,8 @@ public class TestCaseController {
} }
@PostMapping("/batch/copy") @PostMapping("/batch/copy")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT) @RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_COPY)
@MsAuditLog(module = "track_test_case", type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = TestCaseService.class) @MsAuditLog(module = "track_test_case", type = OperLogConstants.BATCH_ADD, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = TestCaseService.class)
@SendNotice(taskType = NoticeConstants.TaskType.TRACK_TEST_CASE_TASK, target = "#targetClass.findByBatchRequest(#request)", targetClass = TestCaseService.class,
event = NoticeConstants.Event.CREATE, mailTemplate = "track/TestCaseUpdate", subject = "测试用例通知")
public void copyTestCaseBath(@RequestBody TestCaseBatchRequest request) { public void copyTestCaseBath(@RequestBody TestCaseBatchRequest request) {
testCaseService.copyTestCaseBath(request); testCaseService.copyTestCaseBath(request);
} }

View File

@ -2194,14 +2194,18 @@ public class TestCaseService {
TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class); TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class);
Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extTestCaseMapper::getLastOrder); Long nextOrder = ServiceUtils.getNextOrder(request.getProjectId(), extTestCaseMapper::getLastOrder);
int nextNum = getNextNum(request.getProjectId());
try { try {
for (int i = 0; i < testCases.size(); i++) { for (int i = 0; i < testCases.size(); i++) {
TestCaseWithBLOBs testCase = testCases.get(i); TestCaseWithBLOBs testCase = testCases.get(i);
testCase.setId(UUID.randomUUID().toString()); testCase.setId(UUID.randomUUID().toString());
testCase.setName(testCase.getName() + "_" + testCase.getId().substring(0, 5)); testCase.setName(ServiceUtils.getCopyName(testCase.getName()));
testCase.setNodeId(request.getNodeId()); testCase.setNodeId(request.getNodeId());
testCase.setNodePath(request.getNodePath()); testCase.setNodePath(request.getNodePath());
testCase.setOrder(nextOrder += ServiceUtils.ORDER_STEP); testCase.setOrder(nextOrder += ServiceUtils.ORDER_STEP);
testCase.setCustomNum(String.valueOf(nextNum));
testCase.setNum(nextNum++);
mapper.insert(testCase); mapper.insert(testCase);
if (i % 50 == 0) if (i % 50 == 0)
sqlSession.flushStatements(); sqlSession.flushStatements();

View File

@ -403,6 +403,7 @@ export default {
components: API_SCENARIO_CONFIGS components: API_SCENARIO_CONFIGS
}, },
scenarioId: "", scenarioId: "",
isMoveBatch: true,
currentScenario: {}, currentScenario: {},
schedule: {}, schedule: {},
tableData: [], tableData: [],
@ -489,16 +490,16 @@ export default {
handleClick: this.handleBatchEdit, handleClick: this.handleBatchEdit,
permissions: ['PROJECT_API_SCENARIO:READ+EDIT'] permissions: ['PROJECT_API_SCENARIO:READ+EDIT']
}, },
{
name: this.$t('api_test.batch_copy'),
handleClick: this.batchCopy,
permissions: ['PROJECT_API_SCENARIO:READ+BATCH_COPY']
},
{ {
name: this.$t('test_track.case.batch_move_case'), name: this.$t('test_track.case.batch_move_case'),
handleClick: this.handleBatchMove, handleClick: this.handleBatchMove,
permissions: ['PROJECT_API_SCENARIO:READ+MOVE_BATCH'] permissions: ['PROJECT_API_SCENARIO:READ+MOVE_BATCH']
}, },
{
name: this.$t('api_test.batch_copy'),
handleClick: this.handleBatchCopy,
permissions: ['PROJECT_API_SCENARIO:READ+BATCH_COPY']
},
{ {
name: this.$t('api_test.definition.request.batch_delete'), name: this.$t('api_test.definition.request.batch_delete'),
handleClick: this.handleDeleteBatch, handleClick: this.handleDeleteBatch,
@ -759,13 +760,21 @@ export default {
} }
}, },
handleBatchMove() { handleBatchMove() {
this.isMoveBatch = true;
this.$refs.testBatchMove.open(this.moduleTree, [], this.moduleOptions); this.$refs.testBatchMove.open(this.moduleTree, [], this.moduleOptions);
}, },
handleBatchCopy() {
this.isMoveBatch = false;
this.$refs.testBatchMove.open(this.moduleTree, this.$refs.scenarioTable.selectIds, this.moduleOptions);
},
moveSave(param) { moveSave(param) {
this.buildBatchParam(param); this.buildBatchParam(param);
param.apiScenarioModuleId = param.nodeId; param.apiScenarioModuleId = param.nodeId;
param.modulePath = param.nodePath; param.modulePath = param.nodePath;
this.$post('/api/automation/batch/edit', param, () => { let url = '/api/automation/batch/edit';
if (!this.isMoveBatch)
url = '/api/automation/batch/copy';
this.$post(url, param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.$refs.testBatchMove.close(); this.$refs.testBatchMove.close();
this.search(); this.search();
@ -1228,28 +1237,6 @@ export default {
} }
}); });
}, },
batchCopy() {
this.$alert(this.$t('api_test.definition.request.batch_copy_confirm') + " ", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this.infoDb = false;
let param = {};
this.buildBatchParam(param);
this.$post('/api/automation/batchCopy', param, response => {
let copyResult = response.data;
if (copyResult.result) {
this.$success(this.$t('api_test.definition.request.batch_copy_end'));
} else {
this.$error(this.$t('commons.already_exists') + ":" + copyResult.errorMsg);
}
this.search();
});
}
}
});
},
stop(row) { stop(row) {
let url = "/api/automation/stop/" + this.reportId; let url = "/api/automation/stop/" + this.reportId;
this.$get(url, () => { this.$get(url, () => {

View File

@ -289,6 +289,7 @@ export default {
enableOrderDrag: true, enableOrderDrag: true,
selectDataRange: "all", selectDataRange: "all",
graphData: [], graphData: [],
isMoveBatch: true,
deletePath: "/test/case/delete", deletePath: "/test/case/delete",
buttons: [ buttons: [
{ {
@ -306,6 +307,11 @@ export default {
handleClick: this.handleBatchMove, handleClick: this.handleBatchMove,
permissions: ['PROJECT_API_DEFINITION:READ+EDIT_API'] permissions: ['PROJECT_API_DEFINITION:READ+EDIT_API']
}, },
{
name: this.$t('api_test.batch_copy'),
handleClick: this.handleBatchCopy,
permissions: ['PROJECT_API_DEFINITION:READ+CREATE_API']
},
{ {
name: this.$t('test_track.case.generate_dependencies'), name: this.$t('test_track.case.generate_dependencies'),
isXPack: true, isXPack: true,
@ -552,8 +558,13 @@ export default {
}); });
}, },
handleBatchMove() { handleBatchMove() {
this.isMoveBatch = true;
this.$refs.testCaseBatchMove.open(this.moduleTree, [], this.moduleOptions); this.$refs.testCaseBatchMove.open(this.moduleTree, [], this.moduleOptions);
}, },
handleBatchCopy() {
this.isMoveBatch = false;
this.$refs.testCaseBatchMove.open(this.moduleTree, this.$refs.table.selectIds, this.moduleOptions);
},
closeCaseModel() { closeCaseModel() {
// //
if (this.$refs.caseList) { if (this.$refs.caseList) {
@ -771,7 +782,10 @@ export default {
param.projectId = this.projectId; param.projectId = this.projectId;
param.condition = this.condition; param.condition = this.condition;
param.moduleId = param.nodeId; param.moduleId = param.nodeId;
this.$post('/api/definition/batch/editByParams', param, () => { let url = '/api/definition/batch/editByParams';
if (!this.isMoveBatch)
url = '/api/definition/batch/copy';
this.$post(url, param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.$refs.testCaseBatchMove.close(); this.$refs.testCaseBatchMove.close();
this.initTable(); this.initTable();

View File

@ -346,7 +346,7 @@ export default {
{ {
name: this.$t('api_test.batch_copy'), name: this.$t('api_test.batch_copy'),
handleClick: this.handleBatchCopy, handleClick: this.handleBatchCopy,
permissions: ['PROJECT_TRACK_CASE:READ+EDIT'] permissions: ['PROJECT_TRACK_CASE:READ+COPY']
}, },
{ {
name: this.$t('test_track.case.batch_delete_case'), name: this.$t('test_track.case.batch_delete_case'),
@ -1079,6 +1079,7 @@ export default {
let url = '/test/case/batch/edit'; let url = '/test/case/batch/edit';
if (!this.isMoveBatch) if (!this.isMoveBatch)
url = '/test/case/batch/copy'; url = '/test/case/batch/copy';
param.projectId = this.projectId;
this.page.result = this.$post(url, param, () => { this.page.result = this.$post(url, param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.$refs.testBatchMove.close(); this.$refs.testBatchMove.close();