feat(project): 实现AI项目初始化及查询功能
- 新增ProjectService接口及实现,实现基于AI解析项目文档生成结构化项目数据 - 使用聊天机器人接口和OSS服务支持文件内容读取与AI解析 - 实现项目基本信息、里程碑、任务、成员、资源、风险及时间节点的持久化保存 - 支持任务层级关系和依赖关系的存储与管理 - 提供项目列表、项目详情、项目甘特图及项目统计接口 - 项目列表支持管理员与普通用户视角不同的数据访问权限 - 统计功能覆盖项目状态分布、本月新增、即将到期、平均进度及高风险项目数 - 项目编号自动生成,状态初始化为规划中 - 采用分页查询支持大数据量高效访问
This commit is contained in:
@@ -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