feat(测试计划): 测试计划&计划组高级搜索

This commit is contained in:
WangXu10 2024-11-08 11:21:59 +08:00 committed by Craftsman
parent b10097ea9f
commit 1764885938
5 changed files with 408 additions and 19 deletions

View File

@ -28,6 +28,7 @@ public class TestPlanTableRequest extends BasePageRequest {
@Schema(description = "通过其他条件查询出来的必须要包含的测试计划ID") @Schema(description = "通过其他条件查询出来的必须要包含的测试计划ID")
private List<String> innerIds; private List<String> innerIds;
private List<String> combineInnerIds;
public String getSortString() { public String getSortString() {
if (StringUtils.isEmpty(super.getSortString())) { if (StringUtils.isEmpty(super.getSortString())) {

View File

@ -78,4 +78,7 @@ public interface ExtTestPlanMapper {
List<ProjectCountDTO> projectPlanCount(@Param("projectIds") Set<String> projectIds, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("userId") String userId); List<ProjectCountDTO> projectPlanCount(@Param("projectIds") Set<String> projectIds, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("userId") String userId);
@BaseConditionFilter
List<TestPlanResponse> selectMyFollowByConditions(@Param("request") TestPlanTableRequest request);
} }

View File

@ -123,6 +123,12 @@
) )
</when> </when>
</choose>--> </choose>-->
<if test="request.combineInnerIds != null and request.combineInnerIds.size() > 0">
and t.id in
<foreach collection="request.combineInnerIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<include refid="filters"> <include refid="filters">
<property name="filter" value="request.filter"/> <property name="filter" value="request.filter"/>
</include> </include>
@ -180,11 +186,104 @@
<property name="searchMode" value="${combineSearch}.searchMode"/> <property name="searchMode" value="${combineSearch}.searchMode"/>
</include> </include>
</foreach> </foreach>
</if>
</trim>
</trim>
<trim prefix="AND">
<trim prefix="(" suffix=")" suffixOverrides="AND|OR">
<if test="${combineSearch} != null">
<foreach collection="${combineSearch}.systemFieldConditions" item="condition"> <foreach collection="${combineSearch}.systemFieldConditions" item="condition">
<include refid="io.metersphere.system.mapper.BaseMapper.commonSystemFieldConditions"> <if test="condition.name == 'moduleId'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/> <property name="condition" value="condition"/>
<property name="tablePrefix" value="t"/> <property name="column" value="t.module_id"/>
</include> </include>
</if>
<if test="condition.name == 'name'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.name"/>
</include>
<if test="condition.operator == 'CONTAINS' or condition.operator == 'EQUALS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.name"/>
</include>
)
</if>
</if>
<if test="condition.name == 'num'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.num"/>
</include>
<if test="request.type != 'TEST_PLAN'" >
<if test="condition.operator == 'CONTAINS' or condition.operator == 'EQUALS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.num"/>
</include>
)
</if>
</if>
</if>
<if test="condition.name == 'createUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.create_user"/>
</include>
</if>
<if test="condition.name == 'updateUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.update_user"/>
</include>
</if>
<if test="condition.name == 'updateTime'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.update_time"/>
</include>
</if>
<if test="condition.name == 'createTime'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.create_time"/>
</include>
</if>
<if test="condition.name == 'tags'">
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
<property name="condition" value="condition"/>
<property name="column" value="t.tags"/>
</include>
<if test="condition.operator == 'CONTAINS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.tags"/>
</include>
)
</if>
</if>
<!-- 状态 --> <!-- 状态 -->
<if test="condition.name == 'status'"> <if test="condition.name == 'status'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <include refid="io.metersphere.system.mapper.BaseMapper.condition">
@ -641,4 +740,249 @@
group by test_plan.project_id; group by test_plan.project_id;
</select> </select>
<select id="selectMyFollowByConditions"
resultMap="BaseResultMapDTO">
select t.* from (
SELECT
t.id,t.num,t.name,t.status,t.group_id,
t.create_user AS createUser,
createUser.name AS createUserName,
t.create_time as createTime,
t.module_id as moduleId,
t.type,
t.description,
t.pos,
t.planned_start_time AS plannedStartTime,
t.planned_end_time AS plannedEndTime,
t.actual_start_time AS actualStartTime,
t.actual_end_time AS actualEndTime,
t.tags
FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id
WHERE t.project_id = #{request.projectId}
<include refid="queryMyFollowGroupByTableRequest">
<property name="group" value="true"/>
<property name="request" value="request"/>
</include>
union
SELECT
t.id,t.num,t.name,t.status,t.group_id,
t.create_user AS createUser,
createUser.name AS createUserName,
t.create_time as createTime,
t.module_id as moduleId,
t.type,
t.description,
t.pos,
t.planned_start_time AS plannedStartTime,
t.planned_end_time AS plannedEndTime,
t.actual_start_time AS actualStartTime,
t.actual_end_time AS actualEndTime,
t.tags
FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id
WHERE t.project_id = #{request.projectId}
<include refid="queryMyFollowGroupByTableRequest">
<property name="group" value="false"/>
<property name="request" value="request"/>
</include>
) t
</select>
<sql id="queryMyFollowGroupByTableRequest">
<include refid="baseConditionQuery"/>
<if test="request.keyword != null and request.keyword != ''">
and (
t.name like concat('%', #{request.keyword},'%')
or t.num like concat('%', #{request.keyword},'%')
or t.tags like concat('%', #{request.keyword}, '%')
<if test="request.keywordFilterIds != null and request.keywordFilterIds.size() > 0">
or t.id in
<foreach collection="request.keywordFilterIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
)
</if>
<if test="request.innerIds != null and request.innerIds.size() > 0">
and t.id in
<foreach collection="request.innerIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="request.combineInnerIds != null and request.combineInnerIds.size() > 0">
and t.id in
<foreach collection="request.combineInnerIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<include refid="filter">
<property name="filter" value="request.filter"/>
</include>
<include refid="myFollowCombine">
<property name="combineSearch" value="request.combineSearch"/>
<property name="group" value="${group}"/>
</include>
</sql>
<sql id="myFollowCombine">
<trim prefix="AND">
<trim prefix="(" suffix=")" suffixOverrides="AND|OR">
<if test="${combineSearch} != null">
<foreach collection="${combineSearch}.userViewConditions" item="condition">
<if test="condition.name == 'createUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.create_user"/>
</include>
</if>
<if test="condition.name == 'follower' and ${group}">
t.id IN (
SELECT
test_plan.group_id
FROM
test_plan_follower
INNER JOIN test_plan on test_plan_follower.test_plan_id = test_plan.id
WHERE
test_plan.project_id = #{request.projectId}
and test_plan_follower.user_id IN
<foreach collection="condition.value" item="v" separator="," open="(" close=")">
#{v}
</foreach>
)
</if>
<if test="condition.name == 'follower' and !${group}">
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
<property name="mainIdColumn" value="t.id"/>
<property name="associationTable" value="test_plan_follower"/>
<property name="associationIdColumn" value="test_plan_id"/>
<property name="searchColumn" value="user_id"/>
<property name="condition" value="condition"/>
</include>
</if>
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
<property name="searchMode" value="${combineSearch}.searchMode"/>
</include>
</foreach>
</if>
</trim>
</trim>
<trim prefix="AND">
<trim prefix="(" suffix=")" suffixOverrides="AND|OR">
<if test="${combineSearch} != null">
<foreach collection="${combineSearch}.systemFieldConditions" item="condition">
<if test="condition.name == 'moduleId'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.module_id"/>
</include>
</if>
<if test="condition.name == 'name'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.name"/>
</include>
<if test="condition.operator == 'CONTAINS' or condition.operator == 'EQUALS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.name"/>
</include>
)
</if>
</if>
<if test="condition.name == 'num'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.num"/>
</include>
<if test="request.type != 'TEST_PLAN'" >
<if test="condition.operator == 'CONTAINS' or condition.operator == 'EQUALS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.num"/>
</include>
)
</if>
</if>
</if>
<if test="condition.name == 'createUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.create_user"/>
</include>
</if>
<if test="condition.name == 'updateUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.update_user"/>
</include>
</if>
<if test="condition.name == 'updateTime'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.update_time"/>
</include>
</if>
<if test="condition.name == 'createTime'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.create_time"/>
</include>
</if>
<if test="condition.name == 'tags'">
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
<property name="condition" value="condition"/>
<property name="column" value="t.tags"/>
</include>
<if test="condition.operator == 'CONTAINS'">
or t.id in
(
SELECT group_id
FROM test_plan
WHERE project_id = #{request.projectId}
AND
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
<property name="condition" value="condition"/>
<property name="column" value="test_plan.tags"/>
</include>
)
</if>
</if>
<!-- 状态 -->
<if test="condition.name == 'status'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="t.status"/>
</include>
</if>
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
<property name="searchMode" value="${combineSearch}.searchMode"/>
</include>
</foreach>
</if>
</trim>
</trim>
</sql>
</mapper> </mapper>

View File

@ -185,10 +185,24 @@ public class TestPlanManagementService {
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private void initDefaultFilter(TestPlanTableRequest request) { private void initDefaultFilter(TestPlanTableRequest request) {
List<String> defaultStatusList = new ArrayList<>(); List<String> defaultStatusList = new ArrayList<>();
defaultStatusList.add(TestPlanConstants.TEST_PLAN_STATUS_NOT_ARCHIVED); defaultStatusList.add(TestPlanConstants.TEST_PLAN_STATUS_NOT_ARCHIVED);
Optional.ofNullable(request.getCombineSearch()).ifPresent(combineSearch -> {
combineSearch.getConditions().forEach(item -> {
if (StringUtils.equalsIgnoreCase(item.getName(), "status")) {
List<String> statusList = (List<String>) item.getValue();
item.setValue(defaultStatusList);
//目前未归档的测试计划只有3中类型所以这里判断如果是3个的话等于直接查询未归档
if (statusList.size() < 3) {
request.setCombineInnerIds(this.selectTestPlanIdByProjectIdAndStatus(request.getProjectId(), statusList));
}
}
});
});
if (!StringUtils.equalsIgnoreCase(request.getViewId(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
if (request.getFilter() == null || !request.getFilter().containsKey("status")) { if (request.getFilter() == null || !request.getFilter().containsKey("status")) {
if (request.getFilter() == null) { if (request.getFilter() == null) {
request.setFilter(new HashMap<>() {{ request.setFilter(new HashMap<>() {{
@ -205,6 +219,7 @@ public class TestPlanManagementService {
request.setInnerIds(this.selectTestPlanIdByProjectIdAndStatus(request.getProjectId(), statusList)); request.setInnerIds(this.selectTestPlanIdByProjectIdAndStatus(request.getProjectId(), statusList));
} }
} }
}
if (StringUtils.isNotBlank(request.getKeyword())) { if (StringUtils.isNotBlank(request.getKeyword())) {
List<String> groupIdList = extTestPlanMapper.selectGroupIdByKeyword(request.getProjectId(), request.getKeyword()); List<String> groupIdList = extTestPlanMapper.selectGroupIdByKeyword(request.getProjectId(), request.getKeyword());
@ -216,7 +231,12 @@ public class TestPlanManagementService {
} }
public List<TestPlanResponse> list(TestPlanTableRequest request) { public List<TestPlanResponse> list(TestPlanTableRequest request) {
List<TestPlanResponse> testPlanResponses = extTestPlanMapper.selectByConditions(request); List<TestPlanResponse> testPlanResponses = new ArrayList<>();
if (StringUtils.equalsIgnoreCase(request.getViewId(), "my_follow")) {
testPlanResponses = extTestPlanMapper.selectMyFollowByConditions(request);
} else {
testPlanResponses = extTestPlanMapper.selectByConditions(request);
}
handChildren(testPlanResponses, request.getProjectId()); handChildren(testPlanResponses, request.getProjectId());
return testPlanResponses; return testPlanResponses;
} }

View File

@ -21,6 +21,8 @@ import io.metersphere.project.dto.filemanagement.request.FileModuleCreateRequest
import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest; import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.*; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
@ -237,7 +239,26 @@ public class TestPlanTests extends BaseTest {
this.requestGetPermissionTest(PermissionConstants.TEST_PLAN_READ, String.format(URL_GET_MODULE_TREE, DEFAULT_PROJECT_ID)); this.requestGetPermissionTest(PermissionConstants.TEST_PLAN_READ, String.format(URL_GET_MODULE_TREE, DEFAULT_PROJECT_ID));
testPlanTableRequest.setProjectId(DEFAULT_PROJECT_ID); testPlanTableRequest.setProjectId(DEFAULT_PROJECT_ID);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
testPlanTableRequest.setViewId("my-follow");
testPlanTableRequest.setCombineSearch(buildCombineSearch());
this.requestPost(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
} }
private CombineSearch buildCombineSearch() {
CombineSearch combineSearch = new CombineSearch();
List<CombineCondition> conditions = new ArrayList<>();
CombineCondition combineCondition = new CombineCondition();
combineCondition.setName("status");
combineCondition.setValue(List.of("PREPARED"));
combineCondition.setOperator("IN");
combineCondition.setCustomField(false);
combineCondition.setCustomFieldType("");
conditions.add(combineCondition);
combineSearch.setConditions(conditions);
return combineSearch;
}
@Test @Test
@Order(2) @Order(2)
public void addModuleTest() throws Exception { public void addModuleTest() throws Exception {