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 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 projects = projectMapper.selectProjectsByUsername(userId); if (projects == null || projects.isEmpty()) { return new ArrayList<>(); } // 3. 转换为 OpenProjectVO 并填充用户角色 List 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 "日报同步成功"; } }