package com.ruoyi.project.system.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysNotice; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUserDept; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysNoticeMapper; import com.ruoyi.project.system.mapper.SysUserDeptMapper; 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.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 公告 服务层实现 * * @author ruoyi */ @Service @RequiredArgsConstructor public class SysNoticeServiceImpl extends ServiceImpl implements ISysNoticeService { private static final Pattern ENTERPRISE_NEWS_ID_PATTERN = Pattern.compile("[?&]id=(\\d+)"); private final SysNoticeMapper noticeMapper; private final SysUserMapper userMapper; private final SysDeptMapper deptMapper; private final SysUserDeptMapper userDeptMapper; private final UnipushService unipushService; private final EnterpriseNewsMapper enterpriseNewsMapper; /** * 查询公告信息 * * @param noticeId 公告ID * @return 公告信息 */ @Override public SysNotice selectNoticeById(Long noticeId) { return noticeMapper.selectNoticeById(noticeId); } /** * 查询公告列表 * * @param notice 公告信息 * @return 公告集合 */ @Override public IPage selectNoticeList(SysNotice notice, Page page) { return noticeMapper.selectNoticeList(notice, page); } /** * 新增公告 * * @param notice 公告信息 * @return 结果 */ @Override public int insertNotice(SysNotice notice) { return noticeMapper.insertNotice(notice); } /** * 修改公告 * * @param notice 公告信息 * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int updateNotice(SysNotice notice) { if (notice == null || notice.getNoticeId() == null) { return 0; } SysNotice dbNotice = noticeMapper.selectNoticeById(notice.getNoticeId()); if (dbNotice == null) { return 0; } boolean needSyncNewsReadCount = isEnterpriseNewsNotice(dbNotice) && notice.getStatus() != null && !notice.getStatus().equals(dbNotice.getStatus()); int rows = noticeMapper.updateNotice(notice); if (rows > 0 && needSyncNewsReadCount) { syncEnterpriseNewsReadCount(dbNotice.getJumpPath()); } return rows; } /** * 删除公告对象 * * @param noticeId 公告ID * @return 结果 */ @Override public int deleteNoticeById(Long noticeId) { return noticeMapper.deleteNoticeById(noticeId); } /** * 批量删除公告信息 * * @param noticeIds 需要删除的公告ID * @return 结果 */ @Override public int deleteNoticeByIds(Long[] noticeIds) { return noticeMapper.deleteNoticeByIds(noticeIds); } @Override public Long getCount(Long consigneeId) { return noticeMapper.selectCount(Wrappers.lambdaQuery() .eq(SysNotice::getStatus, "0") .eq(SysNotice::getConsigneeId, consigneeId)); } @Override public int readAll() { Long userId = SecurityUtils.getUserId(); List unreadNotices = noticeMapper.selectList(Wrappers.lambdaQuery() .eq(SysNotice::getConsigneeId, userId) .eq(SysNotice::getStatus, "0")); int rows = noticeMapper.update(null, Wrappers.lambdaUpdate() .eq(SysNotice::getConsigneeId, userId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")); if (rows > 0) { syncEnterpriseNewsReadCount(unreadNotices); } return rows; } @Override public void simpleNoticeByUser(String title, String message, List consigneeId, String jumpPath) { Long userId = SecurityUtils.getLoginUser().getUserId(); Long tenantId = SecurityUtils.getLoginUser().getTenantId(); List sysNotices = consigneeId.stream() .map(it -> convertSysNotice(title, message, it, tenantId, jumpPath, unipushService.convertWebPathToAppPath(jumpPath), userId)) .collect(Collectors.toList()); noticeMapper.insert(sysNotices); try { unipushService.sendClientMessage(sysNotices); } catch (Exception e) { log.error("APP推送通知失败,原因: {}", e); } } @Override public void simpleNoticeAll(String title, String message, String jumpPath) { Long userId = SecurityUtils.getLoginUser().getUserId(); if (userId == null) { return; } Long rootDeptId = SecurityUtils.getLoginUser().getTenantId(); // 查所有子部门 List childrenDepts = deptMapper.selectChildrenDeptById(rootDeptId); // 组装 deptIds List deptIds = childrenDepts.stream() .map(SysDept::getDeptId) .collect(Collectors.toList()); deptIds.add(rootDeptId); // 查用户ID List userIds = userDeptMapper.selectList( Wrappers.lambdaQuery() .in(SysUserDept::getDeptId, deptIds) ).stream() .map(SysUserDept::getUserId) .distinct() .collect(Collectors.toList()); if (userIds.isEmpty()) { return; } // 查用户 List sysUsers = userMapper.selectList( Wrappers.lambdaQuery() .eq(SysUser::getStatus, "0") .in(SysUser::getUserId, userIds) ); // 发通知 List collect = sysUsers.stream() .map(it -> convertSysNotice( title, message, it.getUserId(), it.getTenantId(), jumpPath, unipushService.convertWebPathToAppPath(jumpPath), userId )) .collect(Collectors.toList()); noticeMapper.insert(collect); try { unipushService.sendClientMessage(collect); } catch (Exception e) { log.error("APP推送通知失败,原因: {}", e); } } private SysNotice convertSysNotice(String title,String message,Long consigneeId, Long tenantId,String jumpPath,String appJumpPath,Long currentUserId) { SysNotice sysNotice = new SysNotice(); sysNotice.setNoticeType("1"); sysNotice.setNoticeTitle(title);//标题 sysNotice.setNoticeContent(message); sysNotice.setStatus("0"); sysNotice.setConsigneeId(consigneeId); sysNotice.setSenderId(currentUserId); sysNotice.setJumpPath(jumpPath); sysNotice.setAppJumpPath(appJumpPath); sysNotice.setTenantId(tenantId); return sysNotice; } @Override @Transactional(rollbackFor = Exception.class) public boolean appReadNotice(Long noticeId) { if (noticeId == null) { return false; } SysNotice sysNotice = noticeMapper.selectNoticeById(noticeId); if (sysNotice == null) { return false; } sysNotice.setStatus("1"); boolean updated = noticeMapper.update(null, Wrappers.lambdaUpdate() .eq(SysNotice::getNoticeId, noticeId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")) > 0; if (updated) { syncEnterpriseNewsReadCount(sysNotice.getJumpPath()); } return updated; } private boolean isEnterpriseNewsNotice(SysNotice sysNotice) { return sysNotice != null && sysNotice.getJumpPath() != null && sysNotice.getJumpPath().startsWith("/enterpriseNews?id="); } private void syncEnterpriseNewsReadCount(List notices) { if (notices == null || notices.isEmpty()) { return; } Set jumpPaths = new HashSet<>(); for (SysNotice notice : notices) { if (isEnterpriseNewsNotice(notice)) { jumpPaths.add(notice.getJumpPath()); } } for (String jumpPath : jumpPaths) { syncEnterpriseNewsReadCount(jumpPath); } } private void syncEnterpriseNewsReadCount(String jumpPath) { Long newsId = parseEnterpriseNewsId(jumpPath); if (newsId == null) { return; } long readCount = noticeMapper.selectCount(Wrappers.lambdaQuery() .eq(SysNotice::getStatus, "1") .eq(SysNotice::getJumpPath, jumpPath)); EnterpriseNews enterpriseNews = new EnterpriseNews(); enterpriseNews.setId(newsId); enterpriseNews.setReadCount((int) readCount); enterpriseNewsMapper.updateById(enterpriseNews); } private Long parseEnterpriseNewsId(String jumpPath) { if (jumpPath == null || !jumpPath.startsWith("/enterpriseNews")) { return null; } Matcher matcher = ENTERPRISE_NEWS_ID_PATTERN.matcher(jumpPath); if (!matcher.find()) { return null; } try { return Long.parseLong(matcher.group(1)); } catch (NumberFormatException e) { return null; } } }