feat(项目设置): 缺陷列表基础功能
This commit is contained in:
parent
fc63fa5bc1
commit
3dab64d0f0
|
@ -27,10 +27,13 @@ public class Bug implements Serializable {
|
|||
@Size(min = 1, max = 300, message = "{bug.title.length_range}", groups = {Created.class, Updated.class})
|
||||
private String title;
|
||||
|
||||
@Schema(description = "指派人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.assign_user.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.assign_user.length_range}", groups = {Created.class, Updated.class})
|
||||
private String assignUser;
|
||||
@Schema(description = "处理人集合;预留字段, 后续工作台统计可能需要")
|
||||
private String handleUsers;
|
||||
|
||||
@Schema(description = "处理人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.handle_user.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.handle_user.length_range}", groups = {Created.class, Updated.class})
|
||||
private String handleUser;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
|
@ -55,7 +58,9 @@ public class Bug implements Serializable {
|
|||
@Size(min = 1, max = 50, message = "{bug.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模板ID")
|
||||
@Schema(description = "模板ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.template_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.template_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String templateId;
|
||||
|
||||
@Schema(description = "缺陷平台", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -84,7 +89,8 @@ public class Bug implements Serializable {
|
|||
id("id", "id", "VARCHAR", false),
|
||||
num("num", "num", "INTEGER", false),
|
||||
title("title", "title", "VARCHAR", false),
|
||||
assignUser("assign_user", "assignUser", "VARCHAR", false),
|
||||
handleUsers("handle_users", "handleUsers", "VARCHAR", false),
|
||||
handleUser("handle_user", "handleUser", "VARCHAR", false),
|
||||
createUser("create_user", "createUser", "VARCHAR", false),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
updateUser("update_user", "updateUser", "VARCHAR", false),
|
||||
|
|
|
@ -38,9 +38,9 @@ public class BugAttachment implements Serializable {
|
|||
@NotNull(message = "{bug_attachment.size.not_blank}", groups = {Created.class})
|
||||
private Long size;
|
||||
|
||||
@Schema(description = "是否关联", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{bug_attachment.association.not_blank}", groups = {Created.class})
|
||||
private Boolean association;
|
||||
@Schema(description = "是否本地", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{bug_attachment.local.not_blank}", groups = {Created.class})
|
||||
private Boolean local;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
|
@ -56,7 +56,7 @@ public class BugAttachment implements Serializable {
|
|||
fileId("file_id", "fileId", "VARCHAR", false),
|
||||
fileName("file_name", "fileName", "VARCHAR", false),
|
||||
size("size", "size", "BIGINT", true),
|
||||
association("association", "association", "BIT", false),
|
||||
local("local", "local", "BIT", true),
|
||||
createUser("create_user", "createUser", "VARCHAR", false),
|
||||
createTime("create_time", "createTime", "BIGINT", false);
|
||||
|
||||
|
|
|
@ -444,63 +444,63 @@ public class BugAttachmentExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationIsNull() {
|
||||
addCriterion("association is null");
|
||||
public Criteria andLocalIsNull() {
|
||||
addCriterion("`local` is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationIsNotNull() {
|
||||
addCriterion("association is not null");
|
||||
public Criteria andLocalIsNotNull() {
|
||||
addCriterion("`local` is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationEqualTo(Boolean value) {
|
||||
addCriterion("association =", value, "association");
|
||||
public Criteria andLocalEqualTo(Boolean value) {
|
||||
addCriterion("`local` =", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationNotEqualTo(Boolean value) {
|
||||
addCriterion("association <>", value, "association");
|
||||
public Criteria andLocalNotEqualTo(Boolean value) {
|
||||
addCriterion("`local` <>", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationGreaterThan(Boolean value) {
|
||||
addCriterion("association >", value, "association");
|
||||
public Criteria andLocalGreaterThan(Boolean value) {
|
||||
addCriterion("`local` >", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("association >=", value, "association");
|
||||
public Criteria andLocalGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("`local` >=", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationLessThan(Boolean value) {
|
||||
addCriterion("association <", value, "association");
|
||||
public Criteria andLocalLessThan(Boolean value) {
|
||||
addCriterion("`local` <", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("association <=", value, "association");
|
||||
public Criteria andLocalLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("`local` <=", value, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationIn(List<Boolean> values) {
|
||||
addCriterion("association in", values, "association");
|
||||
public Criteria andLocalIn(List<Boolean> values) {
|
||||
addCriterion("`local` in", values, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationNotIn(List<Boolean> values) {
|
||||
addCriterion("association not in", values, "association");
|
||||
public Criteria andLocalNotIn(List<Boolean> values) {
|
||||
addCriterion("`local` not in", values, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("association between", value1, value2, "association");
|
||||
public Criteria andLocalBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("`local` between", value1, value2, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssociationNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("association not between", value1, value2, "association");
|
||||
public Criteria andLocalNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("`local` not between", value1, value2, "local");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,9 @@ public class BugComment implements Serializable {
|
|||
private Long updateTime;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug_comment.description.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 65535, message = "{bug_comment.description.length_range}", groups = {Created.class, Updated.class})
|
||||
private String description;
|
||||
@NotBlank(message = "{bug_comment.content.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 65535, message = "{bug_comment.content.length_range}", groups = {Created.class, Updated.class})
|
||||
private String content;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -61,7 +61,7 @@ public class BugComment implements Serializable {
|
|||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
updateUser("update_user", "updateUser", "VARCHAR", false),
|
||||
updateTime("update_time", "updateTime", "BIGINT", false),
|
||||
description("description", "description", "LONGVARCHAR", false);
|
||||
content("content", "content", "LONGVARCHAR", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -304,73 +304,143 @@ public class BugExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserIsNull() {
|
||||
addCriterion("assign_user is null");
|
||||
public Criteria andHandleUsersIsNull() {
|
||||
addCriterion("handle_users is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserIsNotNull() {
|
||||
addCriterion("assign_user is not null");
|
||||
public Criteria andHandleUsersIsNotNull() {
|
||||
addCriterion("handle_users is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserEqualTo(String value) {
|
||||
addCriterion("assign_user =", value, "assignUser");
|
||||
public Criteria andHandleUsersEqualTo(String value) {
|
||||
addCriterion("handle_users =", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserNotEqualTo(String value) {
|
||||
addCriterion("assign_user <>", value, "assignUser");
|
||||
public Criteria andHandleUsersNotEqualTo(String value) {
|
||||
addCriterion("handle_users <>", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserGreaterThan(String value) {
|
||||
addCriterion("assign_user >", value, "assignUser");
|
||||
public Criteria andHandleUsersGreaterThan(String value) {
|
||||
addCriterion("handle_users >", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("assign_user >=", value, "assignUser");
|
||||
public Criteria andHandleUsersGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("handle_users >=", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserLessThan(String value) {
|
||||
addCriterion("assign_user <", value, "assignUser");
|
||||
public Criteria andHandleUsersLessThan(String value) {
|
||||
addCriterion("handle_users <", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserLessThanOrEqualTo(String value) {
|
||||
addCriterion("assign_user <=", value, "assignUser");
|
||||
public Criteria andHandleUsersLessThanOrEqualTo(String value) {
|
||||
addCriterion("handle_users <=", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserLike(String value) {
|
||||
addCriterion("assign_user like", value, "assignUser");
|
||||
public Criteria andHandleUsersLike(String value) {
|
||||
addCriterion("handle_users like", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserNotLike(String value) {
|
||||
addCriterion("assign_user not like", value, "assignUser");
|
||||
public Criteria andHandleUsersNotLike(String value) {
|
||||
addCriterion("handle_users not like", value, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserIn(List<String> values) {
|
||||
addCriterion("assign_user in", values, "assignUser");
|
||||
public Criteria andHandleUsersIn(List<String> values) {
|
||||
addCriterion("handle_users in", values, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserNotIn(List<String> values) {
|
||||
addCriterion("assign_user not in", values, "assignUser");
|
||||
public Criteria andHandleUsersNotIn(List<String> values) {
|
||||
addCriterion("handle_users not in", values, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserBetween(String value1, String value2) {
|
||||
addCriterion("assign_user between", value1, value2, "assignUser");
|
||||
public Criteria andHandleUsersBetween(String value1, String value2) {
|
||||
addCriterion("handle_users between", value1, value2, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andAssignUserNotBetween(String value1, String value2) {
|
||||
addCriterion("assign_user not between", value1, value2, "assignUser");
|
||||
public Criteria andHandleUsersNotBetween(String value1, String value2) {
|
||||
addCriterion("handle_users not between", value1, value2, "handleUsers");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserIsNull() {
|
||||
addCriterion("handle_user is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserIsNotNull() {
|
||||
addCriterion("handle_user is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserEqualTo(String value) {
|
||||
addCriterion("handle_user =", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserNotEqualTo(String value) {
|
||||
addCriterion("handle_user <>", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserGreaterThan(String value) {
|
||||
addCriterion("handle_user >", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("handle_user >=", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserLessThan(String value) {
|
||||
addCriterion("handle_user <", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserLessThanOrEqualTo(String value) {
|
||||
addCriterion("handle_user <=", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserLike(String value) {
|
||||
addCriterion("handle_user like", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserNotLike(String value) {
|
||||
addCriterion("handle_user not like", value, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserIn(List<String> values) {
|
||||
addCriterion("handle_user in", values, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserNotIn(List<String> values) {
|
||||
addCriterion("handle_user not in", values, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserBetween(String value1, String value2) {
|
||||
addCriterion("handle_user between", value1, value2, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andHandleUserNotBetween(String value1, String value2) {
|
||||
addCriterion("handle_user not between", value1, value2, "handleUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@ public class BugHistory implements Serializable {
|
|||
@Schema(description = "变更记录批次号")
|
||||
private Integer num;
|
||||
|
||||
@Schema(description = "变更类型; IMPORT/EDIT/ROLLBACK")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "回退来源")
|
||||
private String rollbackSourceId;
|
||||
|
||||
@Schema(description = "操作人")
|
||||
private String createUser;
|
||||
|
||||
|
@ -43,6 +49,8 @@ public class BugHistory implements Serializable {
|
|||
id("id", "id", "VARCHAR", false),
|
||||
bugId("bug_id", "bugId", "VARCHAR", false),
|
||||
num("num", "num", "INTEGER", false),
|
||||
type("type", "type", "VARCHAR", true),
|
||||
rollbackSourceId("rollback_source_id", "rollbackSourceId", "VARCHAR", false),
|
||||
createUser("create_user", "createUser", "VARCHAR", false),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
content("content", "content", "LONGVARBINARY", false);
|
||||
|
|
|
@ -304,6 +304,146 @@ public class BugHistoryExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeIsNull() {
|
||||
addCriterion("`type` is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeIsNotNull() {
|
||||
addCriterion("`type` is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeEqualTo(String value) {
|
||||
addCriterion("`type` =", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeNotEqualTo(String value) {
|
||||
addCriterion("`type` <>", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeGreaterThan(String value) {
|
||||
addCriterion("`type` >", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("`type` >=", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeLessThan(String value) {
|
||||
addCriterion("`type` <", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeLessThanOrEqualTo(String value) {
|
||||
addCriterion("`type` <=", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeLike(String value) {
|
||||
addCriterion("`type` like", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeNotLike(String value) {
|
||||
addCriterion("`type` not like", value, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeIn(List<String> values) {
|
||||
addCriterion("`type` in", values, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeNotIn(List<String> values) {
|
||||
addCriterion("`type` not in", values, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeBetween(String value1, String value2) {
|
||||
addCriterion("`type` between", value1, value2, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTypeNotBetween(String value1, String value2) {
|
||||
addCriterion("`type` not between", value1, value2, "type");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdIsNull() {
|
||||
addCriterion("rollback_source_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdIsNotNull() {
|
||||
addCriterion("rollback_source_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdEqualTo(String value) {
|
||||
addCriterion("rollback_source_id =", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdNotEqualTo(String value) {
|
||||
addCriterion("rollback_source_id <>", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdGreaterThan(String value) {
|
||||
addCriterion("rollback_source_id >", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("rollback_source_id >=", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdLessThan(String value) {
|
||||
addCriterion("rollback_source_id <", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("rollback_source_id <=", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdLike(String value) {
|
||||
addCriterion("rollback_source_id like", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdNotLike(String value) {
|
||||
addCriterion("rollback_source_id not like", value, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdIn(List<String> values) {
|
||||
addCriterion("rollback_source_id in", values, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdNotIn(List<String> values) {
|
||||
addCriterion("rollback_source_id not in", values, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdBetween(String value1, String value2) {
|
||||
addCriterion("rollback_source_id between", value1, value2, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andRollbackSourceIdNotBetween(String value1, String value2) {
|
||||
addCriterion("rollback_source_id not between", value1, value2, "rollbackSourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateUserIsNull() {
|
||||
addCriterion("create_user is null");
|
||||
return (Criteria) this;
|
||||
|
|
|
@ -18,9 +18,7 @@ public class BugRelationCase implements Serializable {
|
|||
@Size(min = 1, max = 50, message = "{bug_relation_case.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "关联功能用例ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug_relation_case.case_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{bug_relation_case.case_id.length_range}", groups = {Created.class, Updated.class})
|
||||
@Schema(description = "关联功能用例ID")
|
||||
private String caseId;
|
||||
|
||||
@Schema(description = "缺陷ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
|
||||
<result column="file_name" jdbcType="VARCHAR" property="fileName" />
|
||||
<result column="size" jdbcType="BIGINT" property="size" />
|
||||
<result column="association" jdbcType="BIT" property="association" />
|
||||
<result column="local" jdbcType="BIT" property="local" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
</resultMap>
|
||||
|
@ -70,7 +70,7 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, bug_id, file_id, file_name, `size`, association, create_user, create_time
|
||||
id, bug_id, file_id, file_name, `size`, `local`, create_user, create_time
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.bug.domain.BugAttachmentExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -104,11 +104,11 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.bug.domain.BugAttachment">
|
||||
insert into bug_attachment (id, bug_id, file_id,
|
||||
file_name, `size`, association,
|
||||
create_user, create_time)
|
||||
file_name, `size`, `local`, create_user,
|
||||
create_time)
|
||||
values (#{id,jdbcType=VARCHAR}, #{bugId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR},
|
||||
#{fileName,jdbcType=VARCHAR}, #{size,jdbcType=BIGINT}, #{association,jdbcType=BIT},
|
||||
#{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT})
|
||||
#{fileName,jdbcType=VARCHAR}, #{size,jdbcType=BIGINT}, #{local,jdbcType=BIT}, #{createUser,jdbcType=VARCHAR},
|
||||
#{createTime,jdbcType=BIGINT})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.bug.domain.BugAttachment">
|
||||
insert into bug_attachment
|
||||
|
@ -128,8 +128,8 @@
|
|||
<if test="size != null">
|
||||
`size`,
|
||||
</if>
|
||||
<if test="association != null">
|
||||
association,
|
||||
<if test="local != null">
|
||||
`local`,
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user,
|
||||
|
@ -154,8 +154,8 @@
|
|||
<if test="size != null">
|
||||
#{size,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="association != null">
|
||||
#{association,jdbcType=BIT},
|
||||
<if test="local != null">
|
||||
#{local,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
#{createUser,jdbcType=VARCHAR},
|
||||
|
@ -189,8 +189,8 @@
|
|||
<if test="record.size != null">
|
||||
`size` = #{record.size,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.association != null">
|
||||
association = #{record.association,jdbcType=BIT},
|
||||
<if test="record.local != null">
|
||||
`local` = #{record.local,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.createUser != null">
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
|
@ -210,7 +210,7 @@
|
|||
file_id = #{record.fileId,jdbcType=VARCHAR},
|
||||
file_name = #{record.fileName,jdbcType=VARCHAR},
|
||||
`size` = #{record.size,jdbcType=BIGINT},
|
||||
association = #{record.association,jdbcType=BIT},
|
||||
`local` = #{record.local,jdbcType=BIT},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT}
|
||||
<if test="_parameter != null">
|
||||
|
@ -232,8 +232,8 @@
|
|||
<if test="size != null">
|
||||
`size` = #{size,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="association != null">
|
||||
association = #{association,jdbcType=BIT},
|
||||
<if test="local != null">
|
||||
`local` = #{local,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
|
@ -250,18 +250,18 @@
|
|||
file_id = #{fileId,jdbcType=VARCHAR},
|
||||
file_name = #{fileName,jdbcType=VARCHAR},
|
||||
`size` = #{size,jdbcType=BIGINT},
|
||||
association = #{association,jdbcType=BIT},
|
||||
`local` = #{local,jdbcType=BIT},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into bug_attachment
|
||||
(id, bug_id, file_id, file_name, `size`, association, create_user, create_time)
|
||||
(id, bug_id, file_id, file_name, `size`, `local`, create_user, create_time)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.bugId,jdbcType=VARCHAR}, #{item.fileId,jdbcType=VARCHAR},
|
||||
#{item.fileName,jdbcType=VARCHAR}, #{item.size,jdbcType=BIGINT}, #{item.association,jdbcType=BIT},
|
||||
#{item.fileName,jdbcType=VARCHAR}, #{item.size,jdbcType=BIGINT}, #{item.local,jdbcType=BIT},
|
||||
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
@ -290,8 +290,8 @@
|
|||
<if test="'size'.toString() == column.value">
|
||||
#{item.size,jdbcType=BIGINT}
|
||||
</if>
|
||||
<if test="'association'.toString() == column.value">
|
||||
#{item.association,jdbcType=BIT}
|
||||
<if test="'local'.toString() == column.value">
|
||||
#{item.local,jdbcType=BIT}
|
||||
</if>
|
||||
<if test="'create_user'.toString() == column.value">
|
||||
#{item.createUser,jdbcType=VARCHAR}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="bug_id" jdbcType="VARCHAR" property="bugId" />
|
||||
<result column="reply_user" jdbcType="VARCHAR" property="replyUser" />
|
||||
<result column="notifier" jdbcType="VARCHAR" property="notifier" />
|
||||
<result column="parent_id" jdbcType="VARCHAR" property="parentId" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
|
@ -12,7 +13,7 @@
|
|||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.bug.domain.BugComment">
|
||||
<result column="description" jdbcType="LONGVARCHAR" property="description" />
|
||||
<result column="content" jdbcType="LONGVARCHAR" property="content" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -73,10 +74,11 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, bug_id, reply_user, parent_id, create_user, create_time, update_user, update_time
|
||||
id, bug_id, reply_user, notifier, parent_id, create_user, create_time, update_user,
|
||||
update_time
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
description
|
||||
content
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.bug.domain.BugCommentExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
|
@ -128,13 +130,13 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.bug.domain.BugComment">
|
||||
insert into bug_comment (id, bug_id, reply_user,
|
||||
parent_id, create_user, create_time,
|
||||
update_user, update_time, description
|
||||
)
|
||||
notifier, parent_id, create_user,
|
||||
create_time, update_user, update_time,
|
||||
content)
|
||||
values (#{id,jdbcType=VARCHAR}, #{bugId,jdbcType=VARCHAR}, #{replyUser,jdbcType=VARCHAR},
|
||||
#{parentId,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT}, #{description,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
#{notifier,jdbcType=VARCHAR}, #{parentId,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
|
||||
#{createTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
|
||||
#{content,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.bug.domain.BugComment">
|
||||
insert into bug_comment
|
||||
|
@ -148,6 +150,9 @@
|
|||
<if test="replyUser != null">
|
||||
reply_user,
|
||||
</if>
|
||||
<if test="notifier != null">
|
||||
notifier,
|
||||
</if>
|
||||
<if test="parentId != null">
|
||||
parent_id,
|
||||
</if>
|
||||
|
@ -163,8 +168,8 @@
|
|||
<if test="updateTime != null">
|
||||
update_time,
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description,
|
||||
<if test="content != null">
|
||||
content,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
|
@ -177,6 +182,9 @@
|
|||
<if test="replyUser != null">
|
||||
#{replyUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="notifier != null">
|
||||
#{notifier,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="parentId != null">
|
||||
#{parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -192,8 +200,8 @@
|
|||
<if test="updateTime != null">
|
||||
#{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
#{description,jdbcType=LONGVARCHAR},
|
||||
<if test="content != null">
|
||||
#{content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
@ -215,6 +223,9 @@
|
|||
<if test="record.replyUser != null">
|
||||
reply_user = #{record.replyUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.notifier != null">
|
||||
notifier = #{record.notifier,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.parentId != null">
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -230,8 +241,8 @@
|
|||
<if test="record.updateTime != null">
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.description != null">
|
||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||
<if test="record.content != null">
|
||||
content = #{record.content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
|
@ -243,12 +254,13 @@
|
|||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
bug_id = #{record.bugId,jdbcType=VARCHAR},
|
||||
reply_user = #{record.replyUser,jdbcType=VARCHAR},
|
||||
notifier = #{record.notifier,jdbcType=VARCHAR},
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_user = #{record.updateUser,jdbcType=VARCHAR},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
description = #{record.description,jdbcType=LONGVARCHAR}
|
||||
content = #{record.content,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -258,6 +270,7 @@
|
|||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
bug_id = #{record.bugId,jdbcType=VARCHAR},
|
||||
reply_user = #{record.replyUser,jdbcType=VARCHAR},
|
||||
notifier = #{record.notifier,jdbcType=VARCHAR},
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
|
@ -276,6 +289,9 @@
|
|||
<if test="replyUser != null">
|
||||
reply_user = #{replyUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="notifier != null">
|
||||
notifier = #{notifier,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="parentId != null">
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -291,8 +307,8 @@
|
|||
<if test="updateTime != null">
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description = #{description,jdbcType=LONGVARCHAR},
|
||||
<if test="content != null">
|
||||
content = #{content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
|
@ -301,18 +317,20 @@
|
|||
update bug_comment
|
||||
set bug_id = #{bugId,jdbcType=VARCHAR},
|
||||
reply_user = #{replyUser,jdbcType=VARCHAR},
|
||||
notifier = #{notifier,jdbcType=VARCHAR},
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_user = #{updateUser,jdbcType=VARCHAR},
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
description = #{description,jdbcType=LONGVARCHAR}
|
||||
content = #{content,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.bug.domain.BugComment">
|
||||
update bug_comment
|
||||
set bug_id = #{bugId,jdbcType=VARCHAR},
|
||||
reply_user = #{replyUser,jdbcType=VARCHAR},
|
||||
notifier = #{notifier,jdbcType=VARCHAR},
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
|
@ -322,14 +340,14 @@
|
|||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into bug_comment
|
||||
(id, bug_id, reply_user, parent_id, create_user, create_time, update_user, update_time,
|
||||
description)
|
||||
(id, bug_id, reply_user, notifier, parent_id, create_user, create_time, update_user,
|
||||
update_time, content)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.bugId,jdbcType=VARCHAR}, #{item.replyUser,jdbcType=VARCHAR},
|
||||
#{item.parentId,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.description,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
#{item.notifier,jdbcType=VARCHAR}, #{item.parentId,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.createTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.content,jdbcType=LONGVARCHAR})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -351,6 +369,9 @@
|
|||
<if test="'reply_user'.toString() == column.value">
|
||||
#{item.replyUser,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'notifier'.toString() == column.value">
|
||||
#{item.notifier,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'parent_id'.toString() == column.value">
|
||||
#{item.parentId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
|
@ -366,8 +387,8 @@
|
|||
<if test="'update_time'.toString() == column.value">
|
||||
#{item.updateTime,jdbcType=BIGINT}
|
||||
</if>
|
||||
<if test="'description'.toString() == column.value">
|
||||
#{item.description,jdbcType=LONGVARCHAR}
|
||||
<if test="'content'.toString() == column.value">
|
||||
#{item.content,jdbcType=LONGVARCHAR}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="bug_id" jdbcType="VARCHAR" property="bugId" />
|
||||
<result column="num" jdbcType="INTEGER" property="num" />
|
||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||
<result column="rollback_source_id" jdbcType="VARCHAR" property="rollbackSourceId" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
</resultMap>
|
||||
|
@ -70,7 +72,7 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, bug_id, num, create_user, create_time
|
||||
id, bug_id, num, `type`, rollback_source_id, create_user, create_time
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
content
|
||||
|
@ -125,11 +127,11 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.bug.domain.BugHistory">
|
||||
insert into bug_history (id, bug_id, num,
|
||||
create_user, create_time, content
|
||||
)
|
||||
`type`, rollback_source_id, create_user,
|
||||
create_time, content)
|
||||
values (#{id,jdbcType=VARCHAR}, #{bugId,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
|
||||
#{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY}
|
||||
)
|
||||
#{type,jdbcType=VARCHAR}, #{rollbackSourceId,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
|
||||
#{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.bug.domain.BugHistory">
|
||||
insert into bug_history
|
||||
|
@ -143,6 +145,12 @@
|
|||
<if test="num != null">
|
||||
num,
|
||||
</if>
|
||||
<if test="type != null">
|
||||
`type`,
|
||||
</if>
|
||||
<if test="rollbackSourceId != null">
|
||||
rollback_source_id,
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user,
|
||||
</if>
|
||||
|
@ -163,6 +171,12 @@
|
|||
<if test="num != null">
|
||||
#{num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="type != null">
|
||||
#{type,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="rollbackSourceId != null">
|
||||
#{rollbackSourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
#{createUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -192,6 +206,12 @@
|
|||
<if test="record.num != null">
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.type != null">
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.rollbackSourceId != null">
|
||||
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createUser != null">
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -211,6 +231,8 @@
|
|||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
bug_id = #{record.bugId,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
content = #{record.content,jdbcType=LONGVARBINARY}
|
||||
|
@ -223,6 +245,8 @@
|
|||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
bug_id = #{record.bugId,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT}
|
||||
<if test="_parameter != null">
|
||||
|
@ -238,6 +262,12 @@
|
|||
<if test="num != null">
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="type != null">
|
||||
`type` = #{type,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="rollbackSourceId != null">
|
||||
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
|
@ -254,6 +284,8 @@
|
|||
update bug_history
|
||||
set bug_id = #{bugId,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
`type` = #{type,jdbcType=VARCHAR},
|
||||
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
content = #{content,jdbcType=LONGVARBINARY}
|
||||
|
@ -263,18 +295,20 @@
|
|||
update bug_history
|
||||
set bug_id = #{bugId,jdbcType=VARCHAR},
|
||||
num = #{num,jdbcType=INTEGER},
|
||||
`type` = #{type,jdbcType=VARCHAR},
|
||||
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into bug_history
|
||||
(id, bug_id, num, create_user, create_time, content)
|
||||
(id, bug_id, num, `type`, rollback_source_id, create_user, create_time, content)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.bugId,jdbcType=VARCHAR}, #{item.num,jdbcType=INTEGER},
|
||||
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY}
|
||||
)
|
||||
#{item.type,jdbcType=VARCHAR}, #{item.rollbackSourceId,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -296,6 +330,12 @@
|
|||
<if test="'num'.toString() == column.value">
|
||||
#{item.num,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="'type'.toString() == column.value">
|
||||
#{item.type,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'rollback_source_id'.toString() == column.value">
|
||||
#{item.rollbackSourceId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'create_user'.toString() == column.value">
|
||||
#{item.createUser,jdbcType=VARCHAR}
|
||||
</if>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="num" jdbcType="INTEGER" property="num" />
|
||||
<result column="title" jdbcType="VARCHAR" property="title" />
|
||||
<result column="assign_user" jdbcType="VARCHAR" property="assignUser" />
|
||||
<result column="handle_users" jdbcType="VARCHAR" property="handleUsers" />
|
||||
<result column="handle_user" jdbcType="VARCHAR" property="handleUser" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
|
||||
|
@ -79,9 +80,9 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, num, title, assign_user, create_user, create_time, update_user, update_time,
|
||||
delete_user, delete_time, project_id, template_id, platform, `status`, tag, platform_bug_id,
|
||||
trash
|
||||
id, num, title, handle_users, handle_user, create_user, create_time, update_user,
|
||||
update_time, delete_user, delete_time, project_id, template_id, platform, `status`,
|
||||
tag, platform_bug_id, trash
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.bug.domain.BugExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -115,17 +116,19 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.bug.domain.Bug">
|
||||
insert into bug (id, num, title,
|
||||
assign_user, create_user, create_time,
|
||||
update_user, update_time, delete_user,
|
||||
delete_time, project_id, template_id,
|
||||
platform, `status`, tag,
|
||||
platform_bug_id, trash)
|
||||
handle_users, handle_user, create_user,
|
||||
create_time, update_user, update_time,
|
||||
delete_user, delete_time, project_id,
|
||||
template_id, platform, `status`,
|
||||
tag, platform_bug_id, trash
|
||||
)
|
||||
values (#{id,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER}, #{title,jdbcType=VARCHAR},
|
||||
#{assignUser,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT}, #{deleteUser,jdbcType=VARCHAR},
|
||||
#{deleteTime,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR}, #{templateId,jdbcType=VARCHAR},
|
||||
#{platform,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{tag,jdbcType=VARCHAR},
|
||||
#{platformBugId,jdbcType=VARCHAR}, #{trash,jdbcType=BIT})
|
||||
#{handleUsers,jdbcType=VARCHAR}, #{handleUser,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
|
||||
#{createTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
|
||||
#{deleteUser,jdbcType=VARCHAR}, #{deleteTime,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR},
|
||||
#{templateId,jdbcType=VARCHAR}, #{platform,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||
#{tag,jdbcType=VARCHAR}, #{platformBugId,jdbcType=VARCHAR}, #{trash,jdbcType=BIT}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.bug.domain.Bug">
|
||||
insert into bug
|
||||
|
@ -139,8 +142,11 @@
|
|||
<if test="title != null">
|
||||
title,
|
||||
</if>
|
||||
<if test="assignUser != null">
|
||||
assign_user,
|
||||
<if test="handleUsers != null">
|
||||
handle_users,
|
||||
</if>
|
||||
<if test="handleUser != null">
|
||||
handle_user,
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user,
|
||||
|
@ -192,8 +198,11 @@
|
|||
<if test="title != null">
|
||||
#{title,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="assignUser != null">
|
||||
#{assignUser,jdbcType=VARCHAR},
|
||||
<if test="handleUsers != null">
|
||||
#{handleUsers,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="handleUser != null">
|
||||
#{handleUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
#{createUser,jdbcType=VARCHAR},
|
||||
|
@ -254,8 +263,11 @@
|
|||
<if test="record.title != null">
|
||||
title = #{record.title,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.assignUser != null">
|
||||
assign_user = #{record.assignUser,jdbcType=VARCHAR},
|
||||
<if test="record.handleUsers != null">
|
||||
handle_users = #{record.handleUsers,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.handleUser != null">
|
||||
handle_user = #{record.handleUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createUser != null">
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
|
@ -306,7 +318,8 @@
|
|||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
num = #{record.num,jdbcType=INTEGER},
|
||||
title = #{record.title,jdbcType=VARCHAR},
|
||||
assign_user = #{record.assignUser,jdbcType=VARCHAR},
|
||||
handle_users = #{record.handleUsers,jdbcType=VARCHAR},
|
||||
handle_user = #{record.handleUser,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_user = #{record.updateUser,jdbcType=VARCHAR},
|
||||
|
@ -333,8 +346,11 @@
|
|||
<if test="title != null">
|
||||
title = #{title,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="assignUser != null">
|
||||
assign_user = #{assignUser,jdbcType=VARCHAR},
|
||||
<if test="handleUsers != null">
|
||||
handle_users = #{handleUsers,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="handleUser != null">
|
||||
handle_user = #{handleUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
|
@ -382,7 +398,8 @@
|
|||
update bug
|
||||
set num = #{num,jdbcType=INTEGER},
|
||||
title = #{title,jdbcType=VARCHAR},
|
||||
assign_user = #{assignUser,jdbcType=VARCHAR},
|
||||
handle_users = #{handleUsers,jdbcType=VARCHAR},
|
||||
handle_user = #{handleUser,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_user = #{updateUser,jdbcType=VARCHAR},
|
||||
|
@ -400,17 +417,18 @@
|
|||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into bug
|
||||
(id, num, title, assign_user, create_user, create_time, update_user, update_time,
|
||||
delete_user, delete_time, project_id, template_id, platform, `status`, tag, platform_bug_id,
|
||||
trash)
|
||||
(id, num, title, handle_users, handle_user, create_user, create_time, update_user,
|
||||
update_time, delete_user, delete_time, project_id, template_id, platform, `status`,
|
||||
tag, platform_bug_id, trash)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.num,jdbcType=INTEGER}, #{item.title,jdbcType=VARCHAR},
|
||||
#{item.assignUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.deleteUser,jdbcType=VARCHAR},
|
||||
#{item.deleteTime,jdbcType=BIGINT}, #{item.projectId,jdbcType=VARCHAR}, #{item.templateId,jdbcType=VARCHAR},
|
||||
#{item.platform,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.tag,jdbcType=VARCHAR},
|
||||
#{item.platformBugId,jdbcType=VARCHAR}, #{item.trash,jdbcType=BIT})
|
||||
#{item.handleUsers,jdbcType=VARCHAR}, #{item.handleUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.createTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.deleteUser,jdbcType=VARCHAR}, #{item.deleteTime,jdbcType=BIGINT}, #{item.projectId,jdbcType=VARCHAR},
|
||||
#{item.templateId,jdbcType=VARCHAR}, #{item.platform,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR},
|
||||
#{item.tag,jdbcType=VARCHAR}, #{item.platformBugId,jdbcType=VARCHAR}, #{item.trash,jdbcType=BIT}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -432,8 +450,11 @@
|
|||
<if test="'title'.toString() == column.value">
|
||||
#{item.title,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'assign_user'.toString() == column.value">
|
||||
#{item.assignUser,jdbcType=VARCHAR}
|
||||
<if test="'handle_users'.toString() == column.value">
|
||||
#{item.handleUsers,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'handle_user'.toString() == column.value">
|
||||
#{item.handleUser,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'create_user'.toString() == column.value">
|
||||
#{item.createUser,jdbcType=VARCHAR}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
-- set innodb lock wait timeout
|
||||
SET SESSION innodb_lock_wait_timeout = 7200;
|
||||
|
||||
DROP TABLE IF EXISTS bug;
|
||||
CREATE TABLE IF NOT EXISTS bug(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID' ,
|
||||
`num` INT NOT NULL COMMENT '业务ID' ,
|
||||
`title` VARCHAR(300) NOT NULL COMMENT '缺陷标题' ,
|
||||
`assign_user` VARCHAR(50) NOT NULL COMMENT '指派人' ,
|
||||
`handle_users` VARCHAR(1000) COMMENT '处理人集合; 预留字段, 后续工作台统计可能需要' ,
|
||||
`handle_user` VARCHAR(50) NOT NULL COMMENT '处理人' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`update_user` VARCHAR(50) NOT NULL COMMENT '更新人' ,
|
||||
|
@ -26,23 +26,24 @@ CREATE TABLE IF NOT EXISTS bug(
|
|||
|
||||
CREATE INDEX idx_num ON bug(num);
|
||||
CREATE INDEX idx_title ON bug(title);
|
||||
CREATE INDEX idx_assign_user ON bug(assign_user);
|
||||
CREATE INDEX idx_handle_user ON bug(handle_user);
|
||||
CREATE INDEX idx_create_user ON bug(create_user);
|
||||
CREATE INDEX idx_create_time ON bug(create_time);
|
||||
CREATE INDEX idx_update_user ON bug(update_user);
|
||||
CREATE INDEX idx_update_time ON bug(update_time);
|
||||
CREATE INDEX idx_project_id ON bug(project_id);
|
||||
CREATE INDEX idx_platform ON bug(platform);
|
||||
CREATE INDEX idx_status ON bug(status);
|
||||
CREATE INDEX idx_trash ON bug(trash);
|
||||
|
||||
DROP TABLE IF EXISTS bug_content;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bug_content(
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`description` LONGTEXT COMMENT '缺陷描述' ,
|
||||
PRIMARY KEY (bug_id)
|
||||
) COMMENT = '缺陷内容';
|
||||
|
||||
DROP TABLE IF EXISTS bug_follower;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bug_follower(
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`user_id` VARCHAR(50) NOT NULL COMMENT '关注人ID' ,
|
||||
|
@ -52,14 +53,25 @@ CREATE TABLE IF NOT EXISTS bug_follower(
|
|||
|
||||
CREATE INDEX idx_follow_id ON bug_follower(user_id);
|
||||
|
||||
DROP TABLE IF EXISTS bug_comment;
|
||||
CREATE TABLE IF NOT EXISTS bug_attachment(
|
||||
`id` VARCHAR(255) NOT NULL COMMENT 'ID' ,
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`file_id` VARCHAR(50) NOT NULL COMMENT '文件ID' ,
|
||||
`file_name` VARCHAR(255) NOT NULL COMMENT '文件名称' ,
|
||||
`size` BIGINT NOT NULL COMMENT '文件大小' ,
|
||||
`local` BIT(1) NOT NULL COMMENT '是否本地' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
PRIMARY KEY (id)
|
||||
) COMMENT = '缺陷附件';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bug_comment(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID' ,
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`reply_user` VARCHAR(50) COMMENT '回复人' ,
|
||||
`notifier` VARCHAR(1000) COMMENT '通知人' ,
|
||||
`parent_id` VARCHAR(50) COMMENT '父评论ID' ,
|
||||
`description` TEXT NOT NULL COMMENT '内容' ,
|
||||
`content` TEXT NOT NULL COMMENT '内容' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '评论人' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`update_user` VARCHAR(50) NOT NULL COMMENT '更新人' ,
|
||||
|
@ -71,31 +83,16 @@ CREATE TABLE IF NOT EXISTS bug_comment(
|
|||
CREATE INDEX idx_bug_id ON bug_comment(bug_id);
|
||||
CREATE INDEX idx_parent_id ON bug_comment(parent_id);
|
||||
|
||||
DROP TABLE IF EXISTS bug_attachment;
|
||||
CREATE TABLE IF NOT EXISTS bug_attachment(
|
||||
`id` VARCHAR(255) NOT NULL COMMENT 'ID' ,
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`file_id` VARCHAR(50) NOT NULL COMMENT '文件ID' ,
|
||||
`file_name` VARCHAR(255) NOT NULL COMMENT '文件名称' ,
|
||||
`size` BIGINT NOT NULL COMMENT '文件大小' ,
|
||||
`association` BIT(1) NOT NULL COMMENT '是否关联' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
PRIMARY KEY (id)
|
||||
) COMMENT = '缺陷附件';
|
||||
|
||||
DROP TABLE IF EXISTS bug_custom_field;
|
||||
CREATE TABLE IF NOT EXISTS bug_custom_field(
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`field_id` VARCHAR(50) NOT NULL COMMENT '字段ID' ,
|
||||
`value` VARCHAR(1000) COMMENT '字段值' ,
|
||||
PRIMARY KEY (bug_id)
|
||||
PRIMARY KEY (bug_id, field_id)
|
||||
) COMMENT = '缺陷自定义字段';
|
||||
|
||||
DROP TABLE IF EXISTS bug_relation_case;
|
||||
CREATE TABLE IF NOT EXISTS bug_relation_case(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID' ,
|
||||
`case_id` VARCHAR(50) NOT NULL COMMENT '关联功能用例ID' ,
|
||||
`case_id` VARCHAR(50) COMMENT '关联功能用例ID' ,
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '缺陷ID' ,
|
||||
`case_type` VARCHAR(64) NOT NULL DEFAULT 'functional' COMMENT '关联的用例类型;functional/api/ui/performance' ,
|
||||
`test_plan_id` VARCHAR(50) COMMENT '关联测试计划ID' ,
|
||||
|
@ -112,11 +109,12 @@ CREATE INDEX idx_plan_case_id ON bug_relation_case(test_plan_id,test_plan_case_i
|
|||
CREATE INDEX idx_case_id ON bug_relation_case(case_id);
|
||||
CREATE INDEX idx_case_type ON bug_relation_case(case_type);
|
||||
|
||||
DROP TABLE IF EXISTS bug_history;
|
||||
CREATE TABLE IF NOT EXISTS bug_history(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '变更记录ID' ,
|
||||
`bug_id` VARCHAR(50) NOT NULL COMMENT '所属缺陷ID' ,
|
||||
`num` INT NOT NULL COMMENT '变更记录批次号' ,
|
||||
`type` VARCHAR(64) COMMENT '变更类型;IMPORT/EDIT/' ,
|
||||
`rollback_source_id` VARCHAR(50) COMMENT '回退来源' ,
|
||||
`content` BLOB NOT NULL COMMENT '修改内容' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '操作人' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '操作时间' ,
|
||||
|
|
|
@ -120,6 +120,10 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT
|
|||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_APPLICATION_WORKSTATION:UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_LOG:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_LOG:UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+ADD');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+DELETE');
|
||||
|
||||
-- 项目成员权限
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.plugin.platform.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
public class SyncAttachmentToPlatformRequest {
|
||||
/**
|
||||
* 平台资源Key(需求或缺陷ID)
|
||||
*/
|
||||
private String platformKey;
|
||||
|
||||
/**
|
||||
* 需要同步的附件
|
||||
*/
|
||||
private File file;
|
||||
|
||||
/**
|
||||
* 同步类型是上传还是删除
|
||||
* 参考 SyncAttachmentType
|
||||
*/
|
||||
private String syncType;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package io.metersphere.plugin.platform.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class SyncBugAttachmentRequest {
|
||||
/**
|
||||
* 平台 ID
|
||||
*/
|
||||
private String platformId;
|
||||
/**
|
||||
* 需要同步的附件
|
||||
*/
|
||||
private File file;
|
||||
/**
|
||||
* 操作类型是更新还是删除
|
||||
* 参考 AttachmentSyncType
|
||||
*/
|
||||
private String syncType;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.plugin.platform.enums;
|
||||
|
||||
public enum SyncAttachmentType {
|
||||
|
||||
/**
|
||||
* 附件上传
|
||||
*/
|
||||
UPLOAD("upload"),
|
||||
|
||||
/**
|
||||
* 附件删除
|
||||
*/
|
||||
DELETE("delete");
|
||||
|
||||
private final String syncOperateType;
|
||||
|
||||
SyncAttachmentType(String syncOperateType) {
|
||||
this.syncOperateType = syncOperateType;
|
||||
}
|
||||
|
||||
public String syncOperateType() {
|
||||
return syncOperateType;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package io.metersphere.plugin.platform.spi;
|
||||
|
||||
import io.metersphere.plugin.platform.dto.PlatformBugUpdateRequest;
|
||||
import io.metersphere.plugin.platform.dto.PlatformCustomFieldItemDTO;
|
||||
import io.metersphere.plugin.platform.dto.PluginOptionsRequest;
|
||||
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||
import io.metersphere.plugin.platform.dto.PlatformStatusDTO;
|
||||
import io.metersphere.plugin.platform.dto.SyncAttachmentToPlatformRequest;
|
||||
import org.pf4j.ExtensionPoint;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -22,19 +25,23 @@ public interface Platform extends ExtensionPoint {
|
|||
/**
|
||||
* 校验项目配置
|
||||
* 项目设置成点击校验项目 key 时调用
|
||||
* @param projectConfig 项目配置
|
||||
*/
|
||||
void validateProjectConfig(String projectConfig);
|
||||
|
||||
/**
|
||||
* 插件是否支持第三方模板
|
||||
* @return
|
||||
* 平台是否支持第三方模板
|
||||
*
|
||||
* @return 是否支持第三方模板
|
||||
*/
|
||||
boolean isThirdPartTemplateSupport();
|
||||
|
||||
/**
|
||||
* 获取第三方平台缺陷的自定义字段
|
||||
* 需要 PluginMetaInfo 的 isThirdPartTemplateSupport 返回 true
|
||||
* @return
|
||||
*
|
||||
* @param projectConfig 项目配置信息
|
||||
* @return 平台自定义字段集合
|
||||
*/
|
||||
List<PlatformCustomFieldItemDTO> getThirdPartCustomField(String projectConfig);
|
||||
|
||||
|
@ -44,4 +51,52 @@ public interface Platform extends ExtensionPoint {
|
|||
* @return
|
||||
*/
|
||||
List<SelectOption> getPluginOptions(PluginOptionsRequest optionsRequest);
|
||||
|
||||
/**
|
||||
* 新增平台缺陷
|
||||
*
|
||||
* @param request 平台缺陷参数
|
||||
* @return 平台缺陷ID
|
||||
*/
|
||||
String addBug(PlatformBugUpdateRequest request);
|
||||
|
||||
/**
|
||||
* 修改平台缺陷
|
||||
*
|
||||
* @param request 平台缺陷参数
|
||||
*/
|
||||
void updateBug(PlatformBugUpdateRequest request);
|
||||
|
||||
/**
|
||||
* 删除平台缺陷
|
||||
*
|
||||
* @param platformBugId 平台缺陷ID
|
||||
*/
|
||||
void deleteBug(String platformBugId);
|
||||
|
||||
/**
|
||||
* 平台是否支持附件同步
|
||||
*
|
||||
* @return 是否支持附件同步
|
||||
*/
|
||||
boolean isAttachmentUploadSupport();
|
||||
|
||||
/**
|
||||
* 同步MS附件至第三方平台(isAttachmentUploadSupport返回true时执行同步附件的逻辑)
|
||||
*
|
||||
* @param request 同步附件参数
|
||||
*/
|
||||
void syncAttachmentToPlatform(SyncAttachmentToPlatformRequest request);
|
||||
|
||||
/**
|
||||
* 同步部分缺陷
|
||||
*/
|
||||
void syncPartIssues();
|
||||
|
||||
/**
|
||||
* 同步全量缺陷
|
||||
*/
|
||||
void syncAllIssues();
|
||||
|
||||
List<PlatformStatusDTO> getStatusList();
|
||||
}
|
||||
|
|
|
@ -8,66 +8,73 @@ public enum CustomFieldType {
|
|||
/**
|
||||
* 输入框
|
||||
*/
|
||||
INPUT( false),
|
||||
INPUT(false, "input"),
|
||||
/**
|
||||
* 文本框
|
||||
*/
|
||||
TEXTAREA(false),
|
||||
TEXTAREA(false, "textarea"),
|
||||
/**
|
||||
* 单选下拉框框
|
||||
*/
|
||||
SELECT( true),
|
||||
SELECT(true, "select"),
|
||||
/**
|
||||
* 多选下拉框框
|
||||
*/
|
||||
MULTIPLE_SELECT(true),
|
||||
MULTIPLE_SELECT(true, "multipleSelect"),
|
||||
/**
|
||||
* 单选框
|
||||
*/
|
||||
RADIO(true),
|
||||
RADIO(true, "radio"),
|
||||
/**
|
||||
* 复选框
|
||||
*/
|
||||
CHECKBOX(true),
|
||||
CHECKBOX(true, "checkbox"),
|
||||
/**
|
||||
* 单选成员
|
||||
*/
|
||||
MEMBER(true),
|
||||
MEMBER(true, "member"),
|
||||
/**
|
||||
* 多选成员
|
||||
*/
|
||||
MULTIPLE_MEMBER(true),
|
||||
MULTIPLE_MEMBER(true, "multipleMember"),
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
DATE(false),
|
||||
DATE(false, "date"),
|
||||
/**
|
||||
* 日期时间
|
||||
*/
|
||||
DATETIME(false),
|
||||
DATETIME(false, "datetime"),
|
||||
/**
|
||||
* 整型
|
||||
*/
|
||||
INT(false),
|
||||
INT(false, "int"),
|
||||
/**
|
||||
* 浮点型
|
||||
*/
|
||||
FLOAT(false),
|
||||
FLOAT(false, "float"),
|
||||
/**
|
||||
* 多值输入框(标签输入框)
|
||||
*/
|
||||
MULTIPLE_INPUT(false);
|
||||
MULTIPLE_INPUT(false, "multipleInput");
|
||||
|
||||
private final Boolean hasOption;
|
||||
|
||||
CustomFieldType(Boolean hasOption) {
|
||||
private final String type;
|
||||
|
||||
CustomFieldType(Boolean hasOption, String type) {
|
||||
this.hasOption = hasOption;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getHasOption() {
|
||||
return this.hasOption;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public static Set<String> getHasOptionValueSet() {
|
||||
return Arrays.stream(CustomFieldType.values())
|
||||
.filter(CustomFieldType::getHasOption)
|
||||
|
|
|
@ -226,4 +226,11 @@ public class PermissionConstants {
|
|||
public static final String PROJECT_API_DEBUG_READ_IMPORT = "PROJECT_API_DEBUG:READ+IMPORT";
|
||||
public static final String PROJECT_API_DEBUG_READ_EXECUTE = "PROJECT_API_DEBUG:READ+EXECUTE";
|
||||
/*------ end: API_DEBUG ------*/
|
||||
|
||||
/*------ start: BUG ------*/
|
||||
public static final String BUG_READ = "BUG:READ";
|
||||
public static final String BUG_ADD = "BUG:READ+ADD";
|
||||
public static final String BUG_UPDATE = "BUG:READ+UPDATE";
|
||||
public static final String BUG_DELETE = "BUG:READ+DELETE";
|
||||
/*------ end: BUG ------*/
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import java.io.File;
|
|||
|
||||
public class MsFileUtils {
|
||||
|
||||
public static final String DATE_ROOT_DIR = "/opt/metersphere/data/app";
|
||||
public static final String DATA_ROOT_DIR = "/opt/metersphere/data/app";
|
||||
public static final String PLUGIN_DIR_NAME = "plugins";
|
||||
public static final String PLUGIN_DIR = DATE_ROOT_DIR + "/" + PLUGIN_DIR_NAME;
|
||||
|
||||
public static final String PLUGIN_DIR = DATA_ROOT_DIR + "/" + PLUGIN_DIR_NAME;
|
||||
public static final String FUNCTIONAL_CASE_ATTACHMENT_DIR_NAME = "functionalCaseAttachment";
|
||||
public static final String FUNCTIONAL_CASE_ATTACHMENT_DIR = DATE_ROOT_DIR + "/" + FUNCTIONAL_CASE_ATTACHMENT_DIR_NAME;
|
||||
public static final String FUNCTIONAL_CASE_ATTACHMENT_DIR = DATA_ROOT_DIR + "/" + FUNCTIONAL_CASE_ATTACHMENT_DIR_NAME;
|
||||
public static final String BUG_MANAGEMENT_DIR = "bug";
|
||||
|
||||
public static void validateFileName(String... fileNames) {
|
||||
if (fileNames != null) {
|
||||
|
|
|
@ -13,6 +13,8 @@ bug.delete_user.not_blank=删除人不能为空
|
|||
bug.delete_user.length_range=删除人长度必须在1-50之间
|
||||
bug.project_id.not_blank=项目ID不能为空
|
||||
bug.project_id.length_range=项目ID长度必须在1-50之间
|
||||
bug.template_id.not_blank=模板ID不能为空
|
||||
bug.template_id.length_range=模板ID长度必须在1-50之间
|
||||
bug.platform.not_blank=缺陷平台不能为空
|
||||
bug.platform.length_range=缺陷平台长度必须在1-50之间
|
||||
bug.status.not_blank=平台状态不能为空
|
||||
|
@ -49,8 +51,8 @@ bug_attachment.file_id.not_blank=文件ID不能为空
|
|||
bug_attachment.file_id.length_range=文件ID长度必须在1-50之间
|
||||
bug_attachment.file_name.not_blank=文件名称不能为空
|
||||
bug_attachment.file_name.length_range=文件名称长度必须在1-50之间
|
||||
bug_attachment.association.not_blank=是否关联不能为空
|
||||
bug_attachment.association.length_range=是否关联长度必须在1-50之间
|
||||
bug_attachment.local.not_blank=是否本地上传不能为空
|
||||
bug_attachment.local.length_range=是否本地上传长度必须在1-50之间
|
||||
bug_attachment.create_user.not_blank=创建人不能为空
|
||||
bug_attachment.create_user.length_range=创建人长度必须在1-50之间
|
||||
|
||||
|
@ -78,4 +80,11 @@ bug_history.id.length_range=变更记录ID长度必须在1-50之间
|
|||
bug_history.bug_id.not_blank=所属缺陷ID不能为空
|
||||
bug_history.bug_id.length_range=所属缺陷ID长度必须在1-50之间
|
||||
bug_history.create_user.not_blank=操作人不能为空
|
||||
bug_history.create_user.length_range=操作人长度必须在1-50之间
|
||||
bug_history.create_user.length_range=操作人长度必须在1-50之间
|
||||
|
||||
# error
|
||||
bug_not_exist=缺陷不存在
|
||||
not_local_bug_error=非本地缺陷,无法操作
|
||||
third_party_not_config=项目未配置第三方平台
|
||||
bug_attachment_upload_error=缺陷附件上传失败
|
||||
bug_attachment_delete_error=缺陷附件删除失败
|
|
@ -13,6 +13,8 @@ bug.delete_user.not_blank=deleteUser cannot be empty
|
|||
bug.delete_user.length_range=deleteUser length must be between 1-50
|
||||
bug.project_id.not_blank=projectId cannot be empty
|
||||
bug.project_id.length_range=projectId length must be between 1-50
|
||||
bug.template_id.not_blank=templateId cannot be empty
|
||||
bug.template_id.length_range=templateId length must be between 1-50
|
||||
bug.platform.not_blank=platform cannot be empty
|
||||
bug.platform.length_range=platform length must be between 1-50
|
||||
bug.status.not_blank=status cannot be empty
|
||||
|
@ -49,8 +51,8 @@ bug_attachment.file_id.not_blank=fileId cannot be empty
|
|||
bug_attachment.file_id.length_range=fileId length must be between 1-50
|
||||
bug_attachment.file_name.not_blank=fileName cannot be empty
|
||||
bug_attachment.file_name.length_range=fileName length must be between 1-50
|
||||
bug_attachment.association.not_blank=association cannot be empty
|
||||
bug_attachment.association.length_range=association length must be between 1-50
|
||||
bug_attachment.local.not_blank=local cannot be empty
|
||||
bug_attachment.local.length_range=local length must be between 1-50
|
||||
bug_attachment.create_user.not_blank=createUser cannot be empty
|
||||
bug_attachment.create_user.length_range=createUser length must be between 1-50
|
||||
|
||||
|
@ -78,4 +80,11 @@ bug_history.id.length_range=id length must be between 1-50
|
|||
bug_history.bug_id.not_blank=bugId cannot be empty
|
||||
bug_history.bug_id.length_range=bugId length must be between 1-50
|
||||
bug_history.create_user.not_blank=createUser cannot be empty
|
||||
bug_history.create_user.length_range=createUser length must be between 1-50
|
||||
bug_history.create_user.length_range=createUser length must be between 1-50
|
||||
|
||||
# error
|
||||
bug_not_exist=Bug does not exist
|
||||
not_local_bug_error=Not local bug, error
|
||||
third_party_not_config=The project third-party platform not configured
|
||||
bug_attachment_upload_error=Bug attachment upload error
|
||||
bug_attachment_delete_error=Bug attachment delete error
|
||||
|
|
|
@ -13,6 +13,8 @@ bug.delete_user.not_blank=删除人不能为空
|
|||
bug.delete_user.length_range=删除人长度必须在1-50之间
|
||||
bug.project_id.not_blank=项目ID不能为空
|
||||
bug.project_id.length_range=项目ID长度必须在1-50之间
|
||||
bug.template_id.not_blank=模板ID不能为空
|
||||
bug.template_id.length_range=模板ID长度必须在1-50之间
|
||||
bug.platform.not_blank=缺陷平台不能为空
|
||||
bug.platform.length_range=缺陷平台长度必须在1-50之间
|
||||
bug.status.not_blank=平台状态不能为空
|
||||
|
@ -49,8 +51,8 @@ bug_attachment.file_id.not_blank=文件ID不能为空
|
|||
bug_attachment.file_id.length_range=文件ID长度必须在1-50之间
|
||||
bug_attachment.file_name.not_blank=文件名称不能为空
|
||||
bug_attachment.file_name.length_range=文件名称长度必须在1-50之间
|
||||
bug_attachment.association.not_blank=是否关联不能为空
|
||||
bug_attachment.association.length_range=是否关联长度必须在1-50之间
|
||||
bug_attachment.local.not_blank=是否本地上传不能为空
|
||||
bug_attachment.local.length_range=是否本地上传长度必须在1-50之间
|
||||
bug_attachment.create_user.not_blank=创建人不能为空
|
||||
bug_attachment.create_user.length_range=创建人长度必须在1-50之间
|
||||
|
||||
|
@ -78,4 +80,11 @@ bug_history.id.length_range=变更记录ID长度必须在1-50之间
|
|||
bug_history.bug_id.not_blank=所属缺陷ID不能为空
|
||||
bug_history.bug_id.length_range=所属缺陷ID长度必须在1-50之间
|
||||
bug_history.create_user.not_blank=操作人不能为空
|
||||
bug_history.create_user.length_range=操作人长度必须在1-50之间
|
||||
bug_history.create_user.length_range=操作人长度必须在1-50之间
|
||||
|
||||
# error
|
||||
bug_not_exist=缺陷不存在
|
||||
not_local_bug_error=非本地缺陷,无法操作
|
||||
third_party_not_config=项目未配置第三方平台
|
||||
bug_attachment_upload_error=缺陷附件上传失败
|
||||
bug_attachment_delete_error=缺陷附件删除失败
|
|
@ -13,6 +13,8 @@ bug.delete_user.not_blank=删除人不能為空
|
|||
bug.delete_user.length_range=删除人長度必須在1-50之間
|
||||
bug.project_id.not_blank=项目ID不能為空
|
||||
bug.project_id.length_range=项目ID長度必須在1-50之間
|
||||
bug.template_id.not_blank=模板ID不能為空
|
||||
bug.template_id.length_range=模板ID長度必須在1-50之間
|
||||
bug.platform.not_blank=缺陷平台不能為空
|
||||
bug.platform.length_range=缺陷平台長度必須在1-50之間
|
||||
bug.status.not_blank=平台状态不能為空
|
||||
|
@ -49,8 +51,8 @@ bug_attachment.file_id.not_blank=文件ID不能為空
|
|||
bug_attachment.file_id.length_range=文件ID長度必須在1-50之間
|
||||
bug_attachment.file_name.not_blank=文件名称不能為空
|
||||
bug_attachment.file_name.length_range=文件名称長度必須在1-50之間
|
||||
bug_attachment.association.not_blank=是否关联不能為空
|
||||
bug_attachment.association.length_range=是否关联長度必須在1-50之間
|
||||
bug_attachment.local.not_blank=是否本地上傳不能為空
|
||||
bug_attachment.local.length_range=是否本地上傳必須在1-50之間
|
||||
bug_attachment.create_user.not_blank=创建人不能為空
|
||||
bug_attachment.create_user.length_range=创建人長度必須在1-50之間
|
||||
|
||||
|
@ -80,4 +82,10 @@ bug_history.bug_id.length_range=所属缺陷ID長度必須在1-50之間
|
|||
bug_history.create_user.not_blank=操作人不能為空
|
||||
bug_history.create_user.length_range=操作人長度必須在1-50之間
|
||||
|
||||
# error
|
||||
bug_not_exist=缺陷不存在
|
||||
not_local_bug_error=非本地缺陷,無法操作
|
||||
third_party_not_config=項目未配置第三方平台
|
||||
bug_attachment_upload_error=缺陷附件上傳失敗
|
||||
bug_attachment_delete_error=缺陷附件刪除失敗
|
||||
|
||||
|
|
|
@ -471,3 +471,4 @@ file.name.cannot.be.empty=File name cannot be empty
|
|||
project_template_permission_error=The project template is not turned on
|
||||
third_part_config_is_null=Third party configuration cannot be empty
|
||||
plugin_bug_template_remark=Templates are automatically obtained by the system and do not support editing and viewing
|
||||
default_template=default template
|
||||
|
|
|
@ -470,3 +470,4 @@ project_template_permission_error=未开启项目模板
|
|||
|
||||
third_part_config_is_null=第三方平台配置信息不能为空
|
||||
plugin_bug_template_remark=模板为系统自动获取,不支持编辑和查看
|
||||
default_template=默认模板
|
||||
|
|
|
@ -470,4 +470,5 @@ file.name.cannot.be.empty=文件名稱不能為空
|
|||
# template
|
||||
project_template_permission_error=未開啟項目模板
|
||||
third_part_config_is_null=第三方平臺配置信息不能爲空
|
||||
plugin_bug_template_remark=模板為系統自動獲取,不支持編輯和查看
|
||||
plugin_bug_template_remark=模板為系統自動獲取,不支持編輯和查看
|
||||
default_template=默認模板
|
|
@ -28,6 +28,14 @@
|
|||
<artifactId>metersphere-project-management</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.metersphere</groupId>
|
||||
<artifactId>metersphere-system-setting</artifactId>
|
||||
<version>${revision}</version>
|
||||
<classifier>tests</classifier>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package io.metersphere.bug.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.bug.service.BugService;
|
||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||
import io.metersphere.project.service.ProjectTemplateService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.constants.TemplateScene;
|
||||
import io.metersphere.system.dto.sdk.TemplateDTO;
|
||||
import io.metersphere.system.utils.PageUtils;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Tag(name = "缺陷管理")
|
||||
@RestController
|
||||
@RequestMapping("/bug")
|
||||
public class BugController {
|
||||
|
||||
@Resource
|
||||
private BugService bugService;
|
||||
@Resource
|
||||
private ProjectTemplateService projectTemplateService;
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "缺陷管理-获取缺陷列表")
|
||||
@RequiresPermissions(PermissionConstants.BUG_READ)
|
||||
public Pager<List<BugDTO>> page(@Validated @RequestBody BugPageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||
request.setUseTrash(false);
|
||||
return PageUtils.setPageInfo(page, bugService.list(request));
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "缺陷管理-创建缺陷")
|
||||
@RequiresPermissions(PermissionConstants.BUG_ADD)
|
||||
public void add(@Validated({Created.class}) @RequestPart(value = "request") BugEditRequest request,
|
||||
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||
bugService.add(request, files, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "缺陷管理-更新缺陷")
|
||||
@RequiresPermissions(PermissionConstants.BUG_UPDATE)
|
||||
public void update(@Validated({Updated.class}) @RequestPart(value = "request") BugEditRequest request,
|
||||
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||
bugService.update(request, files, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
@Operation(summary = "缺陷管理-删除缺陷")
|
||||
@RequiresPermissions(PermissionConstants.BUG_DELETE)
|
||||
public void delete(@PathVariable String id) {
|
||||
bugService.delete(id);
|
||||
}
|
||||
|
||||
@GetMapping("/template/option")
|
||||
@Operation(summary = "缺陷管理-获取当前项目缺陷模板选项")
|
||||
@RequiresPermissions(PermissionConstants.BUG_READ)
|
||||
public List<ProjectTemplateOptionDTO> getTemplateOption(@RequestParam(value = "projectId") String projectId) {
|
||||
return projectTemplateService.getOption(projectId, TemplateScene.BUG.name());
|
||||
}
|
||||
|
||||
@GetMapping("/template/{id}")
|
||||
@Operation(summary = "缺陷管理-获取模板内容")
|
||||
@RequiresPermissions(PermissionConstants.BUG_READ)
|
||||
public TemplateDTO getTemplateField(@PathVariable String id, @RequestParam(value = "projectId") String projectId) {
|
||||
return bugService.getTemplate(id, projectId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package io.metersphere.bug.controller;
|
||||
|
||||
public class BugHistoryController {
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.metersphere.system.domain.CustomField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Data
|
||||
public class BugCustomFieldDTO extends CustomField {
|
||||
|
||||
@Schema(description = "字段值")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "缺陷ID")
|
||||
private String bugId;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.metersphere.bug.domain.Bug;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Data
|
||||
public class BugDTO extends Bug {
|
||||
|
||||
@Schema(description = "缺陷内容")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "创建人名称")
|
||||
private String createUserName;
|
||||
|
||||
@Schema(description = "指派人名称")
|
||||
private String assignUserName;
|
||||
|
||||
@Schema(description = "状态名称")
|
||||
private String statusName;
|
||||
|
||||
@Schema(description = "关联用例数量")
|
||||
private Integer relationCaseCount;
|
||||
|
||||
@Schema(description = "自定义字段集合")
|
||||
private List<BugCustomFieldDTO> customFields;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BugHistoryContentDTO extends BugDTO {
|
||||
|
||||
/**
|
||||
* 缺陷自定义字段
|
||||
*/
|
||||
private List<BugCustomFieldDTO> customFields;
|
||||
|
||||
/**
|
||||
* 缺陷内容
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 附件名称集合
|
||||
*/
|
||||
private List<String> attachmentNames;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Data
|
||||
public class BugRelationCaseCountDTO {
|
||||
|
||||
@Schema(description = "缺陷ID")
|
||||
private String bugId;
|
||||
|
||||
@Schema(description = "关联用例数量")
|
||||
private Integer relationCaseCount;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BugStatusOptionDTO extends OptionDTO {
|
||||
|
||||
// 状态流转信息
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package io.metersphere.bug.dto.request;
|
||||
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Data
|
||||
public class BugEditRequest {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "缺陷标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.title.not_blank}", groups = {Created.class, Updated.class})
|
||||
@Size(min = 1, max = 300, message = "{bug.title.length_range}", groups = {Created.class, Updated.class})
|
||||
private String title;
|
||||
|
||||
@Schema(description = "处理人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.assign_user.not_blank}", groups = {Created.class, Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.assign_user.length_range}", groups = {Created.class, Updated.class})
|
||||
private String handleUser;
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.project_id.not_blank}", groups = {Created.class, Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模板ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.template_id.not_blank}", groups = {Created.class, Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.template_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String templateId;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.status.not_blank}", groups = {Created.class, Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{bug.status.length_range}", groups = {Created.class, Updated.class})
|
||||
private String status;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private String tag;
|
||||
|
||||
@Schema(description = "缺陷内容")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "自定义字段集合")
|
||||
private Map<String, String> customFieldMap;
|
||||
|
||||
@Schema(description = "删除的本地附件集合")
|
||||
private List<String> deleteLocalFileIds;
|
||||
|
||||
@Schema(description = "取消关联附件集合")
|
||||
private List<String> unLinkFileIds;
|
||||
|
||||
@Schema(description = "关联附件集合")
|
||||
private List<String> linkFileIds;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.bug.dto.request;
|
||||
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BugPageRequest extends BasePageRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "是否回收站")
|
||||
private boolean useTrash;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package io.metersphere.bug.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
|
||||
@Getter
|
||||
public enum BugPlatform {
|
||||
|
||||
/**
|
||||
* 本地
|
||||
*/
|
||||
LOCAL("Local"),
|
||||
/**
|
||||
* Jira
|
||||
*/
|
||||
JIRA("Jira"),
|
||||
/**
|
||||
* Tapd
|
||||
*/
|
||||
TAPD("Tapd"),
|
||||
/**
|
||||
* 禅道
|
||||
*/
|
||||
ZENDAO("Zentao"),
|
||||
/**
|
||||
* Azure
|
||||
*/
|
||||
AZURE("Azure");
|
||||
|
||||
private final String name;
|
||||
|
||||
BugPlatform(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package io.metersphere.bug.enums.result;
|
||||
|
||||
import io.metersphere.sdk.exception.IResultCode;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
|
||||
public enum BugResultCode implements IResultCode {
|
||||
|
||||
/**
|
||||
* 缺陷不存在
|
||||
*/
|
||||
BUG_NOT_EXIST(108001, "bug_not_exist"),
|
||||
|
||||
/**
|
||||
* 非Local缺陷异常
|
||||
*/
|
||||
NOT_LOCAL_BUG_ERROR(108002, "not_local_bug_error");
|
||||
|
||||
private final int code;
|
||||
private final String message;
|
||||
|
||||
BugResultCode(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return getTranslationMessage(this.message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.bug.mapper;
|
||||
|
||||
import io.metersphere.bug.domain.BugAttachment;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtBugAttachmentMapper {
|
||||
|
||||
/**
|
||||
* 批量插入缺陷附件关系
|
||||
* @param attachments 缺陷附件集合
|
||||
*/
|
||||
void batchInsert(@Param("list") List<BugAttachment> attachments);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?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">
|
||||
<mapper namespace="io.metersphere.bug.mapper.ExtBugAttachmentMapper">
|
||||
<insert id="batchInsert" parameterType="io.metersphere.bug.domain.BugAttachment">
|
||||
insert into bug_attachment values
|
||||
<foreach collection="list" item="attachment" separator=",">
|
||||
(#{attachment.id}, #{attachment.bugId}, #{attachment.fileId}, #{attachment.fileName},
|
||||
#{attachment.size}, #{attachment.local}, #{attachment.createUser}, #{attachment.createTime})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.bug.mapper;
|
||||
|
||||
import io.metersphere.bug.domain.BugCustomField;
|
||||
import io.metersphere.bug.dto.BugCustomFieldDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtBugCustomFieldMapper {
|
||||
|
||||
/**
|
||||
* 获取缺陷自定义字段值
|
||||
* @param bugIds 缺陷集合
|
||||
* @param projectId 项目ID
|
||||
* @return 缺陷自定义字段值
|
||||
*/
|
||||
List<BugCustomFieldDTO> getBugCustomFields(@Param("ids") List<String> bugIds, @Param("projectId") String projectId);
|
||||
|
||||
/**
|
||||
* 批量插入缺陷自定义字段值
|
||||
* @param customFields 自定义字段值集合
|
||||
*/
|
||||
void batchInsert(@Param("list") List<BugCustomField> customFields);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?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">
|
||||
<mapper namespace="io.metersphere.bug.mapper.ExtBugCustomFieldMapper">
|
||||
<select id="getBugCustomFields" resultType="io.metersphere.bug.dto.BugCustomFieldDTO">
|
||||
select cf.*, bcf.value, bcf.bug_id from bug_custom_field bcf join custom_field cf on bcf.field_id = cf.id
|
||||
where cf.scene = 'BUG' and cf.scope_type = 'PROJECT' and scope_id = #{projectId}
|
||||
and bug_id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<insert id="batchInsert" parameterType="io.metersphere.bug.domain.BugCustomField">
|
||||
insert into bug_custom_field (bug_id, field_id, value) values
|
||||
<foreach collection="list" item="field" separator=",">
|
||||
(#{field.bugId}, #{field.fieldId}, #{field.value})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.bug.mapper;
|
||||
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtBugMapper {
|
||||
|
||||
/**
|
||||
* 缺陷列表查询
|
||||
*
|
||||
* @param request 请求查询参数
|
||||
* @return 缺陷列表
|
||||
*/
|
||||
List<BugDTO> list(@Param("request") BugPageRequest request);
|
||||
|
||||
/**
|
||||
* 获取缺陷业务ID
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
* @return 最大的业务ID
|
||||
*/
|
||||
Long getMaxNum(String projectId);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
<?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">
|
||||
<mapper namespace="io.metersphere.bug.mapper.ExtBugMapper">
|
||||
<select id="list" resultType="io.metersphere.bug.dto.BugDTO">
|
||||
select b.id, b.num, b.title, b.handle_user, b.create_user, b.create_time, b.update_time, b.delete_time, b.delete_user,
|
||||
b.project_id, b.template_id, b.platform, b.status, bc.description from bug b left join bug_content bc on b.id = bc.bug_id
|
||||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="getMaxNum" resultType="java.lang.Long">
|
||||
select max(num) from bug where project_id = #{projectId}
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
<if test="request.useTrash">
|
||||
b.trash = 1
|
||||
</if>
|
||||
<if test="!request.useTrash">
|
||||
b.trash = 0
|
||||
</if>
|
||||
<if test="request.projectId">
|
||||
and b.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.keyword != null">
|
||||
and (
|
||||
b.title like concat('%', #{request.keyword},'%')
|
||||
or b.num like concat('%', #{request.keyword},'%')
|
||||
)
|
||||
</if>
|
||||
<include refid="filter"/>
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.combine"/>
|
||||
</include>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<sql id="filter">
|
||||
<if test="request.filter != null and request.filter.size() > 0">
|
||||
<foreach collection="request.filter.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key == 'handleUser'">
|
||||
and b.handle_user in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<when test="key == 'createUser'">
|
||||
and b.create_user in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<when test="key == 'platform'">
|
||||
and b.platform in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<when test="key == 'status'">
|
||||
and b.status in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<when test="key.startsWith('custom_single')">
|
||||
and b.id in (
|
||||
select bug_id from bug_custom_field where concat('custom_single_', field_id) = #{key}
|
||||
and trim(both '"' from `value`) in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
)
|
||||
</when>
|
||||
<when test="key.startsWith('custom_multiple')">
|
||||
and b.id in (
|
||||
select bug_id from bug_custom_field where concat('custom_multiple_', field_id) = #{key}
|
||||
and
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterMultipleWrapper"/>
|
||||
)
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="combine">
|
||||
<if test="request.combine != null">
|
||||
<if test='${condition}.handleUser != null'>
|
||||
and b.handle_user
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="${condition}.assignUser"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test='${condition}.createUser != null'>
|
||||
and b.create_user
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="${condition}.createUser"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test='${condition}.platform != null'>
|
||||
and b.platform
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="${condition}.platform"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test='${condition}.status != null'>
|
||||
and b.status
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="${condition}.platform"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
|
||||
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
|
||||
<if test='custom.operator == "not like" or custom.operator == "not in"'>
|
||||
and b.id not in (
|
||||
</if>
|
||||
<if test='custom.operator != "not like" and custom.operator != "not in"'>
|
||||
and b.id in (
|
||||
</if>
|
||||
select bug_id from bug_custom_field where field_id = #{custom.id}
|
||||
<choose>
|
||||
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
|
||||
and ${custom.value}
|
||||
</when>
|
||||
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<when test="custom.type == 'richText' or custom.type == 'textarea'">
|
||||
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>
|
||||
)
|
||||
</foreach>
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package io.metersphere.bug.mapper;
|
||||
|
||||
import io.metersphere.bug.dto.BugRelationCaseCountDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
public interface ExtBugRelationCaseMapper {
|
||||
|
||||
/**
|
||||
* 统计缺陷关联的用例数量
|
||||
* @param bugIds 缺陷ID集合
|
||||
* @return 缺陷关联DTO
|
||||
*/
|
||||
List<BugRelationCaseCountDTO> countRelationCases(@Param("ids") List<String> bugIds);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?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">
|
||||
<mapper namespace="io.metersphere.bug.mapper.ExtBugRelationCaseMapper">
|
||||
<select id="countRelationCases" resultType="io.metersphere.bug.dto.BugRelationCaseCountDTO">
|
||||
select count(id) as relationCaseCount, bug_id as bugId from bug_relation_case brc
|
||||
where brc.bug_id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
group by brc.bug_id
|
||||
</select>
|
||||
</mapper>
|
|
@ -0,0 +1,29 @@
|
|||
//package io.metersphere.bug.service;
|
||||
//
|
||||
//import io.metersphere.bug.mapper.BugAttachmentMapper;
|
||||
//import io.metersphere.bug.mapper.BugMapper;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//@Service
|
||||
//public class BugHistoryService {
|
||||
//
|
||||
// @Resource
|
||||
// private BugMapper bugMapper;
|
||||
// @Resource
|
||||
// private BugAttachmentMapper bugAttachmentMapper;
|
||||
//
|
||||
// public void save(String bugId) {
|
||||
// /*
|
||||
// * 变更历史内容: BUG信息(基础字段, 自定义字段, 缺陷内容大字段, 附件)
|
||||
// */
|
||||
// }
|
||||
//
|
||||
// public void compare() {
|
||||
// // 对比变更历史
|
||||
// }
|
||||
//
|
||||
// public void rollback() {
|
||||
// // 回退变更历史
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,519 @@
|
|||
package io.metersphere.bug.service;
|
||||
|
||||
import io.metersphere.bug.domain.*;
|
||||
import io.metersphere.bug.dto.BugCustomFieldDTO;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.BugRelationCaseCountDTO;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.bug.enums.BugPlatform;
|
||||
import io.metersphere.bug.mapper.*;
|
||||
import io.metersphere.bug.utils.CustomFieldUtils;
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.domain.FileMetadataExample;
|
||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||
import io.metersphere.project.service.FileService;
|
||||
import io.metersphere.project.service.ProjectTemplateService;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.StorageType;
|
||||
import io.metersphere.sdk.constants.TemplateScene;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.MsFileUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.domain.Template;
|
||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||
import io.metersphere.system.dto.sdk.TemplateDTO;
|
||||
import io.metersphere.system.file.FileRequest;
|
||||
import io.metersphere.system.mapper.BaseUserMapper;
|
||||
import io.metersphere.system.mapper.TemplateMapper;
|
||||
import io.metersphere.system.service.BaseTemplateService;
|
||||
import io.metersphere.system.service.PlatformPluginService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.metersphere.bug.enums.result.BugResultCode.BUG_NOT_EXIST;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class BugService {
|
||||
|
||||
@Resource
|
||||
private BugMapper bugMapper;
|
||||
@Resource
|
||||
private ExtBugMapper extBugMapper;
|
||||
@Resource
|
||||
private BugContentMapper bugContentMapper;
|
||||
@Resource
|
||||
private BaseUserMapper baseUserMapper;
|
||||
@Resource
|
||||
protected TemplateMapper templateMapper;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
@Resource
|
||||
private PlatformPluginService platformPluginService;
|
||||
@Resource
|
||||
private ProjectTemplateService projectTemplateService;
|
||||
@Resource
|
||||
private BugCustomFieldMapper bugCustomFieldMapper;
|
||||
@Resource
|
||||
private ExtBugCustomFieldMapper extBugCustomFieldMapper;
|
||||
@Resource
|
||||
private ExtBugRelationCaseMapper extBugRelationCaseMapper;
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private BugAttachmentMapper bugAttachmentMapper;
|
||||
@Resource
|
||||
private ExtBugAttachmentMapper extBugAttachmentMapper;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
@Resource
|
||||
private BaseTemplateService baseTemplateService;
|
||||
|
||||
/**
|
||||
* 缺陷列表查询
|
||||
*
|
||||
* @param request 列表请求参数
|
||||
* @return 缺陷列表
|
||||
*/
|
||||
public List<BugDTO> list(BugPageRequest request) {
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request);
|
||||
List<BugDTO> bugs = extBugMapper.list(request);
|
||||
if (CollectionUtils.isEmpty(bugs)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 处理自定义字段及状态字段
|
||||
List<BugDTO> bugList = handleCustomFieldsAndStatus(bugs, request.getProjectId());
|
||||
return buildExtraInfo(bugList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建缺陷
|
||||
*
|
||||
* @param request 缺陷请求参数
|
||||
* @param files 附件集合
|
||||
* @param currentUser 当前用户
|
||||
*/
|
||||
public void add(BugEditRequest request, List<MultipartFile> files, String currentUser) {
|
||||
/*
|
||||
* 缺陷创建逻辑
|
||||
* 1. 判断所属项目是否关联第三方平台;
|
||||
* 2. 根据模板自定义字段保存缺陷, 附件一起保存;
|
||||
* 3. 第三方平台需调用插件同步缺陷至其他平台(API字段, 附件需处理);
|
||||
* 4. 变更历史, 操作记录;
|
||||
*/
|
||||
// TODO: 后续补充第三方平台同步逻辑(缺陷, 附件)
|
||||
// String platformName = projectApplicationService.getPlatformName(request.getProjectId());
|
||||
// request.setPlatform(platformName);
|
||||
// if (!StringUtils.equals(platformName, BugPlatform.LOCAL.getName())) {
|
||||
// // 关联第三方平台
|
||||
// ServiceIntegration serviceIntegration = projectTemplateService.getServiceIntegration(request.getProjectId());
|
||||
// if (serviceIntegration == null) {
|
||||
// // 项目未配置第三方平台
|
||||
// throw new MSException(Translator.get("third_party_not_config"));
|
||||
// }
|
||||
// // 获取配置平台, 插入平台缺陷
|
||||
// Platform platform = platformPluginService.getPlatform(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId(),
|
||||
// new String(serviceIntegration.getConfiguration()));
|
||||
// PlatformBugUpdateRequest platformRequest = buildPlatformBugRequest(request);
|
||||
// String platformBugId = platform.addBug(platformRequest);
|
||||
// request.setPlatformBugId(platformBugId);
|
||||
// }
|
||||
// 缺陷基础字段
|
||||
handleAndSaveBug(request, currentUser, BugPlatform.LOCAL.getName());
|
||||
// 自定义字段
|
||||
handleAndSaveCustomFields(request, false);
|
||||
// 附件
|
||||
handleAndSaveAttachments(request, files, currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新缺陷
|
||||
*
|
||||
* @param request 缺陷请求参数
|
||||
* @param files 附件集合
|
||||
* @param currentUser 当前用户
|
||||
*/
|
||||
public void update(BugEditRequest request, List<MultipartFile> files, String currentUser) {
|
||||
/*
|
||||
* 缺陷更新逻辑
|
||||
* 1. 保存逻辑与创建(1, 2, 3, 4)一致.
|
||||
* 2. 需校验状态流
|
||||
*/
|
||||
// TODO: 后续补充第三方平台同步逻辑(缺陷, 附件)
|
||||
// 缺陷
|
||||
handleAndSaveBug(request, currentUser, BugPlatform.LOCAL.getName());
|
||||
// 自定义字段
|
||||
handleAndSaveCustomFields(request, true);
|
||||
// 附件
|
||||
handleAndSaveAttachments(request, files, currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缺陷
|
||||
*
|
||||
* @param id 缺陷ID
|
||||
*/
|
||||
public void delete(String id) {
|
||||
Bug bug = bugMapper.selectByPrimaryKey(id);
|
||||
if (bug == null) {
|
||||
throw new MSException(BUG_NOT_EXIST);
|
||||
}
|
||||
if (StringUtils.equals(bug.getPlatform(), BugPlatform.LOCAL.getName())) {
|
||||
Bug record = new Bug();
|
||||
record.setId(id);
|
||||
record.setTrash(true);
|
||||
bugMapper.updateByPrimaryKeySelective(record);
|
||||
} else {
|
||||
bugMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缺陷模板详情
|
||||
*
|
||||
* @param templateId 模板ID
|
||||
* @param projectId 项目ID
|
||||
* @return 模板详情
|
||||
*/
|
||||
public TemplateDTO getTemplate(String templateId, String projectId) {
|
||||
Template template = templateMapper.selectByPrimaryKey(templateId);
|
||||
if (template != null) {
|
||||
// 属于系统模板
|
||||
return baseTemplateService.getTemplateDTO(template);
|
||||
} else {
|
||||
// 不属于系统模板
|
||||
List<ProjectTemplateOptionDTO> option = projectTemplateService.getOption(projectId, TemplateScene.BUG.name());
|
||||
Optional<ProjectTemplateOptionDTO> isThirdPartyDefaultTemplate = option.stream().filter(projectTemplateOptionDTO -> StringUtils.equals(projectTemplateOptionDTO.getId(), templateId)).findFirst();
|
||||
if (isThirdPartyDefaultTemplate.isPresent()) {
|
||||
// TODO: 获取第三方平台模板
|
||||
return null;
|
||||
} else {
|
||||
// 不属于系统模板&&不属于第三方平台默认模板, 则该模板已被删除
|
||||
return projectTemplateService.getDefaultTemplateDTO(projectId, TemplateScene.BUG.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理保存缺陷基础信息
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @param currentUser 当前用户ID
|
||||
* @param platformName 第三方平台名称
|
||||
*/
|
||||
private void handleAndSaveBug(BugEditRequest request, String currentUser, String platformName) {
|
||||
Bug bug = new Bug();
|
||||
BeanUtils.copyBean(bug, request);
|
||||
bug.setPlatform(platformName);
|
||||
// TODO: 关于平台, 后续补充, 暂保留
|
||||
// if (StringUtils.equalsIgnoreCase(BugPlatform.LOCAL.getName(), platformName)) {
|
||||
// bug.setPlatformBugId(null);
|
||||
// } else {
|
||||
// bug.setPlatformBugId(platformBugId);
|
||||
// }
|
||||
if (StringUtils.isEmpty(bug.getId())) {
|
||||
bug.setId(IDGenerator.nextStr());
|
||||
// TODO: 业务ID生成规则, 暂保留, 后续补充
|
||||
bug.setNum(Long.valueOf(NumGenerator.nextNum(request.getProjectId(), ApplicationNumScope.BUG_MANAGEMENT)).intValue());
|
||||
bug.setHandleUsers(request.getHandleUser());
|
||||
bug.setCreateUser(currentUser);
|
||||
bug.setCreateTime(System.currentTimeMillis());
|
||||
bug.setUpdateUser(currentUser);
|
||||
bug.setUpdateTime(System.currentTimeMillis());
|
||||
bug.setDeleteUser(currentUser);
|
||||
bug.setDeleteTime(System.currentTimeMillis());
|
||||
bug.setTrash(false);
|
||||
bugMapper.insert(bug);
|
||||
request.setId(bug.getId());
|
||||
BugContent bugContent = new BugContent();
|
||||
bugContent.setBugId(bug.getId());
|
||||
bugContent.setDescription(request.getDescription());
|
||||
bugContentMapper.insert(bugContent);
|
||||
} else {
|
||||
Bug orignalBug = checkBugExist(request.getId());
|
||||
// 追加处理人
|
||||
bug.setHandleUsers(orignalBug.getHandleUsers() + "," + request.getHandleUser());
|
||||
bug.setUpdateUser(currentUser);
|
||||
bug.setUpdateTime(System.currentTimeMillis());
|
||||
bugMapper.updateByPrimaryKeySelective(bug);
|
||||
BugContent bugContent = new BugContent();
|
||||
bugContent.setBugId(bug.getId());
|
||||
bugContent.setDescription(request.getDescription());
|
||||
bugContentMapper.updateByPrimaryKeySelective(bugContent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验缺陷是否存在
|
||||
* @param id 缺陷ID
|
||||
* @return 缺陷
|
||||
*/
|
||||
private Bug checkBugExist(String id) {
|
||||
BugExample bugExample = new BugExample();
|
||||
bugExample.createCriteria().andIdEqualTo(id).andTrashEqualTo(false);
|
||||
List<Bug> bugs = bugMapper.selectByExample(bugExample);
|
||||
if (CollectionUtils.isEmpty(bugs)) {
|
||||
throw new MSException(BUG_NOT_EXIST);
|
||||
}
|
||||
return bugs.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理保存自定义字段信息
|
||||
*
|
||||
* @param request 请求参数
|
||||
*/
|
||||
private void handleAndSaveCustomFields(BugEditRequest request, boolean merge) {
|
||||
Map<String, String> customFieldMap = request.getCustomFieldMap();
|
||||
if (MapUtils.isEmpty(customFieldMap)) {
|
||||
return;
|
||||
}
|
||||
List<BugCustomField> addFields = new ArrayList<>();
|
||||
List<BugCustomField> updateFields = new ArrayList<>();
|
||||
if (merge) {
|
||||
// 编辑缺陷需合并原有自定义字段
|
||||
List<BugCustomFieldDTO> originalFields = extBugCustomFieldMapper.getBugCustomFields(List.of(request.getId()), request.getProjectId());
|
||||
Map<String, String> originalFieldMap = originalFields.stream().collect(Collectors.toMap(BugCustomFieldDTO::getId, BugCustomFieldDTO::getValue));
|
||||
customFieldMap.keySet().forEach(fieldId -> {
|
||||
BugCustomField bugCustomField = new BugCustomField();
|
||||
if (!originalFieldMap.containsKey(fieldId)) {
|
||||
// 新的缺陷字段关系
|
||||
bugCustomField.setBugId(request.getId());
|
||||
bugCustomField.setFieldId(fieldId);
|
||||
bugCustomField.setValue(customFieldMap.get(fieldId));
|
||||
addFields.add(bugCustomField);
|
||||
} else {
|
||||
// 已存在的缺陷字段关系
|
||||
bugCustomField.setBugId(request.getId());
|
||||
bugCustomField.setFieldId(fieldId);
|
||||
bugCustomField.setValue(customFieldMap.get(fieldId));
|
||||
updateFields.add(bugCustomField);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 新增缺陷不需要合并自定义字段
|
||||
customFieldMap.keySet().forEach(fieldId -> {
|
||||
BugCustomField bugCustomField = new BugCustomField();
|
||||
bugCustomField.setBugId(request.getId());
|
||||
bugCustomField.setFieldId(fieldId);
|
||||
bugCustomField.setValue(customFieldMap.get(fieldId));
|
||||
addFields.add(bugCustomField);
|
||||
});
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(addFields)) {
|
||||
bugCustomFieldMapper.batchInsert(addFields);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateFields)) {
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
BugCustomFieldMapper bugCustomFieldMapper = sqlSession.getMapper(BugCustomFieldMapper.class);
|
||||
for (BugCustomField bugCustomField : updateFields) {
|
||||
BugCustomFieldExample bugCustomFieldExample = new BugCustomFieldExample();
|
||||
bugCustomFieldExample.createCriteria().andBugIdEqualTo(bugCustomField.getBugId()).andFieldIdEqualTo(bugCustomField.getFieldId());
|
||||
bugCustomFieldMapper.updateByExample(bugCustomField, bugCustomFieldExample);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理保存附件信息
|
||||
* @param request 请求参数
|
||||
* @param files 上传附件集合
|
||||
*/
|
||||
private void handleAndSaveAttachments(BugEditRequest request, List<MultipartFile> files, String currentUser) {
|
||||
Map<String, MultipartFile> uploadMinioFiles = new HashMap<>(16);
|
||||
List<BugAttachment> addFiles = new ArrayList<>();
|
||||
// 处理删除的本地上传附件及取消关联的附件
|
||||
List<String> deleteIds = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(request.getDeleteLocalFileIds())) {
|
||||
deleteIds.addAll(request.getDeleteLocalFileIds());
|
||||
request.getDeleteLocalFileIds().forEach(deleteFileId -> {
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setProjectId(request.getProjectId());
|
||||
fileRequest.setFileName(deleteFileId);
|
||||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
try {
|
||||
fileService.deleteFile(fileRequest);
|
||||
} catch (Exception e) {
|
||||
throw new MSException(Translator.get("bug_attachment_delete_error"));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(request.getUnLinkFileIds())) {
|
||||
deleteIds.addAll(request.getUnLinkFileIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(deleteIds)) {
|
||||
BugAttachmentExample example = new BugAttachmentExample();
|
||||
example.createCriteria().andBugIdEqualTo(request.getId()).andFileIdIn(deleteIds);
|
||||
bugAttachmentMapper.deleteByExample(example);
|
||||
// TODO: 如果是第三方平台, 需调用平台插件同步删除附件
|
||||
}
|
||||
// 新本地上传的附件
|
||||
if (CollectionUtils.isNotEmpty(files)) {
|
||||
files.forEach(file -> {
|
||||
BugAttachment bugAttachment = new BugAttachment();
|
||||
bugAttachment.setId(IDGenerator.nextStr());
|
||||
bugAttachment.setBugId(request.getId());
|
||||
bugAttachment.setFileId(IDGenerator.nextStr());
|
||||
bugAttachment.setFileName(file.getOriginalFilename());
|
||||
bugAttachment.setSize(file.getSize());
|
||||
bugAttachment.setLocal(true);
|
||||
bugAttachment.setCreateTime(System.currentTimeMillis());
|
||||
bugAttachment.setCreateUser(currentUser);
|
||||
addFiles.add(bugAttachment);
|
||||
uploadMinioFiles.put(bugAttachment.getFileId(), file);
|
||||
});
|
||||
}
|
||||
// 新关联的附件
|
||||
List<String> linkIds = request.getLinkFileIds();
|
||||
if (CollectionUtils.isNotEmpty(linkIds)) {
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
example.createCriteria().andIdIn(linkIds);
|
||||
List<FileMetadata> linkFiles = fileMetadataMapper.selectByExample(example);
|
||||
Map<String, FileMetadata> linkFileMap = linkFiles.stream().collect(Collectors.toMap(FileMetadata::getId, v -> v));
|
||||
linkIds.forEach(fileId -> {
|
||||
FileMetadata fileMetadata = linkFileMap.get(fileId);
|
||||
if (fileMetadata == null) {
|
||||
return;
|
||||
}
|
||||
BugAttachment bugAttachment = new BugAttachment();
|
||||
bugAttachment.setId(IDGenerator.nextStr());
|
||||
bugAttachment.setBugId(request.getId());
|
||||
bugAttachment.setFileId(fileId);
|
||||
bugAttachment.setFileName(fileMetadata.getName());
|
||||
bugAttachment.setSize(fileMetadata.getSize());
|
||||
bugAttachment.setLocal(false);
|
||||
bugAttachment.setCreateTime(System.currentTimeMillis());
|
||||
bugAttachment.setCreateUser(currentUser);
|
||||
addFiles.add(bugAttachment);
|
||||
});
|
||||
}
|
||||
extBugAttachmentMapper.batchInsert(addFiles);
|
||||
// TODO: 如果是第三方平台, 需调用平台插件同步上传附件
|
||||
uploadMinioFiles.forEach((fileId, file) -> {
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(file.getOriginalFilename());
|
||||
fileRequest.setResourceId("/" + MsFileUtils.BUG_MANAGEMENT_DIR + "/" + request.getProjectId() + "/" + fileId);
|
||||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
try {
|
||||
fileService.upload(file, fileRequest);
|
||||
} catch (Exception e) {
|
||||
throw new MSException(Translator.get("bug_attachment_upload_error"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 封装缺陷平台请求参数
|
||||
// * @param request 缺陷请求参数
|
||||
// */
|
||||
// private PlatformBugUpdateRequest buildPlatformBugRequest(BugEditRequest request) {
|
||||
// /*
|
||||
// * TODO: 封装缺陷平台请求参数
|
||||
// * 如果是系统默认模板, 只需获取模板中有配置API的字段并处理
|
||||
// * 如果是平台默认模板, 则处理参数中全部自定义字段
|
||||
// */
|
||||
// return new PlatformBugUpdateRequest();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 封装缺陷其他字段
|
||||
*
|
||||
* @param bugs 缺陷集合
|
||||
* @return 缺陷DTO集合
|
||||
*/
|
||||
private List<BugDTO> buildExtraInfo(List<BugDTO> bugs) {
|
||||
// 获取用户集合
|
||||
List<String> userIds = new ArrayList<>();
|
||||
userIds.addAll(bugs.stream().map(BugDTO::getCreateUser).toList());
|
||||
userIds.addAll(bugs.stream().map(BugDTO::getHandleUser).toList());
|
||||
List<String> distinctUserIds = userIds.stream().distinct().toList();
|
||||
List<OptionDTO> userOptions = baseUserMapper.selectUserOptionByIds(distinctUserIds);
|
||||
Map<String, String> userMap = userOptions.stream().collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName));
|
||||
// 根据缺陷ID获取关联用例数
|
||||
List<String> ids = bugs.stream().map(BugDTO::getId).toList();
|
||||
List<BugRelationCaseCountDTO> relationCaseCount = extBugRelationCaseMapper.countRelationCases(ids);
|
||||
Map<String, Integer> countMap = relationCaseCount.stream().collect(Collectors.toMap(BugRelationCaseCountDTO::getBugId, BugRelationCaseCountDTO::getRelationCaseCount));
|
||||
bugs.forEach(bug -> {
|
||||
bug.setRelationCaseCount(countMap.get(bug.getId()));
|
||||
bug.setCreateUserName(userMap.get(bug.getCreateUser()));
|
||||
bug.setAssignUserName(userMap.get(bug.getHandleUser()));
|
||||
});
|
||||
return bugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义字段及状态字段
|
||||
*
|
||||
* @param bugs 缺陷集合
|
||||
* @return 缺陷DTO集合
|
||||
*/
|
||||
private List<BugDTO> handleCustomFieldsAndStatus(List<BugDTO> bugs, String projectId) {
|
||||
List<String> ids = bugs.stream().map(BugDTO::getId).toList();
|
||||
List<BugCustomFieldDTO> customFields = extBugCustomFieldMapper.getBugCustomFields(ids, projectId);
|
||||
Map<String, List<BugCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(BugCustomFieldDTO::getBugId));
|
||||
bugs.forEach(bug -> {
|
||||
bug.setCustomFields(customFieldMap.get(bug.getId()));
|
||||
// 缺陷状态选项值不存在时不展示 暂时保留, 项目插件同步配置开发后补充
|
||||
// List<BugStatusOptionDTO> statusOption = bugStatusService.getProjectStatusOption(bug.getProjectId());
|
||||
// if (CollectionUtils.isNotEmpty(statusOption)) {
|
||||
// Optional<BugStatusOptionDTO> statusOpt = statusOption.stream().filter(optionDTO -> optionDTO.getId().equals(bug.getStatus())).findFirst();
|
||||
// statusOpt.ifPresent(optionDTO -> bug.setStatusName(optionDTO.getName()));
|
||||
// }
|
||||
});
|
||||
return bugs;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取第三方平台模板
|
||||
// *
|
||||
// * @param projectId 项目ID
|
||||
// * @return 第三方平台模板
|
||||
// */
|
||||
// private TemplateDTO getPluginBugTemplate(String projectId) {
|
||||
// ServiceIntegration serviceIntegration = projectTemplateService.getServiceIntegration(projectId);
|
||||
// if (serviceIntegration == null) {
|
||||
// return null;
|
||||
// }
|
||||
// TemplateDTO template = new TemplateDTO();
|
||||
// Template pluginTemplate = projectTemplateService.getPluginBugTemplate(projectId);
|
||||
// BeanUtils.copyBean(template, pluginTemplate);
|
||||
// Platform platform = platformPluginService.getPlatform(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId(),
|
||||
// new String(serviceIntegration.getConfiguration()));
|
||||
// // TODO: 插件平台获取自定义字段, 并针对特殊字段单独处理
|
||||
// List<PlatformCustomFieldItemDTO> platformCustomFields = platform.getThirdPartCustomField("");
|
||||
// if (CollectionUtils.isNotEmpty(platformCustomFields)) {
|
||||
// List<TemplateCustomFieldDTO> customFields = platformCustomFields.stream().map(platformCustomField -> {
|
||||
// TemplateCustomFieldDTO customField = new TemplateCustomFieldDTO();
|
||||
// customField.setFieldId(platformCustomField.getId());
|
||||
// customField.setFieldName(platformCustomField.getName());
|
||||
// customField.setDefaultValue(platformCustomField.getDefaultValue());
|
||||
// customField.setRequired(platformCustomField.getRequired());
|
||||
// return customField;
|
||||
// }).toList();
|
||||
// template.setCustomFields(customFields);
|
||||
// }
|
||||
// return template;
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//package io.metersphere.bug.service;
|
||||
//
|
||||
//import io.metersphere.bug.dto.BugStatusOptionDTO;
|
||||
//import io.metersphere.bug.enums.BugPlatform;
|
||||
//import io.metersphere.plugin.platform.spi.Platform;
|
||||
//import io.metersphere.project.service.ProjectApplicationService;
|
||||
//import io.metersphere.project.service.ProjectTemplateService;
|
||||
//import io.metersphere.sdk.exception.MSException;
|
||||
//import io.metersphere.sdk.util.Translator;
|
||||
//import io.metersphere.system.domain.ServiceIntegration;
|
||||
//import io.metersphere.system.service.PlatformPluginService;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import org.apache.commons.lang3.StringUtils;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//@Service
|
||||
//@Transactional(rollbackFor = Exception.class)
|
||||
//public class BugStatusService {
|
||||
//
|
||||
// @Resource
|
||||
// private ProjectApplicationService projectApplicationService;
|
||||
// @Resource
|
||||
// private ProjectTemplateService projectTemplateService;
|
||||
// @Resource
|
||||
// private PlatformPluginService platformPluginService;
|
||||
//
|
||||
// /**
|
||||
// * 获取状态下拉选项
|
||||
// * @param projectId 项目ID
|
||||
// * @return 选项集合
|
||||
// */
|
||||
// public List<BugStatusOptionDTO> getProjectStatusOption(String projectId) {
|
||||
// // TODO: 获取状态下拉选项 {Local平台: 直接取状态流中的选项, 第三方平台: 取第三方插件平台的状态和状态流中的选项}
|
||||
// String platformName = projectApplicationService.getPlatformName(projectId);
|
||||
// if (StringUtils.equals(platformName, BugPlatform.LOCAL.getName())) {
|
||||
// return getProjectStatusItemOption(projectId);
|
||||
// } else {
|
||||
// // 状态流 && 第三方平台状态流
|
||||
// ServiceIntegration serviceIntegration = projectTemplateService.getServiceIntegration(projectId);
|
||||
// if (serviceIntegration == null) {
|
||||
// // 项目未配置第三方平台
|
||||
// throw new MSException(Translator.get("third_party_not_config"));
|
||||
// }
|
||||
// // 获取配置平台, 获取第三方平台状态流
|
||||
// Platform platform = platformPluginService.getPlatform(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId(),
|
||||
// new String(serviceIntegration.getConfiguration()));
|
||||
//// List<PlatformStatusDTO> statusList = platform.getStatusList();
|
||||
// // 获取项目状态流
|
||||
//// List<BugStatusOptionDTO> projectStatusItemOption = getProjectStatusItemOption(projectId);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取项目状态流选项
|
||||
// * @param projectId 项目ID
|
||||
// * @return 选项集合
|
||||
// */
|
||||
// public List<BugStatusOptionDTO> getProjectStatusItemOption(String projectId) {
|
||||
// // TODO: 获取项目状态流选项
|
||||
// return null;
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,19 @@
|
|||
//package io.metersphere.bug.service;
|
||||
//
|
||||
//import io.metersphere.sdk.util.LogUtils;
|
||||
//import io.metersphere.system.service.CleanupProjectResourceService;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//@Component
|
||||
//public class CleanupBugResourceService implements CleanupProjectResourceService {
|
||||
//
|
||||
// @Override
|
||||
// public void deleteResources(String projectId) {
|
||||
// LogUtils.info("删除当前项目[" + projectId + "]相关缺陷资源");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void cleanReportResources(String projectId) {
|
||||
// LogUtils.info("清理当前项目[" + projectId + "]相关缺陷报告资源");
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,63 @@
|
|||
package io.metersphere.bug.utils;
|
||||
|
||||
import io.metersphere.sdk.constants.CustomFieldType;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字段处理工具类
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
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(BasePageRequest request) {
|
||||
// handle filter custom multiple fields
|
||||
if (MapUtils.isNotEmpty(request.getFilter())) {
|
||||
request.getFilter().entrySet().forEach(entry -> {
|
||||
if (entry.getKey().startsWith(CUSTOM_MULTIPLE_PREFIX) && CollectionUtils.isNotEmpty(entry.getValue())) {
|
||||
List<String> jsonValues = entry.getValue().stream().map(item -> "[\"".concat(item).concat("\"]")).collect(Collectors.toList());
|
||||
entry.setValue(jsonValues);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// handle combine custom multiple fields
|
||||
if (MapUtils.isNotEmpty(request.getCombine()) && ObjectUtils.isNotEmpty((request.getCombine().get(COMBINE_CUSTOM)))) {
|
||||
//noinspection unchecked
|
||||
List<Map<String, Object>> customs = (List<Map<String, Object>>) request.getCombine().get(COMBINE_CUSTOM);
|
||||
customs.forEach(custom -> {
|
||||
// when member select or member multipart select support current user, open it
|
||||
// if(StringUtils.equalsIgnoreCase(custom.get(COMBINE_CUSTOM_FIELD_OPERATOR).toString(), IS_CURRENT_USER)){
|
||||
// String userId = SessionUtils.getUserId();
|
||||
// custom.put(COMBINE_CUSTOM_FIELD_VALUE, userId);
|
||||
// }
|
||||
if (StringUtils.equalsAny(custom.get(COMBINE_CUSTOM_FIELD_TYPE).toString(), CustomFieldType.MULTIPLE_MEMBER.getType(),
|
||||
CustomFieldType.CHECKBOX.getType(), CustomFieldType.MULTIPLE_SELECT.getType())
|
||||
&& StringUtils.isNotEmpty(custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString())) {
|
||||
List<String> customValues = JSON.parseArray(custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString(), 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(")"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -71,13 +71,13 @@
|
|||
|
||||
<!--要生成的数据库表 -->
|
||||
<table tableName="bug" />
|
||||
<table tableName="bug_content" />
|
||||
<table tableName="bug_follower" />
|
||||
<table tableName="bug_comment" />
|
||||
<table tableName="bug_attachment" />
|
||||
<table tableName="bug_custom_field" />
|
||||
<table tableName="bug_relation_case" />
|
||||
<table tableName="bug_history" />
|
||||
<!-- <table tableName="bug_content" />-->
|
||||
<!-- <table tableName="bug_follower" />-->
|
||||
<!-- <table tableName="bug_comment" />-->
|
||||
<!-- <table tableName="bug_attachment" />-->
|
||||
<!-- <table tableName="bug_custom_field" />-->
|
||||
<!-- <table tableName="bug_relation_case" />-->
|
||||
<!-- <table tableName="bug_history" />-->
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
[
|
||||
{
|
||||
"id": "BUG",
|
||||
"name": "permission.bug.name",
|
||||
"type": "BUG",
|
||||
"children": [
|
||||
{
|
||||
"id": "BUG",
|
||||
"name": "permission.bug.name",
|
||||
"permissions": [
|
||||
{
|
||||
"id": "BUG:READ"
|
||||
},
|
||||
{
|
||||
"id": "BUG:READ+ADD"
|
||||
},
|
||||
{
|
||||
"id": "BUG:READ+UPDATE"
|
||||
},
|
||||
{
|
||||
"id": "BUG:READ+DELETE"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -19,7 +19,7 @@ import org.springframework.context.annotation.ComponentScan;
|
|||
MinioProperties.class
|
||||
})
|
||||
@ServletComponentScan
|
||||
@ComponentScan(basePackages = {"io.metersphere.sdk", "io.metersphere.bug", "io.metersphere.system"})
|
||||
@ComponentScan(basePackages = {"io.metersphere.sdk", "io.metersphere.system", "io.metersphere.project", "io.metersphere.bug"})
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
package io.metersphere.bug.controller;
|
||||
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import io.metersphere.system.dto.sdk.TemplateDTO;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
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 org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlConfig;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class BugControllerTests extends BaseTest {
|
||||
|
||||
public static final String BUG_PAGE = "/bug/page";
|
||||
public static final String BUG_ADD = "/bug/add";
|
||||
public static final String BUG_UPDATE = "/bug/update";
|
||||
public static final String BUG_DELETE = "/bug/delete";
|
||||
public static final String BUG_TEMPLATE_OPTION = "/bug/template/option";
|
||||
public static final String BUG_TEMPLATE_DETAIL = "/bug/template";
|
||||
|
||||
@Test
|
||||
@Order(0)
|
||||
@Sql(scripts = {"/dml/init_bug.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void testBugPageSuccess() throws Exception {
|
||||
BugPageRequest bugRequest = new BugPageRequest();
|
||||
bugRequest.setCurrent(1);
|
||||
bugRequest.setPageSize(10);
|
||||
bugRequest.setKeyword("default");
|
||||
bugRequest.setProjectId("default-project-for-bug");
|
||||
bugRequest.setFilter(buildRequestFilter());
|
||||
bugRequest.setCombine(buildRequestCombine());
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(BUG_PAGE, bugRequest);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
// 返回值不为空
|
||||
Assertions.assertNotNull(pageData);
|
||||
// 返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(pageData.getCurrent(), bugRequest.getCurrent());
|
||||
// 返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= bugRequest.getPageSize());
|
||||
// 返回值中取出第一条数据, 并判断是否包含关键字default
|
||||
BugDTO bugDTO = JSON.parseArray(JSON.toJSONString(pageData.getList()), BugDTO.class).get(0);
|
||||
Assertions.assertTrue(StringUtils.contains(bugDTO.getTitle(), bugRequest.getKeyword())
|
||||
|| StringUtils.contains(bugDTO.getId(), bugRequest.getKeyword()));
|
||||
|
||||
// sort不为空
|
||||
Map<String, String> sort = new HashMap<>();
|
||||
sort.put("id", "desc");
|
||||
bugRequest.setSort(sort);
|
||||
MvcResult sortResult = this.requestPostWithOkAndReturn(BUG_PAGE, bugRequest);
|
||||
String sortData = sortResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder sortHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||
Pager<?> sortPageData = JSON.parseObject(JSON.toJSONString(sortHolder.getData()), Pager.class);
|
||||
// 返回值中取出第一条ID最大的数据, 并判断是否是default-bug
|
||||
BugDTO maxBugDTO = JSON.parseArray(JSON.toJSONString(sortPageData.getList()), BugDTO.class).get(0);
|
||||
Assertions.assertTrue(maxBugDTO.getId().contains("default"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void testBugPageEmptySuccess() throws Exception {
|
||||
BugPageRequest bugPageRequest = new BugPageRequest();
|
||||
bugPageRequest.setCurrent(1);
|
||||
bugPageRequest.setPageSize(10);
|
||||
bugPageRequest.setKeyword("default-x");
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(BUG_PAGE, bugPageRequest);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
// 返回值不为空
|
||||
Assertions.assertNotNull(pageData);
|
||||
// 返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(pageData.getCurrent(), bugPageRequest.getCurrent());
|
||||
// 返回的数据量为0条
|
||||
Assertions.assertEquals(0, pageData.getTotal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testBugPageError() throws Exception {
|
||||
// 页码有误
|
||||
BugPageRequest bugPageRequest = new BugPageRequest();
|
||||
bugPageRequest.setCurrent(0);
|
||||
bugPageRequest.setPageSize(10);
|
||||
this.requestPost(BUG_PAGE, bugPageRequest, status().isBadRequest());
|
||||
// 页数有误
|
||||
bugPageRequest = new BugPageRequest();
|
||||
bugPageRequest.setCurrent(1);
|
||||
bugPageRequest.setPageSize(1);
|
||||
this.requestPost(BUG_PAGE, bugPageRequest, status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void testAddBugSuccess() throws Exception {
|
||||
BugEditRequest request = buildRequest(false);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
|
||||
File file = new File(filePath);
|
||||
MultiValueMap<String, Object> paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipartWithOkAndReturn(BUG_ADD, paramMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
public void testAddBugError() throws Exception {
|
||||
BugEditRequest request = buildRequest(false);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
|
||||
File file = new File(filePath);
|
||||
// 项目ID为空
|
||||
request.setProjectId(null);
|
||||
MultiValueMap<String, Object> paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_ADD, paramMap).andExpect(status().isBadRequest());
|
||||
// 标题为空
|
||||
request.setProjectId("default-project-for-bug");
|
||||
request.setTitle(null);
|
||||
paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_ADD, paramMap).andExpect(status().isBadRequest());
|
||||
// 处理人为空
|
||||
request.setTitle("default-bug-title");
|
||||
request.setHandleUser(null);
|
||||
paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_ADD, paramMap).andExpect(status().isBadRequest());
|
||||
// 模板为空
|
||||
request.setHandleUser("admin");
|
||||
request.setTemplateId(null);
|
||||
paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_ADD, paramMap).andExpect(status().isBadRequest());
|
||||
// 状态为空
|
||||
request.setTemplateId("default-bug-template");
|
||||
request.setStatus(null);
|
||||
paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_ADD, paramMap).andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
public void testUpdateBugSuccess() throws Exception {
|
||||
BugEditRequest request = buildRequest(true);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
|
||||
File file = new File(filePath);
|
||||
MultiValueMap<String, Object> paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipartWithOkAndReturn(BUG_UPDATE, paramMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
public void testUpdateBugError() throws Exception {
|
||||
BugEditRequest request = buildRequest(true);
|
||||
request.setId("default-bug-id-not-exist");
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
|
||||
File file = new File(filePath);
|
||||
MultiValueMap<String, Object> paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipart(BUG_UPDATE, paramMap).andExpect(status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
public void testUpdateBugWithEmptyField() throws Exception {
|
||||
BugEditRequest request = buildRequest(true);
|
||||
request.setCustomFieldMap(null);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
|
||||
File file = new File(filePath);
|
||||
MultiValueMap<String, Object> paramMap = getDefaultMultiPartParam(request, file);
|
||||
this.requestMultipartWithOkAndReturn(BUG_UPDATE, paramMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
public void testDeleteBugSuccess() throws Exception {
|
||||
this.requestGet(BUG_DELETE + "/default-bug-id", status().isOk());
|
||||
// 非Local缺陷
|
||||
this.requestGet(BUG_DELETE + "/default-bug-id-tapd", status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(9)
|
||||
public void testDeleteBugError() throws Exception {
|
||||
this.requestGet(BUG_DELETE + "/default-bug-id-not-exist", status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(10)
|
||||
public void testGetBugTemplateOption() throws Exception {
|
||||
MvcResult mvcResult = this.requestGetWithOkAndReturn(BUG_TEMPLATE_OPTION + "?projectId=default-project-for-bug");
|
||||
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||
List<ProjectTemplateOptionDTO> templateOptionDTOS = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), ProjectTemplateOptionDTO.class);
|
||||
// 默认模板断言
|
||||
Assertions.assertTrue(templateOptionDTOS.stream().anyMatch(ProjectTemplateOptionDTO::getEnableDefault));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(11)
|
||||
public void testGetBugTemplateDetailSuccess() throws Exception {
|
||||
MvcResult mvcResult = this.requestGetWithOkAndReturn(BUG_TEMPLATE_DETAIL + "/default-bug-template-id" + "?projectId=default-project-for-bug");
|
||||
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||
TemplateDTO templateDTO = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TemplateDTO.class);
|
||||
Assertions.assertNotNull(templateDTO);
|
||||
Assertions.assertEquals("default-bug-template-id", templateDTO.getId());
|
||||
// 获取默认模板
|
||||
MvcResult defaultResult = this.requestGetWithOkAndReturn(BUG_TEMPLATE_DETAIL + "/default-bug-template-id-not-exist" + "?projectId=default-project-for-bug");
|
||||
String defaultData = defaultResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder defaultResultHolder = JSON.parseObject(defaultData, ResultHolder.class);
|
||||
TemplateDTO defaultTemplate = JSON.parseObject(JSON.toJSONString(defaultResultHolder.getData()), TemplateDTO.class);
|
||||
Assertions.assertNotNull(defaultTemplate);
|
||||
Assertions.assertEquals("default-bug-template-id", defaultTemplate.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求过滤参数
|
||||
* @return filter param
|
||||
*/
|
||||
private Map<String, List<String>> buildRequestFilter() {
|
||||
Map<String, List<String>> filter = new HashMap<>();
|
||||
filter.put("custom_multiple_test_field", List.of("default", "default1"));
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成高级搜索参数
|
||||
* @return combine param
|
||||
*/
|
||||
private Map<String, Object> buildRequestCombine() {
|
||||
Map<String, Object> combine = new HashMap<>();
|
||||
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", "multipleSelect");
|
||||
custom.put("value", JSON.toJSONString(List.of("default", "default1")));
|
||||
customs.add(custom);
|
||||
combine.put("customs", customs);
|
||||
return combine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求参数
|
||||
* @param isUpdate 是否更新操作
|
||||
* @return 请求参数
|
||||
*/
|
||||
private BugEditRequest buildRequest(boolean isUpdate) {
|
||||
BugEditRequest request = new BugEditRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
request.setTitle("default-bug-title");
|
||||
request.setDescription("default-bug-description");
|
||||
request.setHandleUser("admin");
|
||||
request.setTemplateId("default-bug-template");
|
||||
request.setStatus("prepare");
|
||||
request.setTag(JSON.toJSONString(List.of("TAG", "DEFAULT-TAG")));
|
||||
request.setLinkFileIds(List.of("default-bug-file-id-1", "default-bug-file-id-3"));
|
||||
Map<String, String> customFieldMap = new HashMap<>();
|
||||
customFieldMap.put("custom-field", "oasis");
|
||||
if (isUpdate) {
|
||||
request.setId("default-bug-id");
|
||||
request.setUnLinkFileIds(List.of("default-bug-file-id-1"));
|
||||
request.setDeleteLocalFileIds(List.of("default-bug-file-id"));
|
||||
request.setLinkFileIds(List.of("default-bug-file-id-2"));
|
||||
customFieldMap.put("test_field", JSON.toJSONString(List.of("test")));
|
||||
}
|
||||
request.setCustomFieldMap(customFieldMap);
|
||||
return request;
|
||||
}
|
||||
}
|
|
@ -6,14 +6,14 @@ server.compression.enabled=true
|
|||
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css,text/javascript,image/jpeg
|
||||
server.compression.min-response-size=2048
|
||||
#
|
||||
quartz.enabled=false
|
||||
quartz.enabled=true
|
||||
quartz.scheduler-name=msScheduler
|
||||
quartz.thread-count=10
|
||||
quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=true
|
||||
#
|
||||
logging.file.path=/opt/metersphere/logs/metersphere
|
||||
# Hikari
|
||||
spring.datasource.url=jdbc:mysql://${embedded.mysql.host}:${embedded.mysql.port}/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
||||
spring.datasource.url=jdbc:mysql://${embedded.mysql.host}:${embedded.mysql.port}/test?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&useSSL=false&sessionVariables=sql_mode=%27STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION%27
|
||||
spring.datasource.username=${embedded.mysql.user}
|
||||
spring.datasource.password=${embedded.mysql.password}
|
||||
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
||||
|
@ -80,4 +80,4 @@ minio.secret-key=${embedded.minio.secretKey}
|
|||
|
||||
logging.level.org.springframework.jdbc.core=info
|
||||
logging.level.io.metersphere.sdk.mapper=info
|
||||
logging.level.io.metersphere.system.mapper=info
|
||||
logging.level.io.metersphere.bug.mapper=info
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
|
||||
('default-project-for-bug-tmp', null, '100001', '测试项目(缺陷)', '系统默认创建的项目(缺陷)', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
||||
|
||||
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
|
||||
('default-project-for-bug', null, '100001', '测试项目(缺陷)', '系统默认创建的项目(缺陷)', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
||||
|
||||
INSERT INTO bug (id, num, title, handle_users, handle_user, create_user, create_time,
|
||||
update_user, update_time, delete_user, delete_time, project_id, template_id, platform, status, tag, platform_bug_id, trash) VALUES
|
||||
('default-bug-id', 100000, 'default-bug', 'oasis', 'oasis', 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'default-project-for-bug', 'bug-template-id', 'Local', 'open', 'default-tag', null, 0),
|
||||
('default-bug-id-tapd', 100000, 'default-bug', 'oasis', 'oasis', 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'default-project-for-bug', 'default-bug-template-id', 'Tapd', 'open', 'default-tag', null, 0);
|
||||
|
||||
INSERT INTO bug_custom_field (bug_id, field_id, value) VALUE ('default-bug-id', 'test_field', '["default", "default-1"]');
|
||||
|
||||
INSERT INTO custom_field (id, name, scene, type, remark, internal, scope_type, create_time, update_time, create_user, scope_id) VALUE
|
||||
('test_field', '测试字段', 'BUG', 'MULTIPLE_SELECT', '', 0, 'PROJECT', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'default-project-for-bug');
|
||||
|
||||
INSERT INTO template (id, name, remark, internal, update_time, create_time, create_user, scope_type, scope_id, enable_third_part, scene) VALUES
|
||||
('bug-template-id', 'bug-template', '', 0, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'PROJECT', 'default-project-for-bug', 0, 'BUG'),
|
||||
('default-bug-template-id', 'bug-default-template', '', 0, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'PROJECT', 'default-project-for-bug', 0, 'BUG');
|
||||
|
||||
INSERT INTO bug_relation_case (id, case_id, bug_id, case_type, test_plan_id, test_plan_case_id, create_user, create_time, update_time) VALUE
|
||||
(UUID_SHORT(), UUID_SHORT(), 'default-bug-id', 'functional', null, null, 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
||||
|
||||
INSERT INTO file_metadata (id, name, type, size, create_time, update_time, project_id, storage, create_user, update_user,
|
||||
tags, description, module_id, path, latest, ref_id, file_version) VALUES
|
||||
('default-bug-file-id-1', 'test-file', 'xlsx', 100, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'default-project-for-bug', 'MINIO', 'admin', 'admin',
|
||||
'["default-tag"]', 'test-file', null, 'test-file', 1, 'default-bug-id', 1),
|
||||
('default-bug-file-id-2', 'test-file', 'xlsx', 100, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'default-project-for-bug', 'MINIO', 'admin', 'admin',
|
||||
'["default-tag"]', 'test-file', null, 'test-file', 1, 'default-bug-id', 1);
|
||||
|
||||
INSERT INTO project_application (project_id, type, type_value) VALUES ('default-project-for-bug', 'BUG_DEFAULT_TEMPLATE', 'default-bug-template-id');
|
Binary file not shown.
|
@ -24,7 +24,7 @@ public class CommandService {
|
|||
|
||||
public static String createFile(MultipartFile bodyFile) {
|
||||
MsFileUtils.validateFileName(bodyFile.getOriginalFilename());
|
||||
String dir = MsFileUtils.DATE_ROOT_DIR + "/body/environment/tmp";
|
||||
String dir = MsFileUtils.DATA_ROOT_DIR + "/body/environment/tmp";
|
||||
File fileDir = new File(dir);
|
||||
if (!fileDir.exists()) {
|
||||
fileDir.mkdirs();
|
||||
|
|
|
@ -18,13 +18,13 @@ import io.metersphere.project.utils.ModuleSortUtils;
|
|||
import io.metersphere.sdk.constants.OperationLogConstants;
|
||||
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||
import io.metersphere.sdk.constants.ScheduleType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.domain.*;
|
||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.mapper.PluginMapper;
|
||||
import io.metersphere.system.mapper.ServiceIntegrationMapper;
|
||||
import io.metersphere.system.sechedule.ScheduleService;
|
||||
|
@ -568,4 +568,14 @@ public class ProjectApplicationService {
|
|||
List<ProjectApplication> projectApplications = projectApplicationMapper.selectByExample(example);
|
||||
return CollectionUtils.isEmpty(projectApplications) ? null : projectApplications.get(0);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取项目所属平台
|
||||
// * @param projectId 项目ID
|
||||
// * @return 项目所属平台
|
||||
// */
|
||||
// public String getPlatformName(String projectId) {
|
||||
// // TODO 需调用项目平台配置接口, 获取项目所属平台名称
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ public class ProjectTemplateService extends BaseTemplateService {
|
|||
* @param projectId
|
||||
* @return
|
||||
*/
|
||||
private Template getPluginBugTemplate(String projectId) {
|
||||
public Template getPluginBugTemplate(String projectId) {
|
||||
ServiceIntegration serviceIntegration = getServiceIntegration(projectId);
|
||||
if (serviceIntegration == null) {
|
||||
return null;
|
||||
|
@ -240,6 +240,7 @@ public class ProjectTemplateService extends BaseTemplateService {
|
|||
PluginWrapper pluginWrapper = pluginLoadService.getPluginWrapper(pluginId);
|
||||
Template template = new Template();
|
||||
template.setId(pluginWrapper.getPluginId());
|
||||
template.setName(((MsPlugin) pluginWrapper.getPlugin()).getName() + Translator.get("default_template"));
|
||||
template.setCreateUser(InternalUser.ADMIN.getValue());
|
||||
template.setScene(TemplateScene.BUG.name());
|
||||
template.setEnableThirdPart(true);
|
||||
|
@ -257,7 +258,7 @@ public class ProjectTemplateService extends BaseTemplateService {
|
|||
* @param projectId
|
||||
* @return
|
||||
*/
|
||||
private ServiceIntegration getServiceIntegration(String projectId) {
|
||||
public ServiceIntegration getServiceIntegration(String projectId) {
|
||||
// 判断项目是否开启集成缺陷
|
||||
ProjectApplication syncEnableConfig = projectApplicationService.getByType(projectId, ProjectApplicationType.BUG_SYNC_CONFIG.SYNC_ENABLE.name());
|
||||
boolean isSyncEnable = syncEnableConfig != null && Boolean.parseBoolean(syncEnableConfig.getTypeValue());
|
||||
|
|
|
@ -94,6 +94,6 @@ public class LocalFileRepository implements FileRepository {
|
|||
|
||||
private String getFileDir(FileRequest request) {
|
||||
MsFileUtils.validateFileName(request.getProjectId(), request.getFileName());
|
||||
return StringUtils.join(MsFileUtils.DATE_ROOT_DIR, "/", request.getProjectId());
|
||||
return StringUtils.join(MsFileUtils.DATA_ROOT_DIR, "/", request.getProjectId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,4 +47,10 @@
|
|||
#{value}
|
||||
</foreach>
|
||||
</sql>
|
||||
|
||||
<sql id="filterMultipleWrapper">
|
||||
<foreach collection="values" item="value" separator="or" open="(" close=")">
|
||||
JSON_CONTAINS(value, #{value})
|
||||
</foreach>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -2,21 +2,22 @@ package io.metersphere.system.service;
|
|||
|
||||
import io.metersphere.sdk.constants.TemplateScene;
|
||||
import io.metersphere.sdk.constants.TemplateScopeType;
|
||||
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
|
||||
import io.metersphere.system.dto.sdk.TemplateDTO;
|
||||
import io.metersphere.system.dto.sdk.request.TemplateCustomFieldRequest;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.LogUtils;
|
||||
import io.metersphere.system.resolver.field.AbstractCustomFieldResolver;
|
||||
import io.metersphere.system.resolver.field.CustomFieldResolverFactory;
|
||||
import io.metersphere.system.utils.ServiceUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.domain.CustomField;
|
||||
import io.metersphere.system.domain.Template;
|
||||
import io.metersphere.system.domain.TemplateCustomField;
|
||||
import io.metersphere.system.domain.TemplateExample;
|
||||
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
|
||||
import io.metersphere.system.dto.sdk.TemplateDTO;
|
||||
import io.metersphere.system.dto.sdk.request.TemplateCustomFieldRequest;
|
||||
import io.metersphere.system.mapper.TemplateMapper;
|
||||
import io.metersphere.system.resolver.field.AbstractCustomFieldResolver;
|
||||
import io.metersphere.system.resolver.field.CustomFieldResolverFactory;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.utils.ServiceUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -26,7 +27,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.metersphere.system.controller.handler.result.CommonResultCode.*;
|
||||
|
@ -94,7 +94,7 @@ public class BaseTemplateService {
|
|||
return templateMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
protected TemplateDTO getTemplateDTO(Template template) {
|
||||
public TemplateDTO getTemplateDTO(Template template) {
|
||||
List<TemplateCustomField> templateCustomFields = baseTemplateCustomFieldService.getByTemplateId(template.getId());
|
||||
|
||||
// 查找字段名称
|
||||
|
|
Loading…
Reference in New Issue