feat(测试计划,定时任务,场景): 支持资源池执行
This commit is contained in:
parent
1043012172
commit
49dae56d76
|
@ -9,4 +9,5 @@ public class RunModeConfig {
|
|||
private String reportName;
|
||||
private String reportId;
|
||||
private boolean onSampleError;
|
||||
private String resourcePoolId;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.response.Response;
|
||||
import lombok.Getter;
|
||||
|
@ -34,6 +35,8 @@ public class RunDefinitionRequest {
|
|||
|
||||
private Response response;
|
||||
|
||||
private RunModeConfig config;
|
||||
|
||||
private List<String> bodyUploadIds;
|
||||
|
||||
private Map<String, String> environmentMap;
|
||||
|
|
|
@ -311,7 +311,8 @@ public class JMeterService {
|
|||
List<Object> jarFiles = getJar();
|
||||
|
||||
// 获取可以执行的资源池
|
||||
TestResource testResource = resourcePoolCalculation.getPool();
|
||||
String resourcePoolId = config.getResourcePoolId();
|
||||
TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId);
|
||||
|
||||
String configuration = testResource.getConfiguration();
|
||||
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
|
||||
|
|
|
@ -33,10 +33,10 @@ public class ResourcePoolCalculation {
|
|||
return restTemplate.getForObject(uri, JvmInfoDTO.class);
|
||||
}
|
||||
|
||||
public TestResource getPool() {
|
||||
public TestResource getPool(String resourcePoolId) {
|
||||
// 获取可以执行的资源池
|
||||
TestResourcePoolExample example = new TestResourcePoolExample();
|
||||
example.createCriteria().andStatusEqualTo("VALID").andTypeEqualTo("NODE").andNameEqualTo("赵勇资源池");
|
||||
example.createCriteria().andStatusEqualTo("VALID").andTypeEqualTo("NODE").andIdEqualTo(resourcePoolId);
|
||||
List<TestResourcePool> pools = testResourcePoolMapper.selectByExample(example);
|
||||
// 按照NODE节点的可用内存空间大小排序
|
||||
JvmInfoDTO jvmInfoDTO = null;
|
||||
|
|
|
@ -1088,8 +1088,11 @@ public class ApiAutomationService {
|
|||
List<String> reportIds = new LinkedList<>();
|
||||
try {
|
||||
HashTree hashTree = generateHashTree(apiScenarios, request, reportIds);
|
||||
jMeterService.runSerial(JSON.toJSONString(reportIds), hashTree, request.getReportId(), runMode, request.getConfig());
|
||||
// jMeterService.runTest(JSON.toJSONString(reportIds), hashTree, runMode, false, request.getConfig());
|
||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||
jMeterService.runTest(JSON.toJSONString(reportIds), hashTree, runMode, false, request.getConfig());
|
||||
} else {
|
||||
jMeterService.runSerial(JSON.toJSONString(reportIds), hashTree, request.getReportId(), runMode, request.getConfig());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage());
|
||||
|
@ -1110,8 +1113,10 @@ public class ApiAutomationService {
|
|||
if (request.getIds().size() > count) {
|
||||
MSException.throwException("并发数量过大,请重新选择!");
|
||||
}
|
||||
return this.modeRun(request);
|
||||
} else {
|
||||
return this.excute(request);
|
||||
}
|
||||
return this.modeRun(request);
|
||||
} else {
|
||||
return this.excute(request);
|
||||
}
|
||||
|
|
|
@ -578,8 +578,11 @@ public class ApiDefinitionService {
|
|||
runMode = ApiRunMode.API_PLAN.name();
|
||||
}
|
||||
// 调用执行方法
|
||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), runMode);
|
||||
//jMeterService.runTest(request.getId(), hashTree, runMode, request.getReportId() != null, null);
|
||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||
jMeterService.runTest(request.getId(), hashTree, runMode, request.getReportId() != null, request.getConfig());
|
||||
} else {
|
||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), runMode);
|
||||
}
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,5 +33,7 @@ public class Schedule implements Serializable {
|
|||
|
||||
private String name;
|
||||
|
||||
private String config;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1053,6 +1053,76 @@ public class ScheduleExample {
|
|||
addCriterion("`name` not between", value1, value2, "name");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigIsNull() {
|
||||
addCriterion("config is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigIsNotNull() {
|
||||
addCriterion("config is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigEqualTo(String value) {
|
||||
addCriterion("config =", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigNotEqualTo(String value) {
|
||||
addCriterion("config <>", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigGreaterThan(String value) {
|
||||
addCriterion("config >", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("config >=", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigLessThan(String value) {
|
||||
addCriterion("config <", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigLessThanOrEqualTo(String value) {
|
||||
addCriterion("config <=", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigLike(String value) {
|
||||
addCriterion("config like", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigNotLike(String value) {
|
||||
addCriterion("config not like", value, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigIn(List<String> values) {
|
||||
addCriterion("config in", values, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigNotIn(List<String> values) {
|
||||
addCriterion("config not in", values, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigBetween(String value1, String value2) {
|
||||
addCriterion("config between", value1, value2, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andConfigNotBetween(String value1, String value2) {
|
||||
addCriterion("config not between", value1, value2, "config");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="config" jdbcType="VARCHAR" property="config" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -77,7 +78,7 @@
|
|||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, `key`, `type`, `value`, `group`, job, `enable`, resource_id, user_id, workspace_id,
|
||||
create_time, update_time, project_id, `name`
|
||||
create_time, update_time, project_id, `name`, config
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.ScheduleExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -114,12 +115,14 @@
|
|||
`value`, `group`, job,
|
||||
`enable`, resource_id, user_id,
|
||||
workspace_id, create_time, update_time,
|
||||
project_id, `name`)
|
||||
project_id, `name`, config
|
||||
)
|
||||
values (#{id,jdbcType=VARCHAR}, #{key,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
||||
#{value,jdbcType=VARCHAR}, #{group,jdbcType=VARCHAR}, #{job,jdbcType=VARCHAR},
|
||||
#{enable,jdbcType=BIT}, #{resourceId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR},
|
||||
#{workspaceId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR})
|
||||
#{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{config,jdbcType=VARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.Schedule">
|
||||
insert into schedule
|
||||
|
@ -166,6 +169,9 @@
|
|||
<if test="name != null">
|
||||
`name`,
|
||||
</if>
|
||||
<if test="config != null">
|
||||
config,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -210,6 +216,9 @@
|
|||
<if test="name != null">
|
||||
#{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="config != null">
|
||||
#{config,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.ScheduleExample" resultType="java.lang.Long">
|
||||
|
@ -263,6 +272,9 @@
|
|||
<if test="record.name != null">
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.config != null">
|
||||
config = #{record.config,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -283,7 +295,8 @@
|
|||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
`name` = #{record.name,jdbcType=VARCHAR}
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
config = #{record.config,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -330,6 +343,9 @@
|
|||
<if test="name != null">
|
||||
`name` = #{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="config != null">
|
||||
config = #{config,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -347,7 +363,8 @@
|
|||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
`name` = #{name,jdbcType=VARCHAR}
|
||||
`name` = #{name,jdbcType=VARCHAR},
|
||||
config = #{config,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -1,6 +1,8 @@
|
|||
package io.metersphere.job.sechedule;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.automation.ExecuteType;
|
||||
import io.metersphere.api.dto.automation.RunModeConfig;
|
||||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
|
@ -8,6 +10,7 @@ import io.metersphere.commons.constants.ReportTriggerMode;
|
|||
import io.metersphere.commons.constants.ScheduleGroup;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.quartz.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -16,15 +19,17 @@ import java.util.UUID;
|
|||
|
||||
/**
|
||||
* 情景测试Job
|
||||
*
|
||||
* @author song.tianyang
|
||||
* @Date 2020/12/22 2:59 下午
|
||||
* @Description
|
||||
*/
|
||||
public class ApiScenarioTestJob extends MsScheduleJob {
|
||||
private String projectID;
|
||||
public class ApiScenarioTestJob extends MsScheduleJob {
|
||||
private String projectID;
|
||||
private List<String> scenarioIds;
|
||||
|
||||
private ApiAutomationService apiAutomationService;
|
||||
|
||||
public ApiScenarioTestJob() {
|
||||
apiAutomationService = (ApiAutomationService) CommonBeanFactory.getBean(ApiAutomationService.class);
|
||||
}
|
||||
|
@ -38,7 +43,7 @@ public class ApiScenarioTestJob extends MsScheduleJob {
|
|||
this.userId = jobDataMap.getString("userId");
|
||||
this.expression = jobDataMap.getString("expression");
|
||||
this.projectID = jobDataMap.getString("projectId");
|
||||
if(resourceId!=null){
|
||||
if (resourceId != null) {
|
||||
scenarioIds = new ArrayList<>();
|
||||
scenarioIds.add(resourceId);
|
||||
}
|
||||
|
@ -61,6 +66,13 @@ public class ApiScenarioTestJob extends MsScheduleJob {
|
|||
request.setReportUserID(this.userId);
|
||||
request.setRunMode(ApiRunMode.SCHEDULE_SCENARIO.name());
|
||||
|
||||
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
||||
String config = jobDataMap.getString("config");
|
||||
if (StringUtils.isNotBlank(config)) {
|
||||
RunModeConfig runModeConfig = JSONObject.parseObject(config, RunModeConfig.class);
|
||||
request.setConfig(runModeConfig);
|
||||
}
|
||||
|
||||
apiAutomationService.run(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.job.sechedule;
|
||||
|
||||
import io.metersphere.base.domain.Schedule;
|
||||
import io.metersphere.commons.constants.ScheduleGroup;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.python.antlr.ast.Str;
|
||||
|
@ -290,11 +291,13 @@ public class ScheduleManager {
|
|||
addOrUpdateCronJob(jobKey, triggerKey, jobClass, cron, null);
|
||||
}
|
||||
|
||||
public JobDataMap getDefaultJobDataMap(String resourceId, String expression, String userId) {
|
||||
public JobDataMap getDefaultJobDataMap(Schedule schedule, String expression, String userId) {
|
||||
JobDataMap jobDataMap = new JobDataMap();
|
||||
jobDataMap.put("resourceId", resourceId);
|
||||
jobDataMap.put("resourceId", schedule.getResourceId());
|
||||
jobDataMap.put("expression", expression);
|
||||
jobDataMap.put("userId", userId);
|
||||
jobDataMap.put("config", schedule.getConfig());
|
||||
|
||||
return jobDataMap;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ public class ScheduleService {
|
|||
LogUtil.info("初始化任务:" + JSON.toJSONString(schedule));
|
||||
scheduleManager.addOrUpdateCronJob(new JobKey(schedule.getKey(), schedule.getGroup()),
|
||||
new TriggerKey(schedule.getKey(), schedule.getGroup()), Class.forName(schedule.getJob()), schedule.getValue(),
|
||||
scheduleManager.getDefaultJobDataMap(schedule.getResourceId(), schedule.getValue(), schedule.getUserId()));
|
||||
scheduleManager.getDefaultJobDataMap(schedule, schedule.getValue(), schedule.getUserId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("初始化任务失败", e);
|
||||
|
@ -166,7 +166,7 @@ public class ScheduleService {
|
|||
if (enable != null && enable && StringUtils.isNotBlank(cronExpression)) {
|
||||
try {
|
||||
scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, clazz, cronExpression,
|
||||
scheduleManager.getDefaultJobDataMap(request.getResourceId(), cronExpression, SessionUtils.getUser().getId()));
|
||||
scheduleManager.getDefaultJobDataMap(request, cronExpression, SessionUtils.getUser().getId()));
|
||||
} catch (SchedulerException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException("定时任务开启异常");
|
||||
|
|
|
@ -15,16 +15,23 @@ UPDATE load_test_report JOIN load_test ON load_test.id = load_test_report.test_i
|
|||
SET load_test_report.test_name = load_test.name;
|
||||
-- api_environment_running_param
|
||||
CREATE TABLE IF NOT EXISTS api_environment_running_param (
|
||||
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`api_enviroment_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
|
||||
`create_time` bigint(13) NULL DEFAULT NULL,
|
||||
`update_time` bigint(13) NULL DEFAULT NULL,
|
||||
`create_user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`update_user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `api_enviroment_id`(`api_enviroment_id`) USING BTREE,
|
||||
INDEX `key_api_enviroment_id`(`api_enviroment_id`,`key`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`api_enviroment_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
|
||||
`create_time` bigint(13) NULL DEFAULT NULL,
|
||||
`update_time` bigint(13) NULL DEFAULT NULL,
|
||||
`create_user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`update_user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `api_enviroment_id` (`api_enviroment_id`) USING BTREE,
|
||||
INDEX `key_api_enviroment_id` (`api_enviroment_id`, `key`) USING BTREE
|
||||
) ENGINE = InnoDB
|
||||
CHARACTER SET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
ROW_FORMAT = Dynamic;
|
||||
|
||||
-- schedule
|
||||
alter table schedule
|
||||
add config VARCHAR(500) null;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
destroy-on-close
|
||||
:title="$t('load_test.runtime_config')"
|
||||
width="350px"
|
||||
:visible.sync="runModeVisible"
|
||||
destroy-on-close
|
||||
:title="$t('load_test.runtime_config')"
|
||||
width="450px"
|
||||
:visible.sync="runModeVisible"
|
||||
>
|
||||
<div>
|
||||
<span class="ms-mode-span">{{ $t("run_mode.title") }}:</span>
|
||||
|
@ -13,19 +13,41 @@
|
|||
</el-radio-group>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.mode === 'serial'">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.other_config") }}:</span>
|
||||
<el-radio-group v-model="runConfig.reportType">
|
||||
<el-radio label="iddReport">{{ $t("run_mode.idd_report") }}</el-radio>
|
||||
<el-radio label="setReport">{{ $t("run_mode.set_report") }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.other_config") }}:</span>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div>
|
||||
<el-radio-group v-model="runConfig.reportType">
|
||||
<el-radio label="iddReport">{{ $t("run_mode.idd_report") }}</el-radio>
|
||||
<el-radio label="setReport">{{ $t("run_mode.set_report") }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div style="padding-top: 10px">
|
||||
<el-checkbox v-model="runConfig.runWithinResourcePool" style="padding-right: 10px;">
|
||||
{{ $t('run_mode.run_with_resource_pool') }}
|
||||
</el-checkbox>
|
||||
<el-select :disabled="!runConfig.runWithinResourcePool" v-model="runConfig.resourcePoolId" size="mini">
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.reportType === 'setReport' && runConfig.mode==='serial'">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.report_name") }}:</span>
|
||||
<el-input
|
||||
v-model="runConfig.reportName"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
size="small"
|
||||
style="width: 200px"
|
||||
v-model="runConfig.reportName"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
size="small"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</div>
|
||||
<template v-slot:footer>
|
||||
|
@ -35,43 +57,63 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||
|
||||
export default {
|
||||
name: "RunMode",
|
||||
components: {MsDialogFooter},
|
||||
data() {
|
||||
return {
|
||||
runModeVisible: false,
|
||||
runConfig: {mode: "serial", reportType: "iddReport", reportName: ""},
|
||||
export default {
|
||||
name: "RunMode",
|
||||
components: {MsDialogFooter},
|
||||
data() {
|
||||
return {
|
||||
runModeVisible: false,
|
||||
testType: null,
|
||||
resourcePools: [],
|
||||
runConfig: {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
reportName: "",
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.runModeVisible = true;
|
||||
this.getResourcePools();
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
reportName: "",
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
};
|
||||
this.runModeVisible = false;
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.runModeVisible = true;
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {mode: "serial", reportType: "iddReport", reportName: ""};
|
||||
this.runModeVisible = false;
|
||||
},
|
||||
handleRunBatch() {
|
||||
if (this.runConfig.mode === 'serial' && this.runConfig.reportType === 'setReport' && this.runConfig.reportName.trim() === "") {
|
||||
this.$warning(this.$t('commons.input_name'));
|
||||
return;
|
||||
}
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
handleRunBatch() {
|
||||
if (this.runConfig.mode === 'serial' && this.runConfig.reportType === 'setReport' && this.runConfig.reportName.trim() === "") {
|
||||
this.$warning(this.$t('commons.input_name'));
|
||||
return;
|
||||
}
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
};
|
||||
getResourcePools() {
|
||||
this.result = this.$get('/testresourcepool/list/quota/valid', response => {
|
||||
this.resourcePools = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ms-mode-span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.ms-mode-span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-mode-div {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.ms-mode-div {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<schedule-switch :schedule="schedule" :corn-value="form.cronValue" @resultListChange="getExecuteTimeTemplate" @scheduleChange="scheduleChange"></schedule-switch>
|
||||
<schedule-switch :schedule="schedule" :corn-value="form.cronValue"
|
||||
@resultListChange="getExecuteTimeTemplate"
|
||||
@scheduleChange="scheduleChange"></schedule-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
@ -174,15 +176,15 @@ export default {
|
|||
|
||||
if (this.isTesterPermission) {
|
||||
this.result = this.$post('user/org/member/list/all', param, response => {
|
||||
this.scheduleReceiverOptions = response.data
|
||||
this.scheduleReceiverOptions = response.data;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
buildParam() {
|
||||
let param = {};
|
||||
param.notices = this.tableData
|
||||
param.testId = this.testId
|
||||
param.notices = this.tableData;
|
||||
param.testId = this.testId;
|
||||
return param;
|
||||
},
|
||||
open(row) {
|
||||
|
@ -202,7 +204,7 @@ export default {
|
|||
this.dialogVisible = true;
|
||||
this.form.cronValue = this.schedule.value;
|
||||
listenGoBack(this.close);
|
||||
this.activeName = 'first'
|
||||
this.activeName = 'first';
|
||||
},
|
||||
findSchedule() {
|
||||
var scheduleResourceID = this.testId;
|
||||
|
@ -228,7 +230,7 @@ export default {
|
|||
this.$refs['from'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.intervalShortValidate();
|
||||
let formCronValue = this.form.cronValue
|
||||
let formCronValue = this.form.cronValue;
|
||||
this.schedule.enable = true;
|
||||
this.schedule.value = formCronValue;
|
||||
this.saveSchedule();
|
||||
|
@ -301,7 +303,7 @@ export default {
|
|||
let time2 = new Date(resultList[1]);
|
||||
return time2 - time1;
|
||||
},
|
||||
getExecuteTimeTemplate(executeTileArr){
|
||||
getExecuteTimeTemplate(executeTileArr) {
|
||||
alert(executeTileArr);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<el-dialog
|
||||
destroy-on-close
|
||||
:title="$t('load_test.runtime_config')"
|
||||
width="350px"
|
||||
width="450px"
|
||||
:visible.sync="runModeVisible"
|
||||
>
|
||||
<div>
|
||||
|
@ -13,8 +13,29 @@
|
|||
</el-radio-group>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.mode === 'serial'">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.other_config") }}:</span>
|
||||
<el-checkbox v-model="runConfig.onSampleError">失败停止</el-checkbox>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.other_config") }}:</span>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div>
|
||||
<el-checkbox v-model="runConfig.onSampleError">失败停止</el-checkbox>
|
||||
</div>
|
||||
<div v-if="testType === 'API'" style="padding-top: 10px">
|
||||
<el-checkbox v-model="runConfig.runWithinResourcePool" style="padding-right: 10px;">
|
||||
{{ $t('run_mode.run_with_resource_pool') }}
|
||||
</el-checkbox>
|
||||
<el-select :disabled="!runConfig.runWithinResourcePool" v-model="runConfig.resourcePoolId" size="mini">
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="close" @confirm="handleRunBatch"/>
|
||||
|
@ -23,39 +44,60 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||
|
||||
export default {
|
||||
name: "MsPlanRunMode",
|
||||
components: {MsDialogFooter},
|
||||
data() {
|
||||
return {
|
||||
runModeVisible: false,
|
||||
runConfig: {mode: "serial", reportType: "iddReport", onSampleError: false},
|
||||
export default {
|
||||
name: "MsPlanRunMode",
|
||||
components: {MsDialogFooter},
|
||||
data() {
|
||||
return {
|
||||
runModeVisible: false,
|
||||
testType: null,
|
||||
resourcePools: [],
|
||||
runConfig: {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open(testType) {
|
||||
this.runModeVisible = true;
|
||||
this.testType = testType;
|
||||
this.getResourcePools();
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
};
|
||||
this.runModeVisible = false;
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.runModeVisible = true;
|
||||
},
|
||||
close() {
|
||||
this.runConfig = {mode: "serial", reportType: "iddReport", onSampleError: false};
|
||||
this.runModeVisible = false;
|
||||
},
|
||||
handleRunBatch() {
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
handleRunBatch() {
|
||||
this.$emit("handleRunBatch", this.runConfig);
|
||||
this.close();
|
||||
},
|
||||
};
|
||||
getResourcePools() {
|
||||
this.result = this.$get('/testresourcepool/list/quota/valid', response => {
|
||||
this.resourcePools = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ms-mode-span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.ms-mode-span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-mode-div {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.ms-mode-div {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,398 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
v-loading="result.loading"
|
||||
:close-on-click-modal="false" width="60%" class="schedule-edit" :visible.sync="dialogVisible"
|
||||
:append-to-body='true'
|
||||
@close="close">
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('schedule.task_config')" name="first">
|
||||
<div class="el-step__icon is-text" style="margin-right: 10px;">
|
||||
<div class="el-step__icon-inner">1</div>
|
||||
</div>
|
||||
<span>{{ $t('schedule.edit_timer_task') }}</span>
|
||||
<el-form :model="form" :rules="rules" ref="from" style="padding-top: 10px;margin-left: 20px;">
|
||||
<el-form-item
|
||||
prop="cronValue">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-input :disabled="isReadOnly" v-model="form.cronValue" class="inp"
|
||||
:placeholder="$t('schedule.please_input_cron_expression')"/>
|
||||
<el-button :disabled="isReadOnly" type="primary" @click="saveCron" v-tester>{{
|
||||
$t('commons.save')
|
||||
}}
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<schedule-switch :schedule="schedule" :corn-value="form.cronValue"
|
||||
@resultListChange="getExecuteTimeTemplate"
|
||||
@scheduleChange="scheduleChange"></schedule-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">
|
||||
{{ $t('schedule.generate_expression') }}
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
<crontab-result :ex="form.cronValue" ref="crontabResult"/>
|
||||
</el-form>
|
||||
|
||||
<div class="el-step__icon is-text" style="margin-right: 10px;">
|
||||
<div class="el-step__icon-inner">2</div>
|
||||
</div>
|
||||
<span>{{ $t('load_test.runtime_config') }}</span>
|
||||
<div style="padding-top: 10px;">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.title") }}:</span>
|
||||
<el-radio-group v-model="runConfig.mode">
|
||||
<el-radio label="serial">{{ $t("run_mode.serial") }}</el-radio>
|
||||
<el-radio label="parallel">{{ $t("run_mode.parallel") }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="ms-mode-div" v-if="runConfig.mode === 'serial'">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<span class="ms-mode-span">{{ $t("run_mode.other_config") }}:</span>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<div>
|
||||
<el-checkbox v-model="runConfig.onSampleError">失败停止</el-checkbox>
|
||||
</div>
|
||||
<div v-if="scheduleTaskType === 'TEST_PLAN_TEST'" style="padding-top: 10px">
|
||||
<el-checkbox v-model="runConfig.runWithinResourcePool" style="padding-right: 10px;">
|
||||
{{ $t('run_mode.run_with_resource_pool') }}
|
||||
</el-checkbox>
|
||||
<el-select :disabled="!runConfig.runWithinResourcePool" v-model="runConfig.resourcePoolId"
|
||||
size="mini">
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-dialog width="60%" :title="$t('schedule.generate_expression')" :visible.sync="showCron"
|
||||
:modal="false">
|
||||
<crontab @hide="showCron=false" @fill="crontabFill" :expression="schedule.value"
|
||||
ref="crontab"/>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('schedule.task_notification')" name="second">
|
||||
<ms-schedule-notification :is-tester-permission="isTesterPermission" :test-id="testId"
|
||||
:schedule-receiver-options="scheduleReceiverOptions"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {checkoutTestManagerOrTestUser, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import Crontab from "@/business/components/common/cron/Crontab";
|
||||
import CrontabResult from "@/business/components/common/cron/CrontabResult";
|
||||
import {cronValidate} from "@/common/js/cron";
|
||||
import MsScheduleNotification from "@/business/components/api/automation/schedule/ScheduleNotification";
|
||||
import ScheduleSwitch from "@/business/components/api/automation/schedule/ScheduleSwitch";
|
||||
|
||||
function defaultCustomValidate() {
|
||||
return {pass: true};
|
||||
}
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
|
||||
export default {
|
||||
name: "MsTestPlanScheduleMaintain",
|
||||
components: {
|
||||
CrontabResult,
|
||||
ScheduleSwitch,
|
||||
Crontab,
|
||||
MsScheduleNotification,
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
|
||||
props: {
|
||||
customValidate: {
|
||||
type: Function,
|
||||
default: defaultCustomValidate
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
'schedule.value'() {
|
||||
this.form.cronValue = this.schedule.value;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateCron = (rule, cronValue, callback) => {
|
||||
let customValidate = this.customValidate(this.getIntervalTime());
|
||||
if (!cronValue) {
|
||||
callback(new Error(this.$t('commons.input_content')));
|
||||
} else if (!cronValidate(cronValue)) {
|
||||
callback(new Error(this.$t('schedule.cron_expression_format_error')));
|
||||
} else if (!customValidate.pass) {
|
||||
callback(new Error(customValidate.info));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
result: {},
|
||||
scheduleReceiverOptions: [],
|
||||
operation: true,
|
||||
dialogVisible: false,
|
||||
schedule: {
|
||||
value: "",
|
||||
},
|
||||
scheduleTaskType: "",
|
||||
testId: String,
|
||||
showCron: false,
|
||||
form: {
|
||||
cronValue: ""
|
||||
},
|
||||
paramRow: {},
|
||||
activeName: 'first',
|
||||
rules: {
|
||||
cronValue: [{required: true, validator: validateCron, trigger: 'blur'}],
|
||||
},
|
||||
resourcePools: [],
|
||||
runConfig: {
|
||||
mode: "serial",
|
||||
reportType: "iddReport",
|
||||
onSampleError: false,
|
||||
runWithinResourcePool: false,
|
||||
resourcePoolId: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
currentUser: () => {
|
||||
return getCurrentUser();
|
||||
},
|
||||
scheduleChange() {
|
||||
let flag = this.schedule.enable;
|
||||
let param = {};
|
||||
param.taskID = this.schedule.id;
|
||||
param.enable = flag;
|
||||
let that = this;
|
||||
if (flag === false) {
|
||||
this.$confirm(this.$t('api_test.home_page.running_task_list.confirm.close_title'), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning',
|
||||
beforeClose(action, instance, done) {
|
||||
if (action === 'cancel') { // 否则在 messageBox 点击取消后,switch 按钮仍然会被关闭
|
||||
that.schedule.enable = param.enable = true;
|
||||
}
|
||||
done(); // done 是关闭 messageBox 的行为
|
||||
},
|
||||
}).then(() => {
|
||||
this.updateTask(param);
|
||||
}).catch(() => {
|
||||
});
|
||||
} else {
|
||||
this.updateTask(param);
|
||||
}
|
||||
},
|
||||
updateTask(param) {
|
||||
this.result = this.$post('/api/schedule/updateEnableByPrimyKey', param, response => {
|
||||
let paramTestId = "";
|
||||
if (this.paramRow.redirectFrom === 'testPlan') {
|
||||
paramTestId = this.paramRow.id;
|
||||
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||
} else {
|
||||
paramTestId = this.paramRow.id;
|
||||
this.scheduleTaskType = "API_SCENARIO_TEST";
|
||||
}
|
||||
this.taskID = paramTestId;
|
||||
this.findSchedule(paramTestId);
|
||||
});
|
||||
},
|
||||
initUserList() {
|
||||
let param = {
|
||||
name: '',
|
||||
organizationId: this.currentUser().lastOrganizationId
|
||||
};
|
||||
|
||||
if (this.isTesterPermission) {
|
||||
this.result = this.$post('user/org/member/list/all', param, response => {
|
||||
this.scheduleReceiverOptions = response.data;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
buildParam() {
|
||||
let param = {};
|
||||
param.notices = this.tableData;
|
||||
param.testId = this.testId;
|
||||
return param;
|
||||
},
|
||||
open(row) {
|
||||
//测试计划页面跳转来的
|
||||
let paramTestId = "";
|
||||
this.paramRow = row;
|
||||
if (row.redirectFrom === 'testPlan') {
|
||||
paramTestId = row.id;
|
||||
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||
} else {
|
||||
paramTestId = row.id;
|
||||
this.scheduleTaskType = "API_SCENARIO_TEST";
|
||||
}
|
||||
this.testId = paramTestId;
|
||||
this.findSchedule(paramTestId);
|
||||
this.initUserList();
|
||||
this.dialogVisible = true;
|
||||
this.form.cronValue = this.schedule.value;
|
||||
listenGoBack(this.close);
|
||||
this.activeName = 'first';
|
||||
this.getResourcePools();
|
||||
},
|
||||
findSchedule() {
|
||||
var scheduleResourceID = this.testId;
|
||||
var taskType = this.scheduleTaskType;
|
||||
this.result = this.$get("/schedule/findOne/" + scheduleResourceID + "/" + taskType, response => {
|
||||
if (response.data != null) {
|
||||
this.schedule = response.data;
|
||||
this.runConfig = JSON.parse(response.data.config);
|
||||
} else {
|
||||
this.schedule = {};
|
||||
}
|
||||
});
|
||||
},
|
||||
crontabFill(value, resultList) {
|
||||
//确定后回传的值
|
||||
this.form.cronValue = value;
|
||||
this.$refs.crontabResult.resultList = resultList;
|
||||
this.$refs['from'].validate();
|
||||
},
|
||||
showCronDialog() {
|
||||
this.showCron = true;
|
||||
},
|
||||
saveCron() {
|
||||
this.$refs['from'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.intervalShortValidate();
|
||||
let formCronValue = this.form.cronValue;
|
||||
this.schedule.enable = true;
|
||||
this.schedule.value = formCronValue;
|
||||
this.saveSchedule();
|
||||
this.dialogVisible = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
saveSchedule() {
|
||||
this.checkScheduleEdit();
|
||||
let param = {};
|
||||
param = this.schedule;
|
||||
param.resourceId = this.testId;
|
||||
param.config = JSON.stringify(this.runConfig);
|
||||
let url = '/api/automation/schedule/create';
|
||||
if (this.scheduleTaskType === "TEST_PLAN_TEST") {
|
||||
param.scheduleFrom = "testPlan";
|
||||
//测试计划页面跳转的创建
|
||||
url = '/schedule/create';
|
||||
if (param.id) {
|
||||
url = '/schedule/update';
|
||||
}
|
||||
} else {
|
||||
param.scheduleFrom = "scenario";
|
||||
if (param.id) {
|
||||
url = '/api/automation/schedule/update';
|
||||
}
|
||||
}
|
||||
|
||||
this.$post(url, param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit("refreshTable");
|
||||
});
|
||||
},
|
||||
checkScheduleEdit() {
|
||||
if (this.create) {
|
||||
this.$message(this.$t('api_test.environment.please_save_test'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
saveNotice() {
|
||||
let param = this.buildParam();
|
||||
this.result = this.$post("notice/save", param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.dialogVisible = false;
|
||||
this.form.cronValue = '';
|
||||
this.$refs['from'].resetFields();
|
||||
if (!this.schedule.value) {
|
||||
this.$refs.crontabResult.resultList = [];
|
||||
}
|
||||
removeGoBackListener(this.close);
|
||||
},
|
||||
intervalShortValidate() {
|
||||
if (this.getIntervalTime() < 3 * 60 * 1000) {
|
||||
// return false;
|
||||
this.$info(this.$t('schedule.cron_expression_interval_short_error'));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
resultListChange() {
|
||||
this.$refs['from'].validate();
|
||||
},
|
||||
getIntervalTime() {
|
||||
let resultList = this.$refs.crontabResult.resultList;
|
||||
let time1 = new Date(resultList[0]);
|
||||
let time2 = new Date(resultList[1]);
|
||||
return time2 - time1;
|
||||
},
|
||||
getExecuteTimeTemplate(executeTileArr) {
|
||||
alert(executeTileArr);
|
||||
},
|
||||
getResourcePools() {
|
||||
this.result = this.$get('/testresourcepool/list/quota/valid', response => {
|
||||
this.resourcePools = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isTesterPermission() {
|
||||
return checkoutTestManagerOrTestUser();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.inp {
|
||||
width: 50%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ms-mode-span {
|
||||
margin-right: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.ms-mode-div {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
|
@ -96,7 +96,7 @@
|
|||
show-overflow-tooltip
|
||||
:key="index">
|
||||
</el-table-column>
|
||||
<el-table-column v-if="item.id == 'tags'" prop="tags"
|
||||
<el-table-column v-if="item.id == 'tags'" prop="tags"
|
||||
:label="$t('api_test.automation.tag')" :key="index">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
|
||||
|
@ -205,7 +205,7 @@
|
|||
:with-tip="enableDeleteTip">
|
||||
{{ $t('test_track.plan.plan_delete_tip') }}
|
||||
</ms-delete-confirm>
|
||||
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="initTableData"/>
|
||||
<ms-test-plan-schedule-maintain ref="scheduleMaintain" @refreshTable="initTableData"/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
|
@ -218,20 +218,19 @@ import MsTableOperatorButton from "../../../common/components/MsTableOperatorBut
|
|||
import MsTableOperator from "../../../common/components/MsTableOperator";
|
||||
import PlanStatusTableItem from "../../common/tableItems/plan/PlanStatusTableItem";
|
||||
import PlanStageTableItem from "../../common/tableItems/plan/PlanStageTableItem";
|
||||
import {checkoutTestManagerOrTestUser, getCurrentUser} from "@/common/js/utils";
|
||||
import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
|
||||
import TestReportTemplateList from "../view/comonents/TestReportTemplateList";
|
||||
import TestCaseReportView from "../view/comonents/report/TestCaseReportView";
|
||||
import MsDeleteConfirm from "../../../common/components/MsDeleteConfirm";
|
||||
import {TEST_PLAN_CONFIGS} from "../../../common/components/search/search-components";
|
||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||
import MsScheduleMaintain from "@/business/components/api/automation/schedule/ScheduleMaintain"
|
||||
import {_filter, _sort, getLabel} from "@/common/js/tableUtils";
|
||||
import {TEST_PLAN_LIST} from "@/common/js/constants";
|
||||
import {Test_Plan_List} from "@/business/components/common/model/JsonData";
|
||||
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
|
||||
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
|
||||
import MsTag from "@/business/components/common/components/MsTag";
|
||||
|
||||
import MsTestPlanScheduleMaintain from "@/business/components/track/plan/components/ScheduleMaintain";
|
||||
|
||||
export default {
|
||||
name: "TestPlanList",
|
||||
|
@ -244,7 +243,7 @@ export default {
|
|||
TestReportTemplateList,
|
||||
PlanStageTableItem,
|
||||
PlanStatusTableItem,
|
||||
MsScheduleMaintain,
|
||||
MsTestPlanScheduleMaintain,
|
||||
MsTableOperator, MsTableOperatorButton, MsDialogFooter, MsTableHeader, MsCreateBox, MsTablePagination
|
||||
},
|
||||
data() {
|
||||
|
@ -275,7 +274,7 @@ export default {
|
|||
{text: this.$t('test_track.plan.system_test'), value: 'system'},
|
||||
{text: this.$t('test_track.plan.regression_test'), value: 'regression'},
|
||||
],
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
|
@ -294,10 +293,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
inite() {
|
||||
this.initTableData()
|
||||
this.initTableData();
|
||||
},
|
||||
customHeader() {
|
||||
this.$refs.headerCustom.open(this.tableLabel)
|
||||
this.$refs.headerCustom.open(this.tableLabel);
|
||||
},
|
||||
initTableData() {
|
||||
if (this.planId) {
|
||||
|
@ -317,14 +316,14 @@ export default {
|
|||
if (item.tags && item.tags.length > 0) {
|
||||
item.tags = JSON.parse(item.tags);
|
||||
}
|
||||
item.passRate = item.passRate + '%'
|
||||
})
|
||||
item.passRate = item.passRate + '%';
|
||||
});
|
||||
});
|
||||
getLabel(this, TEST_PLAN_LIST);
|
||||
|
||||
},
|
||||
copyData(status) {
|
||||
return JSON.parse(JSON.stringify(this.dataMap.get(status)))
|
||||
return JSON.parse(JSON.stringify(this.dataMap.get(status)));
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
|
@ -396,12 +395,12 @@ export default {
|
|||
this.$refs.testCaseReportView.open(planId, reportId);
|
||||
}
|
||||
},
|
||||
scheduleTask(row){
|
||||
scheduleTask(row) {
|
||||
row.redirectFrom = "testPlan";
|
||||
this.$refs.scheduleMaintain.open(row);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<el-card class="card-content" v-loading="result.loading">
|
||||
<template v-slot:header>
|
||||
<test-plan-case-list-header
|
||||
:project-id="getProjectId()"
|
||||
:condition="condition"
|
||||
:plan-id="planId"
|
||||
@refresh="initTable"
|
||||
@relevanceCase="$emit('relevanceCase')"
|
||||
@setEnvironment="setEnvironment"
|
||||
v-if="isPlanModel"/>
|
||||
:project-id="getProjectId()"
|
||||
:condition="condition"
|
||||
:plan-id="planId"
|
||||
@refresh="initTable"
|
||||
@relevanceCase="$emit('relevanceCase')"
|
||||
@setEnvironment="setEnvironment"
|
||||
v-if="isPlanModel"/>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="result.loading" ref="table"
|
||||
|
@ -31,65 +31,67 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
<template v-for="(item, index) in tableLabel">
|
||||
<el-table-column v-if="item.id == 'num'" prop="num" sortable="custom" label="ID" min-width="80" show-overflow-tooltip
|
||||
<el-table-column v-if="item.id == 'num'" prop="num" sortable="custom" label="ID" min-width="80"
|
||||
show-overflow-tooltip
|
||||
:key="index"/>
|
||||
<el-table-column v-if="item.id == 'name'" prop="name" sortable="custom" min-width="120"
|
||||
<el-table-column v-if="item.id == 'name'" prop="name" sortable="custom" min-width="120"
|
||||
:label="$t('api_test.definition.api_name')" show-overflow-tooltip :key="index"/>
|
||||
|
||||
<el-table-column
|
||||
v-if="item.id == 'priority'"
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
sortable="custom"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip
|
||||
min-width="120"
|
||||
:key="index">
|
||||
v-if="item.id == 'priority'"
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
sortable="custom"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip
|
||||
min-width="120"
|
||||
:key="index">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
v-if="item.id == 'path'"
|
||||
min-width="100"
|
||||
prop="path"
|
||||
:label="$t('api_test.definition.api_path')"
|
||||
show-overflow-tooltip
|
||||
:key="index"/>
|
||||
v-if="item.id == 'path'"
|
||||
min-width="100"
|
||||
prop="path"
|
||||
:label="$t('api_test.definition.api_path')"
|
||||
show-overflow-tooltip
|
||||
:key="index"/>
|
||||
|
||||
<el-table-column
|
||||
v-if="item.id == 'createUser'"
|
||||
prop="createUser"
|
||||
column-key="user_id"
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
:filters="userFilters"
|
||||
:label="'创建人'"
|
||||
show-overflow-tooltip
|
||||
:key="index"/>
|
||||
v-if="item.id == 'createUser'"
|
||||
prop="createUser"
|
||||
column-key="user_id"
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
:filters="userFilters"
|
||||
:label="'创建人'"
|
||||
show-overflow-tooltip
|
||||
:key="index"/>
|
||||
|
||||
<el-table-column
|
||||
v-if="item.id == 'custom'"
|
||||
sortable="custom"
|
||||
min-width="160"
|
||||
:label="$t('api_test.definition.api_last_time')"
|
||||
prop="updateTime"
|
||||
:key="index">
|
||||
v-if="item.id == 'custom'"
|
||||
sortable="custom"
|
||||
min-width="160"
|
||||
:label="$t('api_test.definition.api_last_time')"
|
||||
prop="updateTime"
|
||||
:key="index">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
v-if="item.id == 'tags'"
|
||||
prop="tags"
|
||||
min-width="100"
|
||||
:label="$t('commons.tag')"
|
||||
:key="index">
|
||||
v-if="item.id == 'tags'"
|
||||
prop="tags"
|
||||
min-width="100"
|
||||
:label="$t('commons.tag')"
|
||||
:key="index">
|
||||
<template v-slot:default="scope">
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
|
||||
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
|
||||
:content="itemName" style="margin-left: 0px; margin-right: 2px"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
@ -113,7 +115,7 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column fixed="right" min-width="100" v-if="!isReadOnly" :label="$t('commons.operating')" >
|
||||
<el-table-column fixed="right" min-width="100" v-if="!isReadOnly" :label="$t('commons.operating')">
|
||||
<template slot="header">
|
||||
<header-label-operate @exec="customHeader"/>
|
||||
</template>
|
||||
|
@ -173,16 +175,15 @@ import ThreadGroup from "../../../../../api/definition/components/jmeter/compone
|
|||
import {TEST_PLAN_API_CASE, WORKSPACE_ID} from "@/common/js/constants";
|
||||
import {
|
||||
_filter,
|
||||
_handleSelect,
|
||||
_handleSelectAll,
|
||||
_sort,
|
||||
getLabel,
|
||||
_handleSelect,
|
||||
initCondition,
|
||||
setUnSelectIds,
|
||||
getSelectDataCounts,
|
||||
toggleAllSelection,
|
||||
buildBatchParam,
|
||||
checkTableRowIsSelect
|
||||
checkTableRowIsSelect,
|
||||
getLabel,
|
||||
getSelectDataCounts,
|
||||
setUnSelectIds,
|
||||
toggleAllSelection
|
||||
} from "@/common/js/tableUtils";
|
||||
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
|
||||
import {Test_Plan_Api_Case} from "@/business/components/common/model/JsonData";
|
||||
|
@ -261,7 +262,7 @@ export default {
|
|||
userFilters: [],
|
||||
projectIds: [],
|
||||
projectList: []
|
||||
}
|
||||
};
|
||||
},
|
||||
props: {
|
||||
currentProtocol: String,
|
||||
|
@ -285,7 +286,7 @@ export default {
|
|||
model: {
|
||||
type: String,
|
||||
default() {
|
||||
'api'
|
||||
'api';
|
||||
}
|
||||
},
|
||||
planId: String,
|
||||
|
@ -298,7 +299,7 @@ export default {
|
|||
|
||||
},
|
||||
activated() {
|
||||
this.status = 'default'
|
||||
this.status = 'default';
|
||||
},
|
||||
watch: {
|
||||
selectNodeIds() {
|
||||
|
@ -318,27 +319,27 @@ export default {
|
|||
computed: {
|
||||
// 测试计划关联测试列表
|
||||
isRelevanceModel() {
|
||||
return this.model === 'relevance'
|
||||
return this.model === 'relevance';
|
||||
},
|
||||
// 测试计划接口用例列表
|
||||
isPlanModel() {
|
||||
return this.model === 'plan'
|
||||
return this.model === 'plan';
|
||||
},
|
||||
// 接口定义用例列表
|
||||
isApiModel() {
|
||||
return this.model === 'api'
|
||||
return this.model === 'api';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
customHeader() {
|
||||
this.$refs.headerCustom.open(this.tableLabel)
|
||||
this.$refs.headerCustom.open(this.tableLabel);
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||
this.valueArr.userId = response.data;
|
||||
this.userFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id}
|
||||
return {text: u.name, value: u.id};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -376,8 +377,8 @@ export default {
|
|||
setTimeout(this.$refs.table.doLayout, 200);
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
checkTableRowIsSelect(this,this.condition,this.tableData,this.$refs.table,this.selectRows);
|
||||
})
|
||||
checkTableRowIsSelect(this, this.condition, this.tableData, this.$refs.table, this.selectRows);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (this.planId) {
|
||||
|
@ -395,8 +396,8 @@ export default {
|
|||
setTimeout(this.$refs.table.doLayout, 200);
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
checkTableRowIsSelect(this,this.condition,this.tableData,this.$refs.table,this.selectRows);
|
||||
})
|
||||
checkTableRowIsSelect(this, this.condition, this.tableData, this.$refs.table, this.selectRows);
|
||||
});
|
||||
});
|
||||
}
|
||||
getLabel(this, TEST_PLAN_API_CASE);
|
||||
|
@ -447,7 +448,7 @@ export default {
|
|||
let param = buildBatchParam(this);
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
if (this.reviewId) {
|
||||
param.testCaseReviewId = this.reviewId
|
||||
param.testCaseReviewId = this.reviewId;
|
||||
this.$post('/test/case/review/api/case/batch/delete', param, () => {
|
||||
this.selectRows.clear();
|
||||
this.initTable();
|
||||
|
@ -464,22 +465,22 @@ export default {
|
|||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getResult(data) {
|
||||
if (RESULT_MAP.get(data)) {
|
||||
return RESULT_MAP.get(data);
|
||||
} else {
|
||||
return RESULT_MAP.get("default");
|
||||
}
|
||||
},
|
||||
runRefresh(data) {
|
||||
this.rowLoading = "";
|
||||
this.$success(this.$t('schedule.event_success'));
|
||||
this.initTable();
|
||||
},
|
||||
});
|
||||
},
|
||||
getResult(data) {
|
||||
if (RESULT_MAP.get(data)) {
|
||||
return RESULT_MAP.get(data);
|
||||
} else {
|
||||
return RESULT_MAP.get("default");
|
||||
}
|
||||
},
|
||||
runRefresh(data) {
|
||||
this.rowLoading = "";
|
||||
this.$success(this.$t('schedule.event_success'));
|
||||
this.initTable();
|
||||
},
|
||||
singleRun(row) {
|
||||
this.runData = [];
|
||||
this.rowLoading = row.id;
|
||||
|
@ -567,11 +568,11 @@ export default {
|
|||
// 批量修改其它
|
||||
}
|
||||
},
|
||||
orderBySelectRows(rows){
|
||||
orderBySelectRows(rows) {
|
||||
let selectIds = Array.from(rows).map(row => row.id);
|
||||
let array = [];
|
||||
for(let i in this.tableData){
|
||||
if(selectIds.indexOf(this.tableData[i].id)!==-1){
|
||||
for (let i in this.tableData) {
|
||||
if (selectIds.indexOf(this.tableData[i].id) !== -1) {
|
||||
array.push(this.tableData[i]);
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +581,7 @@ export default {
|
|||
handleBatchExecute() {
|
||||
this.getData().then(() => {
|
||||
if (this.runData && this.runData.length > 0) {
|
||||
this.$refs.runMode.open();
|
||||
this.$refs.runMode.open('API');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -597,7 +598,14 @@ export default {
|
|||
threadGroup.hashTree.push(item);
|
||||
testPlan.hashTree.push(threadGroup);
|
||||
});
|
||||
let reqObj = {id: getUUID().substring(0, 8), testElement: testPlan, type: 'API_PLAN', reportId: "run", projectId: projectId};
|
||||
let reqObj = {
|
||||
id: getUUID().substring(0, 8),
|
||||
testElement: testPlan,
|
||||
type: 'API_PLAN',
|
||||
reportId: "run",
|
||||
projectId: projectId,
|
||||
config: config
|
||||
};
|
||||
let bodyFiles = getBodyUploadFiles(reqObj, this.runData);
|
||||
this.$fileUpload("/api/definition/run", null, bodyFiles, reqObj, response => {
|
||||
this.$message('任务执行中,请稍后刷新查看结果');
|
||||
|
@ -610,7 +618,13 @@ export default {
|
|||
this.runData.forEach(item => {
|
||||
threadGroup.hashTree.push(item);
|
||||
});
|
||||
let reqObj = {id: getUUID().substring(0, 8), testElement: testPlan, type: 'API_PLAN', reportId: "run", projectId: projectId};
|
||||
let reqObj = {
|
||||
id: getUUID().substring(0, 8),
|
||||
testElement: testPlan,
|
||||
type: 'API_PLAN',
|
||||
reportId: "run",
|
||||
projectId: projectId
|
||||
};
|
||||
let bodyFiles = getBodyUploadFiles(reqObj, this.runData);
|
||||
this.$fileUpload("/api/definition/run", null, bodyFiles, reqObj, response => {
|
||||
this.$message('任务执行中,请稍后刷新查看结果');
|
||||
|
@ -673,7 +687,7 @@ export default {
|
|||
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card class="table-card" v-loading="loading">
|
||||
<div class="card-container">
|
||||
<el-card class="card-content" v-loading="loading">
|
||||
<template v-slot:header>
|
||||
<test-plan-scenario-list-header
|
||||
:condition="condition"
|
||||
|
@ -8,10 +8,11 @@
|
|||
@relevanceCase="$emit('relevanceCase', 'scenario')"/>
|
||||
</template>
|
||||
|
||||
<el-table ref="scenarioTable" border :data="tableData" class="test-content adjust-table ms-select-all-fixed" @select-all="handleSelectAll"
|
||||
<el-table ref="scenarioTable" border :data="tableData" class="test-content adjust-table ms-select-all-fixed"
|
||||
@select-all="handleSelectAll"
|
||||
:height="screenHeight"
|
||||
@select="handleSelect">
|
||||
<el-table-column type="selection"/>
|
||||
<el-table-column width="50" type="selection"/>
|
||||
<ms-table-header-select-popover v-show="total>0"
|
||||
:page-size="pageSize > total ? total : pageSize"
|
||||
:total="total"
|
||||
|
@ -171,7 +172,7 @@ export default {
|
|||
return {
|
||||
type: TEST_PLAN_SCENARIO_CASE,
|
||||
headerItems: Test_Plan_Scenario_Case,
|
||||
screenHeight: document.documentElement.clientHeight - 348,//屏幕高度
|
||||
screenHeight: 'calc(100vh - 330px)',//屏幕高度
|
||||
tableLabel: [],
|
||||
loading: false,
|
||||
condition: {},
|
||||
|
@ -180,7 +181,7 @@ export default {
|
|||
selectAll: false,
|
||||
tableData: [],
|
||||
currentPage: 1,
|
||||
selectDataCounts:0,
|
||||
selectDataCounts: 0,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
reportId: "",
|
||||
|
@ -297,7 +298,7 @@ export default {
|
|||
})
|
||||
},
|
||||
handleBatchExecute() {
|
||||
this.$refs.runMode.open();
|
||||
this.$refs.runMode.open('API');
|
||||
},
|
||||
orderBySelectRows(rows){
|
||||
let selectIds = Array.from(rows).map(row => row.id);
|
||||
|
|
|
@ -1658,6 +1658,7 @@ export default {
|
|||
not_set: "Not Set",
|
||||
next_execution_time: "Next Execution Time",
|
||||
edit_timer_task: "Edit Timer Task",
|
||||
task_config: "Task Config",
|
||||
test_name: 'Test Name',
|
||||
running_rule: 'Rule',
|
||||
job_status: 'Status',
|
||||
|
@ -1803,5 +1804,6 @@ export default {
|
|||
idd_report: "Report",
|
||||
set_report: "Set report",
|
||||
report_name: "Report name",
|
||||
run_with_resource_pool: "Run Within Resource pool",
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1670,6 +1670,7 @@ export default {
|
|||
running_task: '运行中的任务',
|
||||
next_execution_time: "下次执行时间",
|
||||
edit_timer_task: "编辑定时任务",
|
||||
task_config: "任务配置",
|
||||
please_input_cron_expression: "请输入 Cron 表达式",
|
||||
generate_expression: "生成表达式",
|
||||
cron_expression_format_error: "Cron 表达式格式错误",
|
||||
|
@ -1811,5 +1812,6 @@ export default {
|
|||
idd_report: "独立报告",
|
||||
set_report: "集合报告",
|
||||
report_name: "报告名称",
|
||||
run_with_resource_pool: "资源池运行",
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1670,6 +1670,7 @@ export default {
|
|||
running_task: '運行中的任務',
|
||||
next_execution_time: "下次執行時間",
|
||||
edit_timer_task: "編輯定時任務",
|
||||
task_config: "任務配置",
|
||||
please_input_cron_expression: "請輸入 Cron 表達式",
|
||||
generate_expression: "生成表達式",
|
||||
cron_expression_format_error: "Cron 表達式格式錯誤",
|
||||
|
@ -1811,5 +1812,6 @@ export default {
|
|||
idd_report: "獨立報告",
|
||||
set_report: "集合報告",
|
||||
report_name: "報告名稱",
|
||||
run_with_resource_pool: "資源池運行",
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue