feat(analysis): 新增日报及分析结果分页接口与数据聚合
- 添加DailyReportAnalysisController,包含获取建议及分页查询接口 - 创建DailyReportSuggestionService接口及实现类分页方法 - 实现分页查询项目日报及其对应分析记录和建议功能 - 将日报与最新分析记录及建议数据整合为DailyReportWithAnalysisVO返回 - 增加接口调用的权限校验和错误处理 - 新增ApplyDailyReportSuggestionsRequest请求体及对应逻辑处理 - 补充分页参数默认值及状态筛选逻辑 - 优化查询条件,按日期及创建时间倒序排序
This commit is contained in:
@@ -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<TableDataInfo<DailyReportWithAnalysisVO>> 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<DailyReportWithAnalysisVO> 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用日报进度回写建议
|
||||
*
|
||||
|
||||
@@ -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<DailyReportUpdateSuggestionVO> analysisSuggestions;
|
||||
}
|
||||
@@ -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<DailyReportUpdateSuggestionVO> listSuggestionsByProjectId(Long projectId, LocalDate reportDate, String status);
|
||||
|
||||
TableDataInfo<DailyReportWithAnalysisVO> pageDailyReportsWithAnalysis(Long projectId, LocalDate reportDate, Integer pageNum, Integer pageSize, String suggestionStatus);
|
||||
|
||||
int applySuggestions(Long projectId, List<Long> suggestionIds, Long appliedBy);
|
||||
}
|
||||
|
||||
@@ -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<DailyReportWithAnalysisVO> 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<ProjectDailyReport> page = new Page<>(actualPageNum, actualPageSize);
|
||||
LambdaQueryWrapper<ProjectDailyReport> reportWrapper = new LambdaQueryWrapper<ProjectDailyReport>()
|
||||
.eq(ProjectDailyReport::getProjectId, projectId)
|
||||
.eq(ProjectDailyReport::getDeleted, 0)
|
||||
.eq(reportDate != null, ProjectDailyReport::getReportDate, reportDate)
|
||||
.orderByDesc(ProjectDailyReport::getReportDate)
|
||||
.orderByDesc(ProjectDailyReport::getCreateTime);
|
||||
|
||||
Page<ProjectDailyReport> reportPage = projectDailyReportMapper.selectPage(page, reportWrapper);
|
||||
List<ProjectDailyReport> reports = reportPage.getRecords();
|
||||
if (reports == null || reports.isEmpty()) {
|
||||
return TableDataInfo.build(new Page<DailyReportWithAnalysisVO>(reportPage.getCurrent(), reportPage.getSize(), reportPage.getTotal())
|
||||
.setRecords(new ArrayList<>()));
|
||||
}
|
||||
|
||||
List<Long> reportIds = reports.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(ProjectDailyReport::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
|
||||
Map<Long, DailyReportAnalysisRecord> latestAnalysisByReportId = new HashMap<>();
|
||||
if (!reportIds.isEmpty()) {
|
||||
List<DailyReportAnalysisRecord> analysisRecords = dailyReportAnalysisRecordMapper.selectList(
|
||||
new LambdaQueryWrapper<DailyReportAnalysisRecord>()
|
||||
.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<Long> analysisIds = latestAnalysisByReportId.values().stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(DailyReportAnalysisRecord::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.toList();
|
||||
|
||||
Map<Long, List<DailyReportUpdateSuggestionVO>> suggestionsByAnalysisId = Collections.emptyMap();
|
||||
if (!analysisIds.isEmpty()) {
|
||||
List<DailyReportUpdateSuggestion> suggestions = dailyReportUpdateSuggestionMapper.selectList(
|
||||
new LambdaQueryWrapper<DailyReportUpdateSuggestion>()
|
||||
.eq(DailyReportUpdateSuggestion::getProjectId, projectId)
|
||||
.eq(DailyReportUpdateSuggestion::getDeleted, 0)
|
||||
.eq(StringUtils.hasText(actualSuggestionStatus), DailyReportUpdateSuggestion::getStatus, actualSuggestionStatus)
|
||||
.in(DailyReportUpdateSuggestion::getAnalysisId, analysisIds)
|
||||
.orderByAsc(DailyReportUpdateSuggestion::getCreateTime)
|
||||
);
|
||||
List<DailyReportUpdateSuggestionVO> suggestionVOs = buildSuggestionVOList(projectId, suggestions);
|
||||
suggestionsByAnalysisId = suggestionVOs.stream()
|
||||
.filter(vo -> vo != null && vo.getAnalysisId() != null)
|
||||
.collect(Collectors.groupingBy(DailyReportUpdateSuggestionVO::getAnalysisId));
|
||||
}
|
||||
|
||||
List<DailyReportWithAnalysisVO> 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<DailyReportWithAnalysisVO>(reportPage.getCurrent(), reportPage.getSize(), reportPage.getTotal())
|
||||
.setRecords(voList));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int applySuggestions(Long projectId, List<Long> suggestionIds, Long appliedBy) {
|
||||
|
||||
Reference in New Issue
Block a user