refactor(oa):重构个人报表接口返回结构

- 修改 personalReport 方法返回类型为 PersonalReportDTO
- 新增 PersonalReportDTO 类用于封装用户报表数据
- 调整 controller 层接口返回类型以匹配新的 DTO 结构
-优化 service 层数据组装逻辑,提升代码可读性- 在 VO 对象中补充用户信息、项目列表和进度统计字段
- 统一进度统计字段命名与结构,便于前端处理
This commit is contained in:
2025-10-24 18:07:01 +08:00
parent 4378d12e3e
commit 62629e6f9c
5 changed files with 117 additions and 58 deletions

View File

@@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit;
import com.ruoyi.common.core.AjaxResult; import com.ruoyi.common.core.AjaxResult;
import com.ruoyi.oa.domain.bo.BatchBo; import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.PersonalReportDTO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -128,10 +129,10 @@ public class OaProjectScheduleStepController extends BaseController {
* @return 报表数据 * @return 报表数据
*/ */
@GetMapping("/personal") @GetMapping("/personal")
public R<Map<String, Object>> getPersonalReport( public R<PersonalReportDTO> getPersonalReport(
@RequestParam Long poolId, @RequestParam Long poolId,
@RequestParam String nickName @RequestParam String nickName
) { ) {
return R.ok(iOaProjectScheduleStepService.personalReport(poolId,nickName)); return R.ok(iOaProjectScheduleStepService.personalReport(poolId, nickName));
} }
} }

View File

@@ -0,0 +1,38 @@
package com.ruoyi.oa.domain.dto;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.oa.domain.OaProjectScheduleStep;
import com.ruoyi.oa.domain.SysOaProject;
import lombok.Data;
import java.util.List;
/**
* 个人报表顶层返回结果类
*/
@Data
public class PersonalReportDTO {
/** 用户基本信息 */
private SysUser userInfo;
/** 用户负责的项目列表 */
private List<SysOaProject> responsibleProjects;
/** 进度统计信息 */
private ProgressStats progressStats;
private List<OaProjectScheduleStep> userSteps;
/**
* 进度统计内部类封装total、completed等字段
*/
@Data
public static class ProgressStats {
/** 总进度数 */
private Long total;
/** 已完成进度数 */
private Long completed;
/** 待验收进度数 */
private Long pendingAcceptance;
/** 延期进度数 */
private Long delayed;
}
}

View File

@@ -9,6 +9,8 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.convert.ExcelDictConvert;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.oa.domain.SysOaProject;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo; import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.SysOss;
import lombok.Data; import lombok.Data;
@@ -165,4 +167,21 @@ public class OaProjectScheduleStepVo extends BaseEntity {
//排序字段 //排序字段
private Integer sortNum; private Integer sortNum;
/** 新增:用户基本信息 */
private SysUser userInfo;
/** 新增:用户负责的项目列表 */
private List<SysOaProject> responsibleProjects;
/** 新增:进度统计信息 */
private ProgressStats progressStats;
/** 进度统计内部类封装total、completed等字段 */
@Data
public static class ProgressStats {
private Long total;
private Long completed;
private Long pendingAcceptance;
private Long delayed;
}
} }

View File

@@ -1,9 +1,11 @@
package com.ruoyi.oa.service; package com.ruoyi.oa.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.oa.domain.OaProjectScheduleStep; import com.ruoyi.oa.domain.OaProjectScheduleStep;
import com.ruoyi.oa.domain.bo.BatchBo; import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO; import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.dto.PersonalReportDTO;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo; import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo; import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
@@ -70,5 +72,5 @@ public interface IOaProjectScheduleStepService{
List<Map<String, Object>> queryProgressByHeader(); List<Map<String, Object>> queryProgressByHeader();
Map<String, Object> personalReport(Long poolId, String nickName); PersonalReportDTO personalReport(Long poolId, String nickName);
} }

View File

@@ -18,6 +18,7 @@ import com.ruoyi.oa.domain.OaProjectSchedule;
import com.ruoyi.oa.domain.SysOaProject; import com.ruoyi.oa.domain.SysOaProject;
import com.ruoyi.oa.domain.bo.BatchBo; import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO; import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.dto.PersonalReportDTO;
import com.ruoyi.oa.mapper.OaBonusProjectRelMapper; import com.ruoyi.oa.mapper.OaBonusProjectRelMapper;
import com.ruoyi.oa.mapper.OaProjectScheduleMapper; import com.ruoyi.oa.mapper.OaProjectScheduleMapper;
import com.ruoyi.oa.mapper.SysOaProjectMapper; import com.ruoyi.oa.mapper.SysOaProjectMapper;
@@ -340,83 +341,81 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
* @return 包含个人信息、负责项目、进度统计的结果 * @return 包含个人信息、负责项目、进度统计的结果
*/ */
@Override @Override
public Map<String, Object> personalReport(Long poolId,String nickName) { public PersonalReportDTO personalReport(Long poolId, String nickName) {
Map<String, Object> result = new HashMap<>(); // 1. 查询用户基本信息
//查询用户基本信息sys_user表
SysUser user = sysUserMapper.selectOne( SysUser user = sysUserMapper.selectOne(
Wrappers.<SysUser>lambdaQuery() Wrappers.<SysUser>lambdaQuery()
.eq(SysUser::getNickName, nickName) .eq(SysUser::getNickName, nickName)
.eq(SysUser::getDelFlag, "0") // 未删除 .eq(SysUser::getDelFlag, "0")
); );
if (user == null) { if (user == null) {
throw new RuntimeException("未找到用户:" + nickName); throw new RuntimeException("未找到用户:" + nickName);
} }
result.put("userInfo", user); // 个人基本信息(可按需筛选字段)
// 根据奖金池ID查询关联的项目IDoa_bonus_project_rel表 // 2. 查询奖金池关联的项目ID
List<OaBonusProjectRel> rels = bonusProjectRelMapper.selectList( List<OaBonusProjectRel> rels = bonusProjectRelMapper.selectList(
Wrappers.<OaBonusProjectRel>lambdaQuery() Wrappers.<OaBonusProjectRel>lambdaQuery()
.eq(OaBonusProjectRel::getPoolId, poolId) .eq(OaBonusProjectRel::getPoolId, poolId)
.eq(OaBonusProjectRel::getDelFlag, "0") .eq(OaBonusProjectRel::getDelFlag, "0")
); );
if (CollUtil.isEmpty(rels)) { List<Long> projectIds = CollUtil.isEmpty(rels)
result.put("responsibleProjects", Collections.emptyList()); ? Collections.emptyList()
result.put("progressStats", Collections.emptyMap()); : rels.stream().map(OaBonusProjectRel::getProjectId).collect(Collectors.toList());
return result;
}
List<Long> projectIds = rels.stream()
.map(OaBonusProjectRel::getProjectId)
.collect(Collectors.toList());
// 筛选用户负责的项目sys_oa_project表functionary = nickName // 3. 筛选用户负责的项目
List<SysOaProject> responsibleProjects = projectMapper.selectList( List<SysOaProject> responsibleProjects = projectMapper.selectList(
Wrappers.<SysOaProject>lambdaQuery() Wrappers.<SysOaProject>lambdaQuery()
.in(SysOaProject::getProjectId, projectIds) .in(SysOaProject::getProjectId, projectIds)
.eq(SysOaProject::getFunctionary, nickName) // 项目负责人匹配 .eq(SysOaProject::getFunctionary, nickName)
); );
result.put("responsibleProjects", responsibleProjects); // 负责的项目列表
// 查询用户负责的进度及统计(复用进度统计逻辑,限定关联项目 // 4. 查询用户负责的进度步骤(核心数据
// 先查询关联项目的进度主表IDoa_project_schedule List<OaProjectScheduleStep> userSteps = new ArrayList<>();
List<OaProjectSchedule> schedules = projectScheduleMapper.selectList( if (CollUtil.isNotEmpty(projectIds)) {
Wrappers.<OaProjectSchedule>lambdaQuery() // 查询关联项目的进度主表
.in(OaProjectSchedule::getProjectId, projectIds) List<OaProjectSchedule> schedules = projectScheduleMapper.selectList(
.eq(OaProjectSchedule::getDelFlag, "0") Wrappers.<OaProjectSchedule>lambdaQuery()
); .in(OaProjectSchedule::getProjectId, projectIds)
if (CollUtil.isEmpty(schedules)) { .eq(OaProjectSchedule::getDelFlag, "0")
result.put("progressStats", Collections.emptyMap()); );
return result; if (CollUtil.isNotEmpty(schedules)) {
List<Long> scheduleIds = schedules.stream()
.filter(Objects::nonNull)
.map(OaProjectSchedule::getScheduleId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 查询用户负责的进度步骤
userSteps = projectScheduleStepMapper.selectList(
Wrappers.<OaProjectScheduleStep>lambdaQuery()
.in(OaProjectScheduleStep::getScheduleId, scheduleIds)
.eq(OaProjectScheduleStep::getNodeHeader, nickName)
.eq(OaProjectScheduleStep::getDelFlag, "0")
.eq(OaProjectScheduleStep::getUseFlag, 1)
);
}
} }
List<Long> scheduleIds = schedules.stream()
.map(OaProjectSchedule::getScheduleId)
.collect(Collectors.toList());
//查询这些进度下的步骤,且负责人是当前用户 // 5. 统计进度数据
LambdaQueryWrapper<OaProjectScheduleStep> stepWrapper = Wrappers.lambdaQuery(); PersonalReportDTO.ProgressStats progressStats = new PersonalReportDTO.ProgressStats();
stepWrapper.in(OaProjectScheduleStep::getScheduleId, scheduleIds) progressStats.setTotal((long) userSteps.size());
.eq(OaProjectScheduleStep::getHeader, nickName) // 进度负责人匹配 progressStats.setCompleted(userSteps.stream()
.eq(OaProjectScheduleStep::getDelFlag, "0") .filter(step -> step.getStatus() != null && step.getStatus() == 2)
.eq(OaProjectScheduleStep::getUseFlag, 1); .count());
List<OaProjectScheduleStep> userSteps = projectScheduleStepMapper.selectList(stepWrapper); progressStats.setPendingAcceptance(userSteps.stream()
.filter(step -> step.getStatus() != null && step.getStatus() == 1)
// 统计进度数据(总数量、完成数、待验收数、延期数) .count());
long total = userSteps.size(); progressStats.setDelayed(userSteps.stream()
long completed = userSteps.stream()
.filter(step -> step.getStatus() != null && step.getStatus() == 2) // 已完成
.count();
long pendingAcceptance = userSteps.stream()
.filter(step -> step.getStatus() != null && step.getStatus() == 1) // 待验收
.count();
long delayed = userSteps.stream()
.filter(step -> step.getEndTime() != null && step.getOriginalEndTime() != null) .filter(step -> step.getEndTime() != null && step.getOriginalEndTime() != null)
.filter(step -> step.getEndTime().isAfter(step.getOriginalEndTime())) // 实际结束>原定结束 .filter(step -> step.getEndTime().isAfter(step.getOriginalEndTime()))
.count(); .count());
result.put("total", total); // 6. 封装返回DTO
result.put("completed", completed); PersonalReportDTO result = new PersonalReportDTO();
result.put("pendingAcceptance", pendingAcceptance); result.setUserInfo(user);
result.put("delayed", delayed); result.setResponsibleProjects(responsibleProjects);
result.setProgressStats(progressStats);
result.setUserSteps(userSteps);
return result; return result;
} }