feat(oa): 新增用户活跃统计功能并完善个人报告统计

- 新增用户活跃统计模块,包括实体类、业务接口和实现、控制器及Mapper
- 实现用户登录时记录当日活跃数据
- 在个人报告中增加活跃天数、报工信息、出差信息、项目信息等统计维度
- 添加工程异常统计和关键采购任务统计功能
- 完善任务信息统计,包括发放任务、承担任务及其状态分析
-优化个人报告接口,支持更全面的工作数据展示
This commit is contained in:
2025-10-30 15:33:39 +08:00
parent 29340d323f
commit 4f0ebc1a4e
15 changed files with 1229 additions and 3 deletions

View File

@@ -73,4 +73,5 @@ public interface IOaProjectScheduleStepService{
List<Map<String, Object>> queryProgressByHeader();
PersonalReportDTO personalReport(Long poolId, String nickName);
}

View File

@@ -0,0 +1,53 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaUserActive;
import com.ruoyi.oa.domain.vo.OaUserActiveVo;
import com.ruoyi.oa.domain.bo.OaUserActiveBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 用户活跃统计Service接口
*
* @author ruoyi
* @date 2025-10-30
*/
public interface IOaUserActiveService {
/**
* 查询用户活跃统计
*/
OaUserActiveVo queryById(Long activeId);
/**
* 查询用户活跃统计列表
*/
TableDataInfo<OaUserActiveVo> queryPageList(OaUserActiveBo bo, PageQuery pageQuery);
/**
* 查询用户活跃统计列表
*/
List<OaUserActiveVo> queryList(OaUserActiveBo bo);
/**
* 新增用户活跃统计
*/
Boolean insertByBo(OaUserActiveBo bo);
/**
* 修改用户活跃统计
*/
Boolean updateByBo(OaUserActiveBo bo);
/**
* 校验并批量删除用户活跃统计信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
boolean hasActiveToday(Long userId);
void recordTodayLogin(Long userId);
}

View File

@@ -4,9 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -17,11 +15,20 @@ import com.ruoyi.oa.domain.*;
import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.dto.PersonalReportDTO;
import com.ruoyi.oa.domain.vo.OaExpressVo;
import com.ruoyi.oa.mapper.*;
import com.ruoyi.oa.mapper.OaProjectReportMapper;
import com.ruoyi.oa.mapper.SysOaTaskMapper;
import com.ruoyi.oa.mapper.OaUserActiveMapper;
import com.ruoyi.oa.mapper.OaExpressQuestionMapper;
import com.ruoyi.oa.mapper.OaRequirementsMapper;
import com.ruoyi.oa.service.IOaExpressService;
import com.ruoyi.oa.service.ISysOaTaskService;
import com.ruoyi.system.mapper.SysUserMapper;
import java.math.BigDecimal;
import java.util.Date;
import lombok.RequiredArgsConstructor;
import org.flowable.job.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
@@ -59,6 +66,18 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
private final OaProjectScheduleStepMapper projectScheduleStepMapper;
private final ISysOaTaskService sysOaTaskService;
private final OaProjectReportMapper projectReportMapper;
private final SysOaTaskMapper taskMapper;
private final OaUserActiveMapper userActiveMapper;
private final OaExpressQuestionMapper expressQuestionMapper;
private final OaRequirementsMapper requirementsMapper;
private final IOaExpressService oaExpressService;
@@ -358,6 +377,7 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
if (user == null) {
throw new RuntimeException("未找到用户:" + nickName);
}
Long userId = user.getUserId();
// 查询奖金池关联的项目ID
List<OaBonusProjectRel> rels = bonusProjectRelMapper.selectList(
@@ -444,9 +464,474 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
result.setProgressStats(progressStats);
result.setUserSteps(userSteps); // 此时userSteps已包含每个步骤对应的projectId
result.setTasks(tasks);
// 统计活跃天数
result.setActiveDays(getActiveDays(userId, startTime, endTime));
// 1. 统计报工信息
result.setWorkReportStats(getWorkReportStats(userId, startTime, endTime));
// 2. 统计出差信息
result.setBusinessTripStats(getBusinessTripStats(userId, startTime, endTime));
// 3. 统计项目信息
result.setProjectStats(getProjectStats(userId, nickName, startTime, endTime));
// // 4. 统计进度信息
// result.setProgressStats(getProgressStats(nickName, startDate, endDate));
// 5. 统计任务信息
result.setTaskStats(getTaskStats(userId, startTime, endTime));
// 6. 统计工程异常信息
result.setExceptionStats(getExceptionStats(nickName, startTime, endTime));
// 7. 统计关键采购任务信息
result.setProcurementStats(getProcurementStats(userId, startTime, endTime));
return result;
}
/**
* 统计用户活跃天数
* @param userId 用户ID
* @param startDate 开始日期
* @param endDate 结束日期
* @return 活跃天数
*/
private Integer getActiveDays(Long userId, Date startDate, Date endDate) {
// 构建查询条件
LambdaQueryWrapper<OaUserActive> wrapper = Wrappers.<OaUserActive>lambdaQuery()
.eq(OaUserActive::getUserId, userId)
.eq(OaUserActive::getDelFlag, 0);
// 添加时间范围条件
if (startDate != null && endDate != null) {
wrapper.between(OaUserActive::getActiveDate, startDate, endDate);
}
// 查询活跃记录数量
Long count = userActiveMapper.selectCount(wrapper);
return count != null ? count.intValue() : 0;
}
/**
* 统计报工信息
*/
private PersonalReportDTO.WorkReportStats getWorkReportStats(Long userId, Date startDate, Date endDate) {
PersonalReportDTO.WorkReportStats stats = new PersonalReportDTO.WorkReportStats();
LambdaQueryWrapper<OaProjectReport> wrapper = Wrappers.<OaProjectReport>lambdaQuery()
.eq(OaProjectReport::getDelFlag, 0)
.eq(OaProjectReport::getUserId, userId);
// 添加时间范围条件
if (startDate != null && endDate != null) {
wrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
}
List<OaProjectReport> reports = projectReportMapper.selectList(wrapper);
// 计算报工天数(这里简化处理,实际可能需要按日期去重)
stats.setTotalWorkDays(BigDecimal.valueOf(reports.size()));
stats.setValidWorkDays(BigDecimal.valueOf(reports.size()));
// 统计涉及的项目数量
Set<Long> projectIds = reports.stream()
.map(OaProjectReport::getProjectId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
stats.setReportProjectCount(projectIds.size());
return stats;
}
/**
* 统计出差信息
*/
private PersonalReportDTO.BusinessTripStats getBusinessTripStats(Long userId, Date startDate, Date endDate) {
PersonalReportDTO.BusinessTripStats stats = new PersonalReportDTO.BusinessTripStats();
LambdaQueryWrapper<OaProjectReport> wrapper = Wrappers.<OaProjectReport>lambdaQuery()
.eq(OaProjectReport::getDelFlag, 0)
.eq(OaProjectReport::getIsTrip, 1) // 出差标记
.eq(OaProjectReport::getUserId, userId);
// 添加时间范围条件
if (startDate != null && endDate != null) {
wrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
}
// 1. 统计总出差天数(按记录数统计,假设一条记录对应一天)
Long totalTripCount = projectReportMapper.selectCount(wrapper);
stats.setTotalTripDays(BigDecimal.valueOf(totalTripCount));
// 国外
LambdaQueryWrapper<OaProjectReport> foreignWrapper = Wrappers.<OaProjectReport>lambdaQuery()
.eq(OaProjectReport::getDelFlag, 0)
.eq(OaProjectReport::getIsTrip, 1)
.eq(OaProjectReport::getUserId, userId)
.eq(OaProjectReport::getWorkType, 1); // 国外标志
if (StringUtils.isNull(startDate) && StringUtils.isNull(endDate)) {
foreignWrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
}
Long foreignTripCount = projectReportMapper.selectCount(foreignWrapper);
stats.setForeignTripDays(BigDecimal.valueOf(foreignTripCount));
// 3. 国内出差天数 = 总出差天数 - 国外出差天数
stats.setDomesticTripDays(BigDecimal.valueOf(totalTripCount - foreignTripCount));
// 统计出差项目数量
Set<Long> tripProjectIds = projectReportMapper.selectObjs(wrapper
.select(OaProjectReport::getProjectId)) // 只查询project_id字段
.stream()
.filter(Objects::nonNull)
.map(obj -> (Long) obj)
.collect(Collectors.toSet());
stats.setTripProjectCount(tripProjectIds.size());
return stats;
}
/**
* 统计项目信息
*/
private PersonalReportDTO.ProjectStats getProjectStats(Long userId, String nickName, Date startDate, Date endDate) {
PersonalReportDTO.ProjectStats stats = new PersonalReportDTO.ProjectStats();
// 通过报工记录查询参与的项目
LambdaQueryWrapper<OaProjectReport> reportWrapper = Wrappers.<OaProjectReport>lambdaQuery()
.eq(OaProjectReport::getUserId, userId)
.eq(OaProjectReport::getDelFlag, 0);
// if (startDate != null && endDate != null) {
// reportWrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
// }
List<OaProjectReport> reports = projectReportMapper.selectList(reportWrapper);
Set<Long> participatedProjectIds = reports.stream()
.map(OaProjectReport::getProjectId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 查询负责的项目
LambdaQueryWrapper<SysOaProject> projectWrapper = Wrappers.<SysOaProject>lambdaQuery()
.eq(SysOaProject::getFunctionary, nickName);
List<SysOaProject> responsibleProjectList = projectMapper.selectList(projectWrapper);
stats.setTotalProjects(participatedProjectIds.size());
stats.setResponsibleProjects(responsibleProjectList.size());
stats.setParticipatedProjects(participatedProjectIds.size());
// 构建项目清单
List<PersonalReportDTO.ProjectSummary> projectList = new ArrayList<>();
// 添加负责的项目
for (SysOaProject project : responsibleProjectList) {
PersonalReportDTO.ProjectSummary summary = new PersonalReportDTO.ProjectSummary();
summary.setProjectId(project.getProjectId());
summary.setProjectName(project.getProjectName());
summary.setProjectNum(project.getProjectNum());
summary.setRole("负责人");
// 计算参与天数
//TODO 项目负责人是不报工的
long participationDays = reports.stream()
.filter(report -> project.getProjectId().equals(report.getProjectId()))
.count();
summary.setParticipationDays(BigDecimal.valueOf(participationDays));
projectList.add(summary);
}
// 添加参与的其他项目
for (Long projectId : participatedProjectIds) {
if (responsibleProjectList.stream().noneMatch(p -> p.getProjectId().equals(projectId))) {
SysOaProject project = projectMapper.selectById(projectId);
if (project != null) {
PersonalReportDTO.ProjectSummary summary = new PersonalReportDTO.ProjectSummary();
summary.setProjectId(project.getProjectId());
summary.setProjectName(project.getProjectName());
summary.setProjectNum(project.getProjectNum());
summary.setRole("参与者");
// 计算参与天数
long participationDays = reports.stream()
.filter(report -> projectId.equals(report.getProjectId()))
.count();
summary.setParticipationDays(BigDecimal.valueOf(participationDays));
projectList.add(summary);
}
}
}
stats.setProjectList(projectList);
return stats;
}
/**
* 统计任务信息
*/
private PersonalReportDTO.TaskStats getTaskStats(Long userId, Date startDate, Date endDate) {
PersonalReportDTO.TaskStats stats = new PersonalReportDTO.TaskStats();
// 查询发放的任务(创建的任务)
LambdaQueryWrapper<SysOaTask> assignedWrapper = Wrappers.<SysOaTask>lambdaQuery()
.eq(SysOaTask::getCreateUserId, userId);
if (startDate != null && endDate != null) {
assignedWrapper.between(SysOaTask::getBeginTime, startDate, endDate);
}
List<SysOaTask> assignedTasks = taskMapper.selectList(assignedWrapper);
// 查询承担的任务(被分配的任务)
LambdaQueryWrapper<SysOaTask> undertakenWrapper = Wrappers.<SysOaTask>lambdaQuery()
.eq(SysOaTask::getWorkerId, userId);
if (startDate != null && endDate != null) {
undertakenWrapper.between(SysOaTask::getBeginTime, startDate, endDate);
}
List<SysOaTask> undertakenTasks = taskMapper.selectList(undertakenWrapper);
// 统计数量
stats.setAssignedTasks(assignedTasks.size());
stats.setUndertakenTasks(undertakenTasks.size());
// 统计已完成任务数量(状态为完成)
long completedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(2).equals(task.getState())).count();
long completedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(2).equals(task.getState())).count();
stats.setCompletedTasks((int) (completedAssigned + completedUndertaken));
// 统计进行中任务数量(状态为 1 等待审核)
long underwayAssigned = assignedTasks.stream().filter(task -> Long.valueOf(1).equals(task.getState())).count();
long underwayUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(1).equals(task.getState())).count();
stats.setUnderwayTasks((int) (underwayAssigned + underwayUndertaken));
//未完成的数量
long unfinishedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(0).equals(task.getState())).count();
long unfinishedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(0).equals(task.getState())).count();
stats.setUnfinishedTasks((int) (unfinishedAssigned + unfinishedUndertaken));
// 统计延期任务数量
long delayedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(15).equals(task.getState())).count();
long delayedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(15).equals(task.getState())).count();
stats.setDelayedTasks((int) (delayedAssigned + delayedUndertaken));
// 构建任务清单
List<PersonalReportDTO.TaskSummary> assignedTaskList = assignedTasks.stream()
.map(this::buildTaskSummary)
.collect(Collectors.toList());
List<PersonalReportDTO.TaskSummary> undertakenTaskList = undertakenTasks.stream()
.map(this::buildTaskSummary)
.collect(Collectors.toList());
stats.setAssignedTaskList(assignedTaskList);
stats.setUndertakenTaskList(undertakenTaskList);
return stats;
}
/**
* 构建任务摘要
*/
private PersonalReportDTO.TaskSummary buildTaskSummary(SysOaTask task) {
PersonalReportDTO.TaskSummary summary = new PersonalReportDTO.TaskSummary();
summary.setTaskId(task.getTaskId());
summary.setTaskTitle(task.getTaskTitle());
summary.setState(task.getState());
summary.setIsDelayed(task.getPostponements() != null && task.getPostponements() > 0);
summary.setPostponements(task.getPostponements());
// 获取项目名称
if (task.getProjectId() != null) {
SysOaProject project = projectMapper.selectById(task.getProjectId());
if (project != null) {
summary.setProjectName(project.getProjectName());
}
}
return summary;
}
/**
* 统计工程异常信息基于oa_express_question表
*/
private PersonalReportDTO.EngineeringExceptionStats getExceptionStats(String nickName, Date startDate, Date endDate) {
PersonalReportDTO.EngineeringExceptionStats stats = new PersonalReportDTO.EngineeringExceptionStats();
// 查询快递问题表,通过汇报人匹配
LambdaQueryWrapper<OaExpressQuestion> wrapper = Wrappers.<OaExpressQuestion>lambdaQuery()
.eq(OaExpressQuestion::getReportBy, nickName)
.eq(OaExpressQuestion::getDelFlag, 0);
// 添加时间范围条件(基于汇报时间)
if (startDate != null && endDate != null) {
wrapper.between(OaExpressQuestion::getReportTime, startDate, endDate);
}
List<OaExpressQuestion> questions = expressQuestionMapper.selectList(wrapper);
stats.setTotalExceptions(questions.size());
// 统计已解决和未解决的异常
long resolvedCount = questions.stream().filter(q -> Long.valueOf(1).equals(q.getStatus())).count();
long unresolvedCount = questions.stream().filter(q -> Long.valueOf(0).equals(q.getStatus())).count();
stats.setResolvedExceptions((int) resolvedCount);
stats.setDelayedExceptions((int) unresolvedCount); // 未解决的视为延期异常
// 构建异常清单
List<PersonalReportDTO.ExceptionSummary> exceptionList = questions.stream()
.map(question -> {
PersonalReportDTO.ExceptionSummary summary = new PersonalReportDTO.ExceptionSummary();
summary.setExceptionId(question.getQuestionId());
summary.setDescription(question.getDescription());
summary.setStatus(Long.valueOf(1).equals(question.getStatus()) ? "已解决" : "未解决");
summary.setIsDelayed(Long.valueOf(0).equals(question.getStatus())); // 未解决的视为延期
// 这里可以根据expressId关联获取项目信息
summary.setProjectName(oaExpressService.queryById(question.getExpressId()).getProjectName());
return summary;
})
.collect(Collectors.toList());
stats.setExceptionList(exceptionList);
return stats;
}
/**
* 统计关键采购任务信息基于oa_requirements表
*/
private PersonalReportDTO.ProcurementTaskStats getProcurementStats(Long userId, Date startDate, Date endDate) {
PersonalReportDTO.ProcurementTaskStats stats = new PersonalReportDTO.ProcurementTaskStats();
// 查询需求表通过负责人ID匹配
LambdaQueryWrapper<OaRequirements> wrapper = Wrappers.<OaRequirements>lambdaQuery()
.eq(OaRequirements::getOwnerId, userId)
.eq(OaRequirements::getDelFlag, 0);
// 添加时间范围条件
if (startDate != null && endDate != null) {
wrapper.between(OaRequirements::getCreateTime, startDate, endDate);
}
List<OaRequirements> requirements = requirementsMapper.selectList(wrapper);
stats.setTotalProcurementTasks(requirements.size());
// 统计已完成和延期的需求
long completedCount = requirements.stream().filter(req -> Integer.valueOf(1).equals(req.getStatus())).count();
stats.setCompletedProcurementTasks((int) completedCount);
// 计算延期需求(截止日期已过但未完成的)
long delayedCount = requirements.stream()
.filter(req -> Integer.valueOf(0).equals(req.getStatus())) // 未完成
.filter(req -> req.getDeadline() != null && req.getDeadline().before(new Date())) // 已过期
.count();
stats.setDelayedProcurementTasks((int) delayedCount);
// 构建采购任务清单
List<PersonalReportDTO.ProcurementTaskSummary> procurementList = requirements.stream()
.map(req -> {
PersonalReportDTO.ProcurementTaskSummary summary = new PersonalReportDTO.ProcurementTaskSummary();
summary.setProcurementId(req.getRequirementId());
summary.setProcurementContent(req.getTitle());
summary.setStatus(Integer.valueOf(1).equals(req.getStatus()) ? "已完成" : "进行中");
// 判断是否延期
boolean isDelayed = Integer.valueOf(0).equals(req.getStatus()) &&
req.getDeadline() != null && req.getDeadline().before(new Date());
summary.setIsDelayed(isDelayed);
// 获取项目名称
if (req.getProjectId() != null) {
SysOaProject project = projectMapper.selectById(req.getProjectId());
if (project != null) {
summary.setProjectName(project.getProjectName());
}
} else {
summary.setProjectName("无关联项目");
}
return summary;
})
.collect(Collectors.toList());
stats.setProcurementTaskList(procurementList);
return stats;
}
// /**
// * 统计进度信息
// */
// private PersonalReportDTO.ProgressStats getProgressStats(String nickName, String startDate, String endDate) {
// PersonalReportDTO.ProgressStats stats = new PersonalReportDTO.ProgressStats();
//
// // 查询用户负责的进度
// LambdaQueryWrapper<OaProjectScheduleStep> wrapper = Wrappers.<OaProjectScheduleStep>lambdaQuery()
// .eq(OaProjectScheduleStep::getNodeHeader, nickName)
// .eq(OaProjectScheduleStep::getDelFlag, "0");
//
// if (startDate != null && endDate != null) {
// wrapper.between(OaProjectScheduleStep::getCreateTime, startDate, endDate);
// }
//
// List<OaProjectScheduleStep> steps = baseMapper.selectList(wrapper);
//
// stats.setTotalProgress(steps.size());
//
// // 统计各状态的进度数量
// long completedCount = steps.stream().filter(step -> Long.valueOf(2).equals(step.getStatus())).count();
// long inProgressCount = steps.stream().filter(step -> Long.valueOf(1).equals(step.getStatus())).count();
//
// // 计算延期进度(实际结束时间晚于计划结束时间)
// long delayedCount = steps.stream()
// .filter(step -> step.getActualEnd() != null && step.getPlanEnd() != null)
// .filter(step -> step.getActualEnd().after(step.getPlanEnd()))
// .count();
//
// stats.setCompletedProgress((int) completedCount);
// stats.setInProgressCount((int) inProgressCount);
// stats.setDelayedProgress((int) delayedCount);
//
// // 构建进度清单
// List<PersonalReportDTO.ProgressSummary> progressList = steps.stream()
// .map(step -> {
// PersonalReportDTO.ProgressSummary summary = new PersonalReportDTO.ProgressSummary();
// summary.setTrackId(step.getTrackId());
// summary.setStepName(step.getStepName());
// summary.setStatus(step.getStatus());
//
// // 判断是否延期
// boolean isDelayed = step.getActualEnd() != null && step.getPlanEnd() != null &&
// step.getActualEnd().after(step.getPlanEnd());
// summary.setIsDelayed(isDelayed);
//
// // 获取项目名称
// if (step.getScheduleId() != null) {
// OaProjectSchedule schedule = scheduleMapper.selectById(step.getScheduleId());
// if (schedule != null && schedule.getProjectId() != null) {
// SysOaProject project = projectMapper.selectById(schedule.getProjectId());
// if (project != null) {
// summary.setProjectName(project.getProjectName());
// }
// }
// }
//
// return summary;
// })
// .collect(Collectors.toList());
//
// stats.setProgressList(progressList);
// return stats;
// }
}

View File

@@ -0,0 +1,141 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaUserActiveBo;
import com.ruoyi.oa.domain.vo.OaUserActiveVo;
import com.ruoyi.oa.domain.OaUserActive;
import com.ruoyi.oa.mapper.OaUserActiveMapper;
import com.ruoyi.oa.service.IOaUserActiveService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.time.LocalDate;
import java.sql.Date;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
/**
* 用户活跃统计Service业务层处理
*
* @author ruoyi
* @date 2025-10-30
*/
@RequiredArgsConstructor
@Service
public class OaUserActiveServiceImpl implements IOaUserActiveService {
private final OaUserActiveMapper baseMapper;
/**
* 查询用户活跃统计
*/
@Override
public OaUserActiveVo queryById(Long activeId){
return baseMapper.selectVoById(activeId);
}
/**
* 查询用户活跃统计列表
*/
@Override
public TableDataInfo<OaUserActiveVo> queryPageList(OaUserActiveBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaUserActive> lqw = buildQueryWrapper(bo);
Page<OaUserActiveVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询用户活跃统计列表
*/
@Override
public List<OaUserActiveVo> queryList(OaUserActiveBo bo) {
LambdaQueryWrapper<OaUserActive> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaUserActive> buildQueryWrapper(OaUserActiveBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaUserActive> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, OaUserActive::getUserId, bo.getUserId());
lqw.eq(bo.getActiveDate() != null, OaUserActive::getActiveDate, bo.getActiveDate());
lqw.eq(bo.getLoginCount() != null, OaUserActive::getLoginCount, bo.getLoginCount());
lqw.orderByDesc(OaUserActive::getCreateTime);
return lqw;
}
/**
* 新增用户活跃统计
*/
@Override
public Boolean insertByBo(OaUserActiveBo bo) {
OaUserActive add = BeanUtil.toBean(bo, OaUserActive.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setActiveId(add.getActiveId());
}
return flag;
}
/**
* 修改用户活跃统计
*/
@Override
public Boolean updateByBo(OaUserActiveBo bo) {
OaUserActive update = BeanUtil.toBean(bo, OaUserActive.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaUserActive entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除用户活跃统计
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public boolean hasActiveToday(Long userId) {
Date today = Date.valueOf(LocalDate.now());
LambdaQueryWrapper<OaUserActive> lqw = Wrappers.lambdaQuery();
lqw.eq(OaUserActive::getUserId, userId)
.eq(OaUserActive::getActiveDate, today);
return baseMapper.selectCount(lqw) > 0;
}
@Override
public void recordTodayLogin(Long userId) {
Date today = Date.valueOf(LocalDate.now());
LambdaUpdateWrapper<OaUserActive> uw = Wrappers.lambdaUpdate();
uw.eq(OaUserActive::getUserId, userId)
.eq(OaUserActive::getActiveDate, today)
.setSql("login_count = login_count + 1");
int rows = baseMapper.update(null, uw);
if (rows == 0) {
OaUserActive entity = new OaUserActive();
entity.setUserId(userId);
entity.setActiveDate(today);
entity.setLoginCount(1L);
baseMapper.insert(entity);
}
}
}

View File

@@ -24,6 +24,8 @@ import com.ruoyi.oa.domain.vo.SysOaTaskVo;
import com.ruoyi.oa.mapper.SysOaTaskMapper;
import com.ruoyi.oa.service.ISysOaTaskService;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
@@ -323,6 +325,7 @@ public class SysOaTaskServiceImpl implements ISysOaTaskService {
return Collections.emptyList();
}
// 增加任务开始时间在奖金池时间范围内的筛选
return baseMapper.selectList(Wrappers.<SysOaTask>lambdaQuery()
.eq(SysOaTask::getWorkerId, user.getUserId())