Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
48b0adc065
|
@ -290,7 +290,9 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
|||
}
|
||||
refSet.add(simpleRef);
|
||||
Model model = definitions.get(simpleRef);
|
||||
if (model != null) {
|
||||
jsonObject.put(key, getBodyParameters(model.getProperties(), refSet));
|
||||
}
|
||||
} else {
|
||||
jsonObject.put(key, getDefaultValueByPropertyType(value));
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ public class ApiDefinitionExecResultService {
|
|||
saveResult.setCreateTime(System.currentTimeMillis());
|
||||
saveResult.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
||||
saveResult.setName(item.getName());
|
||||
if (item.getName().indexOf("<->") != -1) {
|
||||
saveResult.setName(item.getName().substring(0, item.getName().indexOf("<->")));
|
||||
}
|
||||
saveResult.setResourceId(item.getName());
|
||||
saveResult.setContent(JSON.toJSONString(item));
|
||||
saveResult.setStartTime(item.getStartTime());
|
||||
|
|
|
@ -14,6 +14,7 @@ import io.metersphere.api.dto.scenario.request.RequestType;
|
|||
import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult;
|
||||
import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.RequestResult;
|
||||
import io.metersphere.api.jmeter.TestResult;
|
||||
import io.metersphere.api.parse.ApiImportParser;
|
||||
import io.metersphere.api.parse.ApiImportParserFactory;
|
||||
|
@ -297,7 +298,7 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private ApiDefinition importCreate(ApiDefinitionResult request, ApiDefinitionMapper batchMapper,ApiTestImportRequest apiTestImportRequest) {
|
||||
private ApiDefinition importCreate(ApiDefinitionResult request, ApiDefinitionMapper batchMapper, ApiTestImportRequest apiTestImportRequest) {
|
||||
SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest();
|
||||
BeanUtils.copyBean(saveReq, request);
|
||||
final ApiDefinitionWithBLOBs apiDefinition = new ApiDefinitionWithBLOBs();
|
||||
|
@ -313,7 +314,7 @@ public class ApiDefinitionService {
|
|||
apiDefinition.setDescription(request.getDescription());
|
||||
|
||||
List<ApiDefinition> sameRequest = getSameRequest(saveReq);
|
||||
if(StringUtils.equals("fullCoverage",apiTestImportRequest.getModeId())){
|
||||
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
|
||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||
batchMapper.insert(apiDefinition);
|
||||
} else {
|
||||
|
@ -321,9 +322,9 @@ public class ApiDefinitionService {
|
|||
apiDefinition.setId(sameRequest.get(0).getId());
|
||||
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
|
||||
}
|
||||
}else if(StringUtils.equals("incrementalMerge",apiTestImportRequest.getModeId())){
|
||||
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
||||
batchMapper.insert(apiDefinition);
|
||||
}else{
|
||||
} else {
|
||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||
batchMapper.insert(apiDefinition);
|
||||
} else {
|
||||
|
@ -372,7 +373,11 @@ public class ApiDefinitionService {
|
|||
|
||||
public void addResult(TestResult res) {
|
||||
if (!res.getScenarios().isEmpty() && !res.getScenarios().get(0).getRequestResults().isEmpty()) {
|
||||
cache.put(res.getTestId(), res.getScenarios().get(0).getRequestResults().get(0));
|
||||
RequestResult result = res.getScenarios().get(0).getRequestResults().get(0);
|
||||
if (result.getName().indexOf("<->") != -1) {
|
||||
result.setName(result.getName().substring(0, result.getName().indexOf("<->")));
|
||||
}
|
||||
cache.put(res.getTestId(), result);
|
||||
} else {
|
||||
MSException.throwException(Translator.get("test_not_found"));
|
||||
}
|
||||
|
@ -451,7 +456,7 @@ public class ApiDefinitionService {
|
|||
item.setName(item.getName().substring(0, 255));
|
||||
}
|
||||
item.setNum(num++);
|
||||
importCreate(item, batchMapper,request);
|
||||
importCreate(item, batchMapper, request);
|
||||
if (i % 300 == 0) {
|
||||
sqlSession.flushStatements();
|
||||
}
|
||||
|
@ -614,7 +619,7 @@ public class ApiDefinitionService {
|
|||
/*swagger定时导入*/
|
||||
public void createSchedule(Schedule request) {
|
||||
/*保存swaggerUrl*/
|
||||
SwaggerUrlProject swaggerUrlProject=new SwaggerUrlProject();
|
||||
SwaggerUrlProject swaggerUrlProject = new SwaggerUrlProject();
|
||||
swaggerUrlProject.setId(UUID.randomUUID().toString());
|
||||
swaggerUrlProject.setProjectId(request.getProjectId());
|
||||
swaggerUrlProject.setSwaggerUrl(request.getResourceId());
|
||||
|
@ -631,33 +636,38 @@ public class ApiDefinitionService {
|
|||
this.addOrUpdateSwaggerImportCronJob(request);
|
||||
|
||||
}
|
||||
|
||||
//关闭
|
||||
public void updateSchedule(Schedule request){
|
||||
public void updateSchedule(Schedule request) {
|
||||
scheduleService.editSchedule(request);
|
||||
this.addOrUpdateSwaggerImportCronJob(request);
|
||||
}
|
||||
|
||||
//删除
|
||||
public void deleteSchedule(ScheduleInfoSwaggerUrlRequest request){
|
||||
public void deleteSchedule(ScheduleInfoSwaggerUrlRequest request) {
|
||||
swaggerUrlProjectMapper.deleteByPrimaryKey(request.getId());
|
||||
scheduleMapper.deleteByPrimaryKey(request.getTaskId());
|
||||
|
||||
}
|
||||
|
||||
//查询swaggerUrl详情
|
||||
public SwaggerUrlProject getSwaggerInfo(String resourceId){
|
||||
public SwaggerUrlProject getSwaggerInfo(String resourceId) {
|
||||
return swaggerUrlProjectMapper.selectByPrimaryKey(resourceId);
|
||||
}
|
||||
public String getResourceId(SwaggerUrlRequest swaggerUrlRequest){
|
||||
SwaggerUrlProjectExample swaggerUrlProjectExample=new SwaggerUrlProjectExample();
|
||||
SwaggerUrlProjectExample.Criteria criteria=swaggerUrlProjectExample.createCriteria();
|
||||
|
||||
public String getResourceId(SwaggerUrlRequest swaggerUrlRequest) {
|
||||
SwaggerUrlProjectExample swaggerUrlProjectExample = new SwaggerUrlProjectExample();
|
||||
SwaggerUrlProjectExample.Criteria criteria = swaggerUrlProjectExample.createCriteria();
|
||||
criteria.andProjectIdEqualTo(swaggerUrlRequest.getProjectId()).andSwaggerUrlEqualTo(swaggerUrlRequest.getSwaggerUrl()).andModuleIdEqualTo(swaggerUrlRequest.getModuleId());
|
||||
List<SwaggerUrlProject> list=swaggerUrlProjectMapper.selectByExample(swaggerUrlProjectExample);
|
||||
String resourceId="";
|
||||
if(list.size()==1){
|
||||
resourceId=list.get(0).getId();
|
||||
List<SwaggerUrlProject> list = swaggerUrlProjectMapper.selectByExample(swaggerUrlProjectExample);
|
||||
String resourceId = "";
|
||||
if (list.size() == 1) {
|
||||
resourceId = list.get(0).getId();
|
||||
}
|
||||
return resourceId;
|
||||
}
|
||||
public List<SwaggerTaskResult> getSwaggerScheduleList(String projectId){
|
||||
|
||||
public List<SwaggerTaskResult> getSwaggerScheduleList(String projectId) {
|
||||
return extSwaggerUrlScheduleMapper.getSwaggerTaskList(projectId);
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ public class HistoricalDataUpgradeService {
|
|||
}
|
||||
}
|
||||
if (!isJsonType) {
|
||||
request1.getHeaders().add(new KeyValue("Content-Type", "application/json"));
|
||||
request1.getHeaders().set(request1.getHeaders().size() - 1, new KeyValue("Content-Type", "application/json"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,6 +412,7 @@ public class HistoricalDataUpgradeService {
|
|||
MsScenario step = new MsScenario();
|
||||
step.setId(scenario1.getId());
|
||||
step.setName(scenario1.getName());
|
||||
step.setEnable(scenario.isEnable());
|
||||
step.setType("scenario");
|
||||
step.setResourceId(UUID.randomUUID().toString());
|
||||
step.setReferenced("REF");
|
||||
|
|
|
@ -33,5 +33,7 @@ public class TestPlanReport implements Serializable {
|
|||
|
||||
private String principal;
|
||||
|
||||
private String components;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -1013,6 +1013,76 @@ public class TestPlanReportExample {
|
|||
addCriterion("principal not between", value1, value2, "principal");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsIsNull() {
|
||||
addCriterion("components is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsIsNotNull() {
|
||||
addCriterion("components is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsEqualTo(String value) {
|
||||
addCriterion("components =", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsNotEqualTo(String value) {
|
||||
addCriterion("components <>", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsGreaterThan(String value) {
|
||||
addCriterion("components >", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("components >=", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsLessThan(String value) {
|
||||
addCriterion("components <", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsLessThanOrEqualTo(String value) {
|
||||
addCriterion("components <=", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsLike(String value) {
|
||||
addCriterion("components like", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsNotLike(String value) {
|
||||
addCriterion("components not like", value, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsIn(List<String> values) {
|
||||
addCriterion("components in", values, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsNotIn(List<String> values) {
|
||||
addCriterion("components not in", values, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsBetween(String value1, String value2) {
|
||||
addCriterion("components between", value1, value2, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andComponentsNotBetween(String value1, String value2) {
|
||||
addCriterion("components not between", value1, value2, "components");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
<result column="creator" jdbcType="VARCHAR" property="creator" />
|
||||
<result column="start_time" jdbcType="BIGINT" property="startTime" />
|
||||
<result column="end_time" jdbcType="BIGINT" property="endTime" />
|
||||
<result column="is_api_case_executing" jdbcType="BIT" property="isApiCaseExecuting" />
|
||||
<result column="is_scenario_executing" jdbcType="BIT" property="isScenarioExecuting" />
|
||||
<result column="is_performance_executing" jdbcType="BIT" property="isPerformanceExecuting" />
|
||||
<result column="is_api_case_executing" jdbcType="TINYINT" property="isApiCaseExecuting" />
|
||||
<result column="is_scenario_executing" jdbcType="TINYINT" property="isScenarioExecuting" />
|
||||
<result column="is_performance_executing" jdbcType="TINYINT" property="isPerformanceExecuting" />
|
||||
<result column="principal" jdbcType="VARCHAR" property="principal" />
|
||||
<result column="components" jdbcType="VARCHAR" property="components" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -78,7 +79,7 @@
|
|||
<sql id="Base_Column_List">
|
||||
id, test_plan_id, create_time, update_time, `name`, `status`, trigger_mode, creator,
|
||||
start_time, end_time, is_api_case_executing, is_scenario_executing, is_performance_executing,
|
||||
principal
|
||||
principal, components
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.TestPlanReportExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -115,12 +116,14 @@
|
|||
update_time, `name`, `status`,
|
||||
trigger_mode, creator, start_time,
|
||||
end_time, is_api_case_executing, is_scenario_executing,
|
||||
is_performance_executing, principal)
|
||||
is_performance_executing, principal, components
|
||||
)
|
||||
values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{updateTime,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||
#{triggerMode,jdbcType=VARCHAR}, #{creator,jdbcType=VARCHAR}, #{startTime,jdbcType=BIGINT},
|
||||
#{endTime,jdbcType=BIGINT}, #{isApiCaseExecuting,jdbcType=BIT}, #{isScenarioExecuting,jdbcType=BIT},
|
||||
#{isPerformanceExecuting,jdbcType=BIT}, #{principal,jdbcType=VARCHAR})
|
||||
#{endTime,jdbcType=BIGINT}, #{isApiCaseExecuting,jdbcType=TINYINT}, #{isScenarioExecuting,jdbcType=TINYINT},
|
||||
#{isPerformanceExecuting,jdbcType=TINYINT}, #{principal,jdbcType=VARCHAR}, #{components,jdbcType=VARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanReport">
|
||||
insert into test_plan_report
|
||||
|
@ -167,6 +170,9 @@
|
|||
<if test="principal != null">
|
||||
principal,
|
||||
</if>
|
||||
<if test="components != null">
|
||||
components,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -200,17 +206,20 @@
|
|||
#{endTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="isApiCaseExecuting != null">
|
||||
#{isApiCaseExecuting,jdbcType=BIT},
|
||||
#{isApiCaseExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="isScenarioExecuting != null">
|
||||
#{isScenarioExecuting,jdbcType=BIT},
|
||||
#{isScenarioExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="isPerformanceExecuting != null">
|
||||
#{isPerformanceExecuting,jdbcType=BIT},
|
||||
#{isPerformanceExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="principal != null">
|
||||
#{principal,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="components != null">
|
||||
#{components,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.TestPlanReportExample" resultType="java.lang.Long">
|
||||
|
@ -253,17 +262,20 @@
|
|||
end_time = #{record.endTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.isApiCaseExecuting != null">
|
||||
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=BIT},
|
||||
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="record.isScenarioExecuting != null">
|
||||
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=BIT},
|
||||
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="record.isPerformanceExecuting != null">
|
||||
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=BIT},
|
||||
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="record.principal != null">
|
||||
principal = #{record.principal,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.components != null">
|
||||
components = #{record.components,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -281,10 +293,11 @@
|
|||
creator = #{record.creator,jdbcType=VARCHAR},
|
||||
start_time = #{record.startTime,jdbcType=BIGINT},
|
||||
end_time = #{record.endTime,jdbcType=BIGINT},
|
||||
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=BIT},
|
||||
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=BIT},
|
||||
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=BIT},
|
||||
principal = #{record.principal,jdbcType=VARCHAR}
|
||||
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=TINYINT},
|
||||
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=TINYINT},
|
||||
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=TINYINT},
|
||||
principal = #{record.principal,jdbcType=VARCHAR},
|
||||
components = #{record.components,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -320,17 +333,20 @@
|
|||
end_time = #{endTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="isApiCaseExecuting != null">
|
||||
is_api_case_executing = #{isApiCaseExecuting,jdbcType=BIT},
|
||||
is_api_case_executing = #{isApiCaseExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="isScenarioExecuting != null">
|
||||
is_scenario_executing = #{isScenarioExecuting,jdbcType=BIT},
|
||||
is_scenario_executing = #{isScenarioExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="isPerformanceExecuting != null">
|
||||
is_performance_executing = #{isPerformanceExecuting,jdbcType=BIT},
|
||||
is_performance_executing = #{isPerformanceExecuting,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="principal != null">
|
||||
principal = #{principal,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="components != null">
|
||||
components = #{components,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -345,10 +361,11 @@
|
|||
creator = #{creator,jdbcType=VARCHAR},
|
||||
start_time = #{startTime,jdbcType=BIGINT},
|
||||
end_time = #{endTime,jdbcType=BIGINT},
|
||||
is_api_case_executing = #{isApiCaseExecuting,jdbcType=BIT},
|
||||
is_scenario_executing = #{isScenarioExecuting,jdbcType=BIT},
|
||||
is_performance_executing = #{isPerformanceExecuting,jdbcType=BIT},
|
||||
principal = #{principal,jdbcType=VARCHAR}
|
||||
is_api_case_executing = #{isApiCaseExecuting,jdbcType=TINYINT},
|
||||
is_scenario_executing = #{isScenarioExecuting,jdbcType=TINYINT},
|
||||
is_performance_executing = #{isPerformanceExecuting,jdbcType=TINYINT},
|
||||
principal = #{principal,jdbcType=VARCHAR},
|
||||
components = #{components,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -0,0 +1,4 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
public interface ExtBaseMapper {
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtBaseMapper">
|
||||
|
||||
|
||||
<sql id="orders">
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="condition">
|
||||
<choose>
|
||||
<when test='${object}.operator == "like"'>
|
||||
like CONCAT('%', #{${object}.value},'%')
|
||||
</when>
|
||||
<when test='${object}.operator == "not like"'>
|
||||
not like CONCAT('%', #{${object}.value},'%')
|
||||
</when>
|
||||
<when test='${object}.operator == "in"'>
|
||||
in
|
||||
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test='${object}.operator == "not in"'>
|
||||
not in
|
||||
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test='${object}.operator == "between"'>
|
||||
between #{${object}.value[0]} and #{${object}.value[1]}
|
||||
</when>
|
||||
<when test='${object}.operator == "gt"'>
|
||||
> #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "lt"'>
|
||||
< #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "ge"'>
|
||||
>= #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "le"'>
|
||||
<= #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "current user"'>
|
||||
= '${@io.metersphere.commons.utils.SessionUtils@getUserId()}'
|
||||
</when>
|
||||
<otherwise>
|
||||
= #{${object}.value}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.TestCase;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
||||
|
@ -46,4 +47,5 @@ public interface ExtTestCaseMapper {
|
|||
*/
|
||||
int checkIsHave(@Param("caseId") String caseId, @Param("workspaceIds") Set<String> workspaceIds);
|
||||
|
||||
List<String> selectIds(@Param("request") BaseQueryRequest condition);
|
||||
}
|
||||
|
|
|
@ -2,102 +2,58 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestCaseMapper">
|
||||
|
||||
<sql id="condition">
|
||||
<choose>
|
||||
<when test='${object}.operator == "like"'>
|
||||
like CONCAT('%', #{${object}.value},'%')
|
||||
</when>
|
||||
<when test='${object}.operator == "not like"'>
|
||||
not like CONCAT('%', #{${object}.value},'%')
|
||||
</when>
|
||||
<when test='${object}.operator == "in"'>
|
||||
in
|
||||
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test='${object}.operator == "not in"'>
|
||||
not in
|
||||
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||
#{v}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test='${object}.operator == "between"'>
|
||||
between #{${object}.value[0]} and #{${object}.value[1]}
|
||||
</when>
|
||||
<when test='${object}.operator == "gt"'>
|
||||
> #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "lt"'>
|
||||
< #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "ge"'>
|
||||
>= #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "le"'>
|
||||
<= #{${object}.value}
|
||||
</when>
|
||||
<when test='${object}.operator == "current user"'>
|
||||
= '${@io.metersphere.commons.utils.SessionUtils@getUserId()}'
|
||||
</when>
|
||||
<otherwise>
|
||||
= #{${object}.value}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<sql id="combine">
|
||||
<if test='${condition}.name != null and (${name} == null or ${name} == "")'>
|
||||
and test_case.name
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.name"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.module != null">
|
||||
and test_case.node_path
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.module"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.priority != null">
|
||||
and test_case.priority
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.priority"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.createTime != null">
|
||||
and test_case.create_time
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.createTime"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.type != null">
|
||||
and test_case.type
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.type"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.updateTime != null">
|
||||
and test_case.update_time
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.updateTime"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.method != null">
|
||||
and test_case.method
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.method"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.creator != null">
|
||||
and test_case.maintainer
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.creator"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.tags != null">
|
||||
and test_case.tags
|
||||
<include refid="condition">
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
|
||||
<property name="object" value="${condition}.tags"/>
|
||||
</include>
|
||||
</if>
|
||||
|
@ -129,32 +85,7 @@
|
|||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='priority'">
|
||||
and test_case.priority in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='status'">
|
||||
and test_case.review_status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
and test_case.type in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
|
@ -184,32 +115,7 @@
|
|||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='priority'">
|
||||
and test_case.priority in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='status'">
|
||||
and test_case.review_status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
and test_case.type in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
|
@ -236,32 +142,7 @@
|
|||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='priority'">
|
||||
and test_case.priority in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='status'">
|
||||
and test_case.review_status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
and test_case.type in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
|
@ -277,66 +158,8 @@
|
|||
<include refid="io.metersphere.base.mapper.TestCaseMapper.Base_Column_List"/>
|
||||
</if>
|
||||
from test_case
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
<property name="name" value="request.name"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and (test_case.name like CONCAT('%', #{request.name},'%')
|
||||
or test_case.num like CONCAT('%', #{request.name},'%')
|
||||
or test_case.tags like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.nodeIds != null and request.nodeIds.size() > 0">
|
||||
and test_case.node_id in
|
||||
<foreach collection="request.nodeIds" item="nodeId" separator="," open="(" close=")">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
and test_case.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='priority'">
|
||||
and test_case.priority in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='type'">
|
||||
and test_case.type in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='status'">
|
||||
and test_case.review_status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
and test_case.method in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
<select id="listByMethod" resultType="io.metersphere.track.dto.TestCaseDTO">
|
||||
SELECT id,name,project_id,"api" as type from api_test
|
||||
|
@ -416,4 +239,74 @@
|
|||
</if>
|
||||
AND test_case.id = #{caseId}
|
||||
</select>
|
||||
|
||||
<select id="selectIds" resultType="java.lang.String">
|
||||
select
|
||||
id
|
||||
from test_case
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<sql id="filters">
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='priority'">
|
||||
and test_case.priority in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='type'">
|
||||
and test_case.type in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='status'">
|
||||
and test_case.review_status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='method'">
|
||||
and test_case.method in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
<property name="name" value="request.name"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and (test_case.name like CONCAT('%', #{request.name},'%')
|
||||
or test_case.num like CONCAT('%', #{request.name},'%')
|
||||
or test_case.tags like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.nodeIds != null and request.nodeIds.size() > 0">
|
||||
and test_case.node_id in
|
||||
<foreach collection="request.nodeIds" item="nodeId" separator="," open="(" close=")">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
and test_case.project_id = #{request.projectId}
|
||||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -1,9 +1,12 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ServiceUtils {
|
||||
|
||||
|
@ -18,4 +21,22 @@ public class ServiceUtils {
|
|||
}
|
||||
return orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前端全选的id列表
|
||||
* @param queryRequest 查询条件
|
||||
* @param func 查询id列表的数据库查询
|
||||
* @return
|
||||
*/
|
||||
public static void getSelectAllIds(BaseQueryRequest queryRequest, Function<BaseQueryRequest, List<String>> func) {
|
||||
if (queryRequest.isSelectAll()) {
|
||||
List<String> ids = func.apply(queryRequest);
|
||||
if (!ids.isEmpty()) {
|
||||
ids = ids.stream()
|
||||
.filter(id -> !queryRequest.getUnSelectIds().contains(id))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
queryRequest.setIds(ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package io.metersphere.controller.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class BaseQueryRequest {
|
||||
|
||||
private String projectId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String workspaceId;
|
||||
|
||||
private List<String> ids;
|
||||
|
||||
private List<String> moduleIds;
|
||||
|
||||
private List<String> nodeIds;
|
||||
|
||||
/**
|
||||
* 是否选中所有数据
|
||||
*/
|
||||
private boolean selectAll;
|
||||
|
||||
/**
|
||||
* 全选之后取消选中的id
|
||||
*/
|
||||
private List<String> unSelectIds;
|
||||
|
||||
/**
|
||||
* 排序条件
|
||||
*/
|
||||
private List<OrderRequest> orders;
|
||||
|
||||
/**
|
||||
* 过滤条件
|
||||
*/
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
/**
|
||||
* 高级搜索
|
||||
|
||||
*/
|
||||
private Map<String, Object> combine;
|
||||
|
||||
/**
|
||||
* 要查询的字段
|
||||
*/
|
||||
private List<String> selectFields;
|
||||
}
|
|
@ -46,9 +46,22 @@ public class NodeResourcePoolService {
|
|||
})
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (nodeIps.size() < testResourcePool.getResources().size()) {
|
||||
List<Integer> nodePorts = testResourcePool.getResources().stream()
|
||||
.map(resource -> {
|
||||
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
||||
return nodeDTO.getPort();
|
||||
})
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (nodeIps.size() < testResourcePool.getResources().size() && nodePorts.size() < testResourcePool.getResources().size()) {
|
||||
MSException.throwException(Translator.get("duplicate_node_ip_port"));
|
||||
}
|
||||
else if (nodeIps.size() < testResourcePool.getResources().size()) {
|
||||
MSException.throwException(Translator.get("duplicate_node_ip"));
|
||||
}
|
||||
else if (nodePorts.size() < testResourcePool.getResources().size()) {
|
||||
MSException.throwException(Translator.get("duplicate_node_port"));
|
||||
}
|
||||
testResourcePool.setStatus(VALID.name());
|
||||
boolean isValid = true;
|
||||
for (TestResource resource : testResourcePool.getResources()) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.base.domain.TestCase;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -10,27 +11,15 @@ import java.util.Map;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QueryTestCaseRequest extends TestCase {
|
||||
public class QueryTestCaseRequest extends BaseQueryRequest {
|
||||
|
||||
private String name;
|
||||
|
||||
private List<String> nodeIds;
|
||||
|
||||
private List<String> testCaseIds;
|
||||
|
||||
private List<OrderRequest> orders;
|
||||
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
private List<String> selectFields;
|
||||
|
||||
private String planId;
|
||||
|
||||
private String workspaceId;
|
||||
|
||||
private String userId;
|
||||
|
||||
private Map<String, Object> combine;
|
||||
|
||||
private String reviewId;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -13,4 +14,6 @@ public class TestCaseBatchRequest extends TestCaseWithBLOBs {
|
|||
private List<String> ids;
|
||||
private List<OrderRequest> orders;
|
||||
private String projectId;
|
||||
|
||||
private BaseQueryRequest condition;
|
||||
}
|
||||
|
|
|
@ -528,6 +528,7 @@ public class TestCaseService {
|
|||
|
||||
|
||||
public void editTestCaseBath(TestCaseBatchRequest request) {
|
||||
getSelectAllIds(request);
|
||||
TestCaseExample testCaseExample = new TestCaseExample();
|
||||
testCaseExample.createCriteria().andIdIn(request.getIds());
|
||||
|
||||
|
@ -541,12 +542,21 @@ public class TestCaseService {
|
|||
}
|
||||
|
||||
public void deleteTestCaseBath(TestCaseBatchRequest request) {
|
||||
getSelectAllIds(request);
|
||||
deleteTestPlanTestCaseBath(request.getIds());
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(request.getIds());
|
||||
testCaseMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
public void getSelectAllIds(TestCaseBatchRequest request) {
|
||||
if (request.getCondition().isSelectAll()) {
|
||||
ServiceUtils.getSelectAllIds(request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
request.setIds(request.getCondition().getIds());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTestPlanTestCaseBath(List<String> caseIds) {
|
||||
TestPlanTestCaseExample example = new TestPlanTestCaseExample();
|
||||
example.createCriteria().andCaseIdIn(caseIds);
|
||||
|
|
|
@ -233,6 +233,8 @@ public class TestPlanReportService {
|
|||
testPlanReport.setEndTime(System.currentTimeMillis());
|
||||
testPlanReport.setUpdateTime(System.currentTimeMillis());
|
||||
|
||||
//手动触发的需要保存手工执行的信息
|
||||
|
||||
JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}");
|
||||
JSONArray componentIds = content.getJSONArray("components");
|
||||
List<ReportComponent> components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e4521190f0f1be113c8b84fbdcdf8ff273bf274e
|
||||
Subproject commit a18f543c2be6bcd8521a22094bb11aacc920ece4
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE test_plan_report ADD components VARCHAR (20);
|
|
@ -43,6 +43,8 @@ test_not_running=Test is not running
|
|||
load_test_already_exists=Duplicate load test name
|
||||
no_nodes_message=No node message
|
||||
duplicate_node_ip=Duplicate IPs
|
||||
duplicate_node_port=Duplicate Ports
|
||||
duplicate_node_ip_port=Duplicate IPs & Ports
|
||||
max_thread_insufficient=The number of concurrent users exceeds
|
||||
related_case_del_fail_prefix=Connected to
|
||||
related_case_del_fail_suffix=TestCase, please disassociate first
|
||||
|
|
|
@ -43,6 +43,8 @@ test_not_running=测试未运行
|
|||
load_test_already_exists=测试名称不能重复
|
||||
no_nodes_message=没有节点信息
|
||||
duplicate_node_ip=节点 IP 重复
|
||||
duplicate_node_port=节点 Port 重复
|
||||
duplicate_node_ip_port=节点 IP、Port 重复
|
||||
max_thread_insufficient=并发用户数超额
|
||||
related_case_del_fail_prefix=已关联到
|
||||
related_case_del_fail_suffix=测试用例,请先解除关联
|
||||
|
|
|
@ -43,6 +43,8 @@ test_not_running=測試未運行
|
|||
load_test_already_exists=測試名稱不能重復
|
||||
no_nodes_message=沒有節點信息
|
||||
duplicate_node_ip=節點 IP 重復
|
||||
duplicate_node_port=節點 Port 重復
|
||||
duplicate_node_ip_port=節點 IP、Port 重復
|
||||
max_thread_insufficient=並發用戶數超額
|
||||
related_case_del_fail_prefix=已關聯到
|
||||
related_case_del_fail_suffix=測試用例,請先解除關聯
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
closable>
|
||||
<div class="ms-api-scenario-div">
|
||||
<ms-edit-api-scenario @refresh="refresh" :currentScenario="item.currentScenario"
|
||||
:moduleOptions="moduleOptions"/>
|
||||
:moduleOptions="moduleOptions" ref="autoScenarioConfig"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
|
@ -111,6 +111,16 @@
|
|||
// 在 DOM 中添加 my-component 组件
|
||||
this.renderComponent = true;
|
||||
});
|
||||
},
|
||||
'$route'(to, from) { // 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除
|
||||
if (to.path.indexOf('/api/automation') == -1) {
|
||||
if (this.$refs && this.$refs.autoScenarioConfig) {
|
||||
console.log(this.$refs.autoScenarioConfig);
|
||||
this.$refs.autoScenarioConfig.forEach(item => {
|
||||
item.removeListener();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -158,6 +168,20 @@
|
|||
label = tab.currentScenario.name;
|
||||
this.tabs.push({label: label, name: name, currentScenario: tab.currentScenario});
|
||||
}
|
||||
if (this.$refs && this.$refs.autoScenarioConfig) {
|
||||
this.$refs.autoScenarioConfig.forEach(item => {
|
||||
item.removeListener();
|
||||
}); // 删除所有tab的 ctrl + s 监听
|
||||
this.addListener();
|
||||
}
|
||||
},
|
||||
addListener() {
|
||||
let index = this.tabs.findIndex(item => item.name === this.activeName); // 找到当前选中tab的index
|
||||
if(index != -1) { // 为当前选中的tab添加监听
|
||||
this.$nextTick(()=>{
|
||||
this.$refs.autoScenarioConfig[index].addListener();
|
||||
});
|
||||
}
|
||||
},
|
||||
handleTabClose() {
|
||||
this.tabs = [];
|
||||
|
@ -181,6 +205,7 @@
|
|||
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
|
||||
if (this.tabs.length > 0) {
|
||||
this.activeName = this.tabs[this.tabs.length - 1].name;
|
||||
this.addListener(); // 自动切换当前标签时,也添加监听
|
||||
} else {
|
||||
this.activeName = "default"
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<!--操作按钮-->
|
||||
<div class="ms-opt-btn">
|
||||
<el-button type="primary" size="small" @click="editScenario">{{$t('commons.save')}}</el-button>
|
||||
<el-button type="primary" size="small" @click="editScenario" title="ctrl + s">{{$t('commons.save')}}</el-button>
|
||||
</div>
|
||||
|
||||
<div class="tip">{{$t('test_track.plan_view.base_info')}}</div>
|
||||
|
@ -148,7 +148,7 @@
|
|||
<!-- 步骤组件-->
|
||||
<ms-component-config :type="data.type" :scenario="data" :response="response" :currentScenario="currentScenario"
|
||||
:currentEnvironmentId="currentEnvironmentId" :node="node"
|
||||
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick"/>
|
||||
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick" @refReload="reload"/>
|
||||
</span>
|
||||
</el-tree>
|
||||
</div>
|
||||
|
@ -222,6 +222,7 @@
|
|||
import ScenarioApiRelevance from "./api/ApiRelevance";
|
||||
import ScenarioRelevance from "./api/ScenarioRelevance";
|
||||
import MsComponentConfig from "./component/ComponentConfig";
|
||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "EditApiScenario",
|
||||
|
@ -295,6 +296,7 @@
|
|||
this.operatingElements = ELEMENTS.get("ALL");
|
||||
this.getMaintainerOptions();
|
||||
this.getApiScenario();
|
||||
this.addListener(); // 添加 ctrl s 监听
|
||||
},
|
||||
directives: {OutsideClick},
|
||||
computed: {
|
||||
|
@ -413,6 +415,16 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
addListener() {
|
||||
document.addEventListener("keydown", this.createCtrlSHandle);
|
||||
// document.addEventListener("keydown", (even => handleCtrlSEvent(even, this.$refs.httpApi.saveApi)));
|
||||
},
|
||||
removeListener() {
|
||||
document.removeEventListener("keydown", this.createCtrlSHandle);
|
||||
},
|
||||
createCtrlSHandle(event) {
|
||||
handleCtrlSEvent(event, this.editScenario);
|
||||
},
|
||||
getIdx(index) {
|
||||
return index - 0.33
|
||||
},
|
||||
|
@ -822,15 +834,13 @@
|
|||
}
|
||||
return bodyUploadFiles;
|
||||
},
|
||||
editScenario(showMessage) {
|
||||
editScenario() {
|
||||
this.$refs['currentScenario'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.setParameter();
|
||||
let bodyFiles = this.getBodyUploadFiles(this.currentScenario);
|
||||
this.$fileUpload(this.path, null, bodyFiles, this.currentScenario, response => {
|
||||
if (showMessage) {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
}
|
||||
this.path = "/api/automation/update";
|
||||
if (response.data) {
|
||||
this.currentScenario.id = response.data.id;
|
||||
|
@ -873,7 +883,6 @@
|
|||
}
|
||||
this.enableCookieShare = obj.enableCookieShare;
|
||||
this.scenarioDefinition = obj.hashTree;
|
||||
console.log(this.scenarioDefinition)
|
||||
}
|
||||
}
|
||||
if (this.currentScenario.copy) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<ms-environment-select :project-id="projectId" v-if="isTestPlan" :is-read-only="isReadOnly" @setEnvironment="setEnvironment"/>
|
||||
|
||||
<el-input placeholder="搜索" @blur="initTable" class="search-input" size="small" @keyup.enter.native="initTable" v-model="condition.name"/>
|
||||
<el-input :placeholder="$t('api_monitor.please_search')" @blur="initTable" class="search-input" size="small" @keyup.enter.native="initTable" v-model="condition.name"/>
|
||||
|
||||
<el-table v-loading="result.loading"
|
||||
border
|
||||
|
@ -26,7 +26,7 @@
|
|||
<ms-tag v-if="scope.row.status == 'Prepare'" type="info" effect="plain" :content="$t('test_track.plan.plan_status_prepare')"/>
|
||||
<ms-tag v-if="scope.row.status == 'Underway'" type="warning" effect="plain" :content="$t('test_track.plan.plan_status_running')"/>
|
||||
<ms-tag v-if="scope.row.status == 'Completed'" type="success" effect="plain" :content="$t('test_track.plan.plan_status_completed')"/>
|
||||
<ms-tag v-if="scope.row.status == 'Trash'" type="danger" effect="plain" content="废弃"/>
|
||||
<ms-tag v-if="scope.row.status == 'Trash'" type="danger" effect="plain" :content="$t('test_track.plan.plan_status_trash')"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<relevance-dialog :title="'场景导入'" ref="relevanceDialog">
|
||||
<relevance-dialog :title="$t('api_test.automation.scenario_import')" ref="relevanceDialog">
|
||||
|
||||
<template v-slot:aside>
|
||||
<ms-api-scenario-module
|
||||
|
@ -19,8 +19,8 @@
|
|||
ref="apiScenarioList"/>
|
||||
|
||||
<template v-slot:footer>
|
||||
<el-button type="primary" @click="copy" @keydown.enter.native.prevent>复制</el-button>
|
||||
<el-button type="primary" @click="reference" @keydown.enter.native.prevent>引用</el-button>
|
||||
<el-button type="primary" @click="copy" @keydown.enter.native.prevent>{{$t('commons.copy')}}</el-button>
|
||||
<el-button type="primary" @click="reference" @keydown.enter.native.prevent> {{ $t('api_test.scenario.reference') }}</el-button>
|
||||
</template>
|
||||
|
||||
</relevance-dialog>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<span @click.stop>
|
||||
<slot name="headerLeft">
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': data.active}"
|
||||
@click="active(data)"/>
|
||||
@click="active(data)" v-if="data.type!='scenario'"/>
|
||||
<el-input :draggable="draggable" v-if="isShowInput && isShowNameInput" size="small" v-model="data.name" class="name-input"
|
||||
@blur="isShowInput = false" :placeholder="$t('commons.input_name')" ref="nameEdit"/>
|
||||
<span v-else>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced==='Deleted'" type="danger">{{$t('api_test.automation.reference_deleted')}}</el-tag>
|
||||
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
|
||||
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced ==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
|
||||
<ms-run :debug="false" :reportId="reportId" :run-data="runData"
|
||||
<ms-run :debug="true" :reportId="reportId" :run-data="runData"
|
||||
@runRefresh="runRefresh" ref="runTest"/>
|
||||
|
||||
</template>
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
this.isActive = true;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
result() {
|
||||
this.response = this.result;
|
||||
this.isActive = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getExecResult() {
|
||||
// 执行结果信息
|
||||
|
|
|
@ -38,11 +38,15 @@
|
|||
},
|
||||
watch: {},
|
||||
created() {
|
||||
if (this.scenario.id && this.scenario.referenced === 'REF') {
|
||||
if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded) {
|
||||
this.result = this.$get("/api/automation/getApiScenario/" + this.scenario.id, response => {
|
||||
if (response.data) {
|
||||
this.scenario.loaded = true;
|
||||
if (response.data.scenarioDefinition) {
|
||||
this.scenario.hashTree = JSON.parse(response.data.scenarioDefinition).hashTree;
|
||||
}
|
||||
this.scenario.name = response.data.name;
|
||||
this.reload();
|
||||
this.$emit('refReload');
|
||||
} else {
|
||||
this.scenario.referenced = "Deleted";
|
||||
}
|
||||
|
@ -58,7 +62,7 @@
|
|||
},
|
||||
computed: {
|
||||
isDeletedOrRef() {
|
||||
if (this.scenario.referenced!= undefined && this.scenario.referenced === 'Deleted' || this.scenario.referenced === 'REF') {
|
||||
if (this.scenario.referenced != undefined && this.scenario.referenced === 'Deleted' || this.scenario.referenced === 'REF') {
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="request-form">
|
||||
<component :is="component" :scenario="scenario" :controller="scenario" :timer="scenario" :assertions="scenario" :extract="scenario" :jsr223-processor="scenario" :request="scenario" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" :node="node"
|
||||
:draggable="true" :title="title" :color="titleColor" :background-color="backgroundColor" @suggestClick="suggestClick(node)" :response="response"
|
||||
@remove="remove" @copyRow="copyRow"/>
|
||||
@remove="remove" @copyRow="copyRow" @refReload="refReload"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -107,6 +107,9 @@
|
|||
suggestClick(node) {
|
||||
this.$emit('suggestClick', node);
|
||||
},
|
||||
refReload(){
|
||||
this.$emit('refReload');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -198,6 +198,15 @@
|
|||
// 在 DOM 中添加 my-component 组件
|
||||
this.renderComponent = true;
|
||||
});
|
||||
},
|
||||
'$route'(to, from) { // 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除
|
||||
if (to.path.indexOf('/api/definition') == -1) {
|
||||
if (this.$refs && this.$refs.apiConfig) {
|
||||
this.$refs.apiConfig.forEach(item => {
|
||||
item.removeListener();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -211,6 +220,17 @@
|
|||
if (tab.name === 'add') {
|
||||
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug");
|
||||
}
|
||||
if (this.$refs.apiConfig) {
|
||||
this.$refs.apiConfig.forEach(item => {
|
||||
console.log(item);
|
||||
item.removeListener();
|
||||
}); // 删除所有tab的 ctrl + s 监听
|
||||
let tabs = this.apiTabs;
|
||||
let index = tabs.findIndex(item => item.name === tab.name); // 找到当前选中tab的index
|
||||
if (index != -1) {
|
||||
this.$refs.apiConfig[index - 1].addListener(); // 为选中tab添加 ctrl + s 监听(index-1的原因是要除去第一个固有tab)
|
||||
}
|
||||
}
|
||||
},
|
||||
handleCommand(e) {
|
||||
switch (e) {
|
||||
|
@ -316,7 +336,11 @@
|
|||
} else {
|
||||
let condition = {};
|
||||
let url = "/api/definition/list/all";
|
||||
condition.filters = ["Prepare", "Underway", "Completed"];
|
||||
condition.filters = new Map(
|
||||
[
|
||||
["status", ["Prepare", "Underway", "Completed"]],
|
||||
]
|
||||
);
|
||||
condition.projectId = getCurrentProjectID();
|
||||
this.$post(url, condition, response => {
|
||||
obj.data = response.data;
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
<div class="card-container">
|
||||
<!-- HTTP 请求参数 -->
|
||||
<ms-edit-complete-http-api @runTest="runTest" @saveApi="saveApi" @createRootModelInTree="createRootModelInTree" :request="request" :response="response"
|
||||
:basisData="currentApi" :moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'HTTP'"/>
|
||||
:basisData="currentApi" :moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'HTTP'" ref="httpApi"/>
|
||||
<!-- TCP -->
|
||||
<ms-edit-complete-tcp-api :request="request" @runTest="runTest" @createRootModelInTree="createRootModelInTree" @saveApi="saveApi" :basisData="currentApi"
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'TCP'"/>
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'TCP'" ref="tcpApi"/>
|
||||
<!--DUBBO-->
|
||||
<ms-edit-complete-dubbo-api :request="request" @runTest="runTest" @createRootModelInTree="createRootModelInTree" @saveApi="saveApi" :basisData="currentApi"
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'DUBBO'"/>
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'DUBBO'" ref="dubboApi"/>
|
||||
<!--SQL-->
|
||||
<ms-edit-complete-sql-api :request="request" @runTest="runTest" @createRootModelInTree="createRootModelInTree" @saveApi="saveApi" :basisData="currentApi"
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'SQL'"/>
|
||||
:moduleOptions="moduleOptions" :syncTabs="syncTabs" v-if="currentProtocol === 'SQL'" ref="sqlApi"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
|||
import {createComponent, Request} from "./jmeter/components";
|
||||
import Sampler from "./jmeter/components/sampler/sampler";
|
||||
import {WORKSPACE_ID} from '@/common/js/constants';
|
||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
|
@ -65,8 +66,30 @@
|
|||
break;
|
||||
}
|
||||
this.formatApi();
|
||||
this.addListener();
|
||||
},
|
||||
methods: {
|
||||
addListener() {
|
||||
document.addEventListener("keydown", this.createCtrlSHandle);
|
||||
// document.addEventListener("keydown", (even => handleCtrlSEvent(even, this.$refs.httpApi.saveApi)));
|
||||
},
|
||||
removeListener() {
|
||||
document.removeEventListener("keydown", this.createCtrlSHandle);
|
||||
},
|
||||
createCtrlSHandle(event) {
|
||||
if(this.$refs.httpApi) {
|
||||
handleCtrlSEvent(event, this.$refs.httpApi.saveApi);
|
||||
}
|
||||
else if(this.$refs.tcpApi) {
|
||||
handleCtrlSEvent(event, this.$refs.tcpApi.saveApi);
|
||||
}
|
||||
else if(this.$refs.dubboApi) {
|
||||
handleCtrlSEvent(event, this.$refs.dubboApi.saveApi);
|
||||
}
|
||||
else if(this.$refs.sqlApi) {
|
||||
handleCtrlSEvent(event, this.$refs.sqlApi.saveApi);
|
||||
}
|
||||
},
|
||||
runTest(data) {
|
||||
this.setParameters(data);
|
||||
let bodyFiles = this.getBodyUploadFiles(data);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<i class="el-icon-edit" style="cursor:pointer" @click="showInput(apiCase)" v-tester/>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div v-if="apiCase.id" style="color: #999999;font-size: 12px">
|
||||
<span>
|
||||
{{ apiCase.createTime | timestampFormatDate }}
|
||||
|
@ -46,12 +47,13 @@
|
|||
</el-col>
|
||||
|
||||
<el-col :span="4">
|
||||
<div class="tag-item">
|
||||
<div class="tag-item" @click.stop>
|
||||
<ms-input-tag :currentScenario="apiCase" ref="tag" @keyup.enter.native="saveTestCase(apiCase)"/>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="4">
|
||||
<span @click.stop>
|
||||
<ms-tip-button @click="singleRun(apiCase)" :tip="$t('api_test.run')" icon="el-icon-video-play"
|
||||
style="background-color: #409EFF;color: white" size="mini" :disabled="!apiCase.id" circle v-tester/>
|
||||
<ms-tip-button @click="copyCase(apiCase)" :tip="$t('commons.copy')" icon="el-icon-document-copy"
|
||||
|
@ -59,13 +61,14 @@
|
|||
<ms-tip-button @click="deleteCase(index,apiCase)" :tip="$t('commons.delete')" icon="el-icon-delete"
|
||||
size="mini" :disabled="!apiCase.id || isCaseEdit" circle v-tester/>
|
||||
<ms-api-extend-btns :is-case-edit="isCaseEdit" :environment="environment" :row="apiCase" v-tester/>
|
||||
</span>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="3">
|
||||
<el-link type="danger" v-if="apiCase.execResult && apiCase.execResult==='error'" @click="showExecResult(apiCase)">
|
||||
<el-link @click.stop type="danger" v-if="apiCase.execResult && apiCase.execResult==='error'" @click="showExecResult(apiCase)">
|
||||
{{ getResult(apiCase.execResult) }}
|
||||
</el-link>
|
||||
<el-link v-else-if="apiCase.execResult && apiCase.execResult==='success'" @click="showExecResult(apiCase)">
|
||||
<el-link @click.stop v-else-if="apiCase.execResult && apiCase.execResult==='success'" @click="showExecResult(apiCase)">
|
||||
{{ getResult(apiCase.execResult) }}
|
||||
</el-link>
|
||||
<div v-else> {{ getResult(apiCase.execResult) }}</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<el-col>
|
||||
<!--操作按钮-->
|
||||
<div style="float: right;margin-right: 20px;margin-top: 20px">
|
||||
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="saveApi" title="ctrl + s">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="runTest">{{ $t('commons.test') }}</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<el-form :model="httpForm" :rules="rule" ref="httpForm" label-width="80px" label-position="right">
|
||||
<!-- 操作按钮 -->
|
||||
<div style="float: right;margin-right: 20px">
|
||||
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="saveApi" title="ctrl + s">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="runTest">{{ $t('commons.test') }}</el-button>
|
||||
</div>
|
||||
<br/>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<el-col>
|
||||
<!--操作按钮-->
|
||||
<div style="float: right;margin-right: 20px;margin-top: 20px">
|
||||
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="saveApi" title="ctrl + s">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="runTest">{{ $t('commons.test') }}</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<el-col>
|
||||
<!--操作按钮-->
|
||||
<div style="float: right;margin-right: 20px;margin-top: 20px">
|
||||
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="saveApi" title="ctrl + s">{{ $t('commons.save') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="runTest">{{ $t('commons.test') }}</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<el-form-item :label="$t('api_report.request')" prop="url">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-model="debugForm.url"
|
||||
class="ms-http-input" size="small" :disabled="testCase!=undefined">
|
||||
class="ms-http-input" size="small" :disabled="testCase!=undefined" @blur="urlChange">
|
||||
<el-select v-model="debugForm.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
|
@ -55,6 +55,7 @@
|
|||
import {REQ_METHOD} from "../../model/JsonData";
|
||||
import MsRequestResultTail from "../response/RequestResultTail";
|
||||
import MsJmxStep from "../step/JmxStep";
|
||||
import {KeyValue} from "../../model/ApiTestModel";
|
||||
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
|
@ -167,7 +168,35 @@
|
|||
return false;
|
||||
}
|
||||
})
|
||||
},
|
||||
urlChange() {
|
||||
if (!this.debugForm.url || this.debugForm.url.indexOf('?') === -1) return;
|
||||
let url = this.getURL(this.addProtocol(this.debugForm.url));
|
||||
if (url) {
|
||||
this.debugForm.url = decodeURIComponent(this.debugForm.url.substr(0, this.debugForm.url.indexOf("?")));
|
||||
}
|
||||
},
|
||||
addProtocol(url) {
|
||||
if (url) {
|
||||
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
|
||||
return "https://" + url;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
getURL(urlStr) {
|
||||
try {
|
||||
let url = new URL(urlStr);
|
||||
url.searchParams.forEach((value, key) => {
|
||||
if (key && value) {
|
||||
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
|
||||
}
|
||||
});
|
||||
return url;
|
||||
} catch (e) {
|
||||
this.$error(this.$t('api_test.request.url_invalid'), 2000);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||
<ms-request-result-tail :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/>
|
||||
|
||||
<ms-jmx-step :request="request" :response="responseData"/>
|
||||
|
||||
<!-- 执行组件 -->
|
||||
<ms-run :debug="true" :reportId="reportId" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/>
|
||||
</el-card>
|
||||
|
@ -50,10 +52,12 @@
|
|||
import {REQ_METHOD} from "../../model/JsonData";
|
||||
import MsRequestResultTail from "../response/RequestResultTail";
|
||||
import TcpBasisParameters from "../request/tcp/TcpBasisParameters";
|
||||
import MsJmxStep from "../step/JmxStep";
|
||||
|
||||
export default {
|
||||
name: "ApiConfig",
|
||||
components: {
|
||||
MsJmxStep,
|
||||
TcpBasisParameters,
|
||||
MsRequestResultTail, MsResponseResult, MsApiRequestForm, MsRequestMetric, MsResponseText, MsRun},
|
||||
props: {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<el-table v-loading="result.loading"
|
||||
ref="caseTable"
|
||||
border
|
||||
:data="tableData" row-key="id" class="test-content adjust-table ms-select-all"
|
||||
:data="tableData" row-key="id" class="test-content adjust-table ms-select-all-fixed"
|
||||
@select-all="handleSelectAll"
|
||||
@filter-change="filter"
|
||||
@sort-change="sort"
|
||||
|
@ -19,7 +19,7 @@
|
|||
|
||||
<el-table-column type="selection" width="50"/>
|
||||
|
||||
<ms-table-select-all
|
||||
<ms-table-header-select-popover v-show="total>0"
|
||||
:page-size="pageSize>total?total:pageSize"
|
||||
:total="total"
|
||||
@selectPageAll="isSelectDataAll(false)"
|
||||
|
@ -74,7 +74,7 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130" align="center">
|
||||
<el-table-column fixed="right" v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<!--<el-button type="text" @click="reductionApi(scope.row)" v-if="trashEnable">{{$t('commons.reduction')}}</el-button>-->
|
||||
<!-- <el-button type="text" @click="handleTestCase(scope.row)" v-if="!trashEnable">{{ $t('commons.edit') }}-->
|
||||
|
@ -131,14 +131,15 @@ import MsSetEnvironment from "@/business/components/api/definition/components/ba
|
|||
import TestPlan from "@/business/components/api/definition/components/jmeter/components/test-plan";
|
||||
import ThreadGroup from "@/business/components/api/definition/components/jmeter/components/thread-group";
|
||||
import {parseEnvironment} from "@/business/components/api/test/model/EnvironmentModel";
|
||||
import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
|
||||
// import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
|
||||
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
||||
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
|
||||
import {API_CASE_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
|
||||
export default {
|
||||
name: "ApiCaseSimpleList",
|
||||
components: {
|
||||
MsTableSelectAll,
|
||||
MsTableHeaderSelectPopover,
|
||||
MsSetEnvironment,
|
||||
ApiCaseList,
|
||||
PriorityTableItem,
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
border
|
||||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
:data="tableData" row-key="id" class="test-content adjust-table ms-select-all"
|
||||
:data="tableData" row-key="id" class="test-content adjust-table ms-select-all-fixed"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelect" :height="screenHeight">
|
||||
<el-table-column width="50" type="selection"/>
|
||||
|
||||
<ms-table-select-all
|
||||
<ms-table-header-select-popover v-show="total>0"
|
||||
:page-size="pageSize>total?total:pageSize"
|
||||
:total="total"
|
||||
@selectPageAll="isSelectDataAll(false)"
|
||||
|
@ -160,7 +160,8 @@
|
|||
import {_filter, _sort, getCurrentProjectID} from "@/common/js/utils";
|
||||
import {WORKSPACE_ID} from '@/common/js/constants';
|
||||
import ApiListContainer from "./ApiListContainer";
|
||||
import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
|
||||
// import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
|
||||
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
|
||||
import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components";
|
||||
|
@ -170,7 +171,7 @@
|
|||
name: "ApiList",
|
||||
components: {
|
||||
ApiStatus,
|
||||
MsTableSelectAll,
|
||||
MsTableHeaderSelectPopover,
|
||||
ApiListContainer,
|
||||
MsTableButton,
|
||||
MsTableOperatorButton,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<ms-node-tree
|
||||
v-loading="result.loading"
|
||||
:tree-nodes="data"
|
||||
allLabel="默认模块"
|
||||
@add="add"
|
||||
:type="'edit'"
|
||||
@edit="edit"
|
||||
|
@ -97,6 +98,10 @@
|
|||
this.$warning("请选择一个模块");
|
||||
return;
|
||||
}
|
||||
if (this.currentModule.id === "root") {
|
||||
this.$warning("不能选默认模块,请重新选择一个模块");
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
let arr = Array.from(this.selectIds);
|
||||
let obj = {testIds: arr, projectId: getCurrentProjectID(), modulePath: this.getPath(this.currentModule.id), moduleId: this.currentModule.id};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<el-dropdown-item command="personal">{{ $t('commons.personal_information') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="about">{{ $t('commons.about_us') }} <i class="el-icon-info"/></el-dropdown-item>
|
||||
<el-dropdown-item command="help">{{ $t('commons.help_documentation') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="ApiHelp">{{ $t('commons.api_help_documentation') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="old" v-show=isReadOnly @click.native="changeBar('old')">
|
||||
{{ $t('commons.cut_back_old_version') }}
|
||||
</el-dropdown-item>
|
||||
|
@ -64,6 +65,9 @@ export default {
|
|||
case "help":
|
||||
window.location.href = "https://metersphere.io/docs/index.html";
|
||||
break;
|
||||
case "ApiHelp":
|
||||
window.open('/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config', "_blank");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
|
||||
<ms-main-container>
|
||||
<test-case-list
|
||||
:module-options="moduleOptions"
|
||||
:select-node-ids="selectNodeIds"
|
||||
:select-parent-nodes="selectParentNodes"
|
||||
:tree-nodes="treeNodes"
|
||||
@testCaseEdit="editTestCase"
|
||||
@testCaseCopy="copyTestCase"
|
||||
@testCaseDetail="showTestCaseDetail"
|
||||
@batchMove="batchMove"
|
||||
@refresh="refresh"
|
||||
@refreshAll="refreshAll"
|
||||
@moveToNode="moveToNode"
|
||||
@setCondition="setCondition"
|
||||
ref="testCaseList">
|
||||
</test-case-list>
|
||||
|
@ -28,6 +28,7 @@
|
|||
|
||||
<test-case-edit
|
||||
@refresh="refreshTable"
|
||||
@setModuleOptions="setModuleOptions"
|
||||
:read-only="testCaseReadOnly"
|
||||
:tree-nodes="treeNodes"
|
||||
:select-node="selectNode"
|
||||
|
@ -35,9 +36,6 @@
|
|||
ref="testCaseEditDialog">
|
||||
</test-case-edit>
|
||||
|
||||
<test-case-move @refresh="refresh" ref="testCaseMove"/>
|
||||
|
||||
<batch-move @refresh="refresh" @moveSave="moveSave" ref="testBatchMove"/>
|
||||
|
||||
</ms-container>
|
||||
|
||||
|
@ -49,12 +47,10 @@ import NodeTree from '../common/NodeTree';
|
|||
import TestCaseEdit from './components/TestCaseEdit';
|
||||
import TestCaseList from "./components/TestCaseList";
|
||||
import SelectMenu from "../common/SelectMenu";
|
||||
import TestCaseMove from "./components/TestCaseMove";
|
||||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsAsideContainer from "../../common/components/MsAsideContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import {checkoutTestManagerOrTestUser, getCurrentProjectID, hasRoles} from "../../../../common/js/utils";
|
||||
import BatchMove from "./components/BatchMove";
|
||||
import TestCaseNodeTree from "../common/TestCaseNodeTree";
|
||||
import {TrackEvent,LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
||||
|
||||
|
@ -63,7 +59,7 @@ export default {
|
|||
components: {
|
||||
TestCaseNodeTree,
|
||||
MsMainContainer,
|
||||
MsAsideContainer, MsContainer, TestCaseMove, TestCaseList, NodeTree, TestCaseEdit, SelectMenu, BatchMove
|
||||
MsAsideContainer, MsContainer, TestCaseList, NodeTree, TestCaseEdit, SelectMenu
|
||||
},
|
||||
comments: {},
|
||||
data() {
|
||||
|
@ -75,7 +71,8 @@ export default {
|
|||
selectParentNodes: [],
|
||||
testCaseReadOnly: true,
|
||||
selectNode: {},
|
||||
condition: {}
|
||||
condition: {},
|
||||
moduleOptions: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -153,32 +150,14 @@ export default {
|
|||
this.$refs.testCaseEditDialog.open();
|
||||
}
|
||||
},
|
||||
|
||||
moveToNode(selectIds) {
|
||||
if (selectIds.size < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||
return;
|
||||
}
|
||||
this.$refs.testCaseEditDialog.getModuleOptions();
|
||||
this.$refs.testCaseMove.open(this.$refs.testCaseEditDialog.moduleOptions, selectIds);
|
||||
},
|
||||
batchMove(selectIds) {
|
||||
this.$refs.testBatchMove.open(this.treeNodes, selectIds, this.$refs.testCaseEditDialog.moduleOptions);
|
||||
},
|
||||
setTreeNodes(data) {
|
||||
this.treeNodes = data;
|
||||
},
|
||||
setCondition(data) {
|
||||
this.condition = data;
|
||||
},
|
||||
moveSave(param) {
|
||||
this.result = this.$post('/test/case/batch/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$refs.testBatchMove.close();
|
||||
// 发送广播,刷新 head 上的最新列表
|
||||
TrackEvent.$emit(LIST_CHANGE);
|
||||
this.refresh();
|
||||
});
|
||||
setModuleOptions(data) {
|
||||
this.moduleOptions = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="batch-move" v-loading="result.loading">
|
||||
<div v-if="dialogVisible" class="batch-move" v-loading="result.loading">
|
||||
<el-dialog :title="this.$t('test_track.case.select_catalog')"
|
||||
:visible.sync="dialogVisible"
|
||||
:before-close="close"
|
||||
|
|
|
@ -379,6 +379,9 @@ export default {
|
|||
treeNodes() {
|
||||
this.getModuleOptions();
|
||||
},
|
||||
moduleOptions() {
|
||||
this.$emit('setModuleOptions', this.moduleOptions);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
:content="$t('test_track.case.import.import')" @click="importTestCase"/>
|
||||
<ms-table-button :is-tester-permission="true" icon="el-icon-upload2"
|
||||
:content="$t('test_track.case.export.export')" @click="handleBatch('export')"/>
|
||||
<!-- <ms-table-button :is-tester-permission="true" icon="el-icon-right" :content="$t('test_track.case.move')"-->
|
||||
<!-- @click="handleBatch('move')"/>-->
|
||||
<!-- <ms-table-button :is-tester-permission="true" icon="el-icon-delete" :content="$t('test_track.case.delete')"-->
|
||||
<!-- @click="handleBatch('delete')"/>-->
|
||||
<!--<test-case-export/>-->
|
||||
</template>
|
||||
</ms-table-header>
|
||||
|
||||
|
@ -33,12 +28,22 @@
|
|||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
@select="handleSelect"
|
||||
@cell-mouse-enter="showPopover"
|
||||
row-key="id"
|
||||
class="test-content adjust-table">
|
||||
class="test-content adjust-table ms-select-all"
|
||||
ref="table">
|
||||
|
||||
<el-table-column
|
||||
width="50"
|
||||
type="selection"/>
|
||||
|
||||
<ms-table-select-all
|
||||
:page-size="pageSize > total ? total : pageSize"
|
||||
:total="total"
|
||||
@selectPageAll="isSelectDataAll(false)"
|
||||
@selectAll="isSelectDataAll(true)"/>
|
||||
|
||||
<el-table-column width="40" :resizable="false" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/>
|
||||
|
@ -156,6 +161,8 @@
|
|||
|
||||
<batch-edit ref="batchEdit" @batchEdit="batchEdit"
|
||||
:typeArr="typeArr" :value-arr="valueArr" :dialog-title="$t('test_track.case.batch_edit_case')"/>
|
||||
|
||||
<batch-move @refresh="refresh" @moveSave="moveSave" ref="testBatchMove"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -184,10 +191,15 @@ import TestCaseDetail from "./TestCaseDetail";
|
|||
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
|
||||
import {getCurrentProjectID} from "../../../../../common/js/utils";
|
||||
import MsTag from "@/business/components/common/components/MsTag";
|
||||
import MsTableSelectAll from "../../../common/components/table/MsTableSelectAll";
|
||||
import {_handleSelect, _handleSelectAll} from "../../../../../common/js/tableUtils";
|
||||
import BatchMove from "./BatchMove";
|
||||
|
||||
export default {
|
||||
name: "TestCaseList",
|
||||
components: {
|
||||
BatchMove,
|
||||
MsTableSelectAll,
|
||||
MsTableButton,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
|
@ -274,7 +286,7 @@ export default {
|
|||
maintainer: [],
|
||||
},
|
||||
currentCaseId: null,
|
||||
projectId: ""
|
||||
projectId: "",
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -283,6 +295,12 @@ export default {
|
|||
},
|
||||
selectParentNodes: {
|
||||
type: Array
|
||||
},
|
||||
treeNodes: {
|
||||
type: Array
|
||||
},
|
||||
moduleOptions: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
|
@ -303,6 +321,8 @@ export default {
|
|||
this.projectId = getCurrentProjectID();
|
||||
this.condition.planId = "";
|
||||
this.condition.nodeIds = [];
|
||||
this.condition.selectAll = false;
|
||||
this.condition.unSelectIds = [];
|
||||
if (this.planId) {
|
||||
// param.planId = this.planId;
|
||||
this.condition.planId = this.planId;
|
||||
|
@ -366,8 +386,10 @@ export default {
|
|||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/test/case/batch/delete', {ids: ids}, () => {
|
||||
let param = {};
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
param.condition = this.condition;
|
||||
this.$post('/test/case/batch/delete', param, () => {
|
||||
this.selectRows.clear();
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
|
@ -401,26 +423,12 @@ export default {
|
|||
this.$emit('testCaseDetail', row);
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.tableData.forEach(item => {
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
_handleSelectAll(this, selection, this.tableData, this.selectRows);
|
||||
this.setUnSelectIds();
|
||||
},
|
||||
handleSelectionChange(selection, row) {
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
handleSelect(selection, row) {
|
||||
_handleSelect(this, selection, row, this.selectRows);
|
||||
this.setUnSelectIds();
|
||||
},
|
||||
importTestCase() {
|
||||
if (!getCurrentProjectID()) {
|
||||
|
@ -457,7 +465,6 @@ export default {
|
|||
});
|
||||
},
|
||||
handleBatch(type) {
|
||||
|
||||
if (this.selectRows.size < 1) {
|
||||
if (type === 'export') {
|
||||
this.$alert(this.$t('test_track.case.export_all_cases'), '', {
|
||||
|
@ -489,6 +496,7 @@ export default {
|
|||
let param = {};
|
||||
param[form.type] = form.value;
|
||||
param.ids = ids;
|
||||
param.condition = this.condition;
|
||||
this.$post('/test/case/batch/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.refresh();
|
||||
|
@ -513,7 +521,7 @@ export default {
|
|||
this.$refs.batchEdit.open();
|
||||
},
|
||||
handleBatchMove() {
|
||||
this.$emit("batchMove", Array.from(this.selectRows).map(row => row.id));
|
||||
this.$refs.testBatchMove.open(this.treeNodes, Array.from(this.selectRows).map(row => row.id), this.moduleOptions);
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
|
@ -525,6 +533,31 @@ export default {
|
|||
if (column.property === 'name') {
|
||||
this.currentCaseId = row.id;
|
||||
}
|
||||
},
|
||||
isSelectDataAll(data) {
|
||||
this.condition.selectAll = data;
|
||||
this.setUnSelectIds();
|
||||
//如果已经全选,不需要再操作了
|
||||
if (this.selectRows.size != this.tableData.length) {
|
||||
this.$refs.table.toggleAllSelection(true);
|
||||
}
|
||||
},
|
||||
setUnSelectIds() {
|
||||
let ids = Array.from(this.selectRows).map(o => o.id);
|
||||
let allIDs = this.tableData.map(o => o.id);
|
||||
this.condition.unSelectIds = allIDs.filter(function (val) {
|
||||
return ids.indexOf(val) === -1
|
||||
});
|
||||
},
|
||||
moveSave(param) {
|
||||
param.condition = this.condition;
|
||||
this.result = this.$post('/test/case/batch/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$refs.testBatchMove.close();
|
||||
// 发送广播,刷新 head 上的最新列表
|
||||
TrackEvent.$emit(LIST_CHANGE);
|
||||
this.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,9 +257,10 @@
|
|||
<el-table-column prop="description" :label="$t('test_track.issue.description')">
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="left"
|
||||
width="400"
|
||||
placement="right"
|
||||
width="500"
|
||||
trigger="hover"
|
||||
popper-class="issues-popover"
|
||||
>
|
||||
<ckeditor :editor="editor" disabled :config="readConfig"
|
||||
v-model="scope.row.description"/>
|
||||
|
@ -748,3 +749,10 @@ p {
|
|||
z-index: 999;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.issues-popover {
|
||||
height: 550px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -356,3 +356,12 @@ export function _getBodyUploadFiles(request, bodyUploadFiles, obj) {
|
|||
}
|
||||
}
|
||||
}
|
||||
export function handleCtrlSEvent(event, func) {
|
||||
if (event.keyCode === 83 && event.ctrlKey) {
|
||||
// console.log('拦截到 ctrl + s');//ctrl+s
|
||||
func();
|
||||
event.preventDefault();
|
||||
event.returnValue = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ export default {
|
|||
comment: '评论',
|
||||
examples: '示例',
|
||||
help_documentation: '帮助文档',
|
||||
api_help_documentation: 'API文档',
|
||||
delete_cancelled: '已取消删除',
|
||||
workspace: '工作空间',
|
||||
organization: '组织',
|
||||
|
|
|
@ -8,6 +8,7 @@ export default {
|
|||
comment: '評論',
|
||||
examples: '示例',
|
||||
help_documentation: '幫助文檔',
|
||||
api_help_documentation: 'API文檔',
|
||||
delete_cancelled: '已取消刪除',
|
||||
workspace: '工作空間',
|
||||
organization: '組織',
|
||||
|
|
Loading…
Reference in New Issue