Compare commits

..

2 Commits

Author SHA1 Message Date
060d90ecb2 公告模块 2024-11-26 16:16:08 +08:00
47f0dd437a 公告模块 2024-11-16 12:17:07 +08:00
43 changed files with 1970 additions and 2 deletions

View File

@ -0,0 +1,61 @@
package com.zsc.edu.gateway;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zsc.edu.gateway.modules.system.dto.RoleDto;
import com.zsc.edu.gateway.modules.system.entity.*;
import com.zsc.edu.gateway.modules.system.repo.DeptRepository;
import com.zsc.edu.gateway.modules.system.repo.RoleRepository;
import com.zsc.edu.gateway.modules.system.repo.UserRepository;
import com.zsc.edu.gateway.modules.system.repo.UserRolesRepository;
import com.zsc.edu.gateway.modules.system.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
/**
* @author zhuang
*/
@RequiredArgsConstructor
@Component
@Profile("!test")
public class FirstTimeInitializer implements CommandLineRunner {
private final DeptRepository deptRepo;
private final RoleRepository roleRepo;
private final RoleService roleService;
private final UserRolesRepository userRolesRepo;
private final UserRepository userRepo;
private final PasswordEncoder passwordEncoder;
@Override
public void run(String... args) throws Exception {
Dept dept1 = new Dept();
Role role = new Role();
if (deptRepo.selectCount(new QueryWrapper<>()) == 0) {
dept1.setName("管理部门");
deptRepo.insert(dept1);
}
if (roleRepo.selectCount(new QueryWrapper<>()) == 0) {
RoleDto dto = new RoleDto();
dto.setName("超级管理员");
// dto.setAuthorities(new HashSet<>(Arrays.asList(Authority.values())));
role = roleService.create(dto);
}
if (userRepo.selectCount(new QueryWrapper<>()) == 0) {
User user = new User();
user.setUsername("管理员");
user.setPassword(passwordEncoder.encode("123456"));
user.setEnableState(true);
user.setPhone("13827993921");
user.setEmail("123@qq.com");
user.setDeptId(dept1.getId());
user.setRoleId(role.getId());
userRepo.insert(user);
}
}
}

View File

@ -0,0 +1,36 @@
package com.zsc.edu.gateway.common.enums;
import com.zsc.edu.gateway.exception.StateException;
import java.util.EnumSet;
/**
* @author harry_yao
*/
public interface IState<T extends Enum<T>> {
/**
* 用于检查对象当前状态是否等于correctStatus
*
* @param correctState 正确状态
*/
default void checkStatus(T correctState) {
if (this != correctState) {
throw new StateException(correctState.getClass(), this, correctState);
}
}
/**
* 用于检查对象当前状态是否在集合correctStates中
*
* @param correctStates 正确状态集合
*/
@SuppressWarnings("SuspiciousMethodCalls")
default void checkStatus(EnumSet<T> correctStates) {
if (!correctStates.contains(this)) {
throw new StateException(this.getClass(), this, correctStates);
}
}
}

View File

@ -17,7 +17,7 @@ public class MybatisPlusConfig {
@Bean @Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() { public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
// // 添加数据权限插件 // // 添加数据权限插件
// MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor(); // MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor();
// // 添加自定义的数据权限处理器 // // 添加自定义的数据权限处理器

View File

@ -0,0 +1,167 @@
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.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;
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/bulletin")
public class BulletinController {
private final BulletinService service;
private final BulletinVoService bulletinVoService;
/**
* 普通用户查看公告详情
*
* @param id ID
* @return 公告
*/
@GetMapping("/self/{id}")
public BulletinVo selfDetail(@AuthenticationPrincipal UserDetailsImpl userDetails,@PathVariable("id") Long id) {
return service.detail(userDetails,id, Bulletin.State.publish);
}
/**
* 普通用户分页查询公告
*
* @param query 查询表单
* @return 分页数据
*/
@GetMapping("/query")
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);
}
/**
* 管理查询公告详情
*
* @param id ID
* @return 公告
*/
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_QUERY')")
public BulletinVo detail(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("id") Long id) {
return service.detail(userDetails,id, null);
}
/**
* 管理员分页查询公告
*
* @param query 查询参数
* @return 分页数据
*/
@GetMapping()
@PreAuthorize("hasAuthority('BULLETIN_QUERY')")
public IPage<BulletinVo> query( BulletinQuery query) {
Page<BulletinVo> page = new Page<>(query.getPageNum(), query.getPageSize());
return bulletinVoService.selectPageByConditions(page, query);
}
/**
* 创建公告
*
* @param userDetails 操作用户
* @param dto 表单数据
* @return 公告
*/
@PostMapping
@PreAuthorize("hasAuthority('BULLETIN_CREATE')")
public Bulletin create(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody BulletinDto dto) {
return service.create(userDetails, dto);
}
/**
* 更新公告只能修改"编辑中""已发布"的公告"已发布"的公告修改后会改为"编辑中"
*
* @param userDetails 操作用户
* @param dto 表单数据
* @param id ID
* @return 公告
*/
@PatchMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
public Boolean update(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody BulletinDto dto, @PathVariable("id") Long id) {
return service.update(userDetails, dto, id);
}
/**
* 切换公告置顶状态
*
* @param id ID
* @return 公告
*/
@PatchMapping("/{id}/toggle-top")
@PreAuthorize("hasAuthority('BULLETIN_UPDATE')")
public Boolean toggleTop(@PathVariable("id") Long id) {
return service.toggleTop(id);
}
/**
* 发布公告只能发布"编辑中"的公告
*
* @param userDetails 操作用户
* @param ids IDs
* @return 公告
*/
@PatchMapping("/publish")
@PreAuthorize("hasAuthority('BULLETIN_PUBLISH')")
public List<String> publish(@AuthenticationPrincipal UserDetailsImpl userDetails,@RequestBody List<Long> ids) {
return service.publish(userDetails, ids);
}
/**
* 关闭公告只能关闭"已发布"的公告
*
* @param userDetails 操作用户
* @param id ID
* @return 公告
*/
@PatchMapping("/{id}/toggleClose")
@PreAuthorize("hasAuthority('BULLETIN_CLOSE')")
public Boolean toggleClose(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable("id") Long id) {
return service.close(userDetails, id);
}
/**
* 删除公告只能删除"编辑中"的公告
*
* @param id ID
* @return
*/
@DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('BULLETIN_DELETE')")
public Boolean delete(@PathVariable("id") Long id) {
return service.removeById(id);
}
/**
*为公告添加附件
*/
@PostMapping("/{id}/add")
@PreAuthorize("hasAuthority('BULLETIN_CREATE')")
public Boolean insertInto(@PathVariable Long id,@RequestBody Set<String> attachments){
return service.insertInto(id, attachments);
}
}

View File

@ -0,0 +1,164 @@
//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);
// }
//
//}

View File

@ -0,0 +1,17 @@
//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

@ -0,0 +1,18 @@
package com.zsc.edu.gateway.modules.notice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zhuang
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BulletinAttachmentDto {
private Long bulletinId;
private String attachmentId;
}

View File

@ -0,0 +1,44 @@
package com.zsc.edu.gateway.modules.notice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotBlank;
import java.util.List;
/**
* @author harry_yao
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BulletinDto {
/**
* 标题
*/
@NotBlank(message = "接收用户不能为空")
public String title;
/**
* 是否置顶
*/
public boolean top;
/**
* 内容
*/
@NotBlank(message = "消息内容不能为空")
public String content;
/**
* 备注
*/
public String remark;
//
// /**
// * 附件ID集合
// */
// private List<String> attachmentIds;
}

View File

@ -0,0 +1,65 @@
package com.zsc.edu.gateway.modules.notice.dto;
import com.zsc.edu.gateway.modules.notice.entity.MessageType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Set;
/**
* @author harry_yao
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserMessageDto {
/**
* 用户ID集合
*/
@NotEmpty(message = "接收用户不能为空")
public Set<Long> userIds;
/**
* 消息类型
*/
@NotNull(message = "消息类型不能为空")
public MessageType type;
/**
* 是否需要发送邮件
*/
public boolean email;
/**
* 是否需要发送短信
*/
public boolean sms;
/**
* 消息内容是否富文本True则以富文本形式发送
*/
public boolean html;
/**
* 消息标题
*/
@NotBlank(message = "消息标题不能为空")
public String title;
/**
* 消息内容
*/
@NotBlank(message = "消息内容不能为空")
public String content;
/**
* 附件ID集合
*/
public Set<String> attachmentIds;
}

View File

@ -0,0 +1,127 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.gateway.common.enums.IState;
import com.zsc.edu.gateway.modules.system.entity.BaseEntity;
import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* 系统公告Domain
*
* @author zhuang
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_bulletin")
public class Bulletin extends BaseEntity {
/**
* 标题
*/
public String title;
/**
* 状态
*/
public State state = State.edit;
/**
* 是否置顶
*/
public Boolean top;
/**
* 编辑者ID
*/
public Long editUserId;
/**
* 编辑者
*/
@TableField(exist = false)
public String editUsername;
/**
* 编辑时间
*/
public LocalDateTime editTime;
/**
* 审核发布者ID
*/
public Long publishUserId;
/**
* 审核发布者
*/
@TableField(exist = false)
public String publishUsername;
/**
* 审核发布时间
*/
public LocalDateTime publishTime;
/**
* 关闭者ID
*/
public Long closeUserId;
/**
* 关闭者
*/
@TableField(exist = false)
public String closeUsername;
/**
* 关闭时间
*/
public LocalDateTime closeTime;
/**
* 内容
*/
public String content;
/**
* 已读状态
*/
@TableField(exist = false)
public Boolean isRead;
/**
* 附件列表
*/
@TableField(exist = false)
public List<Attachment> attachments;
public enum State implements IEnum<Integer>, IState<State> {
edit(1,"编辑中"),
publish(2,"已发布"),
close(3,"已关闭");
private final Integer value;
private final String name;
State(int value, String name) {
this.value=value;
this.name = name;
}
@Override
public Integer getValue() {
return this.value;
}
@Override
public String toString() {
return this.name;
}
}
}

View File

@ -0,0 +1,23 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author zhuang
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_bulletin_attach")
public class BulletinAttachment {
private Long bulletinId;
private String attachmentId;
}

View File

@ -0,0 +1,31 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author zhuang
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_bulletin_user")
public class BulletinUser {
/**
* 公告ID
*/
public Long bulletinId;
/**
* 用户ID
*/
public Long userId;
/**
* 是否已读
*/
public Boolean isRead=true;
}

View File

@ -0,0 +1,65 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.gateway.modules.system.entity.BaseEntity;
import com.zsc.edu.gateway.modules.attachment.entity.Attachment;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
/**
* 消息
*
* @author harry_yao
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_message")
public class Message extends BaseEntity {
/**
* 消息类型
*/
public MessageType type = MessageType.other;
/**
* 是否系统生成
*/
public boolean system;
/**
* 是否需要发送邮件
*/
public boolean email;
/**
* 是否需要发送短信
*/
public boolean sms;
/**
* 消息内容是否富文本True则以富文本形式发送
*/
public boolean html;
/**
* 标题
*/
public String title;
/**
* 消息内容
*/
public String content;
/**
* 附件
*/
public List<Attachment> attachments;
}

View File

@ -0,0 +1,39 @@
package com.zsc.edu.gateway.modules.notice.entity;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 消息内容
*
* @author harry_yao
*/
public abstract class MessagePayload {
public MessageType type;
public String content;
public boolean html;
public static class Other extends MessagePayload {
public Other(String content) {
this.content = content;
this.type = MessageType.other;
}
}
public static class ResetPassword extends MessagePayload {
public String username;
public String password;
public LocalDateTime resetTime;
public ResetPassword(String username, String password, LocalDateTime resetTime) {
this.username = username;
this.password = password;
this.resetTime = resetTime;
this.type =MessageType.resetThePassword;
this.content = String.format("尊敬的用户%s您的密码已于%s被管理员重置新密码为%s" +
"请及时登录系统修改密码!", username, resetTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), password);
}
}
}

View File

@ -0,0 +1,53 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 消息设置
*
* @author harry_yao
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_message_setting")
public class MessageSetting {
/**
* 消息类型
*/
@TableId
public Long id;
/**
* 是否发送邮件
*/
public boolean email;
/**
* 是否发送短信
*/
public boolean sms;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageSetting that = (MessageSetting) o;
return id == that.id;
}
@Override
public int hashCode() {
return id.hashCode();
}
}

View File

@ -0,0 +1,32 @@
package com.zsc.edu.gateway.modules.notice.entity;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.zsc.edu.gateway.common.enums.IState;
/**
* 消息类型
*
* @author zhuang
*/
public enum MessageType implements IEnum<Integer>,IState<MessageType> {
other(1,"其他"),
resetThePassword(2,"重置密码");
private final Integer value;
private final String name;
MessageType(Integer value, String name) {
this.value = value;
this.name = name;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1,48 @@
package com.zsc.edu.gateway.modules.notice.entity;
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 java.io.Serializable;
import java.time.LocalDateTime;
/**
* 用户消息
*
* @author harry_yao
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_user_message")
public class UserMessage implements Serializable {
@TableId
private Long id;
/**
* 用户
*/
public User user;
/**
* 消息
*/
public Message message;
/**
* 是否已读
*/
public boolean read;
/**
* 阅读时间
*/
public LocalDateTime readTime;
}

View File

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

View File

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

View File

@ -0,0 +1,11 @@
//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

@ -0,0 +1,43 @@
package com.zsc.edu.gateway.modules.notice.query;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* 系统公告Query
*
* @author harry_yao
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BulletinQuery {
private Integer pageNum = 1;
private Integer pageSize = 10;
private String title;
private Bulletin.State state;
private LocalDateTime publishTimeBegin;
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

@ -0,0 +1,26 @@
package com.zsc.edu.gateway.modules.notice.query;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsc.edu.gateway.modules.notice.entity.Message;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.StringUtils;
import java.util.Set;
/**
* @author zhuang
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MessageQuery {
Set<Long> messageIds;
public LambdaQueryWrapper<Message> wrapper() {
LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StringUtils.hasText((CharSequence) this.messageIds), Message::getId, this.messageIds);
return queryWrapper;
}
}

View File

@ -0,0 +1,77 @@
package com.zsc.edu.gateway.modules.notice.query;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
import com.zsc.edu.gateway.modules.notice.entity.Message;
import com.zsc.edu.gateway.modules.notice.entity.MessageType;
import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* 用户消息Query
*
* @author harry_yao
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserMessageQuery {
/**
* 用户ID
*/
public Long userId;
/**
* 标题模糊查询
*/
public String title;
/**
* 消息类型
*/
public MessageType type;
/**
* 用户名或真实姓名用户名准确查询姓名模糊查询
*/
public String name;
/**
* 是否系统自动生成
*/
public Boolean system;
/**
* 是否已读
*/
public Boolean read;
/**
* 消息创建时间区间起始
*/
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
public LocalDateTime createAtBegin;
/**
* 消息创建时间区间终止
*/
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
public LocalDateTime createAtEnd;
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

@ -0,0 +1,8 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.BulletinAttachment;
public interface BulletinAttachmentRepository extends BaseMapper<BulletinAttachment> {
}

View File

@ -0,0 +1,25 @@
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.extension.plugins.pagination.Page;
import com.zsc.edu.gateway.modules.notice.dto.PageDto;
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.vo.BulletinVo;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* 公告Repo
*
* @author harry_yao
*/
public interface BulletinRepository extends BaseMapper<Bulletin> {
BulletinVo selectByBulletinId(@Param("bulletinId") Long bulletinId);
}

View File

@ -0,0 +1,16 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.BulletinUser;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* @author zhuang
*/
public interface BulletinUserRepository extends BaseMapper<BulletinUser> {
// @Select("select * from sys_bulletin_user sbu where sbu.bulletin_id=#{bulletinId} and sbu.user_id=#{userId}")
// Boolean selectByBulletinIdAndUserId(@Param("bulletinId") Long bulletinId, @Param("userId") Long userId);
}

View File

@ -0,0 +1,14 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.Message;
/**
* 消息Repo
*
* @author harry_yao
*/
public interface MessageRepository extends BaseMapper<Message> {
}

View File

@ -0,0 +1,14 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.MessageSetting;
/**
* 消息设置Repo
*
* @author harry_yao
*/
public interface MessageSettingRepository extends BaseMapper<MessageSetting> {
}

View File

@ -0,0 +1,13 @@
package com.zsc.edu.gateway.modules.notice.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
/**
* 用户消息Repo
*
* @author harry_yao
*/
public interface UserMessageRepository extends BaseMapper<UserMessage> {
}

View File

@ -0,0 +1,12 @@
package com.zsc.edu.gateway.modules.notice.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zsc.edu.gateway.modules.notice.entity.BulletinAttachment;
/**
* @author zhuang
*/
public interface BulletinAttachmentService extends IService<BulletinAttachment> {
}

View File

@ -0,0 +1,37 @@
package com.zsc.edu.gateway.modules.notice.service;
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.BulletinDto;
import com.zsc.edu.gateway.modules.notice.dto.PageDto;
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.vo.BulletinVo;
import java.util.List;
import java.util.Set;
/**
* 系统公告Service
*
* @author harry_yao
*/
public interface BulletinService extends IService<Bulletin> {
BulletinVo detail(UserDetailsImpl userDetails, Long id, Bulletin.State state);
Bulletin create(UserDetailsImpl userDetails, BulletinDto dto);
Boolean update(UserDetailsImpl userDetails, BulletinDto dto, Long id);
Boolean toggleTop(Long id);
List<String> publish(UserDetailsImpl userDetails, List<Long> id);
Boolean close(UserDetailsImpl userDetails,Long id);
Boolean insertInto(Long bulletinId, Set<String> attachmentIds);
}

View File

@ -0,0 +1,16 @@
package com.zsc.edu.gateway.modules.notice.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.notice.entity.BulletinUser;
/**
* @author zhuang
*/
public interface BulletinUserService extends IService<BulletinUser> {
Boolean isRead(UserDetailsImpl userDetails, Long id);
void toggleIsRead(Long id);
}

View File

@ -0,0 +1,24 @@
package com.zsc.edu.gateway.modules.notice.service;
import com.baomidou.mybatisplus.extension.service.IService;
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.UserMessage;
import com.zsc.edu.gateway.modules.system.entity.User;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
/**
* 用户消息Service
*
* @author harry_yao
*/
public interface UserMessageService extends IService<UserMessageService> {
Boolean createByAdmin(UserMessageDto dto);
public UserMessage detail(Long id);
public boolean createBySystem(Set<User> receivers, MessagePayload payload);
}

View File

@ -0,0 +1,18 @@
package com.zsc.edu.gateway.modules.notice.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsc.edu.gateway.modules.notice.entity.BulletinAttachment;
import com.zsc.edu.gateway.modules.notice.repo.BulletinAttachmentRepository;
import com.zsc.edu.gateway.modules.notice.service.BulletinAttachmentService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
/**
* @author zhuang
*/
@AllArgsConstructor
@Service
public class BulletinAttachmentServiceImpl extends ServiceImpl<BulletinAttachmentRepository, BulletinAttachment> implements BulletinAttachmentService {
}

View File

@ -0,0 +1,198 @@
package com.zsc.edu.gateway.modules.notice.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsc.edu.gateway.exception.ConstraintException;
import com.zsc.edu.gateway.exception.EmptyIdsException;
import com.zsc.edu.gateway.exception.PublishFailedException;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
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.entity.BulletinAttachment;
import com.zsc.edu.gateway.modules.notice.query.BulletinQuery;
import com.zsc.edu.gateway.modules.notice.repo.BulletinRepository;
import com.zsc.edu.gateway.modules.notice.service.BulletinAttachmentService;
import com.zsc.edu.gateway.modules.notice.service.BulletinService;
import com.zsc.edu.gateway.modules.notice.service.BulletinUserService;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import com.zsc.edu.gateway.modules.system.repo.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static com.zsc.edu.gateway.modules.notice.entity.Bulletin.State.*;
/**
* 系统公告Service
*
* @author harry_yao
*/
@AllArgsConstructor
@Service
public class BulletinServiceImpl extends ServiceImpl<BulletinRepository, Bulletin> implements BulletinService {
private final BulletinRepository repo;
private final BulletinAttachmentService bulletinAttachmentService;
private final BulletinUserService bulletinUserService;
private final UserRepository userRepository;
/**
* 查询公告详情
*
* @param id ID
* @param state 公告状态
* @return 公告详情
*/
@Override
public BulletinVo detail(UserDetailsImpl userDetails, Long id, Bulletin.State state) {
BulletinVo bulletin = repo.selectByBulletinId(id);
if (state != null) {
bulletin.getState().checkStatus(state);
}
bulletin.setEditUsername(userRepository.selectNameById(bulletin.getEditUserId()));
bulletin.setPublishUsername(userRepository.selectNameById(bulletin.getPublishUserId()));
bulletin.setCloseUsername(userRepository.selectNameById(bulletin.getCloseUserId()));
bulletinUserService.isRead(userDetails, id);
return bulletin;
}
/**
* 新建公告
*
* @param userDetails 操作用户
* @param dto 表单数据
* @return 新建的公告
*/
@Override
public Bulletin create(UserDetailsImpl userDetails, BulletinDto dto) {
boolean existsByName=count(new LambdaQueryWrapper<Bulletin>().eq(Bulletin::getTitle,dto.getTitle())) > 0;
if(existsByName){
throw new ConstraintException("title", dto.title, "标题已存在");
}
Bulletin bulletin=new Bulletin();
BeanUtils.copyProperties(dto,bulletin);
bulletin.setCreateTime(LocalDateTime.now());
bulletin.setCreateBy(userDetails.getName());
bulletin.setEditUserId(userDetails.getId());
save(bulletin);
return bulletin;
}
/**
* 修改公告只能修改"编辑中""已发布"的公告
*
* @param userDetails 操作用户
* @param dto 表单数据
* @return 已修改的公告
*/
@Override
public Boolean update(UserDetailsImpl userDetails,BulletinDto dto, Long id) {
Bulletin bulletin = getById(id);
bulletin.state.checkStatus(EnumSet.of(edit, publish));
BeanUtils.copyProperties(dto, bulletin);
bulletin.setCreateBy(userDetails.getName());
bulletin.setCreateTime(LocalDateTime.now());
bulletin.state = edit;
bulletinUserService.toggleIsRead(id);
return updateById(bulletin);
}
/**
* 发布公告只能发布"编辑中"的公告
*
* @param userDetails 操作用户
* @param ids ids
* @return 已发布的公告
*/
@Override
public List<String> publish(UserDetailsImpl userDetails, List<Long> ids)throws PublishFailedException, EmptyIdsException {
List<String> results=new ArrayList<>();
if (ids == null || ids.isEmpty()) {
throw new EmptyIdsException("您输入的集合为空");
}
List<Bulletin> bulletins=getBulletinsByIds(ids);
for (Bulletin bulletin : bulletins) {
try {
bulletin.state.checkStatus(EnumSet.of(edit));
} catch (Exception e) {
throw new PublishFailedException("发布失败: " + e.getMessage());
}
}
for(Bulletin bulletin:bulletins){
try{
bulletin.state = publish;
bulletin.setPublishUserId(userDetails.getId());
bulletin.setPublishTime(LocalDateTime.now());
boolean result=updateById(bulletin);
if(result){
results.add("发布成功");
}else {
throw new PublishFailedException("发布失败");
}
}catch(Exception e){
throw new PublishFailedException("发布失败: " + e.getMessage());
}
}
return results;
}
/**
* 切换关闭状态只能关闭"已发布"的公告只能开启已关闭的公告
*
* @param userDetails 操作用户
* @param id ID
* @return 已关闭的公告
*/
@Override
public Boolean close(UserDetailsImpl userDetails, Long id) {
Bulletin bulletin = getById(id);
bulletin.top = false;
if(bulletin.state==close){
bulletin.state.checkStatus(close);
bulletin.state = edit;
return updateById(bulletin);
}
bulletin.state.checkStatus(publish);
bulletin.state = close;
bulletin.setCloseUserId(userDetails.getId());
bulletin.setCloseTime(LocalDateTime.now());
return updateById(bulletin);
}
/**
* 切换公告置顶状态
*
* @param id ID
* @return 被更新的公告
*/
@Override
public Boolean toggleTop(Long id) {
Bulletin bulletin = getById(id);
bulletin.top = !bulletin.top;
return updateById(bulletin);
}
/**
*为公告添加附件
*
* @param bulletinId bulletinId
* @param attachments attachments
* @return true
*/
@Override
public Boolean insertInto(Long bulletinId, Set<String> attachments) {
List<BulletinAttachment> bulletinAttachments=attachments.stream().map(bulletinAttachment->new BulletinAttachment(bulletinId, attachments.toString())).toList();
return bulletinAttachmentService.saveBatch(bulletinAttachments);
}
private List<Bulletin> getBulletinsByIds(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
LambdaQueryWrapper<Bulletin> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.in(Bulletin::getId, ids);
return repo.selectList(queryWrapper);
}
}

View File

@ -0,0 +1,60 @@
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.extension.service.impl.ServiceImpl;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.notice.entity.BulletinUser;
import com.zsc.edu.gateway.modules.notice.repo.BulletinUserRepository;
import com.zsc.edu.gateway.modules.notice.service.BulletinUserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
/**
* @author zhuang
*/
@AllArgsConstructor
@Service
public class BulletinUserServiceImpl extends ServiceImpl<BulletinUserRepository, BulletinUser> implements BulletinUserService {
/**
* 已读公告每次已读自动获取用户id与公告id加入联表
*
* @param userDetails userDetails
* @param id id
* return true
*/
@Override
public Boolean isRead(UserDetailsImpl userDetails,Long id) {
if (id == null || userDetails.getId() == null) {
throw new IllegalArgumentException("Bulletin ID and User ID cannot be null");
}
QueryWrapper<BulletinUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("bulletin_id", id)
.eq("user_id", userDetails.getId());
BulletinUser existingUser = getOne(queryWrapper);
if (existingUser == null) {
BulletinUser newUser = new BulletinUser();
newUser.setBulletinId(id);
newUser.setUserId(userDetails.getId());
newUser.setIsRead(false);
save(newUser);
} else {
UpdateWrapper<BulletinUser> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("bulletin_id", id).eq("user_id", userDetails.getId()).set("is_read",false);
}
return true;
}
/**
* 更新公告后修改已读状态
*
* @param id id
*/
@Override
public void toggleIsRead(Long id) {
UpdateWrapper<BulletinUser> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("bulletin_id",id).set("is_read",true);
}
}

View File

@ -0,0 +1,170 @@
//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);
// }
// }
//
//}

View File

@ -2,6 +2,7 @@ package com.zsc.edu.gateway.modules.system.repo;
import com.zsc.edu.gateway.modules.system.entity.User; import com.zsc.edu.gateway.modules.system.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
/** /**
* <p> * <p>
@ -13,4 +14,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/ */
public interface UserRepository extends BaseMapper<User> { public interface UserRepository extends BaseMapper<User> {
User selectByUsername(String username); User selectByUsername(String username);
@Select("select sys_user.name from sys_user where sys_user.id=#{id}")
String selectNameById(Long id);
} }

View File

@ -8,6 +8,7 @@ mybatis-plus:
configuration: configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
map-underscore-to-camel-case: true
spring: spring:
datasource: datasource:

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zsc.edu.gateway.modules.notice.repo.BulletinRepository">
<resultMap id="BulletinMap" type="com.zsc.edu.gateway.modules.notice.vo.BulletinVo" autoMapping="true">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="title" jdbcType="VARCHAR" property="title"/>
<result column="state" jdbcType="INTEGER" property="state"/>
<result column="top" jdbcType="BOOLEAN" property="top"/>
<result column="edit_time" jdbcType="TIMESTAMP" property="editTime"/>
<result column="publish_time" jdbcType="TIMESTAMP" property="publishTime"/>
<result column="close_time" jdbcType="TIMESTAMP" property="closeTime"/>
<result column="content" jdbcType="VARCHAR" property="content"/>
<result column="edit_user_id" jdbcType="BIGINT" property="editUserId"/>
<result column="publish_user_id" jdbcType="BIGINT" property="publishUserId"/>
<result column="close_user_id" jdbcType="BIGINT" property="closeUserId"/>
<result column="edit_user_name" jdbcType="VARCHAR" property="editUsername"/>
<result column="publish_user_name" jdbcType="VARCHAR" property="publishUsername"/>
<result column="close_user_name" jdbcType="VARCHAR" property="closeUsername"/>
<result column="file_name" jdbcType="VARCHAR" property="fileName"/>
<result column="mime_type" jdbcType="VARCHAR" property="mimeType"/>
<result column="upload_time" jdbcType="TIMESTAMP" property="uploadTime"/>
<result column="url" jdbcType="VARCHAR" property="url"/>
<result column="is_read" jdbcType="BOOLEAN" property="isRead"/>
</resultMap>
<select id="selectByBulletinId" resultMap="BulletinMap">
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 sb.id=#{bulletinId}
order by sb.top DESC, sb.create_time DESC;
</select>
</mapper>

View File

@ -15,7 +15,7 @@ class IotGatewayApplicationTests {
private BulletinRepository bulletinRepository; private BulletinRepository bulletinRepository;
@Test @Test
void contextLoads() { void contextLoads() {
bulletinRepository.selectAll(); // bulletinRepository.selectAll();
} }

View File

@ -0,0 +1,35 @@
package com.zsc.edu.gateway.domain;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
public class BulletinBuilder extends BaseEntityBuilder{
private String title;
private String content;
private Boolean top;
public static BulletinBuilder bBulletin(){return new BulletinBuilder();}
public BulletinBuilder title(String title){
this.title = title;
return this;
}
public BulletinBuilder content(String content){
this.content = content;
return this;
}
public BulletinBuilder top(Boolean top){
this.top = top;
return this;
}
public Bulletin build(){
Bulletin bulletin = new Bulletin();
bulletin.setTitle(title);
bulletin.setContent(content);
bulletin.setTop(top);
return bulletin;
}
}

View File

@ -0,0 +1,89 @@
//package com.zsc.edu.gateway.service;
//
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import com.zsc.edu.gateway.domain.BulletinBuilder;
//import com.zsc.edu.gateway.exception.ConstraintException;
//import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
//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.repo.BulletinRepository;
//import com.zsc.edu.gateway.modules.notice.service.BulletinService;
//import jakarta.annotation.Resource;
//import org.junit.jupiter.api.AfterEach;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.Test;
//
//import java.util.List;
//
//import static org.junit.jupiter.api.Assertions.*;
//
//public class BulletinServiceTest {
// @Resource
// private BulletinService service;
// @Resource
// private BulletinRepository repo;
//
// Bulletin bulletin1;
// Bulletin bulletin2;
//
// @BeforeEach
// void setUp() {
// bulletin1 = BulletinBuilder.bBulletin().title("测试1").build();
// repo.insert(bulletin1);
// bulletin2 = BulletinBuilder.bBulletin().title("测试2").build();
// repo.insert(bulletin2);
// }
//
// @Test
// void list() {
// LambdaQueryWrapper<Bulletin> queryWrapper = new LambdaQueryWrapper<>();
// assertEquals(2, service.list(queryWrapper.like(Bulletin::getTitle, "测试")).size());
// assertEquals(1, service.list(queryWrapper.eq(Bulletin::getTitle, bulletin1.getTitle())).size());
// assertEquals(2, service.list().size());
// }
//
// @Test
// void createBulletin() {
// BulletinDto dto = new BulletinDto();
// dto.setTitle("测试");
// dto.setTop(true);
// dto.setContent("测试测试");
// dto.setRemark("测试公告增加");
// BulletinDto dto2 = new BulletinDto();
// dto2.setTitle(bulletin2.getTitle());
//// dto2.setTop(bulletin2.isTop());
// dto2.setRemark(bulletin2.getRemark());
// UserDetailsImpl userDetails = new UserDetailsImpl();
// userDetails.setUsername("admin");
// Bulletin bulletin=service.create(userDetails,dto);
// assertNotNull(bulletin.getId());
// List<Bulletin> list = service.list();
// assertEquals(3, list.size());
// // 不能创建其他已存在标题公告
// assertThrows(ConstraintException.class, () -> service.create(userDetails,dto2));
// }
//
// @Test
// void updateBulletin() {
// BulletinDto dto = new BulletinDto();
// dto.setTitle("测试3");
// dto.setContent("测试测");
// dto.setTop(true);
// dto.setRemark("测试公告更新");
// UserDetailsImpl userDetails = new UserDetailsImpl();
// userDetails.setUsername("admin");
// assertTrue(service.update(userDetails,dto, bulletin2.id));
// Bulletin bulletin = service.getOne(new LambdaQueryWrapper<Bulletin>().eq(Bulletin::getTitle, dto.getTitle()));
// assertEquals(bulletin.getTitle(), dto.getTitle());
// assertEquals(bulletin.getId(), bulletin2.id);
// // 不能改为其他已存在的同名同代码部门
// assertThrows(ConstraintException.class,
// () -> service.update(userDetails,new BulletinDto(bulletin1.getTitle(),true,null,null), bulletin2.id));
// }
//
// @AfterEach
// void tearDown() {
// repo.delete(new QueryWrapper<>());
// }
//}