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 8ec04b224d..548efbfca9 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -10,6 +10,7 @@ import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.base.domain.ApiDefinition; +import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.json.JSONSchemaGenerator; import io.metersphere.commons.utils.PageUtils; @@ -139,6 +140,11 @@ public class ApiDefinitionController { return apiDefinitionService.apiTestImport(file, request); } + @PostMapping(value = "/schedule/create") + public void createSchedule(@RequestBody Schedule request) { + apiDefinitionService.createSchedule(request); + } + @PostMapping("/getReference") public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) { return apiDefinitionService.getReference(request); @@ -165,5 +171,4 @@ public class ApiDefinitionController { public String preview(@RequestBody String jsonSchema) { return JSONSchemaGenerator.getJson(jsonSchema); } - } 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 5cc5178dd0..e5f2d6bdb4 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -24,10 +24,14 @@ import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ApiRunMode; +import io.metersphere.commons.constants.ScheduleGroup; +import io.metersphere.commons.constants.ScheduleType; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.*; import io.metersphere.i18n.Translator; +import io.metersphere.job.sechedule.SwaggerUrlImportJob; import io.metersphere.service.FileService; +import io.metersphere.service.ScheduleService; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest; import org.apache.commons.collections.CollectionUtils; @@ -73,6 +77,8 @@ public class ApiDefinitionService { private ExtTestPlanMapper extTestPlanMapper; @Resource private ProjectMapper projectMapper; + @Resource + private ScheduleService scheduleService; private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24); @@ -587,4 +593,19 @@ public class ApiDefinitionService { } } } + + /*swagger定时导入*/ + public void createSchedule(Schedule request) { + Schedule schedule = scheduleService.buildApiTestSchedule(request); + schedule.setJob(SwaggerUrlImportJob.class.getName()); + schedule.setGroup(ScheduleGroup.SWAGGER_IMPORT.name()); + schedule.setType(ScheduleType.CRON.name()); + scheduleService.addSchedule(schedule); + this.addOrUpdateSwaggerImportCronJob(request); + + } + + private void addOrUpdateSwaggerImportCronJob(Schedule request) { + scheduleService.addOrUpdateCronJob(request, SwaggerUrlImportJob.getJobKey(request.getResourceId()), SwaggerUrlImportJob.getTriggerKey(request.getResourceId()), SwaggerUrlImportJob.class); + } } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/Schedule.java b/backend/src/main/java/io/metersphere/base/domain/Schedule.java index 7637d9f699..0dcf9e8966 100644 --- a/backend/src/main/java/io/metersphere/base/domain/Schedule.java +++ b/backend/src/main/java/io/metersphere/base/domain/Schedule.java @@ -1,8 +1,9 @@ package io.metersphere.base.domain; -import java.io.Serializable; import lombok.Data; +import java.io.Serializable; + @Data public class Schedule implements Serializable { private String id; @@ -35,4 +36,6 @@ public class Schedule implements Serializable { //定时任务来源: 测试计划/测试场景 private String scheduleFrom; + + private String swaggerUrl; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.java index 174b87cc6d..c7c7ff5c38 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.java @@ -33,4 +33,6 @@ public interface ApiDefinitionExecResultMapper { int updateByPrimaryKeyWithBLOBs(ApiDefinitionExecResult record); int updateByPrimaryKey(ApiDefinitionExecResult record); + + String selectExecResult(String resourceId); } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.xml index d9592dfa3a..4e2443f552 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiDefinitionExecResultMapper.xml @@ -210,6 +210,9 @@ + update api_definition_exec_result diff --git a/backend/src/main/java/io/metersphere/commons/constants/ScheduleGroup.java b/backend/src/main/java/io/metersphere/commons/constants/ScheduleGroup.java index 90b1c5aba7..1d56f1abec 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/ScheduleGroup.java +++ b/backend/src/main/java/io/metersphere/commons/constants/ScheduleGroup.java @@ -1,5 +1,5 @@ package io.metersphere.commons.constants; public enum ScheduleGroup { - API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST,TEST_PLAN_TEST + API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT } diff --git a/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java b/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java new file mode 100644 index 0000000000..4cf4fd7479 --- /dev/null +++ b/backend/src/main/java/io/metersphere/job/sechedule/SwaggerUrlImportJob.java @@ -0,0 +1,37 @@ +package io.metersphere.job.sechedule; + +import io.metersphere.api.dto.ApiTestImportRequest; +import io.metersphere.api.service.ApiDefinitionService; +import io.metersphere.commons.constants.ScheduleGroup; +import io.metersphere.commons.utils.CommonBeanFactory; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; +import org.quartz.TriggerKey; + +public class SwaggerUrlImportJob extends MsScheduleJob { + private ApiDefinitionService apiDefinitionService; + + public SwaggerUrlImportJob() { + apiDefinitionService = (ApiDefinitionService) CommonBeanFactory.getBean(ApiDefinitionService.class); + } + + @Override + void businessExecute(JobExecutionContext context) { + JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); + String resourceId = jobDataMap.getString("resourceId"); + String swaggerUrl = jobDataMap.getString("swaggerUrl"); + ApiTestImportRequest request = new ApiTestImportRequest(); + request.setProjectId(resourceId); + request.setSwaggerUrl(swaggerUrl); + apiDefinitionService.apiTestImport(null, request); + } + + public static JobKey getJobKey(String resourceId) { + return new JobKey(resourceId, ScheduleGroup.SWAGGER_IMPORT.name()); + } + + public static TriggerKey getTriggerKey(String resourceId) { + return new TriggerKey(resourceId, ScheduleGroup.SWAGGER_IMPORT.name()); + } +} diff --git a/backend/src/main/java/io/metersphere/service/ScheduleService.java b/backend/src/main/java/io/metersphere/service/ScheduleService.java index 0b387b9f72..12820f9114 100644 --- a/backend/src/main/java/io/metersphere/service/ScheduleService.java +++ b/backend/src/main/java/io/metersphere/service/ScheduleService.java @@ -104,6 +104,7 @@ public class ScheduleService { public void startEnableSchedules() { List Schedules = getEnableSchedule(); + Schedules.forEach(schedule -> { try { if (schedule.getEnable()) { @@ -122,7 +123,7 @@ public class ScheduleService { public Schedule buildApiTestSchedule(Schedule request) { Schedule schedule = new Schedule(); schedule.setResourceId(request.getResourceId()); - schedule.setEnable(request.getEnable()); + schedule.setEnable(true); schedule.setValue(request.getValue().trim()); schedule.setKey(request.getResourceId()); schedule.setUserId(SessionUtils.getUser().getId()); diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index c2ed883e9b..7f7808c6f0 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit c2ed883e9be6fc7e01589f81916bf4ddc62148c0 +Subproject commit 7f7808c6f0457dd2df6b19a1622558f3f8122646 diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index cb789b2788..dd04068e14 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -30,10 +30,13 @@ + + + @@ -115,10 +118,14 @@ import MsTableSelectAll from "../../../common/components/table/MsTableSelectAll"; import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components"; import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton"; + import PriorityTableItem from "../../../track/common/tableItems/planview/PriorityTableItem"; + import PlanStatusTableItem from "../../../track/common/tableItems/plan/PlanStatusTableItem"; export default { name: "MsApiScenarioList", components: { + PlanStatusTableItem, + PriorityTableItem, MsTableSelectAll, MsTablePagination, MsTableMoreBtn, diff --git a/frontend/src/business/components/api/definition/components/ApiScenarioVariables.vue b/frontend/src/business/components/api/definition/components/ApiScenarioVariables.vue index c4cb506c3a..edda13459d 100644 --- a/frontend/src/business/components/api/definition/components/ApiScenarioVariables.vue +++ b/frontend/src/business/components/api/definition/components/ApiScenarioVariables.vue @@ -4,7 +4,7 @@ {{description}}
- + @@ -18,6 +18,15 @@ + + + + + + + @@ -59,6 +68,11 @@ this.items.splice(index, 1); this.$emit('change', this.items); }, + copy: function (item, index) { + let copy = {}; + Object.assign(copy, item); + this.items.splice(index + 1, 0, copy); + }, change: function () { let isNeedCreate = true; let removeIndex = -1; @@ -105,7 +119,7 @@ margin-top: 10px; } - .kv-delete { + .kv-delete,.kv-copy { width: 60px; } 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 416619781e..b119b49ad2 100644 --- a/frontend/src/business/components/api/definition/components/import/ApiImport.vue +++ b/frontend/src/business/components/api/definition/components/import/ApiImport.vue @@ -3,17 +3,17 @@ :visible.sync="visible" class="api-import" v-loading="result.loading" @close="close">
-
{{$t('api_test.api_import.data_format')}}
+
{{ $t('api_test.api_import.data_format') }}
- {{item.name}} + {{ item.name }}
- {{$t('commons.save')}} + {{ $t('commons.save') }} - {{$t('commons.cancel')}} + {{ $t('commons.cancel') }}
@@ -34,7 +34,7 @@ multiple>
-
{{$t('api_test.api_import.file_size_limit')}}
+
{{ $t('api_test.api_import.file_size_limit') }}
@@ -48,14 +48,23 @@ + + + + + +
- {{$t('api_test.api_import.tip')}}:{{selectedPlatform.tip}} + {{ $t('api_test.api_import.tip') }}:{{ selectedPlatform.tip }}
- {{$t('api_test.api_import.export_tip')}}:{{selectedPlatform.exportTip}} + {{ $t('api_test.api_import.export_tip') }}:{{ selectedPlatform.exportTip }}
@@ -63,217 +72,223 @@ diff --git a/frontend/src/business/components/api/definition/components/import/ImportScheduleEdit.vue b/frontend/src/business/components/api/definition/components/import/ImportScheduleEdit.vue new file mode 100644 index 0000000000..e8a74cb502 --- /dev/null +++ b/frontend/src/business/components/api/definition/components/import/ImportScheduleEdit.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index abefb2d306..7ab5af8958 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -829,6 +829,9 @@ export default { swagger_export_tip: "Export jSON-formatted files via Swagger website", suffixFormatErr: "The file format does not meet the requirements", swagger_url_import: "Import using URL", + timing_synchronization:"Timing synchronization", + next_synchronization_time:"Next synchronization time", + }, home_page: { unit_of_measurement: "", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index e6ca1fa2c1..c1bfaf44ac 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -831,6 +831,10 @@ export default { swagger_export_tip: "通过 Swagger 页面导出", suffixFormatErr: "文件格式不符合要求", swagger_url_import: "使用URL导入", + timing_synchronization:"定时同步", + next_synchronization_time:"下次同步时间" + + }, home_page: { unit_of_measurement: "个", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 7c785862be..2087fad310 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -830,6 +830,9 @@ export default { swagger_export_tip: "通過 Swagger 頁面導出", suffixFormatErr: "文件格式不符合要求", swagger_url_import: "使用URL導入", + timing_synchronization:"定時同步", + next_synchronization_time:"下次同步時間", + }, home_page: { unit_of_measurement: "個",