Explorar o código

feat(business): 添加消息管理功能

- 新增消息主和消息接收者相关实体类、控制器、服务接口和实现类、Mapper接口和XML文件
- 实现消息列表查询、消息详情获取、消息发送、修改和删除等功能
- 添加消息接收者列表查询、消息状态更新等接口
fugui001 hai 7 meses
pai
achega
8d9aaea4bd
Modificáronse 24 ficheiros con 1624 adicións e 2 borrados
  1. 105 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/MessageReceiversController.java
  2. 105 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/MessagesController.java
  3. 58 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/MessageReceivers.java
  4. 68 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/MessagesInfo.java
  5. 62 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/bo/MessageReceiversBo.java
  6. 79 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/bo/MessagesBo.java
  7. 1 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/dto/TournamentsDto.java
  8. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/GameStatus.java
  9. 30 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/MessageStatusEnum.java
  10. 40 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/MessageTypeEnum.java
  11. 56 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/ReceiverTypeEnum.java
  12. 72 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/MessageReceiversVo.java
  13. 92 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/MessagesVo.java
  14. 45 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/MessageReceiversMapper.java
  15. 43 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/MessagesMapper.java
  16. 67 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IMessageReceiversService.java
  17. 68 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IMessagesService.java
  18. 140 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/MessageReceiversServiceImpl.java
  19. 161 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/MessagesServiceImpl.java
  20. 62 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsServiceImpl.java
  21. 79 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/NotificationUtils.java
  22. 88 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/MessageReceiversMapper.xml
  23. 99 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/MessagesMapper.xml
  24. 1 1
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/TournamentsMapper.xml

+ 105 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/MessageReceiversController.java

@@ -0,0 +1,105 @@
+package org.dromara.business.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.business.domain.bo.MessageReceiversBo;
+import org.dromara.business.domain.vo.MessageReceiversVo;
+import org.dromara.business.service.IMessageReceiversService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 【请填写功能名称】
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/business/receivers")
+public class MessageReceiversController extends BaseController {
+
+    private final IMessageReceiversService messageReceiversService;
+
+    /**
+     * 查询【请填写功能名称】列表
+     */
+    @SaCheckPermission("business:receivers:list")
+    @GetMapping("/list")
+    public TableDataInfo<MessageReceiversVo> list(MessageReceiversBo bo, PageQuery pageQuery) {
+        return messageReceiversService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出【请填写功能名称】列表
+     */
+    @SaCheckPermission("business:receivers:export")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(MessageReceiversBo bo, HttpServletResponse response) {
+        List<MessageReceiversVo> list = messageReceiversService.queryList(bo);
+        ExcelUtil.exportExcel(list, "【请填写功能名称】", MessageReceiversVo.class, response);
+    }
+
+    /**
+     * 获取【请填写功能名称】详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("business:receivers:query")
+    @GetMapping("/{id}")
+    public R<MessageReceiversVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(messageReceiversService.queryById(id));
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     */
+    @SaCheckPermission("business:receivers:add")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody MessageReceiversBo bo) {
+        return toAjax(messageReceiversService.insertByBo(bo));
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     */
+    @SaCheckPermission("business:receivers:edit")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody MessageReceiversBo bo) {
+        return toAjax(messageReceiversService.updateByBo(bo));
+    }
+
+    /**
+     * 删除【请填写功能名称】
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("business:receivers:remove")
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(messageReceiversService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 105 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/MessagesController.java

@@ -0,0 +1,105 @@
+package org.dromara.business.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.business.domain.bo.MessagesBo;
+import org.dromara.business.domain.vo.MessagesVo;
+import org.dromara.business.service.IMessagesService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 消息主
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/business/messages")
+public class MessagesController extends BaseController {
+
+    private final IMessagesService messagesService;
+
+    /**
+     * 查询消息主列表
+     */
+    @SaCheckPermission("business:messages:list")
+    @GetMapping("/list")
+    public TableDataInfo<MessagesVo> list(MessagesBo bo, PageQuery pageQuery) {
+        return messagesService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出消息主列表
+     */
+    @SaCheckPermission("business:messages:export")
+    @Log(title = "消息主", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(MessagesBo bo, HttpServletResponse response) {
+        List<MessagesVo> list = messagesService.queryList(bo);
+        ExcelUtil.exportExcel(list, "消息主", MessagesVo.class, response);
+    }
+
+    /**
+     * 获取消息主详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("business:messages:query")
+    @GetMapping("/{id}")
+    public R<MessagesVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(messagesService.queryById(id));
+    }
+
+    /**
+     * 新增消息主
+     */
+    @SaCheckPermission("business:messages:add")
+    @Log(title = "消息主", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody MessagesBo bo) {
+        return toAjax(messagesService.insertByBo(bo));
+    }
+
+    /**
+     * 修改消息主
+     */
+    @SaCheckPermission("business:messages:edit")
+    @Log(title = "消息主", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody MessagesBo bo) {
+        return toAjax(messagesService.updateByBo(bo));
+    }
+
+    /**
+     * 删除消息主
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("business:messages:remove")
+    @Log(title = "消息主", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(messagesService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 58 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/MessageReceivers.java

@@ -0,0 +1,58 @@
+package org.dromara.business.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.util.Date;
+import java.io.Serial;
+
+/**
+ * 【请填写功能名称】对象 message_receivers
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@TableName("message_receivers")
+public class MessageReceivers {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 关联 messages.id
+     */
+    private Long messageId;
+
+    /**
+     * 接收人 ID
+     */
+    private Long userId;
+
+    /**
+     * 0-未读 1-已读
+     */
+    private Long readStatus;
+
+    /**
+     * 阅读时间
+     */
+    private Date readTime;
+
+    /**
+     *
+     */
+    private Date createdAt;
+
+    /**
+     *
+     */
+    private Date updatedAt;
+
+
+}

+ 68 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/MessagesInfo.java

@@ -0,0 +1,68 @@
+package org.dromara.business.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.util.Date;
+import java.io.Serial;
+
+/**
+ * 消息主对象 messages
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@TableName("messages")
+public class MessagesInfo {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 消息标题
+     */
+    private String title;
+
+    /**
+     * 消息内容
+     */
+    private String content;
+
+    /**
+     * 发送者ID
+     */
+    private Long senderId;
+
+    /**
+     * 接收对象类型:所有人、群组、个人  'ALL', 'GROUP', 'INDIVIDUAL'
+     */
+    private String receiverType;
+
+    /**
+     * 接收人ID列表(JSON数组格式)
+     */
+    private String receiverIds;
+
+    /**
+     * 发送时间
+     */
+    private Date sendTime;
+
+    /**
+     * 消息类型: SYSTEM, REWARD, POINTS 等
+     */
+    private String messageType;
+
+    /**
+     * 消息状态 'PENDING', 'SENT', 'DELIVERED', 'READ'
+     */
+    private String status;
+
+
+}

+ 62 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/bo/MessageReceiversBo.java

@@ -0,0 +1,62 @@
+package org.dromara.business.domain.bo;
+
+import org.dromara.business.domain.MessageReceivers;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+/**
+ * 【请填写功能名称】业务对象 message_receivers
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MessageReceivers.class, reverseConvertGenerate = false)
+public class MessageReceiversBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 关联 messages.id
+     */
+    @NotNull(message = "关联 messages.id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long messageId;
+
+    /**
+     * 接收人 ID
+     */
+    @NotNull(message = "接收人 ID不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long userId;
+
+    /**
+     * 0-未读 1-已读
+     */
+    private Long readStatus;
+
+    /**
+     * 阅读时间
+     */
+    private Date readTime;
+
+    /**
+     *
+     */
+    private Date createdAt;
+
+    /**
+     *
+     */
+    private Date updatedAt;
+
+
+}

+ 79 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/bo/MessagesBo.java

@@ -0,0 +1,79 @@
+package org.dromara.business.domain.bo;
+
+import org.dromara.business.domain.MessagesInfo;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+
+
+/**
+ * 消息主业务对象 messages
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MessagesInfo.class, reverseConvertGenerate = false)
+public class MessagesBo extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    @NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 消息标题
+     */
+    @NotBlank(message = "消息标题不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String title;
+
+    /**
+     * 消息内容
+     */
+    @NotBlank(message = "消息内容不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String content;
+
+    /**
+     * 发送者ID
+     */
+    //@NotNull(message = "发送者ID不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long senderId;
+
+    /**
+     * 接收对象类型:所有人、群组、个人  'ALL', 'GROUP', 'INDIVIDUAL'
+     */
+    //@NotBlank(message = "接收对象类型:所有人、群组、个人  'ALL', 'GROUP', 'INDIVIDUAL'不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String receiverType;
+
+    /**
+     * 接收人ID列表(JSON数组格式)
+     */
+    private String receiverIds;
+
+    /**
+     * 发送时间
+     */
+    //@NotNull(message = "发送时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date sendTime;
+
+    /**
+     * 消息类型: SYSTEM, REWARD, POINTS 等
+     */
+    //@NotBlank(message = "消息类型: SYSTEM, REWARD, POINTS 等不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String messageType;
+
+    /**
+     * 消息状态 'PENDING', 'SENT', 'DELIVERED', 'READ'
+     */
+    //@NotBlank(message = "消息状态 'PENDING', 'SENT', 'DELIVERED', 'READ'不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+
+}

+ 1 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/dto/TournamentsDto.java

@@ -43,5 +43,6 @@ public class TournamentsDto {
 
     private String competitionIcon;
 
+    private int rewardPlayers;
 
 }

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/GameStatus.java

@@ -1,5 +1,8 @@
 package org.dromara.business.domain.enums;
 
+import lombok.Getter;
+
+@Getter
 public enum GameStatus {
 
     NOT_STARTED(0, "未开始"),

+ 30 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/MessageStatusEnum.java

@@ -0,0 +1,30 @@
+package org.dromara.business.domain.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum MessageStatusEnum {
+
+    PENDING("PENDING", "待发送"),
+    SENT("SENT", "已发送"),
+    DELIVERED("DELIVERED", "已送达"),
+    READ("READ", "已读");
+
+    private final String code;
+    private final String description;
+
+    MessageStatusEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public static MessageStatusEnum fromCode(String code) {
+        for (MessageStatusEnum status : values()) {
+            if (status.getCode().equalsIgnoreCase(code)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("未知的消息状态: " + code);
+    }
+
+}

+ 40 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/MessageTypeEnum.java

@@ -0,0 +1,40 @@
+package org.dromara.business.domain.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum MessageTypeEnum {
+
+    SYSTEM("SYSTEM", "系统公告"),
+    REWARD("REWARD", "获得奖励"),
+    POINTS("POINTS", "积分变动"),
+    NOTICE("NOTICE", "通用通知"),
+    ACTIVITY("ACTIVITY", "活动通知"),
+    ORDER("ORDER", "订单通知"),
+    TASK("TASK", "任务通知");
+
+    private final String code;
+    private final String description;
+
+    MessageTypeEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public static MessageTypeEnum fromCode(String code) {
+        for (MessageTypeEnum type : values()) {
+            if (type.getCode().equalsIgnoreCase(code)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException("未知的消息类型: " + code);
+    }
+
+    /**
+     * 根据 code 获取 description
+     */
+    public static String getDescriptionByCode(String code) {
+        return fromCode(code).getDescription();
+    }
+
+}

+ 56 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/ReceiverTypeEnum.java

@@ -0,0 +1,56 @@
+package org.dromara.business.domain.enums;
+
+public enum ReceiverTypeEnum {
+
+    ALL("ALL", "所有人"),
+    GROUP("GROUP", "群组"),
+    INDIVIDUAL("INDIVIDUAL", "个人");
+
+    private final String code;
+    private final String description;
+
+    ReceiverTypeEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * 根据 code 获取枚举实例
+     */
+    public static ReceiverTypeEnum fromCode(String code) {
+        for (ReceiverTypeEnum type : values()) {
+            if (type.getCode().equalsIgnoreCase(code)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException("未知的接收类型: " + code);
+    }
+
+    /**
+     * 根据 code 获取 description
+     */
+    public static String getDescriptionByCode(String code) {
+        return fromCode(code).getDescription();
+    }
+
+    /**
+     * 判断是否是合法的 code
+     */
+    public static boolean isValidCode(String code) {
+        try {
+            fromCode(code);
+            return true;
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
+
+}

+ 72 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/MessageReceiversVo.java

@@ -0,0 +1,72 @@
+package org.dromara.business.domain.vo;
+
+import java.util.Date;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.business.domain.MessageReceivers;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 message_receivers
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = MessageReceivers.class)
+public class MessageReceiversVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 关联 messages.id
+     */
+    @ExcelProperty(value = "关联 messages.id")
+    private Long messageId;
+
+    /**
+     * 接收人 ID
+     */
+    @ExcelProperty(value = "接收人 ID")
+    private Long userId;
+
+    /**
+     * 0-未读 1-已读
+     */
+    @ExcelProperty(value = "0-未读 1-已读")
+    private Long readStatus;
+
+    /**
+     * 阅读时间
+     */
+    @ExcelProperty(value = "阅读时间")
+    private Date readTime;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Date createdAt;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Date updatedAt;
+
+
+}

+ 92 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/MessagesVo.java

@@ -0,0 +1,92 @@
+package org.dromara.business.domain.vo;
+
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.business.domain.MessagesInfo;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 消息主视图对象 messages
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = MessagesInfo.class)
+public class MessagesVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @ExcelProperty(value = "主键ID")
+    private Long id;
+
+    /**
+     * 消息标题
+     */
+    @ExcelProperty(value = "消息标题")
+    private String title;
+
+    /**
+     * 消息内容
+     */
+    @ExcelProperty(value = "消息内容")
+    private String content;
+
+    /**
+     * 发送者ID
+     */
+    @ExcelProperty(value = "发送者ID")
+    private Long senderId;
+
+    /**
+     * 接收对象类型:所有人、群组、个人  'ALL', 'GROUP', 'INDIVIDUAL'
+     */
+    @ExcelProperty(value = "接收对象类型:所有人、群组、个人  'ALL', 'GROUP', 'INDIVIDUAL'")
+    private String receiverType;
+
+    /**
+     * 接收人ID列表(JSON数组格式)
+     */
+    @ExcelProperty(value = "接收人ID列表", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "J=SON数组格式")
+    private String receiverIds;
+
+    /**
+     * 发送时间
+     */
+    @ExcelProperty(value = "发送时间")
+    private Date sendTime;
+
+    /**
+     * 消息类型: SYSTEM, REWARD, POINTS 等
+     */
+    @ExcelProperty(value = "消息类型: SYSTEM, REWARD, POINTS 等")
+    private String messageType;
+
+    /**
+     * 消息状态 'PENDING', 'SENT', 'DELIVERED', 'READ'
+     */
+    @ExcelProperty(value = "消息状态 'PENDING', 'SENT', 'DELIVERED', 'READ'")
+    private String status;
+
+    /**
+     * 创建人名称
+     */
+    private String createName;
+
+}

+ 45 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/MessageReceiversMapper.java

@@ -0,0 +1,45 @@
+package org.dromara.business.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.business.domain.MessageReceivers;
+import org.dromara.business.domain.vo.MessageReceiversVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@DS("mysql2")
+public interface MessageReceiversMapper extends BaseMapperPlus<MessageReceivers, MessageReceiversVo> {
+
+    @InterceptorIgnore(tenantLine = "true")
+    Page<MessageReceiversVo> selectVoPage(@Param("page") Page<MessageReceivers> page, @Param("ew") Wrapper<MessageReceivers> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    MessageReceiversVo selectVoInfoById(Long id);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int updateMessageReceiver(MessageReceivers update);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int insertMessageReceiver(MessageReceivers insert);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int deleteMessageReceiversById(@Param("ids") Collection<Long> ids);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<MessageReceiversVo> selectMessagesReceiversList(@Param("ew") Wrapper<MessageReceivers> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int batchInsertMessageReceiver(@Param("list") List<MessageReceivers> list);
+
+}

+ 43 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/MessagesMapper.java

@@ -0,0 +1,43 @@
+package org.dromara.business.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.business.domain.MessagesInfo;
+import org.dromara.business.domain.vo.MessagesVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 消息主Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@DS("mysql2")
+public interface MessagesMapper extends BaseMapperPlus<MessagesInfo, MessagesVo> {
+
+    @InterceptorIgnore(tenantLine = "true")
+    Page<MessagesVo> selectVoPage(@Param("page") Page<MessagesInfo> page, @Param("ew") Wrapper<MessagesInfo> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    MessagesVo selectVoInfoById(Long id);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int updateMessage(MessagesInfo update);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int insertMessage(MessagesInfo insert);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int deleteMessageById(@Param("ids") Collection<Long> ids);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<MessagesVo> selectMessagesList(@Param("ew") Wrapper<MessagesInfo> wrapper);
+
+
+}

+ 67 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IMessageReceiversService.java

@@ -0,0 +1,67 @@
+package org.dromara.business.service;
+
+import org.dromara.business.domain.bo.MessageReceiversBo;
+import org.dromara.business.domain.vo.MessageReceiversVo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+public interface IMessageReceiversService {
+
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param id 主键
+     * @return 【请填写功能名称】
+     */
+    MessageReceiversVo queryById(Long id);
+
+    /**
+     * 分页查询【请填写功能名称】列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 【请填写功能名称】分页列表
+     */
+    TableDataInfo<MessageReceiversVo> queryPageList(MessageReceiversBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的【请填写功能名称】列表
+     *
+     * @param bo 查询条件
+     * @return 【请填写功能名称】列表
+     */
+    List<MessageReceiversVo> queryList(MessageReceiversBo bo);
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param bo 【请填写功能名称】
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(MessageReceiversBo bo);
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param bo 【请填写功能名称】
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(MessageReceiversBo bo);
+
+    /**
+     * 校验并批量删除【请填写功能名称】信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 68 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IMessagesService.java

@@ -0,0 +1,68 @@
+package org.dromara.business.service;
+
+import org.dromara.business.domain.bo.MessagesBo;
+import org.dromara.business.domain.vo.MessagesVo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 消息主Service接口
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+public interface IMessagesService {
+
+    /**
+     * 查询消息主
+     *
+     * @param id 主键
+     * @return 消息主
+     */
+    MessagesVo queryById(Long id);
+
+    /**
+     * 分页查询消息主列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 消息主分页列表
+     */
+    TableDataInfo<MessagesVo> queryPageList(MessagesBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的消息主列表
+     *
+     * @param bo 查询条件
+     * @return 消息主列表
+     */
+    List<MessagesVo> queryList(MessagesBo bo);
+
+    /**
+     * 新增消息主
+     *
+     * @param bo 消息主
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(MessagesBo bo);
+
+    /**
+     * 修改消息主
+     *
+     * @param bo 消息主
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(MessagesBo bo);
+
+    /**
+     * 校验并批量删除消息主信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 140 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/MessageReceiversServiceImpl.java

@@ -0,0 +1,140 @@
+package org.dromara.business.service.impl;
+
+import org.dromara.business.domain.MessageReceivers;
+import org.dromara.business.domain.bo.MessageReceiversBo;
+import org.dromara.business.domain.vo.MessageReceiversVo;
+import org.dromara.business.mapper.MessageReceiversMapper;
+import org.dromara.business.service.IMessageReceiversService;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MessageReceiversServiceImpl implements IMessageReceiversService {
+
+    private final MessageReceiversMapper baseMapper;
+
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param id 主键
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public MessageReceiversVo queryById(Long id){
+        return baseMapper.selectVoInfoById(id);
+    }
+
+    /**
+     * 分页查询【请填写功能名称】列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 【请填写功能名称】分页列表
+     */
+    @Override
+    public TableDataInfo<MessageReceiversVo> queryPageList(MessageReceiversBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<MessageReceivers> lqw = buildQueryWrapper(bo);
+        Page<MessageReceiversVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的【请填写功能名称】列表
+     *
+     * @param bo 查询条件
+     * @return 【请填写功能名称】列表
+     */
+    @Override
+    public List<MessageReceiversVo> queryList(MessageReceiversBo bo) {
+        LambdaQueryWrapper<MessageReceivers> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectMessagesReceiversList(lqw);
+    }
+
+    private LambdaQueryWrapper<MessageReceivers> buildQueryWrapper(MessageReceiversBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<MessageReceivers> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(MessageReceivers::getId);
+        lqw.eq(bo.getMessageId() != null, MessageReceivers::getMessageId, bo.getMessageId());
+        lqw.eq(bo.getUserId() != null, MessageReceivers::getUserId, bo.getUserId());
+        lqw.eq(bo.getReadStatus() != null, MessageReceivers::getReadStatus, bo.getReadStatus());
+        lqw.eq(bo.getReadTime() != null, MessageReceivers::getReadTime, bo.getReadTime());
+        lqw.eq(bo.getCreatedAt() != null, MessageReceivers::getCreatedAt, bo.getCreatedAt());
+        lqw.eq(bo.getUpdatedAt() != null, MessageReceivers::getUpdatedAt, bo.getUpdatedAt());
+        return lqw;
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param bo 【请填写功能名称】
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(MessageReceiversBo bo) {
+        MessageReceivers add = MapstructUtils.convert(bo, MessageReceivers.class);
+        validEntityBeforeSave(add);
+
+
+
+        boolean flag = baseMapper.insertMessageReceiver(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param bo 【请填写功能名称】
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(MessageReceiversBo bo) {
+        MessageReceivers update = MapstructUtils.convert(bo, MessageReceivers.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateMessageReceiver(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(MessageReceivers entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除【请填写功能名称】信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteMessageReceiversById(ids) > 0;
+    }
+}

+ 161 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/MessagesServiceImpl.java

@@ -0,0 +1,161 @@
+package org.dromara.business.service.impl;
+
+import org.dromara.business.domain.MessagesInfo;
+import org.dromara.business.domain.bo.MessagesBo;
+import org.dromara.business.domain.enums.MessageTypeEnum;
+import org.dromara.business.domain.enums.ReceiverTypeEnum;
+import org.dromara.business.domain.vo.MessagesVo;
+import org.dromara.business.mapper.MessagesMapper;
+import org.dromara.business.service.IMessagesService;
+import org.dromara.business.utils.NotificationUtils;
+import org.dromara.common.core.service.UserService;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.springframework.stereotype.Service;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 消息主Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-07-10
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MessagesServiceImpl implements IMessagesService {
+
+    private final MessagesMapper baseMapper;
+
+    private final UserService userService;
+
+    private final NotificationUtils notificationUtils;
+
+    /**
+     * 查询消息主
+     *
+     * @param id 主键
+     * @return 消息主
+     */
+    @Override
+    public MessagesVo queryById(Long id){
+        return baseMapper.selectVoInfoById(id);
+    }
+
+    /**
+     * 分页查询消息主列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 消息主分页列表
+     */
+    @Override
+    public TableDataInfo<MessagesVo> queryPageList(MessagesBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<MessagesInfo> lqw = buildQueryWrapper(bo);
+        Page<MessagesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<MessagesVo> records = result.getRecords();
+        for (MessagesVo record : records) {
+            if(record.getSenderId()!=null){
+                String createName = userService.selectUserNameById(record.getSenderId());
+                record.setCreateName(createName);
+            }
+            String messageType = record.getMessageType();
+            record.setMessageType(MessageTypeEnum.getDescriptionByCode(messageType));
+
+            String receiverType = record.getReceiverType();
+            record.setReceiverType(ReceiverTypeEnum.getDescriptionByCode(receiverType));
+        }
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的消息主列表
+     *
+     * @param bo 查询条件
+     * @return 消息主列表
+     */
+    @Override
+    public List<MessagesVo> queryList(MessagesBo bo) {
+        LambdaQueryWrapper<MessagesInfo> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectMessagesList(lqw);
+    }
+
+    private LambdaQueryWrapper<MessagesInfo> buildQueryWrapper(MessagesBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<MessagesInfo> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(MessagesInfo::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), MessagesInfo::getTitle, bo.getTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getContent()), MessagesInfo::getContent, bo.getContent());
+        lqw.eq(bo.getSenderId() != null, MessagesInfo::getSenderId, bo.getSenderId());
+        lqw.eq(StringUtils.isNotBlank(bo.getReceiverType()), MessagesInfo::getReceiverType, bo.getReceiverType());
+        lqw.eq(StringUtils.isNotBlank(bo.getReceiverIds()), MessagesInfo::getReceiverIds, bo.getReceiverIds());
+        lqw.eq(bo.getSendTime() != null, MessagesInfo::getSendTime, bo.getSendTime());
+        lqw.eq(StringUtils.isNotBlank(bo.getMessageType()), MessagesInfo::getMessageType, bo.getMessageType());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), MessagesInfo::getStatus, bo.getStatus());
+        return lqw;
+    }
+
+    /**
+     * 新增消息主
+     *
+     * @param bo 消息主
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(MessagesBo bo) {
+        MessagesInfo add = MapstructUtils.convert(bo, MessagesInfo.class);
+        validEntityBeforeSave(add);
+        Long userId = LoginHelper.getUserId();
+        add.setSenderId(userId);
+        boolean flag=notificationUtils.sendToAll(bo.getTitle(),add.getContent(),add.getSenderId(), MessageTypeEnum.SYSTEM.getCode());
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改消息主
+     *
+     * @param bo 消息主
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(MessagesBo bo) {
+        MessagesInfo update = MapstructUtils.convert(bo, MessagesInfo.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateMessage(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(MessagesInfo entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除消息主信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteMessageById(ids) > 0;
+    }
+}

+ 62 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsServiceImpl.java

@@ -252,6 +252,8 @@ public class TournamentsServiceImpl implements ITournamentsService {
     @Override
     public Boolean insertByBo(TournamentsDto bo) {
         try {
+
+
             // 转换 BO -> Entity
             Tournaments add = new Tournaments();
             BeanUtils.copyProperties(bo, add);
@@ -299,6 +301,65 @@ public class TournamentsServiceImpl implements ITournamentsService {
     }
 
 
+    /**
+     * 批量插入 1000 条赛事记录
+     *
+     * @return 是否批量插入成功
+     */
+
+    public Boolean batchInsertTournaments() {
+        try {
+            for (int i = 0; i < 1000; i++) {
+                // 模拟构造 TournamentsDto 数据
+                TournamentsDto bo = new TournamentsDto();
+
+                // 设置基础字段
+                bo.setName("赛事名称_" + i);
+                bo.setGameType((long) (1)); // 假设有5种类型
+                bo.setStartingChips(10000L);
+                bo.setLevelDuration(15L);
+                bo.setLateRegistrationLevel(3L);
+                bo.setMaxPlayers(100L);
+                bo.setStatus(1L); // 默认状态为进行中等
+                bo.setStartTime(LocalDateTime.now().plusMinutes(60L * i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+/*
+                bo.setCompetitionIcon("http://public-photos-fugui.oss-cn-beijing.aliyuncs.com/2025/07/05/987480c995204231aa21c3e8ec9af12b.png");
+*/
+                bo.setRewardPlayers(3);
+                bo.setSignTime(10L);
+
+                // 设置盲注结构 ID(假设存在)
+                bo.setBlindStructureId(9L);
+
+                // 设置报名条件
+                bo.setItemsId(1L);
+                bo.setItemsNum(10L);
+
+                // 设置奖励列表
+                List<ItemsPrizeDto> prizeList = new ArrayList<>();
+                ItemsPrizeDto prize = new ItemsPrizeDto();
+                prize.setRanking(1L);
+                prize.setItemId(1L);
+                prize.setQuantity(10L);
+                prize.setItemsName("三湘杯参赛卡");
+                prizeList.add(prize);
+                bo.setItemsPrizeList(prizeList);
+
+                // 调用已有的插入方法
+                if (!insertByBo(bo)) {
+                    log.error("第 {} 条赛事插入失败", i + 1);
+                    return false;
+                }
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("批量插入赛事过程中发生异常", e);
+            return false;
+        }
+    }
+
+
+
 
     private void bindBlindStructure(Long tournamentId, Long blindStructureId) {
         TournamentBlindStructure structure = new TournamentBlindStructure();
@@ -474,7 +535,7 @@ public class TournamentsServiceImpl implements ITournamentsService {
      */
     public static String getCurrentDateTime() {
         LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
         return now.format(formatter);
     }
 

+ 79 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/NotificationUtils.java

@@ -0,0 +1,79 @@
+package org.dromara.business.utils;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.dromara.business.domain.MessageReceivers;
+import org.dromara.business.domain.MessagesInfo;
+import org.dromara.business.domain.User;
+import org.dromara.business.domain.enums.MessageStatusEnum;
+import org.dromara.business.domain.enums.ReceiverTypeEnum;
+import org.dromara.business.domain.vo.UserVo;
+import org.dromara.business.mapper.MessageReceiversMapper;
+import org.dromara.business.mapper.MessagesMapper;
+import org.dromara.business.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class NotificationUtils {
+
+    @Autowired
+    MessagesMapper messagesInfoMapper;
+
+    @Autowired
+    UserMapper userMapper;
+
+    @Autowired
+    MessageReceiversMapper messageReceiversMapper;
+
+    /**
+     * 发送给所有用户
+     */
+    public Boolean sendToAll(String title, String content, Long senderId, String messageType) {
+        try {
+            // 1. 插入主消息(receiver_type = ALL)
+            MessagesInfo bo = new MessagesInfo();
+            bo.setTitle(title);
+            bo.setContent(content);
+            bo.setSenderId(senderId);
+            bo.setReceiverType(ReceiverTypeEnum.ALL.getCode());
+            bo.setMessageType(messageType);
+            bo.setStatus(MessageStatusEnum.SENT.getCode());
+
+            messagesInfoMapper.insertMessage(bo);
+            Long messageId = bo.getId();
+
+            if (messageId == null) {
+                throw new RuntimeException("消息插入失败,无法获取消息ID");
+            }
+
+            // 2. 获取所有用户列表
+            List<UserVo> users = userMapper.selectUserList(new QueryWrapper<User>());
+
+            if (users.isEmpty()) {
+                return true; // 没有用户也视为发送成功
+            }
+
+            // 3. 批量插入 message_receivers 记录
+            List<MessageReceivers> receiverList = users.stream()
+                .map(user -> {
+                    MessageReceivers receiver = new MessageReceivers();
+                    receiver.setMessageId(messageId);
+                    receiver.setUserId(user.getId());
+                    return receiver;
+                })
+                .collect(Collectors.toList());
+            messageReceiversMapper.batchInsertMessageReceiver(receiverList);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 可以记录日志
+            return false;
+        }
+    }
+
+
+}

+ 88 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/MessageReceiversMapper.xml

@@ -0,0 +1,88 @@
+<?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="org.dromara.business.mapper.MessageReceiversMapper">
+
+
+    <select id="selectVoPage" resultType="org.dromara.business.domain.vo.MessageReceiversVo">
+        SELECT
+            id, message_id, user_id, read_status, read_time, created_at, updated_at
+        FROM message_receivers  ${ew.customSqlSegment}
+    </select>
+
+
+    <select id="selectMessagesReceiversList" resultType="org.dromara.business.domain.vo.MessageReceiversVo">
+        SELECT
+            id, message_id, user_id, read_status, read_time, created_at, updated_at
+        FROM message_receivers   ${ew.customSqlSegment}
+    </select>
+
+    <select id="selectVoInfoById" resultType="org.dromara.business.domain.vo.MessageReceiversVo">
+        SELECT
+            id, message_id, user_id, read_status, read_time, created_at, updated_at
+        FROM message_receivers   WHERE id =  #{id}
+    </select>
+
+    <update id="updateMessageReceiver">
+        UPDATE message_receivers
+        <set>
+            <if test="readStatus != null">read_status = #{readStatus},</if>
+            read_time=now()
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <insert id="insertMessageReceiver"  useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO message_receivers
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="messageId != null">message_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="readStatus != null">read_status,</if>
+            <if test="readTime != null">read_time,</if>
+        </trim>
+        VALUES
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="messageId != null">#{messageId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="readStatus != null">#{readStatus},</if>
+            <if test="readTime != null">#{readTime},</if>
+        </trim>
+    </insert>
+
+
+    <delete id="deleteMessageReceiversById">
+        DELETE FROM message_receivers
+        <where>
+            id IN
+            <foreach item="id" collection="ids" open="(" separator="," close=")">
+                <if test="id > 0">
+                    #{id}
+                </if>
+            </foreach>
+        </where>
+    </delete>
+
+    <insert id="batchInsertMessageReceiver">
+        INSERT INTO message_receivers
+        <!-- 动态生成列名 -->
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="list[0].messageId != null">message_id,</if>
+            <if test="list[0].userId != null">user_id,</if>
+            <if test="list[0].readStatus != null">read_status,</if>
+            <if test="list[0].readTime != null">read_time,</if>
+        </trim>
+        <!-- 动态生成每条记录的值 -->
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            <trim prefix="(" suffix=")" suffixOverrides=",">
+                <if test="item.messageId != null">#{item.messageId},</if>
+                <if test="item.userId != null">#{item.userId},</if>
+                <if test="item.readStatus != null">#{item.readStatus},</if>
+                <if test="item.readTime != null">#{item.readTime},</if>
+            </trim>
+        </foreach>
+    </insert>
+
+
+</mapper>

+ 99 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/MessagesMapper.xml

@@ -0,0 +1,99 @@
+<?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="org.dromara.business.mapper.MessagesMapper">
+
+    <select id="selectVoPage" resultType="org.dromara.business.domain.vo.MessagesVo">
+        SELECT  id,
+                title,
+                content,
+                sender_id,
+                receiver_type,
+                receiver_ids,
+                send_time,
+                message_type,
+                status
+        FROM messages ${ew.customSqlSegment}
+    </select>
+
+
+    <select id="selectMessagesList" resultType="org.dromara.business.domain.vo.MessagesVo">
+        SELECT  id,
+                title,
+                content,
+                sender_id,
+                receiver_type,
+                receiver_ids,
+                send_time,
+                message_type,
+                status
+        FROM messages  ${ew.customSqlSegment}
+    </select>
+
+    <select id="selectVoInfoById" resultType="org.dromara.business.domain.vo.MessagesVo">
+        SELECT  id,
+                title,
+                content,
+                sender_id,
+                receiver_type,
+                receiver_ids,
+                send_time,
+                message_type,
+                status
+        FROM messages   WHERE id =  #{id}
+    </select>
+
+    <update id="updateMessage">
+        UPDATE messages
+        SET
+        <if test="title != null">title = #{title},</if>
+        <if test="content != null">content = #{content},</if>
+        <if test="senderId != null">sender_id = #{senderId},</if>
+        <if test="receiverType != null">receiver_type = #{receiverType},</if>
+        <if test="receiverIds != null">receiver_ids = #{receiverIds},</if>
+        <if test="messageType != null">message_type = #{messageType},</if>
+        <if test="status != null">status = #{status},</if>
+        WHERE id = #{id}
+    </update>
+
+    <insert id="insertMessage"  useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO messages
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="title != null and title != ''">title,</if>
+            <if test="content != null and content != ''">content,</if>
+            <if test="senderId != null">sender_id,</if>
+            <if test="receiverType != null and receiverType != ''">receiver_type,</if>
+            <if test="receiverIds != null and receiverIds != ''">receiver_ids,</if>
+            <if test="messageType != null and messageType != ''">message_type,</if>
+            <if test="status != null and status != ''">status,</if>
+        </trim>
+        VALUES
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="title != null and title != ''">#{title},</if>
+            <if test="content != null and content != ''">#{content},</if>
+            <if test="senderId != null">#{senderId},</if>
+            <if test="receiverType != null and receiverType != ''">#{receiverType},</if>
+            <if test="receiverIds != null and receiverIds != ''">#{receiverIds},</if>
+            <if test="messageType != null and messageType != ''">#{messageType},</if>
+            <if test="status != null and status != ''">#{status},</if>
+        </trim>
+    </insert>
+
+
+    <delete id="deleteMessageById">
+        DELETE FROM messages
+        <where>
+            id IN
+            <foreach item="id" collection="ids" open="(" separator="," close=")">
+                <if test="id > 0">
+                    #{id}
+                </if>
+            </foreach>
+        </where>
+    </delete>
+
+
+
+
+</mapper>

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/TournamentsMapper.xml

@@ -67,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="levelDuration != null">#{levelDuration},</if>
             <if test="lateRegistrationLevel != null">#{lateRegistrationLevel},</if>
             <if test="maxPlayers != null">#{maxPlayers},</if>
-            <if test="status != null">#{status}</if>
+            <if test="status != null">#{status},</if>
             <if test="signTime != null">#{signTime},</if>
             <if test="competitionIcon != null">#{competitionIcon},</if>
             <if test="createUserId != null">#{createUserId},</if>