Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
a11a54c23a
|
@ -19,6 +19,7 @@ import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -81,5 +82,10 @@ public class ApiAutomationController {
|
||||||
apiAutomationService.run(request);
|
apiAutomationService.run(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/getReference")
|
||||||
|
public List<ApiScenario> getReference(@RequestBody ApiScenarioRequest request) {
|
||||||
|
return apiAutomationService.getReference(request);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.api.dto.automation;
|
package io.metersphere.api.dto.automation;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ public class SaveApiScenarioRequest {
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private String scenarioDefinition;
|
private MsTestElement scenarioDefinition;
|
||||||
|
|
||||||
List<String> bodyUploadIds;
|
List<String> bodyUploadIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.alibaba.fastjson.annotation.JSONType;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.metersphere.api.dto.scenario.KeyValue;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.service.ApiAutomationService;
|
import io.metersphere.api.service.ApiAutomationService;
|
||||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||||
|
@ -36,6 +37,9 @@ public class MsScenario extends MsTestElement {
|
||||||
@JSONField(ordinal = 12)
|
@JSONField(ordinal = 12)
|
||||||
private String environmentId;
|
private String environmentId;
|
||||||
|
|
||||||
|
@JSONField(ordinal = 13)
|
||||||
|
private List<KeyValue> variables;
|
||||||
|
|
||||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||||
if (environmentId != null) {
|
if (environmentId != null) {
|
||||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||||
|
|
|
@ -60,6 +60,14 @@ public class MsTestElement {
|
||||||
@JSONField(ordinal = 3)
|
@JSONField(ordinal = 3)
|
||||||
private String label;
|
private String label;
|
||||||
@JSONField(ordinal = 4)
|
@JSONField(ordinal = 4)
|
||||||
|
private String resourceId;
|
||||||
|
@JSONField(ordinal = 5)
|
||||||
|
private String referenced;
|
||||||
|
@JSONField(ordinal = 6)
|
||||||
|
private boolean active;
|
||||||
|
@JSONField(ordinal = 7)
|
||||||
|
private String index;
|
||||||
|
@JSONField(ordinal = 8)
|
||||||
private LinkedList<MsTestElement> hashTree;
|
private LinkedList<MsTestElement> hashTree;
|
||||||
|
|
||||||
// 公共环境逐层传递,如果自身有环境 以自身引用环境为准否则以公共环境作为请求环境
|
// 公共环境逐层传递,如果自身有环境 以自身引用环境为准否则以公共环境作为请求环境
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -101,7 +102,7 @@ public class ApiAutomationService {
|
||||||
scenario.setFollowPeople(request.getFollowPeople());
|
scenario.setFollowPeople(request.getFollowPeople());
|
||||||
scenario.setPrincipal(request.getPrincipal());
|
scenario.setPrincipal(request.getPrincipal());
|
||||||
scenario.setStepTotal(request.getStepTotal());
|
scenario.setStepTotal(request.getStepTotal());
|
||||||
scenario.setScenarioDefinition(request.getScenarioDefinition());
|
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||||
scenario.setCreateTime(System.currentTimeMillis());
|
scenario.setCreateTime(System.currentTimeMillis());
|
||||||
scenario.setUpdateTime(System.currentTimeMillis());
|
scenario.setUpdateTime(System.currentTimeMillis());
|
||||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||||
|
@ -137,7 +138,7 @@ public class ApiAutomationService {
|
||||||
scenario.setFollowPeople(request.getFollowPeople());
|
scenario.setFollowPeople(request.getFollowPeople());
|
||||||
scenario.setPrincipal(request.getPrincipal());
|
scenario.setPrincipal(request.getPrincipal());
|
||||||
scenario.setStepTotal(request.getStepTotal());
|
scenario.setStepTotal(request.getStepTotal());
|
||||||
scenario.setScenarioDefinition(request.getScenarioDefinition());
|
scenario.setScenarioDefinition(JSON.toJSONString(request.getScenarioDefinition()));
|
||||||
scenario.setUpdateTime(System.currentTimeMillis());
|
scenario.setUpdateTime(System.currentTimeMillis());
|
||||||
if (StringUtils.isNotEmpty(request.getStatus())) {
|
if (StringUtils.isNotEmpty(request.getStatus())) {
|
||||||
scenario.setStatus(request.getStatus());
|
scenario.setStatus(request.getStatus());
|
||||||
|
@ -299,4 +300,8 @@ public class ApiAutomationService {
|
||||||
createAPIReportResult(request.getId());
|
createAPIReportResult(request.getId());
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ApiScenario> getReference(ApiScenarioRequest request) {
|
||||||
|
return extApiScenarioMapper.selectReference(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package io.metersphere.base.domain;
|
package io.metersphere.base.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class MessageTask implements Serializable {
|
public class MessageTask implements Serializable {
|
||||||
private String id;
|
private String id;
|
||||||
|
@ -27,5 +28,7 @@ public class MessageTask implements Serializable {
|
||||||
|
|
||||||
private Long createTime;
|
private Long createTime;
|
||||||
|
|
||||||
|
private String template;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<select id="selectAll" resultType="io.metersphere.api.dto.ApiMonitorSearch">
|
<select id="selectAll" resultType="io.metersphere.api.dto.ApiMonitorSearch">
|
||||||
select distinct url from api_data_view;
|
select distinct url from api_data_view order by url;
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectResponseTimeByUrl" parameterType="java.lang.String"
|
<select id="selectResponseTimeByUrl" parameterType="java.lang.String"
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectReportIdByUrlAndStartTime" resultType="java.lang.String">
|
<select id="selectReportIdByUrlAndStartTime" resultType="java.lang.String">
|
||||||
select report_id from api_data_view where response_code != 200 and url=#{apiUrl} and start_time=#{startTime};
|
select report_id from api_data_view where url=#{apiUrl} and start_time=#{startTime};
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insertListApiData" parameterType="java.util.List">
|
<insert id="insertListApiData" parameterType="java.util.List">
|
||||||
|
|
|
@ -2,9 +2,10 @@ package io.metersphere.base.mapper;
|
||||||
|
|
||||||
import io.metersphere.base.domain.MessageTask;
|
import io.metersphere.base.domain.MessageTask;
|
||||||
import io.metersphere.base.domain.MessageTaskExample;
|
import io.metersphere.base.domain.MessageTaskExample;
|
||||||
import java.util.List;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface MessageTaskMapper {
|
public interface MessageTaskMapper {
|
||||||
long countByExample(MessageTaskExample example);
|
long countByExample(MessageTaskExample example);
|
||||||
|
|
||||||
|
@ -16,15 +17,21 @@ public interface MessageTaskMapper {
|
||||||
|
|
||||||
int insertSelective(MessageTask record);
|
int insertSelective(MessageTask record);
|
||||||
|
|
||||||
|
List<MessageTask> selectByExampleWithBLOBs(MessageTaskExample example);
|
||||||
|
|
||||||
List<MessageTask> selectByExample(MessageTaskExample example);
|
List<MessageTask> selectByExample(MessageTaskExample example);
|
||||||
|
|
||||||
MessageTask selectByPrimaryKey(String id);
|
MessageTask selectByPrimaryKey(String id);
|
||||||
|
|
||||||
int updateByExampleSelective(@Param("record") MessageTask record, @Param("example") MessageTaskExample example);
|
int updateByExampleSelective(@Param("record") MessageTask record, @Param("example") MessageTaskExample example);
|
||||||
|
|
||||||
|
int updateByExampleWithBLOBs(@Param("record") MessageTask record, @Param("example") MessageTaskExample example);
|
||||||
|
|
||||||
int updateByExample(@Param("record") MessageTask record, @Param("example") MessageTaskExample example);
|
int updateByExample(@Param("record") MessageTask record, @Param("example") MessageTaskExample example);
|
||||||
|
|
||||||
int updateByPrimaryKeySelective(MessageTask record);
|
int updateByPrimaryKeySelective(MessageTask record);
|
||||||
|
|
||||||
|
int updateByPrimaryKeyWithBLOBs(MessageTask record);
|
||||||
|
|
||||||
int updateByPrimaryKey(MessageTask record);
|
int updateByPrimaryKey(MessageTask record);
|
||||||
}
|
}
|
|
@ -2,17 +2,20 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="io.metersphere.base.mapper.MessageTaskMapper">
|
<mapper namespace="io.metersphere.base.mapper.MessageTaskMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.MessageTask">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.MessageTask">
|
||||||
<id column="id" jdbcType="VARCHAR" property="id"/>
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="type" jdbcType="VARCHAR" property="type"/>
|
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||||
<result column="event" jdbcType="VARCHAR" property="event"/>
|
<result column="event" jdbcType="VARCHAR" property="event" />
|
||||||
<result column="user_id" jdbcType="VARCHAR" property="userId"/>
|
<result column="user_id" jdbcType="VARCHAR" property="userId" />
|
||||||
<result column="task_type" jdbcType="VARCHAR" property="taskType"/>
|
<result column="task_type" jdbcType="VARCHAR" property="taskType" />
|
||||||
<result column="webhook" jdbcType="VARCHAR" property="webhook"/>
|
<result column="webhook" jdbcType="VARCHAR" property="webhook" />
|
||||||
<result column="identification" jdbcType="VARCHAR" property="identification"/>
|
<result column="identification" jdbcType="VARCHAR" property="identification" />
|
||||||
<result column="is_set" jdbcType="BIT" property="isSet"/>
|
<result column="is_set" jdbcType="BIT" property="isSet" />
|
||||||
<result column="organization_id" jdbcType="VARCHAR" property="organizationId"/>
|
<result column="organization_id" jdbcType="VARCHAR" property="organizationId" />
|
||||||
<result column="test_id" jdbcType="VARCHAR" property="testId"/>
|
<result column="test_id" jdbcType="VARCHAR" property="testId" />
|
||||||
<result column="create_time" jdbcType="BIGINT" property="createTime"/>
|
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||||
|
</resultMap>
|
||||||
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.MessageTask">
|
||||||
|
<result column="template" jdbcType="LONGVARCHAR" property="template" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<sql id="Example_Where_Clause">
|
<sql id="Example_Where_Clause">
|
||||||
<where>
|
<where>
|
||||||
|
@ -25,13 +28,13 @@
|
||||||
and ${criterion.condition}
|
and ${criterion.condition}
|
||||||
</when>
|
</when>
|
||||||
<when test="criterion.singleValue">
|
<when test="criterion.singleValue">
|
||||||
and ${criterion.condition} #{criterion.value}
|
AND ${criterion.condition} #{criterion.value}
|
||||||
</when>
|
</when>
|
||||||
<when test="criterion.betweenValue">
|
<when test="criterion.betweenValue">
|
||||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
|
||||||
</when>
|
</when>
|
||||||
<when test="criterion.listValue">
|
<when test="criterion.listValue">
|
||||||
and ${criterion.condition}
|
AND ${criterion.condition}
|
||||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||||
#{listItem}
|
#{listItem}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
@ -76,6 +79,25 @@
|
||||||
id, `type`, event, user_id, task_type, webhook, identification, is_set, organization_id,
|
id, `type`, event, user_id, task_type, webhook, identification, is_set, organization_id,
|
||||||
test_id, create_time
|
test_id, create_time
|
||||||
</sql>
|
</sql>
|
||||||
|
<sql id="Blob_Column_List">
|
||||||
|
`template`
|
||||||
|
</sql>
|
||||||
|
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.MessageTaskExample" resultMap="ResultMapWithBLOBs">
|
||||||
|
SELECT
|
||||||
|
<if test="distinct">
|
||||||
|
DISTINCT
|
||||||
|
</if>
|
||||||
|
<include refid="Base_Column_List" />
|
||||||
|
,
|
||||||
|
<include refid="Blob_Column_List" />
|
||||||
|
FROM message_task
|
||||||
|
<if test="_parameter != null">
|
||||||
|
<include refid="Example_Where_Clause" />
|
||||||
|
</if>
|
||||||
|
<if test="orderByClause != null">
|
||||||
|
ORDER BY ${orderByClause}
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultMap="BaseResultMap">
|
<select id="selectByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultMap="BaseResultMap">
|
||||||
select
|
select
|
||||||
<if test="distinct">
|
<if test="distinct">
|
||||||
|
@ -90,9 +112,11 @@
|
||||||
order by ${orderByClause}
|
order by ${orderByClause}
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
|
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||||
select
|
select
|
||||||
<include refid="Base_Column_List" />
|
<include refid="Base_Column_List" />
|
||||||
|
,
|
||||||
|
<include refid="Blob_Column_List" />
|
||||||
from message_task
|
from message_task
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</select>
|
</select>
|
||||||
|
@ -107,14 +131,16 @@
|
||||||
</if>
|
</if>
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.MessageTask">
|
<insert id="insert" parameterType="io.metersphere.base.domain.MessageTask">
|
||||||
insert into message_task (id, `type`, event,
|
INSERT INTO message_task (id, `type`, event,
|
||||||
user_id, task_type, webhook,
|
user_id, task_type, webhook,
|
||||||
identification, is_set, organization_id,
|
identification, is_set, organization_id,
|
||||||
test_id, create_time)
|
test_id, create_time, `template`
|
||||||
values (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR},
|
)
|
||||||
|
VALUES (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR},
|
||||||
#{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR},
|
#{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR},
|
||||||
#{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR},
|
#{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR},
|
||||||
#{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT})
|
#{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{template,jdbcType=LONGVARCHAR}
|
||||||
|
)
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.MessageTask">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.MessageTask">
|
||||||
insert into message_task
|
insert into message_task
|
||||||
|
@ -152,6 +178,9 @@
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
create_time,
|
create_time,
|
||||||
</if>
|
</if>
|
||||||
|
<if test="template != null">
|
||||||
|
`template`,
|
||||||
|
</if>
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
|
@ -187,6 +216,9 @@
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
#{createTime,jdbcType=BIGINT},
|
#{createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="template != null">
|
||||||
|
#{template,jdbcType=LONGVARCHAR},
|
||||||
|
</if>
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
<select id="countByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultType="java.lang.Long">
|
<select id="countByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultType="java.lang.Long">
|
||||||
|
@ -231,11 +263,32 @@
|
||||||
<if test="record.createTime != null">
|
<if test="record.createTime != null">
|
||||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="record.template != null">
|
||||||
|
`template` = #{record.template,jdbcType=LONGVARCHAR},
|
||||||
|
</if>
|
||||||
</set>
|
</set>
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
</update>
|
</update>
|
||||||
|
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||||
|
UPDATE message_task
|
||||||
|
SET id = #{record.id,jdbcType=VARCHAR},
|
||||||
|
`type` = #{record.type,jdbcType=VARCHAR},
|
||||||
|
event = #{record.event,jdbcType=VARCHAR},
|
||||||
|
user_id = #{record.userId,jdbcType=VARCHAR},
|
||||||
|
task_type = #{record.taskType,jdbcType=VARCHAR},
|
||||||
|
webhook = #{record.webhook,jdbcType=VARCHAR},
|
||||||
|
identification = #{record.identification,jdbcType=VARCHAR},
|
||||||
|
is_set = #{record.isSet,jdbcType=BIT},
|
||||||
|
organization_id = #{record.organizationId,jdbcType=VARCHAR},
|
||||||
|
test_id = #{record.testId,jdbcType=VARCHAR},
|
||||||
|
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||||
|
`template` = #{record.template,jdbcType=LONGVARCHAR}
|
||||||
|
<if test="_parameter != null">
|
||||||
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
|
</if>
|
||||||
|
</update>
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update message_task
|
update message_task
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
|
@ -286,12 +339,30 @@
|
||||||
<if test="createTime != null">
|
<if test="createTime != null">
|
||||||
create_time = #{createTime,jdbcType=BIGINT},
|
create_time = #{createTime,jdbcType=BIGINT},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="template != null">
|
||||||
|
`template` = #{template,jdbcType=LONGVARCHAR},
|
||||||
|
</if>
|
||||||
</set>
|
</set>
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
|
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.MessageTask">
|
||||||
|
UPDATE message_task
|
||||||
|
SET `type` = #{type,jdbcType=VARCHAR},
|
||||||
|
event = #{event,jdbcType=VARCHAR},
|
||||||
|
user_id = #{userId,jdbcType=VARCHAR},
|
||||||
|
task_type = #{taskType,jdbcType=VARCHAR},
|
||||||
|
webhook = #{webhook,jdbcType=VARCHAR},
|
||||||
|
identification = #{identification,jdbcType=VARCHAR},
|
||||||
|
is_set = #{isSet,jdbcType=BIT},
|
||||||
|
organization_id = #{organizationId,jdbcType=VARCHAR},
|
||||||
|
test_id = #{testId,jdbcType=VARCHAR},
|
||||||
|
create_time = #{createTime,jdbcType=BIGINT},
|
||||||
|
`template` = #{template,jdbcType=LONGVARCHAR}
|
||||||
|
WHERE id = #{id,jdbcType=VARCHAR}
|
||||||
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.MessageTask">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.MessageTask">
|
||||||
update message_task
|
UPDATE message_task
|
||||||
set `type` = #{type,jdbcType=VARCHAR},
|
SET `type` = #{type,jdbcType=VARCHAR},
|
||||||
event = #{event,jdbcType=VARCHAR},
|
event = #{event,jdbcType=VARCHAR},
|
||||||
user_id = #{userId,jdbcType=VARCHAR},
|
user_id = #{userId,jdbcType=VARCHAR},
|
||||||
task_type = #{taskType,jdbcType=VARCHAR},
|
task_type = #{taskType,jdbcType=VARCHAR},
|
||||||
|
@ -301,6 +372,6 @@
|
||||||
organization_id = #{organizationId,jdbcType=VARCHAR},
|
organization_id = #{organizationId,jdbcType=VARCHAR},
|
||||||
test_id = #{testId,jdbcType=VARCHAR},
|
test_id = #{testId,jdbcType=VARCHAR},
|
||||||
create_time = #{createTime,jdbcType=BIGINT}
|
create_time = #{createTime,jdbcType=BIGINT}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
WHERE id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -14,4 +14,6 @@ public interface ExtApiScenarioMapper {
|
||||||
|
|
||||||
List<ApiScenario> selectIds(@Param("ids") List<String> ids);
|
List<ApiScenario> selectIds(@Param("ids") List<String> ids);
|
||||||
|
|
||||||
|
List<ApiScenario> selectReference(@Param("request") ApiScenarioRequest request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,4 +70,23 @@
|
||||||
#{v}
|
#{v}
|
||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectReference" resultType="io.metersphere.base.domain.ApiScenario">
|
||||||
|
select * from api_scenario
|
||||||
|
<where>
|
||||||
|
id != #{request.id}
|
||||||
|
<if test="request.workspaceId != null">
|
||||||
|
AND project.workspace_id = #{request.workspaceId}
|
||||||
|
</if>
|
||||||
|
<if test="request.projectId != null">
|
||||||
|
AND project_id = #{request.projectId}
|
||||||
|
</if>
|
||||||
|
<if test="request.moduleId != null">
|
||||||
|
AND api_scenario_module_id = #{request.moduleId}
|
||||||
|
</if>
|
||||||
|
and scenario_definition like CONCAT('%', #{request.id},'%')
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -17,4 +17,5 @@ public class MessageDetail {
|
||||||
private Boolean isSet;
|
private Boolean isSet;
|
||||||
private String testId;
|
private String testId;
|
||||||
private Long createTime;
|
private Long createTime;
|
||||||
|
private String template;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.notice.domain.MessageDetail;
|
import io.metersphere.notice.domain.MessageDetail;
|
||||||
import io.metersphere.notice.domain.UserDetail;
|
import io.metersphere.notice.domain.UserDetail;
|
||||||
import io.metersphere.service.UserService;
|
import io.metersphere.service.UserService;
|
||||||
|
import org.apache.commons.collections4.MapUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -14,6 +16,7 @@ import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class AbstractNoticeSender implements NoticeSender {
|
public abstract class AbstractNoticeSender implements NoticeSender {
|
||||||
|
@ -21,13 +24,16 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
protected String getContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
protected String getContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||||
|
// 如果配置了模版就直接使用模版
|
||||||
|
if (StringUtils.isNotBlank(messageDetail.getTemplate())) {
|
||||||
|
return getContent(messageDetail.getTemplate(), noticeModel.getParamMap());
|
||||||
|
}
|
||||||
// 处理 userIds 中包含的特殊值
|
// 处理 userIds 中包含的特殊值
|
||||||
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
||||||
messageDetail.setUserIds(realUserIds);
|
messageDetail.setUserIds(realUserIds);
|
||||||
|
|
||||||
// 处理 WeCom Ding context
|
// 处理 WeCom Ding context
|
||||||
String context = "";
|
String context = "";
|
||||||
String status = noticeModel.getStatus();
|
|
||||||
switch (messageDetail.getEvent()) {
|
switch (messageDetail.getEvent()) {
|
||||||
case NoticeConstants.Event.CREATE:
|
case NoticeConstants.Event.CREATE:
|
||||||
case NoticeConstants.Event.UPDATE:
|
case NoticeConstants.Event.UPDATE:
|
||||||
|
@ -48,6 +54,10 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getHtmlContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
protected String getHtmlContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||||
|
// 如果配置了模版就直接使用模版
|
||||||
|
if (StringUtils.isNotBlank(messageDetail.getTemplate())) {
|
||||||
|
return getContent(messageDetail.getTemplate(), noticeModel.getParamMap());
|
||||||
|
}
|
||||||
// 处理 userIds 中包含的特殊值
|
// 处理 userIds 中包含的特殊值
|
||||||
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
||||||
messageDetail.setUserIds(realUserIds);
|
messageDetail.setUserIds(realUserIds);
|
||||||
|
@ -77,7 +87,20 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
}
|
}
|
||||||
return context;
|
return getContent(context, noticeModel.getParamMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getContent(String template, Map<String, Object> context) {
|
||||||
|
if (MapUtils.isNotEmpty(context)) {
|
||||||
|
for (String k : context.keySet()) {
|
||||||
|
if (context.get(k) != null) {
|
||||||
|
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", context.get(k).toString());
|
||||||
|
} else {
|
||||||
|
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<String> getUserPhones(List<String> userIds) {
|
protected List<String> getUserPhones(List<String> userIds) {
|
||||||
|
|
|
@ -5,8 +5,6 @@ import io.metersphere.notice.domain.MessageDetail;
|
||||||
import io.metersphere.notice.sender.AbstractNoticeSender;
|
import io.metersphere.notice.sender.AbstractNoticeSender;
|
||||||
import io.metersphere.notice.sender.NoticeModel;
|
import io.metersphere.notice.sender.NoticeModel;
|
||||||
import io.metersphere.notice.service.MailService;
|
import io.metersphere.notice.service.MailService;
|
||||||
import org.apache.commons.collections4.MapUtils;
|
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -15,14 +13,13 @@ import javax.annotation.Resource;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MailNoticeSender extends AbstractNoticeSender {
|
public class MailNoticeSender extends AbstractNoticeSender {
|
||||||
@Resource
|
@Resource
|
||||||
private MailService mailService;
|
private MailService mailService;
|
||||||
|
|
||||||
private void sendMail(MessageDetail messageDetail, String template, NoticeModel noticeModel) throws MessagingException {
|
private void sendMail(MessageDetail messageDetail, String context, NoticeModel noticeModel) throws MessagingException {
|
||||||
JavaMailSenderImpl javaMailSender = mailService.getMailSender();
|
JavaMailSenderImpl javaMailSender = mailService.getMailSender();
|
||||||
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||||
|
@ -31,25 +28,11 @@ public class MailNoticeSender extends AbstractNoticeSender {
|
||||||
List<String> emails = super.getUserEmails(messageDetail.getUserIds());
|
List<String> emails = super.getUserEmails(messageDetail.getUserIds());
|
||||||
String[] users = emails.toArray(new String[0]);
|
String[] users = emails.toArray(new String[0]);
|
||||||
LogUtil.info("收件人地址: " + emails);
|
LogUtil.info("收件人地址: " + emails);
|
||||||
helper.setText(this.getContent(template, noticeModel.getParamMap()), true);
|
helper.setText(context, true);
|
||||||
helper.setTo(users);
|
helper.setTo(users);
|
||||||
javaMailSender.send(mimeMessage);
|
javaMailSender.send(mimeMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getContent(String template, Map<String, Object> context) {
|
|
||||||
if (MapUtils.isNotEmpty(context)) {
|
|
||||||
for (String k : context.keySet()) {
|
|
||||||
if (context.get(k) != null) {
|
|
||||||
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", context.get(k).toString());
|
|
||||||
} else {
|
|
||||||
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(MessageDetail messageDetail, NoticeModel noticeModel) {
|
public void send(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||||
String context = super.getHtmlContext(messageDetail, noticeModel);
|
String context = super.getHtmlContext(messageDetail, noticeModel);
|
||||||
|
|
|
@ -2,7 +2,6 @@ package io.metersphere.notice.service;
|
||||||
|
|
||||||
import com.alibaba.nacos.client.utils.StringUtils;
|
import com.alibaba.nacos.client.utils.StringUtils;
|
||||||
import io.metersphere.commons.constants.NoticeConstants;
|
import io.metersphere.commons.constants.NoticeConstants;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
|
||||||
import io.metersphere.notice.domain.MessageDetail;
|
import io.metersphere.notice.domain.MessageDetail;
|
||||||
import io.metersphere.notice.sender.NoticeModel;
|
import io.metersphere.notice.sender.NoticeModel;
|
||||||
import io.metersphere.notice.sender.NoticeSender;
|
import io.metersphere.notice.sender.NoticeSender;
|
||||||
|
@ -22,10 +21,8 @@ public class NoticeSendService {
|
||||||
private WeComNoticeSender weComNoticeSender;
|
private WeComNoticeSender weComNoticeSender;
|
||||||
@Resource
|
@Resource
|
||||||
private DingNoticeSender dingNoticeSender;
|
private DingNoticeSender dingNoticeSender;
|
||||||
|
@Resource
|
||||||
private void event(String event) {
|
private NoticeService noticeService;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private NoticeSender getNoticeSender(MessageDetail messageDetail) {
|
private NoticeSender getNoticeSender(MessageDetail messageDetail) {
|
||||||
NoticeSender noticeSender = null;
|
NoticeSender noticeSender = null;
|
||||||
|
@ -47,8 +44,6 @@ public class NoticeSendService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(String taskType, NoticeModel noticeModel) {
|
public void send(String taskType, NoticeModel noticeModel) {
|
||||||
NoticeService noticeService = CommonBeanFactory.getBean(NoticeService.class);
|
|
||||||
assert noticeService != null;
|
|
||||||
List<MessageDetail> messageDetails;
|
List<MessageDetail> messageDetails;
|
||||||
switch (taskType) {
|
switch (taskType) {
|
||||||
case NoticeConstants.Mode.API:
|
case NoticeConstants.Mode.API:
|
||||||
|
|
|
@ -33,14 +33,17 @@ public class NoticeService {
|
||||||
SessionUser user = SessionUtils.getUser();
|
SessionUser user = SessionUtils.getUser();
|
||||||
String orgId = user.getLastOrganizationId();
|
String orgId = user.getLastOrganizationId();
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
String identification = UUID.randomUUID().toString();
|
String identification = messageDetail.getIdentification();
|
||||||
messageDetail.getUserIds().forEach(m -> {
|
if (StringUtils.isBlank(identification)) {
|
||||||
checkUserIdExist(m, messageDetail, orgId);
|
identification = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
for (String userId : messageDetail.getUserIds()) {
|
||||||
|
checkUserIdExist(userId, messageDetail, orgId);
|
||||||
MessageTask messageTask = new MessageTask();
|
MessageTask messageTask = new MessageTask();
|
||||||
messageTask.setId(UUID.randomUUID().toString());
|
messageTask.setId(UUID.randomUUID().toString());
|
||||||
messageTask.setEvent(messageDetail.getEvent());
|
messageTask.setEvent(messageDetail.getEvent());
|
||||||
messageTask.setTaskType(messageDetail.getTaskType());
|
messageTask.setTaskType(messageDetail.getTaskType());
|
||||||
messageTask.setUserId(m);
|
messageTask.setUserId(userId);
|
||||||
messageTask.setType(messageDetail.getType());
|
messageTask.setType(messageDetail.getType());
|
||||||
messageTask.setWebhook(messageDetail.getWebhook());
|
messageTask.setWebhook(messageDetail.getWebhook());
|
||||||
messageTask.setIdentification(identification);
|
messageTask.setIdentification(identification);
|
||||||
|
@ -48,8 +51,15 @@ public class NoticeService {
|
||||||
messageTask.setOrganizationId(orgId);
|
messageTask.setOrganizationId(orgId);
|
||||||
messageTask.setTestId(messageDetail.getTestId());
|
messageTask.setTestId(messageDetail.getTestId());
|
||||||
messageTask.setCreateTime(time);
|
messageTask.setCreateTime(time);
|
||||||
|
setTemplate(messageDetail, messageTask);
|
||||||
messageTaskMapper.insert(messageTask);
|
messageTaskMapper.insert(messageTask);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTemplate(MessageDetail messageDetail, MessageTask messageTask) {
|
||||||
|
if (StringUtils.isNotBlank(messageDetail.getTemplate())) {
|
||||||
|
messageTask.setTemplate(messageDetail.getTemplate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUserIdExist(String userId, MessageDetail list, String orgId) {
|
private void checkUserIdExist(String userId, MessageDetail list, String orgId) {
|
||||||
|
@ -80,7 +90,7 @@ public class NoticeService {
|
||||||
public List<MessageDetail> searchMessageByTestId(String testId) {
|
public List<MessageDetail> searchMessageByTestId(String testId) {
|
||||||
MessageTaskExample example = new MessageTaskExample();
|
MessageTaskExample example = new MessageTaskExample();
|
||||||
example.createCriteria().andTestIdEqualTo(testId);
|
example.createCriteria().andTestIdEqualTo(testId);
|
||||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||||
List<MessageDetail> scheduleMessageTask = new ArrayList<>();
|
List<MessageDetail> scheduleMessageTask = new ArrayList<>();
|
||||||
Map<String, List<MessageTask>> MessageTaskMap = messageTaskLists.stream().collect(Collectors.groupingBy(MessageTask::getIdentification));
|
Map<String, List<MessageTask>> MessageTaskMap = messageTaskLists.stream().collect(Collectors.groupingBy(MessageTask::getIdentification));
|
||||||
MessageTaskMap.forEach((k, v) -> {
|
MessageTaskMap.forEach((k, v) -> {
|
||||||
|
@ -100,7 +110,7 @@ public class NoticeService {
|
||||||
example.createCriteria()
|
example.createCriteria()
|
||||||
.andTaskTypeEqualTo(type)
|
.andTaskTypeEqualTo(type)
|
||||||
.andOrganizationIdEqualTo(orgId);
|
.andOrganizationIdEqualTo(orgId);
|
||||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||||
|
|
||||||
Map<String, List<MessageTask>> messageTaskMap = messageTaskLists.stream()
|
Map<String, List<MessageTask>> messageTaskMap = messageTaskLists.stream()
|
||||||
.collect(Collectors.groupingBy(NoticeService::fetchGroupKey));
|
.collect(Collectors.groupingBy(NoticeService::fetchGroupKey));
|
||||||
|
@ -130,6 +140,7 @@ public class NoticeService {
|
||||||
messageDetail.setType(m.getType());
|
messageDetail.setType(m.getType());
|
||||||
messageDetail.setIsSet(m.getIsSet());
|
messageDetail.setIsSet(m.getIsSet());
|
||||||
messageDetail.setCreateTime(m.getCreateTime());
|
messageDetail.setCreateTime(m.getCreateTime());
|
||||||
|
messageDetail.setTemplate(m.getTemplate());
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(userIds)) {
|
if (CollectionUtils.isNotEmpty(userIds)) {
|
||||||
messageDetail.setUserIds(new ArrayList<>(userIds));
|
messageDetail.setUserIds(new ArrayList<>(userIds));
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bb494fc68a2367359c9048fa7250c7618de4afb6
|
Subproject commit 905ca8af61ce966d26109e9c5c8c0aee3ca1324e
|
|
@ -0,0 +1,13 @@
|
||||||
|
ALTER TABLE message_task
|
||||||
|
MODIFY identification varchar(50) NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE message_task
|
||||||
|
MODIFY organization_id varchar(50) NULL;
|
||||||
|
|
||||||
|
ALTER TABLE message_task
|
||||||
|
MODIFY test_id varchar(50) NULL;
|
||||||
|
|
||||||
|
ALTER TABLE message_task
|
||||||
|
ADD template TEXT NULL;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS notice;
|
|
@ -86,6 +86,7 @@ export default {
|
||||||
background-color: rgb(44, 42, 72);
|
background-color: rgb(44, 42, 72);
|
||||||
color: rgb(245, 245, 245);
|
color: rgb(245, 245, 245);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
},
|
},
|
||||||
editApi(row) {
|
editApi(row) {
|
||||||
let name = this.request.name;
|
let name = this.request.name;
|
||||||
Object.assign(this.request, JSON.parse(row.request));
|
Object.assign(this.request, row.request);
|
||||||
this.request.name = name;
|
this.request.name = name;
|
||||||
this.request.resourceId = getUUID();
|
this.request.resourceId = getUUID();
|
||||||
this.$emit('addCustomizeApi', this.request);
|
this.$emit('addCustomizeApi', this.request);
|
||||||
|
|
|
@ -46,12 +46,13 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="passingRate" :label="$t('api_test.automation.passing_rate')"
|
<el-table-column prop="passingRate" :label="$t('api_test.automation.passing_rate')"
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
<el-table-column :label="$t('commons.operating')" width="180">
|
<el-table-column :label="$t('commons.operating')" width="240">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>
|
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>
|
||||||
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button>
|
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button>
|
||||||
<el-button type="text" @click="copy(row)">{{ $t('api_test.automation.copy') }}</el-button>
|
<el-button type="text" @click="copy(row)">{{ $t('api_test.automation.copy') }}</el-button>
|
||||||
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
|
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
|
||||||
|
<ms-scenario-extend-buttons :row="row"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -76,10 +77,11 @@
|
||||||
import MsTag from "../../../common/components/MsTag";
|
import MsTag from "../../../common/components/MsTag";
|
||||||
import {getUUID} from "@/common/js/utils";
|
import {getUUID} from "@/common/js/utils";
|
||||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||||
|
import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiScenarioList",
|
name: "MsApiScenarioList",
|
||||||
components: {ShowMoreBtn, MsTablePagination, MsTableHeader, MsTag, MsApiReportDetail},
|
components: {MsScenarioExtendButtons, ShowMoreBtn, MsTablePagination, MsTableHeader, MsTag, MsApiReportDetail},
|
||||||
props: {
|
props: {
|
||||||
currentProject: Object,
|
currentProject: Object,
|
||||||
currentModule: Object,
|
currentModule: Object,
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<span class="kv-description" v-if="description">
|
||||||
|
{{description}}
|
||||||
|
</span>
|
||||||
|
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||||
|
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||||
|
<el-col class="kv-checkbox">
|
||||||
|
<input type="checkbox" v-if="!isDisable(index)" @change="change" :value="item.uuid" v-model="item.enable"
|
||||||
|
:disabled="isDisable(index) || isReadOnly"/>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col>
|
||||||
|
<ms-api-variable-input :show-copy="showCopy" :show-variable="showVariable" :is-read-only="isReadOnly" v-model="item.name" size="small" maxlength="200" @change="change"
|
||||||
|
:placeholder="$t('api_test.variable_name')" show-word-limit/>
|
||||||
|
</el-col>
|
||||||
|
<el-col>
|
||||||
|
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"
|
||||||
|
:placeholder="$t('api_test.value')" show-word-limit/>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="kv-delete">
|
||||||
|
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||||
|
:disabled="isDisable(index) || isReadOnly"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {KeyValue} from "../../definition/model/ApiTestModel";
|
||||||
|
import MsApiVariableInput from "./ApiVariableInput";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsApiScenarioVariables",
|
||||||
|
components: {MsApiVariableInput},
|
||||||
|
props: {
|
||||||
|
description: String,
|
||||||
|
items: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showVariable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showCopy: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
remove: function (index) {
|
||||||
|
this.items.splice(index, 1);
|
||||||
|
this.$emit('change', this.items);
|
||||||
|
},
|
||||||
|
change: function () {
|
||||||
|
let isNeedCreate = true;
|
||||||
|
let removeIndex = -1;
|
||||||
|
this.items.forEach((item, index) => {
|
||||||
|
if (!item.name && !item.value) {
|
||||||
|
// 多余的空行
|
||||||
|
if (index !== this.items.length - 1) {
|
||||||
|
removeIndex = index;
|
||||||
|
}
|
||||||
|
// 没有空行,需要创建空行
|
||||||
|
isNeedCreate = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (isNeedCreate) {
|
||||||
|
this.items.push(new KeyValue({enable: true}));
|
||||||
|
}
|
||||||
|
this.$emit('change', this.items);
|
||||||
|
// TODO 检查key重复
|
||||||
|
},
|
||||||
|
isDisable: function (index) {
|
||||||
|
return this.items.length - 1 === index;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (this.items.length === 0) {
|
||||||
|
this.items.push(new KeyValue({enable: true}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.kv-description {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-checkbox {
|
||||||
|
width: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-row {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-delete {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div class="variable-input" :class="{'show-copy': !showCopy}">
|
||||||
|
<el-input class="el-input__inner_pd" :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||||
|
<div :class="{'hidden': !showVariable}" class="variable-combine" v-if="value">
|
||||||
|
<div v-if="showCopy" class="variable">{{variable}}</div>
|
||||||
|
<el-tooltip v-if="showCopy" :content="$t('api_test.copied')" manual v-model="visible" placement="top" :visible-arrow="false">
|
||||||
|
<i class="el-icon-copy-document copy" @click="copy"/>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "MsApiVariableInput",
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
size: String,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showVariable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showCopy: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showCopyTipWithMultiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
copy() {
|
||||||
|
let input = document.createElement("input");
|
||||||
|
document.body.appendChild(input);
|
||||||
|
input.value = this.variable;
|
||||||
|
input.select();
|
||||||
|
if (input.setSelectionRange) {
|
||||||
|
input.setSelectionRange(0, input.value.length);
|
||||||
|
}
|
||||||
|
document.execCommand("copy");
|
||||||
|
document.body.removeChild(input);
|
||||||
|
this.visible = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.visible = false;
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
change(value) {
|
||||||
|
this.$emit('change', value);
|
||||||
|
},
|
||||||
|
input(value) {
|
||||||
|
this.$emit('input', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
variable() {
|
||||||
|
return "${" + (this.showCopyTipWithMultiple ? (this.value + "_n") : this.value) + "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.variable-input {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__inner_pd >>> .el-input__inner {
|
||||||
|
padding-right: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-copy .el-input__inner_pd >>> .el-input__inner {
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.variable-combine {
|
||||||
|
color: #7F7F7F;
|
||||||
|
max-width: 80px;
|
||||||
|
line-height: 32px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 70px;
|
||||||
|
margin-right: -20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-combine .variable {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 60px;
|
||||||
|
margin-right: 10px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-combine .copy {
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -125,10 +125,12 @@
|
||||||
{{currentScenario.name ===undefined || ''? $t('api_test.scenario.name') : currentScenario.name}}
|
{{currentScenario.name ===undefined || ''? $t('api_test.scenario.name') : currentScenario.name}}
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" class="ms-col-one">
|
<el-col :span="4" class="ms-col-one">
|
||||||
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" class="ms-col-one">
|
<el-col :span="4" class="ms-col-one">
|
||||||
{{$t('api_test.automation.scenario_total')}}:
|
<el-link style="font-size: 13px" @click="showScenarioParameters">{{$t('api_test.automation.scenario_total')}}:
|
||||||
|
{{this.currentScenario.variables!=undefined?this.currentScenario.variables.length-1: 0}}
|
||||||
|
</el-link>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
{{$t('api_test.definition.request.run_env')}}:
|
{{$t('api_test.definition.request.run_env')}}:
|
||||||
|
@ -263,6 +265,9 @@
|
||||||
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||||
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject.id"/>
|
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject.id"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
<!--场景公共参数-->
|
||||||
|
<ms-scenario-parameters :currentScenario="currentScenario" @addParameters="addParameters" ref="scenarioParameters"/>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -288,6 +293,7 @@
|
||||||
import MsImportApiScenario from "./ImportApiScenario";
|
import MsImportApiScenario from "./ImportApiScenario";
|
||||||
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
||||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||||
|
import MsScenarioParameters from "./ScenarioParameters";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -297,7 +303,15 @@
|
||||||
currentProject: {},
|
currentProject: {},
|
||||||
currentScenario: {},
|
currentScenario: {},
|
||||||
},
|
},
|
||||||
components: {ApiEnvironmentConfig, MsApiReportDetail, MsAddTag, MsRun, MsApiScenarioComponent, MsImportApiScenario, MsJsr233Processor, MsConstantTimer, MsIfController, MsApiAssertions, MsApiExtract, MsApiDefinition, MsApiComponent, MsApiCustomize},
|
components: {
|
||||||
|
ApiEnvironmentConfig, MsScenarioParameters,
|
||||||
|
MsApiReportDetail, MsAddTag, MsRun,
|
||||||
|
MsApiScenarioComponent, MsImportApiScenario,
|
||||||
|
MsJsr233Processor, MsConstantTimer,
|
||||||
|
MsIfController, MsApiAssertions,
|
||||||
|
MsApiExtract, MsApiDefinition,
|
||||||
|
MsApiComponent, MsApiCustomize
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
@ -648,9 +662,6 @@
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.setParameter();
|
this.setParameter();
|
||||||
let bodyFiles = this.getBodyUploadFiles(this.currentScenario);
|
let bodyFiles = this.getBodyUploadFiles(this.currentScenario);
|
||||||
console.log(bodyFiles)
|
|
||||||
console.log(this.currentScenario.bodyUploadIds)
|
|
||||||
|
|
||||||
this.$fileUpload(this.path, null, bodyFiles, this.currentScenario, () => {
|
this.$fileUpload(this.path, null, bodyFiles, this.currentScenario, () => {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
this.path = "/api/automation/update";
|
this.path = "/api/automation/update";
|
||||||
|
@ -685,7 +696,7 @@
|
||||||
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
||||||
// 构建一个场景对象 方便引用处理
|
// 构建一个场景对象 方便引用处理
|
||||||
let scenario = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
let scenario = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
||||||
this.currentScenario.scenarioDefinition = JSON.stringify(scenario);
|
this.currentScenario.scenarioDefinition = scenario;
|
||||||
this.currentScenario.tagId = JSON.stringify(this.currentScenario.tagId);
|
this.currentScenario.tagId = JSON.stringify(this.currentScenario.tagId);
|
||||||
if (this.currentModule != null) {
|
if (this.currentModule != null) {
|
||||||
this.currentScenario.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
|
this.currentScenario.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
|
||||||
|
@ -695,6 +706,13 @@
|
||||||
runRefresh() {
|
runRefresh() {
|
||||||
this.debugVisible = true;
|
this.debugVisible = true;
|
||||||
this.isReloadData = false;
|
this.isReloadData = false;
|
||||||
|
},
|
||||||
|
showScenarioParameters() {
|
||||||
|
this.$refs.scenarioParameters.open(this.currentScenario.variables);
|
||||||
|
},
|
||||||
|
addParameters(data) {
|
||||||
|
this.currentScenario.variables = data;
|
||||||
|
this.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.case_ref')" :visible.sync="visible"
|
||||||
|
width="45%" :destroy-on-close="true">
|
||||||
|
<span>{{ $t('api_test.automation.scenario_ref') }}:</span>
|
||||||
|
<div class="refs" v-loading="scenarioLoading">
|
||||||
|
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">{{ item.name }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span>{{ $t('api_test.automation.plan_ref') }}:</span>
|
||||||
|
<div class="refs">
|
||||||
|
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">{{ item.name }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-slot:footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
|
||||||
|
{{ $t('commons.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsReferenceView",
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
scenarioLoading: false,
|
||||||
|
scenarioRefs: [],
|
||||||
|
planRefs: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getReferenceData(row) {
|
||||||
|
this.scenarioLoading = true;
|
||||||
|
this.scenarioRefs = [];
|
||||||
|
this.$post("/api/automation/getReference/", row, response => {
|
||||||
|
this.scenarioRefs = response.data;
|
||||||
|
this.scenarioLoading = false;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
open(row) {
|
||||||
|
this.getReferenceData(row);
|
||||||
|
this.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.refs {
|
||||||
|
min-height: 50px;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<el-dropdown @command="handleCommand" class="scenario-ext-btn">
|
||||||
|
<el-link type="primary" :underline="false">
|
||||||
|
<el-icon class="el-icon-more"></el-icon>
|
||||||
|
</el-link>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
<ms-reference-view ref="viewRef"/>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsReferenceView from "@/business/components/api/automation/scenario/ReferenceView";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsScenarioExtendButtons",
|
||||||
|
components: {MsReferenceView},
|
||||||
|
props: {
|
||||||
|
row: Object
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleCommand(cmd) {
|
||||||
|
switch (cmd) {
|
||||||
|
case "ref":
|
||||||
|
this.$refs.viewRef.open(this.row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.scenario-ext-btn {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :close-on-click-modal="false" :title="$t('api_test.scenario.variables')"
|
||||||
|
:visible.sync="visible" class="environment-dialog" width="60%"
|
||||||
|
@close="close">
|
||||||
|
<el-container>
|
||||||
|
<ms-api-scenario-variables :items="variables"
|
||||||
|
:description="$t('api_test.scenario.kv_description')"/>
|
||||||
|
</el-container>
|
||||||
|
<template v-slot:footer>
|
||||||
|
<ms-dialog-footer
|
||||||
|
@cancel="close"
|
||||||
|
@confirm="saveParameters"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsApiScenarioVariables from "./ApiScenarioVariables";
|
||||||
|
import {KeyValue} from "../../definition/model/ApiTestModel";
|
||||||
|
import MsDialogFooter from "../../../common/components/MsDialogFooter";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsScenarioParameters",
|
||||||
|
components: {
|
||||||
|
MsApiScenarioVariables,
|
||||||
|
MsDialogFooter
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
variables: [new KeyValue()],
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open: function (v) {
|
||||||
|
this.visible = true;
|
||||||
|
if(v){
|
||||||
|
this.variables = v;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
saveParameters() {
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('addParameters', this.variables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -190,6 +190,7 @@
|
||||||
api: {
|
api: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
|
createCase: String,
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -217,7 +218,6 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
// 初始化
|
// 初始化
|
||||||
api() {
|
api() {
|
||||||
|
@ -237,13 +237,35 @@
|
||||||
this.currentRow.cases = [];
|
this.currentRow.cases = [];
|
||||||
}
|
}
|
||||||
this.getApiTest();
|
this.getApiTest();
|
||||||
|
},
|
||||||
|
createCase() {
|
||||||
|
this.sysAddition();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getApiTest();
|
|
||||||
this.getEnvironments();
|
this.getEnvironments();
|
||||||
|
if (this.createCase) {
|
||||||
|
this.sysAddition();
|
||||||
|
} else {
|
||||||
|
this.getApiTest();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
sysAddition() {
|
||||||
|
let condition = {};
|
||||||
|
condition.projectId = this.api.projectId;
|
||||||
|
condition.apiDefinitionId = this.api.id;
|
||||||
|
condition.priority = this.priorityValue;
|
||||||
|
condition.name = this.name;
|
||||||
|
this.$post("/api/testcase/list", condition, response => {
|
||||||
|
for (let index in response.data) {
|
||||||
|
let test = response.data[index];
|
||||||
|
test.request = JSON.parse(test.request);
|
||||||
|
}
|
||||||
|
this.apiCaseList = response.data;
|
||||||
|
this.addCase();
|
||||||
|
});
|
||||||
|
},
|
||||||
getResult(data) {
|
getResult(data) {
|
||||||
if (RESULT_MAP.get(data)) {
|
if (RESULT_MAP.get(data)) {
|
||||||
return RESULT_MAP.get(data);
|
return RESULT_MAP.get(data);
|
||||||
|
|
|
@ -91,35 +91,38 @@
|
||||||
this.maintainerOptions = response.data;
|
this.maintainerOptions = response.data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
initSql() {
|
setRequest() {
|
||||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||||
this.request = JSON.parse(this.currentApi.request);
|
if (Object.prototype.toString.call(this.currentApi.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
|
||||||
this.currentApi.request = this.request;
|
this.request = this.currentApi.request;
|
||||||
} else {
|
} else {
|
||||||
|
this.request = JSON.parse(this.currentApi.request);
|
||||||
|
}
|
||||||
|
this.currentApi.request = this.request;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
initSql() {
|
||||||
|
if (!this.setRequest()) {
|
||||||
this.request = createComponent("JDBCSampler");
|
this.request = createComponent("JDBCSampler");
|
||||||
|
this.currentApi.request = this.request;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initDubbo() {
|
initDubbo() {
|
||||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
if (!this.setRequest()) {
|
||||||
this.request = JSON.parse(this.currentApi.request);
|
|
||||||
this.currentApi.request = this.request;
|
|
||||||
} else {
|
|
||||||
this.request = createComponent("DubboSampler");
|
this.request = createComponent("DubboSampler");
|
||||||
|
this.currentApi.request = this.request;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initTcp() {
|
initTcp() {
|
||||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
if (!this.setRequest()) {
|
||||||
this.request = JSON.parse(this.currentApi.request);
|
|
||||||
this.currentApi.request = this.request;
|
|
||||||
} else {
|
|
||||||
this.request = createComponent("TCPSampler");
|
this.request = createComponent("TCPSampler");
|
||||||
|
this.currentApi.request = this.request;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initHttp() {
|
initHttp() {
|
||||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
if (!this.setRequest()) {
|
||||||
this.request = JSON.parse(this.currentApi.request);
|
|
||||||
this.currentApi.request = this.request;
|
|
||||||
} else {
|
|
||||||
this.request = createComponent("HTTPSamplerProxy");
|
this.request = createComponent("HTTPSamplerProxy");
|
||||||
this.currentApi.request = this.request;
|
this.currentApi.request = this.request;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
this.$refs.debugResult.reload();
|
this.$refs.debugResult.reload();
|
||||||
},
|
},
|
||||||
saveAs() {
|
saveAs() {
|
||||||
let obj = {request: JSON.stringify(this.request)};
|
let obj = {request: this.request};
|
||||||
this.$emit('saveAs', obj);
|
this.$emit('saveAs', obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
saveAs() {
|
saveAs() {
|
||||||
this.$refs['debugForm'].validate((valid) => {
|
this.$refs['debugForm'].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.debugForm.request = JSON.stringify(this.request);
|
this.debugForm.request = this.request;
|
||||||
this.debugForm.userId = getCurrentUser().id;
|
this.debugForm.userId = getCurrentUser().id;
|
||||||
this.debugForm.status = "Underway";
|
this.debugForm.status = "Underway";
|
||||||
this.debugForm.protocol = this.currentProtocol;
|
this.debugForm.protocol = this.currentProtocol;
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
this.$refs.debugResult.reload();
|
this.$refs.debugResult.reload();
|
||||||
},
|
},
|
||||||
saveAs() {
|
saveAs() {
|
||||||
let obj = {request: JSON.stringify(this.request)};
|
let obj = {request: this.request};
|
||||||
this.$emit('saveAs', obj);
|
this.$emit('saveAs', obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
this.$refs.debugResult.reload();
|
this.$refs.debugResult.reload();
|
||||||
},
|
},
|
||||||
saveAs() {
|
saveAs() {
|
||||||
let obj = {request: JSON.stringify(this.request)};
|
let obj = {request: this.request};
|
||||||
this.$emit('saveAs', obj);
|
this.$emit('saveAs', obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<!-- 加载用例 -->
|
<!-- 加载用例 -->
|
||||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api"
|
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api"
|
||||||
:currentProject="currentProject" :loaded="loaded" :refreshSign="refreshSign"
|
:currentProject="currentProject" :loaded="loaded" :refreshSign="refreshSign" :createCase="createCase"
|
||||||
ref="caseList"/>
|
ref="caseList"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
>
|
>
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
loaded: false,
|
loaded: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
currentRequest: {},
|
currentRequest: {},
|
||||||
|
createCase: "",
|
||||||
refreshSign: "",
|
refreshSign: "",
|
||||||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||||
reqOptions: REQ_METHOD,
|
reqOptions: REQ_METHOD,
|
||||||
|
@ -153,9 +154,10 @@
|
||||||
return bodyUploadFiles;
|
return bodyUploadFiles;
|
||||||
},
|
},
|
||||||
saveAsCase() {
|
saveAsCase() {
|
||||||
this.visible = false;
|
//用于触发创建操作
|
||||||
|
this.createCase = getUUID();
|
||||||
|
this.visible = true;
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.$refs.caseList.addCase();
|
|
||||||
},
|
},
|
||||||
saveAsApi() {
|
saveAsApi() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
|
@ -70,9 +70,9 @@
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 加载用例 -->
|
<!-- 加载用例 -->
|
||||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%" ref="drawer">
|
||||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||||
:currentProject="currentProject" :loaded="loaded"
|
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||||
ref="caseList"/>
|
ref="caseList"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
@ -113,8 +113,9 @@
|
||||||
api: {},
|
api: {},
|
||||||
loaded: false,
|
loaded: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
createCase: "",
|
||||||
currentRequest: {},
|
currentRequest: {},
|
||||||
refreshSign:"",
|
refreshSign: "",
|
||||||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||||
reqOptions: REQ_METHOD,
|
reqOptions: REQ_METHOD,
|
||||||
environments: [],
|
environments: [],
|
||||||
|
@ -194,7 +195,9 @@
|
||||||
return bodyUploadFiles;
|
return bodyUploadFiles;
|
||||||
},
|
},
|
||||||
saveAsCase() {
|
saveAsCase() {
|
||||||
this.visible = false;
|
//用于触发创建操作
|
||||||
|
this.createCase = getUUID();
|
||||||
|
this.visible = true;
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
},
|
},
|
||||||
saveAsApi() {
|
saveAsApi() {
|
||||||
|
@ -301,7 +304,8 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-left: 4px solid #783887;
|
border-left: 4px solid #783887;
|
||||||
}
|
}
|
||||||
/deep/.el-drawer{
|
|
||||||
|
/deep/ .el-drawer {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -30,9 +30,10 @@
|
||||||
<!-- 加载用例 -->
|
<!-- 加载用例 -->
|
||||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||||
:currentProject="currentProject" :loaded="loaded"
|
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||||
ref="caseList"/>
|
ref="caseList"/>
|
||||||
</el-drawer>>
|
</el-drawer>
|
||||||
|
>
|
||||||
|
|
||||||
<!-- 环境 -->
|
<!-- 环境 -->
|
||||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||||
|
@ -79,6 +80,7 @@
|
||||||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||||
reqOptions: REQ_METHOD,
|
reqOptions: REQ_METHOD,
|
||||||
refreshSign: "",
|
refreshSign: "",
|
||||||
|
createCase: "",
|
||||||
environments: [],
|
environments: [],
|
||||||
rules: {
|
rules: {
|
||||||
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||||
|
@ -151,9 +153,9 @@
|
||||||
return bodyUploadFiles;
|
return bodyUploadFiles;
|
||||||
},
|
},
|
||||||
saveAsCase() {
|
saveAsCase() {
|
||||||
this.visible = false;
|
this.createCase = getUUID();
|
||||||
|
this.visible = true;
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.$refs.caseList.addCase();
|
|
||||||
},
|
},
|
||||||
saveAsApi() {
|
saveAsApi() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
@ -249,7 +251,8 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-left: 4px solid #783887;
|
border-left: 4px solid #783887;
|
||||||
}
|
}
|
||||||
/deep/.el-drawer{
|
|
||||||
|
/deep/ .el-drawer {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<!-- 加载用例 -->
|
<!-- 加载用例 -->
|
||||||
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
<el-drawer :visible.sync="visible" direction="btt" :with-header="false" :modal="false" size="50%">
|
||||||
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
<ms-api-case-list @apiCaseClose="apiCaseClose" @selectTestCase="selectTestCase" :api="api" :refreshSign="refreshSign"
|
||||||
:currentProject="currentProject" :loaded="loaded"
|
:currentProject="currentProject" :loaded="loaded" :createCase="createCase"
|
||||||
ref="caseList"/>
|
ref="caseList"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<!-- 环境 -->
|
<!-- 环境 -->
|
||||||
|
@ -80,6 +80,7 @@
|
||||||
reqOptions: REQ_METHOD,
|
reqOptions: REQ_METHOD,
|
||||||
environments: [],
|
environments: [],
|
||||||
refreshSign: "",
|
refreshSign: "",
|
||||||
|
createCase: "",
|
||||||
rules: {
|
rules: {
|
||||||
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
method: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||||
url: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}],
|
url: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}],
|
||||||
|
@ -151,9 +152,9 @@
|
||||||
return bodyUploadFiles;
|
return bodyUploadFiles;
|
||||||
},
|
},
|
||||||
saveAsCase() {
|
saveAsCase() {
|
||||||
this.visible = false;
|
this.createCase = getUUID();
|
||||||
|
this.visible = true;
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.$refs.caseList.addCase();
|
|
||||||
},
|
},
|
||||||
saveAsApi() {
|
saveAsApi() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="menu-bar" v-if="isRouterAlive">
|
<div id="menu-bar" v-if="isRouterAlive">
|
||||||
<el-row type="flex">
|
<el-row type="flex">
|
||||||
<el-col :span="10">
|
<el-col :span="14">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||||
|
|
||||||
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider class="menu-divider"/>
|
<el-divider class="menu-divider"/>
|
||||||
<el-menu-item :index="'/performance/project/create'">
|
<el-menu-item :index="'/setting/project/create'">
|
||||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
<span style="padding-left: 7px;">创建项目</span>
|
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<ms-show-all :index="'/setting/project'"/>
|
<ms-show-all :index="'/setting/project/all'"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-menu-item :index="'/api/home'">
|
<el-menu-item :index="'/api/home'">
|
||||||
|
@ -54,12 +54,12 @@
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="6">
|
||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<ms-create-test :to="'/api/test/create'"/>
|
<ms-create-test :to="'/api/test/create'"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6"/>
|
<el-col :span="4"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<common-monitor-chart>
|
<common-monitor-chart>
|
||||||
<template>
|
<template>
|
||||||
<div id="response-time-chart" :style="{ width:'100%',height:'100%' }">
|
<div id="response-time-chart" :style="{ width:'100%',height:'100%' }">
|
||||||
<chart :options="getOptions()" :style="{ width:'100%' }"></chart>
|
<chart :options="getOptions()" :style="{ width:'100%' }" v-on:click="click"></chart>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</common-monitor-chart>
|
</common-monitor-chart>
|
||||||
|
@ -27,8 +27,6 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
click(params) {
|
click(params) {
|
||||||
//如果状态不是以2开头
|
|
||||||
if (params.value.substr(0, 1) !== '2') {
|
|
||||||
let startTime = params.name;
|
let startTime = params.name;
|
||||||
this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, {
|
this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, {
|
||||||
'apiUrl': this.apiUrl
|
'apiUrl': this.apiUrl
|
||||||
|
@ -36,11 +34,8 @@ export default {
|
||||||
this.reportId = response.data;
|
this.reportId = response.data;
|
||||||
let reportId = this.reportId
|
let reportId = this.reportId
|
||||||
let url = '#/api/report/view/' + reportId;
|
let url = '#/api/report/view/' + reportId;
|
||||||
let target = '_blank';
|
window.open(url, '_blank');
|
||||||
window.open(url, target);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
getOptions() {
|
getOptions() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import MsProject from "@/business/components/project/MsProject";
|
import MsProject from "@/business/components/settings/project/MsProject";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: "/api",
|
path: "/api",
|
||||||
|
@ -24,11 +24,11 @@ export default {
|
||||||
name: "ApiTestList",
|
name: "ApiTestList",
|
||||||
component: () => import('@/business/components/api/test/ApiTestList'),
|
component: () => import('@/business/components/api/test/ApiTestList'),
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: "project/:type",
|
// path: "project/:type",
|
||||||
name: "fucProject",
|
// name: "fucProject",
|
||||||
component: MsProject,
|
// component: MsProject,
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: "report/list/:testId",
|
path: "report/list/:testId",
|
||||||
name: "ApiReportList",
|
name: "ApiReportList",
|
||||||
|
@ -53,6 +53,11 @@ export default {
|
||||||
path: "automation/report",
|
path: "automation/report",
|
||||||
name: "ApiReportList",
|
name: "ApiReportList",
|
||||||
component: () => import('@/business/components/api/automation/report/ApiReportList'),
|
component: () => import('@/business/components/api/automation/report/ApiReportList'),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: 'monitor/view',
|
||||||
|
name: 'ApiMonitor',
|
||||||
|
component: () => import('@/business/components/api/monitor/ApiMonitor'),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,10 +213,4 @@ export default {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-select__tags {
|
|
||||||
flex-wrap: unset;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
|
|
||||||
.el-menu >>> .el-menu-item {
|
.el-menu >>> .el-menu-item {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 37px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default {
|
||||||
options: Object
|
options: Object
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.recent();
|
this.init();
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -44,7 +44,7 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
search_text(val) {
|
search_text(val) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.recent();
|
this.init();
|
||||||
} else {
|
} else {
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
recent: function () {
|
init: function () {
|
||||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||||
this.result = this.$get(this.options.url, (response) => {
|
this.result = this.$get(this.options.url, (response) => {
|
||||||
this.items = response.data;
|
this.items = response.data;
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<el-menu-item :index="'/performance/project/create'">
|
<el-menu-item :index="'/setting/project/create'">
|
||||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
<span style="padding-left: 7px;">创建项目</span>
|
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<ms-show-all :index="'/setting/project'"/>
|
<ms-show-all :index="'/setting/project/all'"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-menu-item :index="'/performance/home'">
|
<el-menu-item :index="'/performance/home'">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import MsProject from "@/business/components/project/MsProject";
|
import MsProject from "@/business/components/settings/project/MsProject";
|
||||||
|
|
||||||
const PerformanceTest = () => import('@/business/components/performance/PerformanceTest')
|
const PerformanceTest = () => import('@/business/components/performance/PerformanceTest')
|
||||||
const PerformanceTestHome = () => import('@/business/components/performance/home/PerformanceTestHome')
|
const PerformanceTestHome = () => import('@/business/components/performance/home/PerformanceTestHome')
|
||||||
|
@ -43,11 +43,11 @@ export default {
|
||||||
name: "perPlan",
|
name: "perPlan",
|
||||||
component: PerformanceTestList
|
component: PerformanceTestList
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: "project/:type",
|
// path: "project/:type",
|
||||||
name: "perProject",
|
// name: "perProject",
|
||||||
component: MsProject
|
// component: MsProject
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: "report/:type",
|
path: "report/:type",
|
||||||
name: "perReport",
|
name: "perReport",
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-menu-item v-for="menu in project" :key="menu.index" :index="menu.index" class="setting-item"
|
<el-menu-item v-for="menu in project" :key="menu.index" :index="'/setting/project/all'" class="setting-item"
|
||||||
v-permission="menu.roles">
|
v-permission="menu.roles">
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<font-awesome-icon class="icon" :icon="['fa', 'bars']" size="lg"/>
|
<font-awesome-icon class="icon" :icon="['fa', 'bars']" size="lg"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
:cell-style="rowClass"
|
:cell-style="rowClass"
|
||||||
:header-cell-style="headClass"
|
:header-cell-style="headClass"
|
||||||
>
|
>
|
||||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||||
prop="event" :disabled="!scope.row.isSet">
|
prop="event" :disabled="!scope.row.isSet">
|
||||||
|
@ -64,8 +64,16 @@
|
||||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="mini"
|
||||||
|
v-if="scope.row.isSet"
|
||||||
|
v-xpack
|
||||||
|
@click="handleTemplate(scope.$index,scope.row)"
|
||||||
|
>{{ $t('organization.message.template') }}
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
|
@ -98,14 +106,22 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<notice-template v-xpack ref="noticeTemplate"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
const TASK_TYPE = 'DEFECT_TASK';
|
const TASK_TYPE = 'DEFECT_TASK';
|
||||||
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
|
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "DefectTaskNotification",
|
name: "DefectTaskNotification",
|
||||||
|
components: {
|
||||||
|
"NoticeTemplate": noticeTemplate.default
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
defectReceiverOptions: {
|
defectReceiverOptions: {
|
||||||
type: Array
|
type: Array
|
||||||
|
@ -211,6 +227,11 @@ export default {
|
||||||
},
|
},
|
||||||
headClass() {
|
headClass() {
|
||||||
return "text-align:center;background:'#ededed'"
|
return "text-align:center;background:'#ededed'"
|
||||||
|
},
|
||||||
|
handleTemplate(index, row) {
|
||||||
|
if (hasLicense()) {
|
||||||
|
this.$refs.noticeTemplate.open(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
border
|
border
|
||||||
:cell-style="rowClass"
|
:cell-style="rowClass"
|
||||||
:header-cell-style="headClass">
|
:header-cell-style="headClass">
|
||||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.event"
|
<el-select v-model="scope.row.event"
|
||||||
:placeholder="$t('organization.message.select_events')"
|
:placeholder="$t('organization.message.select_events')"
|
||||||
|
@ -66,25 +66,33 @@
|
||||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="mini"
|
||||||
|
v-if="scope.row.isSet"
|
||||||
|
v-xpack
|
||||||
|
@click="handleTemplate(scope.$index,scope.row)"
|
||||||
|
>{{ $t('organization.message.template') }}
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
v-show="scope.row.isSet"
|
v-if="scope.row.isSet"
|
||||||
@click="handleAddTask(scope.$index,scope.row)"
|
@click="handleAddTask(scope.$index,scope.row)"
|
||||||
>{{ $t('commons.add') }}
|
>{{ $t('commons.add') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
v-show="scope.row.isSet"
|
v-if="scope.row.isSet"
|
||||||
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
||||||
>{{ $t('commons.cancel') }}
|
>{{ $t('commons.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
v-show="!scope.row.isSet"
|
v-if="!scope.row.isSet"
|
||||||
@click="handleEditTask(scope.$index,scope.row)"
|
@click="handleEditTask(scope.$index,scope.row)"
|
||||||
>{{ $t('commons.edit') }}
|
>{{ $t('commons.edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -100,14 +108,23 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<notice-template v-xpack ref="noticeTemplate"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
const TASK_TYPE = 'JENKINS_TASK';
|
const TASK_TYPE = 'JENKINS_TASK';
|
||||||
|
|
||||||
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
|
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "JenkinsNotification",
|
name: "JenkinsNotification",
|
||||||
|
components: {
|
||||||
|
"NoticeTemplate": noticeTemplate.default
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
jenkinsReceiverOptions: {
|
jenkinsReceiverOptions: {
|
||||||
type: Array
|
type: Array
|
||||||
|
@ -187,7 +204,6 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
data.isReadOnly = true;
|
data.isReadOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
addTask(data) {
|
addTask(data) {
|
||||||
this.result = this.$post("/notice/save/message/task", data, () => {
|
this.result = this.$post("/notice/save/message/task", data, () => {
|
||||||
|
@ -215,6 +231,11 @@ export default {
|
||||||
headClass() {
|
headClass() {
|
||||||
return "text-align:center;background:'#ededed'"
|
return "text-align:center;background:'#ededed'"
|
||||||
},
|
},
|
||||||
|
handleTemplate(index, row) {
|
||||||
|
if (hasLicense()) {
|
||||||
|
this.$refs.noticeTemplate.open(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
:data="scheduleTask"
|
:data="scheduleTask"
|
||||||
class="tb-edit"
|
class="tb-edit"
|
||||||
border
|
border
|
||||||
size="mini"
|
|
||||||
:cell-style="rowClass"
|
:cell-style="rowClass"
|
||||||
:header-cell-style="headClass">
|
:header-cell-style="headClass">
|
||||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
<el-table-column :label="$t('schedule.event')" prop="events" min-width="15%">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.event"
|
<el-select v-model="scope.row.event" size="mini"
|
||||||
:placeholder="$t('organization.message.select_events')"
|
:placeholder="$t('organization.message.select_events')"
|
||||||
prop="events" :disabled="!scope.row.isSet">
|
prop="events" :disabled="!scope.row.isSet">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -33,7 +32,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('schedule.receiver')" prop="userIds" min-width="20%">
|
<el-table-column :label="$t('schedule.receiver')" prop="userIds" min-width="20%">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-select v-model="row.userIds" filterable multiple
|
<el-select v-model="row.userIds" filterable multiple size="mini"
|
||||||
:placeholder="$t('commons.please_select')" style="width: 100%;" :disabled="!row.isSet">
|
:placeholder="$t('commons.please_select')" style="width: 100%;" :disabled="!row.isSet">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in scheduleReceiverOptions"
|
v-for="item in scheduleReceiverOptions"
|
||||||
|
@ -44,9 +43,10 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('schedule.receiving_mode')" min-width="20%" prop="type">
|
<el-table-column :label="$t('schedule.receiving_mode')" prop="type" min-width="15%">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.type" :placeholder="$t('organization.message.select_receiving_method')"
|
<el-select v-model="scope.row.type" :placeholder="$t('organization.message.select_receiving_method')"
|
||||||
|
size="mini"
|
||||||
:disabled="!scope.row.isSet" @change="handleEdit(scope.$index, scope.row)"
|
:disabled="!scope.row.isSet" @change="handleEdit(scope.$index, scope.row)"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -60,12 +60,20 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="webhook" min-width="20%" prop="webhook">
|
<el-table-column label="webhook" min-width="20%" prop="webhook">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-input v-model="scope.row.webhook" placeholder="webhook地址"
|
<el-input v-model="scope.row.webhook" placeholder="webhook地址" size="mini"
|
||||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
<el-table-column :label="$t('commons.operating')" prop="result" min-width="20%">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="mini"
|
||||||
|
v-if="scope.row.isSet"
|
||||||
|
v-xpack
|
||||||
|
@click="handleTemplate(scope.$index,scope.row)"
|
||||||
|
>{{ $t('organization.message.template') }}
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
|
@ -102,13 +110,21 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<notice-template v-xpack ref="noticeTemplate"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
|
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ScheduleTaskNotification",
|
name: "ScheduleTaskNotification",
|
||||||
|
components: {
|
||||||
|
"NoticeTemplate": noticeTemplate.default
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
testId: String,
|
testId: String,
|
||||||
scheduleReceiverOptions: Array,
|
scheduleReceiverOptions: Array,
|
||||||
|
@ -226,6 +242,11 @@ export default {
|
||||||
headClass() {
|
headClass() {
|
||||||
return "text-align:center;background:'#ededed'"
|
return "text-align:center;background:'#ededed'"
|
||||||
},
|
},
|
||||||
|
handleTemplate(index, row) {
|
||||||
|
if (hasLicense()) {
|
||||||
|
this.$refs.noticeTemplate.open(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
:cell-style="rowClass"
|
:cell-style="rowClass"
|
||||||
:header-cell-style="headClass"
|
:header-cell-style="headClass"
|
||||||
>
|
>
|
||||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')"
|
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')"
|
||||||
@change="handleTestPlanReceivers(scope.row)" size="mini"
|
@change="handleTestPlanReceivers(scope.row)" size="mini"
|
||||||
|
@ -64,8 +64,16 @@
|
||||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="mini"
|
||||||
|
v-if="scope.row.isSet"
|
||||||
|
v-xpack
|
||||||
|
@click="handleTemplate(scope.$index,scope.row)"
|
||||||
|
>{{ $t('organization.message.template') }}
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
|
@ -98,15 +106,23 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<notice-template v-xpack ref="noticeTemplate"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
const TASK_TYPE = 'TEST_PLAN_TASK';
|
const TASK_TYPE = 'TEST_PLAN_TASK';
|
||||||
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
|
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestPlanTaskNotification",
|
name: "TestPlanTaskNotification",
|
||||||
|
components: {
|
||||||
|
"NoticeTemplate": noticeTemplate.default
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
testPlanReceiverOptions: {
|
testPlanReceiverOptions: {
|
||||||
type: Array
|
type: Array
|
||||||
|
@ -231,6 +247,11 @@ export default {
|
||||||
}
|
}
|
||||||
row.testPlanReceiverOptions = testPlanReceivers;
|
row.testPlanReceiverOptions = testPlanReceivers;
|
||||||
},
|
},
|
||||||
|
handleTemplate(index, row) {
|
||||||
|
if (hasLicense()) {
|
||||||
|
this.$refs.noticeTemplate.open(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
testPlanReceiverOptions(value) {
|
testPlanReceiverOptions(value) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
:cell-style="rowClass"
|
:cell-style="rowClass"
|
||||||
:header-cell-style="headClass"
|
:header-cell-style="headClass"
|
||||||
>
|
>
|
||||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||||
@change="handleReviewReceivers(scope.row)"
|
@change="handleReviewReceivers(scope.row)"
|
||||||
|
@ -65,8 +65,16 @@
|
||||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="mini"
|
||||||
|
v-if="scope.row.isSet"
|
||||||
|
v-xpack
|
||||||
|
@click="handleTemplate(scope.$index,scope.row)"
|
||||||
|
>{{ $t('organization.message.template') }}
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
|
@ -99,14 +107,22 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<notice-template v-xpack ref="noticeTemplate"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
const TASK_TYPE = 'REVIEW_TASK';
|
const TASK_TYPE = 'REVIEW_TASK';
|
||||||
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
|
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestReviewNotification",
|
name: "TestReviewNotification",
|
||||||
|
components: {
|
||||||
|
"NoticeTemplate": noticeTemplate.default
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
reviewReceiverOptions: {
|
reviewReceiverOptions: {
|
||||||
type: Array
|
type: Array
|
||||||
|
@ -236,6 +252,11 @@ export default {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
row.reviewReceiverOptions = reviewReceiverOptions;
|
row.reviewReceiverOptions = reviewReceiverOptions;
|
||||||
|
},
|
||||||
|
handleTemplate(index, row) {
|
||||||
|
if (hasLicense()) {
|
||||||
|
this.$refs.noticeTemplate.open(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<ms-container>
|
<div v-loading="result.loading">
|
||||||
<ms-main-container>
|
<el-card class="table-card">
|
||||||
<el-card class="table-card" v-loading="result.loading">
|
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||||
:create-tip="btnTips" title=""/>
|
:create-tip="btnTips" :title="$t('commons.project')"/>
|
||||||
</template>
|
</template>
|
||||||
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
||||||
|
@ -47,7 +46,6 @@
|
||||||
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
:total="total"/>
|
:total="total"/>
|
||||||
</el-card>
|
</el-card>
|
||||||
</ms-main-container>
|
|
||||||
|
|
||||||
<el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose">
|
<el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose">
|
||||||
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
||||||
|
@ -80,23 +78,23 @@
|
||||||
|
|
||||||
<api-environment-config ref="environmentConfig"/>
|
<api-environment-config ref="environmentConfig"/>
|
||||||
|
|
||||||
</ms-container>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsCreateBox from "../settings/CreateBox";
|
import MsCreateBox from "../CreateBox";
|
||||||
import {Message} from "element-ui";
|
import {Message} from "element-ui";
|
||||||
import MsTablePagination from "../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
import MsTableOperator from "../common/components/MsTableOperator";
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
import MsDialogFooter from "../common/components/MsDialogFooter";
|
import MsDialogFooter from "../../common/components/MsDialogFooter";
|
||||||
import {_sort, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
import {_sort, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||||
import MsContainer from "../common/components/MsContainer";
|
import MsContainer from "../../common/components/MsContainer";
|
||||||
import MsMainContainer from "../common/components/MsMainContainer";
|
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||||
import MsDeleteConfirm from "../common/components/MsDeleteConfirm";
|
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
|
||||||
import MsTableOperatorButton from "../common/components/MsTableOperatorButton";
|
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
|
||||||
import ApiEnvironmentConfig from "../api/test/components/ApiEnvironmentConfig";
|
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
|
||||||
import TemplateComponent from "../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||||
import {ApiEvent, LIST_CHANGE, PerformanceEvent, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {ApiEvent, LIST_CHANGE, PerformanceEvent, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -144,7 +142,7 @@ export default {
|
||||||
if (this.$route.path.split('/')[2] === 'project' &&
|
if (this.$route.path.split('/')[2] === 'project' &&
|
||||||
this.$route.path.split('/')[3] === 'create') {
|
this.$route.path.split('/')[3] === 'create') {
|
||||||
this.create();
|
this.create();
|
||||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
// this.$router.push('/setting/project');
|
||||||
}
|
}
|
||||||
this.list();
|
this.list();
|
||||||
},
|
},
|
||||||
|
@ -156,7 +154,7 @@ export default {
|
||||||
if (this.$route.path.split('/')[2] === 'project' &&
|
if (this.$route.path.split('/')[2] === 'project' &&
|
||||||
to.path.split('/')[3] === 'create') {
|
to.path.split('/')[3] === 'create') {
|
||||||
this.create();
|
this.create();
|
||||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
// this.$router.push('/setting/project');
|
||||||
} else if (this.$route.path.split('/')[2] === 'project' &&
|
} else if (this.$route.path.split('/')[2] === 'project' &&
|
||||||
to.path.split('/')[3] === 'all') {
|
to.path.split('/')[3] === 'all') {
|
||||||
this.list();
|
this.list();
|
|
@ -9,7 +9,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsProject from "@/business/components/project/MsProject";
|
import MsProject from "@/business/components/settings/project/MsProject";
|
||||||
export default {
|
export default {
|
||||||
name: "Project",
|
name: "Project",
|
||||||
components: {MsProject},
|
components: {MsProject},
|
||||||
|
|
|
@ -80,9 +80,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'project',
|
path: 'project/:type',
|
||||||
component: () => import('@/business/components/settings/project/Project'),
|
component: () => import('@/business/components/settings/project/MsProject'),
|
||||||
meta: {project: true, title: '项目管理'}
|
meta: {project: true, title: 'project.manager'}
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<el-menu-item :index="'/performance/project/create'">
|
<el-menu-item :index="'/setting/project/create'">
|
||||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
<span style="padding-left: 7px;">创建项目</span>
|
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<ms-show-all :index="'/setting/project'"/>
|
<ms-show-all :index="'/setting/project/all'"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-menu-item :index="'/track/home'">
|
<el-menu-item :index="'/track/home'">
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<related-test-plan-list ref="relatedTestPlanList"/>
|
<related-test-plan-list ref="relatedTestPlanList"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<review-list :title="$t('review.my_review')" ref="caseReviewList"/>
|
<review-list :title="$t('test_track.review.my_review')" ref="caseReviewList"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="9">
|
<el-col :span="9">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import MsProject from "@/business/components/project/MsProject";
|
import MsProject from "@/business/components/settings/project/MsProject";
|
||||||
|
|
||||||
const TestTrack = () => import('@/business/components/track/TestTrack')
|
const TestTrack = () => import('@/business/components/track/TestTrack')
|
||||||
const TrackHome = () => import('@/business/components/track/home/TrackHome')
|
const TrackHome = () => import('@/business/components/track/home/TrackHome')
|
||||||
|
@ -51,11 +51,11 @@ export default {
|
||||||
name: "planViewEdit",
|
name: "planViewEdit",
|
||||||
component: TestPlanView
|
component: TestPlanView
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: "project/:type",
|
// path: "project/:type",
|
||||||
name: "trackProject",
|
// name: "trackProject",
|
||||||
component: MsProject
|
// component: MsProject
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: "review/:type",
|
path: "review/:type",
|
||||||
name: "testCaseReview",
|
name: "testCaseReview",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a22a3005d9bd254793fcf634d72539cbdf31be3a
|
Subproject commit 29a8fc09602fde5708af06582ac972d98eb69836
|
|
@ -244,7 +244,8 @@ export default {
|
||||||
'3. When selecting the receiver, it must be the person included in the group you created. The mobile phone number of the receiver is required and it is the mobile phone number used by the nailing enterprise,',
|
'3. When selecting the receiver, it must be the person included in the group you created. The mobile phone number of the receiver is required and it is the mobile phone number used by the nailing enterprise,',
|
||||||
message: 'Event, receiver and receiving method are required\n' +
|
message: 'Event, receiver and receiving method are required\n' +
|
||||||
'\n',
|
'\n',
|
||||||
message_webhook: 'Webhook is required when the receiving mode is nail or enterprise robot'
|
message_webhook: 'Webhook is required when the receiving mode is nail or enterprise robot',
|
||||||
|
template: "Template"
|
||||||
},
|
},
|
||||||
integration: {
|
integration: {
|
||||||
select_defect_platform: 'Please select the defect management platform to be integrated:',
|
select_defect_platform: 'Please select the defect management platform to be integrated:',
|
||||||
|
@ -294,6 +295,7 @@ export default {
|
||||||
tapd_id: 'TAPD Project ID',
|
tapd_id: 'TAPD Project ID',
|
||||||
jira_key: 'JIRA Project key',
|
jira_key: 'JIRA Project key',
|
||||||
zentao_id: 'Zentao Project ID',
|
zentao_id: 'Zentao Project ID',
|
||||||
|
manager: 'Manager',
|
||||||
},
|
},
|
||||||
member: {
|
member: {
|
||||||
create: 'Create',
|
create: 'Create',
|
||||||
|
|
|
@ -242,9 +242,8 @@ export default {
|
||||||
' 2.机器人选择为群机器人,安全验证选择“自定义关键词” :"任务通知";\n' +
|
' 2.机器人选择为群机器人,安全验证选择“自定义关键词” :"任务通知";\n' +
|
||||||
' 3.选择接收人时必须是你所建的群里包含的人,接收人手机号为必填项且为钉钉企业所使用的手机号,',
|
' 3.选择接收人时必须是你所建的群里包含的人,接收人手机号为必填项且为钉钉企业所使用的手机号,',
|
||||||
message: '事件,接收人,接收方式为必填项',
|
message: '事件,接收人,接收方式为必填项',
|
||||||
message_webhook: '接收方式为钉钉和企业机器人时,webhook为必填项'
|
message_webhook: '接收方式为钉钉和企业机器人时,webhook为必填项',
|
||||||
|
template: "模版"
|
||||||
|
|
||||||
},
|
},
|
||||||
integration: {
|
integration: {
|
||||||
select_defect_platform: '请选择要集成的缺陷管理平台:',
|
select_defect_platform: '请选择要集成的缺陷管理平台:',
|
||||||
|
@ -293,6 +292,7 @@ export default {
|
||||||
tapd_id: 'TAPD项目ID',
|
tapd_id: 'TAPD项目ID',
|
||||||
jira_key: 'JIRA项目key',
|
jira_key: 'JIRA项目key',
|
||||||
zentao_id: 'Zentao项目ID',
|
zentao_id: 'Zentao项目ID',
|
||||||
|
manager: '项目管理',
|
||||||
},
|
},
|
||||||
member: {
|
member: {
|
||||||
create: '添加成员',
|
create: '添加成员',
|
||||||
|
@ -562,6 +562,10 @@ export default {
|
||||||
execute: "执行",
|
execute: "执行",
|
||||||
copy: "复制",
|
copy: "复制",
|
||||||
remove: "删除",
|
remove: "删除",
|
||||||
|
view_ref: "查看引用",
|
||||||
|
case_ref: "用例引用",
|
||||||
|
scenario_ref: "场景引用",
|
||||||
|
plan_ref: "测试计划引用",
|
||||||
batch_add_plan: "批量添加到测试计划",
|
batch_add_plan: "批量添加到测试计划",
|
||||||
batch_execute: "批量执行",
|
batch_execute: "批量执行",
|
||||||
scenario: {
|
scenario: {
|
||||||
|
|
|
@ -242,9 +242,8 @@ export default {
|
||||||
' 2.接收方式除郵件外webhook為必填;\n' +
|
' 2.接收方式除郵件外webhook為必填;\n' +
|
||||||
' 3.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知"',
|
' 3.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知"',
|
||||||
message: '事件,接收人,接收方式為必填項',
|
message: '事件,接收人,接收方式為必填項',
|
||||||
message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項'
|
message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項',
|
||||||
|
template: "模版"
|
||||||
|
|
||||||
},
|
},
|
||||||
integration: {
|
integration: {
|
||||||
select_defect_platform: '請選擇要集成的缺陷管理平臺:',
|
select_defect_platform: '請選擇要集成的缺陷管理平臺:',
|
||||||
|
@ -293,6 +292,7 @@ export default {
|
||||||
tapd_id: 'TAPD項目ID',
|
tapd_id: 'TAPD項目ID',
|
||||||
jira_key: 'JIRA項目key',
|
jira_key: 'JIRA項目key',
|
||||||
zentao_id: 'Zentao項目ID',
|
zentao_id: 'Zentao項目ID',
|
||||||
|
manager: '項目管理',
|
||||||
},
|
},
|
||||||
member: {
|
member: {
|
||||||
create: '添加成員',
|
create: '添加成員',
|
||||||
|
|
Loading…
Reference in New Issue