feat(project): 实现AI项目初始化及查询功能
- 新增ProjectService接口及实现,实现基于AI解析项目文档生成结构化项目数据 - 使用聊天机器人接口和OSS服务支持文件内容读取与AI解析 - 实现项目基本信息、里程碑、任务、成员、资源、风险及时间节点的持久化保存 - 支持任务层级关系和依赖关系的存储与管理 - 提供项目列表、项目详情、项目甘特图及项目统计接口 - 项目列表支持管理员与普通用户视角不同的数据访问权限 - 统计功能覆盖项目状态分布、本月新增、即将到期、平均进度及高风险项目数 - 项目编号自动生成,状态初始化为规划中 - 采用分页查询支持大数据量高效访问
This commit is contained in:
@@ -4,6 +4,7 @@ import cn.yinlihupo.common.core.BaseResponse;
|
||||
import cn.yinlihupo.common.page.TableDataInfo;
|
||||
import cn.yinlihupo.common.util.ResultUtils;
|
||||
import cn.yinlihupo.common.util.SecurityUtils;
|
||||
import cn.yinlihupo.domain.vo.ProjectDetailVO;
|
||||
import cn.yinlihupo.domain.vo.ProjectGanttVO;
|
||||
import cn.yinlihupo.domain.vo.ProjectListVO;
|
||||
import cn.yinlihupo.domain.vo.ProjectStatisticsVO;
|
||||
@@ -66,6 +67,30 @@ public class ProjectQueryController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目详情(全量信息)
|
||||
* 包括基本信息、参与人员、里程碑、任务、资源、风险、时间节点等
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
* @return 项目详情
|
||||
*/
|
||||
@GetMapping("/{projectId}")
|
||||
public BaseResponse<ProjectDetailVO> getProjectDetail(@PathVariable Long projectId) {
|
||||
log.info("获取项目详情, projectId: {}", projectId);
|
||||
|
||||
if (projectId == null || projectId <= 0) {
|
||||
return ResultUtils.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
ProjectDetailVO result = projectService.getProjectDetail(projectId);
|
||||
return ResultUtils.success("查询成功", result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取项目详情失败: {}", e.getMessage(), e);
|
||||
return ResultUtils.error("查询失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目甘特图数据
|
||||
*
|
||||
|
||||
645
src/main/java/cn/yinlihupo/domain/vo/ProjectDetailVO.java
Normal file
645
src/main/java/cn/yinlihupo/domain/vo/ProjectDetailVO.java
Normal file
@@ -0,0 +1,645 @@
|
||||
package cn.yinlihupo.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目详情VO
|
||||
* 包含项目全量信息:基本信息、参与人员、预算进度、物料资源等
|
||||
*/
|
||||
@Data
|
||||
public class ProjectDetailVO {
|
||||
|
||||
// ==================== 项目基本信息 ====================
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目编号
|
||||
*/
|
||||
private String projectCode;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 项目类型
|
||||
*/
|
||||
private String projectType;
|
||||
|
||||
/**
|
||||
* 项目描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 项目目标
|
||||
*/
|
||||
private String objectives;
|
||||
|
||||
/**
|
||||
* 项目经理ID
|
||||
*/
|
||||
private Long managerId;
|
||||
|
||||
/**
|
||||
* 项目经理名称
|
||||
*/
|
||||
private String managerName;
|
||||
|
||||
/**
|
||||
* 项目发起人ID
|
||||
*/
|
||||
private Long sponsorId;
|
||||
|
||||
/**
|
||||
* 计划开始日期
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 计划结束日期
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始日期
|
||||
*/
|
||||
private LocalDate actualStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束日期
|
||||
*/
|
||||
private LocalDate actualEndDate;
|
||||
|
||||
/**
|
||||
* 项目预算
|
||||
*/
|
||||
private BigDecimal budget;
|
||||
|
||||
/**
|
||||
* 已花费金额
|
||||
*/
|
||||
private BigDecimal cost;
|
||||
|
||||
/**
|
||||
* 币种
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 进度百分比
|
||||
*/
|
||||
private Integer progress;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private String priority;
|
||||
|
||||
/**
|
||||
* 风险等级
|
||||
*/
|
||||
private String riskLevel;
|
||||
|
||||
/**
|
||||
* 可见性
|
||||
*/
|
||||
private Integer visibility;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
// ==================== 统计汇总信息 ====================
|
||||
|
||||
/**
|
||||
* 成员数量
|
||||
*/
|
||||
private Integer memberCount;
|
||||
|
||||
/**
|
||||
* 任务总数
|
||||
*/
|
||||
private Integer taskCount;
|
||||
|
||||
/**
|
||||
* 已完成任务数
|
||||
*/
|
||||
private Integer completedTaskCount;
|
||||
|
||||
/**
|
||||
* 里程碑总数
|
||||
*/
|
||||
private Integer milestoneCount;
|
||||
|
||||
/**
|
||||
* 资源总数
|
||||
*/
|
||||
private Integer resourceCount;
|
||||
|
||||
/**
|
||||
* 风险总数
|
||||
*/
|
||||
private Integer riskCount;
|
||||
|
||||
/**
|
||||
* 高风险数量
|
||||
*/
|
||||
private Integer highRiskCount;
|
||||
|
||||
// ==================== 关联数据列表 ====================
|
||||
|
||||
/**
|
||||
* 项目成员列表
|
||||
*/
|
||||
private List<MemberInfo> members;
|
||||
|
||||
/**
|
||||
* 里程碑列表
|
||||
*/
|
||||
private List<MilestoneInfo> milestones;
|
||||
|
||||
/**
|
||||
* 任务列表
|
||||
*/
|
||||
private List<TaskInfo> tasks;
|
||||
|
||||
/**
|
||||
* 资源列表
|
||||
*/
|
||||
private List<ResourceInfo> resources;
|
||||
|
||||
/**
|
||||
* 风险列表
|
||||
*/
|
||||
private List<RiskInfo> risks;
|
||||
|
||||
/**
|
||||
* 时间节点列表
|
||||
*/
|
||||
private List<TimelineInfo> timelineNodes;
|
||||
|
||||
// ==================== 内部类定义 ====================
|
||||
|
||||
/**
|
||||
* 成员信息
|
||||
*/
|
||||
@Data
|
||||
public static class MemberInfo {
|
||||
/**
|
||||
* 成员记录ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 真实姓名
|
||||
*/
|
||||
private String realName;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 项目角色
|
||||
*/
|
||||
private String roleCode;
|
||||
|
||||
/**
|
||||
* 部门
|
||||
*/
|
||||
private String department;
|
||||
|
||||
/**
|
||||
* 职责描述
|
||||
*/
|
||||
private String responsibility;
|
||||
|
||||
/**
|
||||
* 每周投入小时数
|
||||
*/
|
||||
private BigDecimal weeklyHours;
|
||||
|
||||
/**
|
||||
* 加入日期
|
||||
*/
|
||||
private LocalDate joinDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 里程碑信息
|
||||
*/
|
||||
@Data
|
||||
public static class MilestoneInfo {
|
||||
/**
|
||||
* 里程碑ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 里程碑名称
|
||||
*/
|
||||
private String milestoneName;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 计划日期
|
||||
*/
|
||||
private LocalDate planDate;
|
||||
|
||||
/**
|
||||
* 实际日期
|
||||
*/
|
||||
private LocalDate actualDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 完成进度
|
||||
*/
|
||||
private Integer progress;
|
||||
|
||||
/**
|
||||
* 是否关键里程碑
|
||||
*/
|
||||
private Integer isKey;
|
||||
|
||||
/**
|
||||
* 交付物列表
|
||||
*/
|
||||
private List<String> deliverables;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务信息
|
||||
*/
|
||||
@Data
|
||||
public static class TaskInfo {
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
private String taskType;
|
||||
|
||||
/**
|
||||
* 所属里程碑ID
|
||||
*/
|
||||
private Long milestoneId;
|
||||
|
||||
/**
|
||||
* 执行人ID
|
||||
*/
|
||||
private Long assigneeId;
|
||||
|
||||
/**
|
||||
* 执行人姓名
|
||||
*/
|
||||
private String assigneeName;
|
||||
|
||||
/**
|
||||
* 计划开始日期
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 计划结束日期
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始日期
|
||||
*/
|
||||
private LocalDate actualStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束日期
|
||||
*/
|
||||
private LocalDate actualEndDate;
|
||||
|
||||
/**
|
||||
* 计划工时
|
||||
*/
|
||||
private BigDecimal planHours;
|
||||
|
||||
/**
|
||||
* 实际工时
|
||||
*/
|
||||
private BigDecimal actualHours;
|
||||
|
||||
/**
|
||||
* 进度百分比
|
||||
*/
|
||||
private Integer progress;
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private String priority;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源信息
|
||||
*/
|
||||
@Data
|
||||
public static class ResourceInfo {
|
||||
/**
|
||||
* 资源ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 资源编号
|
||||
*/
|
||||
private String resourceCode;
|
||||
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
private String resourceType;
|
||||
|
||||
/**
|
||||
* 资源名称
|
||||
*/
|
||||
private String resourceName;
|
||||
|
||||
/**
|
||||
* 资源描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
private String specification;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 计划数量
|
||||
*/
|
||||
private BigDecimal planQuantity;
|
||||
|
||||
/**
|
||||
* 实际数量
|
||||
*/
|
||||
private BigDecimal actualQuantity;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 币种
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 供应商
|
||||
*/
|
||||
private String supplier;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 计划到位日期
|
||||
*/
|
||||
private LocalDate planArriveDate;
|
||||
|
||||
/**
|
||||
* 实际到位日期
|
||||
*/
|
||||
private LocalDate actualArriveDate;
|
||||
|
||||
/**
|
||||
* 负责人ID
|
||||
*/
|
||||
private Long responsibleId;
|
||||
|
||||
/**
|
||||
* 存放位置
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private List<String> tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* 风险信息
|
||||
*/
|
||||
@Data
|
||||
public static class RiskInfo {
|
||||
/**
|
||||
* 风险ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 风险编号
|
||||
*/
|
||||
private String riskCode;
|
||||
|
||||
/**
|
||||
* 风险分类
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 风险名称
|
||||
*/
|
||||
private String riskName;
|
||||
|
||||
/**
|
||||
* 风险描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 发生概率
|
||||
*/
|
||||
private BigDecimal probability;
|
||||
|
||||
/**
|
||||
* 影响程度
|
||||
*/
|
||||
private BigDecimal impact;
|
||||
|
||||
/**
|
||||
* 风险得分
|
||||
*/
|
||||
private BigDecimal riskScore;
|
||||
|
||||
/**
|
||||
* 风险等级
|
||||
*/
|
||||
private String riskLevel;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 负责人ID
|
||||
*/
|
||||
private Long ownerId;
|
||||
|
||||
/**
|
||||
* 缓解措施
|
||||
*/
|
||||
private String mitigationPlan;
|
||||
|
||||
/**
|
||||
* 预期解决日期
|
||||
*/
|
||||
private LocalDate dueDate;
|
||||
|
||||
/**
|
||||
* 发现时间
|
||||
*/
|
||||
private LocalDateTime discoverTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间节点信息
|
||||
*/
|
||||
@Data
|
||||
public static class TimelineInfo {
|
||||
/**
|
||||
* 节点ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 节点类型
|
||||
*/
|
||||
private String nodeType;
|
||||
|
||||
/**
|
||||
* 计划日期
|
||||
*/
|
||||
private LocalDate planDate;
|
||||
|
||||
/**
|
||||
* 实际日期
|
||||
*/
|
||||
private LocalDate actualDate;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 知识库范围
|
||||
*/
|
||||
private List<String> kbScope;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.yinlihupo.service.project;
|
||||
|
||||
import cn.yinlihupo.common.page.TableDataInfo;
|
||||
import cn.yinlihupo.domain.vo.ProjectDetailVO;
|
||||
import cn.yinlihupo.domain.vo.ProjectGanttVO;
|
||||
import cn.yinlihupo.domain.vo.ProjectInitResult;
|
||||
import cn.yinlihupo.domain.vo.ProjectListVO;
|
||||
@@ -90,4 +91,12 @@ public interface ProjectService {
|
||||
*/
|
||||
TableDataInfo<ProjectListVO> getAllProjectList(Integer pageNum, Integer pageSize,
|
||||
String keyword, String status);
|
||||
|
||||
/**
|
||||
* 获取项目详情(全量信息)
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
* @return 项目详情
|
||||
*/
|
||||
ProjectDetailVO getProjectDetail(Long projectId);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public class ProjectServiceImpl implements ProjectService {
|
||||
private final ResourceMapper resourceMapper;
|
||||
private final RiskMapper riskMapper;
|
||||
private final ProjectTimelineMapper projectTimelineMapper;
|
||||
private final SysUserMapper sysUserMapper;
|
||||
|
||||
/**
|
||||
* 项目初始化系统提示词模板
|
||||
@@ -825,4 +826,289 @@ public class ProjectServiceImpl implements ProjectService {
|
||||
vo.setSortOrder(task.getSortOrder());
|
||||
return vo;
|
||||
}
|
||||
|
||||
// ==================== 项目详情相关实现 ====================
|
||||
|
||||
@Override
|
||||
public ProjectDetailVO getProjectDetail(Long projectId) {
|
||||
log.info("查询项目详情, projectId: {}", projectId);
|
||||
|
||||
// 1. 查询项目基本信息
|
||||
Project project = projectMapper.selectById(projectId);
|
||||
if (project == null || project.getDeleted() == 1) {
|
||||
throw new RuntimeException("项目不存在");
|
||||
}
|
||||
|
||||
ProjectDetailVO detailVO = new ProjectDetailVO();
|
||||
|
||||
// 2. 设置项目基本信息
|
||||
detailVO.setId(project.getId());
|
||||
detailVO.setProjectCode(project.getProjectCode());
|
||||
detailVO.setProjectName(project.getProjectName());
|
||||
detailVO.setProjectType(project.getProjectType());
|
||||
detailVO.setDescription(project.getDescription());
|
||||
detailVO.setObjectives(project.getObjectives());
|
||||
detailVO.setManagerId(project.getManagerId());
|
||||
detailVO.setSponsorId(project.getSponsorId());
|
||||
detailVO.setPlanStartDate(project.getPlanStartDate());
|
||||
detailVO.setPlanEndDate(project.getPlanEndDate());
|
||||
detailVO.setActualStartDate(project.getActualStartDate());
|
||||
detailVO.setActualEndDate(project.getActualEndDate());
|
||||
detailVO.setBudget(project.getBudget());
|
||||
detailVO.setCost(project.getCost());
|
||||
detailVO.setCurrency(project.getCurrency());
|
||||
detailVO.setProgress(project.getProgress());
|
||||
detailVO.setStatus(project.getStatus());
|
||||
detailVO.setPriority(project.getPriority());
|
||||
detailVO.setRiskLevel(project.getRiskLevel());
|
||||
detailVO.setVisibility(project.getVisibility());
|
||||
detailVO.setTags(project.getTags());
|
||||
detailVO.setCreateTime(project.getCreateTime());
|
||||
detailVO.setUpdateTime(project.getUpdateTime());
|
||||
|
||||
// 查询项目经理名称
|
||||
if (project.getManagerId() != null) {
|
||||
SysUser manager = sysUserMapper.selectById(project.getManagerId());
|
||||
if (manager != null) {
|
||||
detailVO.setManagerName(manager.getRealName());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 查询项目成员
|
||||
List<ProjectMember> members = projectMemberMapper.selectList(
|
||||
new LambdaQueryWrapper<ProjectMember>()
|
||||
.eq(ProjectMember::getProjectId, projectId)
|
||||
.eq(ProjectMember::getDeleted, 0)
|
||||
.orderByAsc(ProjectMember::getId)
|
||||
);
|
||||
|
||||
// 查询成员用户信息
|
||||
List<Long> userIds = members.stream()
|
||||
.map(ProjectMember::getUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, SysUser> userMap = new HashMap<>();
|
||||
if (!userIds.isEmpty()) {
|
||||
List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
|
||||
userMap = users.stream()
|
||||
.collect(Collectors.toMap(SysUser::getId, u -> u, (a, b) -> a));
|
||||
}
|
||||
|
||||
// 转换成员信息
|
||||
final Map<Long, SysUser> finalUserMap = userMap;
|
||||
List<ProjectDetailVO.MemberInfo> memberVOList = members.stream()
|
||||
.map(member -> {
|
||||
ProjectDetailVO.MemberInfo memberInfo = new ProjectDetailVO.MemberInfo();
|
||||
memberInfo.setId(member.getId());
|
||||
memberInfo.setUserId(member.getUserId());
|
||||
memberInfo.setRoleCode(member.getRoleCode());
|
||||
memberInfo.setResponsibility(member.getResponsibility());
|
||||
memberInfo.setWeeklyHours(member.getWeeklyHours());
|
||||
memberInfo.setJoinDate(member.getJoinDate());
|
||||
memberInfo.setStatus(member.getStatus());
|
||||
|
||||
// 填充用户信息
|
||||
if (member.getUserId() != null) {
|
||||
SysUser user = finalUserMap.get(member.getUserId());
|
||||
if (user != null) {
|
||||
memberInfo.setUserName(user.getUsername());
|
||||
memberInfo.setRealName(user.getRealName());
|
||||
memberInfo.setAvatar(user.getAvatar());
|
||||
}
|
||||
}
|
||||
return memberInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setMembers(memberVOList);
|
||||
detailVO.setMemberCount(memberVOList.size());
|
||||
|
||||
// 4. 查询里程碑
|
||||
List<ProjectMilestone> milestones = projectMilestoneMapper.selectList(
|
||||
new LambdaQueryWrapper<ProjectMilestone>()
|
||||
.eq(ProjectMilestone::getProjectId, projectId)
|
||||
.eq(ProjectMilestone::getDeleted, 0)
|
||||
.orderByAsc(ProjectMilestone::getSortOrder)
|
||||
);
|
||||
|
||||
List<ProjectDetailVO.MilestoneInfo> milestoneVOList = milestones.stream()
|
||||
.map(milestone -> {
|
||||
ProjectDetailVO.MilestoneInfo milestoneInfo = new ProjectDetailVO.MilestoneInfo();
|
||||
milestoneInfo.setId(milestone.getId());
|
||||
milestoneInfo.setMilestoneName(milestone.getMilestoneName());
|
||||
milestoneInfo.setDescription(milestone.getDescription());
|
||||
milestoneInfo.setPlanDate(milestone.getPlanDate());
|
||||
milestoneInfo.setActualDate(milestone.getActualDate());
|
||||
milestoneInfo.setStatus(milestone.getStatus());
|
||||
milestoneInfo.setProgress(milestone.getProgress());
|
||||
milestoneInfo.setIsKey(milestone.getIsKey());
|
||||
milestoneInfo.setDeliverables(milestone.getDeliverables());
|
||||
milestoneInfo.setSortOrder(milestone.getSortOrder());
|
||||
return milestoneInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setMilestones(milestoneVOList);
|
||||
detailVO.setMilestoneCount(milestoneVOList.size());
|
||||
|
||||
// 5. 查询任务
|
||||
List<Task> tasks = taskMapper.selectList(
|
||||
new LambdaQueryWrapper<Task>()
|
||||
.eq(Task::getProjectId, projectId)
|
||||
.eq(Task::getDeleted, 0)
|
||||
.orderByAsc(Task::getSortOrder)
|
||||
);
|
||||
|
||||
// 查询任务执行人信息
|
||||
List<Long> assigneeIds = tasks.stream()
|
||||
.map(Task::getAssigneeId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, SysUser> assigneeMap = new HashMap<>();
|
||||
if (!assigneeIds.isEmpty()) {
|
||||
List<SysUser> assignees = sysUserMapper.selectBatchIds(assigneeIds);
|
||||
assigneeMap = assignees.stream()
|
||||
.collect(Collectors.toMap(SysUser::getId, u -> u, (a, b) -> a));
|
||||
}
|
||||
|
||||
// 转换任务信息
|
||||
final Map<Long, SysUser> finalAssigneeMap = assigneeMap;
|
||||
List<ProjectDetailVO.TaskInfo> taskVOList = tasks.stream()
|
||||
.map(task -> {
|
||||
ProjectDetailVO.TaskInfo taskInfo = new ProjectDetailVO.TaskInfo();
|
||||
taskInfo.setId(task.getId());
|
||||
taskInfo.setTaskCode(task.getTaskCode());
|
||||
taskInfo.setTaskName(task.getTaskName());
|
||||
taskInfo.setDescription(task.getDescription());
|
||||
taskInfo.setTaskType(task.getTaskType());
|
||||
taskInfo.setMilestoneId(task.getMilestoneId());
|
||||
taskInfo.setAssigneeId(task.getAssigneeId());
|
||||
taskInfo.setPlanStartDate(task.getPlanStartDate());
|
||||
taskInfo.setPlanEndDate(task.getPlanEndDate());
|
||||
taskInfo.setActualStartDate(task.getActualStartDate());
|
||||
taskInfo.setActualEndDate(task.getActualEndDate());
|
||||
taskInfo.setPlanHours(task.getPlanHours());
|
||||
taskInfo.setActualHours(task.getActualHours());
|
||||
taskInfo.setProgress(task.getProgress());
|
||||
taskInfo.setPriority(task.getPriority());
|
||||
taskInfo.setStatus(task.getStatus());
|
||||
taskInfo.setSortOrder(task.getSortOrder());
|
||||
|
||||
// 填充执行人姓名
|
||||
if (task.getAssigneeId() != null) {
|
||||
SysUser assignee = finalAssigneeMap.get(task.getAssigneeId());
|
||||
if (assignee != null) {
|
||||
taskInfo.setAssigneeName(assignee.getRealName());
|
||||
}
|
||||
}
|
||||
return taskInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setTasks(taskVOList);
|
||||
detailVO.setTaskCount(taskVOList.size());
|
||||
|
||||
// 统计已完成任务数
|
||||
int completedCount = (int) tasks.stream()
|
||||
.filter(t -> "completed".equals(t.getStatus()))
|
||||
.count();
|
||||
detailVO.setCompletedTaskCount(completedCount);
|
||||
|
||||
// 6. 查询资源
|
||||
List<Resource> resources = resourceMapper.selectList(
|
||||
new LambdaQueryWrapper<Resource>()
|
||||
.eq(Resource::getProjectId, projectId)
|
||||
.eq(Resource::getDeleted, 0)
|
||||
.orderByAsc(Resource::getId)
|
||||
);
|
||||
|
||||
List<ProjectDetailVO.ResourceInfo> resourceVOList = resources.stream()
|
||||
.map(resource -> {
|
||||
ProjectDetailVO.ResourceInfo resourceInfo = new ProjectDetailVO.ResourceInfo();
|
||||
resourceInfo.setId(resource.getId());
|
||||
resourceInfo.setResourceCode(resource.getResourceCode());
|
||||
resourceInfo.setResourceType(resource.getResourceType());
|
||||
resourceInfo.setResourceName(resource.getResourceName());
|
||||
resourceInfo.setDescription(resource.getDescription());
|
||||
resourceInfo.setSpecification(resource.getSpecification());
|
||||
resourceInfo.setUnit(resource.getUnit());
|
||||
resourceInfo.setPlanQuantity(resource.getPlanQuantity());
|
||||
resourceInfo.setActualQuantity(resource.getActualQuantity());
|
||||
resourceInfo.setUnitPrice(resource.getUnitPrice());
|
||||
resourceInfo.setCurrency(resource.getCurrency());
|
||||
resourceInfo.setSupplier(resource.getSupplier());
|
||||
resourceInfo.setStatus(resource.getStatus());
|
||||
resourceInfo.setPlanArriveDate(resource.getPlanArriveDate());
|
||||
resourceInfo.setActualArriveDate(resource.getActualArriveDate());
|
||||
resourceInfo.setResponsibleId(resource.getResponsibleId());
|
||||
resourceInfo.setLocation(resource.getLocation());
|
||||
resourceInfo.setTags(resource.getTags());
|
||||
return resourceInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setResources(resourceVOList);
|
||||
detailVO.setResourceCount(resourceVOList.size());
|
||||
|
||||
// 7. 查询风险
|
||||
List<Risk> risks = riskMapper.selectList(
|
||||
new LambdaQueryWrapper<Risk>()
|
||||
.eq(Risk::getProjectId, projectId)
|
||||
.eq(Risk::getDeleted, 0)
|
||||
.orderByDesc(Risk::getRiskScore)
|
||||
);
|
||||
|
||||
List<ProjectDetailVO.RiskInfo> riskVOList = risks.stream()
|
||||
.map(risk -> {
|
||||
ProjectDetailVO.RiskInfo riskInfo = new ProjectDetailVO.RiskInfo();
|
||||
riskInfo.setId(risk.getId());
|
||||
riskInfo.setRiskCode(risk.getRiskCode());
|
||||
riskInfo.setCategory(risk.getCategory());
|
||||
riskInfo.setRiskName(risk.getRiskName());
|
||||
riskInfo.setDescription(risk.getDescription());
|
||||
riskInfo.setProbability(risk.getProbability());
|
||||
riskInfo.setImpact(risk.getImpact());
|
||||
riskInfo.setRiskScore(risk.getRiskScore());
|
||||
riskInfo.setRiskLevel(risk.getRiskLevel());
|
||||
riskInfo.setStatus(risk.getStatus());
|
||||
riskInfo.setOwnerId(risk.getOwnerId());
|
||||
riskInfo.setMitigationPlan(risk.getMitigationPlan());
|
||||
riskInfo.setDueDate(risk.getDueDate());
|
||||
riskInfo.setDiscoverTime(risk.getDiscoverTime());
|
||||
return riskInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setRisks(riskVOList);
|
||||
detailVO.setRiskCount(riskVOList.size());
|
||||
|
||||
// 统计高风险数量
|
||||
int highRiskCount = (int) risks.stream()
|
||||
.filter(r -> "high".equals(r.getRiskLevel()) || "critical".equals(r.getRiskLevel()))
|
||||
.count();
|
||||
detailVO.setHighRiskCount(highRiskCount);
|
||||
|
||||
// 8. 查询时间节点
|
||||
List<ProjectTimeline> timelines = projectTimelineMapper.selectList(
|
||||
new LambdaQueryWrapper<ProjectTimeline>()
|
||||
.eq(ProjectTimeline::getProjectId, projectId)
|
||||
.eq(ProjectTimeline::getDeleted, 0)
|
||||
.orderByAsc(ProjectTimeline::getSortOrder)
|
||||
);
|
||||
|
||||
List<ProjectDetailVO.TimelineInfo> timelineVOList = timelines.stream()
|
||||
.map(timeline -> {
|
||||
ProjectDetailVO.TimelineInfo timelineInfo = new ProjectDetailVO.TimelineInfo();
|
||||
timelineInfo.setId(timeline.getId());
|
||||
timelineInfo.setNodeName(timeline.getNodeName());
|
||||
timelineInfo.setNodeType(timeline.getNodeType());
|
||||
timelineInfo.setPlanDate(timeline.getPlanDate());
|
||||
timelineInfo.setActualDate(timeline.getActualDate());
|
||||
timelineInfo.setDescription(timeline.getDescription());
|
||||
timelineInfo.setStatus(timeline.getStatus());
|
||||
timelineInfo.setSortOrder(timeline.getSortOrder());
|
||||
timelineInfo.setKbScope(timeline.getKbScope());
|
||||
return timelineInfo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
detailVO.setTimelineNodes(timelineVOList);
|
||||
|
||||
return detailVO;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user