liyong
2026-05-09 98d23d2bff330b6d1b30dde59f4e828ad255b2bb
feat(approve): 添加日志报表功能模块

- 新增 LogReportDto 数据传输对象,继承 LogReport 并扩展抄送人相关字段
- 新增 LogReport 实体类,定义日志表的基本属性和数据库映射
- 创建 LogReportController 控制器,提供日志的增删改查和推送接口
- 实现 LogReportService 服务接口,包含分页查询、添加、更新和推送逻辑
- 开发 LogReportServiceImpl 服务实现类,处理业务逻辑和数据转换
- 配置 LogReportMapper 数据访问层,支持分页查询和复杂条件筛选
- 添加 MyBatis XML 映射文件,实现日志列表的关联查询和权限控制
- 整合系统用户查询功能,支持抄送人名称的动态获取和显示
- 实现日志推送功能,支持向指定用户发送通知消息
已添加7个文件
已修改1个文件
391 ■■■■■ 文件已修改
src/main/java/com/ruoyi/approve/bean/dto/LogReportDto.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/LogReportController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/LogReportMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/LogReport.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/LogReportService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/LogReportServiceImpl.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/LogReportMapper.xml 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/bean/dto/LogReportDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.ruoyi.approve.bean.dto;
import com.ruoyi.approve.pojo.LogReport;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class LogReportDto extends LogReport {
    @Schema(description = "抄送人名称")
    private String ccUserName;
    @Schema(description = "抄送人ids")
    private List<Long> ccUserIds;
    private String createUserName;
    private String  startTime;
    private String  endTime;
}
src/main/java/com/ruoyi/approve/controller/LogReportController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
package com.ruoyi.approve.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.approve.bean.dto.LogReportDto;
import com.ruoyi.approve.service.LogReportService;
import com.ruoyi.framework.web.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * <p>
 * æ—¥å¿—表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-05-08 01:51:13
 */
@RestController
@RequestMapping("/sysLogReport")
@Tag(name = "日志管理")
@AllArgsConstructor
public class LogReportController {
    private final LogReportService logReportService;
    @GetMapping("/listPage")
    @Operation(summary = "分页查询日志列表")
    public R listPage(Page page, LogReportDto sysLogReport) {
        IPage<LogReportDto> logReportDtoIPage =logReportService.listPage(page, sysLogReport);
        return R.ok(logReportDtoIPage);
    }
    @PostMapping("/add")
    @Operation(summary = "添加日志")
    public R add(@RequestBody LogReportDto sysLogReport) {
        return logReportService.add(sysLogReport) ? R.ok() : R.fail();
    }
    @PutMapping("/update")
    @Operation(summary = "更新日志")
    public R update( @RequestBody LogReportDto sysLogReport) {
        return logReportService.updateSysLogReportDto(sysLogReport) ? R.ok() : R.fail();
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除日志")
    public R delete(@RequestBody List<Long> ids) {
        return logReportService.removeBatchByIds(ids) ? R.ok() : R.fail();
    }
    @Operation(summary = "推送日志信息到用户")
    @PostMapping("/pushLogReport")
    public void pushLogReport(@RequestBody LogReportDto sysLogReportDto) {
        logReportService.pushLogReport(sysLogReportDto) ;
    }
}
src/main/java/com/ruoyi/approve/mapper/LogReportMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.ruoyi.approve.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.approve.bean.dto.LogReportDto;
import com.ruoyi.approve.pojo.LogReport;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 * æ—¥å¿—表 Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-05-08 01:51:13
 */
@Mapper
public interface LogReportMapper extends BaseMapper<LogReport> {
    IPage<LogReportDto> listPage(Page page, @Param("ew") LogReportDto sysLogReport, @Param("userId") Long userId);
}
src/main/java/com/ruoyi/approve/pojo/LogReport.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.ruoyi.approve.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
 * <p>
 * æ—¥å¿—表
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-05-08 01:51:13
 */
@Getter
@Setter
@ToString
@TableName("log_report")
@ApiModel(value = "SysLogReport对象", description = "日志表")
public class LogReport implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ä¸»é”®ID
     */
    @Schema(description = "主键ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * æ—¥å¿—标题
     */
    @Schema(description = "日志标题")
    private String title;
    /**
     * æŠ¥å‘Šç±»åž‹ï¼šæ—¥æŠ¥ï¼Œå‘¨æŠ¥ï¼ŒæœˆæŠ¥
     */
    @Schema(description = "报告类型:日报,周报,月报")
    private String reportType;
    /**
     * æ—¥å¿—类型:work/project/problem/other
     */
    @Schema(description = "日志类型:work/project/problem/other")
    private String logType;
    /**
     * æ—¥å¿—内容
     */
    @Schema(description = "日志内容")
    private String content;
    /**
     * æŽ¨é€çŠ¶æ€ï¼š0未推送 1已推送 2推送失败
     */
    @Schema(description = "推送状态:0未推送 1已推送 2推送失败")
    private Integer pushStatus;
    /**
     * åˆ›å»ºäºº
     */
    @Schema(description = "创建人")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT)
    private Integer deptId;
    @Schema(description = "抄送人")
    private String ccUsers;
}
src/main/java/com/ruoyi/approve/service/LogReportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.approve.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.approve.bean.dto.LogReportDto;
import com.ruoyi.approve.pojo.LogReport;
/**
 * <p>
 * æ—¥å¿—表 æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-05-08 01:51:13
 */
public interface LogReportService extends IService<LogReport> {
    IPage<LogReportDto> listPage(Page page, LogReportDto sysLogReport);
    Boolean add(LogReportDto sysLogReport);
    Boolean updateSysLogReportDto(LogReportDto sysLogReport);
    void pushLogReport(LogReportDto sysLogReportDto);
}
src/main/java/com/ruoyi/approve/service/impl/LogReportServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
package com.ruoyi.approve.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.approve.bean.dto.LogReportDto;
import com.ruoyi.approve.mapper.LogReportMapper;
import com.ruoyi.approve.pojo.LogReport;
import com.ruoyi.approve.service.LogReportService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.service.ISysNoticeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * <p>
 * æ—¥å¿—表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-05-08 01:51:13
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class LogReportServiceImpl extends ServiceImpl<LogReportMapper, LogReport> implements LogReportService {
    private final LogReportMapper sysLogReportMapper;
    private final ISysNoticeService sysNoticeService;
    private final SysUserMapper sysUserMapper;
    @Override
    public IPage<LogReportDto> listPage(Page page, LogReportDto sysLogReport) {
        Long userId = SecurityUtils.getUserId();
        IPage<LogReportDto> logReportDtoIPage = sysLogReportMapper.listPage(page, sysLogReport, userId);
        logReportDtoIPage.getRecords().forEach(sysLogReportDto -> {
            String ccUsers = sysLogReportDto.getCcUsers();
            if (StringUtils.isBlank(ccUsers)) {
                return;
            }
            List<Long> userIdList = Arrays.stream(ccUsers.split(","))
                    .filter(StringUtils::isNotBlank)  // è¿‡æ»¤ç©ºå­—符串
                    .map(String::trim)                 // åŽ»é™¤ç©ºæ ¼
                    .map(Long::parseLong)              // è½¬æ¢ä¸º Long
                    .collect(Collectors.toList());     // æ”¶é›†ä¸º List
            sysLogReportDto.setCcUserIds(userIdList);
            if (!userIdList.isEmpty()) {
                List<SysUser> users = sysUserMapper.selectUsersByIds(userIdList);
                String userNames = users.stream()
                        .filter(Objects::nonNull)
                        .map(SysUser::getNickName)
                        .filter(StringUtils::isNotBlank)
                        .collect(Collectors.joining(","));
                // å¦‚果所有用户都没有昵称,设置为空字符串
                sysLogReportDto.setCcUserName(StringUtils.isNotBlank(userNames) ? userNames : "");
            } else {
                sysLogReportDto.setCcUserName("");
            }
        });
        return logReportDtoIPage;
    }
    @Override
    public Boolean add(LogReportDto sysLogReport) {
        String collect = sysLogReport.getCcUserIds().stream()
                .map(String::valueOf)           // Long â†’ String
                .collect(Collectors.joining(","));// æ‹¼æŽ¥ä¸º "1,2,3"
        sysLogReport.setCcUsers(collect);
        sysLogReport.setPushStatus(1);
        this.save(sysLogReport);
        if (ObjectUtils.isNotEmpty(sysLogReport.getCcUserIds())) {
            pushLogReport(sysLogReport);
        }
        return true;
    }
    @Override
    public Boolean updateSysLogReportDto(LogReportDto sysLogReport) {
        String collect = sysLogReport.getCcUserIds().stream()
                .map(String::valueOf)           // Long â†’ String
                .collect(Collectors.joining(","));// æ‹¼æŽ¥ä¸º "1,2,3"
        sysLogReport.setCcUsers(collect);
        sysLogReport.setPushStatus(1);
        if (ObjectUtils.isNotEmpty(sysLogReport.getCcUserIds())) {
            pushLogReport(sysLogReport);
        }
        return this.updateById(sysLogReport);
    }
    @Override
    public void pushLogReport(LogReportDto sysLogReportDto) {
        LogReport byId = this.getById(sysLogReportDto.getId());
        sysNoticeService.simpleNoticeByUser(byId.getTitle(), byId.getContent(), sysLogReportDto.getCcUserIds(), "/collaborativeApproval/journal");
    }
}
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
@@ -1,15 +1,11 @@
package com.ruoyi.project.system.mapper;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.collaborativeApproval.pojo.MeetingMinutes;
import com.ruoyi.project.system.domain.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.ruoyi.project.system.domain.SysUser;
import org.springframework.beans.PropertyValues;
import java.util.List;
/**
 * ç”¨æˆ·è¡¨ æ•°æ®å±‚
src/main/resources/mapper/approve/LogReportMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.approve.mapper.LogReportMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.LogReport">
        <id column="id" property="id" />
        <result column="title" property="title" />
        <result column="report_type" property="reportType" />
        <result column="log_type" property="logType" />
        <result column="content" property="content" />
        <result column="push_status" property="pushStatus" />
        <result column="create_user" property="createUser" />
        <result column="create_time" property="createTime" />
        <result column="dept_id" property="deptId" />
    </resultMap>
    <select id="listPage" resultType="com.ruoyi.approve.bean.dto.LogReportDto">
        select
        slr.*,
        su.nick_name as create_user_name
        from
        log_report slr
        left join sys_user su on slr.create_user = su.user_id
        <where>
            <if test="ew.title != null and ew.title != ''">
                and slr.title like concat('%', #{ew.title}, '%')
            </if>
            <if test="ew.logType != null and ew.logType != ''">
                and slr.log_type = #{ew.logType}
            </if>
            <if test="ew.reportType != null and ew.reportType != ''">
                and slr.report_type = #{ew.reportType}
            </if>
            <if test="ew.pushStatus != null and ew.pushStatus != ''">
                and slr.push_status = #{ew.pushStatus}
            </if>
            <if test="ew.createUser != null and ew.createUser != ''">
                and slr.create_user = #{ew.createUser}
            </if>
            <if test="ew.startTime != null and ew.endTime !=''">
                and slr.create_time between #{ew.startTime} and #{ew.endTime}
            </if>
            <if test="ew.ccUserIds != null">
                and (
                slr.create_user = #{userId}
                or (
                slr.cc_users is not null
                and slr.cc_users != ''
                and find_in_set(#{userId}, slr.cc_users)
                )
                )
            </if>
        </where>
        order by slr.create_time desc
    </select>
</mapper>