预警通知统计

This commit is contained in:
Flow 2025-06-19 10:14:49 +08:00
parent 2a1b3d0e32
commit 3dd2d2b7bf
12 changed files with 335 additions and 0 deletions

View File

@ -80,6 +80,12 @@ public class AlertMessageController {
return success(BeanUtils.toBean(pageResult, AlertMessageRespVO.class)); return success(BeanUtils.toBean(pageResult, AlertMessageRespVO.class));
} }
@GetMapping("/statistics")
@Operation(summary = "统计预警信息")
public CommonResult<AlertMessageStatisticsRespVO> getAlertMessageStatistics(@Valid AlertMessageStatisticsReqVO statisticsReqVO) {
return success(alertMessageService.getAlertMessageStatistics(statisticsReqVO));
}
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出预警信息 Excel") @Operation(summary = "导出预警信息 Excel")
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 预警信息统计 Request VO")
@Data
public class AlertMessageStatisticsReqVO {
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
@Schema(description = "机构ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30089")
@NotNull(message = "机构ID不能为空")
private Integer orgid;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.time.LocalDate;
@Schema(description = "管理后台 - 预警信息统计 Response VO")
@Data
public class AlertMessageStatisticsRespVO {
@Schema(description = "总数量", example = "100")
private Long totalCount;
@Schema(description = "已读数量", example = "80")
private Long readCount;
@Schema(description = "未读数量", example = "20")
private Long unreadCount;
@Schema(description = "按日期分组的预警信息数据")
private List<DailyAlertData> dailyData;
@Schema(description = "按日期分组的预警信息数据")
@Data
public static class DailyAlertData {
@Schema(description = "日期", example = "2024-01-01")
private LocalDate date;
@Schema(description = "该日期的预警总数", example = "10")
private Long totalCount;
@Schema(description = "该日期的已读数量", example = "8")
private Long readCount;
@Schema(description = "该日期的未读数量", example = "2")
private Long unreadCount;
}
}

View File

@ -74,6 +74,12 @@ public class RecordController {
return success(BeanUtils.toBean(pageResult, RecordRespVO.class)); return success(BeanUtils.toBean(pageResult, RecordRespVO.class));
} }
@GetMapping("/statistics")
@Operation(summary = "统计会员回访记录")
public CommonResult<RecordStatisticsRespVO> getRecordStatistics(@Valid RecordStatisticsReqVO statisticsReqVO) {
return success(recordService.getRecordStatistics(statisticsReqVO));
}
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出会员回访记录 Excel") @Operation(summary = "导出会员回访记录 Excel")
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.system.controller.admin.record.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 会员回访记录统计 Request VO")
@Data
public class RecordStatisticsReqVO {
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
@Schema(description = "机构ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12205")
@NotNull(message = "机构ID不能为空")
private Integer orgid;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.system.controller.admin.record.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.time.LocalDate;
@Schema(description = "管理后台 - 会员回访记录统计 Response VO")
@Data
public class RecordStatisticsRespVO {
@Schema(description = "总数量", example = "100")
private Long totalCount;
@Schema(description = "已回访数量", example = "80")
private Long visitedCount;
@Schema(description = "未回访数量", example = "20")
private Long unvisitedCount;
@Schema(description = "按日期分组的回访记录数据")
private List<DailyRecordData> dailyData;
@Schema(description = "按日期分组的回访记录数据")
@Data
public static class DailyRecordData {
@Schema(description = "日期", example = "2024-01-01")
private LocalDate date;
@Schema(description = "该日期的回访总数", example = "10")
private Long totalCount;
@Schema(description = "该日期的已回访数量", example = "8")
private Long visitedCount;
@Schema(description = "该日期的未回访数量", example = "2")
private Long unvisitedCount;
}
}

View File

@ -8,7 +8,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.alertmessage.AlertMessageDO; import cn.iocoder.yudao.module.system.dal.dataobject.alertmessage.AlertMessageDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo.*; import cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo.*;
import java.time.LocalDateTime;
import java.time.LocalDate;
/** /**
* 预警信息 Mapper * 预警信息 Mapper
@ -35,4 +39,20 @@ public interface AlertMessageMapper extends BaseMapperX<AlertMessageDO> {
.orderByDesc(AlertMessageDO::getId)); .orderByDesc(AlertMessageDO::getId));
} }
/**
* 按日期分组查询预警信息统计
*/
@Select("SELECT DATE(createtime) as date, " +
"COUNT(*) as totalCount, " +
"SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as readCount, " +
"SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as unreadCount " +
"FROM tb_alert_message " +
"WHERE orgid = #{orgid} " +
"AND createtime BETWEEN #{startTime} AND #{endTime} " +
"GROUP BY DATE(createtime) " +
"ORDER BY date")
List<Map<String, Object>> selectDailyStatistics(@Param("orgid") Integer orgid,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
} }

View File

@ -8,7 +8,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.record.RecordDO; import cn.iocoder.yudao.module.system.dal.dataobject.record.RecordDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import cn.iocoder.yudao.module.system.controller.admin.record.vo.*; import cn.iocoder.yudao.module.system.controller.admin.record.vo.*;
import java.time.LocalDateTime;
import java.time.LocalDate;
/** /**
* 会员回访记录 Mapper * 会员回访记录 Mapper
@ -38,4 +42,20 @@ public interface RecordMapper extends BaseMapperX<RecordDO> {
.orderByDesc(RecordDO::getId)); .orderByDesc(RecordDO::getId));
} }
/**
* 按日期分组查询会员回访记录统计
*/
@Select("SELECT DATE(createtime) as date, " +
"COUNT(*) as totalCount, " +
"SUM(CASE WHEN visitstatus = 1 THEN 1 ELSE 0 END) as visitedCount, " +
"SUM(CASE WHEN visitstatus = 0 THEN 1 ELSE 0 END) as unvisitedCount " +
"FROM visit_record " +
"WHERE orgid = #{orgid} " +
"AND createtime BETWEEN #{startTime} AND #{endTime} " +
"GROUP BY DATE(createtime) " +
"ORDER BY date")
List<Map<String, Object>> selectDailyStatistics(@Param("orgid") Integer orgid,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
} }

View File

@ -57,4 +57,12 @@ public interface AlertMessageService {
*/ */
PageResult<AlertMessageDO> getAlertMessagePage(AlertMessagePageReqVO pageReqVO); PageResult<AlertMessageDO> getAlertMessagePage(AlertMessagePageReqVO pageReqVO);
/**
* 统计预警信息
*
* @param statisticsReqVO 统计请求参数
* @return 统计结果
*/
AlertMessageStatisticsRespVO getAlertMessageStatistics(@Valid AlertMessageStatisticsReqVO statisticsReqVO);
} }

View File

@ -5,6 +5,7 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.*; import java.util.*;
import java.time.LocalDate;
import cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo.*; import cn.iocoder.yudao.module.system.controller.admin.alertmessage.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.alertmessage.AlertMessageDO; import cn.iocoder.yudao.module.system.dal.dataobject.alertmessage.AlertMessageDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -81,4 +82,66 @@ public class AlertMessageServiceImpl implements AlertMessageService {
return alertMessageMapper.selectPage(pageReqVO); return alertMessageMapper.selectPage(pageReqVO);
} }
@Override
public AlertMessageStatisticsRespVO getAlertMessageStatistics(AlertMessageStatisticsReqVO statisticsReqVO) {
// 创建查询条件
LambdaQueryWrapper<AlertMessageDO> queryWrapper = new LambdaQueryWrapper<>();
// 添加时间范围条件
queryWrapper.between(AlertMessageDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime());
// 添加机构ID条件
queryWrapper.eq(AlertMessageDO::getOrgid, statisticsReqVO.getOrgid());
// 查询总数量
Long totalCount = alertMessageMapper.selectCount(queryWrapper);
// 查询已读数量
LambdaQueryWrapper<AlertMessageDO> readQueryWrapper = new LambdaQueryWrapper<>();
readQueryWrapper.between(AlertMessageDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime())
.eq(AlertMessageDO::getOrgid, statisticsReqVO.getOrgid())
.eq(AlertMessageDO::getStatus, 1); // status = 1 表示已读
Long readCount = alertMessageMapper.selectCount(readQueryWrapper);
// 查询未读数量
LambdaQueryWrapper<AlertMessageDO> unreadQueryWrapper = new LambdaQueryWrapper<>();
unreadQueryWrapper.between(AlertMessageDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime())
.eq(AlertMessageDO::getOrgid, statisticsReqVO.getOrgid())
.eq(AlertMessageDO::getStatus, 0); // status = 0 表示未读
Long unreadCount = alertMessageMapper.selectCount(unreadQueryWrapper);
// 查询按日期分组的数据
List<Map<String, Object>> dailyStatistics = alertMessageMapper.selectDailyStatistics(
statisticsReqVO.getOrgid(),
statisticsReqVO.getStartTime(),
statisticsReqVO.getEndTime()
);
// 转换按日期分组的数据
List<AlertMessageStatisticsRespVO.DailyAlertData> dailyData = new ArrayList<>();
for (Map<String, Object> stat : dailyStatistics) {
AlertMessageStatisticsRespVO.DailyAlertData dailyAlertData = new AlertMessageStatisticsRespVO.DailyAlertData();
// 处理日期类型转换
Object dateObj = stat.get("date");
if (dateObj instanceof java.sql.Date) {
dailyAlertData.setDate(((java.sql.Date) dateObj).toLocalDate());
} else if (dateObj instanceof LocalDate) {
dailyAlertData.setDate((LocalDate) dateObj);
}
dailyAlertData.setTotalCount(((Number) stat.get("totalCount")).longValue());
dailyAlertData.setReadCount(((Number) stat.get("readCount")).longValue());
dailyAlertData.setUnreadCount(((Number) stat.get("unreadCount")).longValue());
dailyData.add(dailyAlertData);
}
// 构建返回结果
AlertMessageStatisticsRespVO result = new AlertMessageStatisticsRespVO();
result.setTotalCount(totalCount);
result.setReadCount(readCount);
result.setUnreadCount(unreadCount);
result.setDailyData(dailyData);
return result;
}
} }

View File

@ -52,4 +52,12 @@ public interface RecordService {
*/ */
PageResult<RecordDO> getRecordPage(RecordPageReqVO pageReqVO); PageResult<RecordDO> getRecordPage(RecordPageReqVO pageReqVO);
/**
* 统计会员回访记录
*
* @param statisticsReqVO 统计请求参数
* @return 统计结果
*/
RecordStatisticsRespVO getRecordStatistics(@Valid RecordStatisticsReqVO statisticsReqVO);
} }

View File

@ -7,6 +7,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.time.LocalDate;
import cn.iocoder.yudao.module.system.controller.admin.record.vo.*; import cn.iocoder.yudao.module.system.controller.admin.record.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.record.RecordDO; import cn.iocoder.yudao.module.system.dal.dataobject.record.RecordDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -17,6 +18,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.record.RecordMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
/** /**
* 会员回访记录 Service 实现类 * 会员回访记录 Service 实现类
@ -72,4 +74,66 @@ public class RecordServiceImpl implements RecordService {
return recordMapper.selectPage(pageReqVO); return recordMapper.selectPage(pageReqVO);
} }
@Override
public RecordStatisticsRespVO getRecordStatistics(RecordStatisticsReqVO statisticsReqVO) {
// 创建查询条件
LambdaQueryWrapper<RecordDO> queryWrapper = new LambdaQueryWrapper<>();
// 添加时间范围条件
queryWrapper.between(RecordDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime());
// 添加机构ID条件
queryWrapper.eq(RecordDO::getOrgid, statisticsReqVO.getOrgid());
// 查询总数量
Long totalCount = recordMapper.selectCount(queryWrapper);
// 查询已回访数量
LambdaQueryWrapper<RecordDO> visitedQueryWrapper = new LambdaQueryWrapper<>();
visitedQueryWrapper.between(RecordDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime())
.eq(RecordDO::getOrgid, statisticsReqVO.getOrgid())
.eq(RecordDO::getVisitstatus, 1); // visitstatus = 1 表示已回访
Long visitedCount = recordMapper.selectCount(visitedQueryWrapper);
// 查询未回访数量
LambdaQueryWrapper<RecordDO> unvisitedQueryWrapper = new LambdaQueryWrapper<>();
unvisitedQueryWrapper.between(RecordDO::getCreatetime, statisticsReqVO.getStartTime(), statisticsReqVO.getEndTime())
.eq(RecordDO::getOrgid, statisticsReqVO.getOrgid())
.eq(RecordDO::getVisitstatus, 0); // visitstatus = 0 表示未回访
Long unvisitedCount = recordMapper.selectCount(unvisitedQueryWrapper);
// 查询按日期分组的数据
List<Map<String, Object>> dailyStatistics = recordMapper.selectDailyStatistics(
statisticsReqVO.getOrgid(),
statisticsReqVO.getStartTime(),
statisticsReqVO.getEndTime()
);
// 转换按日期分组的数据
List<RecordStatisticsRespVO.DailyRecordData> dailyData = new ArrayList<>();
for (Map<String, Object> stat : dailyStatistics) {
RecordStatisticsRespVO.DailyRecordData dailyRecordData = new RecordStatisticsRespVO.DailyRecordData();
// 处理日期类型转换
Object dateObj = stat.get("date");
if (dateObj instanceof java.sql.Date) {
dailyRecordData.setDate(((java.sql.Date) dateObj).toLocalDate());
} else if (dateObj instanceof LocalDate) {
dailyRecordData.setDate((LocalDate) dateObj);
}
dailyRecordData.setTotalCount(((Number) stat.get("totalCount")).longValue());
dailyRecordData.setVisitedCount(((Number) stat.get("visitedCount")).longValue());
dailyRecordData.setUnvisitedCount(((Number) stat.get("unvisitedCount")).longValue());
dailyData.add(dailyRecordData);
}
// 构建返回结果
RecordStatisticsRespVO result = new RecordStatisticsRespVO();
result.setTotalCount(totalCount);
result.setVisitedCount(visitedCount);
result.setUnvisitedCount(unvisitedCount);
result.setDailyData(dailyData);
return result;
}
} }