diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index 05ab85d224..16c7e5cc7b 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -8,7 +8,6 @@ import io.metersphere.api.dto.automation.ApiScenarioRequest; import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; -import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest; import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult; import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest; import io.metersphere.api.service.ApiDefinitionService; @@ -22,10 +21,8 @@ import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.OperLogConstants; import io.metersphere.commons.constants.PermissionConstants; import io.metersphere.commons.json.JSONSchemaGenerator; -import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; -import io.metersphere.commons.utils.SessionUtils; import io.metersphere.controller.request.ScheduleRequest; import io.metersphere.log.annotation.MsAuditLog; import io.metersphere.service.CheckPermissionService; @@ -39,8 +36,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.net.MalformedURLException; -import java.util.Date; import java.util.List; @@ -211,12 +206,12 @@ public class ApiDefinitionController { //定时任务创建 @PostMapping(value = "/schedule/create") @MsAuditLog(module = "api_definition", type = OperLogConstants.CREATE, title = "#request.scheduleFrom", project = "#request.projectId") - public void createSchedule(@RequestBody ScheduleRequest request) throws MalformedURLException { + public void createSchedule(@RequestBody ScheduleRequest request) { apiDefinitionService.createSchedule(request); } @PostMapping(value = "/schedule/update") - public void updateSchedule(@RequestBody Schedule request) { + public void updateSchedule(@RequestBody ScheduleRequest request) { apiDefinitionService.updateSchedule(request); } @@ -229,30 +224,18 @@ public class ApiDefinitionController { //查找定时任务列表 @GetMapping("/scheduleTask/{projectId}") public List getSwaggerScheduleList(@PathVariable String projectId) { - List resultList = apiDefinitionService.getSwaggerScheduleList(projectId); - int dataIndex = 1; - for (SwaggerTaskResult swaggerTaskResult : - resultList) { - swaggerTaskResult.setIndex(dataIndex++); - Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule()); - if (nextExecutionTime != null) { - swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime()); - } - } - return resultList; + return apiDefinitionService.getSwaggerScheduleList(projectId); } - //更新定时任务 - @PostMapping(value = "/schedule/updateByPrimyKey") - public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoSwaggerUrlRequest request) { - Schedule schedule = scheduleService.getSchedule(request.getTaskId()); - schedule.setEnable(request.getTaskStatus()); - apiDefinitionService.updateSchedule(schedule); + //更新定时任务更新定时任务 + @PostMapping(value = "/schedule/switch") + public void updateScheduleEnable(@RequestBody Schedule request) { + apiDefinitionService.switchSchedule(request); } //删除定时任务和swaggereUrl - @PostMapping("/schedule/deleteByPrimyKey") - public void deleteSchedule(@RequestBody ScheduleInfoSwaggerUrlRequest request) { + @PostMapping("/schedule/delete") + public void deleteSchedule(@RequestBody ScheduleRequest request) { apiDefinitionService.deleteSchedule(request); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportUtil.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportUtil.java index 67db73a587..f84a94253a 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportUtil.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportUtil.java @@ -14,12 +14,20 @@ import java.util.List; public class ApiDefinitionImportUtil { public static ApiModule getSelectModule(String moduleId) { + return getSelectModule(moduleId, null); + } + + public static ApiModule getSelectModule(String moduleId, String userId) { ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) { ApiModule module = new ApiModule(); ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId); if (moduleDTO != null) { BeanUtils.copyBean(module, moduleDTO); + } else { + if (StringUtils.isNotBlank(userId)) { + module.setCreateUser(userId); + } } return module; } @@ -57,7 +65,24 @@ public class ApiDefinitionImportUtil { return module; } + public static ApiModule buildModule(ApiModule parentModule, String name, String projectId, String userId) { + ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + ApiModule module; + if (parentModule != null) { + module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1); + module.setParentId(parentModule.getId()); + } else { + module = apiModuleService.getNewModule(name, projectId, 1); + } + createModule(module, userId); + return module; + } + public static void createModule(ApiModule module) { + createModule(module, null); + } + + public static void createModule(ApiModule module, String userId) { ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); module.setProtocol(RequestType.HTTP); if (module.getName().length() > 64) { @@ -65,6 +90,9 @@ public class ApiDefinitionImportUtil { } List apiModules = apiModuleService.selectSameModule(module); if (CollectionUtils.isEmpty(apiModules)) { + if (StringUtils.isNotBlank(userId)) { + module.setCreateUser(userId); + } apiModuleService.addNode(module); } else { module.setId(apiModules.get(0).getId()); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java index 43299a6220..7716a91984 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java @@ -128,7 +128,7 @@ public class MsDefinitionParser extends MsAbstractParser { Iterator iterator = modules.iterator(); while (iterator.hasNext()) { String item = iterator.next(); - parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId); + parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId, importRequest.getUserId()); if (!iterator.hasNext()) { apiDefinition.setModuleId(parent.getId()); String path = apiDefinition.getModulePath() == null ? "" : apiDefinition.getModulePath(); diff --git a/backend/src/main/java/io/metersphere/api/dto/swaggerurl/SwaggerTaskResult.java b/backend/src/main/java/io/metersphere/api/dto/swaggerurl/SwaggerTaskResult.java index 0601d0e587..e7443783c6 100644 --- a/backend/src/main/java/io/metersphere/api/dto/swaggerurl/SwaggerTaskResult.java +++ b/backend/src/main/java/io/metersphere/api/dto/swaggerurl/SwaggerTaskResult.java @@ -1,27 +1,22 @@ package io.metersphere.api.dto.swaggerurl; +import io.metersphere.base.domain.SwaggerUrlProject; import lombok.Getter; import lombok.Setter; @Getter @Setter -public class SwaggerTaskResult { +public class SwaggerTaskResult extends SwaggerUrlProject { //序号 private int index; //定时任务号 private String taskId; - //SwaggerUrlId - private String SwaggerUrlId; - //SwaggerUrl - private String swaggerUrl; - //导入模块 - private String modulePath; //同步规则 private String rule; //下次同步时间 private Long nextExecutionTime; //同步开关 - private boolean taskStatus; + private boolean enable; //定时任务类型 swaggerUrlType private String taskType; } diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index bd82f8d5d1..667771d09e 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -203,7 +203,7 @@ public class APITestService { } deleteFileByTestId(testId); apiReportService.deleteByTestId(testId); - scheduleService.deleteByResourceId(testId); + scheduleService.deleteByResourceId(testId, ScheduleGroup.API_TEST.name()); apiTestMapper.deleteByPrimaryKey(testId); deleteBodyFiles(testId); } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 758c34c7bf..d5d299cbb0 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -411,7 +411,7 @@ public class ApiAutomationService { ids.add(scenarioId); deleteApiScenarioReport(ids); - scheduleService.deleteScheduleAndJobByResourceId(scenarioId, ScheduleGroup.API_SCENARIO_TEST.name()); + scheduleService.deleteByResourceId(scenarioId, ScheduleGroup.API_SCENARIO_TEST.name()); TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); example.createCriteria().andApiScenarioIdEqualTo(scenarioId); List testPlanApiScenarioList = testPlanApiScenarioMapper.selectByExample(example); @@ -485,7 +485,7 @@ public class ApiAutomationService { } } - scheduleService.deleteByResourceId(id); + scheduleService.deleteByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name()); } if (!testPlanApiScenarioIdList.isEmpty()) { TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); @@ -507,7 +507,7 @@ public class ApiAutomationService { extApiScenarioMapper.removeToGc(apiIds); //将这些场景的定时任务删除掉 for (String id : apiIds) { - scheduleService.deleteScheduleAndJobByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name()); + scheduleService.deleteByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name()); } } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 6c717a8f6b..ca682daf27 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -12,7 +12,6 @@ import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImportParserFactory; import io.metersphere.api.dto.definition.parse.Swagger3Parser; import io.metersphere.api.dto.definition.request.ParameterConfig; -import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.scenario.Body; @@ -917,21 +916,22 @@ public class ApiDefinitionService { } /*swagger定时导入*/ - public void createSchedule(ScheduleRequest request) throws MalformedURLException { + public void createSchedule(ScheduleRequest request) { /*保存swaggerUrl*/ SwaggerUrlProject swaggerUrlProject = new SwaggerUrlProject(); + BeanUtils.copyBean(swaggerUrlProject, request); swaggerUrlProject.setId(UUID.randomUUID().toString()); - swaggerUrlProject.setProjectId(request.getProjectId()); - swaggerUrlProject.setSwaggerUrl(request.getResourceId()); - swaggerUrlProject.setModuleId(request.getModuleId()); - swaggerUrlProject.setModulePath(request.getModulePath()); - swaggerUrlProject.setModeId(request.getModeId()); scheduleService.addSwaggerUrlSchedule(swaggerUrlProject); + request.setResourceId(swaggerUrlProject.getId()); Schedule schedule = scheduleService.buildApiTestSchedule(request); schedule.setProjectId(swaggerUrlProject.getProjectId()); - java.net.URL swaggerUrl = new java.net.URL(swaggerUrlProject.getSwaggerUrl()); - schedule.setName(swaggerUrl.getHost()); // swagger 定时任务的 name 设置为 swaggerURL 的域名 + try { + schedule.setName(new java.net.URL(swaggerUrlProject.getSwaggerUrl()).getHost()); + } catch (MalformedURLException e) { + LogUtil.error(e.getMessage(), e); + MSException.throwException("URL 格式不正确!"); + } schedule.setJob(SwaggerUrlImportJob.class.getName()); schedule.setGroup(ScheduleGroup.SWAGGER_IMPORT.name()); schedule.setType(ScheduleType.CRON.name()); @@ -940,17 +940,39 @@ public class ApiDefinitionService { } - //关闭 - public void updateSchedule(Schedule request) { + public void updateSchedule(ScheduleRequest request) { + SwaggerUrlProject swaggerUrlProject = new SwaggerUrlProject(); + BeanUtils.copyBean(swaggerUrlProject, request); + scheduleService.updateSwaggerUrlSchedule(swaggerUrlProject); + // 只修改表达式和名称 + Schedule schedule = new Schedule(); + schedule.setId(request.getTaskId()); + schedule.setValue(request.getValue().trim()); + schedule.setEnable(request.getEnable()); + try { + schedule.setName(new java.net.URL(swaggerUrlProject.getSwaggerUrl()).getHost()); + } catch (MalformedURLException e) { + LogUtil.error(e.getMessage(), e); + MSException.throwException("URL 格式不正确!"); + } + scheduleService.editSchedule(schedule); + request.setResourceId(swaggerUrlProject.getId()); + this.addOrUpdateSwaggerImportCronJob(request); + } + + /** + * 列表开关切换 + * @param request + */ + public void switchSchedule(Schedule request) { scheduleService.editSchedule(request); this.addOrUpdateSwaggerImportCronJob(request); } //删除 - public void deleteSchedule(ScheduleInfoSwaggerUrlRequest request) { + public void deleteSchedule(ScheduleRequest request) { swaggerUrlProjectMapper.deleteByPrimaryKey(request.getId()); - scheduleMapper.deleteByPrimaryKey(request.getTaskId()); - + scheduleService.deleteByResourceId(request.getTaskId(), ScheduleGroup.SWAGGER_IMPORT.name()); } //查询swaggerUrl详情 @@ -974,7 +996,17 @@ public class ApiDefinitionService { } public List getSwaggerScheduleList(String projectId) { - return extSwaggerUrlScheduleMapper.getSwaggerTaskList(projectId); + List resultList = extSwaggerUrlScheduleMapper.getSwaggerTaskList(projectId); + int dataIndex = 1; + for (SwaggerTaskResult swaggerTaskResult : + resultList) { + swaggerTaskResult.setIndex(dataIndex++); + Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule()); + if (nextExecutionTime != null) { + swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime()); + } + } + return resultList; } private void addOrUpdateSwaggerImportCronJob(Schedule request) { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiModuleService.java b/backend/src/main/java/io/metersphere/api/service/ApiModuleService.java index 50ca40240c..00dfa92546 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiModuleService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiModuleService.java @@ -184,7 +184,9 @@ public class ApiModuleService extends NodeTreeService { node.setCreateTime(System.currentTimeMillis()); node.setUpdateTime(System.currentTimeMillis()); node.setId(UUID.randomUUID().toString()); - node.setCreateUser(SessionUtils.getUserId()); + if (StringUtils.isBlank(node.getCreateUser())) { + node.setCreateUser(SessionUtils.getUserId()); + } double pos = getNextLevelPos(node.getProjectId(), node.getLevel(), node.getParentId()); node.setPos(pos); apiModuleMapper.insertSelective(node); diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtSwaggerUrlScheduleMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtSwaggerUrlScheduleMapper.xml index 652f4a4808..7799b2f8d4 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtSwaggerUrlScheduleMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtSwaggerUrlScheduleMapper.xml @@ -3,14 +3,17 @@ - \ No newline at end of file + diff --git a/backend/src/main/java/io/metersphere/commons/utils/SessionUtils.java b/backend/src/main/java/io/metersphere/commons/utils/SessionUtils.java index 636053ef08..8b81a9e3e2 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/SessionUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/SessionUtils.java @@ -9,14 +9,14 @@ import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.DefaultSubjectContext; import java.util.Collection; -import java.util.Objects; import static io.metersphere.commons.constants.SessionConstants.ATTR_USER; public class SessionUtils { public static String getUserId() { - return Objects.requireNonNull(getUser()).getId(); + SessionUser user = getUser(); + return user == null ? null : user.getId(); } public static SessionUser getUser() { diff --git a/backend/src/main/java/io/metersphere/controller/request/ScheduleRequest.java b/backend/src/main/java/io/metersphere/controller/request/ScheduleRequest.java index 057f499903..901519fe19 100644 --- a/backend/src/main/java/io/metersphere/controller/request/ScheduleRequest.java +++ b/backend/src/main/java/io/metersphere/controller/request/ScheduleRequest.java @@ -24,4 +24,8 @@ public class ScheduleRequest extends Schedule { private String modeId; + private String swaggerUrl; + + private String taskId; + } diff --git a/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java b/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java index 9c188e5ae9..feb7430039 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java @@ -1,12 +1,10 @@ package io.metersphere.job.sechedule; import io.metersphere.api.dto.ApiTestImportRequest; -import io.metersphere.api.dto.definition.ApiSwaggerUrlDTO; import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.base.domain.SwaggerUrlProject; import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.service.ScheduleService; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobKey; @@ -16,7 +14,7 @@ public class SwaggerUrlImportJob extends MsScheduleJob { private ApiDefinitionService apiDefinitionService; public SwaggerUrlImportJob() { - apiDefinitionService = (ApiDefinitionService) CommonBeanFactory.getBean(ApiDefinitionService.class); + apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); } @Override @@ -31,6 +29,7 @@ public class SwaggerUrlImportJob extends MsScheduleJob { request.setPlatform("Swagger2"); request.setUserId(jobDataMap.getString("userId")); request.setType("schedule"); + request.setUserId(jobDataMap.getString("userId")); apiDefinitionService.apiTestImport(null, request); } diff --git a/backend/src/main/java/io/metersphere/listener/AppStartListener.java b/backend/src/main/java/io/metersphere/listener/AppStartListener.java index 1b408c2ba4..f3a6be5c11 100644 --- a/backend/src/main/java/io/metersphere/listener/AppStartListener.java +++ b/backend/src/main/java/io/metersphere/listener/AppStartListener.java @@ -40,7 +40,7 @@ public class AppStartListener implements ApplicationListener relatedUsers = new ArrayList<>(); diff --git a/frontend/src/business/components/api/definition/ApiDefinition.vue b/frontend/src/business/components/api/definition/ApiDefinition.vue index 91c5925652..938c80b367 100644 --- a/frontend/src/business/components/api/definition/ApiDefinition.vue +++ b/frontend/src/business/components/api/definition/ApiDefinition.vue @@ -13,6 +13,7 @@ @setModuleOptions="setModuleOptions" @setNodeTree="setNodeTree" @enableTrash="enableTrash" + @schedule="handleTabsEdit($t('api_test.definition.request.fast_debug'), 'SCHEDULE')" :type="'edit'" page-source="definition" ref="nodeTree"/> @@ -118,6 +119,12 @@ :project-id="projectId" @saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='DUBBO'"/> + + +
+ +
+
@@ -173,6 +180,7 @@ import MsTabButton from "@/business/components/common/components/MsTabButton"; import {getLabel} from "@/common/js/tableUtils"; import MockConfig from "@/business/components/api/definition/components/mock/MockConfig"; +import ApiSchedule from "@/business/components/api/definition/components/import/ApiSchedule"; export default { name: "ApiDefinition", @@ -191,6 +199,7 @@ export default { }, }, components: { + ApiSchedule, MsTabButton, MsTableButton, ApiCaseSimpleList, diff --git a/frontend/src/business/components/api/definition/components/import/ApiImport.vue b/frontend/src/business/components/api/definition/components/import/ApiImport.vue index 2b4989b1c5..35a262e07f 100644 --- a/frontend/src/business/components/api/definition/components/import/ApiImport.vue +++ b/frontend/src/business/components/api/definition/components/import/ApiImport.vue @@ -127,14 +127,16 @@ id: 'id', label: 'name', }, - modeOptions: [{ - id: 'fullCoverage', - name: this.$t('commons.cover') - }, + modeOptions: [ + { + id: 'fullCoverage', + name: this.$t('commons.cover') + }, { id: 'incrementalMerge', name: this.$t('commons.not_cover') - }], + } + ], protocol: "", platforms: [ { diff --git a/frontend/src/business/components/api/definition/components/import/ApiSchedule.vue b/frontend/src/business/components/api/definition/components/import/ApiSchedule.vue new file mode 100644 index 0000000000..22a2a9a82d --- /dev/null +++ b/frontend/src/business/components/api/definition/components/import/ApiSchedule.vue @@ -0,0 +1,256 @@ + + + + + diff --git a/frontend/src/business/components/api/definition/components/import/SwaggerTaskList.vue b/frontend/src/business/components/api/definition/components/import/SwaggerTaskList.vue index cb8a59f297..1d8ea9779d 100644 --- a/frontend/src/business/components/api/definition/components/import/SwaggerTaskList.vue +++ b/frontend/src/business/components/api/definition/components/import/SwaggerTaskList.vue @@ -1,21 +1,33 @@