feat(项目需求): 开发项目需求的富文本和附件功能。
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -37,13 +38,13 @@ public class ProductRequirementRespVO {
|
||||
@Schema(description = "需求分类名称", example = "功能需求")
|
||||
private String categoryName;
|
||||
|
||||
@Schema(description = "需求来源类型,manual 表示手工新增,work_order 表示工单流转", requiredMode = Schema.RequiredMode.REQUIRED, example = "manual")
|
||||
@Schema(description = "需求来源类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "manual")
|
||||
private String sourceType;
|
||||
|
||||
@Schema(description = "来源业务ID", example = "1024")
|
||||
private Long sourceBizId;
|
||||
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "优先级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer priority;
|
||||
|
||||
@Schema(description = "优先级名称", example = "中")
|
||||
@@ -88,10 +89,13 @@ public class ProductRequirementRespVO {
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
@Schema(description = "子需求列表,树形结构")
|
||||
private List<ProductRequirementRespVO> children;
|
||||
|
||||
@Schema(description = "是否为终态,已拒绝、已取消、已关闭都算终态", example = "false")
|
||||
@Schema(description = "是否为终态", example = "false")
|
||||
private Boolean terminal;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 产品需求保存 Request VO
|
||||
*/
|
||||
@@ -29,7 +33,7 @@ public class ProductRequirementSaveReqVO {
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -37,7 +41,7 @@ public class ProductRequirementSaveReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@@ -67,4 +71,8 @@ public class ProductRequirementSaveReqVO {
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 产品需求拆分 Request VO
|
||||
*/
|
||||
@@ -30,7 +34,7 @@ public class ProductRequirementSplitReqVO {
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -38,7 +42,7 @@ public class ProductRequirementSplitReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@@ -68,4 +72,8 @@ public class ProductRequirementSplitReqVO {
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 产品需求编辑 Request VO
|
||||
*/
|
||||
@@ -30,7 +34,7 @@ public class ProductRequirementUpdateReqVO {
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -38,7 +42,7 @@ public class ProductRequirementUpdateReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@@ -68,4 +72,8 @@ public class ProductRequirementUpdateReqVO {
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -13,19 +14,19 @@ import java.util.List;
|
||||
@Data
|
||||
public class ProjectRequirementRespVO {
|
||||
|
||||
@Schema(description = "需求 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "需求ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "父需求 ID,0 表示顶级需求", example = "0")
|
||||
@Schema(description = "父需求ID,0 表示顶级需求", example = "0")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "所属项目 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "所属项目ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "所属模块 ID", example = "1024")
|
||||
@Schema(description = "所属模块ID", example = "1024")
|
||||
private Long moduleId;
|
||||
|
||||
@Schema(description = "是否需要评审,0 不需要,1 需要", example = "0")
|
||||
@Schema(description = "是否需要评审,0不需要,1需要", example = "0")
|
||||
private Integer reviewRequired;
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@@ -43,7 +44,7 @@ public class ProjectRequirementRespVO {
|
||||
@Schema(description = "需求来源类型", example = "manual")
|
||||
private String sourceType;
|
||||
|
||||
@Schema(description = "来源业务 ID", example = "1024")
|
||||
@Schema(description = "来源业务ID", example = "1024")
|
||||
private Long sourceBizId;
|
||||
|
||||
@Schema(description = "优先级", example = "1")
|
||||
@@ -61,19 +62,19 @@ public class ProjectRequirementRespVO {
|
||||
@Schema(description = "最近一次状态动作原因", example = "评审通过")
|
||||
private String lastStatusReason;
|
||||
|
||||
@Schema(description = "提出人用户 ID", example = "1024")
|
||||
@Schema(description = "提出人用户ID", example = "1024")
|
||||
private Long proposerId;
|
||||
|
||||
@Schema(description = "提出人昵称", example = "张三")
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
private Double workHours;
|
||||
|
||||
@Schema(description = "当前处理人用户 ID", example = "1024")
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@Schema(description = "当前处理人昵称", example = "李四")
|
||||
@Schema(description = "当前处理人姓名", example = "李四")
|
||||
private String currentHandlerUserNickname;
|
||||
|
||||
@Schema(description = "排序值", example = "0")
|
||||
@@ -85,6 +86,9 @@ public class ProjectRequirementRespVO {
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
@Schema(description = "子需求列表,树形结构")
|
||||
private List<ProjectRequirementRespVO> children;
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 项目需求保存 Request VO
|
||||
*/
|
||||
@@ -13,23 +17,23 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ProjectRequirementSaveReqVO {
|
||||
|
||||
@Schema(description = "需求 ID", example = "1024")
|
||||
@Schema(description = "需求ID", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "所属项目 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目 ID 不能为空")
|
||||
@Schema(description = "所属项目ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "所属模块 ID,为空时归入全部需求模块", example = "1024")
|
||||
@Schema(description = "所属模块ID,为空时归入全部需求模块", example = "1024")
|
||||
private Long moduleId;
|
||||
|
||||
@Schema(description = "是否需要评审,0 不需要,1 需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@Schema(description = "是否需要评审,0不需要,1需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@NotNull(message = "是否需要评审不能为空")
|
||||
private Integer reviewRequired;
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -37,31 +41,35 @@ public class ProjectRequirementSaveReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级,0 低、1 中、2 高、3 紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "优先级不能为空")
|
||||
private Integer priority;
|
||||
|
||||
@Schema(description = "提出人用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "提出人用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "提出人不能为空")
|
||||
private Long proposerId;
|
||||
|
||||
@Schema(description = "提出人昵称", example = "张三")
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
|
||||
@Schema(description = "当前处理人用户 ID", example = "1024")
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@Schema(description = "当前处理人昵称", example = "李四")
|
||||
@Schema(description = "当前处理人姓名", example = "李四")
|
||||
private String currentHandlerUserNickname;
|
||||
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 项目需求拆分 Request VO
|
||||
*/
|
||||
@@ -13,24 +17,24 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ProjectRequirementSplitReqVO {
|
||||
|
||||
@Schema(description = "父需求 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "父需求 ID 不能为空")
|
||||
@Schema(description = "父需求ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "父需求ID不能为空")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "所属项目 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目 ID 不能为空")
|
||||
@Schema(description = "所属项目ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "所属模块 ID,为空时继承父需求模块", example = "1024")
|
||||
@Schema(description = "所属模块ID,为空时继承父需求模块", example = "1024")
|
||||
private Long moduleId;
|
||||
|
||||
@Schema(description = "是否需要评审,0 不需要,1 需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@Schema(description = "是否需要评审,0不需要,1需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@NotNull(message = "是否需要评审不能为空")
|
||||
private Integer reviewRequired;
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -38,31 +42,35 @@ public class ProjectRequirementSplitReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "优先级不能为空")
|
||||
private Integer priority;
|
||||
|
||||
@Schema(description = "提出人用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "提出人用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "提出人不能为空")
|
||||
private Long proposerId;
|
||||
|
||||
@Schema(description = "提出人昵称", example = "张三")
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
|
||||
@Schema(description = "当前处理人用户 ID", example = "1024")
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@Schema(description = "当前处理人昵称", example = "李四")
|
||||
@Schema(description = "当前处理人姓名", example = "李四")
|
||||
private String currentHandlerUserNickname;
|
||||
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台 - 项目需求编辑 Request VO
|
||||
*/
|
||||
@@ -13,24 +17,24 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ProjectRequirementUpdateReqVO {
|
||||
|
||||
@Schema(description = "需求 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "需求 ID 不能为空")
|
||||
@Schema(description = "需求ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "需求ID不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "所属项目 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目 ID 不能为空")
|
||||
@Schema(description = "所属项目ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "所属模块 ID,为空时归入全部需求模块", example = "1024")
|
||||
@Schema(description = "所属模块ID,为空时归入全部需求模块", example = "1024")
|
||||
private Long moduleId;
|
||||
|
||||
@Schema(description = "是否需要评审,0 不需要,1 需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@Schema(description = "是否需要评审,0不需要,1需要", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@NotNull(message = "是否需要评审不能为空")
|
||||
private Integer reviewRequired;
|
||||
|
||||
@Schema(description = "需求标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "支持需求模块化管理")
|
||||
@NotBlank(message = "需求标题不能为空")
|
||||
@Size(max = 200, message = "需求标题长度不能超过 200 个字符")
|
||||
@Size(max = 200, message = "需求标题长度不能超过200个字符")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "需求描述,支持富文本", example = "<p>详细描述需求内容</p>")
|
||||
@@ -38,31 +42,35 @@ public class ProjectRequirementUpdateReqVO {
|
||||
|
||||
@Schema(description = "需求分类字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "function")
|
||||
@NotBlank(message = "需求分类不能为空")
|
||||
@Size(max = 64, message = "需求分类长度不能超过 64 个字符")
|
||||
@Size(max = 64, message = "需求分类长度不能超过64个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "优先级,0 低、1 中、2 高、3 紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "优先级,0低、1中、2高、3紧急", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "优先级不能为空")
|
||||
private Integer priority;
|
||||
|
||||
@Schema(description = "提出人用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Schema(description = "提出人用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "提出人不能为空")
|
||||
private Long proposerId;
|
||||
|
||||
@Schema(description = "提出人昵称", example = "张三")
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
|
||||
@Schema(description = "当前处理人用户 ID", example = "1024")
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@Schema(description = "当前处理人昵称", example = "李四")
|
||||
@Schema(description = "当前处理人姓名", example = "李四")
|
||||
private String currentHandlerUserNickname;
|
||||
|
||||
@Schema(description = "排序值,越小越靠前", example = "0")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "附件列表")
|
||||
@Valid
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.product;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 产品需求主表
|
||||
*/
|
||||
@TableName("rdms_product_requirement")
|
||||
@TableName(value = "rdms_product_requirement", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ProductRequirementDO extends BaseDO {
|
||||
@@ -95,5 +100,10 @@ public class ProductRequirementDO extends BaseDO {
|
||||
* 排序值,越小越靠前
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 闄勪欢鍒楄〃锛圝SON锛夈€傚厓绱?{@link AttachmentItem}锛歩d / url / name / size / contentType銆?
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.project;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目需求主表
|
||||
*/
|
||||
@TableName("rdms_project_requirement")
|
||||
@TableName(value = "rdms_project_requirement", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ProjectRequirementDO extends BaseDO {
|
||||
@@ -95,5 +100,10 @@ public class ProjectRequirementDO extends BaseDO {
|
||||
* 排序值
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 闄勪欢鍒楄〃锛圝SON锛夈€傚厓绱?{@link AttachmentItem}锛歩d / url / name / size / contentType銆?
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.njcn.rdms.module.project.dal.mysql.project.ProjectRequirementModuleMa
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusModelMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusTransitionMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.project.framework.attachment.AttachmentFileIdResolver;
|
||||
import com.njcn.rdms.module.project.framework.attachment.AttachmentValidator;
|
||||
import com.njcn.rdms.module.project.framework.security.annotation.CheckObjectPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -108,6 +110,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
private ProjectRequirementModuleMapper projectRequirementModuleMapper;
|
||||
@Resource
|
||||
private UserObjectRoleMapper userObjectRoleMapper;
|
||||
@Resource
|
||||
private AttachmentFileIdResolver attachmentFileIdResolver;
|
||||
|
||||
// ========== 需求增删改查 ==========
|
||||
|
||||
@@ -120,6 +124,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
Long moduleId = resolveModuleId(createReqVO.getModuleId(), createReqVO.getProductId());
|
||||
// 校验模块是否属于当前产品
|
||||
validateModuleBelongsToProduct(moduleId, createReqVO.getProductId());
|
||||
AttachmentValidator.validate(createReqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(createReqVO.getAttachments());
|
||||
|
||||
ProductRequirementDO requirement = new ProductRequirementDO();
|
||||
requirement.setProductId(createReqVO.getProductId());
|
||||
@@ -142,6 +148,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(createReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setImplementProjectId(createReqVO.getImplementProjectId());
|
||||
requirement.setSort(createReqVO.getSort() != null ? createReqVO.getSort() : 0);
|
||||
requirement.setAttachments(createReqVO.getAttachments());
|
||||
requirementMapper.insert(requirement);
|
||||
|
||||
// 写入业务审计日志
|
||||
@@ -162,6 +169,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
Long moduleId = resolveModuleId(updateReqVO.getModuleId(), updateReqVO.getProductId());
|
||||
// 校验模块是否属于当前产品
|
||||
validateModuleBelongsToProduct(moduleId, updateReqVO.getProductId());
|
||||
AttachmentValidator.validate(updateReqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(updateReqVO.getAttachments());
|
||||
|
||||
ProductRequirementDO before = cloneRequirement(requirement);
|
||||
String fromStatus = requirement.getStatusCode();
|
||||
@@ -178,6 +187,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(updateReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setImplementProjectId(updateReqVO.getImplementProjectId());
|
||||
requirement.setSort(updateReqVO.getSort() != null ? updateReqVO.getSort() : 0);
|
||||
requirement.setAttachments(updateReqVO.getAttachments());
|
||||
requirementMapper.updateById(requirement);
|
||||
|
||||
writeBizAuditLog(requirement, ACTION_UPDATE, fromStatus, requirement.getStatusCode(),
|
||||
@@ -582,6 +592,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
validateRequirementNotDispatched(parentRequirement);
|
||||
// 校验父需求状态是否允许拆分(只能是待分流或实施中)
|
||||
validateParentAllowSplit(parentRequirement);
|
||||
AttachmentValidator.validate(reqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(reqVO.getAttachments());
|
||||
|
||||
// 创建子需求
|
||||
ProductRequirementDO childRequirement = new ProductRequirementDO();
|
||||
@@ -606,6 +618,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
childRequirement.setCurrentHandlerUserNickname(normalizeNullableText(reqVO.getCurrentHandlerUserNickname()));
|
||||
childRequirement.setImplementProjectId(reqVO.getImplementProjectId());
|
||||
childRequirement.setSort(reqVO.getSort() != null ? reqVO.getSort() : 0);
|
||||
childRequirement.setAttachments(reqVO.getAttachments());
|
||||
requirementMapper.insert(childRequirement);
|
||||
|
||||
// 父需求状态从待分流变为实施中
|
||||
@@ -1257,6 +1270,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setImplementProjectId(source.getImplementProjectId());
|
||||
target.setSort(source.getSort());
|
||||
target.setAttachments(source.getAttachments());
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -1304,6 +1318,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
valueOf(after, ProductRequirementDO::getImplementProjectId));
|
||||
appendFieldChange(fieldChanges, "sort", valueOf(before, ProductRequirementDO::getSort),
|
||||
valueOf(after, ProductRequirementDO::getSort));
|
||||
appendFieldChange(fieldChanges, "attachments", valueOf(before, ProductRequirementDO::getAttachments),
|
||||
valueOf(after, ProductRequirementDO::getAttachments));
|
||||
return fieldChanges.isEmpty() ? null : JsonUtils.toJsonString(fieldChanges);
|
||||
}
|
||||
|
||||
@@ -1384,6 +1400,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
newRequirement.setCurrentHandlerUserId(productRequirement.getCurrentHandlerUserId());
|
||||
newRequirement.setCurrentHandlerUserNickname(productRequirement.getCurrentHandlerUserNickname());
|
||||
newRequirement.setWorkHours(productRequirement.getWorkHours());
|
||||
newRequirement.setAttachments(productRequirement.getAttachments());
|
||||
newRequirement.setCreator(productRequirement.getCreator());
|
||||
newRequirement.setCreateTime(productRequirement.getCreateTime());
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ import com.njcn.rdms.module.project.dal.mysql.project.ProjectRequirementStatusLo
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusModelMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusTransitionMapper;
|
||||
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.project.framework.attachment.AttachmentFileIdResolver;
|
||||
import com.njcn.rdms.module.project.framework.attachment.AttachmentValidator;
|
||||
import com.njcn.rdms.module.project.framework.security.annotation.CheckObjectPermission;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -122,6 +124,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
private ObjectStatusTransitionMapper statusTransitionMapper;
|
||||
@Resource
|
||||
private ObjectStatusModelMapper statusModelMapper;
|
||||
@Resource
|
||||
private AttachmentFileIdResolver attachmentFileIdResolver;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -130,6 +134,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
public Long createRequirement(ProjectRequirementSaveReqVO createReqVO) {
|
||||
Long moduleId = resolveModuleId(createReqVO.getModuleId(), createReqVO.getProjectId());
|
||||
validateModuleBelongsToProject(moduleId, createReqVO.getProjectId());
|
||||
AttachmentValidator.validate(createReqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(createReqVO.getAttachments());
|
||||
|
||||
ProjectRequirementDO requirement = new ProjectRequirementDO();
|
||||
requirement.setProjectId(createReqVO.getProjectId());
|
||||
@@ -150,6 +156,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
requirement.setCurrentHandlerUserId(createReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(createReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setSort(createReqVO.getSort() != null ? createReqVO.getSort() : 0);
|
||||
requirement.setAttachments(createReqVO.getAttachments());
|
||||
requirementMapper.insert(requirement);
|
||||
|
||||
writeBizAuditLog(requirement, ACTION_CREATE, null, initialStatus,
|
||||
@@ -168,6 +175,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
|
||||
Long moduleId = resolveModuleId(updateReqVO.getModuleId(), updateReqVO.getProjectId());
|
||||
validateModuleBelongsToProject(moduleId, updateReqVO.getProjectId());
|
||||
AttachmentValidator.validate(updateReqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(updateReqVO.getAttachments());
|
||||
|
||||
ProjectRequirementDO before = cloneRequirement(requirement);
|
||||
String fromStatus = requirement.getStatusCode();
|
||||
@@ -183,6 +192,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
requirement.setCurrentHandlerUserId(updateReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(updateReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setSort(updateReqVO.getSort() != null ? updateReqVO.getSort() : 0);
|
||||
requirement.setAttachments(updateReqVO.getAttachments());
|
||||
requirementMapper.updateById(requirement);
|
||||
|
||||
writeBizAuditLog(requirement, ACTION_UPDATE, fromStatus, requirement.getStatusCode(),
|
||||
@@ -346,6 +356,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
ProjectRequirementDO parentRequirement = validateRequirementExists(reqVO.getParentId());
|
||||
validateRequirementBelongsToProject(parentRequirement, reqVO.getProjectId());
|
||||
validateParentAllowSplit(parentRequirement);
|
||||
AttachmentValidator.validate(reqVO.getAttachments());
|
||||
attachmentFileIdResolver.resolve(reqVO.getAttachments());
|
||||
|
||||
Long moduleId = reqVO.getModuleId() != null ? reqVO.getModuleId() : parentRequirement.getModuleId();
|
||||
validateModuleBelongsToProject(moduleId, reqVO.getProjectId());
|
||||
@@ -371,6 +383,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
childRequirement.setCurrentHandlerUserId(reqVO.getCurrentHandlerUserId());
|
||||
childRequirement.setCurrentHandlerUserNickname(normalizeNullableText(reqVO.getCurrentHandlerUserNickname()));
|
||||
childRequirement.setSort(reqVO.getSort() != null ? reqVO.getSort() : 0);
|
||||
childRequirement.setAttachments(reqVO.getAttachments());
|
||||
requirementMapper.insert(childRequirement);
|
||||
|
||||
writeBizAuditLog(childRequirement, ACTION_CREATE, null, initialStatus,
|
||||
@@ -1110,6 +1123,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
target.setCurrentHandlerUserId(source.getCurrentHandlerUserId());
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setSort(source.getSort());
|
||||
target.setAttachments(source.getAttachments());
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -1158,6 +1172,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
valueOf(after, ProjectRequirementDO::getCurrentHandlerUserNickname));
|
||||
appendFieldChange(fieldChanges, "sort", valueOf(before, ProjectRequirementDO::getSort),
|
||||
valueOf(after, ProjectRequirementDO::getSort));
|
||||
appendFieldChange(fieldChanges, "attachments", valueOf(before, ProjectRequirementDO::getAttachments),
|
||||
valueOf(after, ProjectRequirementDO::getAttachments));
|
||||
return fieldChanges.isEmpty() ? null : JsonUtils.toJsonString(fieldChanges);
|
||||
}
|
||||
|
||||
@@ -1218,6 +1234,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setImplementProjectId(source.getImplementProjectId());
|
||||
target.setSort(source.getSort());
|
||||
target.setAttachments(source.getAttachments());
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -1262,6 +1279,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
valueOf(after, ProductRequirementDO::getImplementProjectId));
|
||||
appendFieldChange(fieldChanges, "sort", valueOf(before, ProductRequirementDO::getSort),
|
||||
valueOf(after, ProductRequirementDO::getSort));
|
||||
appendFieldChange(fieldChanges, "attachments", valueOf(before, ProductRequirementDO::getAttachments),
|
||||
valueOf(after, ProductRequirementDO::getAttachments));
|
||||
return fieldChanges.isEmpty() ? null : JsonUtils.toJsonString(fieldChanges);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user