24282 2 年之前
父节点
当前提交
ded95eabbd

+ 79 - 0
hx-common/src/main/java/com/fjhx/common/controller/send/SendMegController.java

@@ -0,0 +1,79 @@
+package com.fjhx.common.controller.send;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.common.entity.send.dto.SendMegDto;
+import com.fjhx.common.entity.send.dto.SendMegSelectDto;
+import com.fjhx.common.entity.send.vo.SendMegVo;
+import com.fjhx.common.service.send.SendMegService;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-05-22
+ */
+@EnableScheduling
+@RestController
+@RequestMapping("/sendMeg")
+public class SendMegController {
+
+    @Autowired
+    private SendMegService sendMegService;
+
+    /**
+     * 分页
+     */
+    @PostMapping("/page")
+    public Page<SendMegVo> page(@RequestBody SendMegSelectDto dto) {
+        return sendMegService.getPage(dto);
+    }
+
+    /**
+     * 明细
+     */
+    @PostMapping("/detail")
+    public SendMegVo detail(@RequestBody BaseSelectDto dto) {
+        return sendMegService.detail(dto.getId());
+    }
+
+    /**
+     * 新增
+     */
+    @PostMapping("/add")
+    public void add(@RequestBody SendMegDto sendMegDto) {
+        sendMegService.add(sendMegDto);
+    }
+
+    /**
+     * 编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody SendMegDto sendMegDto) {
+        sendMegService.edit(sendMegDto);
+    }
+
+    /**
+     * 删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        sendMegService.delete(dto.getId());
+    }
+
+    @Scheduled(cron = "0 0/1 *  * * ? ")   // 每1分钟执行一次
+    public void execute() {
+        sendMegService.executeSend();
+    }
+
+}

+ 19 - 0
hx-common/src/main/java/com/fjhx/common/entity/send/dto/SendMegDto.java

@@ -0,0 +1,19 @@
+package com.fjhx.common.entity.send.dto;
+
+import com.fjhx.common.entity.send.po.SendMeg;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 新增编辑入参实体
+ *
+ * @author 
+ * @since 2023-05-22
+ */
+@Getter
+@Setter
+public class SendMegDto extends SendMeg {
+
+
+
+}

+ 27 - 0
hx-common/src/main/java/com/fjhx/common/entity/send/dto/SendMegSelectDto.java

@@ -0,0 +1,27 @@
+package com.fjhx.common.entity.send.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 列表查询入参实体
+ *
+ * @author 
+ * @since 2023-05-22
+ */
+@Getter
+@Setter
+public class SendMegSelectDto extends BaseSelectDto {
+
+    /**
+     * 状态 0待发送 1以发送
+     */
+    private Integer status;
+
+    /**
+     * 消息类型 1系统公告
+     */
+    private Integer type;
+
+}

+ 59 - 0
hx-common/src/main/java/com/fjhx/common/entity/send/po/SendMeg.java

@@ -0,0 +1,59 @@
+package com.fjhx.common.entity.send.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author
+ * @since 2023-05-22
+ */
+@Getter
+@Setter
+@TableName("send_meg")
+public class SendMeg extends BasePo {
+
+    /**
+     * 消息类型 1系统公告
+     */
+    @NotNull(message = "消息类型不能为空")
+    private Integer type;
+
+    /**
+     * 标题
+     */
+    @NotEmpty(message = "标题不能为空")
+    private String title;
+
+    /**
+     * 内容
+     */
+    @NotEmpty(message = "消息正文不能为空")
+    private String content;
+
+    /**
+     * 发送时间
+     */
+    @NotEmpty(message = "发送时间不能为空")
+    private Date sendTime;
+
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+
+    /**
+     * 状态 0待发送 1已发送
+     */
+    private Integer status;
+
+}

+ 17 - 0
hx-common/src/main/java/com/fjhx/common/entity/send/vo/SendMegVo.java

@@ -0,0 +1,17 @@
+package com.fjhx.common.entity.send.vo;
+
+import com.fjhx.common.entity.send.po.SendMeg;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 列表查询返回值实体
+ *
+ * @author 
+ * @since 2023-05-22
+ */
+@Getter
+@Setter
+public class SendMegVo extends SendMeg {
+
+}

+ 26 - 0
hx-common/src/main/java/com/fjhx/common/mapper/send/SendMegMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.common.mapper.send;
+
+import com.fjhx.common.entity.send.po.SendMeg;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.common.entity.send.vo.SendMegVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-05-22
+ */
+public interface SendMegMapper extends BaseMapper<SendMeg> {
+
+    /**
+     * 分页
+     */
+    Page<SendMegVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<SendMeg> wrapper);
+
+}

+ 55 - 0
hx-common/src/main/java/com/fjhx/common/service/send/SendMegService.java

@@ -0,0 +1,55 @@
+package com.fjhx.common.service.send;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.common.entity.send.dto.SendMegDto;
+import com.fjhx.common.entity.send.dto.SendMegSelectDto;
+import com.fjhx.common.entity.send.po.SendMeg;
+import com.fjhx.common.entity.send.vo.SendMegVo;
+import com.ruoyi.common.core.service.BaseService;
+
+
+/**
+ * <p>
+ * 服务类
+ * </p>
+ *
+ * @author
+ * @since 2023-05-22
+ */
+public interface SendMegService extends BaseService<SendMeg> {
+
+    /**
+     * 分页
+     */
+    Page<SendMegVo> getPage(SendMegSelectDto dto);
+
+    /**
+     * 明细
+     */
+    SendMegVo detail(Long id);
+
+    /**
+     * 新增
+     */
+    void add(SendMegDto sendMegDto);
+
+    /**
+     * 编辑
+     */
+    void edit(SendMegDto sendMegDto);
+
+    /**
+     * 删除
+     */
+    void delete(Long id);
+
+    /**
+     * 推送数据
+     */
+    void send(SendMeg sendMeg);
+
+
+    void executeSend();
+
+
+}

+ 167 - 0
hx-common/src/main/java/com/fjhx/common/service/send/impl/SendMegServiceImpl.java

@@ -0,0 +1,167 @@
+package com.fjhx.common.service.send.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.common.constant.SourceConstant;
+import com.fjhx.common.entity.send.dto.SendMegDto;
+import com.fjhx.common.entity.send.dto.SendMegSelectDto;
+import com.fjhx.common.entity.send.po.SendMeg;
+import com.fjhx.common.entity.send.vo.SendMegVo;
+import com.fjhx.common.mapper.send.SendMegMapper;
+import com.fjhx.common.service.send.SendMegService;
+import com.fjhx.socket.entity.MessageEntity;
+import com.fjhx.socket.event.WebSocketUserOfflineEvent;
+import com.fjhx.socket.service.WebSocketServer;
+import com.ruoyi.common.constant.StatusConstant;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import com.ruoyi.framework.mybatis.holder.TenantHolder;
+import com.ruoyi.system.service.ISysUserService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-05-22
+ */
+@Slf4j
+@Service
+public class SendMegServiceImpl extends ServiceImpl<SendMegMapper, SendMeg> implements SendMegService {
+
+    @Autowired
+    private ISysUserService sysUserService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    private static final String sendMessageKey = "sendMessage:";
+
+    @Override
+    public Page<SendMegVo> getPage(SendMegSelectDto dto) {
+        IWrapper<SendMeg> wrapper = getWrapper();
+        wrapper.eq("sm", SendMeg::getType, dto.getType());
+        wrapper.eq("sm", SendMeg::getStatus, dto.getStatus());
+        wrapper.orderByAsc("sm", SendMeg::getStatus);
+        wrapper.orderByDesc("sm", SendMeg::getId);
+        Page<SendMegVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public SendMegVo detail(Long id) {
+        SendMeg SendMeg = this.getById(id);
+        SendMegVo result = BeanUtil.toBean(SendMeg, SendMegVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(SendMegDto sendMegDto) {
+        Date sendTime = sendMegDto.getSendTime();
+        if (sendTime.before(DateUtil.endOfMinute(new Date()))) {
+            sendMegDto.setStatus(StatusConstant.YES);
+            new Thread(() -> send(sendMegDto)).start();
+        } else {
+            sendMegDto.setStatus(StatusConstant.NO);
+        }
+
+        this.save(sendMegDto);
+    }
+
+    @Override
+    public void edit(SendMegDto sendMegDto) {
+        sendMegDto.setStatus(StatusConstant.YES);
+        this.updateById(sendMegDto);
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+    @Override
+    public synchronized void send(SendMeg sendMeg) {
+        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
+        TenantHolder.setIgnore(true);
+        List<SysUser> list = sysUserService.list();
+        DynamicDataSourceContextHolder.poll();
+
+        for (SysUser sysUser : list) {
+            WebSocketServer.sendInfo(sysUser.getUserId(), 0, sendMeg);
+        }
+
+    }
+
+    @Override
+    public void executeSend() {
+
+        Set<String> scan = redisCache.scan(sendMessageKey + "**");
+        for (String key : scan) {
+            String[] split = key.split(":");
+            if (split.length != 3) {
+                return;
+            }
+            String userIdStr = split[2];
+            Long userId = Convert.toLong(userIdStr);
+            if (userId == null) {
+                return;
+            }
+
+            try {
+                SendMeg cacheObject = redisCache.getCacheObject(key);
+                redisCache.deleteObject(key);
+                WebSocketServer.sendInfo(userId, 0, cacheObject);
+            } catch (Exception e) {
+                log.error("推送异常", e);
+            }
+
+        }
+
+
+        List<SendMeg> list = list(q -> q
+                .eq(SendMeg::getStatus, StatusConstant.NO)
+                .le(SendMeg::getSendTime, DateUtil.endOfMinute(new Date())));
+
+        for (SendMeg sendMeg : list) {
+            send(sendMeg);
+            sendMeg.setStatus(StatusConstant.YES);
+        }
+        updateBatchById(list);
+
+    }
+
+    @EventListener
+    public void userOfflineEvent(WebSocketUserOfflineEvent webSocketUserOfflineEvent) {
+        MessageEntity messageEntity = webSocketUserOfflineEvent.getMessageEntity();
+
+        Object data = messageEntity.getData();
+
+        if (messageEntity.getType() != 0 || !(data instanceof SendMeg)) {
+            return;
+        }
+
+        log.error("用户{}不在线", messageEntity.getUserId());
+        String key = sendMessageKey + ((SendMeg) data).getId() + ":" + messageEntity.getUserId();
+        if (((SendMeg) data).getEndTime().after(new Date())) {
+            redisCache.setCacheObject(key, data);
+        }
+
+    }
+
+
+}

+ 21 - 0
hx-common/src/main/resources/mapper/send/SendMegMapper.xml

@@ -0,0 +1,21 @@
+<?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.fjhx.common.mapper.send.SendMegMapper">
+    <select id="getPage" resultType="com.fjhx.common.entity.send.vo.SendMegVo">
+        select
+            sm.id,
+            sm.type,
+            sm.title,
+            sm.content,
+            sm.send_time,
+            sm.end_time,
+            sm.status,
+            sm.create_user,
+            sm.create_time,
+            sm.update_user,
+            sm.update_time
+        from send_meg sm
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>