feat: 测试计划缺陷管理改造 (#2166)
* feat: 缺陷管理 * feat: 测试计划缺陷管理改造 * 代码规范 Co-authored-by: chenjianxing <jianxing.chen@fit2cloud.com> Co-authored-by: jianxing <41557596+AgAngle@users.noreply.github.com>
This commit is contained in:
parent
afc4e2ff10
commit
82cc5801c1
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
@ -22,13 +21,7 @@ public class Issues implements Serializable {
|
|||
|
||||
private String platform;
|
||||
|
||||
private String description;
|
||||
|
||||
private String model;
|
||||
|
||||
private String projectName;
|
||||
|
||||
private String currentOwner;
|
||||
private String projectId;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class IssuesDao extends IssuesWithBLOBs {
|
||||
private String model;
|
||||
private String projectName;
|
||||
}
|
|
@ -643,6 +643,76 @@ public class IssuesExample {
|
|||
addCriterion("platform not between", value1, value2, "platform");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNull() {
|
||||
addCriterion("project_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNotNull() {
|
||||
addCriterion("project_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdEqualTo(String value) {
|
||||
addCriterion("project_id =", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotEqualTo(String value) {
|
||||
addCriterion("project_id <>", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThan(String value) {
|
||||
addCriterion("project_id >", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("project_id >=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThan(String value) {
|
||||
addCriterion("project_id <", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("project_id <=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLike(String value) {
|
||||
addCriterion("project_id like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotLike(String value) {
|
||||
addCriterion("project_id not like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIn(List<String> values) {
|
||||
addCriterion("project_id in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotIn(List<String> values) {
|
||||
addCriterion("project_id not in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdBetween(String value1, String value2) {
|
||||
addCriterion("project_id between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
||||
addCriterion("project_id not between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class IssuesWithBLOBs extends Issues implements Serializable {
|
||||
private String description;
|
||||
|
||||
private String customFields;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -2,6 +2,7 @@ package io.metersphere.base.mapper;
|
|||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesExample;
|
||||
import io.metersphere.base.domain.IssuesWithBLOBs;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -12,25 +13,25 @@ public interface IssuesMapper {
|
|||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(Issues record);
|
||||
int insert(IssuesWithBLOBs record);
|
||||
|
||||
int insertSelective(Issues record);
|
||||
int insertSelective(IssuesWithBLOBs record);
|
||||
|
||||
List<Issues> selectByExampleWithBLOBs(IssuesExample example);
|
||||
List<IssuesWithBLOBs> selectByExampleWithBLOBs(IssuesExample example);
|
||||
|
||||
List<Issues> selectByExample(IssuesExample example);
|
||||
|
||||
Issues selectByPrimaryKey(String id);
|
||||
IssuesWithBLOBs selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") Issues record, @Param("example") IssuesExample example);
|
||||
int updateByExampleSelective(@Param("record") IssuesWithBLOBs record, @Param("example") IssuesExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") Issues record, @Param("example") IssuesExample example);
|
||||
int updateByExampleWithBLOBs(@Param("record") IssuesWithBLOBs record, @Param("example") IssuesExample example);
|
||||
|
||||
int updateByExample(@Param("record") Issues record, @Param("example") IssuesExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(Issues record);
|
||||
int updateByPrimaryKeySelective(IssuesWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(Issues record);
|
||||
int updateByPrimaryKeyWithBLOBs(IssuesWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKey(Issues record);
|
||||
}
|
|
@ -10,9 +10,11 @@
|
|||
<result column="reporter" jdbcType="VARCHAR" property="reporter" />
|
||||
<result column="lastmodify" jdbcType="VARCHAR" property="lastmodify" />
|
||||
<result column="platform" jdbcType="VARCHAR" property="platform" />
|
||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.Issues">
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.IssuesWithBLOBs">
|
||||
<result column="description" jdbcType="LONGVARCHAR" property="description" />
|
||||
<result column="custom_fields" jdbcType="LONGVARCHAR" property="customFields" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -73,10 +75,10 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, title, `status`, create_time, update_time, reporter, lastmodify, platform
|
||||
id, title, `status`, create_time, update_time, reporter, lastmodify, platform, project_id
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
description
|
||||
description, custom_fields
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.IssuesExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
|
@ -126,17 +128,17 @@
|
|||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.Issues">
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.IssuesWithBLOBs">
|
||||
insert into issues (id, title, `status`,
|
||||
create_time, update_time, reporter,
|
||||
lastmodify, platform, description
|
||||
)
|
||||
lastmodify, platform, project_id,
|
||||
description, custom_fields)
|
||||
values (#{id,jdbcType=VARCHAR}, #{title,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{reporter,jdbcType=VARCHAR},
|
||||
#{lastmodify,jdbcType=VARCHAR}, #{platform,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
#{lastmodify,jdbcType=VARCHAR}, #{platform,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR},
|
||||
#{description,jdbcType=LONGVARCHAR}, #{customFields,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.Issues">
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.IssuesWithBLOBs">
|
||||
insert into issues
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -163,9 +165,15 @@
|
|||
<if test="platform != null">
|
||||
platform,
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id,
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description,
|
||||
</if>
|
||||
<if test="customFields != null">
|
||||
custom_fields,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -192,9 +200,15 @@
|
|||
<if test="platform != null">
|
||||
#{platform,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
#{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
#{description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="customFields != null">
|
||||
#{customFields,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.IssuesExample" resultType="java.lang.Long">
|
||||
|
@ -230,9 +244,15 @@
|
|||
<if test="record.platform != null">
|
||||
platform = #{record.platform,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.projectId != null">
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.description != null">
|
||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.customFields != null">
|
||||
custom_fields = #{record.customFields,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -248,7 +268,9 @@
|
|||
reporter = #{record.reporter,jdbcType=VARCHAR},
|
||||
lastmodify = #{record.lastmodify,jdbcType=VARCHAR},
|
||||
platform = #{record.platform,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=LONGVARCHAR}
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||
custom_fields = #{record.customFields,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -262,12 +284,13 @@
|
|||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
reporter = #{record.reporter,jdbcType=VARCHAR},
|
||||
lastmodify = #{record.lastmodify,jdbcType=VARCHAR},
|
||||
platform = #{record.platform,jdbcType=VARCHAR}
|
||||
platform = #{record.platform,jdbcType=VARCHAR},
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.Issues">
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.IssuesWithBLOBs">
|
||||
update issues
|
||||
<set>
|
||||
<if test="title != null">
|
||||
|
@ -291,13 +314,19 @@
|
|||
<if test="platform != null">
|
||||
platform = #{platform,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description = #{description,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="customFields != null">
|
||||
custom_fields = #{customFields,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.Issues">
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.IssuesWithBLOBs">
|
||||
update issues
|
||||
set title = #{title,jdbcType=VARCHAR},
|
||||
`status` = #{status,jdbcType=VARCHAR},
|
||||
|
@ -306,7 +335,9 @@
|
|||
reporter = #{reporter,jdbcType=VARCHAR},
|
||||
lastmodify = #{lastmodify,jdbcType=VARCHAR},
|
||||
platform = #{platform,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=LONGVARCHAR}
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=LONGVARCHAR},
|
||||
custom_fields = #{customFields,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.Issues">
|
||||
|
@ -317,7 +348,8 @@
|
|||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
reporter = #{reporter,jdbcType=VARCHAR},
|
||||
lastmodify = #{lastmodify,jdbcType=VARCHAR},
|
||||
platform = #{platform,jdbcType=VARCHAR}
|
||||
platform = #{platform,jdbcType=VARCHAR},
|
||||
project_id = #{projectId,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -1,11 +1,14 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtIssuesMapper {
|
||||
|
||||
List<Issues> getIssues(@Param("caseId") String caseId, @Param("platform") String platform);
|
||||
List<IssuesDao> getIssuesByCaseId(@Param("request") IssuesRequest issuesRequest);
|
||||
|
||||
List<IssuesDao> getIssuesByProjectId(@Param("request") IssuesRequest issuesRequest);
|
||||
}
|
||||
|
|
|
@ -2,12 +2,61 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtIssuesMapper">
|
||||
|
||||
<select id="getIssues" resultType="io.metersphere.base.domain.Issues">
|
||||
<select id="getIssuesByCaseId" resultType="io.metersphere.base.domain.IssuesDao">
|
||||
select issues.*
|
||||
from test_case_issues, issues
|
||||
where test_case_issues.issues_id = issues.id
|
||||
and test_case_issues.test_case_id = #{caseId}
|
||||
and issues.platform = #{platform}
|
||||
order by issues.create_time DESC
|
||||
from issues
|
||||
inner join test_case_issues
|
||||
on test_case_issues.issues_id = issues.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<select id="getIssuesByProjectId" resultType="io.metersphere.base.domain.IssuesDao">
|
||||
select issues.*
|
||||
from issues
|
||||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
|
||||
<if test="request.projectId != null and request.projectId != ''">
|
||||
and issues.project_id = #{request.projectId}
|
||||
</if>
|
||||
|
||||
<if test="request.testCaseId != null and request.testCaseId != ''">
|
||||
and test_case_issues.test_case_id = #{request.testCaseId}
|
||||
</if>
|
||||
|
||||
<if test="request.platform != null and request.platform != ''">
|
||||
and issues.platform = #{request.platform}
|
||||
</if>
|
||||
|
||||
<!-- <if test="request.ids != null and request.ids.size() > 0">-->
|
||||
<!-- and issues.id in-->
|
||||
<!-- <foreach collection="request.ids" item="id" separator="," open="(" close=")">-->
|
||||
<!-- #{id}-->
|
||||
<!-- </foreach>-->
|
||||
<!-- </if>-->
|
||||
|
||||
|
||||
<!-- <if test="request.filters != null and request.filters.size() > 0">-->
|
||||
<!-- <foreach collection="request.filters.entrySet()" index="key" item="values">-->
|
||||
<!-- <if test="values != null and values.size() > 0">-->
|
||||
<!-- <choose>-->
|
||||
<!-- <when test="key == 'scene'">-->
|
||||
<!-- AND cf.scene IN-->
|
||||
<!-- <foreach collection="values" item="value" separator="," open="(" close=")">-->
|
||||
<!-- #{value}-->
|
||||
<!-- </foreach>-->
|
||||
<!-- </when>-->
|
||||
<!-- </choose>-->
|
||||
<!-- </if>-->
|
||||
<!-- </foreach>-->
|
||||
<!-- </if>-->
|
||||
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -32,6 +32,14 @@ public interface ExtTestCaseMapper {
|
|||
*/
|
||||
List<TestCase> getTestCaseByNotInPlan(@Param("request") QueryTestCaseRequest request);
|
||||
|
||||
/**
|
||||
* 获取不在测试缺陷中的用例
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
List<TestCaseDTO> getTestCaseByNotInIssue(@Param("request") QueryTestCaseRequest request);
|
||||
|
||||
/**
|
||||
* 获取不在评审范围中的用例
|
||||
*
|
||||
|
@ -78,4 +86,6 @@ public interface ExtTestCaseMapper {
|
|||
|
||||
|
||||
List<TestCaseWithBLOBs> listForMinder(@Param("request") QueryTestCaseRequest request);
|
||||
|
||||
List<TestCaseDTO> getTestCaseByIds(@Param("ids")List<String> ids);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,12 @@
|
|||
select test_case.id, test_case.name, test_case.priority, test_case.type, test_case.review_status from test_case
|
||||
as test_case
|
||||
left join test_case_review_test_case as T2 on test_case.id=T2.case_id and T2.review_id =#{request.reviewId}
|
||||
and T2.case_id is null
|
||||
<include refid="notInQueryWhereCondition"></include>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
|
||||
<sql id="notInQueryWhereCondition">
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
|
@ -84,11 +90,15 @@
|
|||
<property name="objectKey" value="request.combine.tags"/>
|
||||
</include>
|
||||
</if>
|
||||
and T2.case_id is null
|
||||
<if test="request.testCaseContainIds != null and request.testCaseContainIds.size() > 0">
|
||||
and test_case.id not in
|
||||
<foreach collection="request.testCaseContainIds" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and test_case.name like CONCAT('%', #{request.name},'%')
|
||||
</if>
|
||||
|
||||
<if test="request.projectId != null">
|
||||
AND test_case.project_id = #{request.projectId}
|
||||
</if>
|
||||
|
@ -100,37 +110,14 @@
|
|||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
</sql>
|
||||
|
||||
<select id="getTestCaseByNotInPlan" resultType="io.metersphere.base.domain.TestCase">
|
||||
select test_case.id, test_case.name, test_case.priority, test_case.type, test_case.review_status from test_case
|
||||
as test_case
|
||||
left join test_plan_test_case as T2 on test_case.id=T2.case_id and T2.plan_id =#{request.planId}
|
||||
<where>
|
||||
<if test="request.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
<property name="name" value="request.name"/>
|
||||
<property name="objectKey" value="request.combine.tags"/>
|
||||
</include>
|
||||
</if>
|
||||
and T2.case_id is null
|
||||
<if test="request.name != null">
|
||||
and test_case.name like CONCAT('%', #{request.name},'%')
|
||||
</if>
|
||||
|
||||
<if test="request.projectId != null">
|
||||
AND test_case.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.nodeIds != null and request.nodeIds.size() > 0">
|
||||
AND test_case.node_id IN
|
||||
<foreach collection="request.nodeIds" open="(" close=")" separator="," item="nodeId">
|
||||
#{nodeId}
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="filters"/>
|
||||
</where>
|
||||
and T2.case_id is null
|
||||
<include refid="notInQueryWhereCondition"></include>
|
||||
ORDER BY test_case.update_time DESC
|
||||
</select>
|
||||
|
||||
|
@ -428,5 +415,21 @@
|
|||
from test_case
|
||||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="getTestCaseByNotInIssue" resultType="io.metersphere.track.dto.TestCaseDTO">
|
||||
select
|
||||
<include refid="io.metersphere.base.mapper.TestCaseMapper.Base_Column_List"/>
|
||||
from test_case
|
||||
<include refid="notInQueryWhereCondition"></include>
|
||||
</select>
|
||||
<select id="getTestCaseByIds" resultType="io.metersphere.track.dto.TestCaseDTO">
|
||||
select
|
||||
<include refid="io.metersphere.base.mapper.TestCaseMapper.Base_Column_List"/>
|
||||
from test_case
|
||||
<where>
|
||||
test_case.id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum IssuesStatus {
|
||||
NEW("new"), CLOSED("closed"), RESOLVED("resolved"), DELETE("delete");
|
||||
private String value;
|
||||
IssuesStatus(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import io.metersphere.commons.utils.PageUtils;
|
|||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.UpdateIssueTemplateRequest;
|
||||
import io.metersphere.dto.IssueTemplateDao;
|
||||
import io.metersphere.service.IssueTemplateService;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
|
@ -48,4 +49,9 @@ public class IssueTemplateController {
|
|||
public List<IssueTemplate> list(@PathVariable String workspaceId) {
|
||||
return issueTemplateService.getOption(workspaceId);
|
||||
}
|
||||
|
||||
@GetMapping("/get/relate/{projectId}")
|
||||
public IssueTemplateDao getTemplate(@PathVariable String projectId) {
|
||||
return issueTemplateService.getTemplate(projectId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
import io.metersphere.base.domain.IssueTemplate;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class IssueTemplateDao extends IssueTemplate {
|
||||
List<CustomFieldDao> customFields;
|
||||
}
|
|
@ -4,13 +4,16 @@ import com.github.pagehelper.Page;
|
|||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.CustomField;
|
||||
import io.metersphere.base.domain.CustomFieldExample;
|
||||
import io.metersphere.base.domain.CustomFieldTemplate;
|
||||
import io.metersphere.base.mapper.CustomFieldMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtCustomFieldMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.controller.request.QueryCustomFieldRequest;
|
||||
import io.metersphere.dto.CustomFieldDao;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -19,10 +22,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -102,6 +102,28 @@ public class CustomFieldService {
|
|||
.andSceneEqualTo(scene);
|
||||
return customFieldMapper.selectByExampleWithBLOBs(example);
|
||||
}
|
||||
|
||||
public List<CustomFieldDao> getCustomFieldByTemplateId(String templateId) {
|
||||
List<CustomFieldTemplate> customFields = customFieldTemplateService.getCustomFields(templateId);
|
||||
List<String> fieldIds = customFields.stream()
|
||||
.map(CustomFieldTemplate::getFieldId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<CustomField> fields = getFieldByIds(fieldIds);
|
||||
Map<String, CustomField> fieldMap = fields.stream()
|
||||
.collect(Collectors.toMap(CustomField::getId, item -> item));
|
||||
|
||||
List<CustomFieldDao> result = new ArrayList<>();
|
||||
customFields.forEach((item) -> {
|
||||
CustomFieldDao customFieldDao = new CustomFieldDao();
|
||||
CustomField customField = fieldMap.get(item.getFieldId());
|
||||
BeanUtils.copyBean(customFieldDao, customField);
|
||||
BeanUtils.copyBean(customFieldDao, item);
|
||||
result.add(customFieldDao);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<CustomField> getFieldByIds(List<String> ids) {
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
CustomFieldExample example = new CustomFieldExample();
|
||||
|
|
|
@ -9,6 +9,8 @@ import io.metersphere.commons.utils.BeanUtils;
|
|||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.UpdateIssueTemplateRequest;
|
||||
import io.metersphere.dto.CustomFieldDao;
|
||||
import io.metersphere.dto.IssueTemplateDao;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -35,6 +37,9 @@ public class IssueTemplateService {
|
|||
@Resource
|
||||
CustomFieldService customFieldService;
|
||||
|
||||
@Resource
|
||||
ProjectService projectService;
|
||||
|
||||
public void add(UpdateIssueTemplateRequest request) {
|
||||
checkExist(request);
|
||||
IssueTemplate template = new IssueTemplate();
|
||||
|
@ -163,4 +168,23 @@ public class IssueTemplateService {
|
|||
issueTemplates.add(getDefaultTemplate(workspaceId));
|
||||
return issueTemplates;
|
||||
}
|
||||
|
||||
public IssueTemplateDao getTemplate(String projectId) {
|
||||
Project project = projectService.getProjectById(projectId);
|
||||
String caseTemplateId = project.getCaseTemplateId();
|
||||
IssueTemplate issueTemplate = null;
|
||||
IssueTemplateDao issueTemplateDao = new IssueTemplateDao();
|
||||
if (StringUtils.isNotBlank(caseTemplateId)) {
|
||||
issueTemplate = issueTemplateMapper.selectByPrimaryKey(caseTemplateId);
|
||||
if (issueTemplate == null) {
|
||||
issueTemplate = getDefaultTemplate(project.getWorkspaceId());
|
||||
}
|
||||
} else {
|
||||
issueTemplate = getDefaultTemplate(project.getWorkspaceId());
|
||||
}
|
||||
BeanUtils.copyBean(issueTemplateDao, issueTemplate);
|
||||
List<CustomFieldDao> result = customFieldService.getCustomFieldByTemplateId(issueTemplate.getId());
|
||||
issueTemplateDao.setCustomFields(result);
|
||||
return issueTemplateDao;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,15 @@ public class ProjectService {
|
|||
return extProjectMapper.getProjectWithWorkspace(request);
|
||||
}
|
||||
|
||||
public List<Project> getProjectByIds(List<String> ids) {
|
||||
if (!CollectionUtils.isEmpty(ids)) {
|
||||
ProjectExample example = new ProjectExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
return projectMapper.selectByExample(example);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void deleteProject(String projectId) {
|
||||
// delete test
|
||||
LoadTestExample loadTestExample = new LoadTestExample();
|
||||
|
|
|
@ -179,27 +179,14 @@ public class TestCaseTemplateService {
|
|||
TestCaseTemplateDao caseTemplateDao = new TestCaseTemplateDao();
|
||||
if (StringUtils.isNotBlank(caseTemplateId)) {
|
||||
caseTemplate = testCaseTemplateMapper.selectByPrimaryKey(caseTemplateId);
|
||||
if (caseTemplate == null) {
|
||||
caseTemplate = getDefaultTemplate(project.getWorkspaceId());
|
||||
}
|
||||
} else {
|
||||
caseTemplate = getDefaultTemplate(project.getWorkspaceId());
|
||||
}
|
||||
BeanUtils.copyBean(caseTemplateDao, caseTemplate);
|
||||
List<CustomFieldTemplate> customFields = customFieldTemplateService.getCustomFields(caseTemplate.getId());
|
||||
List<String> fieldIds = customFields.stream()
|
||||
.map(CustomFieldTemplate::getFieldId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<CustomField> fields = customFieldService.getFieldByIds(fieldIds);
|
||||
Map<String, CustomField> fieldMap = fields.stream()
|
||||
.collect(Collectors.toMap(CustomField::getId, item -> item));
|
||||
|
||||
List<CustomFieldDao> result = new ArrayList<>();
|
||||
customFields.forEach((item) -> {
|
||||
CustomFieldDao customFieldDao = new CustomFieldDao();
|
||||
CustomField customField = fieldMap.get(item.getFieldId());
|
||||
BeanUtils.copyBean(customFieldDao, customField);
|
||||
BeanUtils.copyBean(customFieldDao, item);
|
||||
result.add(customFieldDao);
|
||||
});
|
||||
List<CustomFieldDao> result = customFieldService.getCustomFieldByTemplateId(caseTemplate.getId());
|
||||
caseTemplateDao.setCustomFields(result);
|
||||
return caseTemplateDao;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package io.metersphere.track.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import io.metersphere.track.service.IssuesService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@RequestMapping("issues")
|
||||
@RestController
|
||||
public class IssuesController {
|
||||
|
||||
@Resource
|
||||
private IssuesService issuesService;
|
||||
|
||||
@PostMapping("/list/{goPage}/{pageSize}")
|
||||
public Pager<List<IssuesDao>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody IssuesRequest request) {
|
||||
Page<List<Issues>> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page, issuesService.list(request));
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
public void addIssues(@RequestBody IssuesUpdateRequest issuesRequest) {
|
||||
issuesService.addIssues(issuesRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public void updateIssues(@RequestBody IssuesUpdateRequest issuesRequest) {
|
||||
issuesService.updateIssues(issuesRequest);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{id}")
|
||||
public List<IssuesDao> getIssues(@PathVariable String id) {
|
||||
return issuesService.getIssues(id);
|
||||
}
|
||||
|
||||
@GetMapping("/auth/{platform}")
|
||||
public void testAuth(@PathVariable String platform) {
|
||||
issuesService.testAuth(platform);
|
||||
}
|
||||
|
||||
@GetMapping("/close/{id}")
|
||||
public void closeLocalIssue(@PathVariable String id) {
|
||||
issuesService.closeLocalIssue(id);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public void deleteIssue(@RequestBody IssuesRequest request) {
|
||||
issuesService.deleteIssue(request);
|
||||
}
|
||||
|
||||
@GetMapping("/tapd/user/{caseId}")
|
||||
public List<PlatformUser> getTapdUsers(@PathVariable String caseId) {
|
||||
return issuesService.getTapdProjectUsers(caseId);
|
||||
}
|
||||
|
||||
@GetMapping("/zentao/user/{caseId}")
|
||||
public List<PlatformUser> getZentaoUsers(@PathVariable String caseId) {
|
||||
return issuesService.getZentaoUsers(caseId);
|
||||
}
|
||||
|
||||
@GetMapping("/zentao/builds/{caseId}")
|
||||
public List<ZentaoBuild> getZentaoBuilds(@PathVariable String caseId) {
|
||||
return issuesService.getZentaoBuilds(caseId);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -92,10 +92,16 @@ public class TestCaseController {
|
|||
return testCaseService.getTestCaseByNodeId(nodeIds);
|
||||
}
|
||||
|
||||
@PostMapping("/name/{goPage}/{pageSize}")
|
||||
public Pager<List<TestCase>> getTestCaseNames(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
|
||||
@PostMapping("/relate/{goPage}/{pageSize}")
|
||||
public Pager<List<TestCase>> getTestCaseRelateList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page,testCaseService.getTestCaseNames(request));
|
||||
return PageUtils.setPageInfo(page,testCaseService.getTestCaseRelateList(request));
|
||||
}
|
||||
|
||||
@PostMapping("/relate/issue/{goPage}/{pageSize}")
|
||||
public Pager<List<TestCaseDTO>> getTestCaseIssueRelateList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page,testCaseService.getTestCaseIssueRelateList(request));
|
||||
}
|
||||
|
||||
@PostMapping("/reviews/case/{goPage}/{pageSize}")
|
||||
|
|
|
@ -1,61 +1,25 @@
|
|||
package io.metersphere.track.controller;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.service.IssuesService;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.track.request.issues.IssuesRelevanceRequest;
|
||||
import io.metersphere.track.service.TestCaseIssueService;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@RequestMapping("issues")
|
||||
@RequestMapping("test/case/issues")
|
||||
@RestController
|
||||
public class TestCaseIssuesController {
|
||||
|
||||
@Resource
|
||||
private IssuesService issuesService;
|
||||
private TestCaseIssueService testCaseIssueService;
|
||||
|
||||
@PostMapping("/add")
|
||||
public void addIssues(@RequestBody IssuesRequest issuesRequest) {
|
||||
issuesService.addIssues(issuesRequest);
|
||||
@PostMapping("/list")
|
||||
public List<TestCaseDTO> list(@RequestBody IssuesRelevanceRequest request) {
|
||||
return testCaseIssueService.list(request);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{id}")
|
||||
public List<Issues> getIssues(@PathVariable String id) {
|
||||
return issuesService.getIssues(id);
|
||||
}
|
||||
|
||||
@GetMapping("/auth/{platform}")
|
||||
public void testAuth(@PathVariable String platform) {
|
||||
issuesService.testAuth(platform);
|
||||
}
|
||||
|
||||
@GetMapping("/close/{id}")
|
||||
public void closeLocalIssue(@PathVariable String id) {
|
||||
issuesService.closeLocalIssue(id);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public void deleteIssue(@RequestBody IssuesRequest request) {
|
||||
issuesService.deleteIssue(request);
|
||||
}
|
||||
|
||||
@GetMapping("/tapd/user/{caseId}")
|
||||
public List<PlatformUser> getTapdUsers(@PathVariable String caseId) {
|
||||
return issuesService.getTapdProjectUsers(caseId);
|
||||
}
|
||||
|
||||
@GetMapping("/zentao/user/{caseId}")
|
||||
public List<PlatformUser> getZentaoUsers(@PathVariable String caseId) {
|
||||
return issuesService.getZentaoUsers(caseId);
|
||||
}
|
||||
|
||||
@GetMapping("/zentao/builds/{caseId}")
|
||||
public List<ZentaoBuild> getZentaoBuilds(@PathVariable String caseId) {
|
||||
return issuesService.getZentaoBuilds(caseId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,12 @@ public class TestCaseNodeController {
|
|||
return testCaseNodeService.getAllNodeByPlanId(request);
|
||||
}
|
||||
|
||||
/*模块列表列表*/
|
||||
@PostMapping("/list/project")
|
||||
public List<TestCaseNodeDTO> getAllNodeByProjectId(@RequestBody QueryNodeRequest request) {
|
||||
return testCaseNodeService.getAllNodeByProjectId(request);
|
||||
}
|
||||
|
||||
@PostMapping("/list/all/review")
|
||||
public List<TestCaseNodeDTO> getAllNodeByReviewId(@RequestBody QueryNodeRequest request) {
|
||||
return testCaseNodeService.getAllNodeByReviewId(request);
|
||||
|
|
|
@ -15,6 +15,7 @@ public class TestCaseDTO extends TestCaseWithBLOBs {
|
|||
private String apiName;
|
||||
private String performName;
|
||||
private String lastResultId;
|
||||
private String projectName;
|
||||
|
||||
private List<String> caseTags = new ArrayList<>();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -15,7 +15,7 @@ public class TestCaseReportMetricDTO {
|
|||
private List<TestCaseReportModuleResultDTO> moduleExecuteResult;
|
||||
private FailureTestCasesAdvanceDTO failureTestCases;
|
||||
// private List<TestPlanCaseDTO> failureTestCases;
|
||||
private List<Issues> Issues;
|
||||
private List<IssuesDao> Issues;
|
||||
private List<String> executors;
|
||||
private String principal;
|
||||
private Long startTime;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.base.domain.ServiceIntegration;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.IssuesMapper;
|
||||
import io.metersphere.base.mapper.TestCaseIssuesMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
|
||||
|
@ -14,6 +14,7 @@ import io.metersphere.controller.request.IntegrationRequest;
|
|||
import io.metersphere.service.IntegrationService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import io.metersphere.track.service.TestCaseService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
|
@ -22,10 +23,13 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
|||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class AbstractIssuePlatform implements IssuesPlatform {
|
||||
|
||||
|
@ -41,6 +45,11 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
|
|||
protected RestTemplate restTemplateIgnoreSSL;
|
||||
|
||||
protected String testCaseId;
|
||||
protected String key;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
|
@ -112,4 +121,45 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
|
|||
return StringUtils.isNotBlank(integration.getId());
|
||||
}
|
||||
|
||||
protected void insertTestCaseIssues(String issuesId, String caseId) {
|
||||
if (StringUtils.isNotBlank(caseId)) {
|
||||
TestCaseIssues testCaseIssues = new TestCaseIssues();
|
||||
testCaseIssues.setId(UUID.randomUUID().toString());
|
||||
testCaseIssues.setIssuesId(issuesId);
|
||||
testCaseIssues.setTestCaseId(caseId);
|
||||
testCaseIssuesMapper.insert(testCaseIssues);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleIssueUpdate(IssuesUpdateRequest request) {
|
||||
request.setUpdateTime(System.currentTimeMillis());
|
||||
issuesMapper.updateByPrimaryKeySelective(request);
|
||||
handleTestCaseIssues(request);
|
||||
}
|
||||
|
||||
protected void handleTestCaseIssues(IssuesUpdateRequest issuesRequest) {
|
||||
String issuesId = issuesRequest.getId();
|
||||
if (StringUtils.isNotBlank(issuesRequest.getTestCaseId())) {
|
||||
insertTestCaseIssues(issuesId, issuesRequest.getTestCaseId());
|
||||
} else {
|
||||
List<String> testCaseIds = issuesRequest.getTestCaseIds();
|
||||
TestCaseIssuesExample example = new TestCaseIssuesExample();
|
||||
example.createCriteria().andIssuesIdEqualTo(issuesId);
|
||||
testCaseIssuesMapper.deleteByExample(example);
|
||||
if (!CollectionUtils.isEmpty(testCaseIds)) {
|
||||
testCaseIds.forEach(caseId -> {
|
||||
insertTestCaseIssues(issuesId, caseId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void insertIssuesWithoutContext(String id, IssuesUpdateRequest issuesRequest) {
|
||||
IssuesWithBLOBs issues = new IssuesWithBLOBs();
|
||||
issues.setId(id);
|
||||
issues.setPlatform(issuesRequest.getPlatform());
|
||||
issues.setProjectId(issuesRequest.getProjectId());
|
||||
issues.setCustomFields(issuesRequest.getCustomFields());
|
||||
issuesMapper.insert(issues);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ import io.metersphere.track.request.testcase.IssuesRequest;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IssueFactory {
|
||||
public static AbstractIssuePlatform createPlatform(String platform, IssuesRequest addIssueRequest) {
|
||||
|
@ -15,7 +17,7 @@ public class IssueFactory {
|
|||
return new JiraPlatform(addIssueRequest);
|
||||
} else if (StringUtils.equals(IssuesManagePlatform.Zentao.toString(), platform)) {
|
||||
return new ZentaoPlatform(addIssueRequest);
|
||||
} else if (StringUtils.equals("LOCAL", platform)) {
|
||||
} else if (StringUtils.equalsIgnoreCase(IssuesManagePlatform.Local.toString(), platform)) {
|
||||
return new LocalPlatform(addIssueRequest);
|
||||
}
|
||||
return null;
|
||||
|
@ -31,4 +33,15 @@ public class IssueFactory {
|
|||
});
|
||||
return platforms;
|
||||
}
|
||||
|
||||
public static Map<String, AbstractIssuePlatform> createPlatformsForMap(List<String> types, IssuesRequest addIssueRequest) {
|
||||
Map<String, AbstractIssuePlatform> platformMap = new HashMap<>();
|
||||
types.forEach(type -> {
|
||||
AbstractIssuePlatform abstractIssuePlatform = createPlatform(type, addIssueRequest);
|
||||
if (abstractIssuePlatform != null) {
|
||||
platformMap.put(type, abstractIssuePlatform);
|
||||
}
|
||||
});
|
||||
return platformMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -14,7 +15,13 @@ public interface IssuesPlatform {
|
|||
*
|
||||
* @return platform issues list
|
||||
*/
|
||||
List<Issues> getIssue();
|
||||
List<IssuesDao> getIssue(IssuesRequest request);
|
||||
|
||||
/**
|
||||
* 过滤分页数据
|
||||
* @param issues
|
||||
*/
|
||||
void filter(List<IssuesDao> issues);
|
||||
|
||||
/*获取平台相关需求*/
|
||||
List<DemandDTO> getDemandList(String projectId);
|
||||
|
@ -24,7 +31,13 @@ public interface IssuesPlatform {
|
|||
*
|
||||
* @param issuesRequest issueRequest
|
||||
*/
|
||||
void addIssue(IssuesRequest issuesRequest);
|
||||
void addIssue(IssuesUpdateRequest issuesRequest);
|
||||
|
||||
/**
|
||||
* 更新缺陷
|
||||
* @param request
|
||||
*/
|
||||
void updateIssue(IssuesUpdateRequest request);
|
||||
|
||||
/**
|
||||
* 删除缺陷平台缺陷
|
||||
|
|
|
@ -5,12 +5,14 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.EncryptUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
|
@ -28,40 +30,31 @@ import org.springframework.web.client.RestTemplate;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class JiraPlatform extends AbstractIssuePlatform {
|
||||
|
||||
protected String key = IssuesManagePlatform.Jira.toString();
|
||||
|
||||
public JiraPlatform(IssuesRequest issuesRequest) {
|
||||
super(issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Issues> getIssue() {
|
||||
List<Issues> list = new ArrayList<>();
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
|
||||
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
|
||||
JSONObject object = JSON.parseObject(config);
|
||||
|
||||
if (object == null) {
|
||||
MSException.throwException("tapd config is null");
|
||||
}
|
||||
|
||||
String account = object.getString("account");
|
||||
String password = object.getString("password");
|
||||
HttpHeaders headers = getAuthHeader(object);
|
||||
String url = object.getString("url");
|
||||
HttpHeaders headers = auth(account, password);
|
||||
|
||||
TestCaseIssuesExample example = new TestCaseIssuesExample();
|
||||
example.createCriteria().andTestCaseIdEqualTo(testCaseId);
|
||||
|
||||
List<Issues> issues = extIssuesMapper.getIssues(testCaseId, IssuesManagePlatform.Jira.toString());
|
||||
|
||||
List<String> issuesIds = issues.stream().map(Issues::getId).collect(Collectors.toList());
|
||||
issuesIds.forEach(issuesId -> {
|
||||
Issues dto = getJiraIssues(headers, url, issuesId);
|
||||
IssuesDao dto = getJiraIssues(headers, url, issuesId);
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 缺陷不存在,解除用例和缺陷的关联
|
||||
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
|
@ -80,6 +73,37 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
return list;
|
||||
}
|
||||
|
||||
public HttpHeaders getAuthHeader(JSONObject object) {
|
||||
if (object == null) {
|
||||
MSException.throwException("tapd config is null");
|
||||
}
|
||||
|
||||
String account = object.getString("account");
|
||||
String password = object.getString("password");
|
||||
return auth(account, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(List<IssuesDao> issues) {
|
||||
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
|
||||
JSONObject object = JSON.parseObject(config);
|
||||
HttpHeaders headers = getAuthHeader(object);
|
||||
String url = object.getString("url");
|
||||
|
||||
issues.forEach((issuesDao) -> {
|
||||
IssuesDao dto = getJiraIssues(headers, url, issuesDao.getId());
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 标记成删除
|
||||
issuesDao.setStatus(IssuesStatus.DELETE.toString());
|
||||
} else {
|
||||
// 缺陷状态为 完成,则不显示
|
||||
if (!StringUtils.equals("done", dto.getStatus())) {
|
||||
issuesDao.setStatus(IssuesStatus.RESOLVED.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DemandDTO> getDemandList(String projectId) {
|
||||
List<DemandDTO> list = new ArrayList<>();
|
||||
|
@ -134,8 +158,9 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addIssue(IssuesRequest issuesRequest) {
|
||||
public void addIssue(IssuesUpdateRequest issuesRequest) {
|
||||
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
JSONObject object = JSON.parseObject(config);
|
||||
|
||||
if (object == null) {
|
||||
|
@ -151,7 +176,6 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
String auth = EncryptUtils.base64Encoding(account + ":" + password);
|
||||
|
||||
String testCaseId = issuesRequest.getTestCaseId();
|
||||
String jiraKey = getProjectId(null);
|
||||
|
||||
|
||||
|
@ -159,7 +183,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
MSException.throwException("未关联Jira 项目Key");
|
||||
}
|
||||
|
||||
String content = issuesRequest.getContent();
|
||||
String content = issuesRequest.getDescription();
|
||||
|
||||
Document document = Jsoup.parse(content);
|
||||
document.outputSettings(new Document.OutputSettings().prettyPrint(false));
|
||||
|
@ -187,18 +211,19 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
JSONObject jsonObject = JSON.parseObject(result);
|
||||
String id = jsonObject.getString("key");
|
||||
|
||||
issuesRequest.setId(id);
|
||||
// 用例与第三方缺陷平台中的缺陷关联
|
||||
TestCaseIssues testCaseIssues = new TestCaseIssues();
|
||||
testCaseIssues.setId(UUID.randomUUID().toString());
|
||||
testCaseIssues.setIssuesId(id);
|
||||
testCaseIssues.setTestCaseId(testCaseId);
|
||||
testCaseIssuesMapper.insert(testCaseIssues);
|
||||
handleTestCaseIssues(issuesRequest);
|
||||
|
||||
// 插入缺陷表
|
||||
Issues issues = new Issues();
|
||||
issues.setId(id);
|
||||
issues.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
issuesMapper.insert(issues);
|
||||
insertIssuesWithoutContext(id, issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIssue(IssuesUpdateRequest request) {
|
||||
// todo 调用接口
|
||||
request.setDescription(null);
|
||||
handleIssueUpdate(request);
|
||||
}
|
||||
|
||||
private String addJiraIssue(String url, String auth, String json) {
|
||||
|
@ -258,12 +283,12 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
return project.getJiraKey();
|
||||
}
|
||||
|
||||
private Issues getJiraIssues(HttpHeaders headers, String url, String issuesId) {
|
||||
private IssuesDao getJiraIssues(HttpHeaders headers, String url, String issuesId) {
|
||||
HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(headers);
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
//post
|
||||
ResponseEntity<String> responseEntity;
|
||||
Issues issues = new Issues();
|
||||
IssuesDao issues = new IssuesDao();
|
||||
try {
|
||||
responseEntity = restTemplate.exchange(url + "/rest/api/2/issue/" + issuesId, HttpMethod.GET, requestEntity, String.class);
|
||||
String body = responseEntity.getBody();
|
||||
|
@ -307,7 +332,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
issues.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
} catch (HttpClientErrorException.NotFound e) {
|
||||
LogUtil.error(e.getStackTrace(), e);
|
||||
return new Issues();
|
||||
return new IssuesDao();
|
||||
} catch (HttpClientErrorException.Unauthorized e) {
|
||||
LogUtil.error(e.getStackTrace(), e);
|
||||
MSException.throwException("获取Jira缺陷失败,检查Jira配置信息");
|
||||
|
|
|
@ -1,26 +1,35 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.TestCaseIssues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.base.domain.IssuesWithBLOBs;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LocalPlatform extends AbstractIssuePlatform {
|
||||
|
||||
protected String key = IssuesManagePlatform.Local.toString();
|
||||
|
||||
public LocalPlatform(IssuesRequest issuesRequest) {
|
||||
super(issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Issues> getIssue() {
|
||||
return extIssuesMapper.getIssues(testCaseId, IssuesManagePlatform.Local.toString());
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Local.toString());
|
||||
return extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(List<IssuesDao> issues) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,25 +38,26 @@ public class LocalPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addIssue(IssuesRequest issuesRequest) {
|
||||
public void addIssue(IssuesUpdateRequest issuesRequest) {
|
||||
SessionUser user = SessionUtils.getUser();
|
||||
String id = UUID.randomUUID().toString();
|
||||
Issues issues = new Issues();
|
||||
IssuesWithBLOBs issues = new IssuesWithBLOBs();
|
||||
BeanUtils.copyBean(issues, issuesRequest);
|
||||
issues.setId(id);
|
||||
issues.setStatus("new");
|
||||
issues.setReporter(user.getId());
|
||||
issues.setTitle(issuesRequest.getTitle());
|
||||
issues.setDescription(issuesRequest.getContent());
|
||||
issues.setCreateTime(System.currentTimeMillis());
|
||||
issues.setUpdateTime(System.currentTimeMillis());
|
||||
issues.setPlatform(IssuesManagePlatform.Local.toString());
|
||||
issues.setPlatform(IssuesManagePlatform.Local.toString());;
|
||||
issuesMapper.insert(issues);
|
||||
|
||||
TestCaseIssues testCaseIssues = new TestCaseIssues();
|
||||
testCaseIssues.setId(UUID.randomUUID().toString());
|
||||
testCaseIssues.setIssuesId(id);
|
||||
testCaseIssues.setTestCaseId(issuesRequest.getTestCaseId());
|
||||
testCaseIssuesMapper.insert(testCaseIssues);
|
||||
issuesRequest.setId(id);
|
||||
handleTestCaseIssues(issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIssue(IssuesUpdateRequest request) {
|
||||
handleIssueUpdate(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +81,7 @@ public class LocalPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
public void closeIssue(String issueId) {
|
||||
Issues issues = new Issues();
|
||||
IssuesWithBLOBs issues = new IssuesWithBLOBs();
|
||||
issues.setId(issueId);
|
||||
issues.setStatus("closed");
|
||||
issuesMapper.updateByPrimaryKeySelective(issues);
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
|
@ -12,6 +13,7 @@ import io.metersphere.controller.ResultHolder;
|
|||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
@ -23,29 +25,30 @@ import org.springframework.web.client.RestTemplate;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TapdPlatform extends AbstractIssuePlatform {
|
||||
|
||||
protected String key = IssuesManagePlatform.Tapd.toString();
|
||||
|
||||
public TapdPlatform(IssuesRequest issueRequest) {
|
||||
super(issueRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Issues> getIssue() {
|
||||
List<Issues> list = new ArrayList<>();
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
String tapdId = getProjectId("");
|
||||
|
||||
TestCaseIssuesExample example = new TestCaseIssuesExample();
|
||||
example.createCriteria().andTestCaseIdEqualTo(testCaseId);
|
||||
|
||||
List<Issues> issues = extIssuesMapper.getIssues(testCaseId, IssuesManagePlatform.Tapd.toString());
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
|
||||
List<String> issuesIds = issues.stream().map(Issues::getId).collect(Collectors.toList());
|
||||
issuesIds.forEach(issuesId -> {
|
||||
Issues dto = getTapdIssues(tapdId, issuesId);
|
||||
IssuesDao dto = getTapdIssues(tapdId, issuesId);
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 缺陷不存在,解除用例和缺陷的关联
|
||||
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
|
@ -57,7 +60,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
} else {
|
||||
dto.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
// 缺陷状态为 关闭,则不显示
|
||||
if (!StringUtils.equals("closed", dto.getStatus())) {
|
||||
if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
|
||||
list.add(dto);
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +68,30 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(List<IssuesDao> issues) {
|
||||
String tapdId = "";
|
||||
for (IssuesDao item : issues) {
|
||||
if (StringUtils.isNotBlank(item.getProjectId())) {
|
||||
tapdId = getProjectId(issues.get(0).getProjectId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (IssuesDao item : issues) {
|
||||
IssuesDao dto = getTapdIssues(tapdId, item.getId());
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 标记成删除
|
||||
item.setStatus(IssuesStatus.DELETE.toString());
|
||||
} else {
|
||||
// 缺陷状态为 完成,则不显示
|
||||
if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
|
||||
item.setStatus(IssuesStatus.CLOSED.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DemandDTO> getDemandList(String projectId) {
|
||||
List<DemandDTO> demandList = new ArrayList<>();
|
||||
|
@ -86,17 +113,17 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
return demandList;
|
||||
}
|
||||
|
||||
private Issues getTapdIssues(String projectId, String issuesId) {
|
||||
private IssuesDao getTapdIssues(String projectId, String issuesId) {
|
||||
String url = "https://api.tapd.cn/bugs?workspace_id=" + projectId + "&id=" + issuesId;
|
||||
ResultHolder call = call(url);
|
||||
String listJson = JSON.toJSONString(call.getData());
|
||||
if (StringUtils.equals(Boolean.FALSE.toString(), listJson)) {
|
||||
return new Issues();
|
||||
return new IssuesDao();
|
||||
}
|
||||
JSONObject jsonObject = JSONObject.parseObject(listJson);
|
||||
JSONObject bug = jsonObject.getJSONObject("Bug");
|
||||
Long created = bug.getLong("created");
|
||||
Issues issues = jsonObject.getObject("Bug", Issues.class);
|
||||
IssuesDao issues = jsonObject.getObject("Bug", IssuesDao.class);
|
||||
|
||||
// 获取工作流中缺陷状态名称
|
||||
String workflow = "https://api.tapd.cn/workflows/status_map?workspace_id=" + projectId + "&system=bug";
|
||||
|
@ -112,7 +139,9 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addIssue(IssuesRequest issuesRequest) {
|
||||
public void addIssue(IssuesUpdateRequest issuesRequest) {
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
|
||||
String url = "https://api.tapd.cn/bugs";
|
||||
String testCaseId = issuesRequest.getTestCaseId();
|
||||
String tapdId = getProjectId("");
|
||||
|
@ -129,7 +158,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("title", issuesRequest.getTitle());
|
||||
paramMap.add("workspace_id", tapdId);
|
||||
paramMap.add("description", issuesRequest.getContent());
|
||||
paramMap.add("description", issuesRequest.getDescription());
|
||||
paramMap.add("reporter", username);
|
||||
paramMap.add("current_owner", usersStr);
|
||||
|
||||
|
@ -139,18 +168,19 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
JSONObject jsonObject = JSONObject.parseObject(listJson);
|
||||
String issuesId = jsonObject.getObject("Bug", Issues.class).getId();
|
||||
|
||||
issuesRequest.setId(issuesId);
|
||||
// 用例与第三方缺陷平台中的缺陷关联
|
||||
TestCaseIssues testCaseIssues = new TestCaseIssues();
|
||||
testCaseIssues.setId(UUID.randomUUID().toString());
|
||||
testCaseIssues.setIssuesId(issuesId);
|
||||
testCaseIssues.setTestCaseId(testCaseId);
|
||||
testCaseIssuesMapper.insert(testCaseIssues);
|
||||
handleTestCaseIssues(issuesRequest);
|
||||
|
||||
// 插入缺陷表
|
||||
Issues issues = new Issues();
|
||||
issues.setId(issuesId);
|
||||
issues.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
issuesMapper.insert(issues);
|
||||
insertIssuesWithoutContext(issuesId, issuesRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIssue(IssuesUpdateRequest request) {
|
||||
// todo 调用接口
|
||||
request.setDescription(null);
|
||||
handleIssueUpdate(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,12 +5,14 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
@ -38,6 +40,8 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
*/
|
||||
private final String url;
|
||||
|
||||
protected String key = IssuesManagePlatform.Zentao.toString();
|
||||
|
||||
public ZentaoPlatform(IssuesRequest issuesRequest) {
|
||||
super(issuesRequest);
|
||||
String config = getPlatformConfig(IssuesManagePlatform.Zentao.toString());
|
||||
|
@ -58,17 +62,19 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Issues> getIssue() {
|
||||
List<Issues> list = new ArrayList<>();
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
|
||||
TestCaseIssuesExample example = new TestCaseIssuesExample();
|
||||
example.createCriteria().andTestCaseIdEqualTo(testCaseId);
|
||||
|
||||
List<Issues> issues = extIssuesMapper.getIssues(testCaseId, IssuesManagePlatform.Zentao.toString());
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Zentao.toString());
|
||||
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
|
||||
List<String> issuesIds = issues.stream().map(Issues::getId).collect(Collectors.toList());
|
||||
issuesIds.forEach(issuesId -> {
|
||||
Issues dto = getZentaoIssues(issuesId);
|
||||
IssuesDao dto = getZentaoIssues(issuesId);
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 缺陷不存在,解除用例和缺陷的关联
|
||||
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
|
@ -89,6 +95,22 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(List<IssuesDao> issues) {
|
||||
issues.forEach((issuesDao) -> {
|
||||
IssuesDao dto = getZentaoIssues(issuesDao.getId());
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 标记成删除
|
||||
issuesDao.setStatus(IssuesStatus.DELETE.toString());
|
||||
} else {
|
||||
// 缺陷状态为 完成,则不显示
|
||||
if (!StringUtils.equals("done", dto.getStatus())) {
|
||||
issuesDao.setStatus(IssuesStatus.RESOLVED.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DemandDTO> getDemandList(String projectId) {
|
||||
//getTestStories
|
||||
|
@ -126,7 +148,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
return list;
|
||||
}
|
||||
|
||||
private Issues getZentaoIssues(String bugId) {
|
||||
private IssuesDao getZentaoIssues(String bugId) {
|
||||
String session = login();
|
||||
HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(new HttpHeaders());
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
@ -148,9 +170,9 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
String reporter = bug.getString("openedBy");
|
||||
int deleted = bug.getInteger("deleted");
|
||||
if (deleted == 1) {
|
||||
return new Issues();
|
||||
return new IssuesDao();
|
||||
}
|
||||
Issues issues = new Issues();
|
||||
IssuesDao issues = new IssuesDao();
|
||||
issues.setId(id);
|
||||
issues.setTitle(title);
|
||||
issues.setDescription(description);
|
||||
|
@ -163,11 +185,12 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
LogUtil.error("get zentao bug fail " + e.getMessage());
|
||||
}
|
||||
|
||||
return new Issues();
|
||||
return new IssuesDao();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIssue(IssuesRequest issuesRequest) {
|
||||
public void addIssue(IssuesUpdateRequest issuesRequest) {
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Zentao.toString());
|
||||
|
||||
String session = login();
|
||||
String projectId = getProjectId(null);
|
||||
|
@ -183,7 +206,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("product", projectId);
|
||||
paramMap.add("title", issuesRequest.getTitle());
|
||||
paramMap.add("steps", issuesRequest.getContent());
|
||||
paramMap.add("steps", issuesRequest.getDescription());
|
||||
if (!CollectionUtils.isEmpty(issuesRequest.getZentaoBuilds())) {
|
||||
List<String> builds = issuesRequest.getZentaoBuilds();
|
||||
builds.forEach(build -> {
|
||||
|
@ -208,27 +231,28 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
JSONObject data = obj.getJSONObject("data");
|
||||
String id = data.getString("id");
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
issuesRequest.setId(id);
|
||||
// 用例与第三方缺陷平台中的缺陷关联
|
||||
TestCaseIssues testCaseIssues = new TestCaseIssues();
|
||||
testCaseIssues.setId(UUID.randomUUID().toString());
|
||||
testCaseIssues.setIssuesId(id);
|
||||
testCaseIssues.setTestCaseId(testCaseId);
|
||||
testCaseIssuesMapper.insert(testCaseIssues);
|
||||
handleTestCaseIssues(issuesRequest);
|
||||
|
||||
IssuesExample issuesExample = new IssuesExample();
|
||||
issuesExample.createCriteria().andIdEqualTo(id)
|
||||
.andPlatformEqualTo(IssuesManagePlatform.Zentao.toString());
|
||||
if (issuesMapper.selectByExample(issuesExample).size() <= 0) {
|
||||
// 插入缺陷表
|
||||
Issues issues = new Issues();
|
||||
issues.setId(id);
|
||||
issues.setPlatform(IssuesManagePlatform.Zentao.toString());
|
||||
issuesMapper.insert(issues);
|
||||
insertIssuesWithoutContext(id, issuesRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIssue(IssuesUpdateRequest request) {
|
||||
// todo 调用接口
|
||||
request.setDescription(null);
|
||||
handleIssueUpdate(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteIssue(String id) {
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.track.request.issues;
|
||||
|
||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class IssuesRelevanceRequest {
|
||||
/**
|
||||
* 缺陷ID
|
||||
*/
|
||||
private String issuesId;
|
||||
|
||||
/**
|
||||
* 当选择关联全部用例时把加载条件送到后台,从后台查询
|
||||
*/
|
||||
private QueryTestCaseRequest request;
|
||||
|
||||
/**
|
||||
* 具体要关联的用例
|
||||
*/
|
||||
private List<String> testCaseIds = new ArrayList<>();
|
||||
|
||||
private Boolean checked;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -7,7 +8,7 @@ import java.util.List;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class IssuesRequest {
|
||||
public class IssuesRequest extends BaseQueryRequest {
|
||||
private String title;
|
||||
private String content;
|
||||
private String projectId;
|
||||
|
@ -27,4 +28,7 @@ public class IssuesRequest {
|
|||
*/
|
||||
private String id;
|
||||
private String caseId;
|
||||
private String platform;
|
||||
private String customFields;
|
||||
private List<String> testCaseIds;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.base.domain.IssuesWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class IssuesUpdateRequest extends IssuesWithBLOBs {
|
||||
private String content;
|
||||
private String testCaseId;
|
||||
private List<String> tapdUsers;
|
||||
/**
|
||||
* zentao bug 处理人
|
||||
*/
|
||||
private String zentaoUser;
|
||||
/**
|
||||
* zentao bug 影响版本
|
||||
*/
|
||||
private List<String> zentaoBuilds;
|
||||
private List<String> testCaseIds;
|
||||
}
|
|
@ -19,6 +19,8 @@ public class QueryTestCaseRequest extends BaseQueryRequest {
|
|||
|
||||
private String planId;
|
||||
|
||||
private String issuesId;
|
||||
|
||||
private String userId;
|
||||
|
||||
private String reviewId;
|
||||
|
@ -30,4 +32,5 @@ public class QueryTestCaseRequest extends BaseQueryRequest {
|
|||
|
||||
private long createTime = 0;
|
||||
private long relevanceCreateTime = 0;
|
||||
private List<String> testCaseContainIds;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package io.metersphere.track.service;
|
|||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.IssuesMapper;
|
||||
import io.metersphere.base.mapper.TestCaseIssuesMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.NoticeConstants;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.IntegrationRequest;
|
||||
import io.metersphere.i18n.Translator;
|
||||
|
@ -13,11 +15,17 @@ import io.metersphere.notice.sender.NoticeModel;
|
|||
import io.metersphere.notice.service.NoticeSendService;
|
||||
import io.metersphere.service.IntegrationService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.track.issue.*;
|
||||
import io.metersphere.track.issue.AbstractIssuePlatform;
|
||||
import io.metersphere.track.issue.IssueFactory;
|
||||
import io.metersphere.track.issue.ZentaoPlatform;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.ZentaoBuild;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
@ -35,6 +43,7 @@ public class IssuesService {
|
|||
private IntegrationService integrationService;
|
||||
@Resource
|
||||
private ProjectService projectService;
|
||||
@Lazy
|
||||
@Resource
|
||||
private TestCaseService testCaseService;
|
||||
@Resource
|
||||
|
@ -43,53 +52,27 @@ public class IssuesService {
|
|||
private NoticeSendService noticeSendService;
|
||||
@Resource
|
||||
private TestCaseIssuesMapper testCaseIssuesMapper;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
@Resource
|
||||
private ExtIssuesMapper extIssuesMapper;
|
||||
|
||||
public void testAuth(String platform) {
|
||||
AbstractIssuePlatform abstractPlatform = IssueFactory.createPlatform(platform, new IssuesRequest());
|
||||
abstractPlatform.testAuth();
|
||||
}
|
||||
|
||||
public void addIssues(IssuesRequest issuesRequest) {
|
||||
SessionUser user = SessionUtils.getUser();
|
||||
String orgId = user.getLastOrganizationId();
|
||||
|
||||
boolean tapd = isIntegratedPlatform(orgId, IssuesManagePlatform.Tapd.toString());
|
||||
boolean jira = isIntegratedPlatform(orgId, IssuesManagePlatform.Jira.toString());
|
||||
boolean zentao = isIntegratedPlatform(orgId, IssuesManagePlatform.Zentao.toString());
|
||||
|
||||
String tapdId = getTapdProjectId(issuesRequest.getTestCaseId());
|
||||
String jiraKey = getJiraProjectKey(issuesRequest.getTestCaseId());
|
||||
String zentaoId = getZentaoProjectId(issuesRequest.getTestCaseId());
|
||||
|
||||
List<String> platforms = new ArrayList<>();
|
||||
|
||||
if (tapd) {
|
||||
// 是否关联了项目
|
||||
if (StringUtils.isNotBlank(tapdId)) {
|
||||
platforms.add(IssuesManagePlatform.Tapd.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (jira) {
|
||||
if (StringUtils.isNotBlank(jiraKey)) {
|
||||
platforms.add(IssuesManagePlatform.Jira.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (zentao) {
|
||||
if (StringUtils.isNotBlank(zentaoId)) {
|
||||
platforms.add(IssuesManagePlatform.Zentao.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(tapdId) && StringUtils.isBlank(jiraKey) && StringUtils.isBlank(zentaoId)) {
|
||||
platforms.add("LOCAL");
|
||||
}
|
||||
|
||||
List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, issuesRequest);
|
||||
public void addIssues(IssuesUpdateRequest issuesRequest) {
|
||||
List<AbstractIssuePlatform> platformList = getUpdatePlatforms(issuesRequest);
|
||||
platformList.forEach(platform -> {
|
||||
platform.addIssue(issuesRequest);
|
||||
});
|
||||
noticeIssueEven(issuesRequest, "IssuesCreate");
|
||||
}
|
||||
|
||||
public void noticeIssueEven(IssuesUpdateRequest issuesRequest, String type) {
|
||||
SessionUser user = SessionUtils.getUser();
|
||||
String orgId = user.getLastOrganizationId();
|
||||
List<String> userIds = new ArrayList<>();
|
||||
userIds.add(orgId);
|
||||
String context = getIssuesContext(user, issuesRequest, NoticeConstants.Event.CREATE);
|
||||
|
@ -100,18 +83,75 @@ public class IssuesService {
|
|||
.context(context)
|
||||
.relatedUsers(userIds)
|
||||
.subject(Translator.get("task_defect_notification"))
|
||||
.mailTemplate("IssuesCreate")
|
||||
.mailTemplate(type)
|
||||
.paramMap(paramMap)
|
||||
.event(NoticeConstants.Event.CREATE)
|
||||
.build();
|
||||
noticeSendService.send(NoticeConstants.TaskType.DEFECT_TASK, noticeModel);
|
||||
}
|
||||
|
||||
public List<Issues> getIssues(String caseId) {
|
||||
List<Issues> list = new ArrayList<>();
|
||||
|
||||
public void updateIssues(IssuesUpdateRequest issuesRequest) {
|
||||
List<AbstractIssuePlatform> platformList = getUpdatePlatforms(issuesRequest);
|
||||
platformList.forEach(platform -> {
|
||||
platform.updateIssue(issuesRequest);
|
||||
});
|
||||
// todo 缺陷更新事件?
|
||||
}
|
||||
|
||||
public List<AbstractIssuePlatform> getUpdatePlatforms(IssuesUpdateRequest updateRequest) {
|
||||
List<String> platforms = null;
|
||||
if (StringUtils.isNotBlank(updateRequest.getTestCaseId())) {
|
||||
// 测试计划关联
|
||||
platforms = getPlatformsByCaseId(updateRequest.getTestCaseId());
|
||||
} else {
|
||||
// 缺陷管理关联
|
||||
platforms = getPlatformsByProjectId(updateRequest.getProjectId());
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(platforms)) {
|
||||
platforms.add("LOCAL");
|
||||
}
|
||||
IssuesRequest issuesRequest = new IssuesRequest();
|
||||
issuesRequest.setTestCaseId(updateRequest.getTestCaseId());
|
||||
return IssueFactory.createPlatforms(platforms, issuesRequest);
|
||||
}
|
||||
|
||||
public List<IssuesDao> getIssues(String caseId) {
|
||||
IssuesRequest issueRequest = new IssuesRequest();
|
||||
issueRequest.setTestCaseId(caseId);
|
||||
ServiceUtils.getDefaultOrder(issueRequest.getOrders());
|
||||
Project project = getProjectByCaseId(caseId);
|
||||
return getIssuesByProject(issueRequest, project);
|
||||
}
|
||||
public List<IssuesDao> getIssuesByProject(IssuesRequest issueRequest, Project project) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
List<String> platforms = getPlatforms(project);
|
||||
platforms.add(IssuesManagePlatform.Local.toString());
|
||||
List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, issueRequest);
|
||||
platformList.forEach(platform -> {
|
||||
List<IssuesDao> issue = platform.getIssue(issueRequest);
|
||||
list.addAll(issue);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> getPlatformsByProjectId(String projectId) {
|
||||
return getPlatforms(projectService.getProjectById(projectId));
|
||||
}
|
||||
|
||||
public List<String> getPlatformsByCaseId(String caseId) {
|
||||
TestCaseWithBLOBs testCase = testCaseService.getTestCase(caseId);
|
||||
Project project = projectService.getProjectById(testCase.getProjectId());
|
||||
List<String> platforms = getPlatforms(project);
|
||||
platforms.add("LOCAL");
|
||||
return getPlatforms(project);
|
||||
}
|
||||
|
||||
public List<String> getPlatforms(Project project) {
|
||||
SessionUser user = SessionUtils.getUser();
|
||||
String orgId = user.getLastOrganizationId();
|
||||
|
||||
boolean tapd = isIntegratedPlatform(orgId, IssuesManagePlatform.Tapd.toString());
|
||||
boolean jira = isIntegratedPlatform(orgId, IssuesManagePlatform.Jira.toString());
|
||||
boolean zentao = isIntegratedPlatform(orgId, IssuesManagePlatform.Zentao.toString());
|
||||
|
@ -119,7 +159,7 @@ public class IssuesService {
|
|||
List<String> platforms = new ArrayList<>();
|
||||
if (tapd) {
|
||||
// 是否关联了项目
|
||||
String tapdId = getTapdProjectId(caseId);
|
||||
String tapdId = project.getTapdId();
|
||||
if (StringUtils.isNotBlank(tapdId)) {
|
||||
platforms.add(IssuesManagePlatform.Tapd.name());
|
||||
}
|
||||
|
@ -127,29 +167,25 @@ public class IssuesService {
|
|||
}
|
||||
|
||||
if (jira) {
|
||||
String jiraKey = getJiraProjectKey(caseId);
|
||||
String jiraKey = project.getJiraKey();
|
||||
if (StringUtils.isNotBlank(jiraKey)) {
|
||||
platforms.add(IssuesManagePlatform.Jira.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (zentao) {
|
||||
String zentaoId = getZentaoProjectId(caseId);
|
||||
String zentaoId = project.getZentaoId();
|
||||
if (StringUtils.isNotBlank(zentaoId)) {
|
||||
platforms.add(IssuesManagePlatform.Zentao.name());
|
||||
}
|
||||
}
|
||||
return platforms;
|
||||
}
|
||||
|
||||
platforms.add("LOCAL");
|
||||
IssuesRequest issueRequest = new IssuesRequest();
|
||||
issueRequest.setTestCaseId(caseId);
|
||||
List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, issueRequest);
|
||||
platformList.forEach(platform -> {
|
||||
List<Issues> issue = platform.getIssue();
|
||||
list.addAll(issue);
|
||||
});
|
||||
|
||||
return list;
|
||||
private Project getProjectByCaseId(String testCaseId) {
|
||||
TestCaseWithBLOBs testCase = testCaseService.getTestCase(testCaseId);
|
||||
Project project = projectService.getProjectById(testCase.getProjectId());
|
||||
return project;
|
||||
}
|
||||
|
||||
private String getTapdProjectId(String testCaseId) {
|
||||
|
@ -182,7 +218,7 @@ public class IssuesService {
|
|||
}
|
||||
|
||||
public void closeLocalIssue(String issueId) {
|
||||
Issues issues = new Issues();
|
||||
IssuesWithBLOBs issues = new IssuesWithBLOBs();
|
||||
issues.setId(issueId);
|
||||
issues.setStatus("closed");
|
||||
issuesMapper.updateByPrimaryKeySelective(issues);
|
||||
|
@ -212,7 +248,7 @@ public class IssuesService {
|
|||
testCaseIssuesMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
private static String getIssuesContext(SessionUser user, IssuesRequest issuesRequest, String type) {
|
||||
private static String getIssuesContext(SessionUser user, IssuesUpdateRequest issuesRequest, String type) {
|
||||
String context = "";
|
||||
if (StringUtils.equals(NoticeConstants.Event.CREATE, type)) {
|
||||
context = "缺陷任务通知:" + user.getName() + "发起了一个缺陷" + "'" + issuesRequest.getTitle() + "'" + "请跟进";
|
||||
|
@ -226,4 +262,41 @@ public class IssuesService {
|
|||
ZentaoPlatform platform = (ZentaoPlatform) IssueFactory.createPlatform(IssuesManagePlatform.Zentao.name(), issueRequest);
|
||||
return platform.getBuilds();
|
||||
}
|
||||
|
||||
public List<IssuesDao> list(IssuesRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByProjectId(request);
|
||||
Map<String, List<IssuesDao>> issueMap = getIssueMap(issues);
|
||||
Map<String, AbstractIssuePlatform> platformMap = getPlatformMap(request);
|
||||
issueMap.forEach((platformName, data) -> {
|
||||
AbstractIssuePlatform platform = platformMap.get(platformName);
|
||||
platform.filter(data);
|
||||
});
|
||||
return issues;
|
||||
}
|
||||
|
||||
public Map<String, List<IssuesDao>> getIssueMap(List<IssuesDao> issues) {
|
||||
Map<String, List<IssuesDao>> issueMap = new HashMap<>();
|
||||
issues.forEach(item -> {
|
||||
String platForm = item.getPlatform();
|
||||
if (StringUtils.equalsIgnoreCase(IssuesManagePlatform.Local.toString(), item.getPlatform())) {
|
||||
// 可能有大小写的问题
|
||||
platForm = IssuesManagePlatform.Local.toString();
|
||||
}
|
||||
List<IssuesDao> issuesDao = issueMap.get(platForm);
|
||||
if (issuesDao == null) {
|
||||
issuesDao = new ArrayList<>();
|
||||
}
|
||||
issuesDao.add(item);
|
||||
issueMap.put(platForm, issuesDao);
|
||||
});
|
||||
return issueMap;
|
||||
}
|
||||
|
||||
public Map<String, AbstractIssuePlatform> getPlatformMap(IssuesRequest request) {
|
||||
Project project = projectService.getProjectById(request.getProjectId());
|
||||
List<String> platforms = getPlatforms(project);
|
||||
platforms.add(IssuesManagePlatform.Local.toString());
|
||||
return IssueFactory.createPlatformsForMap(platforms, request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import io.metersphere.base.domain.TestCaseIssues;
|
|||
import io.metersphere.base.domain.TestCaseIssuesExample;
|
||||
import io.metersphere.base.mapper.IssuesMapper;
|
||||
import io.metersphere.base.mapper.TestCaseIssuesMapper;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.track.request.issues.IssuesRelevanceRequest;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -18,6 +21,9 @@ public class TestCaseIssueService {
|
|||
|
||||
@Resource
|
||||
private TestCaseIssuesMapper testCaseIssuesMapper;
|
||||
@Lazy
|
||||
@Resource
|
||||
private TestCaseService testCaseService;
|
||||
@Resource
|
||||
private IssuesMapper issuesMapper;
|
||||
|
||||
|
@ -33,4 +39,23 @@ public class TestCaseIssueService {
|
|||
}
|
||||
testCaseIssuesMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
public List<TestCaseDTO> list(IssuesRelevanceRequest request) {
|
||||
List<String> testCaseIds = getTestCaseIdsByIssuesId(request.getIssuesId());
|
||||
List<TestCaseDTO> list = testCaseService.getTestCaseByIds(testCaseIds);
|
||||
testCaseService.addProjectName(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<TestCaseIssues> getTestCaseIssuesByIssuesId(String issuesId) {
|
||||
TestCaseIssuesExample example = new TestCaseIssuesExample();
|
||||
example.createCriteria().andIssuesIdEqualTo(issuesId);
|
||||
return testCaseIssuesMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public List<String> getTestCaseIdsByIssuesId(String issuesId) {
|
||||
return getTestCaseIssuesByIssuesId(issuesId).stream()
|
||||
.map(TestCaseIssues::getTestCaseId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -337,13 +337,15 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
|
||||
public List<TestCaseNodeDTO> getAllNodeByPlanId(QueryNodeRequest request) {
|
||||
String planId = request.getTestPlanId();
|
||||
String projectId = request.getProjectId();
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
if (testPlan == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return getAllNodeByProjectId(request);
|
||||
}
|
||||
|
||||
return getNodeTreeByProjectId(projectId);
|
||||
public List<TestCaseNodeDTO> getAllNodeByProjectId(QueryNodeRequest request) {
|
||||
return getNodeTreeByProjectId(request.getProjectId());
|
||||
}
|
||||
|
||||
public List<TestCaseNodeDTO> getAllNodeByReviewId(QueryNodeRequest request) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.metersphere.excel.listener.TestCaseDataListener;
|
|||
import io.metersphere.excel.utils.EasyExcelExporter;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.service.FileService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.track.request.testcase.EditTestCaseRequest;
|
||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||
|
@ -35,6 +36,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -70,6 +72,10 @@ public class TestCaseService {
|
|||
@Resource
|
||||
ProjectMapper projectMapper;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
ProjectService projectService;
|
||||
|
||||
@Resource
|
||||
SqlSessionFactory sqlSessionFactory;
|
||||
|
||||
|
@ -278,16 +284,41 @@ public class TestCaseService {
|
|||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public List<TestCase> getTestCaseNames(QueryTestCaseRequest request) {
|
||||
public List<TestCase> getTestCaseRelateList(QueryTestCaseRequest request) {
|
||||
List<OrderRequest> orderList = ServiceUtils.getDefaultOrder(request.getOrders());
|
||||
OrderRequest order = new OrderRequest();
|
||||
order.setName("sort");
|
||||
order.setType("desc");
|
||||
orderList.add(order);
|
||||
request.setOrders(orderList);
|
||||
return getTestCaseByNotInPlan(request);
|
||||
}
|
||||
|
||||
public List<TestCase> getTestCaseByNotInPlan(QueryTestCaseRequest request) {
|
||||
return extTestCaseMapper.getTestCaseByNotInPlan(request);
|
||||
}
|
||||
|
||||
public List<TestCaseDTO> getTestCaseByNotInIssue(QueryTestCaseRequest request) {
|
||||
List<TestCaseDTO> list = extTestCaseMapper.getTestCaseByNotInIssue(request);
|
||||
addProjectName(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public void addProjectName(List<TestCaseDTO> list) {
|
||||
List<String> projectIds = list.stream()
|
||||
.map(TestCase::getProjectId)
|
||||
.collect(Collectors.toList());
|
||||
List<Project> projects = projectService.getProjectByIds(projectIds);
|
||||
Map<String, String> projectMap = projects.stream()
|
||||
.collect(Collectors.toMap(Project::getId, Project::getName));
|
||||
list.forEach(item -> {
|
||||
String projectName = projectMap.get(item.getProjectId());
|
||||
if (StringUtils.isNotBlank(projectName)) {
|
||||
item.setProjectName(projectName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<TestCase> getReviewCase(QueryTestCaseRequest request) {
|
||||
List<OrderRequest> orderList = ServiceUtils.getDefaultOrder(request.getOrders());
|
||||
OrderRequest order = new OrderRequest();
|
||||
|
@ -925,4 +956,17 @@ public class TestCaseService {
|
|||
public List<TestCaseWithBLOBs> listTestCaseForMinder(QueryTestCaseRequest request) {
|
||||
return extTestCaseMapper.listForMinder(request);
|
||||
}
|
||||
|
||||
public List<TestCaseDTO> getTestCaseByIds(List<String> testCaseIds) {
|
||||
if (CollectionUtils.isNotEmpty(testCaseIds)) {
|
||||
return extTestCaseMapper.getTestCaseByIds(testCaseIds);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public List<TestCaseDTO> getTestCaseIssueRelateList(QueryTestCaseRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return getTestCaseByNotInIssue(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ public class TestPlanReportService {
|
|||
testPlanService.buildLoadCaseReport(testPlanReport.getTestPlanId(), components);
|
||||
|
||||
if (StringUtils.equals(ReportTriggerMode.MANUAL.name(), triggerMode)) {
|
||||
List<Issues> issues = testPlanService.buildFunctionalCaseReport(testPlanReport.getTestPlanId(), components);
|
||||
List<IssuesDao> issues = testPlanService.buildFunctionalCaseReport(testPlanReport.getTestPlanId(), components);
|
||||
issuesInfo = JSONArray.toJSONString(issues);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,9 @@ public class TestPlanService {
|
|||
private ApiScenarioReportMapper apiScenarioReportMapper;
|
||||
@Resource
|
||||
private TestPlanReportMapper testPlanReportMapper;
|
||||
@Lazy
|
||||
@Resource
|
||||
private IssuesService issuesService;
|
||||
|
||||
public synchronized String addTestPlan(AddTestPlanRequest testPlan) {
|
||||
if (getTestPlanByName(testPlan.getName()).size() > 0) {
|
||||
|
@ -620,7 +623,7 @@ public class TestPlanService {
|
|||
JSONArray componentIds = content.getJSONArray("components");
|
||||
|
||||
List<ReportComponent> components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan);
|
||||
List<Issues> issues = buildFunctionalCaseReport(planId, components);
|
||||
List<IssuesDao> issues = buildFunctionalCaseReport(planId, components);
|
||||
buildApiCaseReport(planId, components);
|
||||
buildScenarioCaseReport(planId, components);
|
||||
buildLoadCaseReport(planId, components);
|
||||
|
@ -780,7 +783,7 @@ public class TestPlanService {
|
|||
JSONArray componentIds = content.getJSONArray("components");
|
||||
|
||||
List<ReportComponent> components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan);
|
||||
List<Issues> issues = buildFunctionalCaseReport(planId, components);
|
||||
List<IssuesDao> issues = buildFunctionalCaseReport(planId, components);
|
||||
buildApiCaseReport(planId, components);
|
||||
buildScenarioCaseReport(planId, components);
|
||||
buildLoadCaseReport(planId, components);
|
||||
|
@ -826,14 +829,13 @@ public class TestPlanService {
|
|||
}
|
||||
}
|
||||
|
||||
public List<Issues> buildFunctionalCaseReport(String planId, List<ReportComponent> components) {
|
||||
IssuesService issuesService = (IssuesService) CommonBeanFactory.getBean("issuesService");
|
||||
public List<IssuesDao> buildFunctionalCaseReport(String planId, List<ReportComponent> components) {
|
||||
List<TestPlanCaseDTO> testPlanTestCases = listTestCaseByPlanId(planId);
|
||||
List<Issues> issues = new ArrayList<>();
|
||||
List<IssuesDao> issues = new ArrayList<>();
|
||||
for (TestPlanCaseDTO testCase : testPlanTestCases) {
|
||||
List<Issues> issue = issuesService.getIssues(testCase.getCaseId());
|
||||
List<IssuesDao> issue = issuesService.getIssues(testCase.getCaseId());
|
||||
if (issue.size() > 0) {
|
||||
for (Issues i : issue) {
|
||||
for (IssuesDao i : issue) {
|
||||
i.setModel(testCase.getNodePath());
|
||||
i.setProjectName(testCase.getProjectName());
|
||||
String des = i.getDescription().replaceAll("<p>", "").replaceAll("</p>", "");
|
||||
|
|
|
@ -37,7 +37,7 @@ VALUES ('09642424-7b1b-4004-867e-ff9c798a1933','i43sf4_issueCreator','ISSUE','me
|
|||
INSERT INTO custom_field (id,name,scene,`type`,remark,`options`,`system`,`global`,workspace_id,create_time,update_time)
|
||||
VALUES ('a577bc60-75fe-47ec-8aa6-32dca23bf3d6','i43sf4_issueProcessor','ISSUE','member','','[]',1,1,'global',unix_timestamp() * 1000,unix_timestamp() * 1000);
|
||||
INSERT INTO custom_field (id,name,scene,`type`,remark,`options`,`system`,`global`,workspace_id,create_time,update_time)
|
||||
VALUES ('beb57501-19c8-4ca3-8dfb-2cef7c0ea087','i43sf4_issueStatus','ISSUE','select','','[{"text":"test_track.issue.status_new","value":"NEW","system": true},{"text":"test_track.issue.status_resolved","value":"RESOLVED","system": true},{"text":"test_track.issue.status_closed","value":"CLOSED","system": true}]',1,1,'global',unix_timestamp() * 1000,unix_timestamp() * 1000);
|
||||
VALUES ('beb57501-19c8-4ca3-8dfb-2cef7c0ea087','i43sf4_issueStatus','ISSUE','select','','[{"text":"test_track.issue.status_new","value":"new","system": true},{"text":"test_track.issue.status_resolved","value":"resolved","system": true},{"text":"test_track.issue.status_closed","value":"closed","system": true}]',1,1,'global',unix_timestamp() * 1000,unix_timestamp() * 1000);
|
||||
INSERT INTO custom_field (id,name,scene,`type`,remark,`options`,`system`,`global`,workspace_id,create_time,update_time)
|
||||
VALUES ('d392af07-fdfe-4475-a459-87d59f0b1626','i43sf4_issueSeverity','ISSUE','select','','[{"text":"P0","value":"P0","system": true},{"text":"P1","value":"P1","system": true},{"text":"P2","value":"P2","system": true},{"text":"P3","value":"P3","system": true}]',1,1,'global',unix_timestamp() * 1000,unix_timestamp() * 1000);
|
||||
|
||||
|
@ -119,7 +119,7 @@ VALUES ('657e70c3-0d1b-4bbe-b52f-bfadee05148a','09642424-7b1b-4004-867e-ff9c798a
|
|||
INSERT INTO custom_field_template (id,field_id,template_id,scene,required,default_value)
|
||||
VALUES ('b8921cbc-05b3-4d8f-a96e-d1e4ae9d8664','a577bc60-75fe-47ec-8aa6-32dca23bf3d6','5d7c87d2-f405-4ec1-9a3d-71b514cdfda3','ISSUE',1,'');
|
||||
INSERT INTO custom_field_template (id,field_id,template_id,scene,required,default_value)
|
||||
VALUES ('d5908553-1b29-4868-9001-e938822b92ef','beb57501-19c8-4ca3-8dfb-2cef7c0ea087','5d7c87d2-f405-4ec1-9a3d-71b514cdfda3','ISSUE',1,'"NEW"');
|
||||
VALUES ('d5908553-1b29-4868-9001-e938822b92ef','beb57501-19c8-4ca3-8dfb-2cef7c0ea087','5d7c87d2-f405-4ec1-9a3d-71b514cdfda3','ISSUE',1,'"new"');
|
||||
|
||||
ALTER TABLE project
|
||||
ADD case_template_id varchar(50) NULL COMMENT 'Relate test case template id';
|
||||
|
@ -192,6 +192,29 @@ VALUES ('metersphere.module.reportStat', 'ENABLE', 'text', 1);
|
|||
INSERT INTO system_parameter (param_key, param_value, type, sort)
|
||||
VALUES ('metersphere.module.testTrack', 'ENABLE', 'text', 1);
|
||||
|
||||
|
||||
-- issue表添加自定义字段和项目id列
|
||||
ALTER TABLE issues ADD custom_fields TEXT NULL COMMENT 'CustomField';
|
||||
ALTER TABLE issues ADD project_id varchar(50) NULL;
|
||||
|
||||
-- 兼容旧数据,初始化issue表的project_id
|
||||
update issues i
|
||||
inner join
|
||||
(
|
||||
select tc.project_id, tci.issues_id
|
||||
from test_case_issues tci
|
||||
inner join test_case tc
|
||||
on tci.test_case_id = tc.id
|
||||
) as tmp
|
||||
on i.id = tmp.issues_id
|
||||
set i.project_id = tmp.project_id;
|
||||
|
||||
-- 修改issue表主键
|
||||
alter table issues drop primary key;
|
||||
alter table issues
|
||||
add constraint issues_pk
|
||||
primary key (id);
|
||||
|
||||
-- init prometheus host
|
||||
INSERT INTO system_parameter (param_key, param_value, type, sort)
|
||||
VALUES ('prometheus.host', 'http://ms-prometheus:9090', 'text', 1);
|
||||
|
@ -206,3 +229,4 @@ alter table load_test_report
|
|||
alter table load_test_report
|
||||
add tps VARCHAR(10) null;
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<!-- <table tableName="test_case_template"></table>-->
|
||||
<!-- <table tableName="custom_field"></table>-->
|
||||
<!-- <table tableName="test_case"></table>-->
|
||||
<table tableName="test_plan_test_case"></table>
|
||||
<table tableName="issues"></table>
|
||||
<!-- <table tableName="custom_field_template"></table>-->
|
||||
|
||||
</context>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="card-container" >
|
||||
<div class="card-container">
|
||||
|
||||
<el-table
|
||||
border
|
||||
|
@ -11,13 +11,14 @@
|
|||
@header-dragend="headerDragend"
|
||||
@cell-mouse-enter="showPopover"
|
||||
row-key="id"
|
||||
class="test-content adjust-table ms-select-all-fixed"
|
||||
class="test-content adjust-table"
|
||||
:class="{'ms-select-all-fixed':showSelectAll}"
|
||||
:height="screenHeight"
|
||||
ref="table" @row-click="handleRowClick">
|
||||
|
||||
<el-table-column v-if="enableSelection" width="50" type="selection"/>
|
||||
|
||||
<ms-table-header-select-popover v-if="enableSelection" ref="selectPopover"
|
||||
<ms-table-header-select-popover v-if="enableSelection && showSelectAll" ref="selectPopover"
|
||||
:page-size="pageSize > total ? total : pageSize"
|
||||
:total="total"
|
||||
@selectPageAll="isSelectDataAll(false)"
|
||||
|
@ -139,6 +140,12 @@ export default {
|
|||
default() {
|
||||
return true;
|
||||
}
|
||||
}, //开启全选
|
||||
showSelectAll: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -221,12 +228,15 @@ export default {
|
|||
this.$emit("handleRowClick");
|
||||
},
|
||||
handleRefresh() {
|
||||
this.selectRows.clear();
|
||||
this.clear();
|
||||
this.$emit('refresh');
|
||||
},
|
||||
handlePageChange() {
|
||||
this.$emit('pageChange');
|
||||
},
|
||||
clear() {
|
||||
this.selectRows.clear();
|
||||
this.selectDataCounts = 0;
|
||||
checkTableRowIsSelect() {
|
||||
checkTableRowIsSelect(this, this.condition, this.data, this.$refs.table, this.selectRows);
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
<el-form-item :label="'用例名称'" prop="caseName">
|
||||
<el-input v-model="form.caseName" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.prerequisite')" :data="form" prop="prerequisite"/>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.step_desc')" :data="form" prop="stepDescription"/>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.expected_results')" :data="form" prop="expectedResult"/>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.plan_view.actual_result')" :data="form" prop="actualResult"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.prerequisite')" :data="form" prop="prerequisite"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.step_desc')" :data="form" prop="stepDescription"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.expected_results')" :data="form" prop="expectedResult"/>
|
||||
<form-rich-text-item :title="$t('test_track.plan_view.actual_result')" :data="form" prop="actualResult"/>
|
||||
</template>
|
||||
|
||||
</field-template-edit>
|
||||
|
@ -46,12 +46,12 @@ import {CASE_TYPE_OPTION} from "@/common/js/table-constants";
|
|||
import CustomFieldFormList from "@/business/components/settings/workspace/template/CustomFieldFormList";
|
||||
import CustomFieldRelateList from "@/business/components/settings/workspace/template/CustomFieldRelateList";
|
||||
import FieldTemplateEdit from "@/business/components/settings/workspace/template/FieldTemplateEdit";
|
||||
import TestCaseRIchTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
|
||||
export default {
|
||||
name: "TestCaseTemplateEdit",
|
||||
components: {
|
||||
TestCaseRIchTextItem,
|
||||
FormRichTextItem,
|
||||
FieldTemplateEdit,
|
||||
CustomFieldRelateList,
|
||||
CustomFieldFormList,
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<template>
|
||||
<el-form>
|
||||
<el-form-item :disable="true" :label="title">
|
||||
<test-case-rich-text :disabled="disabled" :content="data[prop]" @updateRichText="updateData"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form-item :disable="true" :label="title" :prop="prop">
|
||||
<test-case-rich-text :disabled="disabled" :content="data[prop]" @updateRichText="updateData"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -63,9 +63,9 @@
|
|||
<ms-form-divider :title="$t('步骤信息')"/>
|
||||
|
||||
<div class="step-info">
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.prerequisite')" :data="form" prop="prerequisite"/>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.step_desc')" :data="form" prop="stepDesc"/>
|
||||
<test-case-r-ich-text-item :title="$t('test_track.case.expected_results')" :data="form" prop="stepResult"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.prerequisite')" :data="form" prop="prerequisite"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.step_desc')" :data="form" prop="stepDesc"/>
|
||||
<form-rich-text-item :title="$t('test_track.case.expected_results')" :data="form" prop="stepResult"/>
|
||||
</div>
|
||||
|
||||
<ms-form-divider :title="$t('其他信息')"/>
|
||||
|
@ -109,7 +109,6 @@
|
|||
import {TokenKey, WORKSPACE_ID} from '@/common/js/constants';
|
||||
import MsDialogFooter from '../../../common/components/MsDialogFooter'
|
||||
import {getCurrentUser, getNodePath, handleCtrlSEvent, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import {Message} from "element-ui";
|
||||
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
|
||||
import CaseComment from "@/business/components/track/case/components/CaseComment";
|
||||
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
|
||||
|
@ -130,16 +129,16 @@ import {
|
|||
parseCustomField
|
||||
} from "@/common/js/custom_field";
|
||||
import {SYSTEM_FIELD_NAME_MAP} from "@/common/js/table-constants";
|
||||
import TestCaseRIchTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import TestCaseEditOtherInfo from "@/business/components/track/case/components/TestCaseEditOtherInfo";
|
||||
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
|
||||
export default {
|
||||
name: "TestCaseEdit",
|
||||
components: {
|
||||
FormRichTextItem,
|
||||
TestCaseEditOtherInfo,
|
||||
MsFormDivider,
|
||||
TestCaseRIchTextItem,
|
||||
CustomFiledComponent,
|
||||
MsTableButton,
|
||||
MsSelectTree,
|
||||
|
@ -594,7 +593,7 @@ export default {
|
|||
if (this.$refs.otherInfo && this.$refs.otherInfo.fileList) {
|
||||
if (param.isCopy) {
|
||||
// 如果是copy,则把文件的ID传到后台进行文件复制
|
||||
param.fileIds = this.$refs.fileList.map(f => f.id);
|
||||
param.fileIds = this.$refs.otherInfo.fileList.map(f => f.id);
|
||||
}
|
||||
param.updatedFileList = this.$refs.otherInfo.fileList;
|
||||
} else {
|
||||
|
|
|
@ -44,7 +44,11 @@
|
|||
</el-col>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-if="!isTestPlan" label="关联缺陷" name="bug">关联缺陷</el-tab-pane>
|
||||
<el-tab-pane label="关联缺陷" name="bug">
|
||||
<test-case-issue-relate
|
||||
:case-id="caseId" ref="issue"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('test_track.case.attachment')" name="attachment">
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="1">
|
||||
|
@ -81,10 +85,11 @@ import TestCaseRichText from "@/business/components/track/case/components/MsRich
|
|||
import MsRichText from "@/business/components/track/case/components/MsRichText";
|
||||
import {TEST} from "@/business/components/api/definition/model/JsonData";
|
||||
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
|
||||
import TestCaseIssueRelate from "@/business/components/track/case/components/TestCaseIssueRelate";
|
||||
|
||||
export default {
|
||||
name: "TestCaseEditOtherInfo",
|
||||
components: {TestCaseAttachment, MsRichText, TestCaseRichText},
|
||||
components: {TestCaseIssueRelate, TestCaseAttachment, MsRichText, TestCaseRichText},
|
||||
props: ['form', 'labelWidth', 'caseId', 'readOnly', 'projectId', 'isTestPlan'],
|
||||
data() {
|
||||
return {
|
||||
|
@ -109,7 +114,7 @@ export default {
|
|||
} else if (this.tabActiveName === 'demand') {
|
||||
this.getDemandOptions();
|
||||
} else if (this.tabActiveName === 'bug') {
|
||||
//remark..
|
||||
this.$refs.issue.getIssues();
|
||||
} else if (this.tabActiveName === 'attachment') {
|
||||
this.getFileMetaData();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-button class="add-btn" type="primary" size="mini" @click="appIssue">添加缺陷</el-button>
|
||||
<el-tooltip class="item" effect="dark"
|
||||
:content="$t('test_track.issue.platform_tip')"
|
||||
placement="right">
|
||||
<i class="el-icon-info"/>
|
||||
</el-tooltip>
|
||||
|
||||
<ms-table
|
||||
v-loading="result.loading"
|
||||
:show-select-all="false"
|
||||
:data="issues"
|
||||
:enable-selection="false"
|
||||
@refresh="getIssues">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.id')"
|
||||
prop="id">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.title')"
|
||||
prop="title">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.status')"
|
||||
prop="status">
|
||||
<template v-slot="scope">
|
||||
<span>{{ issueStatusMap[scope.row.status] }}</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.platform')"
|
||||
prop="platform">
|
||||
</ms-table-column>
|
||||
|
||||
<issue-description-table-item/>
|
||||
|
||||
<el-table-column :label="$t('test_track.issue.operate')">
|
||||
<template v-slot:default="scope">
|
||||
<el-tooltip :content="$t('test_track.issue.close')"
|
||||
placement="top" :enterable="false">
|
||||
<el-button type="danger" icon="el-icon-circle-close" size="mini"
|
||||
circle v-if="scope.row.platform === 'Local'"
|
||||
@click="closeIssue(scope.row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('test_track.issue.delete')"
|
||||
placement="top" :enterable="false">
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini"
|
||||
circle v-if="scope.row.platform === 'Local'"
|
||||
@click="deleteIssue(scope.row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<test-plan-issue-edit :case-id="caseId" @refresh="getIssues" ref="issueEdit"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TestPlanIssueEdit from "@/business/components/track/case/components/TestPlanIssueEdit";
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
|
||||
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
|
||||
import {ISSUE_STATUS_MAP} from "@/common/js/table-constants";
|
||||
export default {
|
||||
name: "TestCaseIssueRelate",
|
||||
components: {IssueDescriptionTableItem, MsTableColumn, MsTable, TestPlanIssueEdit},
|
||||
data() {
|
||||
return {
|
||||
issues: [],
|
||||
result: {},
|
||||
}
|
||||
},
|
||||
props: ['caseId'],
|
||||
computed: {
|
||||
issueStatusMap() {
|
||||
return ISSUE_STATUS_MAP;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getIssues() {
|
||||
this.result = this.$get("/issues/get/" + this.caseId, (response) => {
|
||||
this.issues = response.data;
|
||||
});
|
||||
},
|
||||
appIssue() {
|
||||
this.$refs.issueEdit.open();
|
||||
},
|
||||
closeIssue(row) {
|
||||
if (row.status === 'closed') {
|
||||
this.$success(this.$t('test_track.issue.close_success'));
|
||||
} else {
|
||||
this.result = this.$get("/issues/close/" + row.id, () => {
|
||||
this.getIssues();
|
||||
this.$success(this.$t('test_track.issue.close_success'));
|
||||
});
|
||||
}
|
||||
},
|
||||
deleteIssue(row) {
|
||||
this.result = this.$post("/issues/delete", {id: row.id, caseId: this.caseId}, () => {
|
||||
this.getIssues();
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.add-btn {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,53 @@
|
|||
<template>
|
||||
<ms-edit-dialog
|
||||
width="60%"
|
||||
:visible.sync="visible"
|
||||
@confirm="confirm"
|
||||
:title="'创建字段'"
|
||||
append-to-body
|
||||
ref="msEditDialog">
|
||||
<template v-slot:default="scope">
|
||||
<issue-edit-detail :case-id="caseId" :is-plan="true" @refresh="$emit('refresh')" @close="handleClose" ref="issueEditDetail"/>
|
||||
</template>
|
||||
</ms-edit-dialog>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import TemplateComponentEditHeader
|
||||
from "@/business/components/track/plan/view/comonents/report/TemplateComponentEditHeader";
|
||||
import IssueEditDetail from "@/business/components/track/issue/IssueEditDetail";
|
||||
import MsEditDialog from "@/business/components/common/components/MsEditDialog";
|
||||
export default {
|
||||
name: "TestPlanIssueEdit",
|
||||
components: {MsEditDialog, IssueEditDetail, TemplateComponentEditHeader},
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
projectId() {
|
||||
return this.$store.state.projectId;
|
||||
}
|
||||
},
|
||||
props: ['caseId'],
|
||||
methods: {
|
||||
open(data) {
|
||||
this.visible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.issueEditDetail.open(data);
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.visible = false;
|
||||
},
|
||||
confirm() {
|
||||
this.$refs.issueEditDetail.save();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -46,6 +46,10 @@
|
|||
:title="$t('test_track.plan.create_plan')"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/track/issue'">
|
||||
{{ $t("缺陷管理") }}
|
||||
</el-menu-item>
|
||||
|
||||
<el-menu-item :index="'/track/testPlan/reportList'">
|
||||
{{ $t("commons.report") }}
|
||||
</el-menu-item>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.description')"
|
||||
prop="description">
|
||||
<template v-slot:default="scope">
|
||||
<el-popover
|
||||
placement="right"
|
||||
width="500"
|
||||
trigger="hover"
|
||||
popper-class="issues-popover"
|
||||
>
|
||||
<ckeditor :editor="editor" disabled :config="readConfig"
|
||||
v-model="scope.row.description"/>
|
||||
<el-button slot="reference" type="text">{{ $t('test_track.issue.preview') }}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
|
||||
export default {
|
||||
name: "IssueDescriptionTableItem",
|
||||
components: {MsTableColumn},
|
||||
data() {
|
||||
return {
|
||||
editor: ClassicEditor,
|
||||
readConfig: {toolbar: []},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
|
||||
<el-drawer
|
||||
class="field-template-edit"
|
||||
:before-close="handleClose"
|
||||
:visible.sync="visible"
|
||||
:with-header="false"
|
||||
size="100%"
|
||||
:modal-append-to-body="false"
|
||||
ref="drawer"
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<template-component-edit-header :show-edit="false" :template="{}" prop="title" @cancel="handleClose" @save="save"/>
|
||||
<issue-edit-detail @refresh="$emit('refresh')" @close="handleClose" ref="issueEditDetail"/>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import TemplateComponentEditHeader
|
||||
from "@/business/components/track/plan/view/comonents/report/TemplateComponentEditHeader";
|
||||
import IssueEditDetail from "@/business/components/track/issue/IssueEditDetail";
|
||||
export default {
|
||||
name: "IssueEdit",
|
||||
components: {IssueEditDetail, TemplateComponentEditHeader},
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(data) {
|
||||
this.visible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.issueEditDetail.open(data);
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.visible = false;
|
||||
},
|
||||
save() {
|
||||
this.$refs.issueEditDetail.save();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,271 @@
|
|||
<template>
|
||||
<el-main v-loading="result.loading" class="container">
|
||||
<el-scrollbar>
|
||||
<el-form :model="form" :rules="rules" label-position="right" label-width="140px" ref="form">
|
||||
|
||||
<el-form-item :label="'标题'" prop="title">
|
||||
<el-input v-model="form.title" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-row class="custom-field-row">
|
||||
<el-col :span="8" v-if="hasTapdId">
|
||||
<el-form-item :label="$t('test_track.issue.tapd_current_owner')" prop="tapdUsers">
|
||||
<el-select v-model="form.tapdUsers" multiple filterable
|
||||
:placeholder="$t('test_track.issue.please_choose_current_owner')">
|
||||
<el-option v-for="(userInfo, index) in tapdUsers" :key="index" :label="userInfo.user"
|
||||
:value="userInfo.user"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="hasZentaoId">
|
||||
<el-form-item :label="$t('test_track.issue.zentao_bug_build')" prop="zentaoBuilds">
|
||||
<el-select v-model="form.zentaoBuilds" multiple filterable
|
||||
:placeholder="$t('test_track.issue.zentao_bug_build')">
|
||||
<el-option v-for="(build, index) in Builds" :key="index" :label="build.name"
|
||||
:value="build.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="hasZentaoId">
|
||||
<el-form-item :label="$t('test_track.issue.zentao_bug_assigned')" prop="zentaoAssigned">
|
||||
<el-select v-model="form.zentaoAssigned" filterable
|
||||
:placeholder="$t('test_track.issue.please_choose_current_owner')">
|
||||
<el-option v-for="(userInfo, index) in zentaoUsers" :key="index" :label="userInfo.name"
|
||||
:value="userInfo.user"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 自定义字段 -->
|
||||
<el-form v-if="isFormAlive" :model="customFieldForm" :rules="customFieldRules" ref="customFieldForm"
|
||||
class="case-form">
|
||||
<el-row class="custom-field-row">
|
||||
<el-col :span="8" v-for="(item, index) in issueTemplate.customFields" :key="index">
|
||||
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item.name"
|
||||
:label-width="formLabelWidth">
|
||||
<custom-filed-component @reload="reloadForm" :data="item" :form="customFieldForm" prop="defaultValue"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<form-rich-text-item :title="$t('缺陷内容')" :data="form" prop="description"/>
|
||||
|
||||
<el-form-item v-if="!isPlan">
|
||||
<test-case-issue-list :test-case-contain-ids="testCaseContainIds" :issues-id="form.id" ref="testCaseIssueList"/>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import TemplateComponentEditHeader
|
||||
from "@/business/components/track/plan/view/comonents/report/TemplateComponentEditHeader";
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import CustomFieldFormList from "@/business/components/settings/workspace/template/CustomFieldFormList";
|
||||
import CustomFieldRelateList from "@/business/components/settings/workspace/template/CustomFieldRelateList";
|
||||
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
import {SYSTEM_FIELD_NAME_MAP} from "@/common/js/table-constants";
|
||||
import {buildCustomFields, getTemplate, parseCustomField} from "@/common/js/custom_field";
|
||||
import CustomFiledComponent from "@/business/components/settings/workspace/template/CustomFiledComponent";
|
||||
import TestCaseIssueList from "@/business/components/track/issue/TestCaseIssueList";
|
||||
import IssueEditDetail from "@/business/components/track/issue/IssueEditDetail";
|
||||
|
||||
export default {
|
||||
name: "IssueEditDetail",
|
||||
components: {
|
||||
IssueEditDetail,
|
||||
TestCaseIssueList,
|
||||
CustomFiledComponent,
|
||||
FormRichTextItem,
|
||||
CustomFieldRelateList,
|
||||
CustomFieldFormList,
|
||||
MsFormDivider,
|
||||
TemplateComponentEditHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
relateFields: [],
|
||||
isFormAlive: true,
|
||||
formLabelWidth: "120px",
|
||||
issueTemplate: {},
|
||||
customFieldForm: {},
|
||||
customFieldRules: {},
|
||||
rules: {
|
||||
title: [
|
||||
{required: true, message: this.$t('请填写标题'), trigger: 'blur'},
|
||||
{max: 64, message: this.$t('test_track.length_less_than') + '64', trigger: 'blur'}
|
||||
],
|
||||
description: [
|
||||
{required: true, message: this.$t('请填写内容'), trigger: 'blur'},
|
||||
]
|
||||
},
|
||||
testCaseContainIds: new Set(),
|
||||
url: '',
|
||||
form:{
|
||||
title: '',
|
||||
description: ''
|
||||
},
|
||||
tapdUsers: [],
|
||||
zentaoUsers: [],
|
||||
Builds: [],
|
||||
hasTapdId: false,
|
||||
hasZentaoId: false
|
||||
};
|
||||
},
|
||||
props: {
|
||||
isPlan: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
caseId: String
|
||||
},
|
||||
computed: {
|
||||
isSystem() {
|
||||
return this.form.system;
|
||||
},
|
||||
systemNameMap() {
|
||||
return SYSTEM_FIELD_NAME_MAP;
|
||||
},
|
||||
projectId() {
|
||||
return this.$store.state.projectId
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(data) {
|
||||
let initAddFuc = this.initEdit;
|
||||
getTemplate('field/template/issue/get/relate/', this)
|
||||
.then((template) => {
|
||||
this.issueTemplate = template;
|
||||
initAddFuc(data);
|
||||
});
|
||||
},
|
||||
getThirdPartyInfo() {
|
||||
let url = '/project/get/' + this.projectId;
|
||||
if (this.isPlan) {
|
||||
url = '/test/case/project/' + this.caseId;
|
||||
}
|
||||
this.$get(url, res => {
|
||||
let project = res.data;
|
||||
if (project.tapdId) {
|
||||
this.hasTapdId = true;
|
||||
this.result = this.$get("/issues/tapd/user/" + this.caseId, (response) => {
|
||||
this.tapdUsers = response.data;
|
||||
});
|
||||
}
|
||||
if (project.zentaoId) {
|
||||
this.hasZentaoId = true;
|
||||
this.result = this.$get("/issues/zentao/builds/" + this.caseId,response => {
|
||||
this.Builds = response.data;
|
||||
});
|
||||
this.result = this.$get("/issues/zentao/user/" + this.caseId, response => {
|
||||
this.zentaoUsers = response.data;
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
initEdit(data) {
|
||||
this.testCaseContainIds = new Set();
|
||||
if (data) {
|
||||
Object.assign(this.form, data);
|
||||
if (!(data.options instanceof Array)) {
|
||||
this.form.options = data.options ? JSON.parse(data.options) : [];
|
||||
}
|
||||
if (data.id) {
|
||||
this.url = 'issues/update';
|
||||
} else {
|
||||
//copy
|
||||
this.url = 'issues/add';
|
||||
}
|
||||
} else {
|
||||
this.form = {
|
||||
title: '',
|
||||
description: ''
|
||||
}
|
||||
this.url = 'issues/add';
|
||||
}
|
||||
parseCustomField(this.form, this.issueTemplate, this.customFieldForm, this.customFieldRules, null);
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.testCaseIssueList) {
|
||||
this.$refs.testCaseIssueList.initTableData();
|
||||
}
|
||||
});
|
||||
},
|
||||
reloadForm() {
|
||||
this.isFormAlive = false;
|
||||
this.$nextTick(() => (this.isFormAlive = true));
|
||||
},
|
||||
save() {
|
||||
let isValidate = true;
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (!valid) {
|
||||
isValidate = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.$refs['customFieldForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
isValidate = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (isValidate) {
|
||||
this._save();
|
||||
}
|
||||
},
|
||||
buildPram() {
|
||||
let param = {};
|
||||
Object.assign(param, this.form);
|
||||
param.projectId = this.projectId;
|
||||
buildCustomFields(this.form, param, this.issueTemplate);
|
||||
if (this.isPlan) {
|
||||
param.testCaseIds = [this.caseId];
|
||||
} else {
|
||||
param.testCaseIds = Array.from(this.testCaseContainIds);
|
||||
}
|
||||
return param;
|
||||
},
|
||||
_save() {
|
||||
let param = this.buildPram();
|
||||
this.parseOldFields(param);
|
||||
this.result = this.$post(this.url, param, () => {
|
||||
this.$emit('close');
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
parseOldFields(param) {
|
||||
let customFieldsStr = param.customFields;
|
||||
if (customFieldsStr) {
|
||||
let customFields = JSON.parse(customFieldsStr);
|
||||
if (customFields['i43sf4_issueStatus']) {
|
||||
param.status = JSON.parse(customFields['i43sf4_issueStatus']);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.container {
|
||||
height: calc(100vh - 62px);
|
||||
}
|
||||
|
||||
.filed-list {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.custom-field-row {
|
||||
padding-left: 18px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<el-main>
|
||||
<el-card>
|
||||
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="getIssues" @create="handleCreate"
|
||||
:create-tip="'创建缺陷'" :title="'缺陷列表'"/>
|
||||
</template>
|
||||
|
||||
<ms-table
|
||||
v-loading="result.loading"
|
||||
:data="tableData"
|
||||
:condition="condition"
|
||||
:total="total"
|
||||
:page-size.sync="pageSize"
|
||||
:operators="operators"
|
||||
:show-select-all="false"
|
||||
@handlePageChange="getIssues"
|
||||
@refresh="getIssues">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.id')"
|
||||
prop="id">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.title')"
|
||||
prop="title">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.status')"
|
||||
prop="status">
|
||||
<template v-slot="scope">
|
||||
<span>{{ issueStatusMap[scope.row.status] }}</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.platform')"
|
||||
prop="platform">
|
||||
</ms-table-column>
|
||||
|
||||
<issue-description-table-item/>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<ms-table-pagination :change="getIssues" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total"/>
|
||||
|
||||
<issue-edit @refresh="getIssues" ref="issueEdit"/>
|
||||
|
||||
</el-card>
|
||||
</el-main>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
|
||||
import MsTableOperators from "@/business/components/common/components/MsTableOperators";
|
||||
import MsTableButton from "@/business/components/common/components/MsTableButton";
|
||||
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
|
||||
import {
|
||||
CUSTOM_FIELD_SCENE_OPTION,
|
||||
CUSTOM_FIELD_TYPE_OPTION,
|
||||
FIELD_TYPE_MAP, ISSUE_STATUS_MAP,
|
||||
SYSTEM_FIELD_NAME_MAP
|
||||
} from "@/common/js/table-constants";
|
||||
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
|
||||
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
|
||||
import IssueEdit from "@/business/components/track/issue/IssueEdit";
|
||||
export default {
|
||||
name: "CustomFieldList",
|
||||
components: {
|
||||
IssueEdit,
|
||||
IssueDescriptionTableItem,
|
||||
MsTableHeader,
|
||||
MsTablePagination, MsTableButton, MsTableOperators, MsTableColumn, MsTable},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
condition: {},
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
result: {},
|
||||
operators: [
|
||||
{
|
||||
tip: this.$t('commons.edit'), icon: "el-icon-edit",
|
||||
exec: this.handleEdit
|
||||
}, {
|
||||
tip: this.$t('commons.copy'), icon: "el-icon-copy-document", type: "success",
|
||||
exec: this.handleCopy,
|
||||
isDisable: this.systemDisable
|
||||
}, {
|
||||
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
|
||||
exec: this.handleDelete,
|
||||
isDisable: this.systemDisable
|
||||
}
|
||||
],
|
||||
};
|
||||
},
|
||||
activated() {
|
||||
this.getIssues();
|
||||
},
|
||||
computed: {
|
||||
fieldFilters() {
|
||||
return CUSTOM_FIELD_TYPE_OPTION;
|
||||
},
|
||||
sceneFilters() {
|
||||
return CUSTOM_FIELD_SCENE_OPTION;
|
||||
},
|
||||
fieldTypeMap() {
|
||||
return FIELD_TYPE_MAP;
|
||||
},
|
||||
issueStatusMap() {
|
||||
return ISSUE_STATUS_MAP;
|
||||
},
|
||||
systemNameMap() {
|
||||
return SYSTEM_FIELD_NAME_MAP;
|
||||
},
|
||||
projectId() {
|
||||
return this.$store.state.projectId;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getIssues() {
|
||||
this.condition.projectId = this.projectId;
|
||||
this.result = this.$post('issues/list/' + this.currentPage + '/' + this.pageSize,
|
||||
this.condition, (response) => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
});
|
||||
},
|
||||
handleEdit(data) {
|
||||
this.$refs.issueEdit.open(data);
|
||||
},
|
||||
handleCreate() {
|
||||
this.$refs.issueEdit.open();
|
||||
},
|
||||
handleCopy(data) {
|
||||
let copyData = {};
|
||||
Object.assign(copyData, data);
|
||||
copyData.id = null;
|
||||
copyData.name = data.name + '_copy';
|
||||
this.$refs.issueEdit.open(copyData);
|
||||
},
|
||||
handleDelete(data) {
|
||||
this.result = this.$get('custom/field/delete/' + data.id, () => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.getIssues();
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-button type="primary" @click="relateTestCase">关联用例</el-button>
|
||||
|
||||
<ms-table
|
||||
v-loading="result.loading"
|
||||
:enable-selection="false"
|
||||
:operators="operators"
|
||||
:data="tableData"
|
||||
@refresh="initTableData"
|
||||
ref="table">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.id')"
|
||||
prop="num">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.name')"
|
||||
prop="name">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.priority')"
|
||||
prop="name">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority" ref="priority"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.type')"
|
||||
prop="type">
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.module')"
|
||||
prop="nodePath">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.plan.plan_project')"
|
||||
prop="projectName">
|
||||
</ms-table-column>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<test-case-relate-list
|
||||
@refresh="initTableData"
|
||||
@save="handleRelate"
|
||||
:test-case-contain-ids="testCaseContainIds"
|
||||
ref="testCaseRelevance"/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
|
||||
import PriorityTableItem from "@/business/components/track/common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "@/business/components/track/common/tableItems/planview/TypeTableItem";
|
||||
import TestCaseRelateList from "@/business/components/track/issue/TestCaseRelateList";
|
||||
export default {
|
||||
name: "TestCaseIssueList",
|
||||
components: {TestCaseRelateList, TypeTableItem, PriorityTableItem, MsTableColumn, MsTable},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
tableData: [],
|
||||
operators: [
|
||||
{
|
||||
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
|
||||
exec: this.handleDelete
|
||||
}
|
||||
],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
issuesId: String,
|
||||
testCaseContainIds: Set,
|
||||
},
|
||||
methods: {
|
||||
handleDelete(item, index) {
|
||||
this.testCaseContainIds.delete(item.id);
|
||||
this.tableData.splice(index, 1);
|
||||
},
|
||||
initTableData() {
|
||||
this.tableData = [];
|
||||
let condition = {
|
||||
issuesId: this.issuesId
|
||||
};
|
||||
if (this.issuesId) {
|
||||
this.result = this.$post('test/case/issues/list', condition, response => {
|
||||
this.tableData = response.data;
|
||||
this.tableData.forEach(item => {
|
||||
this.testCaseContainIds.add(item.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
relateTestCase() {
|
||||
this.$refs.testCaseRelevance.open();
|
||||
},
|
||||
handleRelate(selectRows) {
|
||||
let selectData = Array.from(selectRows);
|
||||
selectData.forEach(item => {
|
||||
if (item.id) {
|
||||
this.testCaseContainIds.add(item.id);
|
||||
}
|
||||
});
|
||||
this.tableData.push(...selectData);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,178 @@
|
|||
<template>
|
||||
<test-case-relevance-base
|
||||
@setProject="setProject"
|
||||
@save="save"
|
||||
ref="baseRelevance">
|
||||
|
||||
<template v-slot:aside>
|
||||
<ms-node-tree class="node-tree"
|
||||
v-loading="result.loading"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<el-card>
|
||||
|
||||
<ms-table-header :condition="condition" @search="initTableData" title="" :show-create="false"/>
|
||||
<ms-table
|
||||
v-loading="result.loading"
|
||||
:data="tableData"
|
||||
:condition="condition"
|
||||
:total="total"
|
||||
:page-size.sync="pageSize"
|
||||
:show-select-all="false"
|
||||
@handlePageChange="initTableData"
|
||||
@refresh="initTableData"
|
||||
ref="table">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.id')"
|
||||
prop="num">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.name')"
|
||||
prop="name">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.priority')"
|
||||
prop="name">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority" ref="priority"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.type')"
|
||||
prop="type">
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.module')"
|
||||
prop="nodePath">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.plan.plan_project')"
|
||||
prop="projectName">
|
||||
</ms-table-column>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total"/>
|
||||
</el-card>
|
||||
|
||||
</test-case-relevance-base>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
|
||||
import {CUSTOM_FIELD_LIST} from "@/common/js/default-table-header";
|
||||
import MsTableButton from "@/business/components/common/components/MsTableButton";
|
||||
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
|
||||
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
|
||||
import MsEditDialog from "@/business/components/common/components/MsEditDialog";
|
||||
import TestCaseRelevanceBase from "@/business/components/track/plan/view/comonents/base/TestCaseRelevanceBase";
|
||||
import MsNodeTree from "@/business/components/track/common/NodeTree";
|
||||
import PriorityTableItem from "@/business/components/track/common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "@/business/components/track/common/tableItems/planview/TypeTableItem";
|
||||
export default {
|
||||
name: "TestCaseRelateList",
|
||||
components: {
|
||||
TypeTableItem,
|
||||
PriorityTableItem,
|
||||
MsNodeTree,
|
||||
TestCaseRelevanceBase,
|
||||
MsEditDialog,
|
||||
MsTableHeader,
|
||||
MsTablePagination, MsTableButton, MsTableColumn, MsTable},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
condition: {},
|
||||
visible: false,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
projectId: '',
|
||||
result: {},
|
||||
treeNodes: [],
|
||||
projects: [],
|
||||
selectNodeIds: [],
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'testCaseContainIds'
|
||||
],
|
||||
watch: {
|
||||
selectNodeIds() {
|
||||
this.initTableData();
|
||||
},
|
||||
projectId() {
|
||||
this.getProjectNode();
|
||||
this.initTableData();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
fields() {
|
||||
return CUSTOM_FIELD_LIST;
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
this.condition.projectId = this.projectId;
|
||||
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.condition.testCaseContainIds = Array.from(this.testCaseContainIds)
|
||||
this.result = this.$post('/test/case/relate/issue/' + +this.currentPage + '/' + this.pageSize, this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
});
|
||||
}
|
||||
},
|
||||
nodeChange(node, nodeIds, nodeNames) {
|
||||
this.selectNodeIds = nodeIds;
|
||||
this.selectNodeNames = nodeNames;
|
||||
},
|
||||
getProjectNode(projectId) {
|
||||
if (projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
this.$refs.nodeTree.result = this.$post("/case/node/list/project",
|
||||
{projectId: this.projectId}, response => {
|
||||
this.treeNodes = response.data;
|
||||
});
|
||||
this.selectNodeIds = [];
|
||||
},
|
||||
open() {
|
||||
this.$refs.baseRelevance.open();
|
||||
this.initTableData();
|
||||
},
|
||||
save() {
|
||||
this.$emit('save', this.$refs.table.selectRows);
|
||||
this.$refs.table.clear();
|
||||
this.$refs.baseRelevance.close();
|
||||
},
|
||||
setProject(projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -42,169 +42,61 @@
|
|||
</el-header>
|
||||
|
||||
<div class="case_container">
|
||||
<el-row>
|
||||
<el-col :span="4" :offset="1">
|
||||
<span class="cast_label">{{ $t('test_track.case.priority') }}:</span>
|
||||
<span class="cast_item">{{ testCase.priority }}</span>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<span class="cast_label">{{ $t('test_track.case.module') }}:</span>
|
||||
<span class="cast_item">{{ testCase.nodePath }}</span>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<test-plan-test-case-status-button class="status-button"
|
||||
@statusChange="statusChange"
|
||||
:is-read-only="isReadOnly"
|
||||
:status="testCase.status"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="4" :offset="1">
|
||||
<span class="cast_label">{{ $t('test_track.plan.plan_project') }}:</span>
|
||||
<span class="cast_item">{{ testCase.projectName }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="4" :offset="1" v-if="testCase.testId == 'other'">
|
||||
<span class="cast_label">{{ $t('test_track.case.test_name') }}:</span>
|
||||
<span class="cast_item">{{ testCase.otherTestName }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form ref="customFieldForm"
|
||||
class="case-form">
|
||||
<el-form>
|
||||
<el-row>
|
||||
<el-col :span="7" v-for="(item, index) in testCaseTemplate.customFields" :key="index">
|
||||
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item.name"
|
||||
label-width="120px">
|
||||
<custom-filed-component :disabled="true" :data="item" :form="{}" prop="defaultValue"/>
|
||||
</el-form-item>
|
||||
<el-col :span="4" :offset="1">
|
||||
<span class="cast_label">{{ $t('test_track.case.priority') }}:</span>
|
||||
<span class="cast_item">{{ testCase.priority }}</span>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<span class="cast_label">{{ $t('test_track.case.module') }}:</span>
|
||||
<span class="cast_item">{{ testCase.nodePath }}</span>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<test-plan-test-case-status-button class="status-button"
|
||||
@statusChange="statusChange"
|
||||
:is-read-only="isReadOnly"
|
||||
:status="testCase.status"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="22" :offset="1">
|
||||
<div class="step-info">
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.prerequisite')" :data="testCase" prop="prerequisite"/>
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.step_desc')" :data="testCase" prop="stepDesc"/>
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.expected_results')" :data="testCase" prop="stepResult"/>
|
||||
<form-rich-text-item :title="$t('test_track.plan_view.actual_result')" :data="testCase" prop="actualResult"/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="4" :offset="1">
|
||||
<span class="cast_label">{{ $t('test_track.plan.plan_project') }}:</span>
|
||||
<span class="cast_item">{{ testCase.projectName }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="5" :offset="1">
|
||||
<el-switch
|
||||
:disabled="isReadOnly"
|
||||
v-model="issuesSwitch"
|
||||
@change="issuesChange"
|
||||
:active-text="$t('test_track.plan_view.submit_issues')">
|
||||
</el-switch>
|
||||
<el-tooltip class="item" effect="dark"
|
||||
:content="$t('test_track.issue.platform_tip')"
|
||||
placement="right">
|
||||
<i class="el-icon-info"/>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="4" :offset="1" v-if="testCase.testId == 'other'">
|
||||
<span class="cast_label">{{ $t('test_track.case.test_name') }}:</span>
|
||||
<span class="cast_item">{{ testCase.otherTestName }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-if="issuesSwitch">
|
||||
<el-col :span="20" :offset="1" class="issues-edit">
|
||||
<el-input
|
||||
type="text"
|
||||
:placeholder="$t('test_track.issue.input_title')"
|
||||
v-model="testCase.issues.title"
|
||||
maxlength="60"
|
||||
show-word-limit
|
||||
/>
|
||||
<ckeditor :editor="editor" :disabled="isReadOnly" :config="editorConfig"
|
||||
v-model="testCase.issues.content"/>
|
||||
<el-row v-if="hasTapdId">
|
||||
{{ $t('test_track.issue.tapd_current_owner') }}
|
||||
<el-select v-model="testCase.tapdUsers"
|
||||
multiple
|
||||
filterable
|
||||
style="width: 20%"
|
||||
:placeholder="$t('test_track.issue.please_choose_current_owner')"
|
||||
collapse-tags size="small">
|
||||
<el-option v-for="(userInfo, index) in users" :key="index" :label="userInfo.user"
|
||||
:value="userInfo.user"/>
|
||||
</el-select>
|
||||
<el-form ref="customFieldForm"
|
||||
class="case-form">
|
||||
<el-row>
|
||||
<el-col :span="7" v-for="(item, index) in testCaseTemplate.customFields" :key="index">
|
||||
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item.name"
|
||||
label-width="120px">
|
||||
<custom-filed-component :disabled="true" :data="item" :form="{}" prop="defaultValue"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="hasZentaoId">
|
||||
{{ $t('test_track.issue.zentao_bug_build') }}
|
||||
<el-select v-model="testCase.zentaoBuilds"
|
||||
multiple
|
||||
filterable
|
||||
style="width: 20%"
|
||||
:placeholder="$t('test_track.issue.zentao_bug_build')"
|
||||
collapse-tags size="small">
|
||||
<el-option v-for="(build, index) in Builds" :key="index" :label="build.name"
|
||||
:value="build.id"/>
|
||||
</el-select>
|
||||
{{ $t('test_track.issue.zentao_bug_assigned') }}
|
||||
<el-select v-model="testCase.zentaoAssigned"
|
||||
filterable
|
||||
style="width: 20%"
|
||||
:placeholder="$t('test_track.issue.please_choose_current_owner')"
|
||||
collapse-tags size="small">
|
||||
<el-option v-for="(userInfo, index) in zentaoUsers" :key="index" :label="userInfo.name"
|
||||
:value="userInfo.user"/>
|
||||
</el-select>
|
||||
</el-row>
|
||||
<el-button type="primary" size="small" @click="saveIssues">{{ $t('commons.save') }}</el-button>
|
||||
<el-button size="small" @click="issuesSwitch=false">{{ $t('commons.cancel') }}</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="1" class="issues-edit">
|
||||
<el-table border class="adjust-table" :data="issues" style="width: 100%">
|
||||
<el-table-column prop="id" :label="$t('test_track.issue.id')" show-overflow-tooltip/>
|
||||
<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="right"
|
||||
width="500"
|
||||
trigger="hover"
|
||||
popper-class="issues-popover"
|
||||
>
|
||||
<ckeditor :editor="editor" disabled :config="readConfig"
|
||||
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="status" :label="$t('test_track.issue.status')"/>
|
||||
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
||||
<el-table-column :label="$t('test_track.issue.operate')">
|
||||
<template v-slot:default="scope">
|
||||
<el-tooltip :content="$t('test_track.issue.close')"
|
||||
placement="top" :enterable="false">
|
||||
<el-button type="danger" icon="el-icon-circle-close" size="mini"
|
||||
circle v-if="scope.row.platform === 'Local'"
|
||||
@click="closeIssue(scope.row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('test_track.issue.delete')"
|
||||
placement="top" :enterable="false">
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini"
|
||||
circle v-if="scope.row.platform === 'Local'"
|
||||
@click="deleteIssue(scope.row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="22" :offset="1">
|
||||
<div class="step-info">
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.prerequisite')" :data="testCase" prop="prerequisite"/>
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.step_desc')" :data="testCase" prop="stepDesc"/>
|
||||
<form-rich-text-item :disabled="true" :title="$t('test_track.case.expected_results')" :data="testCase" prop="stepResult"/>
|
||||
<form-rich-text-item :title="$t('test_track.plan_view.actual_result')" :data="testCase" prop="actualResult"/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form>
|
||||
<test-case-edit-other-info @openTest="openTest" :read-only="true" :is-test-plan="true" :project-id="projectId" :form="testCase" :case-id="testCase.caseId" ref="otherInfo"/>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -255,10 +147,12 @@ import MsFormDivider from "@/business/components/common/components/MsFormDivider
|
|||
import TestCaseEditOtherInfo from "@/business/components/track/case/components/TestCaseEditOtherInfo";
|
||||
import CustomFiledComponent from "@/business/components/settings/workspace/template/CustomFiledComponent";
|
||||
import {SYSTEM_FIELD_NAME_MAP} from "@/common/js/table-constants";
|
||||
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
|
||||
|
||||
export default {
|
||||
name: "FunctionalTestCaseEdit",
|
||||
components: {
|
||||
IssueDescriptionTableItem,
|
||||
CustomFiledComponent,
|
||||
TestCaseEditOtherInfo,
|
||||
MsFormDivider,
|
||||
|
@ -279,9 +173,7 @@ export default {
|
|||
showDialog: false,
|
||||
testCase: {},
|
||||
index: 0,
|
||||
issuesSwitch: false,
|
||||
testCases: [],
|
||||
issues: [],
|
||||
editor: ClassicEditor,
|
||||
editorConfig: {
|
||||
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'insertTable', '|', 'undo', 'redo'],
|
||||
|
@ -443,13 +335,11 @@ export default {
|
|||
// 如果没值,使用模板的默认值
|
||||
this.testCase.actualResult = this.testCaseTemplate.actualResult;
|
||||
}
|
||||
this.getIssues(item.caseId);
|
||||
this.getComments(item);
|
||||
});
|
||||
},
|
||||
openTestCaseEdit(testCase) {
|
||||
this.showDialog = true;
|
||||
this.issuesSwitch = false;
|
||||
this.activeTab = 'detail';
|
||||
this.hasTapdId = false;
|
||||
this.hasZentaoId = false;
|
||||
|
@ -509,101 +399,12 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
issuesChange() {
|
||||
if (this.issuesSwitch) {
|
||||
let desc = this.addPLabel('[' + this.$t('test_track.plan_view.operate_step') + ']');
|
||||
let result = this.addPLabel('[' + this.$t('test_track.case.expected_results') + ']');
|
||||
let actualResult = this.addPLabel('[' + this.$t('test_track.plan_view.actual_result') + ']');
|
||||
this.testCase.steps.forEach(step => {
|
||||
let stepPrefix = this.$t('test_track.plan_view.step') + step.num + ':';
|
||||
desc += this.addPLabel(stepPrefix + (step.desc === undefined ? '' : step.desc));
|
||||
result += this.addPLabel(stepPrefix + (step.result === undefined ? '' : step.result));
|
||||
actualResult += this.addPLabel(stepPrefix + (step.actualResult === undefined ? '' : step.actualResult));
|
||||
});
|
||||
this.testCase.issues.content = desc + this.addPLabel('') + result + this.addPLabel('') + actualResult + this.addPLabel('');
|
||||
|
||||
this.$get("/test/case/project/" + this.testCase.caseId, res => {
|
||||
const project = res.data;
|
||||
if (project.tapdId) {
|
||||
this.hasTapdId = true;
|
||||
this.result = this.$get("/issues/tapd/user/" + this.testCase.caseId).then(response => {
|
||||
this.users = response.data.data;
|
||||
}).catch(() => {
|
||||
console.log("get tapd user error.");
|
||||
})
|
||||
}
|
||||
if (project.zentaoId) {
|
||||
this.hasZentaoId = true;
|
||||
this.result = this.$get("/issues/zentao/builds/" + this.testCase.caseId).then(response => {
|
||||
this.Builds = response.data.data;
|
||||
}).catch(() => {
|
||||
console.log("get zentao builds error.");
|
||||
})
|
||||
this.result = this.$get("/issues/zentao/user/" + this.testCase.caseId).then(response => {
|
||||
this.zentaoUsers = response.data.data;
|
||||
}).catch(() => {
|
||||
console.log("get zentao user error.");
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
addPLabel(str) {
|
||||
return "<p>" + str + "</p>";
|
||||
},
|
||||
setPlanStatus(planId) {
|
||||
this.$post('/test/plan/edit/status/' + planId);
|
||||
},
|
||||
saveIssues() {
|
||||
if (!this.testCase.issues.title || !this.testCase.issues.content) {
|
||||
this.$warning(this.$t('test_track.issue.title_description_required'));
|
||||
return;
|
||||
}
|
||||
|
||||
let param = {};
|
||||
param.title = this.testCase.issues.title;
|
||||
param.content = this.testCase.issues.content;
|
||||
param.testCaseId = this.testCase.caseId;
|
||||
param.tapdUsers = this.testCase.tapdUsers;
|
||||
param.zentaoBuilds = this.testCase.zentaoBuilds;
|
||||
param.zentaoUser = this.testCase.zentaoAssigned;
|
||||
|
||||
this.result = this.$post("/issues/add", param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.getIssues(param.testCaseId);
|
||||
});
|
||||
|
||||
this.issuesSwitch = false;
|
||||
this.testCase.issues.title = "";
|
||||
this.testCase.issues.content = "";
|
||||
this.testCase.tapdUsers = [];
|
||||
this.testCase.zentaoBuilds = [];
|
||||
this.testCase.zentaoAssigned = "";
|
||||
},
|
||||
getIssues(caseId) {
|
||||
this.result = this.$get("/issues/get/" + caseId).then(response => {
|
||||
this.issues = response.data.data;
|
||||
}).catch(() => {
|
||||
console.log("get issues error")
|
||||
})
|
||||
},
|
||||
closeIssue(row) {
|
||||
if (row.status === 'closed') {
|
||||
this.$success(this.$t('test_track.issue.close_success'));
|
||||
} else {
|
||||
this.result = this.$get("/issues/close/" + row.id, () => {
|
||||
this.getIssues(this.testCase.caseId);
|
||||
this.$success(this.$t('test_track.issue.close_success'));
|
||||
});
|
||||
}
|
||||
},
|
||||
deleteIssue(row) {
|
||||
let caseId = this.testCase.caseId;
|
||||
this.result = this.$post("/issues/delete", {id: row.id, caseId: caseId}, () => {
|
||||
this.getIssues(caseId);
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<el-row type="flex" class="head-bar">
|
||||
|
||||
<el-col :span="12">
|
||||
<div class="name-edit">
|
||||
<el-input :placeholder="$t('test_track.plan_view.input_template_name')" v-model="template.name" @change="change"/>
|
||||
<span v-if="template.name" class="title">{{template.name}}</span>
|
||||
<span class="name-tip" v-if="!template.name">{{$t('test_track.plan_view.input_template_name')}}</span>
|
||||
<div v-if="showEdit" class="name-edit">
|
||||
<el-input :placeholder="$t('test_track.plan_view.input_template_name')" v-model="template[prop]"/>
|
||||
<span v-if="template[prop]" class="title">{{template[prop]}}</span>
|
||||
<span class="name-tip" v-else>{{$t('test_track.plan_view.input_template_name')}}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12" class="head-right">
|
||||
|
@ -32,6 +32,18 @@
|
|||
return {}
|
||||
}
|
||||
},
|
||||
prop: {
|
||||
type: String,
|
||||
default() {
|
||||
return 'name';
|
||||
}
|
||||
},
|
||||
showEdit: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleCancel() {
|
||||
|
@ -39,9 +51,6 @@
|
|||
},
|
||||
handleSave() {
|
||||
this.$emit('save');
|
||||
},
|
||||
change() {
|
||||
this.$emit('update:template', this.templateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ const TestCaseReview = () => import('@/business/components/track/review/TestCase
|
|||
const TestCaseReviewView = () => import('@/business/components/track/review/view/TestCaseReviewView')
|
||||
const TestPlanView = () => import('@/business/components/track/plan/view/TestPlanView')
|
||||
const reportListView = () => import('@/business/components/track/report/TestPlanReport')
|
||||
const issueList = () => import('@/business/components/track/issue/IssueList.vue')
|
||||
// const reportListView = () => import('@/business/components/track/plan/TestPlan')
|
||||
|
||||
export default {
|
||||
|
@ -42,6 +43,11 @@ export default {
|
|||
name: 'testPlanReportList',
|
||||
component: reportListView,
|
||||
},
|
||||
{
|
||||
path: 'issue',
|
||||
name: 'issueManagement',
|
||||
component: issueList,
|
||||
},
|
||||
{
|
||||
path: "plan/:type",
|
||||
name: "testPlan",
|
||||
|
|
|
@ -58,6 +58,7 @@ export function parseCustomField(data, template, customFieldForm, rules, oldFiel
|
|||
});
|
||||
}
|
||||
|
||||
// 将template的属性值设置给customFields
|
||||
export function buildCustomFields(data, param, template) {
|
||||
if (template.customFields) {
|
||||
let customFields = data.customFields;
|
||||
|
|
|
@ -58,3 +58,10 @@ export const SYSTEM_FIELD_NAME_MAP = {
|
|||
i43sf4_issueStatus: 'custom_field.issue_status',
|
||||
i43sf4_issueSeverity: 'custom_field.issue_severity',
|
||||
}
|
||||
|
||||
|
||||
export const ISSUE_STATUS_MAP = {
|
||||
'new': '新建',
|
||||
'closed': '已关闭',
|
||||
'resolved': '已解决'
|
||||
}
|
||||
|
|
|
@ -45,12 +45,14 @@ export function setUnSelectIds(tableData, condition, selectRows) {
|
|||
let thisUnSelectIds = allIDs.filter(function (val) {
|
||||
return ids.indexOf(val) === -1;
|
||||
});
|
||||
let needPushIds = thisUnSelectIds.filter(function (val) {
|
||||
return condition.unSelectIds.indexOf(val) === -1;
|
||||
});
|
||||
needPushIds.forEach(id => {
|
||||
condition.unSelectIds.push(id);
|
||||
});
|
||||
if (condition.unSelectIds) {
|
||||
let needPushIds = thisUnSelectIds.filter(function (val) {
|
||||
return condition.unSelectIds.indexOf(val) === -1;
|
||||
});
|
||||
needPushIds.forEach(id => {
|
||||
condition.unSelectIds.push(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getSelectDataCounts(condition, total, selectRows) {
|
||||
|
|
Loading…
Reference in New Issue