Files
ylhp-ai-project-manager/src/main/java/cn/yinlihupo/service/open/impl/OpenApiServiceImpl.java
JiaoTianBo 88c9fe5e06 feat(open-api): 新增对外开放接口及项目日报同步功能
- 新增项目日报表及其防重唯一索引,支持外部系统同步日报数据
- 添加项目日报实体类及对应 Mapper 和 XML 配置
- 新增对外开放接口控制器 OpenApiController,实现项目列表查询及日报同步接口
- 实现 OpenApiService 服务及其实现类,包含用户项目查询和日报防重同步逻辑
- 扩展 ProjectMapper,支持根据用户名查询用户关联项目列表
- 配置 SaToken 过滤白名单,放行 /api/open/** 路径无登录验证
- 引入 spring-boot-starter-validation 依赖,支持请求参数校验
- 创建数据传输对象 DailyReportSyncDTO,带参数校验注解
- 日志记录和异常处理增强,保证数据同步和查询的健壮性
2026-03-31 15:45:36 +08:00

135 lines
5.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package cn.yinlihupo.service.open.impl;
import cn.yinlihupo.common.exception.BusinessException;
import cn.yinlihupo.domain.dto.DailyReportSyncDTO;
import cn.yinlihupo.domain.entity.Project;
import cn.yinlihupo.domain.entity.ProjectDailyReport;
import cn.yinlihupo.domain.entity.SysUser;
import cn.yinlihupo.domain.vo.OpenProjectVO;
import cn.yinlihupo.mapper.ProjectDailyReportMapper;
import cn.yinlihupo.mapper.ProjectMapper;
import cn.yinlihupo.mapper.ProjectMemberMapper;
import cn.yinlihupo.mapper.SysUserMapper;
import cn.yinlihupo.service.open.OpenApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 开放接口服务实现
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OpenApiServiceImpl implements OpenApiService {
private final SysUserMapper sysUserMapper;
private final ProjectMapper projectMapper;
private final ProjectMemberMapper projectMemberMapper;
private final ProjectDailyReportMapper projectDailyReportMapper;
/**
* 根据用户标识 (sys_user.username) 查询用户所在的项目列表
*/
@Override
public List<OpenProjectVO> getProjectsByUserId(String userId) {
if (!StringUtils.hasText(userId)) {
return new ArrayList<>();
}
// 1. 先验证用户是否存在
SysUser user = sysUserMapper.selectByUsername(userId);
if (user == null) {
log.warn("[OpenApi] 用户不存在, username={}", userId);
return new ArrayList<>();
}
// 2. 联查用户所在的项目列表(通过 username 关联 sys_user -> project/project_member
List<Project> projects = projectMapper.selectProjectsByUsername(userId);
if (projects == null || projects.isEmpty()) {
return new ArrayList<>();
}
// 3. 转换为 OpenProjectVO 并填充用户角色
List<OpenProjectVO> result = new ArrayList<>();
for (Project project : projects) {
OpenProjectVO vo = new OpenProjectVO();
vo.setId(project.getId());
vo.setProjectCode(project.getProjectCode());
vo.setProjectName(project.getProjectName());
vo.setProjectType(project.getProjectType());
vo.setStatus(project.getStatus());
vo.setPriority(project.getPriority());
vo.setPlanStartDate(project.getPlanStartDate());
vo.setPlanEndDate(project.getPlanEndDate());
vo.setProgress(project.getProgress());
// 4. 填充用户在该项目的角色
if (project.getManagerId() != null && project.getManagerId().equals(user.getId())) {
vo.setMyRole("manager");
} else {
String role = projectMemberMapper.selectRoleByUserAndProject(project.getId(), user.getId());
vo.setMyRole(role);
}
result.add(vo);
}
log.info("[OpenApi] 查询用户项目列表成功, username={}, 项目数={}", userId, result.size());
return result;
}
/**
* 同步日报数据到库(带防重设计)
*/
@Override
public String syncDailyReport(DailyReportSyncDTO dto) {
String username = dto.getUserId();
// 1. 校验用户是否存在
SysUser user = sysUserMapper.selectByUsername(username);
if (user == null) {
log.warn("[OpenApi] 日报同步失败,用户不存在, username={}", username);
throw new BusinessException("用户不存在: " + username);
}
// 2. 校验项目是否存在
Project project = projectMapper.selectById(dto.getProjectId());
if (project == null || project.getDeleted() == 1) {
log.warn("[OpenApi] 日报同步失败,项目不存在, projectId={}", dto.getProjectId());
throw new BusinessException("项目不存在: " + dto.getProjectId());
}
// 3. 防重检查:同一用户同一天同一项目只能提交一条日报
int count = projectDailyReportMapper.countByUniqueKey(
dto.getProjectId(), dto.getReportDate(), username);
if (count > 0) {
log.warn("[OpenApi] 日报重复提交, projectId={}, reportDate={}, username={}",
dto.getProjectId(), dto.getReportDate(), username);
throw new BusinessException("日报已提交请勿重复提交项目ID: "
+ dto.getProjectId() + ",日期: " + dto.getReportDate() + "");
}
// 4. 入库保存
ProjectDailyReport report = new ProjectDailyReport();
report.setProjectId(dto.getProjectId());
report.setSubmitterUsername(username);
report.setSubmitterId(user.getId());
report.setReportDate(dto.getReportDate());
report.setWorkContent(dto.getWorkContent());
report.setTomorrowPlan(dto.getTomorrowPlan());
report.setWorkIntensity(dto.getWorkIntensity());
report.setNeedHelp(dto.getNeedHelp());
report.setHelpContent(dto.getHelpContent());
projectDailyReportMapper.insert(report);
log.info("[OpenApi] 日报同步成功, projectId={}, reportDate={}, username={}",
dto.getProjectId(), dto.getReportDate(), username);
return "日报同步成功";
}
}