feat(接口自动化): 冲突合并
This commit is contained in:
commit
3e15d419fb
|
@ -263,13 +263,20 @@
|
|||
<artifactId>spring-boot-starter-data-ldap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger 解析 -->
|
||||
<!-- swagger2 解析 -->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-parser</artifactId>
|
||||
<version>1.0.51</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger3 解析 -->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>io.swagger.parser.v3</groupId>-->
|
||||
<!--<artifactId>swagger-parser</artifactId>-->
|
||||
<!--<version>2.0.24</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!-- 执行 js 代码依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.sdk</groupId>
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
|
@ -92,5 +93,10 @@ public class ApiAutomationController {
|
|||
apiAutomationService.run(request);
|
||||
}
|
||||
|
||||
@PostMapping("/getReference")
|
||||
public List<ApiScenario> getReference(@RequestBody ApiScenarioRequest request) {
|
||||
return apiAutomationService.getReference(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
@ -329,4 +330,8 @@ public class ApiAutomationService {
|
|||
createAPIReportResult(request.getId(), ReportTriggerMode.MANUAL.name());
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
public List<ApiScenario> getReference(ApiScenarioRequest request) {
|
||||
return extApiScenarioMapper.selectReference(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class MessageTask implements Serializable {
|
||||
private String id;
|
||||
|
@ -27,5 +28,7 @@ public class MessageTask implements Serializable {
|
|||
|
||||
private Long createTime;
|
||||
|
||||
private String template;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
</delete>
|
||||
|
||||
<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 id="selectResponseTimeByUrl" parameterType="java.lang.String"
|
||||
|
@ -56,7 +56,7 @@
|
|||
</select>
|
||||
|
||||
<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>
|
||||
|
||||
<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.MessageTaskExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MessageTaskMapper {
|
||||
long countByExample(MessageTaskExample example);
|
||||
|
||||
|
@ -16,15 +17,21 @@ public interface MessageTaskMapper {
|
|||
|
||||
int insertSelective(MessageTask record);
|
||||
|
||||
List<MessageTask> selectByExampleWithBLOBs(MessageTaskExample example);
|
||||
|
||||
List<MessageTask> selectByExample(MessageTaskExample example);
|
||||
|
||||
MessageTask selectByPrimaryKey(String id);
|
||||
|
||||
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 updateByPrimaryKeySelective(MessageTask record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(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">
|
||||
<mapper namespace="io.metersphere.base.mapper.MessageTaskMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.MessageTask">
|
||||
<id column="id" jdbcType="VARCHAR" property="id"/>
|
||||
<result column="type" jdbcType="VARCHAR" property="type"/>
|
||||
<result column="event" jdbcType="VARCHAR" property="event"/>
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId"/>
|
||||
<result column="task_type" jdbcType="VARCHAR" property="taskType"/>
|
||||
<result column="webhook" jdbcType="VARCHAR" property="webhook"/>
|
||||
<result column="identification" jdbcType="VARCHAR" property="identification"/>
|
||||
<result column="is_set" jdbcType="BIT" property="isSet"/>
|
||||
<result column="organization_id" jdbcType="VARCHAR" property="organizationId"/>
|
||||
<result column="test_id" jdbcType="VARCHAR" property="testId"/>
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime"/>
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||
<result column="event" jdbcType="VARCHAR" property="event" />
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId" />
|
||||
<result column="task_type" jdbcType="VARCHAR" property="taskType" />
|
||||
<result column="webhook" jdbcType="VARCHAR" property="webhook" />
|
||||
<result column="identification" jdbcType="VARCHAR" property="identification" />
|
||||
<result column="is_set" jdbcType="BIT" property="isSet" />
|
||||
<result column="organization_id" jdbcType="VARCHAR" property="organizationId" />
|
||||
<result column="test_id" jdbcType="VARCHAR" property="testId" />
|
||||
<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>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -25,13 +28,13 @@
|
|||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
AND ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
AND ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
|
@ -76,6 +79,25 @@
|
|||
id, `type`, event, user_id, task_type, webhook, identification, is_set, organization_id,
|
||||
test_id, create_time
|
||||
</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
|
||||
<if test="distinct">
|
||||
|
@ -90,9 +112,11 @@
|
|||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from message_task
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
@ -107,14 +131,16 @@
|
|||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
insert into message_task (id, `type`, event,
|
||||
user_id, task_type, webhook,
|
||||
identification, is_set, organization_id,
|
||||
test_id, create_time)
|
||||
values (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR},
|
||||
#{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR},
|
||||
#{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR},
|
||||
#{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT})
|
||||
INSERT INTO message_task (id, `type`, event,
|
||||
user_id, task_type, webhook,
|
||||
identification, is_set, organization_id,
|
||||
test_id, create_time, `template`
|
||||
)
|
||||
VALUES (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR},
|
||||
#{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR},
|
||||
#{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR},
|
||||
#{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{template,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
insert into message_task
|
||||
|
@ -152,6 +178,9 @@
|
|||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="template != null">
|
||||
`template`,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -187,6 +216,9 @@
|
|||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="template != null">
|
||||
#{template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultType="java.lang.Long">
|
||||
|
@ -231,24 +263,45 @@
|
|||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.template != null">
|
||||
`template` = #{record.template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</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 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}
|
||||
`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}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -286,21 +339,39 @@
|
|||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="template != null">
|
||||
`template` = #{template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</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 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}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
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}
|
||||
WHERE id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -14,4 +14,6 @@ public interface ExtApiScenarioMapper {
|
|||
|
||||
List<ApiScenario> selectIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<ApiScenario> selectReference(@Param("request") ApiScenarioRequest request);
|
||||
|
||||
}
|
||||
|
|
|
@ -71,4 +71,23 @@
|
|||
#{v}
|
||||
</foreach>
|
||||
</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>
|
|
@ -17,4 +17,5 @@ public class MessageDetail {
|
|||
private Boolean isSet;
|
||||
private String testId;
|
||||
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.UserDetail;
|
||||
import io.metersphere.service.UserService;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -14,6 +16,7 @@ import java.net.URL;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class AbstractNoticeSender implements NoticeSender {
|
||||
|
@ -21,13 +24,16 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
|||
private UserService userService;
|
||||
|
||||
protected String getContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||
// 如果配置了模版就直接使用模版
|
||||
if (StringUtils.isNotBlank(messageDetail.getTemplate())) {
|
||||
return getContent(messageDetail.getTemplate(), noticeModel.getParamMap());
|
||||
}
|
||||
// 处理 userIds 中包含的特殊值
|
||||
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
||||
messageDetail.setUserIds(realUserIds);
|
||||
|
||||
// 处理 WeCom Ding context
|
||||
String context = "";
|
||||
String status = noticeModel.getStatus();
|
||||
switch (messageDetail.getEvent()) {
|
||||
case NoticeConstants.Event.CREATE:
|
||||
case NoticeConstants.Event.UPDATE:
|
||||
|
@ -48,6 +54,10 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
|||
}
|
||||
|
||||
protected String getHtmlContext(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||
// 如果配置了模版就直接使用模版
|
||||
if (StringUtils.isNotBlank(messageDetail.getTemplate())) {
|
||||
return getContent(messageDetail.getTemplate(), noticeModel.getParamMap());
|
||||
}
|
||||
// 处理 userIds 中包含的特殊值
|
||||
List<String> realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent());
|
||||
messageDetail.setUserIds(realUserIds);
|
||||
|
@ -77,7 +87,20 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
|||
} catch (IOException 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) {
|
||||
|
|
|
@ -5,8 +5,6 @@ import io.metersphere.notice.domain.MessageDetail;
|
|||
import io.metersphere.notice.sender.AbstractNoticeSender;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
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.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -15,14 +13,13 @@ import javax.annotation.Resource;
|
|||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class MailNoticeSender extends AbstractNoticeSender {
|
||||
@Resource
|
||||
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();
|
||||
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||
|
@ -31,25 +28,11 @@ public class MailNoticeSender extends AbstractNoticeSender {
|
|||
List<String> emails = super.getUserEmails(messageDetail.getUserIds());
|
||||
String[] users = emails.toArray(new String[0]);
|
||||
LogUtil.info("收件人地址: " + emails);
|
||||
helper.setText(this.getContent(template, noticeModel.getParamMap()), true);
|
||||
helper.setText(context, true);
|
||||
helper.setTo(users);
|
||||
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
|
||||
public void send(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||
String context = super.getHtmlContext(messageDetail, noticeModel);
|
||||
|
|
|
@ -2,7 +2,6 @@ package io.metersphere.notice.service;
|
|||
|
||||
import com.alibaba.nacos.client.utils.StringUtils;
|
||||
import io.metersphere.commons.constants.NoticeConstants;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.notice.domain.MessageDetail;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
import io.metersphere.notice.sender.NoticeSender;
|
||||
|
@ -22,10 +21,8 @@ public class NoticeSendService {
|
|||
private WeComNoticeSender weComNoticeSender;
|
||||
@Resource
|
||||
private DingNoticeSender dingNoticeSender;
|
||||
|
||||
private void event(String event) {
|
||||
|
||||
}
|
||||
@Resource
|
||||
private NoticeService noticeService;
|
||||
|
||||
private NoticeSender getNoticeSender(MessageDetail messageDetail) {
|
||||
NoticeSender noticeSender = null;
|
||||
|
@ -47,8 +44,6 @@ public class NoticeSendService {
|
|||
}
|
||||
|
||||
public void send(String taskType, NoticeModel noticeModel) {
|
||||
NoticeService noticeService = CommonBeanFactory.getBean(NoticeService.class);
|
||||
assert noticeService != null;
|
||||
List<MessageDetail> messageDetails;
|
||||
switch (taskType) {
|
||||
case NoticeConstants.Mode.API:
|
||||
|
|
|
@ -33,14 +33,17 @@ public class NoticeService {
|
|||
SessionUser user = SessionUtils.getUser();
|
||||
String orgId = user.getLastOrganizationId();
|
||||
long time = System.currentTimeMillis();
|
||||
String identification = UUID.randomUUID().toString();
|
||||
messageDetail.getUserIds().forEach(m -> {
|
||||
checkUserIdExist(m, messageDetail, orgId);
|
||||
String identification = messageDetail.getIdentification();
|
||||
if (StringUtils.isBlank(identification)) {
|
||||
identification = UUID.randomUUID().toString();
|
||||
}
|
||||
for (String userId : messageDetail.getUserIds()) {
|
||||
checkUserIdExist(userId, messageDetail, orgId);
|
||||
MessageTask messageTask = new MessageTask();
|
||||
messageTask.setId(UUID.randomUUID().toString());
|
||||
messageTask.setEvent(messageDetail.getEvent());
|
||||
messageTask.setTaskType(messageDetail.getTaskType());
|
||||
messageTask.setUserId(m);
|
||||
messageTask.setUserId(userId);
|
||||
messageTask.setType(messageDetail.getType());
|
||||
messageTask.setWebhook(messageDetail.getWebhook());
|
||||
messageTask.setIdentification(identification);
|
||||
|
@ -48,8 +51,15 @@ public class NoticeService {
|
|||
messageTask.setOrganizationId(orgId);
|
||||
messageTask.setTestId(messageDetail.getTestId());
|
||||
messageTask.setCreateTime(time);
|
||||
setTemplate(messageDetail, 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) {
|
||||
|
@ -80,7 +90,7 @@ public class NoticeService {
|
|||
public List<MessageDetail> searchMessageByTestId(String testId) {
|
||||
MessageTaskExample example = new MessageTaskExample();
|
||||
example.createCriteria().andTestIdEqualTo(testId);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||
List<MessageDetail> scheduleMessageTask = new ArrayList<>();
|
||||
Map<String, List<MessageTask>> MessageTaskMap = messageTaskLists.stream().collect(Collectors.groupingBy(MessageTask::getIdentification));
|
||||
MessageTaskMap.forEach((k, v) -> {
|
||||
|
@ -100,7 +110,7 @@ public class NoticeService {
|
|||
example.createCriteria()
|
||||
.andTaskTypeEqualTo(type)
|
||||
.andOrganizationIdEqualTo(orgId);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||
|
||||
Map<String, List<MessageTask>> messageTaskMap = messageTaskLists.stream()
|
||||
.collect(Collectors.groupingBy(NoticeService::fetchGroupKey));
|
||||
|
@ -130,6 +140,7 @@ public class NoticeService {
|
|||
messageDetail.setType(m.getType());
|
||||
messageDetail.setIsSet(m.getIsSet());
|
||||
messageDetail.setCreateTime(m.getCreateTime());
|
||||
messageDetail.setTemplate(m.getTemplate());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(userIds)) {
|
||||
messageDetail.setUserIds(new ArrayList<>(userIds));
|
||||
|
|
|
@ -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;
|
|
@ -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>
|
|
@ -358,7 +358,7 @@
|
|||
let bodyUploadFiles = [];
|
||||
row.bodyUploadIds = [];
|
||||
let request = row.request;
|
||||
if (request.body) {
|
||||
if (request.body && request.body.kvs) {
|
||||
request.body.kvs.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
|
@ -372,19 +372,21 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
request.body.binary.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
row.bodyUploadIds.push(fileId);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (request.body.binary) {
|
||||
request.body.binary.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
row.bodyUploadIds.push(fileId);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return bodyUploadFiles;
|
||||
},
|
||||
|
|
|
@ -58,25 +58,10 @@
|
|||
getBodyUploadFiles(obj) {
|
||||
let bodyUploadFiles = [];
|
||||
obj.bodyUploadIds = [];
|
||||
this.runData.forEach(request => {
|
||||
if (request.body) {
|
||||
request.body.kvs.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
if (!item.id) {
|
||||
let fileId = getUUID().substring(0, 12);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
}
|
||||
obj.bodyUploadIds.push(item.id);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (request.body.binary) {
|
||||
request.body.binary.forEach(param => {
|
||||
if (this.runData) {
|
||||
this.runData.forEach(request => {
|
||||
if (request.body) {
|
||||
request.body.kvs.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
|
@ -91,9 +76,26 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
if (request.body.binary) {
|
||||
request.body.binary.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
if (!item.id) {
|
||||
let fileId = getUUID().substring(0, 12);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
}
|
||||
obj.bodyUploadIds.push(item.id);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return bodyUploadFiles;
|
||||
},
|
||||
run() {
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<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']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/api/home'">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<common-monitor-chart>
|
||||
<template>
|
||||
<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>
|
||||
</template>
|
||||
</common-monitor-chart>
|
||||
|
@ -27,20 +27,15 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
click(params) {
|
||||
//如果状态不是以2开头
|
||||
if (params.value.substr(0, 1) !== '2') {
|
||||
let startTime = params.name;
|
||||
this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, {
|
||||
'apiUrl': this.apiUrl
|
||||
}, response => {
|
||||
this.reportId = response.data;
|
||||
let reportId = this.reportId
|
||||
let url = '#/api/report/view/' + reportId;
|
||||
let target = '_blank';
|
||||
window.open(url, target);
|
||||
});
|
||||
}
|
||||
|
||||
let startTime = params.name;
|
||||
this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, {
|
||||
'apiUrl': this.apiUrl
|
||||
}, response => {
|
||||
this.reportId = response.data;
|
||||
let reportId = this.reportId
|
||||
let url = '#/api/report/view/' + reportId;
|
||||
window.open(url, '_blank');
|
||||
});
|
||||
},
|
||||
getOptions() {
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import MsProject from "@/business/components/project/MsProject";
|
||||
import MsProject from "@/business/components/settings/project/MsProject";
|
||||
|
||||
export default {
|
||||
path: "/api",
|
||||
|
@ -24,11 +24,11 @@ export default {
|
|||
name: "ApiTestList",
|
||||
component: () => import('@/business/components/api/test/ApiTestList'),
|
||||
},
|
||||
{
|
||||
path: "project/:type",
|
||||
name: "fucProject",
|
||||
component: MsProject,
|
||||
},
|
||||
// {
|
||||
// path: "project/:type",
|
||||
// name: "fucProject",
|
||||
// component: MsProject,
|
||||
// },
|
||||
{
|
||||
path: "report/list/:testId",
|
||||
name: "ApiReportList",
|
||||
|
@ -53,6 +53,11 @@ export default {
|
|||
path: "automation/report",
|
||||
name: "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;
|
||||
}
|
||||
|
||||
/deep/ .el-select__tags {
|
||||
flex-wrap: unset;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -32,7 +32,7 @@ export default {
|
|||
options: Object
|
||||
},
|
||||
mounted() {
|
||||
this.recent();
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -44,7 +44,7 @@ export default {
|
|||
watch: {
|
||||
search_text(val) {
|
||||
if (!val) {
|
||||
this.recent();
|
||||
this.init();
|
||||
} else {
|
||||
this.search();
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
recent: function () {
|
||||
init: function () {
|
||||
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
this.result = this.$get(this.options.url, (response) => {
|
||||
this.items = response.data;
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/performance/project/create'">
|
||||
<el-menu-item :index="'/setting/project/create'">
|
||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/performance/home'">
|
||||
|
|
|
@ -241,14 +241,9 @@ export default {
|
|||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.result = this.$post('/performance/report/batch/delete', {ids: ids}, () => {
|
||||
this.selectRows.clear();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.search();
|
||||
// 发送广播,刷新 head 上的最新列表
|
||||
PerformanceEvent.$emit(LIST_CHANGE);
|
||||
});
|
||||
this.selectRows.forEach(row => {
|
||||
this._handleDelete(row);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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 PerformanceTestHome = () => import('@/business/components/performance/home/PerformanceTestHome')
|
||||
|
@ -43,11 +43,11 @@ export default {
|
|||
name: "perPlan",
|
||||
component: PerformanceTestList
|
||||
},
|
||||
{
|
||||
path: "project/:type",
|
||||
name: "perProject",
|
||||
component: MsProject
|
||||
},
|
||||
// {
|
||||
// path: "project/:type",
|
||||
// name: "perProject",
|
||||
// component: MsProject
|
||||
// },
|
||||
{
|
||||
path: "report/:type",
|
||||
name: "perReport",
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</el-menu-item>
|
||||
</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">
|
||||
<template v-slot:title>
|
||||
<font-awesome-icon class="icon" :icon="['fa', 'bars']" size="lg"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
: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">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||
prop="event" :disabled="!scope.row.isSet">
|
||||
|
@ -64,8 +64,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</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">
|
||||
<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
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -98,14 +106,22 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
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 {
|
||||
name: "DefectTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
defectReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -211,6 +227,11 @@ export default {
|
|||
},
|
||||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,22 +11,22 @@
|
|||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
:data="jenkinsTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
:data="jenkinsTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event"
|
||||
:placeholder="$t('organization.message.select_events')"
|
||||
size="mini"
|
||||
prop="events" :disabled="!scope.row.isSet">
|
||||
<el-option
|
||||
v-for="item in jenkinsEventOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
v-for="item in jenkinsEventOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -36,10 +36,10 @@
|
|||
<el-select v-model="row.userIds" filterable multiple size="mini"
|
||||
:placeholder="$t('commons.please_select')" style="width: 100%;" :disabled="!row.isSet">
|
||||
<el-option
|
||||
v-for="item in jenkinsReceiverOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
v-for="item in jenkinsReceiverOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -51,10 +51,10 @@
|
|||
:disabled="!scope.row.isSet" @change="handleEdit(scope.$index, scope.row)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in receiveTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
v-for="item in receiveTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -66,48 +66,65 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</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">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-show="scope.row.isSet"
|
||||
@click="handleAddTask(scope.$index,scope.row)"
|
||||
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
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
@click="handleAddTask(scope.$index,scope.row)"
|
||||
>{{ $t('commons.add') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
v-show="scope.row.isSet"
|
||||
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
||||
>{{ $t('commons.cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click="handleEditTask(scope.$index,scope.row)"
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="!scope.row.isSet"
|
||||
@click="handleEditTask(scope.$index,scope.row)"
|
||||
>{{ $t('commons.edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click.native.prevent="deleteRowTask(scope.$index,scope.row)"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click.native.prevent="deleteRowTask(scope.$index,scope.row)"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
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 {
|
||||
name: "JenkinsNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
jenkinsReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -187,7 +204,6 @@ export default {
|
|||
} else {
|
||||
data.isReadOnly = true;
|
||||
}
|
||||
|
||||
},
|
||||
addTask(data) {
|
||||
this.result = this.$post("/notice/save/message/task", data, () => {
|
||||
|
@ -215,6 +231,11 @@ export default {
|
|||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
:data="scheduleTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
size="mini"
|
||||
:cell-style="rowClass"
|
||||
: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">
|
||||
<el-select v-model="scope.row.event"
|
||||
<el-select v-model="scope.row.event" size="mini"
|
||||
:placeholder="$t('organization.message.select_events')"
|
||||
prop="events" :disabled="!scope.row.isSet">
|
||||
<el-option
|
||||
|
@ -33,7 +32,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column :label="$t('schedule.receiver')" prop="userIds" min-width="20%">
|
||||
<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">
|
||||
<el-option
|
||||
v-for="item in scheduleReceiverOptions"
|
||||
|
@ -44,9 +43,10 @@
|
|||
</el-select>
|
||||
</template>
|
||||
</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">
|
||||
<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)"
|
||||
>
|
||||
<el-option
|
||||
|
@ -60,12 +60,20 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="webhook" min-width="20%" prop="webhook">
|
||||
<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>
|
||||
</template>
|
||||
</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">
|
||||
<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
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -102,13 +110,21 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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 {
|
||||
name: "ScheduleTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
testId: String,
|
||||
scheduleReceiverOptions: Array,
|
||||
|
@ -226,6 +242,11 @@ export default {
|
|||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
: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">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')"
|
||||
@change="handleTestPlanReceivers(scope.row)" size="mini"
|
||||
|
@ -64,8 +64,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</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">
|
||||
<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
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -98,15 +106,23 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
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 {
|
||||
name: "TestPlanTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
testPlanReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -231,6 +247,11 @@ export default {
|
|||
}
|
||||
row.testPlanReceiverOptions = testPlanReceivers;
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
testPlanReceiverOptions(value) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
: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">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||
@change="handleReviewReceivers(scope.row)"
|
||||
|
@ -65,8 +65,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</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">
|
||||
<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
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -99,14 +107,22 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
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 {
|
||||
name: "TestReviewNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
reviewReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -236,6 +252,11 @@ export default {
|
|||
break;
|
||||
}
|
||||
row.reviewReceiverOptions = reviewReceiverOptions;
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -1,53 +1,51 @@
|
|||
<template>
|
||||
<ms-container>
|
||||
<ms-main-container>
|
||||
<el-card class="table-card" v-loading="result.loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||
:create-tip="btnTips" title=""/>
|
||||
</template>
|
||||
<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="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<pre>{{ scope.row.description }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
||||
@deleteClick="handleDelete(scope.row)">
|
||||
<template v-slot:behind>
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||
</template>
|
||||
</ms-table-operator>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</el-card>
|
||||
</ms-main-container>
|
||||
<div v-loading="result.loading">
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||
:create-tip="btnTips" :title="$t('commons.project')"/>
|
||||
</template>
|
||||
<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="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<pre>{{ scope.row.description }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
||||
@deleteClick="handleDelete(scope.row)">
|
||||
<template v-slot:behind>
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||
</template>
|
||||
</ms-table-operator>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</el-card>
|
||||
|
||||
<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">
|
||||
|
@ -80,23 +78,23 @@
|
|||
|
||||
<api-environment-config ref="environmentConfig"/>
|
||||
|
||||
</ms-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCreateBox from "../settings/CreateBox";
|
||||
import MsCreateBox from "../CreateBox";
|
||||
import {Message} from "element-ui";
|
||||
import MsTablePagination from "../common/pagination/TablePagination";
|
||||
import MsTableHeader from "../common/components/MsTableHeader";
|
||||
import MsTableOperator from "../common/components/MsTableOperator";
|
||||
import MsDialogFooter from "../common/components/MsDialogFooter";
|
||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||
import MsDialogFooter from "../../common/components/MsDialogFooter";
|
||||
import {_sort, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import MsContainer from "../common/components/MsContainer";
|
||||
import MsMainContainer from "../common/components/MsMainContainer";
|
||||
import MsDeleteConfirm from "../common/components/MsDeleteConfirm";
|
||||
import MsTableOperatorButton from "../common/components/MsTableOperatorButton";
|
||||
import ApiEnvironmentConfig from "../api/test/components/ApiEnvironmentConfig";
|
||||
import TemplateComponent from "../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
|
||||
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
|
||||
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
|
||||
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||
import {ApiEvent, LIST_CHANGE, PerformanceEvent, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||
|
||||
export default {
|
||||
|
@ -144,7 +142,7 @@ export default {
|
|||
if (this.$route.path.split('/')[2] === 'project' &&
|
||||
this.$route.path.split('/')[3] === 'create') {
|
||||
this.create();
|
||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
||||
// this.$router.push('/setting/project');
|
||||
}
|
||||
this.list();
|
||||
},
|
||||
|
@ -156,7 +154,7 @@ export default {
|
|||
if (this.$route.path.split('/')[2] === 'project' &&
|
||||
to.path.split('/')[3] === 'create') {
|
||||
this.create();
|
||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
||||
// this.$router.push('/setting/project');
|
||||
} else if (this.$route.path.split('/')[2] === 'project' &&
|
||||
to.path.split('/')[3] === 'all') {
|
||||
this.list();
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsProject from "@/business/components/project/MsProject";
|
||||
import MsProject from "@/business/components/settings/project/MsProject";
|
||||
export default {
|
||||
name: "Project",
|
||||
components: {MsProject},
|
||||
|
|
|
@ -80,9 +80,9 @@ export default {
|
|||
}
|
||||
},
|
||||
{
|
||||
path: 'project',
|
||||
component: () => import('@/business/components/settings/project/Project'),
|
||||
meta: {project: true, title: '项目管理'}
|
||||
path: 'project/:type',
|
||||
component: () => import('@/business/components/settings/project/MsProject'),
|
||||
meta: {project: true, title: 'project.manager'}
|
||||
},
|
||||
|
||||
]
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
|
||||
<script>
|
||||
import NodeEdit from "./NodeEdit";
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER} from "../../../../common/js/constants";
|
||||
import {checkoutTestManagerOrTestUser, hasRoles} from "../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<span class="menu-title">{{'[' + title + ']'}}</span>
|
||||
<el-select filterable slot="prepend" v-model="value" @change="changeData" class="project_menu"
|
||||
<el-select filterable slot="prepend" v-model="value" @change="changeData" :style="{width: width}"
|
||||
size="small">
|
||||
<el-option v-for="(item,index) in data" :key="index" :label="item.name" :value="index"/>
|
||||
</el-select>
|
||||
|
@ -20,6 +20,12 @@
|
|||
},
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default() {
|
||||
return "214px";
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -43,9 +49,6 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.project_menu {
|
||||
width: 214px;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
color: darkgrey;
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/performance/project/create'">
|
||||
<el-menu-item :index="'/setting/project/create'">
|
||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/track/home'">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<related-test-plan-list ref="relatedTestPlanList"/>
|
||||
</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-col>
|
||||
<el-col :span="9">
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
<script>
|
||||
|
||||
import NodeTree from "../../common/NodeTree";
|
||||
import TestPlanTestCaseList from "./comonents/TestPlanTestCaseList";
|
||||
import TestCaseRelevance from "./comonents/TestCaseRelevance";
|
||||
import TestPlanTestCaseList from "./comonents/functional/FunctionalTestCaseList";
|
||||
import TestCaseRelevance from "./comonents/functional/TestCaseFunctionalRelevance";
|
||||
import SelectMenu from "../../common/SelectMenu";
|
||||
import MsContainer from "../../../common/components/MsContainer";
|
||||
import MsAsideContainer from "../../../common/components/MsAsideContainer";
|
||||
|
|
|
@ -1,105 +1,169 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"
|
||||
:visible.sync="dialogFormVisible"
|
||||
@close="close"
|
||||
width="60%" v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
top="50px">
|
||||
|
||||
<el-container class="main-content">
|
||||
<el-aside class="tree-aside" width="250px">
|
||||
<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName :
|
||||
$t('test_track.switch_project') }}
|
||||
</el-link>
|
||||
<node-tree class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refresh="refresh"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</el-aside>
|
||||
<test-case-relevance-base ref="baseRelevance">
|
||||
|
||||
<el-container>
|
||||
<el-main class="case-content">
|
||||
<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>
|
||||
<el-table
|
||||
:data="testCases"
|
||||
@filter-change="filter"
|
||||
row-key="id"
|
||||
@mouseleave.passive="leave"
|
||||
v-el-table-infinite-scroll="scrollLoading"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
<template v-slot:aside>
|
||||
<node-tree class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refresh="refresh"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<el-table-column
|
||||
type="selection"></el-table-column>
|
||||
<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>
|
||||
<el-table
|
||||
:data="testCases"
|
||||
@filter-change="filter"
|
||||
row-key="id"
|
||||
@mouseleave.passive="leave"
|
||||
v-el-table-infinite-scroll="scrollLoading"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('test_track.case.name')"
|
||||
style="width: 100%">
|
||||
<template v-slot:default="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table-column
|
||||
type="selection"></el-table-column>
|
||||
|
||||
<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>
|
||||
<div style="text-align: center">共 {{total}} 条</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('test_track.case.name')"
|
||||
style="width: 100%">
|
||||
<template v-slot:default="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="dialogFormVisible = false" @confirm="saveCaseRelevance"/>
|
||||
</template>
|
||||
<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>
|
||||
<div style="text-align: center">共 {{total}} 条</div>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>
|
||||
</div>
|
||||
</test-case-relevance-base>
|
||||
|
||||
<!--<div>-->
|
||||
<!--<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"-->
|
||||
<!--:visible.sync="dialogFormVisible"-->
|
||||
<!--@close="close"-->
|
||||
<!--width="60%" v-loading="result.loading"-->
|
||||
<!--:close-on-click-modal="false"-->
|
||||
<!--top="50px">-->
|
||||
|
||||
<!--<el-container class="main-content">-->
|
||||
<!--<el-aside class="tree-aside" width="250px">-->
|
||||
<!--<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName :-->
|
||||
<!--$t('test_track.switch_project') }}-->
|
||||
<!--</el-link>-->
|
||||
<!--<node-tree class="node-tree"-->
|
||||
<!--@nodeSelectEvent="nodeChange"-->
|
||||
<!--@refresh="refresh"-->
|
||||
<!--:tree-nodes="treeNodes"-->
|
||||
<!--ref="nodeTree"/>-->
|
||||
<!--</el-aside>-->
|
||||
|
||||
<!--<el-container>-->
|
||||
<!--<el-main class="case-content">-->
|
||||
<!--<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>-->
|
||||
<!--<el-table-->
|
||||
<!--:data="testCases"-->
|
||||
<!--@filter-change="filter"-->
|
||||
<!--row-key="id"-->
|
||||
<!--@mouseleave.passive="leave"-->
|
||||
<!--v-el-table-infinite-scroll="scrollLoading"-->
|
||||
<!--@select-all="handleSelectAll"-->
|
||||
<!--@select="handleSelectionChange"-->
|
||||
<!--height="50vh"-->
|
||||
<!--ref="table">-->
|
||||
|
||||
<!--<el-table-column-->
|
||||
<!--type="selection"></el-table-column>-->
|
||||
|
||||
<!--<el-table-column-->
|
||||
<!--prop="name"-->
|
||||
<!--:label="$t('test_track.case.name')"-->
|
||||
<!--style="width: 100%">-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--{{scope.row.name}}-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--<el-table-column-->
|
||||
<!--prop="priority"-->
|
||||
<!--:filters="priorityFilters"-->
|
||||
<!--column-key="priority"-->
|
||||
<!--:label="$t('test_track.case.priority')"-->
|
||||
<!--show-overflow-tooltip>-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--<priority-table-item :value="scope.row.priority"/>-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--<el-table-column-->
|
||||
<!--prop="type"-->
|
||||
<!--:filters="typeFilters"-->
|
||||
<!--column-key="type"-->
|
||||
<!--:label="$t('test_track.case.type')"-->
|
||||
<!--show-overflow-tooltip>-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--<type-table-item :value="scope.row.type"/>-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--</el-table>-->
|
||||
|
||||
<!--<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>-->
|
||||
<!--<div style="text-align: center">共 {{total}} 条</div>-->
|
||||
<!--</el-main>-->
|
||||
<!--</el-container>-->
|
||||
<!--</el-container>-->
|
||||
|
||||
<!--<template v-slot:footer>-->
|
||||
<!--<ms-dialog-footer @cancel="dialogFormVisible = false" @confirm="saveCaseRelevance"/>-->
|
||||
<!--</template>-->
|
||||
|
||||
<!--</el-dialog>-->
|
||||
|
||||
<!--<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>-->
|
||||
<!--</div>-->
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import NodeTree from '../../../common/NodeTree';
|
||||
import MsDialogFooter from '../../../../common/components/MsDialogFooter'
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import {_filter} from "../../../../../../common/js/utils";
|
||||
import MsTableSearchBar from "../../../../common/components/MsTableSearchBar";
|
||||
import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar";
|
||||
import MsTableHeader from "../../../../common/components/MsTableHeader";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import SwitchProject from "../../../case/components/SwitchProject";
|
||||
import NodeTree from '../../../../common/NodeTree';
|
||||
import MsDialogFooter from '../../../../../common/components/MsDialogFooter'
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MsTableSearchBar from "../../../../../common/components/MsTableSearchBar";
|
||||
import MsTableAdvSearchBar from "../../../../../common/components/search/MsTableAdvSearchBar";
|
||||
import MsTableHeader from "../../../../../common/components/MsTableHeader";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import SwitchProject from "../../../../case/components/SwitchProject";
|
||||
import elTableInfiniteScroll from 'el-table-infinite-scroll';
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import {_filter} from "../../../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "TestCaseRelevance",
|
||||
name: "TestCaseApiRelevance",
|
||||
components: {
|
||||
TestCaseRelevanceBase,
|
||||
NodeTree,
|
||||
MsDialogFooter,
|
||||
PriorityTableItem,
|
||||
|
@ -168,10 +232,13 @@
|
|||
this.toggleSelection(this.testCases);
|
||||
},
|
||||
methods: {
|
||||
openTestCaseRelevanceDialog() {
|
||||
this.getProject();
|
||||
this.dialogFormVisible = true;
|
||||
|
||||
open() {
|
||||
this.$refs.baseRelevance.open();
|
||||
|
||||
//
|
||||
},
|
||||
|
||||
saveCaseRelevance() {
|
||||
let param = {};
|
||||
param.planId = this.planId;
|
|
@ -10,8 +10,9 @@
|
|||
:draggable="false"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<template v-slot:main>
|
||||
<test-plan-test-case-list
|
||||
<test-plan-api-case-list
|
||||
class="table-list"
|
||||
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
|
||||
@refresh="refresh"
|
||||
|
@ -21,23 +22,28 @@
|
|||
ref="testPlanTestCaseList"/>
|
||||
</template>
|
||||
|
||||
<test-case-relevance
|
||||
<test-case-api-relevance
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
ref="testCaseRelevance"/>
|
||||
|
||||
</ms-test-plan-common-component>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeTree from "../../../../common/NodeTree";
|
||||
import TestPlanTestCaseList from "../TestPlanTestCaseList";
|
||||
import TestCaseRelevance from "../TestCaseRelevance";
|
||||
import MsTestPlanCommonComponent from "../TestPlanCommonComponent";
|
||||
import TestPlanTestCaseList from "../functional/FunctionalTestCaseList";
|
||||
import TestCaseRelevance from "../functional/TestCaseFunctionalRelevance";
|
||||
import MsTestPlanCommonComponent from "../base/TestPlanCommonComponent";
|
||||
import TestPlanApiCaseList from "./TestPlanApiCaseList";
|
||||
import TestCaseApiRelevance from "./TestCaseApiRelevance";
|
||||
|
||||
export default {
|
||||
name: "TestPlanApi",
|
||||
components: {
|
||||
TestCaseApiRelevance,
|
||||
TestPlanApiCaseList,
|
||||
MsTestPlanCommonComponent,
|
||||
TestCaseRelevance,
|
||||
TestPlanTestCaseList,
|
||||
|
@ -77,7 +83,7 @@
|
|||
this.getNodeTreeByPlanId();
|
||||
},
|
||||
openTestCaseRelevanceDialog() {
|
||||
this.$refs.testCaseRelevance.openTestCaseRelevanceDialog();
|
||||
this.$refs.testCaseRelevance.open();
|
||||
},
|
||||
nodeChange(nodeIds, pNodes) {
|
||||
this.selectNodeIds = nodeIds;
|
||||
|
|
|
@ -213,33 +213,33 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ExecutorEdit from './ExecutorEdit';
|
||||
import StatusEdit from './StatusEdit';
|
||||
import TestPlanTestCaseEdit from "./TestPlanTestCaseEdit";
|
||||
import MsTipButton from '../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../common/NodeBreadcrumb';
|
||||
import ExecutorEdit from '../ExecutorEdit';
|
||||
import StatusEdit from '../StatusEdit';
|
||||
import TestPlanTestCaseEdit from "../functional/FunctionalTestCaseEdit";
|
||||
import MsTipButton from '../../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../../common/NodeBreadcrumb';
|
||||
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, TokenKey, WORKSPACE_ID} from "@/common/js/constants";
|
||||
import {_filter, _sort, checkoutTestManagerOrTestUser, hasRoles} from "@/common/js/utils";
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "./TestReportTemplateList";
|
||||
import TestCaseReportView from "./report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../case/components/BatchEdit";
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "../TestReportTemplateList";
|
||||
import TestCaseReportView from "../report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../../case/components/BatchEdit";
|
||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||
import {hub} from "@/business/components/track/plan/event-bus";
|
||||
|
||||
export default {
|
||||
name: "TestPlanTestCaseList",
|
||||
name: "TestPlanApiCaseList",
|
||||
components: {
|
||||
TestCaseReportView,
|
||||
TestReportTemplateList,
|
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"
|
||||
:visible.sync="dialogVisible"
|
||||
@close="close"
|
||||
width="60%" v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
top="50px">
|
||||
|
||||
<el-container class="main-content">
|
||||
<el-aside class="tree-aside" width="250px">
|
||||
<select-menu
|
||||
:data="projects"
|
||||
width="185px"
|
||||
:current-data="currentProject"
|
||||
:title="$t('test_track.plan_view.plan')"
|
||||
@dataChange="changeProject"/>
|
||||
<slot name="aside"></slot>
|
||||
</el-aside>
|
||||
|
||||
<el-container>
|
||||
<el-main class="case-content">
|
||||
<slot></slot>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="dialogVisible = false" @confirm="save"/>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsDialogFooter from '../../../../../common/components/MsDialogFooter'
|
||||
import SelectMenu from "../../../../common/SelectMenu";
|
||||
|
||||
export default {
|
||||
name: "TestCaseRelevanceBase",
|
||||
components: {
|
||||
SelectMenu,
|
||||
MsDialogFooter,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
dialogVisible: false,
|
||||
currentProject: {},
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
projects: [],
|
||||
|
||||
};
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.getProject();
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
|
||||
refreshNode() {
|
||||
this.$emit('refresh');
|
||||
},
|
||||
|
||||
save() {
|
||||
this.$emit('save');
|
||||
},
|
||||
|
||||
refresh() {
|
||||
// this.close();
|
||||
|
||||
},
|
||||
|
||||
close() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
getProject() {
|
||||
if (this.planId) {
|
||||
this.result = this.$post("/test/plan/project/", {planId: this.planId}, res => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.projects = data;
|
||||
this.projectId = data[0].id;
|
||||
this.projectName = data[0].name;
|
||||
this.changeProject(data[0]);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
changeProject(project) {
|
||||
this.currentProject = project;
|
||||
this.$emit('setProject', project.id);
|
||||
// 获取项目时刷新该项目模块
|
||||
this.$emit('refreshNode');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.tb-edit .el-input {
|
||||
display: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tb-edit .current-row .el-input {
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.tb-edit .current-row .el-input + span {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
.node-tree {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.el-header {
|
||||
background-color: darkgrey;
|
||||
color: #333;
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
.case-content {
|
||||
padding: 0px 20px;
|
||||
height: 100%;
|
||||
/*border: 1px solid #EBEEF5;*/
|
||||
}
|
||||
|
||||
.tree-aside {
|
||||
min-height: 300px;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
min-height: 300px;
|
||||
height: 100%;
|
||||
/*border: 1px solid #EBEEF5;*/
|
||||
}
|
||||
|
||||
.project-link {
|
||||
float: right;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -15,9 +15,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsMainContainer from "../../../../common/components/MsMainContainer";
|
||||
import MsAsideContainer from "../../../../common/components/MsAsideContainer";
|
||||
import MsContainer from "../../../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../../../../common/components/MsMainContainer";
|
||||
import MsAsideContainer from "../../../../../common/components/MsAsideContainer";
|
||||
import MsContainer from "../../../../../common/components/MsContainer";
|
||||
export default {
|
||||
name: "MsTestPlanCommonComponent",
|
||||
components: {MsContainer, MsAsideContainer, MsMainContainer}
|
|
@ -351,17 +351,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import TestPlanTestCaseStatusButton from '../../common/TestPlanTestCaseStatusButton';
|
||||
import TestPlanTestCaseStatusButton from '../../../common/TestPlanTestCaseStatusButton';
|
||||
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||
import ApiTestDetail from "./test/ApiTestDetail";
|
||||
import ApiTestResult from "./test/ApiTestResult";
|
||||
import PerformanceTestDetail from "./test/PerformanceTestDetail";
|
||||
import PerformanceTestResult from "./test/PerformanceTestResult";
|
||||
import ApiTestDetail from "../test/ApiTestDetail";
|
||||
import ApiTestResult from "../test/ApiTestResult";
|
||||
import PerformanceTestDetail from "../test/PerformanceTestDetail";
|
||||
import PerformanceTestResult from "../test/PerformanceTestResult";
|
||||
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
|
||||
|
||||
export default {
|
||||
name: "TestPlanTestCaseEdit",
|
||||
name: "FunctionalTestCaseEdit",
|
||||
components: {
|
||||
PerformanceTestResult,
|
||||
PerformanceTestDetail,
|
|
@ -0,0 +1,608 @@
|
|||
<template>
|
||||
<div class="card-container">
|
||||
<el-card class="card-content" v-loading="result.loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="initTableData"
|
||||
:show-create="false" :tip="$t('commons.search_by_name_or_id')">
|
||||
<template v-slot:title>
|
||||
<node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="breadcrumbRefresh"/>
|
||||
</template>
|
||||
<template v-slot:button>
|
||||
<ms-table-button :is-tester-permission="true" v-if="!showMyTestCase" icon="el-icon-s-custom"
|
||||
:content="$t('test_track.plan_view.my_case')" @click="searchMyTestCase"/>
|
||||
<ms-table-button :is-tester-permission="true" v-if="showMyTestCase" icon="el-icon-files"
|
||||
:content="$t('test_track.plan_view.all_case')" @click="searchMyTestCase"/>
|
||||
<ms-table-button :is-tester-permission="true" icon="el-icon-connection"
|
||||
:content="$t('test_track.plan_view.relevance_test_case')"
|
||||
@click="$emit('openTestCaseRelevanceDialog')"/>
|
||||
<ms-table-button :is-tester-permission="true" v-if="!testPlan.reportId" icon="el-icon-document"
|
||||
:content="$t('test_track.plan_view.create_report')" @click="openTestReport"/>
|
||||
<ms-table-button :is-tester-permission="true" v-if="testPlan.reportId" icon="el-icon-document"
|
||||
:content="$t('test_track.plan_view.view_report')" @click="openReport"/>
|
||||
<ms-table-button :is-tester-permission="true" icon="el-icon-document-remove"
|
||||
:content="$t('test_track.plan_view.cancel_all_relevance')" @click="handleDeleteBatch"/>
|
||||
</template>
|
||||
</ms-table-header>
|
||||
</template>
|
||||
|
||||
<executor-edit ref="executorEdit" :select-ids="new Set(Array.from(this.selectRows).map(row => row.id))"
|
||||
@refresh="initTableData"/>
|
||||
<status-edit ref="statusEdit" :plan-id="planId"
|
||||
:select-ids="new Set(Array.from(this.selectRows).map(row => row.id))" @refresh="initTableData"/>
|
||||
|
||||
<el-table
|
||||
class="adjust-table"
|
||||
border
|
||||
@select-all="handleSelectAll"
|
||||
@filter-change="filter"
|
||||
@sort-change="sort"
|
||||
@select="handleSelectionChange"
|
||||
row-key="id"
|
||||
@row-click="showDetail"
|
||||
:data="tableData">
|
||||
|
||||
<el-table-column
|
||||
type="selection"/>
|
||||
<el-table-column width="40" :resizable="false" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="num"
|
||||
sortable="custom"
|
||||
:label="$t('commons.id')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority" ref="priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="method"
|
||||
:filters="methodFilters"
|
||||
column-key="method"
|
||||
:label="$t('test_track.case.method')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<method-table-item :value="scope.row.method"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="nodePath"
|
||||
:label="$t('test_track.case.module')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="projectName"
|
||||
:label="$t('test_track.plan.plan_project')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
:label="$t('test_track.issue.issue')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="right"
|
||||
width="400"
|
||||
trigger="hover">
|
||||
<el-table border class="adjust-table" :data="scope.row.issuesContent" style="width: 100%">
|
||||
<el-table-column prop="title" :label="$t('test_track.issue.title')" show-overflow-tooltip/>
|
||||
<el-table-column prop="description" :label="$t('test_track.issue.description')">
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="left"
|
||||
width="400"
|
||||
trigger="hover"
|
||||
>
|
||||
<ckeditor :editor="editor" disabled :config="editorConfig"
|
||||
v-model="scope.row.description"/>
|
||||
<el-button slot="reference" type="text">{{ $t('test_track.issue.preview') }}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
||||
</el-table>
|
||||
<el-button slot="reference" type="text">{{ scope.row.issuesSize }}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
<el-table-column
|
||||
prop="executorName"
|
||||
:filters="executorFilters"
|
||||
column-key="executor"
|
||||
:label="$t('test_track.plan_view.executor')">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:filters="statusFilters"
|
||||
column-key="status"
|
||||
:label="$t('test_track.plan_view.execute_result')">
|
||||
<template v-slot:default="scope">
|
||||
<span @click.stop="clickt = 'stop'">
|
||||
<el-dropdown class="test-case-status" @command="statusChange">
|
||||
<span class="el-dropdown-link">
|
||||
<status-table-item :value="scope.row.status"/>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown" chang>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Pass'}">
|
||||
{{ $t('test_track.plan_view.pass') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Failure'}">
|
||||
{{ $t('test_track.plan_view.failure') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Blocking'}">
|
||||
{{ $t('test_track.plan_view.blocking') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Skip'}">
|
||||
{{ $t('test_track.plan_view.skip') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="100"
|
||||
:label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.edit')" icon="el-icon-edit"
|
||||
@exec="handleEdit(scope.row)"/>
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('test_track.plan_view.cancel_relevance')"
|
||||
icon="el-icon-unlock" type="danger" @exec="handleDelete(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
|
||||
<functional-test-case-edit
|
||||
ref="testPlanTestCaseEdit"
|
||||
:search-param.sync="condition"
|
||||
@refresh="initTableData"
|
||||
:is-read-only="isReadOnly"
|
||||
@refreshTable="search"/>
|
||||
|
||||
<test-report-template-list @openReport="openReport" ref="testReportTemplateList"/>
|
||||
<test-case-report-view @refresh="initTableData" ref="testCaseReportView"/>
|
||||
</el-card>
|
||||
<batch-edit ref="batchEdit" @batchEdit="batchEdit"
|
||||
:type-arr="typeArr" :value-arr="valueArr" :dialog-title="$t('test_track.case.batch_edit_case')"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ExecutorEdit from '../ExecutorEdit';
|
||||
import StatusEdit from '../StatusEdit';
|
||||
import FunctionalTestCaseEdit from "./FunctionalTestCaseEdit";
|
||||
import MsTipButton from '../../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../../common/NodeBreadcrumb';
|
||||
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, TokenKey, WORKSPACE_ID} from "@/common/js/constants";
|
||||
import {_filter, _sort, checkoutTestManagerOrTestUser, hasRoles} from "@/common/js/utils";
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "../TestReportTemplateList";
|
||||
import TestCaseReportView from "../report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../../case/components/BatchEdit";
|
||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||
import {hub} from "@/business/components/track/plan/event-bus";
|
||||
|
||||
export default {
|
||||
name: "FunctionalTestCaseList",
|
||||
components: {
|
||||
FunctionalTestCaseEdit,
|
||||
TestCaseReportView,
|
||||
TestReportTemplateList,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
MethodTableItem,
|
||||
TypeTableItem,
|
||||
StatusTableItem,
|
||||
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
|
||||
MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
|
||||
BatchEdit
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
deletePath: "/test/case/delete",
|
||||
condition: {
|
||||
components: TEST_CASE_CONFIGS
|
||||
},
|
||||
showMyTestCase: false,
|
||||
tableData: [],
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
selectRows: new Set(),
|
||||
testPlan: {},
|
||||
isReadOnly: false,
|
||||
isTestManagerOrTestUser: false,
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
{text: 'P2', value: 'P2'},
|
||||
{text: 'P3', value: 'P3'}
|
||||
],
|
||||
methodFilters: [
|
||||
{text: this.$t('test_track.case.manual'), value: 'manual'},
|
||||
{text: this.$t('test_track.case.auto'), value: 'auto'}
|
||||
],
|
||||
typeFilters: [
|
||||
{text: this.$t('commons.functional'), value: 'functional'},
|
||||
{text: this.$t('commons.performance'), value: 'performance'},
|
||||
{text: this.$t('commons.api'), value: 'api'}
|
||||
],
|
||||
statusFilters: [
|
||||
{text: this.$t('test_track.plan.plan_status_prepare'), value: 'Prepare'},
|
||||
{text: this.$t('test_track.plan_view.pass'), value: 'Pass'},
|
||||
{text: this.$t('test_track.plan_view.failure'), value: 'Failure'},
|
||||
{text: this.$t('test_track.plan_view.blocking'), value: 'Blocking'},
|
||||
{text: this.$t('test_track.plan_view.skip'), value: 'Skip'},
|
||||
{text: this.$t('test_track.plan.plan_status_running'), value: 'Underway'},
|
||||
],
|
||||
executorFilters: [],
|
||||
showMore: false,
|
||||
buttons: [
|
||||
{
|
||||
name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit
|
||||
},
|
||||
{
|
||||
name: this.$t('test_track.case.batch_unlink'), handleClick: this.handleDeleteBatch
|
||||
}
|
||||
],
|
||||
typeArr: [
|
||||
{id: 'status', name: this.$t('test_track.plan_view.execute_result')},
|
||||
{id: 'executor', name: this.$t('test_track.plan_view.executor')},
|
||||
],
|
||||
valueArr: {
|
||||
executor: [],
|
||||
status: [
|
||||
{name: this.$t('test_track.plan_view.pass'), id: 'Pass'},
|
||||
{name: this.$t('test_track.plan_view.failure'), id: 'Failure'},
|
||||
{name: this.$t('test_track.plan_view.blocking'), id: 'Blocking'},
|
||||
{name: this.$t('test_track.plan_view.skip'), id: 'Skip'}
|
||||
]
|
||||
},
|
||||
editor: ClassicEditor,
|
||||
editorConfig: {
|
||||
// 'increaseIndent','decreaseIndent'
|
||||
toolbar: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
},
|
||||
selectNodeIds: {
|
||||
type: Array
|
||||
},
|
||||
selectParentNodes: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
planId() {
|
||||
this.refreshTableAndPlan();
|
||||
},
|
||||
selectNodeIds() {
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
hub.$on("openFailureTestCase", row => {
|
||||
this.isReadOnly = true;
|
||||
this.condition.status = 'Failure';
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
});
|
||||
this.refreshTableAndPlan();
|
||||
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
|
||||
this.getMaintainerOptions();
|
||||
},
|
||||
beforeDestroy() {
|
||||
hub.$off("openFailureTestCase");
|
||||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
if (this.planId) {
|
||||
// param.planId = this.planId;
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
// param.nodeIds = this.selectNodeIds;
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
if (this.planId) {
|
||||
this.result = this.$post(this.buildPagePath('/test/plan/case/list'), this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", 0);
|
||||
this.$get("/issues/get/" + this.tableData[i].caseId, response => {
|
||||
let issues = response.data;
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", issues.length);
|
||||
this.$set(this.tableData[i], "issuesContent", issues);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
this.selectRows.clear();
|
||||
});
|
||||
}
|
||||
},
|
||||
showDetail(row, event, column) {
|
||||
this.isReadOnly = true;
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
},
|
||||
refresh() {
|
||||
this.condition = {components: TEST_CASE_CONFIGS};
|
||||
this.selectRows.clear();
|
||||
this.$emit('refresh');
|
||||
},
|
||||
breadcrumbRefresh() {
|
||||
this.showMyTestCase = false;
|
||||
this.refresh();
|
||||
},
|
||||
refreshTableAndPlan() {
|
||||
this.getTestPlanById();
|
||||
this.initTableData();
|
||||
},
|
||||
refreshTestPlanRecent() {
|
||||
if (hasRoles(ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
let param = {};
|
||||
param.id = this.planId;
|
||||
param.updateTime = Date.now();
|
||||
this.$post('/test/plan/edit', param);
|
||||
}
|
||||
},
|
||||
search() {
|
||||
this.initTableData();
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
handleEdit(testCase, index) {
|
||||
this.isReadOnly = false;
|
||||
if (!checkoutTestManagerOrTestUser()) {
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(testCase);
|
||||
},
|
||||
handleDelete(testCase) {
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + ' ' + testCase.name + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this._handleDelete(testCase);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDeleteBatch() {
|
||||
if (this.tableData.length < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.no_case_relevance'));
|
||||
return;
|
||||
}
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
if (this.selectRows.size > 0) {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this._handleBatchDelete(ids);
|
||||
} else {
|
||||
if (this.planId) {
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
// 根据条件查询计划下所有的关联用例
|
||||
this.$post('/test/plan/case/list/all', this.condition, res => {
|
||||
let data = res.data;
|
||||
let ids = data.map(d => d.id);
|
||||
this._handleBatchDelete(ids);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
_handleBatchDelete(ids) {
|
||||
this.result = this.$post('/test/plan/case/batch/delete', {ids: ids}, () => {
|
||||
this.selectRows.clear();
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
_handleDelete(testCase) {
|
||||
let testCaseId = testCase.id;
|
||||
this.result = this.$post('/test/plan/case/delete/' + testCaseId, {}, () => {
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.tableData.forEach(item => {
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
},
|
||||
handleSelectionChange(selection, row) {
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
},
|
||||
handleBatch(type) {
|
||||
if (this.selectRows.size < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||
return;
|
||||
}
|
||||
if (type === 'executor') {
|
||||
this.$refs.executorEdit.openExecutorEdit();
|
||||
} else if (type === 'status') {
|
||||
this.$refs.statusEdit.openStatusEdit();
|
||||
} else if (type === 'delete') {
|
||||
this.handleDeleteBatch();
|
||||
}
|
||||
},
|
||||
searchMyTestCase() {
|
||||
this.showMyTestCase = !this.showMyTestCase;
|
||||
if (this.showMyTestCase) {
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
this.condition.executor = user.id;
|
||||
} else {
|
||||
this.condition.executor = null;
|
||||
}
|
||||
this.initTableData();
|
||||
},
|
||||
openTestReport() {
|
||||
this.$refs.testReportTemplateList.open(this.planId);
|
||||
},
|
||||
statusChange(param) {
|
||||
this.$post('/test/plan/case/edit', param, () => {
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i].id == param.id) {
|
||||
this.tableData[i].status = param.status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getTestPlanById() {
|
||||
if (this.planId) {
|
||||
this.$post('/test/plan/get/' + this.planId, {}, response => {
|
||||
this.testPlan = response.data;
|
||||
this.refreshTestPlanRecent();
|
||||
});
|
||||
}
|
||||
},
|
||||
openReport(planId, id) {
|
||||
this.getTestPlanById();
|
||||
if (!id) {
|
||||
id = this.testPlan.reportId;
|
||||
}
|
||||
if (!planId) {
|
||||
planId = this.planId;
|
||||
}
|
||||
this.$refs.testCaseReportView.open(planId, id);
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
if (this.condition.orders) {
|
||||
this.condition.orders = [];
|
||||
}
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
batchEdit(form) {
|
||||
let param = {};
|
||||
param[form.type] = form.value;
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/test/plan/case/batch/edit', param, () => {
|
||||
this.selectRows.clear();
|
||||
this.status = '';
|
||||
this.$post('/test/plan/edit/status/' + this.planId);
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
handleBatchEdit() {
|
||||
this.getMaintainerOptions();
|
||||
this.$refs.batchEdit.open();
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||
this.valueArr.executor = response.data;
|
||||
this.executorFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.search {
|
||||
margin-left: 10px;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.test-case-status, .el-table {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,303 @@
|
|||
<template>
|
||||
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="saveCaseRelevance"
|
||||
:plan-id="planId"
|
||||
ref="baseRelevance">
|
||||
|
||||
<template v-slot:aside>
|
||||
<node-tree class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refresh="refresh"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>
|
||||
|
||||
<el-table
|
||||
v-loading="result.loading"
|
||||
:data="testCases"
|
||||
@filter-change="filter"
|
||||
row-key="id"
|
||||
@mouseleave.passive="leave"
|
||||
v-el-table-infinite-scroll="scrollLoading"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
|
||||
<el-table-column
|
||||
type="selection"></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('test_track.case.name')"
|
||||
style="width: 100%">
|
||||
<template v-slot:default="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>
|
||||
<div style="text-align: center">共 {{total}} 条</div>
|
||||
|
||||
</test-case-relevance-base>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import NodeTree from '../../../../common/NodeTree';
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MsTableSearchBar from "../../../../../common/components/MsTableSearchBar";
|
||||
import MsTableAdvSearchBar from "../../../../../common/components/search/MsTableAdvSearchBar";
|
||||
import MsTableHeader from "../../../../../common/components/MsTableHeader";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import elTableInfiniteScroll from 'el-table-infinite-scroll';
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import {_filter} from "../../../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "TestCaseFunctionalRelevance",
|
||||
components: {
|
||||
TestCaseRelevanceBase,
|
||||
NodeTree,
|
||||
PriorityTableItem,
|
||||
TypeTableItem,
|
||||
MsTableSearchBar,
|
||||
MsTableAdvSearchBar,
|
||||
MsTableHeader,
|
||||
},
|
||||
directives: {
|
||||
'el-table-infinite-scroll': elTableInfiniteScroll
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
isCheckAll: false,
|
||||
testCases: [],
|
||||
selectIds: new Set(),
|
||||
treeNodes: [],
|
||||
selectNodeIds: [],
|
||||
selectNodeNames: [],
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
projects: [],
|
||||
pageSize: 50,
|
||||
currentPage: 1,
|
||||
total: 0,
|
||||
lineStatus: true,
|
||||
condition: {
|
||||
components: TEST_CASE_CONFIGS
|
||||
},
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
{text: 'P2', value: 'P2'},
|
||||
{text: 'P3', value: 'P3'}
|
||||
],
|
||||
typeFilters: [
|
||||
{text: this.$t('commons.functional'), value: 'functional'},
|
||||
{text: this.$t('commons.performance'), value: 'performance'},
|
||||
{text: this.$t('commons.api'), value: 'api'}
|
||||
]
|
||||
};
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
planId() {
|
||||
this.condition.planId = this.planId;
|
||||
},
|
||||
selectNodeIds() {
|
||||
this.search();
|
||||
},
|
||||
projectId() {
|
||||
this.condition.projectId = this.projectId;
|
||||
this.getProjectNode();
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
this.toggleSelection(this.testCases);
|
||||
},
|
||||
methods: {
|
||||
|
||||
open() {
|
||||
this.$refs.baseRelevance.open();
|
||||
},
|
||||
|
||||
setProject(projectId) {
|
||||
this.projectId = projectId;
|
||||
},
|
||||
|
||||
saveCaseRelevance() {
|
||||
let param = {};
|
||||
param.planId = this.planId;
|
||||
param.testCaseIds = [...this.selectIds];
|
||||
param.request = this.condition;
|
||||
// 选择全选则全部加入到评审,无论是否加载完全部
|
||||
if (this.testCases.length === param.testCaseIds.length) {
|
||||
param.testCaseIds = ['all'];
|
||||
}
|
||||
this.result = this.$post('/test/plan/relevance', param, () => {
|
||||
this.selectIds.clear();
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
|
||||
this.$refs.baseRelevance.close();
|
||||
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
search() {
|
||||
this.currentPage = 1;
|
||||
this.testCases = [];
|
||||
this.getTestCases(true);
|
||||
},
|
||||
getTestCases(flag) {
|
||||
if (this.planId) {
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
} else {
|
||||
this.condition.nodeIds = [];
|
||||
}
|
||||
if (this.projectId) {
|
||||
this.condition.projectId = this.projectId;
|
||||
this.result = this.$post(this.buildPagePath('/test/case/name'), this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
let tableData = data.listObject;
|
||||
tableData.forEach(item => {
|
||||
item.checked = false;
|
||||
});
|
||||
flag ? this.testCases = tableData : this.testCases = this.testCases.concat(tableData);
|
||||
// 去重处理
|
||||
let hash = {}
|
||||
this.testCases = this.testCases.reduce((item, next) => {
|
||||
if (!hash[next.id]) {
|
||||
hash[next.id] = true
|
||||
item.push(next)
|
||||
}
|
||||
return item
|
||||
}, [])
|
||||
|
||||
this.lineStatus = tableData.length === 50 && this.testCases.length < this.total;
|
||||
});
|
||||
}
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.testCases.forEach(item => {
|
||||
this.selectIds.add(item.id);
|
||||
});
|
||||
} else {
|
||||
this.testCases.forEach(item => {
|
||||
if (this.selectIds.has(item.id)) {
|
||||
this.selectIds.delete(item.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleSelectionChange(selection, row) {
|
||||
if (this.selectIds.has(row.id)) {
|
||||
this.selectIds.delete(row.id);
|
||||
} else {
|
||||
this.selectIds.add(row.id);
|
||||
}
|
||||
},
|
||||
nodeChange(nodeIds, nodeNames) {
|
||||
this.selectNodeIds = nodeIds;
|
||||
this.selectNodeNames = nodeNames;
|
||||
},
|
||||
refresh() {
|
||||
this.close();
|
||||
},
|
||||
scrollLoading() {
|
||||
if (this.lineStatus) {
|
||||
this.currentPage += 1;
|
||||
this.getTestCases();
|
||||
}
|
||||
},
|
||||
getAllNodeTreeByPlanId() {
|
||||
if (this.planId) {
|
||||
let param = {
|
||||
testPlanId: this.planId,
|
||||
projectId: this.projectId
|
||||
};
|
||||
this.result = this.$post("/case/node/list/all/plan", param, response => {
|
||||
this.treeNodes = response.data;
|
||||
});
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.lineStatus = false;
|
||||
this.selectIds.clear();
|
||||
this.selectNodeIds = [];
|
||||
this.selectNodeNames = [];
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.search();
|
||||
},
|
||||
toggleSelection(rows) {
|
||||
rows.forEach(row => {
|
||||
this.selectIds.forEach(id => {
|
||||
if (row.id === id) {
|
||||
// true 是为选中
|
||||
this.$refs.table.toggleRowSelection(row, true)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
getProjectNode(projectId) {
|
||||
const index = this.projects.findIndex(project => project.id === projectId);
|
||||
if (index !== -1) {
|
||||
this.projectName = this.projects[index].name;
|
||||
}
|
||||
if (projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
this.$refs.nodeTree.result = this.$post("/case/node/list/all/plan",
|
||||
{testPlanId: this.planId, projectId: this.projectId}, response => {
|
||||
this.treeNodes = response.data;
|
||||
});
|
||||
this.selectNodeIds = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -11,7 +11,7 @@
|
|||
ref="nodeTree"/>
|
||||
</template>
|
||||
<template v-slot:main>
|
||||
<test-plan-test-case-list
|
||||
<functional-test-case-list
|
||||
class="table-list"
|
||||
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
|
||||
@refresh="refresh"
|
||||
|
@ -21,7 +21,7 @@
|
|||
ref="testPlanTestCaseList"/>
|
||||
</template>
|
||||
|
||||
<test-case-relevance
|
||||
<test-case-functional-relevance
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
ref="testCaseRelevance"/>
|
||||
|
@ -31,16 +31,18 @@
|
|||
|
||||
<script>
|
||||
import NodeTree from "../../../../common/NodeTree";
|
||||
import TestPlanTestCaseList from "../TestPlanTestCaseList";
|
||||
import TestCaseRelevance from "../TestCaseRelevance";
|
||||
import MsTestPlanCommonComponent from "../TestPlanCommonComponent";
|
||||
import TestCaseRelevance from "./TestCaseFunctionalRelevance";
|
||||
import MsTestPlanCommonComponent from "../base/TestPlanCommonComponent";
|
||||
import TestCaseFunctionalRelevance from "./TestCaseFunctionalRelevance";
|
||||
import FunctionalTestCaseList from "./FunctionalTestCaseList";
|
||||
|
||||
export default {
|
||||
name: "TestPlanFunctional",
|
||||
components: {
|
||||
FunctionalTestCaseList,
|
||||
TestCaseFunctionalRelevance,
|
||||
MsTestPlanCommonComponent,
|
||||
TestCaseRelevance,
|
||||
TestPlanTestCaseList,
|
||||
NodeTree,
|
||||
},
|
||||
data() {
|
||||
|
@ -77,7 +79,7 @@
|
|||
this.getNodeTreeByPlanId();
|
||||
},
|
||||
openTestCaseRelevanceDialog() {
|
||||
this.$refs.testCaseRelevance.openTestCaseRelevanceDialog();
|
||||
this.$refs.testCaseRelevance.open();
|
||||
},
|
||||
nodeChange(nodeIds, pNodes) {
|
||||
this.selectNodeIds = nodeIds;
|
||||
|
|
|
@ -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 TrackHome = () => import('@/business/components/track/home/TrackHome')
|
||||
|
@ -51,11 +51,11 @@ export default {
|
|||
name: "planViewEdit",
|
||||
component: TestPlanView
|
||||
},
|
||||
{
|
||||
path: "project/:type",
|
||||
name: "trackProject",
|
||||
component: MsProject
|
||||
},
|
||||
// {
|
||||
// path: "project/:type",
|
||||
// name: "trackProject",
|
||||
// component: MsProject
|
||||
// },
|
||||
{
|
||||
path: "review/:type",
|
||||
name: "testCaseReview",
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a22a3005d9bd254793fcf634d72539cbdf31be3a
|
||||
Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8
|
|
@ -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,',
|
||||
message: 'Event, receiver and receiving method are required\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: {
|
||||
select_defect_platform: 'Please select the defect management platform to be integrated:',
|
||||
|
@ -294,6 +295,7 @@ export default {
|
|||
tapd_id: 'TAPD Project ID',
|
||||
jira_key: 'JIRA Project key',
|
||||
zentao_id: 'Zentao Project ID',
|
||||
manager: 'Manager',
|
||||
},
|
||||
member: {
|
||||
create: 'Create',
|
||||
|
|
|
@ -242,9 +242,8 @@ export default {
|
|||
' 2.机器人选择为群机器人,安全验证选择“自定义关键词” :"任务通知";\n' +
|
||||
' 3.选择接收人时必须是你所建的群里包含的人,接收人手机号为必填项且为钉钉企业所使用的手机号,',
|
||||
message: '事件,接收人,接收方式为必填项',
|
||||
message_webhook: '接收方式为钉钉和企业机器人时,webhook为必填项'
|
||||
|
||||
|
||||
message_webhook: '接收方式为钉钉和企业机器人时,webhook为必填项',
|
||||
template: "模版"
|
||||
},
|
||||
integration: {
|
||||
select_defect_platform: '请选择要集成的缺陷管理平台:',
|
||||
|
@ -293,6 +292,7 @@ export default {
|
|||
tapd_id: 'TAPD项目ID',
|
||||
jira_key: 'JIRA项目key',
|
||||
zentao_id: 'Zentao项目ID',
|
||||
manager: '项目管理',
|
||||
},
|
||||
member: {
|
||||
create: '添加成员',
|
||||
|
@ -562,6 +562,10 @@ export default {
|
|||
execute: "执行",
|
||||
copy: "复制",
|
||||
remove: "删除",
|
||||
view_ref: "查看引用",
|
||||
case_ref: "用例引用",
|
||||
scenario_ref: "场景引用",
|
||||
plan_ref: "测试计划引用",
|
||||
batch_add_plan: "批量添加到测试计划",
|
||||
batch_execute: "批量执行",
|
||||
scenario: {
|
||||
|
|
|
@ -242,9 +242,8 @@ export default {
|
|||
' 2.接收方式除郵件外webhook為必填;\n' +
|
||||
' 3.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知"',
|
||||
message: '事件,接收人,接收方式為必填項',
|
||||
message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項'
|
||||
|
||||
|
||||
message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項',
|
||||
template: "模版"
|
||||
},
|
||||
integration: {
|
||||
select_defect_platform: '請選擇要集成的缺陷管理平臺:',
|
||||
|
@ -293,6 +292,7 @@ export default {
|
|||
tapd_id: 'TAPD項目ID',
|
||||
jira_key: 'JIRA項目key',
|
||||
zentao_id: 'Zentao項目ID',
|
||||
manager: '項目管理',
|
||||
},
|
||||
member: {
|
||||
create: '添加成員',
|
||||
|
|
Loading…
Reference in New Issue