- 新增项目日报表及其防重唯一索引,支持外部系统同步日报数据 - 添加项目日报实体类及对应 Mapper 和 XML 配置 - 新增对外开放接口控制器 OpenApiController,实现项目列表查询及日报同步接口 - 实现 OpenApiService 服务及其实现类,包含用户项目查询和日报防重同步逻辑 - 扩展 ProjectMapper,支持根据用户名查询用户关联项目列表 - 配置 SaToken 过滤白名单,放行 /api/open/** 路径无登录验证 - 引入 spring-boot-starter-validation 依赖,支持请求参数校验 - 创建数据传输对象 DailyReportSyncDTO,带参数校验注解 - 日志记录和异常处理增强,保证数据同步和查询的健壮性
135 lines
5.3 KiB
Java
135 lines
5.3 KiB
Java
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 "日报同步成功";
|
||
}
|
||
}
|