diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/Bug.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/Bug.java index 9ed6b7a85b..228ce0efa9 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/Bug.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/Bug.java @@ -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), diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachment.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachment.java index d4295cf5f7..af3589d0f3 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachment.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachment.java @@ -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); diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachmentExample.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachmentExample.java index 436f387932..16e7844168 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachmentExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugAttachmentExample.java @@ -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 values) { - addCriterion("association in", values, "association"); + public Criteria andLocalIn(List values) { + addCriterion("`local` in", values, "local"); return (Criteria) this; } - public Criteria andAssociationNotIn(List values) { - addCriterion("association not in", values, "association"); + public Criteria andLocalNotIn(List 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; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugComment.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugComment.java index 724320e309..6af27e2fd2 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugComment.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugComment.java @@ -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 = "`"; diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugExample.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugExample.java index 56a3932d9f..850624bac9 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugExample.java @@ -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 values) { - addCriterion("assign_user in", values, "assignUser"); + public Criteria andHandleUsersIn(List values) { + addCriterion("handle_users in", values, "handleUsers"); return (Criteria) this; } - public Criteria andAssignUserNotIn(List values) { - addCriterion("assign_user not in", values, "assignUser"); + public Criteria andHandleUsersNotIn(List 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 values) { + addCriterion("handle_user in", values, "handleUser"); + return (Criteria) this; + } + + public Criteria andHandleUserNotIn(List 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; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistory.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistory.java index f24cad2d00..619ae89605 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistory.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistory.java @@ -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); diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistoryExample.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistoryExample.java index 577e10072f..7f22e284b3 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistoryExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugHistoryExample.java @@ -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 values) { + addCriterion("`type` in", values, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotIn(List 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 values) { + addCriterion("rollback_source_id in", values, "rollbackSourceId"); + return (Criteria) this; + } + + public Criteria andRollbackSourceIdNotIn(List 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; diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugRelationCase.java b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugRelationCase.java index 59b5cae9de..29278f0cf4 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugRelationCase.java +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/domain/BugRelationCase.java @@ -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) diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugAttachmentMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugAttachmentMapper.xml index 4c6ca52ec8..ac626d64d0 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugAttachmentMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugAttachmentMapper.xml @@ -7,7 +7,7 @@ - + @@ -70,7 +70,7 @@ - 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 select @@ -128,13 +130,13 @@ 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 into bug_comment @@ -148,6 +150,9 @@ reply_user, + + notifier, + parent_id, @@ -163,8 +168,8 @@ update_time, - - description, + + content, @@ -177,6 +182,9 @@ #{replyUser,jdbcType=VARCHAR}, + + #{notifier,jdbcType=VARCHAR}, + #{parentId,jdbcType=VARCHAR}, @@ -192,8 +200,8 @@ #{updateTime,jdbcType=BIGINT}, - - #{description,jdbcType=LONGVARCHAR}, + + #{content,jdbcType=LONGVARCHAR}, @@ -215,6 +223,9 @@ reply_user = #{record.replyUser,jdbcType=VARCHAR}, + + notifier = #{record.notifier,jdbcType=VARCHAR}, + parent_id = #{record.parentId,jdbcType=VARCHAR}, @@ -230,8 +241,8 @@ update_time = #{record.updateTime,jdbcType=BIGINT}, - - description = #{record.description,jdbcType=LONGVARCHAR}, + + content = #{record.content,jdbcType=LONGVARCHAR}, @@ -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} @@ -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 @@ reply_user = #{replyUser,jdbcType=VARCHAR}, + + notifier = #{notifier,jdbcType=VARCHAR}, + parent_id = #{parentId,jdbcType=VARCHAR}, @@ -291,8 +307,8 @@ update_time = #{updateTime,jdbcType=BIGINT}, - - description = #{description,jdbcType=LONGVARCHAR}, + + content = #{content,jdbcType=LONGVARCHAR}, 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 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 @@ 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 (#{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}) @@ -351,6 +369,9 @@ #{item.replyUser,jdbcType=VARCHAR} + + #{item.notifier,jdbcType=VARCHAR} + #{item.parentId,jdbcType=VARCHAR} @@ -366,8 +387,8 @@ #{item.updateTime,jdbcType=BIGINT} - - #{item.description,jdbcType=LONGVARCHAR} + + #{item.content,jdbcType=LONGVARCHAR} ) diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugHistoryMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugHistoryMapper.xml index e23b80309c..555ccfd1f5 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugHistoryMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugHistoryMapper.xml @@ -5,6 +5,8 @@ + + @@ -70,7 +72,7 @@ - id, bug_id, num, create_user, create_time + id, bug_id, num, `type`, rollback_source_id, create_user, create_time content @@ -125,11 +127,11 @@ 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 into bug_history @@ -143,6 +145,12 @@ num, + + `type`, + + + rollback_source_id, + create_user, @@ -163,6 +171,12 @@ #{num,jdbcType=INTEGER}, + + #{type,jdbcType=VARCHAR}, + + + #{rollbackSourceId,jdbcType=VARCHAR}, + #{createUser,jdbcType=VARCHAR}, @@ -192,6 +206,12 @@ num = #{record.num,jdbcType=INTEGER}, + + `type` = #{record.type,jdbcType=VARCHAR}, + + + rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR}, + create_user = #{record.createUser,jdbcType=VARCHAR}, @@ -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} @@ -238,6 +262,12 @@ num = #{num,jdbcType=INTEGER}, + + `type` = #{type,jdbcType=VARCHAR}, + + + rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR}, + create_user = #{createUser,jdbcType=VARCHAR}, @@ -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} 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 (#{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}) @@ -296,6 +330,12 @@ #{item.num,jdbcType=INTEGER} + + #{item.type,jdbcType=VARCHAR} + + + #{item.rollbackSourceId,jdbcType=VARCHAR} + #{item.createUser,jdbcType=VARCHAR} diff --git a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugMapper.xml index 711a892d47..be21d1ee70 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/bug/mapper/BugMapper.xml @@ -5,7 +5,8 @@ - + + @@ -79,9 +80,9 @@ - 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 + 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 + + #{id} + + + + + insert into bug_custom_field (bug_id, field_id, value) values + + (#{field.bugId}, #{field.fieldId}, #{field.value}) + + + \ No newline at end of file diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.java new file mode 100644 index 0000000000..12a74c8786 --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.java @@ -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 list(@Param("request") BugPageRequest request); + + /** + * 获取缺陷业务ID + * + * @param projectId 项目ID + * @return 最大的业务ID + */ + Long getMaxNum(String projectId); +} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.xml b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.xml new file mode 100644 index 0000000000..cac097357a --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugMapper.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + b.trash = 1 + + + b.trash = 0 + + + and b.project_id = #{request.projectId} + + + and ( + b.title like concat('%', #{request.keyword},'%') + or b.num like concat('%', #{request.keyword},'%') + ) + + + + + + + + + + + + + + + and b.handle_user in + + + + and b.create_user in + + + + and b.platform in + + + + and b.status in + + + + and b.id in ( + select bug_id from bug_custom_field where concat('custom_single_', field_id) = #{key} + and trim(both '"' from `value`) in + + ) + + + and b.id in ( + select bug_id from bug_custom_field where concat('custom_multiple_', field_id) = #{key} + and + + ) + + + + + + + + + + + and b.handle_user + + + + + + and b.create_user + + + + + + and b.platform + + + + + + and b.status + + + + + + + + and b.id not in ( + + + and b.id in ( + + select bug_id from bug_custom_field where field_id = #{custom.id} + + + and ${custom.value} + + + and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13) + + + + + + and `value` + + + + + + and trim(both '"' from `value`) + + + + + + ) + + + + + + diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.java new file mode 100644 index 0000000000..789c4677b7 --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.java @@ -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 countRelationCases(@Param("ids") List bugIds); +} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.xml b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.xml new file mode 100644 index 0000000000..e05f0a83d1 --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/mapper/ExtBugRelationCaseMapper.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugHistoryService.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugHistoryService.java new file mode 100644 index 0000000000..2b6681efb5 --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugHistoryService.java @@ -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() { +// // 回退变更历史 +// } +//} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java new file mode 100644 index 0000000000..539cbd162d --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugService.java @@ -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 list(BugPageRequest request) { + CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request); + List bugs = extBugMapper.list(request); + if (CollectionUtils.isEmpty(bugs)) { + return new ArrayList<>(); + } + // 处理自定义字段及状态字段 + List bugList = handleCustomFieldsAndStatus(bugs, request.getProjectId()); + return buildExtraInfo(bugList); + } + + /** + * 创建缺陷 + * + * @param request 缺陷请求参数 + * @param files 附件集合 + * @param currentUser 当前用户 + */ + public void add(BugEditRequest request, List 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 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 option = projectTemplateService.getOption(projectId, TemplateScene.BUG.name()); + Optional 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 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 customFieldMap = request.getCustomFieldMap(); + if (MapUtils.isEmpty(customFieldMap)) { + return; + } + List addFields = new ArrayList<>(); + List updateFields = new ArrayList<>(); + if (merge) { + // 编辑缺陷需合并原有自定义字段 + List originalFields = extBugCustomFieldMapper.getBugCustomFields(List.of(request.getId()), request.getProjectId()); + Map 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 files, String currentUser) { + Map uploadMinioFiles = new HashMap<>(16); + List addFiles = new ArrayList<>(); + // 处理删除的本地上传附件及取消关联的附件 + List 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 linkIds = request.getLinkFileIds(); + if (CollectionUtils.isNotEmpty(linkIds)) { + FileMetadataExample example = new FileMetadataExample(); + example.createCriteria().andIdIn(linkIds); + List linkFiles = fileMetadataMapper.selectByExample(example); + Map 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 buildExtraInfo(List bugs) { + // 获取用户集合 + List userIds = new ArrayList<>(); + userIds.addAll(bugs.stream().map(BugDTO::getCreateUser).toList()); + userIds.addAll(bugs.stream().map(BugDTO::getHandleUser).toList()); + List distinctUserIds = userIds.stream().distinct().toList(); + List userOptions = baseUserMapper.selectUserOptionByIds(distinctUserIds); + Map userMap = userOptions.stream().collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName)); + // 根据缺陷ID获取关联用例数 + List ids = bugs.stream().map(BugDTO::getId).toList(); + List relationCaseCount = extBugRelationCaseMapper.countRelationCases(ids); + Map 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 handleCustomFieldsAndStatus(List bugs, String projectId) { + List ids = bugs.stream().map(BugDTO::getId).toList(); + List customFields = extBugCustomFieldMapper.getBugCustomFields(ids, projectId); + Map> customFieldMap = customFields.stream().collect(Collectors.groupingBy(BugCustomFieldDTO::getBugId)); + bugs.forEach(bug -> { + bug.setCustomFields(customFieldMap.get(bug.getId())); + // 缺陷状态选项值不存在时不展示 暂时保留, 项目插件同步配置开发后补充 +// List statusOption = bugStatusService.getProjectStatusOption(bug.getProjectId()); +// if (CollectionUtils.isNotEmpty(statusOption)) { +// Optional 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 platformCustomFields = platform.getThirdPartCustomField(""); +// if (CollectionUtils.isNotEmpty(platformCustomFields)) { +// List 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; +// } +} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugStatusService.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugStatusService.java new file mode 100644 index 0000000000..5d5ca0cc8b --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/BugStatusService.java @@ -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 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 statusList = platform.getStatusList(); +// // 获取项目状态流 +//// List projectStatusItemOption = getProjectStatusItemOption(projectId); +// } +// return null; +// } +// +// /** +// * 获取项目状态流选项 +// * @param projectId 项目ID +// * @return 选项集合 +// */ +// public List getProjectStatusItemOption(String projectId) { +// // TODO: 获取项目状态流选项 +// return null; +// } +//} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/service/CleanupBugResourceService.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/CleanupBugResourceService.java new file mode 100644 index 0000000000..431916093b --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/service/CleanupBugResourceService.java @@ -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 + "]相关缺陷报告资源"); +// } +//} diff --git a/backend/services/bug-management/src/main/java/io/metersphere/bug/utils/CustomFieldUtils.java b/backend/services/bug-management/src/main/java/io/metersphere/bug/utils/CustomFieldUtils.java new file mode 100644 index 0000000000..513ec98505 --- /dev/null +++ b/backend/services/bug-management/src/main/java/io/metersphere/bug/utils/CustomFieldUtils.java @@ -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 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> customs = (List>) 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 customValues = JSON.parseArray(custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString(), String.class); + List jsonValues = customValues.stream().map(item -> "JSON_CONTAINS(`value`, '[\"".concat(item).concat("\"]')")).toList(); + custom.put(COMBINE_CUSTOM_FIELD_VALUE, "(".concat(StringUtils.join(jsonValues, " OR ")).concat(")")); + } + }); + } + } +} diff --git a/backend/services/bug-management/src/main/resources/bugGeneratorConfig.xml b/backend/services/bug-management/src/main/resources/bugGeneratorConfig.xml index 62507f6eda..ac2cada802 100644 --- a/backend/services/bug-management/src/main/resources/bugGeneratorConfig.xml +++ b/backend/services/bug-management/src/main/resources/bugGeneratorConfig.xml @@ -71,13 +71,13 @@ -
-
-
-
-
-
-
+ + + + + + + diff --git a/backend/services/bug-management/src/main/resources/permission.json b/backend/services/bug-management/src/main/resources/permission.json new file mode 100644 index 0000000000..6bcb2c84bf --- /dev/null +++ b/backend/services/bug-management/src/main/resources/permission.json @@ -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" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/backend/services/bug-management/src/test/java/io/metersphere/bug/Application.java b/backend/services/bug-management/src/test/java/io/metersphere/bug/Application.java index 8394eb791f..83f3e98ec8 100644 --- a/backend/services/bug-management/src/test/java/io/metersphere/bug/Application.java +++ b/backend/services/bug-management/src/test/java/io/metersphere/bug/Application.java @@ -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); diff --git a/backend/services/bug-management/src/test/java/io/metersphere/bug/controller/BugControllerTests.java b/backend/services/bug-management/src/test/java/io/metersphere/bug/controller/BugControllerTests.java new file mode 100644 index 0000000000..72ccf6ca6e --- /dev/null +++ b/backend/services/bug-management/src/test/java/io/metersphere/bug/controller/BugControllerTests.java @@ -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 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 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 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 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 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 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 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> buildRequestFilter() { + Map> filter = new HashMap<>(); + filter.put("custom_multiple_test_field", List.of("default", "default1")); + return filter; + } + + /** + * 生成高级搜索参数 + * @return combine param + */ + private Map buildRequestCombine() { + Map combine = new HashMap<>(); + List> customs = new ArrayList<>(); + Map 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 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; + } +} diff --git a/backend/services/bug-management/src/test/resources/application.properties b/backend/services/bug-management/src/test/resources/application.properties index 7ec051882b..13f5364f31 100644 --- a/backend/services/bug-management/src/test/resources/application.properties +++ b/backend/services/bug-management/src/test/resources/application.properties @@ -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 diff --git a/backend/services/bug-management/src/test/resources/dml/init_bug.sql b/backend/services/bug-management/src/test/resources/dml/init_bug.sql new file mode 100644 index 0000000000..6a30c8b7fe --- /dev/null +++ b/backend/services/bug-management/src/test/resources/dml/init_bug.sql @@ -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'); \ No newline at end of file diff --git a/backend/services/bug-management/src/test/resources/file/test.xlsx b/backend/services/bug-management/src/test/resources/file/test.xlsx new file mode 100644 index 0000000000..732067f6ec Binary files /dev/null and b/backend/services/bug-management/src/test/resources/file/test.xlsx differ diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java index b3e0a824e2..5732a15dc6 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java @@ -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(); diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java index 8737455e9b..08cf373429 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java @@ -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 projectApplications = projectApplicationMapper.selectByExample(example); return CollectionUtils.isEmpty(projectApplications) ? null : projectApplications.get(0); } + +// /** +// * 获取项目所属平台 +// * @param projectId 项目ID +// * @return 项目所属平台 +// */ +// public String getPlatformName(String projectId) { +// // TODO 需调用项目平台配置接口, 获取项目所属平台名称 +// return null; +// } } diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectTemplateService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectTemplateService.java index ced2b3407d..3926e1bf7a 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectTemplateService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectTemplateService.java @@ -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()); diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/file/LocalFileRepository.java b/backend/services/system-setting/src/main/java/io/metersphere/system/file/LocalFileRepository.java index 8c76922628..79eeadaf40 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/file/LocalFileRepository.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/file/LocalFileRepository.java @@ -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()); } } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/mapper/BaseMapper.xml b/backend/services/system-setting/src/main/java/io/metersphere/system/mapper/BaseMapper.xml index b571dedb9d..6ac1e62448 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/mapper/BaseMapper.xml +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/mapper/BaseMapper.xml @@ -47,4 +47,10 @@ #{value} + + + + JSON_CONTAINS(value, #{value}) + + \ No newline at end of file diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/BaseTemplateService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/BaseTemplateService.java index 947747860f..195499fb72 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/BaseTemplateService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/BaseTemplateService.java @@ -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 templateCustomFields = baseTemplateCustomFieldService.getByTemplateId(template.getId()); // 查找字段名称