From 9d1294d1974309aef0d893a404f70251d126a89c Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Wed, 1 Apr 2026 15:04:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(analysis):=20=E6=96=B0=E5=A2=9E=E6=97=A5?= =?UTF-8?q?=E6=8A=A5=E5=8F=8A=E5=88=86=E6=9E=90=E7=BB=93=E6=9E=9C=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E6=8E=A5=E5=8F=A3=E4=B8=8E=E6=95=B0=E6=8D=AE=E8=81=9A?= =?UTF-8?q?=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加DailyReportAnalysisController,包含获取建议及分页查询接口 - 创建DailyReportSuggestionService接口及实现类分页方法 - 实现分页查询项目日报及其对应分析记录和建议功能 - 将日报与最新分析记录及建议数据整合为DailyReportWithAnalysisVO返回 - 增加接口调用的权限校验和错误处理 - 新增ApplyDailyReportSuggestionsRequest请求体及对应逻辑处理 - 补充分页参数默认值及状态筛选逻辑 - 优化查询条件,按日期及创建时间倒序排序 --- .../DailyReportAnalysisController.java | 25 ++++ .../domain/vo/DailyReportWithAnalysisVO.java | 42 ++++++ .../DailyReportSuggestionService.java | 4 + .../DailyReportSuggestionServiceImpl.java | 120 ++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 src/main/java/cn/yinlihupo/domain/vo/DailyReportWithAnalysisVO.java diff --git a/src/main/java/cn/yinlihupo/controller/analysis/DailyReportAnalysisController.java b/src/main/java/cn/yinlihupo/controller/analysis/DailyReportAnalysisController.java index 77cca37..00da8f6 100644 --- a/src/main/java/cn/yinlihupo/controller/analysis/DailyReportAnalysisController.java +++ b/src/main/java/cn/yinlihupo/controller/analysis/DailyReportAnalysisController.java @@ -3,12 +3,14 @@ package cn.yinlihupo.controller.analysis; import cn.yinlihupo.common.core.BaseResponse; import cn.yinlihupo.common.enums.ErrorCode; import cn.yinlihupo.common.exception.BusinessException; +import cn.yinlihupo.common.page.TableDataInfo; import cn.yinlihupo.common.util.ResultUtils; import cn.yinlihupo.common.util.SecurityUtils; import cn.yinlihupo.domain.dto.ApplyDailyReportSuggestionsRequest; import cn.yinlihupo.domain.entity.DailyReportUpdateSuggestion; import cn.yinlihupo.domain.vo.DailyReportAnalysisSuggestionsVO; import cn.yinlihupo.domain.vo.DailyReportUpdateSuggestionVO; +import cn.yinlihupo.domain.vo.DailyReportWithAnalysisVO; import cn.yinlihupo.mapper.DailyReportUpdateSuggestionMapper; import cn.yinlihupo.service.analysis.DailyReportSuggestionService; import jakarta.validation.Valid; @@ -57,6 +59,29 @@ public class DailyReportAnalysisController { return ResultUtils.success("查询成功", vo); } + /** + * 分页获取项目日报及分析结果 + */ + @GetMapping("/reports") + public BaseResponse> pageDailyReportsWithAnalysis( + @RequestParam Long projectId, + @RequestParam(required = false) LocalDate reportDate, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) String suggestionStatus) { + Long userId = SecurityUtils.getCurrentUserId(); + if (userId == null) { + return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录"); + } + try { + TableDataInfo result = dailyReportSuggestionService.pageDailyReportsWithAnalysis(projectId, reportDate, pageNum, pageSize, suggestionStatus); + return ResultUtils.success("查询成功", result); + } catch (Exception e) { + log.error("查询日报及分析结果失败: {}", e.getMessage(), e); + return ResultUtils.error("查询失败: " + e.getMessage()); + } + } + /** * 应用日报进度回写建议 * diff --git a/src/main/java/cn/yinlihupo/domain/vo/DailyReportWithAnalysisVO.java b/src/main/java/cn/yinlihupo/domain/vo/DailyReportWithAnalysisVO.java new file mode 100644 index 0000000..a19a9cd --- /dev/null +++ b/src/main/java/cn/yinlihupo/domain/vo/DailyReportWithAnalysisVO.java @@ -0,0 +1,42 @@ +package cn.yinlihupo.domain.vo; + +import cn.yinlihupo.domain.dto.DailyReportAnalysisResult; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class DailyReportWithAnalysisVO { + + private Long reportId; + + private Long projectId; + + private LocalDate reportDate; + + private String submitterUsername; + + private Long submitterId; + + private String workContent; + + private String tomorrowPlan; + + private Integer workIntensity; + + private Boolean needHelp; + + private String helpContent; + + private LocalDateTime createTime; + + private Long analysisId; + + private String analysisStatus; + + private DailyReportAnalysisResult analysisResult; + + private List analysisSuggestions; +} diff --git a/src/main/java/cn/yinlihupo/service/analysis/DailyReportSuggestionService.java b/src/main/java/cn/yinlihupo/service/analysis/DailyReportSuggestionService.java index 202155f..24e6b41 100644 --- a/src/main/java/cn/yinlihupo/service/analysis/DailyReportSuggestionService.java +++ b/src/main/java/cn/yinlihupo/service/analysis/DailyReportSuggestionService.java @@ -2,6 +2,8 @@ package cn.yinlihupo.service.analysis; import cn.yinlihupo.domain.vo.DailyReportAnalysisSuggestionsVO; import cn.yinlihupo.domain.vo.DailyReportUpdateSuggestionVO; +import cn.yinlihupo.domain.vo.DailyReportWithAnalysisVO; +import cn.yinlihupo.common.page.TableDataInfo; import java.time.LocalDate; import java.util.List; @@ -14,5 +16,7 @@ public interface DailyReportSuggestionService { List listSuggestionsByProjectId(Long projectId, LocalDate reportDate, String status); + TableDataInfo pageDailyReportsWithAnalysis(Long projectId, LocalDate reportDate, Integer pageNum, Integer pageSize, String suggestionStatus); + int applySuggestions(Long projectId, List suggestionIds, Long appliedBy); } diff --git a/src/main/java/cn/yinlihupo/service/analysis/impl/DailyReportSuggestionServiceImpl.java b/src/main/java/cn/yinlihupo/service/analysis/impl/DailyReportSuggestionServiceImpl.java index 69e238a..e2ba31c 100644 --- a/src/main/java/cn/yinlihupo/service/analysis/impl/DailyReportSuggestionServiceImpl.java +++ b/src/main/java/cn/yinlihupo/service/analysis/impl/DailyReportSuggestionServiceImpl.java @@ -2,6 +2,7 @@ package cn.yinlihupo.service.analysis.impl; import cn.yinlihupo.common.enums.ErrorCode; import cn.yinlihupo.common.exception.BusinessException; +import cn.yinlihupo.common.page.TableDataInfo; import cn.yinlihupo.domain.dto.DailyReportAnalysisResult; import cn.yinlihupo.domain.entity.DailyReportAnalysisRecord; import cn.yinlihupo.domain.entity.DailyReportUpdateSuggestion; @@ -10,12 +11,14 @@ import cn.yinlihupo.domain.entity.ProjectMilestone; import cn.yinlihupo.domain.entity.Task; import cn.yinlihupo.domain.vo.DailyReportAnalysisSuggestionsVO; import cn.yinlihupo.domain.vo.DailyReportUpdateSuggestionVO; +import cn.yinlihupo.domain.vo.DailyReportWithAnalysisVO; import cn.yinlihupo.mapper.DailyReportAnalysisRecordMapper; import cn.yinlihupo.mapper.DailyReportUpdateSuggestionMapper; import cn.yinlihupo.mapper.ProjectDailyReportMapper; import cn.yinlihupo.mapper.ProjectMilestoneMapper; import cn.yinlihupo.mapper.TaskMapper; import cn.yinlihupo.service.analysis.DailyReportSuggestionService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -129,6 +132,123 @@ public class DailyReportSuggestionServiceImpl implements DailyReportSuggestionSe return buildSuggestionVOList(projectId, suggestions); } + @Override + public TableDataInfo pageDailyReportsWithAnalysis(Long projectId, LocalDate reportDate, Integer pageNum, Integer pageSize, String suggestionStatus) { + if (projectId == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "projectId不能为空"); + } + int actualPageNum = pageNum == null || pageNum < 1 ? 1 : pageNum; + int actualPageSize = pageSize == null || pageSize < 1 ? 10 : pageSize; + String actualSuggestionStatus; + if (!StringUtils.hasText(suggestionStatus)) { + actualSuggestionStatus = "pending"; + } else if ("all".equalsIgnoreCase(suggestionStatus)) { + actualSuggestionStatus = null; + } else { + actualSuggestionStatus = suggestionStatus; + } + + Page page = new Page<>(actualPageNum, actualPageSize); + LambdaQueryWrapper reportWrapper = new LambdaQueryWrapper() + .eq(ProjectDailyReport::getProjectId, projectId) + .eq(ProjectDailyReport::getDeleted, 0) + .eq(reportDate != null, ProjectDailyReport::getReportDate, reportDate) + .orderByDesc(ProjectDailyReport::getReportDate) + .orderByDesc(ProjectDailyReport::getCreateTime); + + Page reportPage = projectDailyReportMapper.selectPage(page, reportWrapper); + List reports = reportPage.getRecords(); + if (reports == null || reports.isEmpty()) { + return TableDataInfo.build(new Page(reportPage.getCurrent(), reportPage.getSize(), reportPage.getTotal()) + .setRecords(new ArrayList<>())); + } + + List reportIds = reports.stream() + .filter(Objects::nonNull) + .map(ProjectDailyReport::getId) + .filter(Objects::nonNull) + .toList(); + + Map latestAnalysisByReportId = new HashMap<>(); + if (!reportIds.isEmpty()) { + List analysisRecords = dailyReportAnalysisRecordMapper.selectList( + new LambdaQueryWrapper() + .eq(DailyReportAnalysisRecord::getProjectId, projectId) + .in(DailyReportAnalysisRecord::getReportId, reportIds) + .eq(DailyReportAnalysisRecord::getDeleted, 0) + .orderByDesc(DailyReportAnalysisRecord::getCreateTime) + ); + if (analysisRecords != null && !analysisRecords.isEmpty()) { + for (DailyReportAnalysisRecord record : analysisRecords) { + if (record == null || record.getReportId() == null) { + continue; + } + latestAnalysisByReportId.putIfAbsent(record.getReportId(), record); + } + } + } + + List analysisIds = latestAnalysisByReportId.values().stream() + .filter(Objects::nonNull) + .map(DailyReportAnalysisRecord::getId) + .filter(Objects::nonNull) + .distinct() + .toList(); + + Map> suggestionsByAnalysisId = Collections.emptyMap(); + if (!analysisIds.isEmpty()) { + List suggestions = dailyReportUpdateSuggestionMapper.selectList( + new LambdaQueryWrapper() + .eq(DailyReportUpdateSuggestion::getProjectId, projectId) + .eq(DailyReportUpdateSuggestion::getDeleted, 0) + .eq(StringUtils.hasText(actualSuggestionStatus), DailyReportUpdateSuggestion::getStatus, actualSuggestionStatus) + .in(DailyReportUpdateSuggestion::getAnalysisId, analysisIds) + .orderByAsc(DailyReportUpdateSuggestion::getCreateTime) + ); + List suggestionVOs = buildSuggestionVOList(projectId, suggestions); + suggestionsByAnalysisId = suggestionVOs.stream() + .filter(vo -> vo != null && vo.getAnalysisId() != null) + .collect(Collectors.groupingBy(DailyReportUpdateSuggestionVO::getAnalysisId)); + } + + List voList = new ArrayList<>(); + for (ProjectDailyReport report : reports) { + if (report == null) { + continue; + } + DailyReportWithAnalysisVO vo = new DailyReportWithAnalysisVO(); + vo.setReportId(report.getId()); + vo.setProjectId(report.getProjectId()); + vo.setReportDate(report.getReportDate()); + vo.setSubmitterUsername(report.getSubmitterUsername()); + vo.setSubmitterId(report.getSubmitterId()); + vo.setWorkContent(report.getWorkContent()); + vo.setTomorrowPlan(report.getTomorrowPlan()); + vo.setWorkIntensity(report.getWorkIntensity()); + vo.setNeedHelp(report.getNeedHelp()); + vo.setHelpContent(report.getHelpContent()); + vo.setCreateTime(report.getCreateTime()); + + DailyReportAnalysisRecord record = report.getId() != null ? latestAnalysisByReportId.get(report.getId()) : null; + if (record != null) { + vo.setAnalysisId(record.getId()); + vo.setAnalysisStatus(record.getStatus()); + if (record.getAnalysisResult() != null) { + DailyReportAnalysisResult analysisResult = OBJECT_MAPPER.convertValue(record.getAnalysisResult(), DailyReportAnalysisResult.class); + vo.setAnalysisResult(analysisResult); + } + vo.setAnalysisSuggestions(record.getId() != null ? suggestionsByAnalysisId.getOrDefault(record.getId(), List.of()) : List.of()); + } else { + vo.setAnalysisSuggestions(List.of()); + } + + voList.add(vo); + } + + return TableDataInfo.build(new Page(reportPage.getCurrent(), reportPage.getSize(), reportPage.getTotal()) + .setRecords(voList)); + } + @Override @Transactional(rollbackFor = Exception.class) public int applySuggestions(Long projectId, List suggestionIds, Long appliedBy) {