feat(公告消息模块): 公告消息的增删改查

This commit is contained in:
zhuangtianxiang 2024-11-28 16:05:34 +08:00
parent 060d90ecb2
commit be99aedaba
26 changed files with 544 additions and 435 deletions

View File

@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import org.springframework.core.io.FileSystemResource;
import java.io.Serializable;
@ -18,9 +15,9 @@ import java.time.LocalDateTime;
*
* @author harry_yao
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@TableName(value ="attachment")
public class Attachment implements Serializable {

View File

@ -2,19 +2,22 @@ package com.zsc.edu.gateway.modules.attachment.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* @author fantianzhi
* @description 针对表attach_file(票据附件表)的数据库操作Service
* @createDate 2024-01-28 19:48:22
*/
* @description 针对表attach_file(票据附件表)的数据库操作Service
* @createDate 2024-01-28 19:48:22
*/
public interface AttachmentService extends IService<Attachment> {
Attachment store(Attachment.Type type, MultipartFile file) throws IOException;
Attachment stores(Attachment.Type type, MultipartFile file)throws IOException;
Resource loadAsResource(String id);
Attachment.Wrapper loadAsWrapper(String id);
}

View File

@ -142,6 +142,7 @@ public class AttachmentServiceImpl extends ServiceImpl<AttachmentRepository, Att
return save(file, sha1, filename, mimeType, type);
}
@Override
public Resource loadAsResource(String id) {
Path file = attachmentPath.resolve(id);
FileSystemResource resource = new FileSystemResource(file);
@ -152,6 +153,7 @@ public class AttachmentServiceImpl extends ServiceImpl<AttachmentRepository, Att
}
}
@Override
public Attachment.Wrapper loadAsWrapper(String id) {
Path file = attachmentPath.resolve(id);
FileSystemResource resource = new FileSystemResource(file);

View File

@ -7,7 +7,6 @@ import com.zsc.edu.gateway.modules.notice.dto.BulletinDto;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
import com.zsc.edu.gateway.modules.notice.query.BulletinQuery;
import com.zsc.edu.gateway.modules.notice.service.BulletinService;
import com.zsc.edu.gateway.modules.notice.service.BulletinVoService;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
@ -28,7 +27,6 @@ import java.util.Set;
public class BulletinController {
private final BulletinService service;
private final BulletinVoService bulletinVoService;
/**
* 普通用户查看公告详情
@ -51,7 +49,7 @@ public class BulletinController {
public IPage<BulletinVo> getBulletins( BulletinQuery query) {
query.setState(Bulletin.State.publish);
Page<BulletinVo> page = new Page<>(query.getPageNum(), query.getPageSize());
return bulletinVoService.selectPageByConditions(page, query);
return service.selectPageByConditions(page, query);
}
/**
@ -76,7 +74,7 @@ public class BulletinController {
@PreAuthorize("hasAuthority('BULLETIN_QUERY')")
public IPage<BulletinVo> query( BulletinQuery query) {
Page<BulletinVo> page = new Page<>(query.getPageNum(), query.getPageSize());
return bulletinVoService.selectPageByConditions(page, query);
return service.selectPageByConditions(page, query);
}
/**

View File

@ -1,164 +1,156 @@
//package com.zsc.edu.gateway.modules.notice.controller;
//
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
//import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
//import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
//import com.zsc.edu.gateway.modules.notice.query.MessageQuery;
//import com.zsc.edu.gateway.modules.notice.query.UserMessageQuery;
//import com.zsc.edu.gateway.modules.notice.service.UserMessageService;
//import lombok.AllArgsConstructor;
//import org.springframework.data.domain.Pageable;
//import org.springframework.data.domain.Sort;
//import org.springframework.data.web.PageableDefault;
//import org.springframework.security.access.prepost.PreAuthorize;
//import org.springframework.security.core.annotation.AuthenticationPrincipal;
//import org.springframework.web.bind.annotation.*;
//
//import java.util.List;
//import java.util.Set;
//
///**
// * 用户消息Controller
// *
// * @author harry_yao
// */
//@AllArgsConstructor
//@RestController
//@RequestMapping("api/rest/message")
//public class UserMessageController {
//
// private final UserMessageService service;
//
// /**
// * 普通用户查看消息详情
// *
// * @param userDetails 操作用户
// * @param messageId 消息ID
// * @return 用户消息详情
// */
// @GetMapping("/self/{message-id}")
// public UserMessage selfDetail(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("message-id") Long messageId) {
// UserMessage id = new UserMessage.Id(userDetails.id, messageId);
// return service.detail(id);
// }
//
// /**
// * 普通用户分页查询消息不能设置查询参数userId和username
// *
// * @param userDetails 操作用户
// * @param query 查询参数
// * @param page 分页参数
// * @return 分页数据
// */
// @GetMapping("/self")
// public Page<UserMessage> selfPage(@AuthenticationPrincipal UserDetailsImpl userDetails, UserMessageQuery query, Page<UserMessage> page) {
// query.userId = userDetails.id;
// query.name = null;
// return service.page(page, query.wrapper());
// }
//
// /**
// * 普通用户统计自己未读消息数量
// *
// * @param userDetails 操作用户
// * @return 数据
// */
// @GetMapping("/count-unread")
// public int countUnread(
// @AuthenticationPrincipal UserDetailsImpl userDetails) {
// return service.countUnread(userDetails);
// }
//
// /**
// * 普通用户确认消息已读如果提交的已读消息ID集合为空则将所有未读消息设为已读
// *
// * @param userDetails 操作用户
// * @param messageIds 已读消息ID集合
// * @return 确认已读数量
// */
// @PatchMapping("/read")
// public int acknowledge(
// @AuthenticationPrincipal UserDetailsImpl userDetails,
// @RequestBody MessageQuery messageQuery
//// @RequestBody Set<Long> messageIds
// ) {
// return service.markAsRead(userDetails, messageQuery.getMessageIds());
// }
//
// /**
// * 管理查询消息详情
// *
// * @param userId 用户ID
// * @param messageId 消息ID
// * @return 用户消息详情
// */
// @GetMapping("/{user-id}/{message-id}")
// @PreAuthorize("hasAuthority('MESSAGE_QUERY')")
// public UserMessage detail(
// @PathVariable("user-id") Long userId,
// @PathVariable("message-id") Long messageId
// ) {
// UserMessage.Id id = new UserMessage.Id(userId, messageId);
// return service.detail(id);
// }
//
// /**
// * 管理员分页查询消息
// *
// * @param query 查询参数
// * @param pageable 分页参数
// * @return 分页数据
// */
// @GetMapping
// @PreAuthorize("hasAuthority('MESSAGE_QUERY')")
// public Page<UserMessage> page(
// UserMessageQuery query,
// @PageableDefault(
// sort = {"message.createAt"},
// direction = Sort.Direction.DESC
// ) Pageable pageable
// ) {
// return service.page(query, pageable);
// }
//
// /**
// * 管理员手动创建消息
// *
// * @param dto 表单数据
// * @return 消息列表
// */
// @PostMapping
// @PreAuthorize("hasAuthority('MESSAGE_CREATE')")
// public boolean create(
// @RequestBody com.zsc.gateway.module.notice.dto.UserMessageDto dto
// ) {
// return service.createByAdmin(dto);
// }
//
// /**
// * 获取消息推送方式
// *
// * @return 消息推送方式列表
// */
// @GetMapping("/setting")
// @PreAuthorize("hasAuthority('MESSAGE_SETTING')")
// public List<MessageSetting> getSetting() {
// return service.getSetting();
// }
//
// /**
// * 设置消息推送方式
// *
// * @param settings 表单数据
// * @return 消息设置
// */
// @PatchMapping("/setting")
// @PreAuthorize("hasAuthority('MESSAGE_SETTING')")
// public List<MessageSetting> saveSetting(
// @RequestBody Set<MessageSetting> settings
// ) {
// return service.saveSetting(settings);
// }
//
//}
package com.zsc.edu.gateway.modules.notice.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.notice.dto.UserMessageDto;
import com.zsc.edu.gateway.modules.notice.entity.MessagePayload;
import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
import com.zsc.edu.gateway.modules.notice.query.UserMessageQuery;
import com.zsc.edu.gateway.modules.notice.service.UserMessageService;
import com.zsc.edu.gateway.modules.notice.vo.UserMessageVo;
import com.zsc.edu.gateway.modules.system.entity.User;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
/**
* 用户消息Controller
*
* @author harry_yao
*/
@AllArgsConstructor
@RestController
@RequestMapping("api/rest/message")
public class UserMessageController {
private final UserMessageService service;
/**
* 普通用户查看消息详情
*
* @param userDetails 操作用户
* @param messageId 消息ID
* @return 用户消息详情
*/
@GetMapping("/self/{messageId}")
public UserMessageVo selfDetail(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("messageId") Long messageId) {
return service.detail(messageId, userDetails.getId());
}
/**
* 普通用户分页查询消息不能设置查询参数userId和username
*
* @param userDetails 操作用户
* @param query 查询参数
* @return 分页数据
*/
@GetMapping("/self")
public IPage<UserMessageVo> selfPage(@AuthenticationPrincipal UserDetailsImpl userDetails, UserMessageQuery query) {
query.userId = userDetails.id;
query.name = null;
Page<UserMessageVo> page = new Page<>(query.getPageNum(), query.getPageSize());
return service.page(page, query);
}
/**
* 普通用户统计自己未读消息数量
*
* @param userDetails 操作用户
* @return 数据
*/
@GetMapping("/countUnread")
public int countUnread(@AuthenticationPrincipal UserDetailsImpl userDetails) {
return service.countUnread(userDetails);
}
/**
* 普通用户确认消息已读如果提交的已读消息ID集合为空则将所有未读消息设为已读
*
* @param userDetails 操作用户
* @param messageIds 已读消息ID集合
* @return 确认已读数量
*/
@PatchMapping("/read")
public int acknowledge(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody List<Long> messageIds) {
return service.markAsRead(userDetails, messageIds);
}
/**
* 管理查询消息详情
*
* @param userId 用户ID
* @param messageId 消息ID
* @return 用户消息详情
*/
@GetMapping("/{userId}/{messageId}")
@PreAuthorize("hasAuthority('MESSAGE_QUERY')")
public UserMessageVo detail(@PathVariable("userId") Long userId, @PathVariable("messageId") Long messageId) {
return service.detail(messageId, userId);
}
/**
* 管理员分页查询消息
*
* @param query 查询参数
* @return 分页数据
*/
@GetMapping
@PreAuthorize("hasAuthority('MESSAGE_QUERY')")
public IPage<UserMessageVo> page(UserMessageQuery query) {
Page<UserMessageVo> page = new Page<>(query.getPageNum(), query.getPageSize());
return service.page(page, query);
}
/**
* 管理员手动创建消息
*
* @param dto 表单数据
* @return 消息列表
*/
@PostMapping
@PreAuthorize("hasAuthority('MESSAGE_CREATE')")
public Boolean create(@RequestBody UserMessageDto dto) {
return service.createByAdmin(dto);
}
/**
* 获取消息推送方式
*
* @return 消息推送方式列表
*/
@GetMapping("/setting")
@PreAuthorize("hasAuthority('MESSAGE_SETTING')")
public List<MessageSetting> getSetting() {
return service.getSetting();
}
/**
* 设置消息推送方式
*
* @param settings 表单数据
* @return 消息设置
*/
@PatchMapping("/setting")
@PreAuthorize("hasAuthority('MESSAGE_SETTING')")
public List<MessageSetting> saveSetting(@RequestBody List<MessageSetting> settings) {
return service.saveSetting(settings);
}
/**
* 系统自动创建用户消息并发送
*
* @param receivers 接收者
* @param payload 消息内容
*/
@PostMapping("/system/setting")
@PreAuthorize("hasAuthority('MESSAGE_SETTING')")
public Boolean createBySystem(Set<User> receivers, MessagePayload payload) {
return service.createBySystem(receivers, payload);
}
}

View File

@ -1,17 +0,0 @@
//package com.zsc.edu.gateway.modules.notice.dto;
//
//import lombok.AllArgsConstructor;
//import lombok.Data;
//import lombok.NoArgsConstructor;
//
//import java.util.Set;
///**
// * @author zhuang
// */
//@Data
//@AllArgsConstructor
//@NoArgsConstructor
//public class BulletinAttachmentCreateDto {
//
// private String attachmentIds;
//}

View File

@ -33,17 +33,17 @@ public class UserMessageDto {
/**
* 是否需要发送邮件
*/
public boolean email;
public Boolean email;
/**
* 是否需要发送短信
*/
public boolean sms;
public Boolean sms;
/**
* 消息内容是否富文本True则以富文本形式发送
*/
public boolean html;
public Boolean html;
/**
* 消息标题

View File

@ -30,22 +30,22 @@ public class Message extends BaseEntity {
/**
* 是否系统生成
*/
public boolean system;
public Boolean system;
/**
* 是否需要发送邮件
*/
public boolean email;
public Boolean email;
/**
* 是否需要发送短信
*/
public boolean sms;
public Boolean sms;
/**
* 消息内容是否富文本True则以富文本形式发送
*/
public boolean html;
public Boolean html;
/**
* 标题

View File

@ -12,7 +12,7 @@ public abstract class MessagePayload {
public MessageType type;
public String content;
public boolean html;
public Boolean html;
public static class Other extends MessagePayload {
public Other(String content) {

View File

@ -7,6 +7,8 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Objects;
/**
* 消息设置
@ -29,21 +31,23 @@ public class MessageSetting {
/**
* 是否发送邮件
*/
public boolean email;
public Boolean email;
/**
* 是否发送短信
*/
public boolean sms;
public Boolean sms;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MessageSetting that = (MessageSetting) o;
return id == that.id;
return Objects.equals(id, that.id);
}
@Override

View File

@ -1,12 +1,10 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.gateway.modules.system.entity.User;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import java.io.Serializable;
import java.time.LocalDateTime;
@ -16,8 +14,7 @@ import java.time.LocalDateTime;
*
* @author harry_yao
*/
@Setter
@Getter
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_user_message")
@ -25,24 +22,39 @@ public class UserMessage implements Serializable {
@TableId
private Long id;
/**
* 用户ID
*/
public Long userId;
/**
* 用户
*/
@TableField(exist = false)
public User user;
/**
* 消息ID
*/
public Long messageId;
/**
* 消息
*/
@TableField(exist = false)
public Message message;
/**
* 是否已读
*/
public boolean read;
public Boolean isRead;
/**
* 阅读时间
*/
public LocalDateTime readTime;
public UserMessage(Object o, User user, Message message, boolean b, Object o1) {
}
}

View File

@ -1,11 +0,0 @@
//package com.zsc.edu.gateway.modules.notice.mapper;
//
//import org.mapstruct.Mapper;
//import org.mapstruct.ReportingPolicy;
//
///**
// * @author zhuang
// */
//@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
//public interface BulletinUserMapper extends BaseMapper<>{
//}

View File

@ -27,17 +27,9 @@ public class BulletinQuery {
private Integer pageSize = 10;
private String title;
private Bulletin.State state;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime publishTimeBegin;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime publishTimeEnd;
private Boolean isRead;
public LambdaQueryWrapper<BulletinVo> wrapper() {
LambdaQueryWrapper<BulletinVo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.hasText(this.title), BulletinVo::getTitle, this.title);
queryWrapper.eq(Objects.nonNull(this.state), BulletinVo::getState, this.state);
if(Objects.nonNull(this.publishTimeBegin)&&Objects.nonNull(this.publishTimeEnd)) {
queryWrapper.between(BulletinVo::getPublishTime,publishTimeBegin,publishTimeEnd);
}
queryWrapper.eq(Objects.nonNull(this.isRead), BulletinVo::getIsRead, this.isRead);
return queryWrapper;
}
}

View File

@ -52,7 +52,7 @@ public class UserMessageQuery {
/**
* 是否已读
*/
public Boolean read;
public Boolean isRead;
/**
* 消息创建时间区间起始
@ -66,12 +66,7 @@ public class UserMessageQuery {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
public LocalDateTime createAtEnd;
private Integer pageNum = 1;
private Integer pageSize = 10;
public LambdaQueryWrapper<UserMessage> wrapper() {
LambdaQueryWrapper<UserMessage> queryWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<Message> messageQueryWrapper = new LambdaQueryWrapper<>();
messageQueryWrapper.like(StringUtils.hasText(this.title), Message::getTitle, this.title);
// messageQueryWrapper.eq(Objects::nonNull(this.type) Message::getType, this.type);
return queryWrapper;
}
}

View File

@ -3,6 +3,9 @@ package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.BulletinAttachment;
/**
* @author zhuang
*/
public interface BulletinAttachmentRepository extends BaseMapper<BulletinAttachment> {
}

View File

@ -4,6 +4,7 @@ package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.modules.notice.dto.PageDto;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
@ -22,4 +23,5 @@ public interface BulletinRepository extends BaseMapper<Bulletin> {
BulletinVo selectByBulletinId(@Param("bulletinId") Long bulletinId);
IPage<BulletinVo> selectPageByConditions(Page<BulletinVo> page, @Param("query") BulletinQuery query);
}

View File

@ -3,6 +3,9 @@ package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 消息设置Repo
@ -10,5 +13,6 @@ import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
* @author harry_yao
*/
public interface MessageSettingRepository extends BaseMapper<MessageSetting> {
@Select("select * from sys_message_setting")
List<MessageSetting> findAll();
}

View File

@ -1,7 +1,14 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
import com.zsc.edu.gateway.modules.notice.query.BulletinQuery;
import com.zsc.edu.gateway.modules.notice.query.UserMessageQuery;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import com.zsc.edu.gateway.modules.notice.vo.UserMessageVo;
import org.apache.ibatis.annotations.Param;
/**
* 用户消息Repo
@ -9,5 +16,7 @@ import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
* @author harry_yao
*/
public interface UserMessageRepository extends BaseMapper<UserMessage> {
UserMessageVo selectByMessageIdAndUserId(@Param("messageId") Long messageId, @Param("userId") Long userId);
IPage<UserMessageVo> query(Page<UserMessageVo> page, @Param("query") UserMessageQuery query);
}

View File

@ -1,5 +1,6 @@
package com.zsc.edu.gateway.modules.notice.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
@ -34,4 +35,5 @@ public interface BulletinService extends IService<Bulletin> {
Boolean insertInto(Long bulletinId, Set<String> attachmentIds);
IPage<BulletinVo> selectPageByConditions(Page<BulletinVo> page, BulletinQuery query);
}

View File

@ -1,12 +1,21 @@
package com.zsc.edu.gateway.modules.notice.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.notice.dto.UserMessageDto;
import com.zsc.edu.gateway.modules.notice.entity.MessagePayload;
import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
import com.zsc.edu.gateway.modules.notice.query.BulletinQuery;
import com.zsc.edu.gateway.modules.notice.query.UserMessageQuery;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import com.zsc.edu.gateway.modules.notice.vo.UserMessageVo;
import com.zsc.edu.gateway.modules.system.entity.User;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Set;
/**
@ -14,11 +23,23 @@ import java.util.Set;
*
* @author harry_yao
*/
public interface UserMessageService extends IService<UserMessageService> {
public interface UserMessageService extends IService<UserMessage> {
Boolean createByAdmin(UserMessageDto dto);
public UserMessage detail(Long id);
UserMessageVo detail(Long messageId, Long userId);
public boolean createBySystem(Set<User> receivers, MessagePayload payload);
List<MessageSetting> getSetting();
IPage<UserMessageVo> page(Page<UserMessageVo> page, UserMessageQuery query);
Integer countUnread(UserDetailsImpl userDetails);
Integer markAsRead(UserDetailsImpl userDetails, List<Long> messageIds);
@Transactional
List<MessageSetting> saveSetting(List<MessageSetting> settings);
@Transactional
Boolean createBySystem(Set<User> receivers, MessagePayload payload);
}

View File

@ -1,6 +1,7 @@
package com.zsc.edu.gateway.modules.notice.service.impl;
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 com.zsc.edu.gateway.exception.ConstraintException;
@ -195,4 +196,9 @@ public class BulletinServiceImpl extends ServiceImpl<BulletinRepository, Bulleti
queryWrapper.in(Bulletin::getId, ids);
return repo.selectList(queryWrapper);
}
@Override
public IPage<BulletinVo> selectPageByConditions(Page<BulletinVo> page, BulletinQuery query) {
return baseMapper.selectPageByConditions(page, query);
}
}

View File

@ -1,170 +1,205 @@
//package com.zsc.edu.gateway.modules.notice.service.impl;
//
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
//import com.zsc.edu.gateway.modules.attachment.service.AttachmentService;
//import com.zsc.edu.gateway.modules.notice.dto.UserMessageDto;
//import com.zsc.edu.gateway.modules.notice.entity.Message;
//import com.zsc.edu.gateway.modules.notice.entity.MessagePayload;
//import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
//import com.zsc.edu.gateway.modules.notice.repo.MessageRepository;
//import com.zsc.edu.gateway.modules.notice.repo.MessageSettingRepository;
//import com.zsc.edu.gateway.modules.notice.repo.UserMessageRepository;
//import com.zsc.edu.gateway.modules.notice.service.UserMessageService;
//import com.zsc.edu.gateway.modules.system.entity.User;
//import com.zsc.edu.gateway.modules.system.service.UserService;
//import lombok.AllArgsConstructor;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.util.List;
//import java.util.Optional;
//import java.util.Set;
//import java.util.concurrent.atomic.AtomicBoolean;
//import java.util.stream.Collectors;
//
///**
// * 用户消息Service
// *
// * @author harry_yao
// */
//@AllArgsConstructor
//@Service
//public class UserMessageServiceImpl extends ServiceImpl<UserMessageRepository, UserMessage> implements UserMessageService {
//
// private final MessageRepository messageRepo;
// private final MessageSettingRepository messageSettingRepo;
// private final UserService userService;
// private final AttachmentService attachmentService;
//// private final EmailSender emailSender;
//// private final SmsSender smsSender;
//
//
// /**
// * 查询用户消息详情
// *
// * @param id ID
// * @return 用户消息详情
// */
// @Override
// public UserMessage detail(Long id) {
// return getById(id);
// }
//
// /**
// * 分页查询用户消息
// *
// * @param query 查询表单
// * @param pageable 分页参数
// * @return 页面数据
// */
//// public Page<UserMessage> page(UserMessageQuery query, Pageable pageable) {
//// return this.page(query, pageable);
//// }
//
// /**
// * 管理员手动创建用户消息并发送
// *
// * @param dto 表单数据
// * @return 创建的用户消息列表
// */
// @Transactional
// @Override
// public Boolean createByAdmin(UserMessageDto dto) {
// Set<User> users = dto.userIds.stream().map(userService::getById).collect(Collectors.toSet());
// List<Attachment> attachments = attachmentService.listByIds(dto.attachmentIds);
// Message message = new Message(dto.type, false, dto.email, dto.sms, dto.html,
// dto.title, dto.content, attachments);
// messageRepo.insert(message);
// Set<UserMessage> userMessages = users.stream().map(user ->
// new UserMessage(null, user, message, false, null)).collect(Collectors.toSet());
// send(users, message);
// return saveBatch(userMessages);
// }
//
// /**
// * 系统自动创建用户消息并发送
// *
// * @param receivers 接收者
// * @param payload 消息内容
// */
// @Transactional
// @Override
// public boolean createBySystem(Set<User> receivers, MessagePayload payload) {
// AtomicBoolean email = new AtomicBoolean(false);
// AtomicBoolean sms = new AtomicBoolean(false);
// Optional.of(messageSettingRepo.selectById(payload.type)).ifPresent(messageSetting -> {
// email.set(messageSetting.email);
// sms.set(messageSetting.sms);
// });
// Message message = new Message(payload.type, true, email.get(), sms.get(),
// payload.html, payload.type.name(), payload.content, null);
// messageRepo.insert(message);
// Set<UserMessage> userMessages = receivers.stream().map(user ->
// new UserMessage(null, user, message, false, null)).collect(Collectors.toSet());
//// List<UserMessage> list = saveBatch(userMessages);
// send(receivers, message);
// return saveBatch(userMessages);
// }
//
// /**
// * 统计用户未读消息数量
// *
// * @param userDetails 操作用户
// * @return 未读消息数量
// */
//// public int countUnread(UserDetailsImpl userDetails) {
//// return repo.countByUserIdAndRead(userDetails.id, false);
//// }
//
// /**
// * 设为已读
// *
// * @param userDetails 操作用户
// * @param messageIds 消息ID集合如为空则将该用户的所有未读消息设为已读
// * @return 修改记录数量
// */
//// public int markAsRead(UserDetailsImpl userDetails, Set<Long> messageIds) {
//// if (CollectionUtils.isEmpty(messageIds)) {
//// return repo.markAsRead(userDetails.id, LocalDateTime.now());
//// }
//// return repo.markAsRead(userDetails.id, messageIds, LocalDateTime.now());
//// }
//
// /**
// * 获取所有消息推送方式
// *
// * @return 消息设置列表
// */
//// public List<MessageSetting> getSetting() {
//// return messageSettingRepo.findAll();
//// }
//
// /**
// * 设置消息推送方式
// *
// * @param settings 消息设置集合
// * @return 消息设置列表
// */
//// public List<MessageSetting> saveSetting(Set<MessageSetting> settings) {
//// return messageSettingRepo.saveAll(settings);
//// }
//
// /**
// * 以邮件短信等形式发送消息只有非html格式的消息才能以短信方式发送
// *
// * @param users 接收者
// * @param message 消息
// */
// @Async
// void send(Set<User> users, Message message) {
// if (message.email) {
// emailSender.send(users.stream().map(User::getEmail).collect(Collectors.toSet()), message);
// }
// if (message.sms && !message.html) {
// smsSender.send(users.stream().map(User::getPhone).collect(Collectors.toSet()), message.content);
// }
// }
//
//}
package com.zsc.edu.gateway.modules.notice.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsc.edu.gateway.framework.message.email.EmailSender;
import com.zsc.edu.gateway.framework.message.sms.SmsSender;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
import com.zsc.edu.gateway.modules.attachment.service.AttachmentService;
import com.zsc.edu.gateway.modules.notice.dto.UserMessageDto;
import com.zsc.edu.gateway.modules.notice.entity.*;
import com.zsc.edu.gateway.modules.notice.query.UserMessageQuery;
import com.zsc.edu.gateway.modules.notice.repo.MessageRepository;
import com.zsc.edu.gateway.modules.notice.repo.MessageSettingRepository;
import com.zsc.edu.gateway.modules.notice.repo.UserMessageRepository;
import com.zsc.edu.gateway.modules.notice.service.UserMessageService;
import com.zsc.edu.gateway.modules.notice.vo.UserMessageVo;
import com.zsc.edu.gateway.modules.system.entity.User;
import com.zsc.edu.gateway.modules.system.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* 用户消息Service
*
* @author harry_yao
*/
@AllArgsConstructor
@Service
public class UserMessageServiceImpl extends ServiceImpl<UserMessageRepository, UserMessage> implements UserMessageService {
private final MessageRepository messageRepo;
private final MessageSettingRepository messageSettingRepo;
private final UserService userService;
private final AttachmentService attachmentService;
private final EmailSender emailSender;
private final SmsSender smsSender;
private final UserMessageRepository userMessageRepository;
/**
* 查询消息详情
*
* @param messageId 消息ID
* @param userId 用户ID
* @return 查询详情
*/
@Override
public UserMessageVo detail(Long messageId, Long userId) {
return userMessageRepository.selectByMessageIdAndUserId(messageId, userId);
}
/**
* 分页查询用户消息
*
* @param query 查询表单
* @param page 分页参数
* @return 页面数据
*/
@Override
public IPage<UserMessageVo> page(Page<UserMessageVo> page, UserMessageQuery query) {
return userMessageRepository.query(page, query);
}
/**
* 统计用户未读消息数量
*
* @param userDetails 操作用户
* @return 未读消息数量
*/
@Override
public Integer countUnread(UserDetailsImpl userDetails) {
QueryWrapper<UserMessage> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userDetails.getId()).eq("is_read", true);
return Math.toIntExact(userMessageRepository.selectCount(queryWrapper));
}
/**
* 设为已读
*
* @param userDetails 操作用户
* @param messageIds 消息ID集合如为空则将该用户的所有未读消息设为已读
* @return 修改记录数量
*/
@Override
public Integer markAsRead(UserDetailsImpl userDetails, List<Long> messageIds) {
if (CollectionUtils.isEmpty(messageIds)) {
throw new RuntimeException("messageIds is NULL!");
}
UpdateWrapper<UserMessage> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("user_id", userDetails.getId()).in("message_id", messageIds);
updateWrapper.set("is_read", false);
updateWrapper.set("read_time", LocalDateTime.now());
return userMessageRepository.update(updateWrapper);
}
/**
* 管理员手动创建用户消息并发送
*
* @param dto 表单数据
* @return 创建的用户消息列表
*/
@Transactional
@Override
public Boolean createByAdmin(UserMessageDto dto) {
Set<User> users = dto.userIds.stream().map(userService::getById).collect(Collectors.toSet());
List<Attachment> attachments = attachmentService.listByIds(dto.attachmentIds);
Message message = new Message(dto.type, false, dto.email, dto.sms, dto.html,
dto.title, dto.content, attachments);
messageRepo.insert(message);
Set<UserMessage> userMessages = users.stream().map(user ->
new UserMessage(null, user, message, false, null)).collect(Collectors.toSet());
send(users, message);
return saveBatch(userMessages);
}
/**
* 获取所有消息推送方式
*
* @return 消息设置列表
*/
@Override
public List<MessageSetting> getSetting() {
return messageSettingRepo.findAll();
}
/**
* 设置消息推送方式
*
* @param settings 消息设置集合
* @return 消息设置列表
*/
@Transactional
@Override
public List<MessageSetting> saveSetting(List<MessageSetting> settings) {
if (CollectionUtils.isEmpty(settings)) {
throw new RuntimeException("settings is NULL!");
}
for (MessageSetting setting : settings) {
try {
messageSettingRepo.insert(setting);
} catch (Exception e) {
throw new RuntimeException("设置失败" + e.getMessage());
}
}
return settings;
}
/**
* 以邮件短信等形式发送消息只有非html格式的消息才能以短信方式发送
*
* @param users 接收者
* @param message 消息
*/
@Async
void send(Set<User> users, Message message) {
if (message.email) {
emailSender.send(users.stream().map(User::getEmail).collect(Collectors.toSet()), message);
}
if (message.sms && !message.html) {
smsSender.send(users.stream().map(User::getPhone).collect(Collectors.toSet()), message.content);
}
}
/**
* 系统自动创建用户消息并发送
*
* @param receivers 接收者
* @param payload 消息内容
*/
@Transactional
@Override
public Boolean createBySystem(Set<User> receivers, MessagePayload payload) {
AtomicBoolean email = new AtomicBoolean(false);
AtomicBoolean sms = new AtomicBoolean(false);
Optional.of(messageSettingRepo.selectById(payload.type)).ifPresent(messageSetting -> {
email.set(messageSetting.email);
sms.set(messageSetting.sms);
});
Message message = new Message(payload.type, true, email.get(), sms.get(),
payload.html, payload.type.name(), payload.content, null);
messageRepo.insert(message);
Set<UserMessage> userMessages = receivers.stream().map(user ->
new UserMessage(null, user, message, false, null)).collect(Collectors.toSet());
send(receivers, message);
return saveBatch(userMessages);
}
}

View File

@ -32,11 +32,11 @@ public class DeptController {
* @param query 查询表单
* @return 部门列表
*/
@GetMapping
@PreAuthorize("hasAuthority('DEPT_QUERY')")
public Page<Dept> query(DeptQuery query, Page<Dept> page) {
return service.page(page, query.wrapper());
}
// @GetMapping
// @PreAuthorize("hasAuthority('DEPT_QUERY')")
// public Dept query(DeptQuery query, Page<Dept> page) {
// return service.page(page, query.wrapper());
// }
/**
* 新建管理部门 hasAuthority('DEPT_CREATE')

View File

@ -35,6 +35,9 @@ spring:
properties:
mail:
smtp:
auth: true
starttls:
enable: true
socketFactoryClass: javax.net.ssl.SSLSocketFactory
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
debug: true

View File

@ -156,9 +156,9 @@ create table sys_message
title varchar,
content varchar,
remark varchar,
create_time time,
create_time timestamp,
create_by varchar,
update_time time,
update_time timestamp,
update_by varchar
);
comment on table sys_message is '消息';
@ -297,16 +297,16 @@ create table sys_user_message
id bigint not null
constraint sys_user_message_pk
primary key,
"user" sys_user not null,
message sys_message not null,
read boolean not null,
read_time time
user_id bigint not null,
message_id bigint not null,
is_read boolean not null,
read_time timestamp
);
comment on table sys_user_message is '用户消息';
comment on column sys_user_message.id is '主键';
comment on column sys_user_message."user" is '用户';
comment on column sys_user_message.message is '消息';
comment on column sys_user_message.read is '是否已读';
comment on column sys_user_message.user_id is '用户';
comment on column sys_user_message.message_id is '消息';
comment on column sys_user_message.is_read is '是否已读';
comment on column sys_user_message.read_time is '阅读时间';
alter table sys_user_message
owner to postgres;
@ -409,3 +409,39 @@ INSERT INTO "attachment" VALUES ('84fa4f586f190886ea8708c49e8645f5a9a1ea04', '
INSERT INTO "sys_bulletin" VALUES (1,'测试测试测试测试测试测试测试',1,true,50,'2024-03-21 15:20:03',51,'2024-03-21 15:20:03',54,'2024-03-21 15:20:03','测试测试测试数据',null,null,null,null);
INSERT INTO "sys_bulletin_attach" VALUES (1,'195bd3517bfcd9915906957730bdd6fef7fa5a86')
INSERT INTO sys_message (id, type, system, email, sms, html, title, content, remark, create_time, create_by,
update_time, update_by)
VALUES (1, 1, TRUE, FALSE, TRUE, FALSE, '系统通知', '系统维护通知', '例行维护', NOW(), 'admin', NOW(), 'admin'),
(2, 1, FALSE, TRUE, FALSE, TRUE, '用户注册', '欢迎注册我们的平台', '感谢您的注册', NOW() - INTERVAL '1 day',
'user1', NOW() - INTERVAL '1 day', 'user1'),
(3, 1, TRUE, TRUE, FALSE, FALSE, '密码重置', '您的密码已重置', '请尽快登录并修改密码', NOW() - INTERVAL '2 days',
'admin', NOW() - INTERVAL '2 days', 'admin'),
(4, 1, FALSE, FALSE, TRUE, TRUE, '订单确认', '您的订单已确认', '订单号123456789', NOW() - INTERVAL '3 days',
'user2', NOW() - INTERVAL '3 days', 'user2'),
(5, 1, TRUE, FALSE, TRUE, FALSE, '系统更新', '系统已更新到最新版本', '新功能介绍', NOW() - INTERVAL '4 days',
'admin', NOW() - INTERVAL '4 days', 'admin'),
(6, 1, FALSE, TRUE, FALSE, TRUE, '活动邀请', '您被邀请参加我们的活动', '活动详情见附件',
NOW() - INTERVAL '5 days', 'user3', NOW() - INTERVAL '5 days', 'user3'),
(7, 1, TRUE, TRUE, FALSE, FALSE, '账户激活', '您的账户已激活', '您可以开始使用了', NOW() - INTERVAL '6 days',
'admin', NOW() - INTERVAL '6 days', 'admin'),
(8, 1, FALSE, FALSE, TRUE, TRUE, '支付成功', '您的支付已成功', '感谢您的支持', NOW() - INTERVAL '7 days',
'user4', NOW() - INTERVAL '7 days', 'user4'),
(9, 1, TRUE, FALSE, TRUE, FALSE, '安全提醒', '请检查您的账户安全设置', '安全提示', NOW() - INTERVAL '8 days',
'admin', NOW() - INTERVAL '8 days', 'admin'),
(10, 1, FALSE, TRUE, FALSE, TRUE, '反馈回复', '感谢您的反馈', '我们会尽快处理', NOW() - INTERVAL '9 days',
'user5', NOW() - INTERVAL '9 days', 'user5');
INSERT INTO sys_message_setting (id, email, sms)
VALUES (1, TRUE, FALSE),
(2, FALSE, TRUE),
(3, TRUE, TRUE),
(4, FALSE, FALSE),
(5, TRUE, FALSE),
(6, FALSE, TRUE),
(7, TRUE, TRUE),
(8, FALSE, FALSE),
(9, TRUE, FALSE),
(10, FALSE, TRUE);

View File

@ -32,7 +32,28 @@
left join sys_bulletin_user sbu on sb.id=sbu.bulletin_id
left join sys_user su on sbu.user_id=su.id
where sb.id=#{bulletinId}
order by sb.top DESC, sb.create_time DESC;
</select>
<select id="selectPageByConditions" resultType="com.zsc.edu.gateway.modules.notice.vo.BulletinVo">
select sb.*,a.id as attachment_id,a.file_name as attachment_file_name,a.mime_type as attachment_mime_type,a.url
as attachment_url,a.upload_time as attachment_upload_time,sbu.is_read
from sys_bulletin sb
left join sys_bulletin_attach sba on sb.id=sba.bulletin_id
left join attachment a on a.id=sba.attachment_id
left join sys_bulletin_user sbu on sb.id=sbu.bulletin_id
left join sys_user su on sbu.user_id=su.id where 1=1
<if test="query.title != null and query.title != ''">
AND sb.title LIKE CONCAT('%', #{query.title}, '%')
</if>
<if test="query.state != null">
AND sb.state = #{query.state}
</if>
<if test="query.publishTimeBegin != null and query.publishTimeEnd != null">
AND sb.publish_time BETWEEN #{query.publishTimeBegin} AND #{query.publishTimeEnd}
</if>
<if test="query.isRead != null">
AND sbu.is_read = #{query.isRead}
</if>
order by sb.top DESC,sb.publish_time DESC,sb.create_time DESC
</select>
</mapper>