首页新增通知公告消息提醒

This commit is contained in:
RuoYi
2026-03-20 10:36:10 +08:00
parent f80143eccb
commit 5b52281fe1
13 changed files with 677 additions and 10 deletions

View File

@@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.xss.Xss;
@@ -31,6 +32,10 @@ public class SysNotice extends BaseEntity
/** 公告状态0正常 1关闭 */
private String status;
/** 是否已读 */
@JsonProperty("isRead")
private boolean isRead;
public Long getNoticeId()
{
return noticeId;
@@ -84,6 +89,16 @@ public class SysNotice extends BaseEntity
return status;
}
public boolean getIsRead()
{
return isRead;
}
public void setIsRead(boolean isRead)
{
this.isRead = isRead;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@@ -0,0 +1,76 @@
package com.ruoyi.system.domain;
import java.util.Date;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 公告已读记录表 sys_notice_read
*
* @author ruoyi
*/
public class SysNoticeRead
{
/** 主键 */
private Long readId;
/** 公告ID */
private Long noticeId;
/** 用户ID */
private Long userId;
/** 阅读时间 */
private Date readTime;
public Long getReadId()
{
return readId;
}
public void setReadId(Long readId)
{
this.readId = readId;
}
public Long getNoticeId()
{
return noticeId;
}
public void setNoticeId(Long noticeId)
{
this.noticeId = noticeId;
}
public Long getUserId()
{
return userId;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public Date getReadTime()
{
return readTime;
}
public void setReadTime(Date readTime)
{
this.readTime = readTime;
}
@Override
public String toString()
{
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("readId", getReadId())
.append("noticeId", getNoticeId())
.append("userId", getUserId())
.append("readTime", getReadTime())
.toString();
}
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.ruoyi.system.domain.SysNoticeRead;
import com.ruoyi.system.domain.SysNotice;
/**
* 公告已读记录 数据层
*
* @author ruoyi
*/
public interface SysNoticeReadMapper
{
/**
* 新增已读记录(忽略重复)
*
* @param noticeRead 已读记录
* @return 结果
*/
public int insertNoticeRead(SysNoticeRead noticeRead);
/**
* 查询某用户未读公告数量
*
* @param userId 用户ID
* @return 未读数量
*/
public int selectUnreadCount(@Param("userId") Long userId);
/**
* 查询某用户是否已读某公告
*
* @param noticeId 公告ID
* @param userId 用户ID
* @return 已读记录数0未读 1已读
*/
public int selectIsRead(@Param("noticeId") Long noticeId, @Param("userId") Long userId);
/**
* 批量标记已读
*
* @param userId 用户ID
* @param noticeIds 公告ID数组
* @return 结果
*/
public int insertNoticeReadBatch(@Param("userId") Long userId, @Param("noticeIds") Long[] noticeIds);
/**
* 查询带已读状态的公告列表SQL层限制条数一次查询完成
*
* @param userId 用户ID
* @param limit 最多返回条数
* @return 带 isRead 标记的公告列表
*/
public List<SysNotice> selectNoticeListWithReadStatus(@Param("userId") Long userId, @Param("limit") int limit);
/**
* 公告删除时清理对应已读记录
*
* @param noticeIds 公告ID数组
* @return 结果
*/
public int deleteByNoticeIds(@Param("noticeIds") Long[] noticeIds);
}

View File

@@ -0,0 +1,52 @@
package com.ruoyi.system.service;
import java.util.List;
import com.ruoyi.system.domain.SysNotice;
/**
* 公告已读记录 服务层
*
* @author ruoyi
*/
public interface ISysNoticeReadService
{
/**
* 标记已读(幂等,重复调用不报错)
*
* @param noticeId 公告ID
* @param userId 用户ID
*/
public void markRead(Long noticeId, Long userId);
/**
* 查询某用户未读公告数量
*
* @param userId 用户ID
* @return 未读数量
*/
public int selectUnreadCount(Long userId);
/**
* 查询公告列表并标记当前用户已读状态(用于首页展示)
*
* @param userId 用户ID
* @param limit 最多返回条数
* @return 带 isRead 标记的公告列表
*/
public List<SysNotice> selectNoticeListWithReadStatus(Long userId, int limit);
/**
* 批量标记已读
*
* @param userId 用户ID
* @param noticeIds 公告ID数组
*/
public void markReadBatch(Long userId, Long[] noticeIds);
/**
* 删除公告时清理对应已读记录
*
* @param noticeIds 公告ID数组
*/
public void deleteByNoticeIds(Long[] noticeIds);
}

View File

@@ -0,0 +1,73 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.SysNoticeRead;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.mapper.SysNoticeReadMapper;
import com.ruoyi.system.service.ISysNoticeReadService;
/**
* 公告已读记录 服务层实现
*
* @author ruoyi
*/
@Service
public class SysNoticeReadServiceImpl implements ISysNoticeReadService
{
@Autowired
private SysNoticeReadMapper noticeReadMapper;
/**
* 标记已读
*/
@Override
public void markRead(Long noticeId, Long userId)
{
SysNoticeRead record = new SysNoticeRead();
record.setNoticeId(noticeId);
record.setUserId(userId);
noticeReadMapper.insertNoticeRead(record);
}
/**
* 查询某用户未读公告数量
*/
@Override
public int selectUnreadCount(Long userId)
{
return noticeReadMapper.selectUnreadCount(userId);
}
/**
* 查询公告列表并标记当前用户已读状态
*/
@Override
public List<SysNotice> selectNoticeListWithReadStatus(Long userId, int limit)
{
return noticeReadMapper.selectNoticeListWithReadStatus(userId, limit);
}
/**
* 批量标记已读
*/
@Override
public void markReadBatch(Long userId, Long[] noticeIds)
{
if (noticeIds == null || noticeIds.length == 0)
{
return;
}
noticeReadMapper.insertNoticeReadBatch(userId, noticeIds);
}
/**
* 删除公告时清理对应已读记录
*/
@Override
public void deleteByNoticeIds(Long[] noticeIds)
{
noticeReadMapper.deleteByNoticeIds(noticeIds);
}
}

View File

@@ -40,6 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND create_by like concat('%', #{createBy}, '%')
</if>
</where>
order by notice_id desc
</select>
<insert id="insertNotice" parameterType="SysNotice">

View File

@@ -0,0 +1,66 @@
<?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.system.mapper.SysNoticeReadMapper">
<resultMap type="SysNoticeRead" id="SysNoticeReadResult">
<id property="readId" column="read_id" />
<result property="noticeId" column="notice_id" />
<result property="userId" column="user_id" />
<result property="readTime" column="read_time" />
</resultMap>
<!-- 新增已读记录 -->
<insert id="insertNoticeRead" parameterType="SysNoticeRead">
insert ignore into sys_notice_read (notice_id, user_id, read_time)
values (#{noticeId}, #{userId}, sysdate())
</insert>
<!-- 查询未读数量:正常状态公告 减去 当前用户已读数 -->
<select id="selectUnreadCount" resultType="int">
select count(*) from sys_notice n
where n.status = '0' and not exists (select 1 from sys_notice_read r where r.notice_id = n.notice_id and r.user_id = #{userId})
</select>
<!-- 查询是否已读 -->
<select id="selectIsRead" resultType="int">
select count(*) from sys_notice_read where notice_id = #{noticeId} and user_id = #{userId}
</select>
<!-- 查询带已读状态的公告列表直接在SQL中限制条数 -->
<select id="selectNoticeListWithReadStatus" resultType="SysNotice">
select
n.notice_id as noticeId,
n.notice_title as noticeTitle,
n.notice_type as noticeType,
n.status,
n.create_by as createBy,
n.create_time as createTime,
case when r.notice_id is not null then true else false end as isRead
from sys_notice n
left join sys_notice_read r
on r.notice_id = n.notice_id and r.user_id = #{userId}
where n.status = '0'
order by n.notice_id desc
limit #{limit}
</select>
<!-- 批量标记已读 -->
<insert id="insertNoticeReadBatch">
insert ignore into sys_notice_read (notice_id, user_id, read_time)
values
<foreach collection="noticeIds" item="noticeId" separator=",">
(#{noticeId}, #{userId}, sysdate())
</foreach>
</insert>
<!-- 删除公告时清理已读记录 -->
<delete id="deleteByNoticeIds">
delete from sys_notice_read where notice_id in
<foreach collection="noticeIds" item="noticeId" open="(" separator="," close=")">
#{noticeId}
</foreach>
</delete>
</mapper>