package cn.iocoder.yudao.module.bpm.service.oa;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.OaNoticePageReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.OaNoticeSaveReqVO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.OaNoticeDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.OaNoticeReadDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.OaNoticeUserDO;
|
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.OaNoticeMapper;
|
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.OaNoticeReadMapper;
|
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.OaNoticeUserMapper;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.module.bpm.enums.oa.OaNoticeSendScopeEnum;
|
import cn.iocoder.yudao.module.bpm.enums.oa.OaNoticeStatusEnum;
|
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
|
import cn.iocoder.yudao.module.system.service.notify.NotifySendService;
|
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_NOTICE_NOT_EXISTS;
|
|
/**
|
* OA 通知公告 Service 实现类
|
*/
|
@Service
|
@Slf4j
|
public class OaNoticeServiceImpl implements OaNoticeService {
|
|
@Resource
|
private OaNoticeMapper oaNoticeMapper;
|
|
@Resource
|
private OaNoticeUserMapper oaNoticeUserMapper;
|
|
@Resource
|
private OaNoticeReadMapper oaNoticeReadMapper;
|
|
@Resource
|
private NotifySendService notifySendService;
|
|
@Resource
|
private AdminUserService adminUserService;
|
|
@Resource
|
private NotifyMessageMapper notifyMessageMapper;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createNotice(Long userId, OaNoticeSaveReqVO createReqVO) {
|
// 创建通知公告
|
OaNoticeDO notice = BeanUtils.toBean(createReqVO, OaNoticeDO.class);
|
notice.setPublishUserId(userId);
|
if (OaNoticeStatusEnum.PUBLISHED.getStatus().equals(createReqVO.getStatus())) {
|
notice.setPublishTime(LocalDateTime.now());
|
}
|
oaNoticeMapper.insert(notice);
|
|
// 指定人写入关联表
|
if (OaNoticeSendScopeEnum.SPECIFIED.getScope().equals(createReqVO.getSendScope())
|
&& CollUtil.isNotEmpty(createReqVO.getUserIds())) {
|
saveNoticeUsers(notice.getId(), createReqVO.getUserIds());
|
}
|
|
// 已发布则发送系统通知
|
if (OaNoticeStatusEnum.PUBLISHED.getStatus().equals(notice.getStatus())) {
|
sendPublishNotify(notice);
|
}
|
|
return notice.getId();
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateNotice(OaNoticeSaveReqVO updateReqVO) {
|
// 校验是否存在
|
OaNoticeDO oldNotice = validateNoticeExists(updateReqVO.getId());
|
|
// 更新通知公告
|
OaNoticeDO updateObj = BeanUtils.toBean(updateReqVO, OaNoticeDO.class);
|
// 从未发布变为已发布时,设置发布时间
|
if (!OaNoticeStatusEnum.PUBLISHED.getStatus().equals(oldNotice.getStatus())
|
&& OaNoticeStatusEnum.PUBLISHED.getStatus().equals(updateReqVO.getStatus())) {
|
updateObj.setPublishTime(LocalDateTime.now());
|
}
|
oaNoticeMapper.updateById(updateObj);
|
|
// 更新指定人关联
|
oaNoticeUserMapper.deleteByNoticeId(updateReqVO.getId());
|
if (OaNoticeSendScopeEnum.SPECIFIED.getScope().equals(updateReqVO.getSendScope())
|
&& CollUtil.isNotEmpty(updateReqVO.getUserIds())) {
|
saveNoticeUsers(updateReqVO.getId(), updateReqVO.getUserIds());
|
}
|
|
// 新发布时发送系统通知
|
if (!OaNoticeStatusEnum.PUBLISHED.getStatus().equals(oldNotice.getStatus())
|
&& OaNoticeStatusEnum.PUBLISHED.getStatus().equals(updateReqVO.getStatus())) {
|
sendPublishNotify(updateObj);
|
}
|
|
// 撤销时删除已发送的系统通知
|
if (OaNoticeStatusEnum.REVOKED.getStatus().equals(updateReqVO.getStatus())
|
&& OaNoticeStatusEnum.PUBLISHED.getStatus().equals(oldNotice.getStatus())) {
|
notifyMessageMapper.deleteByTemplateCodeAndNoticeId(
|
"oa-notice-publish", updateReqVO.getId());
|
}
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void deleteNotice(Long id) {
|
validateNoticeExists(id);
|
oaNoticeMapper.deleteById(id);
|
oaNoticeUserMapper.deleteByNoticeId(id);
|
}
|
|
@Override
|
public PageResult<OaNoticeDO> getNoticePage(Long userId, OaNoticePageReqVO reqVO) {
|
// 构建可见的通知ID集合
|
Set<Long> visibleIds = buildVisibleNoticeIds(userId);
|
if (visibleIds != null && visibleIds.isEmpty()) {
|
return PageResult.empty();
|
}
|
return oaNoticeMapper.selectPage(reqVO, visibleIds);
|
}
|
|
@Override
|
public OaNoticeDO getNotice(Long id, Long userId) {
|
OaNoticeDO notice = validateNoticeExists(id);
|
// 标记已读
|
markAsRead(id, userId);
|
return notice;
|
}
|
|
@Override
|
public Long getUnreadCount(Long userId) {
|
// 获取所有已发布且当前用户可见的公告ID
|
Set<Long> visibleIds = buildVisibleNoticeIds(userId);
|
if (CollUtil.isEmpty(visibleIds)) {
|
return 0L;
|
}
|
List<Long> visibleIdList = new ArrayList<>(visibleIds);
|
return oaNoticeReadMapper.selectUnreadCountByUserId(userId, visibleIdList);
|
}
|
|
/**
|
* 构建当前用户可见的通知公告ID集合
|
*
|
* @param userId 当前用户ID
|
* @return null表示全部可见,空集合表示无可看
|
*/
|
private Set<Long> buildVisibleNoticeIds(Long userId) {
|
// 所有通知所有人公告ID
|
List<OaNoticeDO> allPublishedNotices = oaNoticeMapper.selectList(
|
new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX<OaNoticeDO>()
|
.eq(OaNoticeDO::getSendScope, OaNoticeSendScopeEnum.ALL.getScope()));
|
Set<Long> allNoticeIds = allPublishedNotices.stream()
|
.map(OaNoticeDO::getId).collect(Collectors.toSet());
|
|
// 指定人能看到的本用户相关公告ID
|
List<OaNoticeDO> specifiedNotices = oaNoticeMapper.selectList(
|
new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX<OaNoticeDO>()
|
.eq(OaNoticeDO::getSendScope, OaNoticeSendScopeEnum.SPECIFIED.getScope()));
|
for (OaNoticeDO notice : specifiedNotices) {
|
// 创建者可见
|
if (userId.equals(notice.getPublishUserId())) {
|
allNoticeIds.add(notice.getId());
|
continue;
|
}
|
// 被指定用户可见
|
Long count = oaNoticeUserMapper.selectCount(
|
new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX<OaNoticeUserDO>()
|
.eq(OaNoticeUserDO::getNoticeId, notice.getId())
|
.eq(OaNoticeUserDO::getUserId, userId));
|
if (count > 0) {
|
allNoticeIds.add(notice.getId());
|
}
|
}
|
|
return allNoticeIds;
|
}
|
|
/**
|
* 标记已读
|
*/
|
private void markAsRead(Long noticeId, Long userId) {
|
OaNoticeReadDO existing = oaNoticeReadMapper.selectByNoticeIdAndUserId(noticeId, userId);
|
if (existing == null) {
|
OaNoticeReadDO readRecord = new OaNoticeReadDO();
|
readRecord.setNoticeId(noticeId);
|
readRecord.setUserId(userId);
|
readRecord.setReadTime(LocalDateTime.now());
|
oaNoticeReadMapper.insert(readRecord);
|
}
|
}
|
|
/**
|
* 保存指定人关联
|
*/
|
private void saveNoticeUsers(Long noticeId, List<Long> userIds) {
|
List<OaNoticeUserDO> userList = userIds.stream().map(uid -> {
|
OaNoticeUserDO user = new OaNoticeUserDO();
|
user.setNoticeId(noticeId);
|
user.setUserId(uid);
|
return user;
|
}).collect(Collectors.toList());
|
oaNoticeUserMapper.insertBatch(userList);
|
}
|
|
/**
|
* 发送发布通知给目标用户
|
*/
|
private void sendPublishNotify(OaNoticeDO notice) {
|
Map<String, Object> templateParams = new HashMap<>();
|
templateParams.put("title", notice.getTitle());
|
templateParams.put("content", notice.getContent());
|
templateParams.put("noticeId", notice.getId());
|
List<Long> targetUserIds;
|
if (OaNoticeSendScopeEnum.ALL.getScope().equals(notice.getSendScope())) {
|
// 通知所有人:查询所有启用的管理员用户
|
targetUserIds = adminUserService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus())
|
.stream().map(cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO::getId)
|
.collect(Collectors.toList());
|
} else {
|
// 指定人
|
targetUserIds = oaNoticeUserMapper.selectListByNoticeId(notice.getId()).stream()
|
.map(OaNoticeUserDO::getUserId)
|
.collect(Collectors.toList());
|
}
|
for (Long userId : targetUserIds) {
|
try {
|
notifySendService.sendSingleNotifyToAdmin(userId, "oa-notice-publish", templateParams);
|
} catch (Exception e) {
|
log.warn("发送通知公告[{}]给用户[{}]失败", notice.getId(), userId, e);
|
}
|
}
|
}
|
|
private OaNoticeDO validateNoticeExists(Long id) {
|
OaNoticeDO notice = oaNoticeMapper.selectById(id);
|
if (notice == null) {
|
throw exception(OA_NOTICE_NOT_EXISTS);
|
}
|
return notice;
|
}
|
|
}
|