| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package com.emoon.okr.service;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
- import com.baomidou.mybatisplus.core.metadata.IPage;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.emoon.okr.dto.NotificationDto;
- import com.emoon.okr.entity.Notification;
- import com.emoon.okr.mapper.NotificationMapper;
- import lombok.RequiredArgsConstructor;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import com.emoon.okr.exception.BusinessException;
- import java.time.LocalDateTime;
- import java.time.temporal.ChronoUnit;
- @Service
- @RequiredArgsConstructor
- public class NotificationService {
- private final NotificationMapper notificationMapper;
- @Transactional
- public boolean createOnce(Long userId, String type, String title, String content,
- String refType, Long refId) {
- long existing = notificationMapper.selectCount(new LambdaQueryWrapper<Notification>()
- .eq(Notification::getUserId, userId)
- .eq(Notification::getType, type)
- .eq(Notification::getRefType, refType)
- .eq(Notification::getRefId, refId));
- if (existing > 0) {
- return false;
- }
- Notification notification = new Notification();
- notification.setUserId(userId);
- notification.setType(type);
- notification.setTitle(title);
- notification.setContent(content);
- notification.setRefType(refType);
- notification.setRefId(refId);
- notification.setIsRead(0);
- // ponytail: application-level dedupe is enough for hourly reminders; add a unique index if concurrent producers emerge.
- notificationMapper.insert(notification);
- return true;
- }
- public long getUnreadCount(Long userId) {
- return notificationMapper.selectCount(
- new LambdaQueryWrapper<Notification>()
- .eq(Notification::getUserId, userId)
- .eq(Notification::getIsRead, 0));
- }
- public IPage<NotificationDto> getPage(Long userId, int page, int size, String type) {
- LambdaQueryWrapper<Notification> qw = new LambdaQueryWrapper<Notification>()
- .eq(Notification::getUserId, userId)
- .orderByDesc(Notification::getCreatedAt);
- if (type != null && !type.isEmpty()) {
- qw.eq(Notification::getType, type);
- }
- IPage<Notification> result = notificationMapper.selectPage(new Page<>(page, size), qw);
- return result.convert(this::toDto);
- }
- public void markRead(Long id, Long userId) {
- Notification n = notificationMapper.selectById(id);
- if (n == null) {
- throw new BusinessException(404, "通知不存在");
- }
- if (!n.getUserId().equals(userId)) {
- throw new BusinessException(403, "无权操作此通知");
- }
- n.setIsRead(1);
- n.setReadAt(LocalDateTime.now());
- notificationMapper.updateById(n);
- }
- public void markAllRead(Long userId) {
- notificationMapper.update(null,
- new LambdaUpdateWrapper<Notification>()
- .eq(Notification::getUserId, userId)
- .eq(Notification::getIsRead, 0)
- .set(Notification::getIsRead, 1)
- .set(Notification::getReadAt, LocalDateTime.now()));
- }
- public java.util.Map<String, Long> getUnreadByType(Long userId) {
- java.util.Map<String, Long> result = new java.util.LinkedHashMap<>();
- java.util.List<Notification> unread = notificationMapper.selectList(
- new LambdaQueryWrapper<Notification>()
- .eq(Notification::getUserId, userId)
- .eq(Notification::getIsRead, 0));
- long total = 0;
- for (Notification n : unread) {
- String type = n.getType() != null ? n.getType() : "OTHER";
- result.merge(type, 1L, Long::sum);
- total++;
- }
- result.put("_total", total);
- return result;
- }
- private NotificationDto toDto(Notification n) {
- NotificationDto dto = new NotificationDto();
- dto.setId(n.getId());
- dto.setType(n.getType());
- dto.setTitle(n.getTitle());
- dto.setContent(n.getContent());
- dto.setRefType(n.getRefType());
- dto.setRefId(n.getRefId());
- dto.setIsRead(n.getIsRead());
- dto.setCreatedAt(n.getCreatedAt());
- long seconds = n.getCreatedAt() != null
- ? ChronoUnit.SECONDS.between(n.getCreatedAt(), LocalDateTime.now()) : 0;
- if (seconds < 60) dto.setCreatedAtFriendly("刚刚");
- else if (seconds < 3600) dto.setCreatedAtFriendly((seconds / 60) + "分钟前");
- else if (seconds < 86400) dto.setCreatedAtFriendly((seconds / 3600) + "小时前");
- else dto.setCreatedAtFriendly((seconds / 86400) + "天前");
- return dto;
- }
- }
|