feat(系统设置): 功能用例页面高级搜索

--task=1016128 --user=陈建星 高级搜索-视图增删改查-后端 https://www.tapd.cn/55049933/s/1573254
This commit is contained in:
AgAngle 2024-09-06 15:02:41 +08:00 committed by Craftsman
parent 170dce538d
commit 186ca8edf0
99 changed files with 606 additions and 838 deletions

View File

@ -1,6 +1,7 @@
package io.metersphere.request; package io.metersphere.request;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Max;
@ -18,7 +19,7 @@ import java.util.Map;
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class AssociateBugPageRequest extends BaseProviderCondition { public class AssociateBugPageRequest extends BaseCondition {
@Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED)
private String caseId; private String caseId;

View File

@ -1,5 +1,6 @@
package io.metersphere.request; package io.metersphere.request;
import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -13,7 +14,7 @@ import java.util.List;
* @author wx * @author wx
*/ */
@Data @Data
public class AssociateBugRequest extends BaseProviderCondition { public class AssociateBugRequest extends BaseCondition {
@Schema(description = "不处理的ID") @Schema(description = "不处理的ID")
List<String> excludeIds; List<String> excludeIds;

View File

@ -1,6 +1,7 @@
package io.metersphere.request; package io.metersphere.request;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
@ -9,7 +10,7 @@ import lombok.Data;
import java.util.List; import java.util.List;
@Data @Data
public class AssociateCaseModuleRequest extends BaseProviderCondition { public class AssociateCaseModuleRequest extends BaseCondition {
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)") @Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<@NotBlank String> moduleIds; private List<@NotBlank String> moduleIds;

View File

@ -1,5 +1,6 @@
package io.metersphere.request; package io.metersphere.request;
import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -54,5 +55,5 @@ public class AssociateOtherCaseRequest {
private String apiDefinitionId; private String apiDefinitionId;
@Schema(description = "查询条件") @Schema(description = "查询条件")
private BaseProviderCondition condition = new BaseProviderCondition(); private BaseCondition condition = new BaseCondition();
} }

View File

@ -1,35 +0,0 @@
package io.metersphere.request;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
@Data
public class BaseProviderCondition {
@Schema(description = "关键字")
private String keyword;
@Schema(description = "匹配模式 所有/任一", allowableValues = {"AND", "OR"})
private String searchMode = "AND";
@Schema(description = "过滤字段")
private Map<String, List<String>> filter;
@Schema(description = "高级搜索")
private Map<String, Object> combine;
// 转JSON时会调用 前台数据传过来时可以顺便处理掉转义字符
public void setKeyword(String keyword) {
keyword = StringUtils.replace(keyword, "%", "\\%");
keyword = StringUtils.replace(keyword, "_", "\\_");
this.keyword = keyword;
}
// 直接初始化keyword
public void initKeyword(String keyword) {
this.keyword = keyword;
}
}

View File

@ -1,6 +1,7 @@
package io.metersphere.request; package io.metersphere.request;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Max;
@ -13,7 +14,6 @@ import org.apache.commons.lang3.StringUtils;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -21,7 +21,7 @@ import java.util.Map;
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class BugPageProviderRequest implements Serializable { public class BugPageProviderRequest extends BaseCondition implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -38,18 +38,6 @@ public class BugPageProviderRequest implements Serializable {
@Schema(description = "排序字段model中的字段 : asc/desc") @Schema(description = "排序字段model中的字段 : asc/desc")
private Map<@Valid @Pattern(regexp = "^[A-Za-z]+$") String, @Valid @NotBlank String> sort; private Map<@Valid @Pattern(regexp = "^[A-Za-z]+$") String, @Valid @NotBlank String> sort;
@Schema(description = "关键字")
private String keyword;
@Schema(description = "匹配模式 所有/任一", allowableValues = {"AND", "OR"})
private String searchMode = "AND";
@Schema(description = "过滤字段")
private Map<String, List<String>> filter;
@Schema(description = "高级搜索")
private Map<String, Object> combine;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case.project_id.not_blank}") @NotBlank(message = "{functional_case.project_id.not_blank}")
private String projectId; private String projectId;

View File

@ -1,6 +1,7 @@
package io.metersphere.request; package io.metersphere.request;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
@ -19,7 +20,7 @@ import java.util.Map;
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class TestCasePageProviderRequest extends BaseProviderCondition implements Serializable { public class TestCasePageProviderRequest extends BaseCondition implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -137,6 +137,12 @@
<version>${guava.version}</version> <version>${guava.version}</version>
</dependency> </dependency>
<!-- sdk 使用 schema 注解 -->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core-jakarta</artifactId>
<version>${swagger-core-jakarta.revision}</version>
</dependency>
<!--java json schema json格式校验--> <!--java json schema json格式校验-->
<dependency> <dependency>

View File

@ -1,4 +1,4 @@
package io.metersphere.system.dto.sdk; package io.metersphere.sdk.dto;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@ -16,6 +16,9 @@ public class BaseCondition {
@Schema(description = "过滤字段") @Schema(description = "过滤字段")
private Map<String, List<String>> filter; private Map<String, List<String>> filter;
@Schema(description = "视图ID")
private String viewId;
@Schema(description = "高级搜索") @Schema(description = "高级搜索")
@Valid @Valid
private CombineSearch combineSearch; private CombineSearch combineSearch;

View File

@ -1,11 +1,14 @@
package io.metersphere.system.dto.sdk; package io.metersphere.sdk.dto;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.List;
/** /**
* @Author: jianxing * @Author: jianxing
* @CreateTime: 2024-08-28 17:31 * @CreateTime: 2024-08-28 17:31
@ -30,7 +33,16 @@ public class CombineCondition {
private String operator; private String operator;
public boolean valid() { public boolean valid() {
return StringUtils.isNotBlank(name) && StringUtils.isNotBlank(operator) && value != null; if (value == null) {
return false;
}
if (value instanceof List valueList && CollectionUtils.isEmpty(valueList)) {
return false;
}
if (value instanceof String valueStr && StringUtils.isBlank(valueStr)) {
return false;
}
return StringUtils.isNotBlank(name) && StringUtils.isNotBlank(operator);
} }
public enum CombineConditionOperator { public enum CombineConditionOperator {

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.sdk; package io.metersphere.sdk.dto;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package io.metersphere.system.valid; package io.metersphere.sdk.valid;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto; package io.metersphere.api.dto;
import io.metersphere.sdk.constants.ApiBatchRunMode; import io.metersphere.sdk.constants.ApiBatchRunMode;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition;
import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.domain.ApiDefinitionCustomField; import io.metersphere.api.domain.ApiDefinitionCustomField;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -2,7 +2,7 @@ package io.metersphere.api.dto.definition;
import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.domain.ApiDefinitionCustomField; import io.metersphere.api.domain.ApiDefinitionCustomField;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,6 +1,6 @@
package io.metersphere.api.dto.definition; package io.metersphere.api.dto.definition;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.definition; package io.metersphere.api.dto.definition;
import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.definition; package io.metersphere.api.dto.definition;
import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.controller; package io.metersphere.api.dto.request.controller;
import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -4,7 +4,7 @@ import io.metersphere.api.dto.request.controller.loop.MsCountController;
import io.metersphere.api.dto.request.controller.loop.MsForEachController; import io.metersphere.api.dto.request.controller.loop.MsForEachController;
import io.metersphere.api.dto.request.controller.loop.MsWhileController; import io.metersphere.api.dto.request.controller.loop.MsWhileController;
import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -3,7 +3,7 @@ package io.metersphere.api.dto.request.controller;
import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.constants.ScriptLanguageType; import io.metersphere.project.constants.ScriptLanguageType;
import io.metersphere.project.dto.CommonScriptInfo; import io.metersphere.project.dto.CommonScriptInfo;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.controller.loop; package io.metersphere.api.dto.request.controller.loop;
import io.metersphere.api.dto.request.controller.WhileConditionType; import io.metersphere.api.dto.request.controller.WhileConditionType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
@Data @Data

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.controller.loop; package io.metersphere.api.dto.request.controller.loop;
import io.metersphere.api.dto.request.controller.ConditionUtils; import io.metersphere.api.dto.request.controller.ConditionUtils;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
@Data @Data

View File

@ -4,7 +4,7 @@ import io.metersphere.api.dto.request.http.body.Body;
import io.metersphere.plugin.api.spi.AbstractMsProtocolTestElement; import io.metersphere.plugin.api.spi.AbstractMsProtocolTestElement;
import io.metersphere.project.dto.environment.auth.HTTPAuthConfig; import io.metersphere.project.dto.environment.auth.HTTPAuthConfig;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.http; package io.metersphere.api.dto.request.http;
import io.metersphere.project.api.KeyValueEnableParam; import io.metersphere.project.api.KeyValueEnableParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
/** /**

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.http; package io.metersphere.api.dto.request.http;
import io.metersphere.project.api.KeyValueEnableParam; import io.metersphere.project.api.KeyValueEnableParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
/** /**

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.request.http.body; package io.metersphere.api.dto.request.http.body;
import io.metersphere.project.api.KeyValueEnableParam; import io.metersphere.project.api.KeyValueEnableParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
/** /**

View File

@ -2,7 +2,7 @@ package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStatus; import io.metersphere.api.constants.ApiScenarioStatus;
import io.metersphere.api.dto.ResourceAddFileParam; import io.metersphere.api.dto.ResourceAddFileParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,6 +1,6 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -2,7 +2,7 @@ package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStepRefType; import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.api.constants.ApiScenarioStepType; import io.metersphere.api.constants.ApiScenarioStepType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStepRefType; import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -2,7 +2,7 @@ package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStatus; import io.metersphere.api.constants.ApiScenarioStatus;
import io.metersphere.api.dto.ResourceUpdateFileParam; import io.metersphere.api.dto.ResourceUpdateFileParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -2,7 +2,7 @@ package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.ApiFile;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -3,7 +3,7 @@ package io.metersphere.api.dto.schema;
import io.metersphere.project.constants.PropertyConstant; import io.metersphere.project.constants.PropertyConstant;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;

View File

@ -367,107 +367,108 @@
</sql> </sql>
<sql id="combine"> <sql id="combine">
<if test='${condition}.name != null and (${name} == null or ${name} == "")'> -- todo 待修改
and api_definition.name <!-- <if test='${condition}.name != null and (${name} == null or ${name} == "")'>-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- and api_definition.name-->
<property name="object" value="${condition}.name"/> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
</include> <!-- <property name="object" value="${condition}.name"/>-->
</if> <!-- </include>-->
<!-- </if>-->
<if test='${condition}.id != null'> <!-- <if test='${condition}.id != null'>-->
and api_definition.num <!-- and api_definition.num-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.id"/> <!-- <property name="object" value="${condition}.id"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.updateTime != null"> <!-- <if test="${condition}.updateTime != null">-->
and api_definition.update_time <!-- and api_definition.update_time-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.updateTime"/> <!-- <property name="object" value="${condition}.updateTime"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.createTime != null"> <!-- <if test="${condition}.createTime != null">-->
and api_definition.create_time <!-- and api_definition.create_time-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.createTime"/> <!-- <property name="object" value="${condition}.createTime"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.status != null"> <!-- <if test="${condition}.status != null">-->
and api_definition.status <!-- and api_definition.status-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.status"/> <!-- <property name="object" value="${condition}.status"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.path != null"> <!-- <if test="${condition}.path != null">-->
and api_definition.path <!-- and api_definition.path-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.path"/> <!-- <property name="object" value="${condition}.path"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.method != null"> <!-- <if test="${condition}.method != null">-->
and api_definition.method <!-- and api_definition.method-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.method"/> <!-- <property name="object" value="${condition}.method"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test='${condition}.tags != null and ${ObjectTags}.operator == "not like"'> <!-- <if test='${condition}.tags != null and ${ObjectTags}.operator == "not like"'>-->
and (api_definition.tags is null or api_definition.tags <!-- and (api_definition.tags is null or api_definition.tags-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.tags"/> <!-- <property name="object" value="${condition}.tags"/>-->
</include> <!-- </include>-->
) <!-- )-->
</if> <!-- </if>-->
<if test='${condition}.tags != null and ${ObjectTags}.operator == "like"'> <!-- <if test='${condition}.tags != null and ${ObjectTags}.operator == "like"'>-->
and api_definition.tags <!-- and api_definition.tags-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="${condition}.tags"/> <!-- <property name="object" value="${condition}.tags"/>-->
</include> <!-- </include>-->
</if> <!-- </if>-->
<if test="${condition}.customs != null and ${condition}.customs.size() > 0"> <!-- <if test="${condition}.customs != null and ${condition}.customs.size() > 0">-->
<foreach collection="${condition}.customs" item="custom" separator="" open="" close=""> <!-- <foreach collection="${condition}.customs" item="custom" separator="" open="" close="">-->
<if test="custom.value != ''"> <!-- <if test="custom.value != ''">-->
<if test='custom.operator == "not like" or custom.operator == "not in"'> <!-- <if test='custom.operator == "not like" or custom.operator == "not in"'>-->
and api_definition.id not in ( <!-- and api_definition.id not in (-->
</if> <!-- </if>-->
<if test='custom.operator != "not like" and custom.operator != "not in"'> <!-- <if test='custom.operator != "not like" and custom.operator != "not in"'>-->
and api_definition.id in ( <!-- and api_definition.id in (-->
</if> <!-- </if>-->
select api_id from api_definition_custom_field where field_id = #{custom.id} <!-- select api_id from api_definition_custom_field where field_id = #{custom.id}-->
<choose> <!-- <choose>-->
<when test="custom.type == 'TEXTAREA' or custom.operator == 'current user'"> <!-- <when test="custom.type == 'TEXTAREA' or custom.operator == 'current user'">-->
and `value` <!-- and `value`-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="custom"/> <!-- <property name="object" value="custom"/>-->
</include> <!-- </include>-->
</when> <!-- </when>-->
<when test="custom.type == 'MULTIPLE_MEMBER' or custom.type == 'CHECKBOX' or custom.type == 'MULTIPLE_SELECT'"> <!-- <when test="custom.type == 'MULTIPLE_MEMBER' or custom.type == 'CHECKBOX' or custom.type == 'MULTIPLE_SELECT'">-->
and ${custom.value} <!-- and ${custom.value}-->
</when> <!-- </when>-->
<when test="custom.type == 'DATE' or custom.type == 'DATETIME'"> <!-- <when test="custom.type == 'DATE' or custom.type == 'DATETIME'">-->
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13) <!-- and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="custom"/> <!-- <property name="object" value="custom"/>-->
</include> <!-- </include>-->
</when> <!-- </when>-->
<otherwise> <!-- <otherwise>-->
and trim(both '"' from `value`) <!-- and trim(both '"' from `value`)-->
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <!-- <include refid="io.metersphere.system.mapper.BaseMapper.condition">-->
<property name="object" value="custom"/> <!-- <property name="object" value="custom"/>-->
</include> <!-- </include>-->
</otherwise> <!-- </otherwise>-->
</choose> <!-- </choose>-->
) <!-- )-->
</if> <!-- </if>-->
</foreach> <!-- </foreach>-->
</if> <!-- </if>-->
</sql> </sql>
<sql id="queryVersionCondition"> <sql id="queryVersionCondition">

View File

@ -11,7 +11,6 @@ import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.utils.CustomFieldUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -74,7 +73,6 @@ public class ApiDefinitionExportService {
} }
if (request.isSelectAll()) { if (request.isSelectAll()) {
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request.getCondition(), userId);
List<String> ids = extApiDefinitionMapper.getIdsBySort(request, request.getProjectId(), protocols, request.getSortString()); List<String> ids = extApiDefinitionMapper.getIdsBySort(request, request.getProjectId(), protocols, request.getSortString());
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds()); ids.removeAll(request.getExcludeIds());

View File

@ -50,7 +50,6 @@ import io.metersphere.system.service.OperationHistoryService;
import io.metersphere.system.service.UserLoginService; import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator; import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.CustomFieldUtils;
import io.metersphere.system.utils.ServiceUtils; import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -143,7 +142,6 @@ public class ApiDefinitionService extends MoveNodeService {
if (CollectionUtils.isEmpty(request.getProtocols())) { if (CollectionUtils.isEmpty(request.getProtocols())) {
return new ArrayList<>(); return new ArrayList<>();
} }
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request); List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
processApiDefinitions(list); processApiDefinitions(list);
return list; return list;
@ -153,7 +151,6 @@ public class ApiDefinitionService extends MoveNodeService {
if (CollectionUtils.isEmpty(request.getProtocols())) { if (CollectionUtils.isEmpty(request.getProtocols())) {
return new ArrayList<>(); return new ArrayList<>();
} }
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request); List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list)) {
processApiDefinitionsDoc(list); processApiDefinitionsDoc(list);
@ -891,7 +888,6 @@ public class ApiDefinitionService extends MoveNodeService {
public <T> List<String> getBatchApiIds(T dto, String projectId, List<String> protocols, boolean deleted, String userId) { public <T> List<String> getBatchApiIds(T dto, String projectId, List<String> protocols, boolean deleted, String userId) {
TableBatchProcessDTO request = (TableBatchProcessDTO) dto; TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
if (request.isSelectAll() && CollectionUtils.isNotEmpty(protocols)) { if (request.isSelectAll() && CollectionUtils.isNotEmpty(protocols)) {
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request.getCondition(), userId);
List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocols, deleted); List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocols, deleted);
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds()); ids.removeAll(request.getExcludeIds());

View File

@ -45,7 +45,7 @@ import io.metersphere.system.domain.OperationHistoryExample;
import io.metersphere.system.dto.AddProjectRequest; import io.metersphere.system.dto.AddProjectRequest;
import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.system.dto.request.OperationHistoryVersionRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.OperationHistoryMapper; import io.metersphere.system.mapper.OperationHistoryMapper;

View File

@ -19,7 +19,7 @@ import io.metersphere.system.domain.TestResourcePoolBlob;
import io.metersphere.system.dto.pool.TestResourceDTO; import io.metersphere.system.dto.pool.TestResourceDTO;
import io.metersphere.system.dto.pool.TestResourceNodeDTO; import io.metersphere.system.dto.pool.TestResourceNodeDTO;
import io.metersphere.system.dto.pool.TestResourcePoolDTO; import io.metersphere.system.dto.pool.TestResourcePoolDTO;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest; import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest; import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;

View File

@ -1,7 +1,7 @@
package io.metersphere.api.controller.param; package io.metersphere.api.controller.param;
import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.bug.dto.request; package io.metersphere.bug.dto.request;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,25 +0,0 @@
package io.metersphere.functional.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author wx
*/
@Data
public class AssociationDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "类型",allowableValues = {"EMPTY","NOT_EMPTY"})
private String operatorType;
@Schema(description = "用例类型",allowableValues = {"API","API_SCENARIO","UI_SCENARIO","LOAD"})
private List<String> caseType;
}

View File

@ -12,6 +12,7 @@ import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.request.AssociateOtherCaseRequest; import io.metersphere.request.AssociateOtherCaseRequest;
import io.metersphere.request.TestCasePageProviderRequest; import io.metersphere.request.TestCasePageProviderRequest;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.interceptor.BaseConditionFilter;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -33,11 +34,12 @@ public interface ExtFunctionalCaseMapper {
List<FunctionalCase> checkCaseByModuleIds(@Param("moduleIds") List<String> deleteIds); List<FunctionalCase> checkCaseByModuleIds(@Param("moduleIds") List<String> deleteIds);
@BaseConditionFilter
List<FunctionalCasePageDTO> list(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted, @Param("isRepeat") boolean isRepeat); List<FunctionalCasePageDTO> list(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted, @Param("isRepeat") boolean isRepeat);
void recoverCase(@Param("ids") List<String> ids, @Param("userId") String userId, @Param("time") long time); void recoverCase(@Param("ids") List<String> ids, @Param("userId") String userId, @Param("time") long time);
@BaseConditionFilter
List<String> getIds(@Param("request") BaseFunctionalCaseBatchDTO request, @Param("projectId") String projectId, @Param("deleted") boolean deleted); List<String> getIds(@Param("request") BaseFunctionalCaseBatchDTO request, @Param("projectId") String projectId, @Param("deleted") boolean deleted);
void batchDelete(@Param("ids") List<String> ids, @Param("userId") String userId); void batchDelete(@Param("ids") List<String> ids, @Param("userId") String userId);
@ -46,6 +48,7 @@ public interface ExtFunctionalCaseMapper {
List<String> getRefIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted); List<String> getRefIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
@BaseConditionFilter
void batchMoveModule(@Param("request") FunctionalCaseBatchMoveRequest request, @Param("ids") List<String> ids, @Param("userId") String userId); void batchMoveModule(@Param("request") FunctionalCaseBatchMoveRequest request, @Param("ids") List<String> ids, @Param("userId") String userId);
List<FunctionalCase> getTagsByIds(@Param("ids") List<String> ids); List<FunctionalCase> getTagsByIds(@Param("ids") List<String> ids);
@ -55,8 +58,10 @@ public interface ExtFunctionalCaseMapper {
void recoverCaseByRefIds(@Param("refIds") List<String> refIds, @Param("userId") String userId, @Param("time") long time); void recoverCaseByRefIds(@Param("refIds") List<String> refIds, @Param("userId") String userId, @Param("time") long time);
@BaseConditionFilter
List<ModuleCountDTO> countModuleIdByRequest(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted); List<ModuleCountDTO> countModuleIdByRequest(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted);
@BaseConditionFilter
long caseCount(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted); long caseCount(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted);
Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos); Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
@ -71,6 +76,7 @@ public interface ExtFunctionalCaseMapper {
* @param sort 排序 * @param sort 排序
* @return 通用的列表Case集合 * @return 通用的列表Case集合
*/ */
@BaseConditionFilter
List<TestCaseProviderDTO> listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort); List<TestCaseProviderDTO> listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort);
/** /**
@ -80,6 +86,7 @@ public interface ExtFunctionalCaseMapper {
* @param deleted 是否删除状态 * @param deleted 是否删除状态
* @return 关联的用例ID集合 * @return 关联的用例ID集合
*/ */
@BaseConditionFilter
List<String> getSelectIdsByAssociateParam(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); List<String> getSelectIdsByAssociateParam(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted);
/** /**

View File

@ -58,7 +58,7 @@
<select id="getFunctionalCaseByRefId" resultType="io.metersphere.functional.dto.FunctionalCaseVersionDTO"> <select id="getFunctionalCaseByRefId" resultType="io.metersphere.functional.dto.FunctionalCaseVersionDTO">
SELECT SELECT
id, id,
NAME, name,
version_id, version_id,
project_id project_id
FROM FROM
@ -184,16 +184,34 @@
<include refid="filters"> <include refid="filters">
<property name="filter" value="request.filter"/> <property name="filter" value="request.filter"/>
</include> </include>
<choose> <include refid="queryCombine">
<when test='request.searchMode == "AND"'> <property name="combineSearch" value="request.combineSearch"/>
AND <include refid="queryCombine"/> </include>
</when> <include refid="queryVersionCondition">
<when test='request.searchMode == "OR"'> <property name="versionTable" value="functional_case"/>
</include>
</sql>
<sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
and functional_case.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId}
</foreach>
</if>
<if test="request.condition.keyword != null and request.condition.keyword != ''">
and ( and (
<include refid="queryCombine"/> functional_case.name like concat('%', #{request.condition.keyword},'%')
or functional_case.num like concat('%', #{request.condition.keyword},'%')
or functional_case.tags like concat('%', #{request.condition.keyword},'%')
) )
</when> </if>
</choose> <include refid="filters">
<property name="filter" value="request.condition.filter"/>
</include>
<include refid="queryCombine">
<property name="combineSearch" value="request.condition.combineSearch"/>
</include>
<include refid="queryVersionCondition"> <include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/> <property name="versionTable" value="functional_case"/>
</include> </include>
@ -264,127 +282,115 @@
</sql> </sql>
<sql id="queryCombine"> <sql id="queryCombine">
<if test="request.combine != null"> <trim prefix="AND" suffixOverrides="AND|OR">
<include refid="combine"> <if test="${combineSearch} != null">
<property name="condition" value="request.combine"/> <foreach collection="${combineSearch}.userViewConditions" item="condition">
<property name="searchMode" value="request.searchMode"/> <if test="condition.name == 'createUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.create_user"/>
</include> </include>
</if> </if>
<include refid="queryAssociationCase"> <if test="condition.name == 'follower'">
<property name="searchMode" value="request.searchMode"/> functional_case.id in (
</include> select case_id from functional_case_follower where
<include refid="queryAssociationBug">
<property name="searchMode" value="request.searchMode"/>
</include>
1=1
</sql>
<sql id="combine">
<!-- 名称 -->
<if test='${condition}.name != null'>
functional_case.name
<include refid="io.metersphere.system.mapper.BaseMapper.condition"> <include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.name"/> <property name="condition" value="condition"/>
<property name="column" value="user_id"/>
</include> </include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- id -->
<if test='${condition}.id != null'>
functional_case.num
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.id"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 所属模块 -->
<if test='${condition}.moduleId != null'>
functional_case.moduleId
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.moduleId"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 创建人 -->
<if test='${condition}.createUser != null'>
functional_case.create_user
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.createUser"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 创建时间 -->
<if test='${condition}.createTime != null'>
functional_case.create_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.createTime"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 更新人 -->
<if test='${condition}.updateUser != null'>
functional_case.update_user
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.updateUser"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 更新时间 -->
<if test='${condition}.updateTime != null'>
functional_case.update_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.updateTime"/>
</include>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 标签 -->
<if test='${condition}.tags != null'>
<include refid="queryTag">
<property name="searchMode" value="${searchMode}"/>
<property name="combineTag" value="${condition}.tags"/>
</include>
</if>
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
functional_case.id ${custom.operator} (
select case_id from functional_case_custom_field where field_id = #{custom.id}
<choose>
<when test="custom.type == 'List'">
and JSON_CONTAINS(`value`, json_array(#{custom.value}))
</when>
<when test="custom.type == 'date' or custom.type == 'datetime'">
and `value`
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="custom"/>
</include>
</when>
<otherwise>
and trim(both '"' from `value`)
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="custom"/>
</include>
</otherwise>
</choose>
) )
<include refid="queryType"> </if>
<property name="searchMode" value="${searchMode}"/> <include refid="io.metersphere.system.mapper.BaseMapper.queryType">
<property name="searchMode" value="${combineSearch}.searchMode"/>
</include> </include>
</foreach> </foreach>
<foreach collection="${combineSearch}.systemFieldConditions" item="condition">
<if test="condition.name == 'name'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.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="functional_case.num"/>
</include>
</if>
<if test="condition.name == 'moduleId'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.module_id"/>
</include>
</if>
<if test="condition.name == 'createUser'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.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="functional_case.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="functional_case.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="functional_case.create_time"/>
</include>
</if>
<if test="condition.name == 'tags'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.tags"/>
</include>
</if>
<if test="condition.name == 'reviewStatus'">
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="functional_case.review_status"/>
</include>
</if>
<if test="condition.name == 'demand'">
functional_case.id in (
select case_id from functional_case_demand where
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="demand_name"/>
</include>
)
</if>
<if test="condition.name == 'attachment'">
functional_case.id in (
select case_id from functional_case_attachment where
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="file_name"/>
</include>
)
</if>
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
<property name="searchMode" value="${combineSearch}.searchMode"/>
</include>
</foreach>
<if test="${combineSearch}.customFiledConditions.size() > 0">
functional_case.id in (
select case_id from functional_case_custom_field where
<include refid="io.metersphere.system.mapper.BaseMapper.customFiledConditions">
<property name="conditions" value="${combineSearch}.customFiledConditions"/>
</include>
)
</if>
</if>
</trim>
</sql> </sql>
<sql id="queryVersionCondition"> <sql id="queryVersionCondition">
@ -401,121 +407,6 @@
</choose> </choose>
</sql> </sql>
<sql id="queryAssociationCase">
<if test="request.associationCase != null">
<choose>
<when test="request.associationCase.operatorType == 'EMPTY'">
functional_case.id not in (
select functional_case.id from functional_case LEFT JOIN functional_case_test on functional_case.id
= functional_case_test.case_id where functional_case_test.source_type in
<foreach collection="request.associationCase.caseType" item="item" open="(" separator="," close=")">
#{item}
</foreach>
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</when>
<when test="request.associationCase.operatorType == 'NOT_EMPTY'">
functional_case.id in (
select functional_case.id from functional_case LEFT JOIN functional_case_test on functional_case.id
= functional_case_test.case_id where functional_case_test.source_type in
<foreach collection="request.associationCase.caseType" item="item" open="(" separator="," close=")">
#{item}
</foreach>
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</when>
</choose>
</if>
</sql>
<sql id="queryAssociationBug">
<if test="request.associationBug != null">
<choose>
<when test="request.associationBug.operatorType == 'EMPTY'">
functional_case.id not in (
select functional_case.id from functional_case LEFT JOIN bug_relation_case on functional_case.id =
bug_relation_case.case_id where bug_relation_case.case_type = 'functional'
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</when>
<when test="request.associationBug.operatorType == 'NOT_EMPTY'">
functional_case.id in (
select functional_case.id from functional_case LEFT JOIN bug_relation_case on functional_case.id =
bug_relation_case.case_id where bug_relation_case.case_type = 'functional'
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</when>
</choose>
</if>
</sql>
<sql id="queryType">
<choose>
<when test='${searchMode} == "AND"'>
AND
</when>
<when test='${searchMode} == "OR"'>
OR
</when>
</choose>
</sql>
<sql id="queryTag">
<!-- 不包含 -->
<if test='${combineTag}.value.size() > 0 and ${combineTag}.operator == "not like"'>
(
functional_case.tags is null or functional_case.tags = '[]' or
<foreach collection="${combineTag}.value" item="tag" separator="and" open="(" close=")">
!JSON_CONTAINS(functional_case.tags, JSON_ARRAY(#{tag}))
</foreach>
)
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!-- 包含 -->
<if test='${combineTag}.value.size() > 0 and ${combineTag}.operator == "like"'>
<foreach collection="${combineTag}.value" item="tag" separator="or" open="(" close=")">
JSON_CONTAINS(functional_case.tags, JSON_ARRAY(#{tag}))
</foreach>
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
<!---->
<if test='${combineTag}.operator == "is null"'>
(functional_case.tags is null or functional_case.tags = '[]')
<include refid="queryType">
<property name="searchMode" value="${searchMode}"/>
</include>
</if>
</sql>
<select id="getIds" resultType="java.lang.String"> <select id="getIds" resultType="java.lang.String">
SELECT SELECT
id id
@ -527,48 +418,6 @@
<include refid="queryWhereConditionByBaseQueryRequest"/> <include refid="queryWhereConditionByBaseQueryRequest"/>
</select> </select>
<sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
and functional_case.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId}
</foreach>
</if>
<if test="request.condition.keyword != null and request.condition.keyword != ''">
and (
functional_case.name like concat('%', #{request.condition.keyword},'%')
or functional_case.num like concat('%', #{request.condition.keyword},'%')
or functional_case.tags like concat('%', #{request.condition.keyword},'%')
)
</if>
<include refid="filters">
<property name="filter" value="request.condition.filter"/>
</include>
<choose>
<when test='request.condition.searchMode == "AND"'>
AND <include refid="baseQueryCombine"/>
</when>
<when test='request.condition.searchMode == "OR"'>
and (
<include refid="baseQueryCombine"/>
)
</when>
</choose>
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
</sql>
<sql id="baseQueryCombine">
<if test="request.condition.combine != null">
<include refid="combine">
<property name="condition" value="request.condition.combine"/>
<property name="searchMode" value="request.condition.searchMode"/>
</include>
</if>
1=1
</sql>
<select id="getRefIds" resultType="java.lang.String"> <select id="getRefIds" resultType="java.lang.String">
SELECT SELECT
ref_id ref_id

View File

@ -1,6 +1,6 @@
package io.metersphere.functional.request; package io.metersphere.functional.request;
import io.metersphere.request.BaseProviderCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Min;
@ -12,7 +12,7 @@ import java.util.List;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class AssociatePlanPageRequest extends BaseProviderCondition { public class AssociatePlanPageRequest extends BaseCondition {
@Schema(description = "功能用例id", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "功能用例id", requiredMode = Schema.RequiredMode.REQUIRED)

View File

@ -1,6 +1,5 @@
package io.metersphere.functional.request; package io.metersphere.functional.request;
import io.metersphere.functional.dto.AssociationDTO;
import io.metersphere.system.dto.sdk.BasePageRequest; import io.metersphere.system.dto.sdk.BasePageRequest;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@ -32,15 +31,6 @@ public class FunctionalCasePageRequest extends BasePageRequest implements Serial
@Schema(description = "模块id") @Schema(description = "模块id")
private List<String> moduleIds; private List<String> moduleIds;
@Schema(description = "关联用例")
private AssociationDTO associationCase;
@Schema(description = "关联需求")
private AssociationDTO associationDemand;
@Schema(description = "关联缺陷")
private AssociationDTO associationBug;
@Schema(description = "评审id") @Schema(description = "评审id")
private String reviewId; private String reviewId;

View File

@ -14,7 +14,7 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.OptionDTO; import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;

View File

@ -32,6 +32,8 @@ import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.CustomField; import io.metersphere.system.domain.CustomField;
import io.metersphere.system.dto.OperationHistoryDTO; import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO; import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO; import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.dto.sdk.request.PosRequest;
@ -484,14 +486,14 @@ public class FunctionalCaseControllerTests extends BaseTest {
Assertions.assertNotNull(resultHolder); Assertions.assertNotNull(resultHolder);
//自定义字段 测试 //自定义字段 测试
Map<String, Object> map = new HashMap<>(); CombineSearch combineSearch = new CombineSearch();
map.put("customs", Arrays.asList(new LinkedHashMap() {{ CombineCondition condition = new CombineCondition();
put("id", "TEST_FIELD_ID"); condition.setCustomField(true);
put("operator", "in"); condition.setName("TEST_FIELD_ID");
put("value", "222"); condition.setOperator(CombineCondition.CombineConditionOperator.IN.name());
put("type", "List"); condition.setValue("222");
}})); combineSearch.setConditions(List.of());
request.setCombine(map); request.setCombineSearch(combineSearch);
MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_LIST_URL, request); MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_LIST_URL, request);
Pager<List<FunctionalCasePageDTO>> tableData = JSON.parseObject(JSON.toJSONString( Pager<List<FunctionalCasePageDTO>> tableData = JSON.parseObject(JSON.toJSONString(
JSON.parseObject(mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), JSON.parseObject(mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()),

View File

@ -5,7 +5,7 @@ import io.metersphere.project.api.assertion.body.MsDocumentAssertion;
import io.metersphere.project.api.assertion.body.MsJSONPathAssertion; import io.metersphere.project.api.assertion.body.MsJSONPathAssertion;
import io.metersphere.project.api.assertion.body.MsRegexAssertion; import io.metersphere.project.api.assertion.body.MsRegexAssertion;
import io.metersphere.project.api.assertion.body.MsXPathAssertion; import io.metersphere.project.api.assertion.body.MsXPathAssertion;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.assertion; package io.metersphere.project.api.assertion;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.assertion; package io.metersphere.project.api.assertion;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.assertion; package io.metersphere.project.api.assertion;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package io.metersphere.project.api.assertion.body; package io.metersphere.project.api.assertion.body;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;

View File

@ -2,7 +2,7 @@ package io.metersphere.project.api.assertion.body;
import io.metersphere.sdk.constants.MsAssertionCondition; import io.metersphere.sdk.constants.MsAssertionCondition;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.assertion.body; package io.metersphere.project.api.assertion.body;
import io.metersphere.sdk.constants.MsAssertionCondition; import io.metersphere.sdk.constants.MsAssertionCondition;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.assertion.body; package io.metersphere.project.api.assertion.body;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;

View File

@ -3,7 +3,7 @@ package io.metersphere.project.api.processor;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.project.constants.ScriptLanguageType; import io.metersphere.project.constants.ScriptLanguageType;
import io.metersphere.project.dto.CommonScriptInfo; import io.metersphere.project.dto.CommonScriptInfo;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -2,7 +2,7 @@ package io.metersphere.project.api.processor.extract;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.processor.extract; package io.metersphere.project.api.processor.extract;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
@Data @Data

View File

@ -1,6 +1,6 @@
package io.metersphere.project.api.processor.extract; package io.metersphere.project.api.processor.extract;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.api.processor.extract; package io.metersphere.project.api.processor.extract;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
/** /**

View File

@ -1,7 +1,7 @@
package io.metersphere.project.dto; package io.metersphere.project.dto;
import io.metersphere.sdk.constants.FakeErrorType; import io.metersphere.sdk.constants.FakeErrorType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,7 +1,7 @@
package io.metersphere.project.dto.customfunction.request; package io.metersphere.project.dto.customfunction.request;
import io.metersphere.project.constants.ScriptLanguageType; import io.metersphere.project.constants.ScriptLanguageType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,6 +1,6 @@
package io.metersphere.project.dto.environment.auth; package io.metersphere.project.dto.environment.auth;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import lombok.Data; import lombok.Data;
import java.util.HashMap; import java.util.HashMap;

View File

@ -3,7 +3,7 @@ package io.metersphere.project.dto.environment.http;
import io.metersphere.project.api.KeyValueEnableParam; import io.metersphere.project.api.KeyValueEnableParam;
import io.metersphere.project.dto.environment.auth.HTTPAuthConfig; import io.metersphere.project.dto.environment.auth.HTTPAuthConfig;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package io.metersphere.project.dto.environment.http; package io.metersphere.project.dto.environment.http;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -1,9 +1,10 @@
package io.metersphere.system.constants; package io.metersphere.system.constants;
import io.metersphere.system.dto.UserViewDTO; import io.metersphere.system.dto.UserViewDTO;
import io.metersphere.system.dto.sdk.CombineCondition; import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.system.dto.sdk.CombineSearch; import io.metersphere.sdk.dto.CombineSearch;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -21,7 +22,7 @@ public enum InternalUserView {
UserViewDTO userViewDTO = getUserViewDTO("my_follow"); UserViewDTO userViewDTO = getUserViewDTO("my_follow");
CombineCondition condition = new CombineCondition(); CombineCondition condition = new CombineCondition();
condition.setName("follower"); condition.setName("follower");
condition.setValue(getCurrentUserValue()); condition.setValue(getCurrentUserArrayValue());
condition.setOperator(CombineCondition.CombineConditionOperator.IN.name()); condition.setOperator(CombineCondition.CombineConditionOperator.IN.name());
userViewDTO.setConditions(List.of(condition)); userViewDTO.setConditions(List.of(condition));
return userViewDTO; return userViewDTO;
@ -30,7 +31,7 @@ public enum InternalUserView {
UserViewDTO userViewDTO = getUserViewDTO("my_create"); UserViewDTO userViewDTO = getUserViewDTO("my_create");
CombineCondition condition = new CombineCondition(); CombineCondition condition = new CombineCondition();
condition.setName("createUser"); condition.setName("createUser");
condition.setValue(getCurrentUserValue()); condition.setValue(getCurrentUserArrayValue());
condition.setOperator(CombineCondition.CombineConditionOperator.IN.name()); condition.setOperator(CombineCondition.CombineConditionOperator.IN.name());
userViewDTO.setConditions(List.of(condition)); userViewDTO.setConditions(List.of(condition));
return userViewDTO; return userViewDTO;
@ -39,7 +40,7 @@ public enum InternalUserView {
UserViewDTO userViewDTO = getUserViewDTO("my_review"); UserViewDTO userViewDTO = getUserViewDTO("my_review");
CombineCondition condition = new CombineCondition(); CombineCondition condition = new CombineCondition();
condition.setName("reviewUser"); condition.setName("reviewUser");
condition.setValue(getCurrentUserValue()); condition.setValue(getCurrentUserArrayValue());
condition.setOperator(CombineCondition.CombineConditionOperator.IN.name()); condition.setOperator(CombineCondition.CombineConditionOperator.IN.name());
userViewDTO.setConditions(List.of(condition)); userViewDTO.setConditions(List.of(condition));
return userViewDTO; return userViewDTO;
@ -60,8 +61,10 @@ public enum InternalUserView {
userView = initCombineSearchFunc.get(); userView = initCombineSearchFunc.get();
} }
public static String getCurrentUserValue() { public static List<String> getCurrentUserArrayValue() {
return CURRENT_USER; List<String> values = new ArrayList<>(0);
values.add(CURRENT_USER);
return values;
} }
public UserViewDTO getUserView() { public UserViewDTO getUserView() {

View File

@ -1,7 +1,7 @@
package io.metersphere.system.dto; package io.metersphere.system.dto;
import io.metersphere.system.domain.UserView; import io.metersphere.system.domain.UserView;
import io.metersphere.system.dto.sdk.CombineCondition; import io.metersphere.sdk.dto.CombineCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.request; package io.metersphere.system.dto.request;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.request; package io.metersphere.system.dto.request;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.request; package io.metersphere.system.dto.request;
import io.metersphere.system.dto.sdk.CombineSearch; import io.metersphere.sdk.dto.CombineSearch;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.request; package io.metersphere.system.dto.request;
import io.metersphere.system.dto.sdk.CombineSearch; import io.metersphere.sdk.dto.CombineSearch;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,7 @@
package io.metersphere.system.dto.sdk; package io.metersphere.system.dto.sdk;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import io.metersphere.sdk.dto.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Max;

View File

@ -0,0 +1,29 @@
package io.metersphere.system.dto.sdk;
import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch;
import lombok.Data;
import java.util.List;
/**
* @Author: jianxing
* @CreateTime: 2024-08-28 17:31
* 封装 mapper 查询需要的条件
* 搭配 BaseConditionFilter BaseConditionFilterAspect 使用
*/
@Data
public class DBCombineSearch extends CombineSearch {
/**
* 视图的查询条件
*/
private List<CombineCondition> userViewConditions;
/**
* 系统字段筛选条件
*/
private List<CombineCondition> systemFieldConditions;
/**
* 自定义字段筛选条件
*/
private List<CombineCondition> customFiledConditions;
}

View File

@ -2,7 +2,7 @@ package io.metersphere.system.dto.sdk.request;
import io.metersphere.sdk.constants.CustomFieldType; import io.metersphere.sdk.constants.CustomFieldType;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.dto.sdk.request; package io.metersphere.system.dto.sdk.request;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.dto.sdk.request; package io.metersphere.system.dto.sdk.request;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.dto.sdk.request; package io.metersphere.system.dto.sdk.request;
import io.metersphere.sdk.constants.UserRoleType; import io.metersphere.sdk.constants.UserRoleType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,6 +1,6 @@
package io.metersphere.system.dto.table; package io.metersphere.system.dto.table;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -2,7 +2,7 @@ package io.metersphere.system.dto.taskcenter.request;
import io.metersphere.sdk.constants.TaskCenterResourceType; import io.metersphere.sdk.constants.TaskCenterResourceType;
import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,7 +2,7 @@ package io.metersphere.system.dto.taskcenter.request;
import io.metersphere.sdk.constants.TaskCenterResourceType; import io.metersphere.sdk.constants.TaskCenterResourceType;
import io.metersphere.system.dto.sdk.BasePageRequest; import io.metersphere.system.dto.sdk.BasePageRequest;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,7 +2,7 @@ package io.metersphere.system.dto.taskcenter.request;
import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.dto.taskcenter.enums.ScheduleTagType; import io.metersphere.system.dto.taskcenter.enums.ScheduleTagType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,7 +2,7 @@ package io.metersphere.system.dto.taskcenter.request;
import io.metersphere.system.dto.sdk.BasePageRequest; import io.metersphere.system.dto.sdk.BasePageRequest;
import io.metersphere.system.dto.taskcenter.enums.ScheduleTagType; import io.metersphere.system.dto.taskcenter.enums.ScheduleTagType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -0,0 +1,15 @@
package io.metersphere.system.interceptor;
import java.lang.annotation.*;
/**
* 标记需要处理 BaseCondition 查询条件
* BaseConditionFilterAspect 处理切面逻辑
* {@link BaseConditionFilterAspect}
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BaseConditionFilter {
}

View File

@ -0,0 +1,112 @@
package io.metersphere.system.interceptor;
import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.constants.InternalUserView;
import io.metersphere.system.dto.UserViewDTO;
import io.metersphere.system.dto.sdk.*;
import io.metersphere.system.utils.SessionUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
/**
* @Author: jianxing
* @CreateTime: 2024-08-28 17:31
* 拦截高级搜索等查询
* 处理高级搜索等通用查询条件
* 1. 处理视图查询条件
* 2. 预先过滤不合法的查询条件
* 3. 拆分系统字段和自定义字段
* 4. 处理成员选项中的 CURRENT_USER
*/
@Aspect
@Component
public class BaseConditionFilterAspect {
@Pointcut("@annotation(io.metersphere.system.interceptor.BaseConditionFilter)")
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
if (arg instanceof BaseCondition baseCondition) {
parseBaseCondition(baseCondition);
} else {
try {
// 批量操作
Method getCondition = arg.getClass().getMethod("getCondition");
BaseCondition baseCondition = (BaseCondition) getCondition.invoke(arg);
parseBaseCondition(baseCondition);
} catch (Exception e) {
// do nothing
}
}
}
}
private void parseBaseCondition(BaseCondition baseCondition) {
CombineSearch combineSearch = baseCondition.getCombineSearch();
if (combineSearch == null) {
return;
}
List<CombineCondition> validConditions = getValidConditions(combineSearch.getConditions());
replaceCurrentUser(validConditions);
List<CombineCondition> systemFieldConditions = validConditions.stream().filter(item -> !BooleanUtils.isTrue(item.getCustomField())).toList();
List<CombineCondition> customFieldConditions = validConditions.stream().filter(item -> BooleanUtils.isTrue(item.getCustomField())).toList();
// 拆分系统字段和自定义字段
DBCombineSearch dbCombineSearch = BeanUtils.copyBean(new DBCombineSearch(), combineSearch);
dbCombineSearch.setSystemFieldConditions(systemFieldConditions);
dbCombineSearch.setCustomFiledConditions(customFieldConditions);
baseCondition.setCombineSearch(dbCombineSearch);
// 处理视图查询条件
String viewId = baseCondition.getViewId();
dbCombineSearch.setUserViewConditions(List.of());
for (InternalUserView internalUserView : InternalUserView.values()) {
UserViewDTO userView = internalUserView.getUserView();
if (StringUtils.equals(userView.getId(), viewId)) {
replaceCurrentUser(userView.getConditions());
dbCombineSearch.setUserViewConditions(userView.getConditions());
}
}
}
/**
* 处理成员选项中的 CURRENT_USER
* 替换当前用户的用户ID
* @param validConditions
*/
private void replaceCurrentUser(List<CombineCondition> validConditions) {
for (CombineCondition validCondition : validConditions) {
Object value = validCondition.getValue();
if (value instanceof List arrayValues) {
for (int i = 0; i < arrayValues.size(); i++) {
Object arrayValue = arrayValues.get(i);
if (arrayValue != null && StringUtils.equals(arrayValue.toString(), InternalUserView.CURRENT_USER)) {
// 替换当前用户的用户ID
arrayValues.set(i, SessionUtils.getUserId());
}
}
}
}
}
public List<CombineCondition> getValidConditions(List<CombineCondition> conditions) {
if (CollectionUtils.isEmpty(conditions)) {
return List.of();
}
return conditions.stream().filter(CombineCondition::valid).toList();
}
}

View File

@ -2,7 +2,7 @@ package io.metersphere.system.log.vo;
import io.metersphere.sdk.constants.UserRoleType; import io.metersphere.sdk.constants.UserRoleType;
import io.metersphere.system.dto.sdk.BasePageRequest; import io.metersphere.system.dto.sdk.BasePageRequest;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,44 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.system.mapper.BaseMapper"> <mapper namespace="io.metersphere.system.mapper.BaseMapper">
<sql id="customFiledConditions">
<trim suffixOverrides="AND|OR">
<foreach collection="${conditions}" item="condition">
<trim prefix="(" suffix=")">
field_id = #{condition.name}
and
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="condition" value="condition"/>
<property name="column" value="value"/>
</include>
</trim>
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
<property name="searchMode" value="request.combineSearch.searchMode"/>
</include>
</foreach>
</trim>
</sql>
<sql id="condition"> <sql id="condition">
<trim prefix="(" suffix=")">
<choose> <choose>
<when test='${object}.operator == "like"'> <when test="${condition}.operator == 'CONTAINS'">
like CONCAT('%', #{${object}.value},'%') ${column} like CONCAT('%', #{condition.value},'%')
</when> </when>
<when test='${object}.operator == "not like"'> <when test="${condition}.operator == 'NOT_CONTAINS'">
not like CONCAT('%', #{${object}.value},'%') ${column} not like CONCAT('%', #{condition.value},'%')
</when> </when>
<when test='${object}.operator == "in"'> <when test="${condition}.operator == 'IN'">
in ${column} in
<foreach collection="${object}.value" item="v" separator="," open="(" close=")"> <foreach collection="${condition}.value" item="v" separator="," open="(" close=")">
#{v} #{v}
</foreach> </foreach>
</when> </when>
<when test='${object}.operator == "not in"'> <when test="${condition}.operator == 'NOT_IN'">
not in ${column} not in
<foreach collection="${object}.value" item="v" separator="," open="(" close=")"> <foreach collection="${condition}.value" item="v" separator="," open="(" close=")">
#{v} #{v}
</foreach> </foreach>
</when> </when>
<when test='${object}.operator == "between"'> <when test="${condition}.operator == 'BETWEEN'">
between #{${object}.value[0]} and #{${object}.value[1]} ${column} between #{condition.value[0]} and #{condition.value[1]}
</when> </when>
<when test='${object}.operator == "gt"'> <when test="${condition}.operator == 'GT'">
&gt; #{${object}.value} ${column} &gt; #{condition.value}
</when> </when>
<when test='${object}.operator == "lt"'> <when test="${condition}.operator == 'LT'">
&lt; #{${object}.value} ${column} &lt; #{condition.value}
</when> </when>
<when test='${object}.operator == "ge"'> <when test="${condition}.operator == 'COUNT_GT'">
&gt;= #{${object}.value} JSON_LENGTH(${column}) &gt; #{condition.value}
</when> </when>
<when test='${object}.operator == "le"'> <when test="${condition}.operator == 'COUNT_LT'">
&lt;= #{${object}.value} JSON_LENGTH(${column}) &lt; #{condition.value}
</when>
<when test="${condition}.operator == 'EMPTY'">
${column} is null or ${column} #{condition.value} = ''
</when>
<when test="${condition}.operator == 'NOT_EMPTY'">
${column} is not null and ${column} #{condition.value} = ''
</when>
<when test="${condition}.operator == 'EQUALS'">
${column} = #{condition.value}
</when>
<when test="${condition}.operator == 'NOT_EQUALS'">
${column} != #{condition.value}
</when>
</choose>
</trim>
</sql>
<sql id="queryType">
<choose>
<when test="${searchMode} == 'AND'">
AND
</when>
<when test="${searchMode} == 'OR'">
OR
</when> </when>
<otherwise>
= #{${object}.value}
</otherwise>
</choose> </choose>
</sql> </sql>

View File

@ -16,7 +16,7 @@ import io.metersphere.system.dto.UserViewDTO;
import io.metersphere.system.dto.UserViewListGroupedDTO; import io.metersphere.system.dto.UserViewListGroupedDTO;
import io.metersphere.system.dto.request.UserViewAddRequest; import io.metersphere.system.dto.request.UserViewAddRequest;
import io.metersphere.system.dto.request.UserViewUpdateRequest; import io.metersphere.system.dto.request.UserViewUpdateRequest;
import io.metersphere.system.dto.sdk.CombineCondition; import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.system.mapper.ExtUserViewMapper; import io.metersphere.system.mapper.ExtUserViewMapper;
import io.metersphere.system.mapper.UserViewConditionMapper; import io.metersphere.system.mapper.UserViewConditionMapper;
import io.metersphere.system.mapper.UserViewMapper; import io.metersphere.system.mapper.UserViewMapper;
@ -65,6 +65,8 @@ public class UserViewService {
userViewDTO.setName(translateInternalView(userView.getName())); userViewDTO.setName(translateInternalView(userView.getName()));
userViewDTO.setViewType(viewType.name()); userViewDTO.setViewType(viewType.name());
userViewDTO.setUserId(userId); userViewDTO.setUserId(userId);
// 系统内置视图前端不展示查询条件
userViewDTO.setConditions(List.of());
return userViewDTO; return userViewDTO;
} }
} }

View File

@ -1,105 +0,0 @@
package io.metersphere.system.utils;
import io.metersphere.sdk.constants.CustomFieldType;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.dto.sdk.BaseCondition;
import lombok.experimental.UtilityClass;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 自定义字段处理工具类
*/
@UtilityClass
public class CustomFieldUtils {
public static final String COMBINE_CUSTOM = "customs";
public static final String COMBINE_CUSTOM_FIELD_TYPE = "type";
public static final String COMBINE_CUSTOM_FIELD_VALUE = "value";
public static final String COMBINE_CUSTOM_FIELD_OPERATOR = "operator";
public static final String IS_CURRENT_USER = "current user";
public static final String CUSTOM_MULTIPLE_PREFIX = "custom_multiple";
/**
* 设置列表查询的多选字段参数
* @param request 请求参数
*/
public static void setBaseQueryRequestCustomMultipleFields(BaseCondition request, String userId) {
handleFilterCustomMultipleFields(request);
handleCombineFields(request, userId);
}
private static void handleFilterCustomMultipleFields(BaseCondition request) {
if (MapUtils.isNotEmpty(request.getFilter())) {
request.getFilter().forEach((key, value) -> {
if (key.startsWith(CUSTOM_MULTIPLE_PREFIX) && CollectionUtils.isNotEmpty(value)) {
List<String> jsonValues = value.stream().map(item -> "[\"".concat(item).concat("\"]")).toList();
request.getFilter().put(key, jsonValues);
}
});
}
}
private static void handleCombineFields(BaseCondition request, String userId) {
Map<String, Object> combine = request.getCombine();
if (MapUtils.isNotEmpty(combine)) {
combine.forEach((k, v) -> {
if (StringUtils.equals(k, COMBINE_CUSTOM) && ObjectUtils.isNotEmpty(v)) {
handleCombineCustomFields((List<Map<String, Object>>) v, userId);
} else {
handleCombineField(v, userId);
}
});
}
}
private static void handleCombineCustomFields(List<Map<String, Object>> customs, String userId) {
customs.forEach(custom -> {
String operator = custom.get(COMBINE_CUSTOM_FIELD_OPERATOR).toString();
if (StringUtils.equalsIgnoreCase(operator, IS_CURRENT_USER)) {
custom.put(COMBINE_CUSTOM_FIELD_VALUE, userId);
return;
}
String fieldType = custom.get(COMBINE_CUSTOM_FIELD_TYPE).toString();
String fieldValue = custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString();
if (StringUtils.equalsAny(fieldType, CustomFieldType.MULTIPLE_MEMBER.name(),
CustomFieldType.CHECKBOX.name(), CustomFieldType.MULTIPLE_SELECT.name()) && StringUtils.isNotEmpty(fieldValue)) {
List<String> customValues = JSON.parseArray(fieldValue, String.class);
List<String> jsonValues = customValues.stream().map(item -> "JSON_CONTAINS(`value`, '[\"".concat(item).concat("\"]')")).toList();
custom.put(COMBINE_CUSTOM_FIELD_VALUE, "(".concat(StringUtils.join(jsonValues, " OR ")).concat(")"));
}
});
}
private static void handleCombineField(Object v, String userId) {
Map<String, Object> combineField = new HashMap<>((Map<String, Object>) v);
if (StringUtils.equalsIgnoreCase(combineField.get(COMBINE_CUSTOM_FIELD_OPERATOR).toString(), IS_CURRENT_USER)) {
combineField.put(COMBINE_CUSTOM_FIELD_VALUE, userId);
}
}
/**
* 多选字段追加值
* @param originalVal 原始值
* @param appendVal 追加值
* @return 追加后的值
*/
public static String appendToMultipleCustomField(String originalVal, String appendVal) {
if (StringUtils.isEmpty(originalVal)) {
return appendVal;
}
List<String> originalList = JSON.parseArray(originalVal, String.class);
List<String> appendList = JSON.parseArray(appendVal, String.class);
originalList.addAll(appendList);
// 追加后需去重
return JSON.toJSONString(originalList.stream().distinct().toList());
}
}

View File

@ -2,7 +2,7 @@ package io.metersphere.system.base.param;
import io.metersphere.sdk.constants.ValueEnum; import io.metersphere.sdk.constants.ValueEnum;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.base.param; package io.metersphere.system.base.param;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -1,132 +0,0 @@
package io.metersphere.system.controller;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.dto.sdk.BaseCondition;
import io.metersphere.system.utils.CustomFieldUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* @author: LAN
* @date: 2023/12/14 10:18
* @version: 1.0
*/
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class CustomFieldTests extends BaseTest {
@Test
@Order(1)
void testSetBaseQueryRequestCustomMultipleFields() {
BaseCondition baseCondition = new BaseCondition();
Map<String, List<String>> filters = new HashMap<>();
filters.put("status", Arrays.asList("Underway", "Completed"));
filters.put("custom_multiple_custom-field", List.of("oasis"));
Map<String, Object> map = new HashMap<>();
map.put("name", Map.of("operator", "like", "value", "test"));
map.put("method", Map.of("operator", "in", "value", Arrays.asList("GET", "POST")));
map.put("createUser", Map.of("operator", "current user", "value", StringUtils.EMPTY));
List<Map<String, Object>> customs = new ArrayList<>();
Map<String, Object> custom = new HashMap<>();
custom.put("id", "test_field");
custom.put("operator", "in");
custom.put("type", "MULTIPLE_SELECT");
custom.put("value", JSON.toJSONString(List.of("test", "default")));
customs.add(custom);
Map<String, Object> currentUserCustom = new HashMap<>();
currentUserCustom.put("id", "test_field");
currentUserCustom.put("operator", "current user");
currentUserCustom.put("type", "MULTIPLE_MEMBER");
currentUserCustom.put("value", "current user");
customs.add(currentUserCustom);
currentUserCustom.put("value", "");
customs.add(currentUserCustom);
map.put("customs", customs);
baseCondition.setFilter(filters);
baseCondition.setCombine(map);
// 调用测试方法
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(baseCondition, "admin");
// 验证预期结果
Assertions.assertNotNull(baseCondition.getFilter());
Assertions.assertNotNull(baseCondition.getCombine());
// 验证多选字段是否被正确处理
List<String> customMultipleValues = baseCondition.getFilter().get("custom_multiple_custom-field");
Assertions.assertNotNull(customMultipleValues);
Assertions.assertEquals(1, customMultipleValues.size());
Assertions.assertTrue(customMultipleValues.contains("[\"oasis\"]"));
// 验证 CombineField 方法
Map<String, Object> combineField = (Map<String, Object>) baseCondition.getCombine().get("createUser");
Assertions.assertNotNull(combineField);
Assertions.assertEquals(StringUtils.EMPTY, combineField.get("value"));
}
@Test
void testHandleFilterCustomMultipleFieldsEmptyFilter() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 创建测试数据
BaseCondition baseCondition = new BaseCondition();
// 调用被测试方法
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(baseCondition, "user123");
// 验证预期结果
Assertions.assertNull(baseCondition.getFilter());
}
@Test
void testHandleCombineFieldsEmptyCombine() {
// 创建测试数据
BaseCondition baseCondition = new BaseCondition();
// 调用被测试方法
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(baseCondition, "user123");
// 验证预期结果
Assertions.assertNull(baseCondition.getCombine());
}
@Test
@Order(2)
void testAppendToMultipleCustomFieldWithEmptyOriginalValue() {
// 创建测试数据originalValue 为空
String originalValue = "";
String appendValue = "[\"value2\",\"value3\"]";
// 调用被测试方法
String resultEmptyOriginal = CustomFieldUtils.appendToMultipleCustomField(originalValue, appendValue);
// 验证预期结果
Assertions.assertNotNull(resultEmptyOriginal);
Assertions.assertEquals("[\"value2\",\"value3\"]", resultEmptyOriginal);
}
@Test
@Order(3)
void testAppendToMultipleCustomField() {
// 创建测试数据
String originalValue = "[\"value1\", \"value2\"]";
String appendValue = "[\"value2\", \"value3\"]";
// 调用被测试方法
String result = CustomFieldUtils.appendToMultipleCustomField(originalValue, appendValue);
// 验证预期结果
Assertions.assertNotNull(result);
Assertions.assertEquals("[\"value1\",\"value2\",\"value3\"]", result);
}
}

View File

@ -10,8 +10,8 @@ import io.metersphere.system.dto.UserViewDTO;
import io.metersphere.system.dto.UserViewListGroupedDTO; import io.metersphere.system.dto.UserViewListGroupedDTO;
import io.metersphere.system.dto.request.UserViewAddRequest; import io.metersphere.system.dto.request.UserViewAddRequest;
import io.metersphere.system.dto.request.UserViewUpdateRequest; import io.metersphere.system.dto.request.UserViewUpdateRequest;
import io.metersphere.system.dto.sdk.CombineCondition; import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.system.dto.sdk.CombineSearch; import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.system.mapper.UserViewMapper; import io.metersphere.system.mapper.UserViewMapper;
import io.metersphere.system.service.UserViewService; import io.metersphere.system.service.UserViewService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -167,6 +167,11 @@ public class UserViewControllerTests extends BaseTest {
Assertions.assertEquals(resultData.getName(), "全部数据"); Assertions.assertEquals(resultData.getName(), "全部数据");
Assertions.assertEquals(resultData.getId(), InternalUserView.ALL_DATA.name().toLowerCase()); Assertions.assertEquals(resultData.getId(), InternalUserView.ALL_DATA.name().toLowerCase());
Assertions.assertEquals(resultData.getConditions().size(), 0); Assertions.assertEquals(resultData.getConditions().size(), 0);
mvcResult = this.requestGetWithOkAndReturn(DEFAULT_GET, InternalUserView.MY_CREATE.name());
resultData = getResultData(mvcResult, UserViewDTO.class);
Assertions.assertEquals(resultData.getId(), InternalUserView.MY_CREATE.name().toLowerCase());
Assertions.assertEquals(resultData.getConditions().size(), 0);
} }
@Test @Test

View File

@ -1,7 +1,7 @@
package io.metersphere.system.controller.param; package io.metersphere.system.controller.param;
import io.metersphere.sdk.constants.CustomFieldType; import io.metersphere.sdk.constants.CustomFieldType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.controller.param; package io.metersphere.system.controller.param;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,7 +1,7 @@
package io.metersphere.system.controller.param; package io.metersphere.system.controller.param;
import io.metersphere.sdk.constants.UserRoleType; import io.metersphere.sdk.constants.UserRoleType;
import io.metersphere.system.valid.EnumValue; import io.metersphere.sdk.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@ -1,7 +1,7 @@
package io.metersphere.plan.dto; package io.metersphere.plan.dto;
import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@ -17,7 +17,7 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseCondition; import io.metersphere.sdk.dto.BaseCondition;
import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest; import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest; import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;

View File

@ -85,6 +85,7 @@
<commons-jexl3.version>3.3</commons-jexl3.version> <commons-jexl3.version>3.3</commons-jexl3.version>
<revision>3.x</revision> <revision>3.x</revision>
<monitoring-engine.revision>3.1</monitoring-engine.revision> <monitoring-engine.revision>3.1</monitoring-engine.revision>
<swagger-core-jakarta.revision>2.2.20</swagger-core-jakarta.revision>
</properties> </properties>