From 6b13ab307a525a46b2d06da477081c60a4063b58 Mon Sep 17 00:00:00 2001
From: wanghao
Date: Thu, 5 Feb 2026 19:18:12 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B6=88=E6=81=AF=E9=80=9A=E7=9F=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
db/updatesql/20260205-xj-system新增表.sql | 35 ++
.../org/jeecg/constant/NoticeConstants.java | 44 ++
.../system/mapper/SysDepartMapper.java | 12 +
.../modules/system/mapper/SysUserMapper.java | 8 +
.../system/mapper/xml/SysDepartMapper.xml | 11 +
.../system/mapper/xml/SysUserMapper.xml | 10 +
.../SysMessageNoticeAppController.java | 53 +++
.../SysMessageNoticeController.java | 119 ++++++
.../mapper/SysMessageNoticeMapper.java | 14 +
.../mapper/SysMessageNoticeScopeMapper.java | 16 +
.../model/dto/SysMessageNoticeDTO.java | 29 ++
.../message/model/po/SysMessageNotice.java | 137 ++++++
.../model/po/SysMessageNoticeScope.java | 66 +++
.../model/query/SysMessageNoticeQuery.java | 45 ++
.../message/model/vo/SysMessageNoticeVO.java | 36 ++
.../ISysMessageNoticeScopeService.java | 14 +
.../service/ISysMessageNoticeService.java | 78 ++++
.../SysMessageNoticeScopeServiceImpl.java | 18 +
.../impl/SysMessageNoticeServiceImpl.java | 393 ++++++++++++++++++
19 files changed, 1138 insertions(+)
create mode 100644 db/updatesql/20260205-xj-system新增表.sql
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/constant/NoticeConstants.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeAppController.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeController.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeMapper.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeScopeMapper.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/dto/SysMessageNoticeDTO.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNotice.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNoticeScope.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/query/SysMessageNoticeQuery.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/vo/SysMessageNoticeVO.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeScopeService.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeService.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeScopeServiceImpl.java
create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeServiceImpl.java
diff --git a/db/updatesql/20260205-xj-system新增表.sql b/db/updatesql/20260205-xj-system新增表.sql
new file mode 100644
index 0000000..780c6d0
--- /dev/null
+++ b/db/updatesql/20260205-xj-system新增表.sql
@@ -0,0 +1,35 @@
+-- 消息通知表
+CREATE TABLE `sys_message_notice` (
+ `id` varchar(32) NOT NULL COMMENT 'id',
+ `title` varchar(255) DEFAULT NULL COMMENT '标题',
+ `content` text COMMENT '内容',
+ `scope_type` int(2) DEFAULT NULL COMMENT '范围(1-指定部门,2-指定人群,3-既指定部门又指定人群)',
+ `org_code` varchar(100) DEFAULT NULL COMMENT '创建机构',
+ `notice_status` int(2) DEFAULT '1' COMMENT '通知状态(0:否 1:是)',
+ `start_time` datetime DEFAULT NULL COMMENT '通知开始时间',
+ `end_time` datetime DEFAULT NULL COMMENT '通知结束时间',
+ `del_flag` varchar(1) DEFAULT '0' COMMENT '删除状态(0-正常,1-已删除)',
+ `create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_org_code` (`org_code`),
+ KEY `idx_notice_status` (`notice_status`),
+ KEY `idx_start_time` (`start_time`),
+ KEY `idx_end_time` (`end_time`),
+ KEY `idx_del_flag` (`del_flag`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息通知表';
+
+-- 消息通知范围表
+CREATE TABLE `sys_message_notice_scope` (
+ `id` varchar(32) NOT NULL COMMENT 'id',
+ `notice_id` varchar(32) NOT NULL COMMENT '消息id',
+ `type` int(2) DEFAULT NULL COMMENT '类别(1-指定部门,2-指定人群)',
+ `scope_id` varchar(100) DEFAULT NULL COMMENT '限制范围标识(如:部门Code,人员ID)',
+ `record` varchar(255) DEFAULT NULL COMMENT '记录值(例:部门名称,人员名称)',
+ PRIMARY KEY (`id`),
+ KEY `idx_notice_id` (`notice_id`),
+ KEY `idx_type` (`type`),
+ KEY `idx_scope_id` (`scope_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息通知范围表';
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/constant/NoticeConstants.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/constant/NoticeConstants.java
new file mode 100644
index 0000000..316e8c8
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/constant/NoticeConstants.java
@@ -0,0 +1,44 @@
+package org.jeecg.constant;
+
+/**
+ * 消息通知常量
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+public interface NoticeConstants {
+ /**
+ * 通知范围类型 - 指定部门
+ */
+ Integer NOTICE_SCOPE_TYPE_DEPART = 1;
+
+ /**
+ * 通知范围类型 - 指定人群
+ */
+ Integer NOTICE_SCOPE_TYPE_PEOPLE = 2;
+
+ /**
+ * 通知范围类型 - 既指定部门又指定人群
+ */
+ Integer NOTICE_SCOPE_TYPE_BOTH = 3;
+
+ /**
+ * 查询来源 - 后台管理
+ */
+ Integer QUERY_SOURCE_ADMIN = 0;
+
+ /**
+ * 查询来源 - 移动端
+ */
+ Integer QUERY_SOURCE_APP = 1;
+
+ /**
+ * 通知状态 - 不显示
+ */
+ Integer NOTICE_STATUS_HIDE = 0;
+
+ /**
+ * 通知状态 - 显示
+ */
+ Integer NOTICE_STATUS_SHOW = 1;
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDepartMapper.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDepartMapper.java
index 29370fe..2c4e0f8 100644
--- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDepartMapper.java
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysDepartMapper.java
@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.jeecg.common.system.bean.response.BaseUser;
@@ -13,6 +15,8 @@ import org.jeecg.modules.system.entity.SysUser;
import org.springframework.data.repository.query.Param;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
*
@@ -22,6 +26,7 @@ import java.util.List;
* @Author: Steve
* @Since: 2019-01-22
*/
+@Mapper
public interface SysDepartMapper extends BaseMapper {
/**
@@ -167,4 +172,11 @@ public interface SysDepartMapper extends BaseMapper {
List selectDepartByDepartIds(String departId);
SysDepartGps selectDepartGpsByDepartId(String departId);
+
+ /**
+ * 根据部门编码集合查询部门名称映射
+ * @param orgCodes 部门编码集合
+ * @return Map
+ */
+ List selectNameByCodes(@Param("orgCodes") Set orgCodes);
}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java
index 6f4ee29..4b7be79 100644
--- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java
@@ -417,4 +417,12 @@ public interface SysUserMapper extends BaseMapper, MPJBaseMapper getUserInfoByTypeCode(@Param("findCode") String findCode,
@Param("findType") String findType);
+
+
+ /**
+ * 根据用户id集合查询用户昵称映射
+ * @param userIds 用户id集合
+ * @return Map
+ */
+ List selectNameByIds(@Param("userIds") Set userIds);
}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDepartMapper.xml b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDepartMapper.xml
index e88fec0..5955d8f 100644
--- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDepartMapper.xml
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDepartMapper.xml
@@ -177,4 +177,15 @@
depart_id as "departId"
from sys_depart_gps where depart_id = #{departId}
+
+
+
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
index 41bf2d5..9a599f4 100644
--- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
@@ -1241,4 +1241,14 @@
ORDER BY processed_group;
+
+
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeAppController.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeAppController.java
new file mode 100644
index 0000000..e15ad0e
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeAppController.java
@@ -0,0 +1,53 @@
+package org.jeecg.modules.system.message.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.model.query.SysMessageNoticeQuery;
+import org.jeecg.modules.system.message.model.vo.SysMessageNoticeVO;
+import org.jeecg.modules.system.message.service.ISysMessageNoticeService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 消息通知 移动端Controller
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Tag(name = "消息通知/移动端")
+@RestController
+@RequestMapping("/app/sys/message/notice")
+@Slf4j
+@RequiredArgsConstructor
+public class SysMessageNoticeAppController extends JeecgController {
+
+ private final ISysMessageNoticeService sysMessageNoticeService;
+
+ /**
+ * 分页列表查询
+ */
+ @Operation(summary = "消息通知-分页列表查询", description = "消息通知-分页列表查询")
+ @GetMapping(value = "/list")
+ public Result> queryPageList(SysMessageNoticeQuery query,
+ @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+ @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
+ Page page = new Page<>(pageNo, pageSize);
+ return Result.OK(sysMessageNoticeService.queryPageAppList(query,page));
+ }
+
+ /**
+ * 通过id查询
+ */
+ @Operation(summary = "消息通知-通过id查询", description = "消息通知-通过id查询")
+ @GetMapping(value = "/queryById")
+ public Result queryById(@RequestParam(name = "id", required = true) String id) {
+ return Result.OK(sysMessageNoticeService.getNoticeById(id));
+ }
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeController.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeController.java
new file mode 100644
index 0000000..fdb53a8
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/controller/SysMessageNoticeController.java
@@ -0,0 +1,119 @@
+package org.jeecg.modules.system.message.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.modules.system.message.model.dto.SysMessageNoticeDTO;
+import org.jeecg.modules.system.message.model.query.SysMessageNoticeQuery;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.model.vo.SysMessageNoticeVO;
+import org.jeecg.modules.system.message.service.ISysMessageNoticeService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+
+/**
+ * 消息通知 Controller
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Tag(name = "消息通知/后台")
+@RestController
+@RequestMapping("/sys/message/notice")
+@Slf4j
+@RequiredArgsConstructor
+public class SysMessageNoticeController extends JeecgController {
+
+ private final ISysMessageNoticeService sysMessageNoticeService;
+
+ /**
+ * 分页列表查询
+ */
+ @Operation(summary = "消息通知-分页列表查询", description = "消息通知-分页列表查询")
+ @GetMapping(value = "/list")
+ public Result> queryPageList(SysMessageNoticeQuery query,
+ @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+ @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
+ Page page = new Page<>(pageNo, pageSize);
+ return Result.OK(sysMessageNoticeService.queryPageList(query,page));
+ }
+
+ /**
+ * 添加
+ */
+ @AutoLog(value = "消息通知-添加")
+ @Operation(summary = "消息通知-添加", description = "消息通知-添加")
+ @PostMapping(value = "/add")
+ public Result add(@RequestBody SysMessageNoticeDTO dto) {
+ sysMessageNoticeService.add(dto);
+ return Result.OK("添加成功!");
+ }
+
+ /**
+ * 编辑
+ */
+ @AutoLog(value = "消息通知-编辑")
+ @Operation(summary = "消息通知-编辑", description = "消息通知-编辑")
+ @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
+ public Result edit(@RequestBody SysMessageNoticeDTO dto) {
+ sysMessageNoticeService.edit(dto);
+ return Result.OK("编辑成功!");
+ }
+
+ /**
+ * 通过id删除
+ */
+ @AutoLog(value = "消息通知-通过id删除")
+ @Operation(summary = "消息通知-通过id删除", description = "消息通知-通过id删除")
+ @DeleteMapping(value = "/delete")
+ public Result delete(@RequestParam(name = "id", required = true) String id) {
+ sysMessageNoticeService.deleteNotice(id);
+ return Result.OK("删除成功!");
+ }
+
+ /**
+ * 批量删除
+ */
+ @AutoLog(value = "消息通知-批量删除")
+ @Operation(summary = "消息通知-批量删除", description = "消息通知-批量删除")
+ @DeleteMapping(value = "/deleteBatch")
+ public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
+ sysMessageNoticeService.deleteBatchNotice(Arrays.asList(ids.split(",")));
+ return Result.OK("批量删除成功!");
+ }
+
+ /**
+ * 通过id查询
+ */
+ @Operation(summary = "消息通知-通过id查询", description = "消息通知-通过id查询")
+ @GetMapping(value = "/queryById")
+ public Result queryById(@RequestParam(name = "id", required = true) String id) {
+ return Result.OK(sysMessageNoticeService.getNoticeById(id));
+ }
+
+ /**
+ * 导出excel
+ */
+ @RequestMapping(value = "/exportXls")
+ public ModelAndView exportXls(HttpServletRequest request, SysMessageNotice sysMessageNotice) {
+ return super.exportXls(request, sysMessageNotice, SysMessageNotice.class, "消息通知");
+ }
+
+ /**
+ * 导入excel
+ */
+ @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+ public Result> importExcel(HttpServletRequest request, HttpServletResponse response) {
+ return super.importExcel(request, response, SysMessageNotice.class);
+ }
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeMapper.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeMapper.java
new file mode 100644
index 0000000..75a81b8
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeMapper.java
@@ -0,0 +1,14 @@
+package org.jeecg.modules.system.message.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+
+/**
+ * 消息通知 Mapper
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+public interface SysMessageNoticeMapper extends BaseMapper {
+
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeScopeMapper.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeScopeMapper.java
new file mode 100644
index 0000000..381014c
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/mapper/SysMessageNoticeScopeMapper.java
@@ -0,0 +1,16 @@
+package org.jeecg.modules.system.message.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+
+/**
+ * 消息通知范围 Mapper
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Mapper
+public interface SysMessageNoticeScopeMapper extends BaseMapper {
+
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/dto/SysMessageNoticeDTO.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/dto/SysMessageNoticeDTO.java
new file mode 100644
index 0000000..7b6b6fd
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/dto/SysMessageNoticeDTO.java
@@ -0,0 +1,29 @@
+package org.jeecg.modules.system.message.model.dto;
+
+import cn.hutool.core.bean.BeanUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+
+import java.util.List;
+
+/**
+ * 消息通知数据传输对象
+ * 用于接收前端传递的消息通知数据,包含范围信息
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SysMessageNoticeDTO extends SysMessageNotice {
+ /**
+ * 指定机构
+ */
+ private List departScopeList;
+ /**
+ * 指定人群
+ */
+ private List userScopeList;
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNotice.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNotice.java
new file mode 100644
index 0000000..d6892fd
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNotice.java
@@ -0,0 +1,137 @@
+package org.jeecg.modules.system.message.model.po;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 消息通知实体类
+ *
+ * 用于系统消息通知的管理,支持在移动端首页顶部显示通知信息。
+ * 主要功能包括:
+ *
+ * - 支持按部门、人群或两者组合的方式指定通知范围
+ * - 支持设置通知的有效时间范围(开始时间和结束时间)
+ * - 支持通知状态控制,决定是否在移动端首页显示
+ * - 支持逻辑删除,保留历史通知记录
+ *
+ *
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Data
+@TableName("sys_message_notice")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(title = "sys_message_notice对象", description = "消息通知")
+public class SysMessageNotice implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ @Schema(title = "id")
+ private String id;
+
+ /**
+ * 标题
+ */
+ @Excel(name = "标题", width = 15)
+ @Schema(title = "标题")
+ private String title;
+
+ /**
+ * 内容
+ */
+ @Excel(name = "内容", width = 15)
+ @Schema(title = "内容")
+ private String content;
+
+ /**
+ * 范围(1-指定部门,2-指定人群,3-既指定部门又指定人群)
+ */
+ @Schema(title = "范围")
+ private Integer scopeType;
+
+ /**
+ * 创建机构
+ */
+ @Schema(title = "创建机构")
+ private String orgCode;
+
+ /**
+ * 公告状态(0:否 1:是)
+ * 冗余字段 用于移动端首页是否在顶部显示通知 目前说是创建的通知都显示 默认1
+ */
+ @Schema(title = "通知状态")
+ private Integer noticeStatus;
+
+ /**
+ * 通知开始时间
+ * 用于移动端首页顶部通知显示时效范围的起始时间
+ * 目前说是都是凌晨发布通知 为了防止可能会存在任意时间发布 格式化为 yyyy-MM-dd HH:mm:ss
+ * HH:mm:ss 则填0
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Schema(title = "通知开始时间")
+ private Date startTime;
+
+ /**
+ * 通知结束时间
+ * 用于移动端首页顶部通知显示时效范围的停止时间
+ * 目前说是都是凌晨发布通知 为了防止可能会存在任意时间发布 格式化为 yyyy-MM-dd HH:mm:ss
+ * HH:mm:ss 则填0
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Schema(title = "通知结束时间")
+ private Date endTime;
+
+ /**
+ * 删除状态(0-正常,1-已删除)
+ */
+ @Excel(name = "删除状态(0-正常,1-已删除)", width = 15)
+ @Schema(title = "删除状态(0-正常,1-已删除)")
+ @TableLogic
+ private String delFlag;
+
+ /**
+ * 创建人
+ */
+ @Schema(title = "创建人")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Schema(title = "创建时间")
+ private Date createTime;
+
+ /**
+ * 更新人
+ */
+ @Schema(title = "更新人")
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Schema(title = "更新时间")
+ private Date updateTime;
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNoticeScope.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNoticeScope.java
new file mode 100644
index 0000000..daa9517
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/po/SysMessageNoticeScope.java
@@ -0,0 +1,66 @@
+package org.jeecg.modules.system.message.model.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 消息通知范围实体类
+ *
+ * 用于记录消息通知的发送范围,与消息通知表(sys_message_notice)关联。
+ * 支持两种范围类型:
+ *
+ * - 指定部门:记录部门Code和部门名称
+ * - 指定人群:记录人员ID和人员名称
+ *
+ * 一条消息通知可以对应多条范围记录,实现灵活的消息推送控制。
+ *
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Data
+@TableName("sys_message_notice_scope")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(title = "sys_message_notice_scope对象", description = "消息范围")
+public class SysMessageNoticeScope implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ @Schema(title = "id")
+ private String id;
+
+ /**
+ * 消息id
+ */
+ @Schema(title = "消息id")
+ private String noticeId;
+
+ /**
+ * 类别 1-指定部门,2-指定人群
+ */
+ @Schema(title = "类别")
+ private Integer type;
+
+ /**
+ * 限制范围标识(如:部门Code,人员ID)
+ */
+ @Schema(title = "限制范围标识")
+ private String scopeId;
+
+ /**
+ * 记录值(例:部门名称,人员名称)
+ */
+ @Schema(title = "记录值")
+ private String record;
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/query/SysMessageNoticeQuery.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/query/SysMessageNoticeQuery.java
new file mode 100644
index 0000000..3807a37
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/query/SysMessageNoticeQuery.java
@@ -0,0 +1,45 @@
+package org.jeecg.modules.system.message.model.query;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 消息通知查询参数对象
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Data
+public class SysMessageNoticeQuery {
+ /**
+ * 通知标题
+ */
+ @Schema(title = "通知标题")
+ private String title;
+
+ /**
+ * 通知范围(1:指定机构 2:指定人员)
+ */
+ @Schema(title = "通知范围(1:指定机构 2:指定人员)")
+ private String scopeType;
+
+ /**
+ * 发布日期开始
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Schema(title = "发布日期开始")
+ private Date startDate;
+
+ /**
+ * 发布日期结束
+ */
+ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @Schema(title = "发布日期结束")
+ private Date endDate;
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/vo/SysMessageNoticeVO.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/vo/SysMessageNoticeVO.java
new file mode 100644
index 0000000..36f5e43
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/model/vo/SysMessageNoticeVO.java
@@ -0,0 +1,36 @@
+package org.jeecg.modules.system.message.model.vo;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+
+import java.util.List;
+
+/**
+ * 消息通知视图对象
+ * 用于返回给前端的消息通知数据,包含范围信息
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SysMessageNoticeVO extends SysMessageNotice {
+ /**
+ * 指定机构
+ */
+ private List departScopeList;
+ /**
+ * 指定人群
+ */
+ private List userScopeList;
+
+ public SysMessageNoticeVO() {}
+
+ public SysMessageNoticeVO(SysMessageNotice sysMessageNotice) {
+ BeanUtil.copyProperties(sysMessageNotice, this);
+ }
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeScopeService.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeScopeService.java
new file mode 100644
index 0000000..2ab4e16
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeScopeService.java
@@ -0,0 +1,14 @@
+package org.jeecg.modules.system.message.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+
+/**
+ * 消息通知范围 Service
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+public interface ISysMessageNoticeScopeService extends IService {
+
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeService.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeService.java
new file mode 100644
index 0000000..cdab9af
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/ISysMessageNoticeService.java
@@ -0,0 +1,78 @@
+package org.jeecg.modules.system.message.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.system.message.model.dto.SysMessageNoticeDTO;
+import org.jeecg.modules.system.message.model.query.SysMessageNoticeQuery;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.model.vo.SysMessageNoticeVO;
+
+import java.util.List;
+
+/**
+ * 消息通知 Service
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+public interface ISysMessageNoticeService extends IService {
+
+ /**
+ * 查询后台管理分页列表
+ * 根据用户角色权限过滤数据
+ *
+ * @param query 查询条件
+ * @param page 分页参数
+ * @return 分页结果
+ */
+ IPage queryPageList(SysMessageNoticeQuery query, Page page);
+
+ /**
+ * 查询移动端分页列表
+ * 根据用户所属部门和个人权限过滤数据
+ *
+ * @param query 查询条件
+ * @param page 分页参数
+ * @return 列表结果
+ */
+ List queryPageAppList(SysMessageNoticeQuery query, Page page);
+
+ /**
+ * 添加消息通知
+ *
+ * @param dto 消息通知数据
+ */
+ void add(SysMessageNoticeDTO dto);
+
+ /**
+ * 编辑消息通知
+ *
+ * @param dto 消息通知数据
+ */
+ void edit(SysMessageNoticeDTO dto);
+
+ /**
+ * 删除消息通知
+ * 同时删除关联的范围数据
+ *
+ * @param id 通知ID
+ */
+ void deleteNotice(String id);
+
+ /**
+ * 批量删除消息通知
+ * 同时删除关联的范围数据
+ *
+ * @param ids 通知ID列表
+ */
+ void deleteBatchNotice(List ids);
+
+ /**
+ * 根据ID获取消息通知
+ *
+ * @param id 通知ID
+ * @return 消息通知
+ */
+ SysMessageNotice getNoticeById(String id);
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeScopeServiceImpl.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeScopeServiceImpl.java
new file mode 100644
index 0000000..baab612
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeScopeServiceImpl.java
@@ -0,0 +1,18 @@
+package org.jeecg.modules.system.message.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+import org.jeecg.modules.system.message.mapper.SysMessageNoticeScopeMapper;
+import org.jeecg.modules.system.message.service.ISysMessageNoticeScopeService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 消息通知范围 ServiceImpl
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Service
+public class SysMessageNoticeScopeServiceImpl extends ServiceImpl implements ISysMessageNoticeScopeService {
+
+}
diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeServiceImpl.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeServiceImpl.java
new file mode 100644
index 0000000..78bc32c
--- /dev/null
+++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/message/service/impl/SysMessageNoticeServiceImpl.java
@@ -0,0 +1,393 @@
+package org.jeecg.modules.system.message.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.jeecg.common.exception.ExceptionAssertsUtil;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.constant.NoticeConstants;
+import org.jeecg.enums.RoleEnum;
+import org.jeecg.global.GlobalUtils;
+import org.jeecg.modules.manager.ISysCache;
+import org.jeecg.modules.system.entity.SysDepart;
+import org.jeecg.modules.system.entity.SysUser;
+import org.jeecg.modules.system.mapper.SysDepartMapper;
+import org.jeecg.modules.system.mapper.SysUserMapper;
+import org.jeecg.modules.system.message.mapper.SysMessageNoticeScopeMapper;
+import org.jeecg.modules.system.message.model.dto.SysMessageNoticeDTO;
+import org.jeecg.modules.system.message.model.query.SysMessageNoticeQuery;
+import org.jeecg.modules.system.message.model.po.SysMessageNotice;
+import org.jeecg.modules.system.message.mapper.SysMessageNoticeMapper;
+import org.jeecg.modules.system.message.model.po.SysMessageNoticeScope;
+import org.jeecg.modules.system.message.model.vo.SysMessageNoticeVO;
+import org.jeecg.modules.system.message.service.ISysMessageNoticeScopeService;
+import org.jeecg.modules.system.message.service.ISysMessageNoticeService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 消息通知 ServiceImpl
+ *
+ * @author wangHao
+ * @date 2026-02-05
+ */
+@Service
+@RequiredArgsConstructor
+public class SysMessageNoticeServiceImpl extends ServiceImpl implements ISysMessageNoticeService {
+
+ private final ISysCache sysCache;
+ private final ISysMessageNoticeScopeService scopeService;
+ private final SysDepartMapper departMapper;
+ private final SysUserMapper userMapper;
+
+ @Override
+ public IPage queryPageList(SysMessageNoticeQuery query, Page page) {
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+ setQueryData(query, wrapper, NoticeConstants.QUERY_SOURCE_ADMIN);
+ Page resultPage = this.page(page, wrapper);
+ if (CollUtil.isEmpty(resultPage.getRecords())) {
+ return new Page<>();
+ }
+ IPage resultPageVO = new Page<>();
+ BeanUtil.copyProperties(resultPage, resultPageVO);
+ return resultPageVO.setRecords(setResultData(resultPage.getRecords()));
+ }
+
+ @Override
+ public List queryPageAppList(SysMessageNoticeQuery query, Page page) {
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+ setQueryData(query, wrapper, NoticeConstants.QUERY_SOURCE_APP);
+ Page resultPage = this.page(page, wrapper);
+ if (CollUtil.isEmpty(resultPage.getRecords())) {
+ return new ArrayList<>();
+ }
+ return setResultData(resultPage.getRecords());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void add(SysMessageNoticeDTO dto) {
+ // 前置处理
+ beforeHandle(dto);
+ // 保存消息
+ dto.setOrgCode(GlobalUtils.getLoginUser().getOrgCode());
+ this.save(dto);
+ // 保存范围
+ List scopes = new ArrayList<>();
+ if (CollUtil.isNotEmpty(dto.getDepartScopeList())) {
+ scopes.addAll(dto.getDepartScopeList());
+ }
+ if (CollUtil.isNotEmpty(dto.getUserScopeList())) {
+ scopes.addAll(dto.getUserScopeList());
+ }
+ if (CollUtil.isNotEmpty(scopes)) {
+ for (SysMessageNoticeScope scope : scopes) {
+ scope.setNoticeId(dto.getId());
+ }
+ scopeService.saveBatch(scopes);
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void edit(SysMessageNoticeDTO dto) {
+ // 前置处理
+ beforeHandle(dto);
+ // 删除范围
+ scopeService.remove(new LambdaQueryWrapper().eq(SysMessageNoticeScope::getNoticeId, dto.getId()));
+ // 保存范围
+ List scopes = new ArrayList<>();
+ if (CollUtil.isNotEmpty(dto.getDepartScopeList())) {
+ scopes.addAll(dto.getDepartScopeList());
+ }
+ if (CollUtil.isNotEmpty(dto.getUserScopeList())) {
+ scopes.addAll(dto.getUserScopeList());
+ }
+ if (CollUtil.isNotEmpty(scopes)) {
+ for (SysMessageNoticeScope scope : scopes) {
+ scope.setNoticeId(dto.getId());
+ }
+ scopeService.saveBatch(scopes);
+ }
+ // 更新消息
+ this.updateById(dto);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteNotice(String id) {
+ // 先删除关联的范围表
+ scopeService.remove(new LambdaQueryWrapper().eq(SysMessageNoticeScope::getNoticeId, id));
+ // 再删除主表
+ this.removeById(id);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteBatchNotice(List ids) {
+ // 先删除关联的范围表
+ scopeService.remove(new LambdaQueryWrapper().in(SysMessageNoticeScope::getNoticeId, ids));
+ // 再删除主表
+ this.removeByIds(ids);
+ }
+
+ @Override
+ public SysMessageNotice getNoticeById(String id) {
+ SysMessageNotice notice = this.getById(id);
+ if (notice == null) {
+ ExceptionAssertsUtil.fail("未找到对应数据");
+ }
+ return notice;
+ }
+
+ /**
+ * 设置查询条件
+ *
+ * @param query 查询参数
+ * @param wrapper 查询包装器
+ * @param source 查询来源(0-后台管理,1-移动端)
+ */
+ private void setQueryData(SysMessageNoticeQuery query, LambdaQueryWrapper wrapper, Integer source) {
+ // 设置权限过滤
+ applyPermissionFilter(wrapper, source);
+ // 设置查询条件
+ applyQueryConditions(query, wrapper);
+ // 设置排序
+ wrapper.orderByDesc(SysMessageNotice::getCreateTime);
+ }
+
+ /**
+ * 应用权限过滤
+ *
+ * @param wrapper 查询包装器
+ * @param source 查询来源
+ */
+ private void applyPermissionFilter(LambdaQueryWrapper wrapper, Integer source) {
+ if (NoticeConstants.QUERY_SOURCE_ADMIN.equals(source)) {
+ applyAdminPermissionFilter(wrapper);
+ } else if (NoticeConstants.QUERY_SOURCE_APP.equals(source)) {
+ applyAppPermissionFilter(wrapper);
+ }
+ }
+
+ /**
+ * 应用后台管理权限过滤
+ *
+ * @param wrapper 查询包装器
+ */
+ private void applyAdminPermissionFilter(LambdaQueryWrapper wrapper) {
+ LoginUser loginUser = GlobalUtils.getLoginUser();
+ /*
+ * 1.后台接口的消息列表需要做一定数据权限控制需考虑的角色有admin,system,second_manager,third_manager
+ * 2.admin,system可查看所有的活动
+ * 3.second_manager,third_manager可查看管理单位下的消息列表
+ */
+ boolean permissions = false;
+ List roleCodes = Arrays.asList(Objects.toString(loginUser.getRoleCodes(), "").split(","));
+ if (roleCodes.contains(RoleEnum.ADMIN_MANAGER.roleName) || roleCodes.contains(RoleEnum.SYSTEM.roleName) || roleCodes.contains(RoleEnum.WEIGHT_PLAN_ADMIN.roleName)) {
+ permissions = true;
+ } else if (roleCodes.contains(RoleEnum.SECOND_MANAGER.roleName)) {
+ if (StrUtil.isNotEmpty(loginUser.getDepartCodes())) {
+ List manageDepartCode = Arrays.stream(loginUser.getDepartCodes().split(",")).collect(Collectors.toList());
+ wrapper.in(SysMessageNotice::getOrgCode, manageDepartCode);
+ permissions = true;
+ }
+ }
+ // 没有权限,返回空结果
+ wrapper.eq(!permissions, SysMessageNotice::getId, "-1");
+ }
+
+ /**
+ * 应用移动端权限过滤
+ *
+ * @param wrapper 查询包装器
+ */
+ private void applyAppPermissionFilter(LambdaQueryWrapper wrapper) {
+ LoginUser loginUser = GlobalUtils.getLoginUser();
+ // 默认条件只获取当前登录用户所能看到的消息范围
+ List noticeIds = getAccessibleNoticeIds(loginUser);
+ if (CollUtil.isEmpty(noticeIds)) {
+ // 没有可以查看的通知
+ wrapper.eq(SysMessageNotice::getId, "-1");
+ } else {
+ wrapper.in(SysMessageNotice::getId, noticeIds);
+ }
+ }
+
+ /**
+ * 获取用户可访问的通知ID列表
+ *
+ * @param loginUser 登录用户
+ * @return 通知ID列表
+ */
+ private List getAccessibleNoticeIds(LoginUser loginUser) {
+ LambdaQueryWrapper scopeWrapper = new LambdaQueryWrapper<>();
+ scopeWrapper.select(SysMessageNoticeScope::getNoticeId)
+ .eq(SysMessageNoticeScope::getScopeId, loginUser.getId())
+ .or()
+ .likeRight(SysMessageNoticeScope::getScopeId,
+ sysCache.getDepartByOrgCode(GlobalUtils.getFirstDepartOrgCode(loginUser.getOrgCode())).getOrgCode())
+ .or()
+ .likeRight(SysMessageNoticeScope::getScopeId,
+ sysCache.getDepartByOrgCode(GlobalUtils.getSecondDepartOrgCode(loginUser.getOrgCode())).getOrgCode())
+ .or()
+ .likeRight(SysMessageNoticeScope::getScopeId,
+ sysCache.getDepartByOrgCode(GlobalUtils.getThirdDepartOrgCode(loginUser.getOrgCode())).getOrgCode())
+ .or()
+ .likeRight(SysMessageNoticeScope::getScopeId,
+ sysCache.getDepartByOrgCode(loginUser.getOrgCode()).getOrgCode());
+ List planScopes = scopeService.list(scopeWrapper);
+ return planScopes.stream().map(SysMessageNoticeScope::getNoticeId).collect(Collectors.toList());
+ }
+
+ /**
+ * 应用查询条件
+ *
+ * @param query 查询参数
+ * @param wrapper 查询包装器
+ */
+ private void applyQueryConditions(SysMessageNoticeQuery query, LambdaQueryWrapper wrapper) {
+ if (query == null) {
+ return;
+ }
+ if (StrUtil.isNotEmpty(query.getTitle())) {
+ wrapper.like(SysMessageNotice::getTitle, query.getTitle());
+ }
+ if (StrUtil.isNotEmpty(query.getScopeType())) {
+ wrapper.eq(SysMessageNotice::getScopeType, query.getScopeType());
+ }
+ if (ObjUtil.isNotEmpty(query.getStartDate()) && ObjUtil.isNotEmpty(query.getEndDate())) {
+ wrapper.between(SysMessageNotice::getCreateTime, DateUtil.beginOfDay(query.getStartDate()), DateUtil.endOfDay(query.getEndDate()));
+ }
+ }
+
+ /**
+ * 设置结果数据
+ * 将消息通知列表转换为VO列表,并填充范围信息
+ *
+ * @param list 消息通知列表
+ * @return VO列表
+ */
+ private List setResultData(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return new ArrayList<>();
+ }
+
+ // 获取范围数据并分组
+ List noticeIds = list.stream().map(SysMessageNotice::getId).collect(Collectors.toList());
+ LambdaQueryWrapper scopeWrapper = new LambdaQueryWrapper<>();
+ scopeWrapper.in(SysMessageNoticeScope::getNoticeId, noticeIds);
+ List scopeList = scopeService.list(scopeWrapper);
+ Map> scopeMap =
+ scopeList.stream().collect(Collectors.groupingBy(SysMessageNoticeScope::getNoticeId));
+
+ // 构建结果列表
+ List resultList = new ArrayList<>();
+ for (SysMessageNotice notice : list) {
+ SysMessageNoticeVO noticeVO = new SysMessageNoticeVO(notice);
+ List scopes = scopeMap.get(notice.getId());
+ if (CollUtil.isNotEmpty(scopes)) {
+ // 根据type分组
+ Map> scopeTypeMap = scopes.stream().collect(Collectors.groupingBy(SysMessageNoticeScope::getType));
+ // 设置部门和人群范围(添加空值检查)
+ noticeVO.setDepartScopeList(scopeTypeMap.getOrDefault(NoticeConstants.NOTICE_SCOPE_TYPE_DEPART, new ArrayList<>()));
+ noticeVO.setUserScopeList(scopeTypeMap.getOrDefault(NoticeConstants.NOTICE_SCOPE_TYPE_PEOPLE, new ArrayList<>()));
+ }
+ resultList.add(noticeVO);
+ }
+ return resultList;
+ }
+
+ /**
+ * 前置处理
+ * 校验数据并填充范围信息
+ *
+ * @param data 消息通知数据
+ */
+ private void beforeHandle(SysMessageNoticeDTO data) {
+ // 校验范围类型
+ if (data.getScopeType() == null) {
+ ExceptionAssertsUtil.fail("未知类型!");
+ }
+ // 校验范围数据
+ if (CollUtil.isEmpty(data.getDepartScopeList()) && CollUtil.isEmpty(data.getUserScopeList())) {
+ ExceptionAssertsUtil.fail("未选择部门或者员工!");
+ }
+ // 校验时间范围
+ if (data.getStartTime() != null && data.getEndTime() != null) {
+ if (data.getStartTime().after(data.getEndTime())) {
+ ExceptionAssertsUtil.fail("开始时间不能晚于结束时间!");
+ }
+ }
+ // 处理部门范围
+ if (NoticeConstants.NOTICE_SCOPE_TYPE_DEPART.equals(data.getScopeType())
+ || NoticeConstants.NOTICE_SCOPE_TYPE_BOTH.equals(data.getScopeType())) {
+ if (CollUtil.isNotEmpty(data.getDepartScopeList())) {
+ processDepartScopes(data.getDepartScopeList());
+ }
+ }
+ // 处理人群范围
+ if (NoticeConstants.NOTICE_SCOPE_TYPE_PEOPLE.equals(data.getScopeType())
+ || NoticeConstants.NOTICE_SCOPE_TYPE_BOTH.equals(data.getScopeType())) {
+ if (CollUtil.isNotEmpty(data.getUserScopeList())) {
+ processUserScopes(data.getUserScopeList());
+ }
+ }
+ }
+
+ /**
+ * 处理部门范围
+ * 填充部门名称
+ *
+ * @param departScopes 部门范围列表
+ */
+ private void processDepartScopes(List departScopes) {
+ Set orgCodes = departScopes.stream()
+ .map(SysMessageNoticeScope::getScopeId)
+ .collect(Collectors.toSet());
+ List departs = departMapper.selectNameByCodes(orgCodes);
+ Map departNameMap = departs.stream()
+ .collect(Collectors.toMap(SysDepart::getOrgCode, SysDepart::getDepartName));
+
+ for (SysMessageNoticeScope scope : departScopes) {
+ scope.setType(NoticeConstants.NOTICE_SCOPE_TYPE_DEPART);
+ String departName = departNameMap.get(scope.getScopeId());
+ if (StrUtil.isNotEmpty(departName)) {
+ scope.setRecord(departName);
+ }
+ }
+ }
+
+ /**
+ * 处理人群范围
+ * 填充人员姓名
+ *
+ * @param userScopes 人群范围列表
+ */
+ private void processUserScopes(List userScopes) {
+ Set userIds = userScopes.stream()
+ .map(SysMessageNoticeScope::getScopeId)
+ .collect(Collectors.toSet());
+ List users = userMapper.selectNameByIds(userIds);
+ Map userNameMap = users.stream()
+ .collect(Collectors.toMap(SysUser::getId, SysUser::getRealname));
+
+ for (SysMessageNoticeScope scope : userScopes) {
+ scope.setType(NoticeConstants.NOTICE_SCOPE_TYPE_PEOPLE);
+ String userName = userNameMap.get(scope.getScopeId());
+ if (StrUtil.isNotEmpty(userName)) {
+ scope.setRecord(userName);
+ }
+ }
+ }
+}