diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application-dev.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application-dev.yml index be349c0a..953e8f06 100644 --- a/xinnengyuan/ruoyi-admin/src/main/resources/application-dev.yml +++ b/xinnengyuan/ruoyi-admin/src/main/resources/application-dev.yml @@ -368,3 +368,14 @@ drone: chat: server: port: 19099 +# rabbitmq 配置 +rabbitmq: + exchange-name: dev-normal-exchange + queue-name: dev-normal-queue + routing-key: dev.normal.routing.key + delay-exchange-name: dev-delay-queue + delay-queue-name: dev-delay-exchange + delay-routing-key: dev.delay.routing.key + dead-letter-exchange: dev-dlx-exchange + dead-letter-queue: dev-dlx-queue + dead-letter-routing-key: dev.dlx.routing.key diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application-local.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application-local.yml index 64b0ccdc..38eebf83 100644 --- a/xinnengyuan/ruoyi-admin/src/main/resources/application-local.yml +++ b/xinnengyuan/ruoyi-admin/src/main/resources/application-local.yml @@ -343,3 +343,14 @@ drone: chat: server: port: 18088 +# rabbitmq 配置 +rabbitmq: + exchange-name: local-normal-exchange + queue-name: local-normal-queue + routing-key: local.normal.routing.key + delay-exchange-name: local-delay-queue + delay-queue-name: local-delay-exchange + delay-routing-key: local.delay.routing.key + dead-letter-exchange: local-dlx-exchange + dead-letter-queue: local-dlx-queue + dead-letter-routing-key: local.dlx.routing.key diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application-prod.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application-prod.yml index 235b008a..5b6e6e05 100644 --- a/xinnengyuan/ruoyi-admin/src/main/resources/application-prod.yml +++ b/xinnengyuan/ruoyi-admin/src/main/resources/application-prod.yml @@ -358,3 +358,14 @@ drone: chat: server: port: 19099 +# rabbitmq 配置 +rabbitmq: + exchange-name: prod-normal-exchange + queue-name: prod-normal-queue + routing-key: prod.normal.routing.key + delay-exchange-name: prod-delay-queue + delay-queue-name: prod-delay-exchange + delay-routing-key: prod.delay.routing.key + dead-letter-exchange: prod-dlx-exchange + dead-letter-queue: prod-dlx-queue + dead-letter-routing-key: prod.dlx.routing.key diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml index 84e30e7e..87e8a97c 100644 --- a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml +++ b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml @@ -95,7 +95,13 @@ spring: deserialization: # 允许对象忽略json中不存在的属性 fail_on_unknown_properties: false - + rabbitmq: + host: 192.168.110.2 + port: 5672 + username: admin + password: yuanjiexny + publisher-returns: true + publisher-confirm-type: correlated # Sa-Token配置 sa-token: # token名称 (同时也是cookie名称) diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/pom.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/pom.xml index 4bffab53..c9925bb7 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/pom.xml +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/pom.xml @@ -29,6 +29,10 @@ + + org.springframework.boot + spring-boot-starter-amqp + com.twelvemonkeys.imageio diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/device/service/impl/DeviceAccessRecordServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/device/service/impl/DeviceAccessRecordServiceImpl.java index ee4297b5..b73aeb5c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/device/service/impl/DeviceAccessRecordServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/device/service/impl/DeviceAccessRecordServiceImpl.java @@ -16,6 +16,7 @@ import org.dromara.device.domain.DeviceAccessRecord; import org.dromara.device.mapper.DeviceAccessRecordMapper; import org.dromara.device.service.IDeviceAccessRecordService; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.Collection; @@ -77,6 +78,16 @@ public class DeviceAccessRecordServiceImpl extends ServiceImpl list = baseMapper.selectList(queryWrapper); checkIds.addAll(list.stream().map(DeviceType::getId).toList()); } + checkIds.addAll(ids); List list = deviceInfoService.lambdaQuery().in(DeviceInfo::getTypeId, checkIds).list(); if(CollectionUtil.isNotEmpty(list)){ throw new ServiceException("当前类型或子级类型存在设备"); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/JxAqjcgl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/JxAqjcgl.java index 4fd181d4..e2909aee 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/JxAqjcgl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/JxAqjcgl.java @@ -97,11 +97,27 @@ public class JxAqjcgl extends BaseEntity { */ private String riskGrade; + + /** + * 整改状态 + */ + private String abarbeitungState; + /** * 整改责任人 */ private Long abarbeitung; + /** + * 选择分包还是班组 + */ + private String rectificationUnit; + + /** + * 整改单位 + */ + private Long rectificationId; + /** * 整改日期 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/bo/JxAqjcglBo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/bo/JxAqjcglBo.java index a3d4d15a..510a9425 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/bo/JxAqjcglBo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/bo/JxAqjcglBo.java @@ -57,6 +57,22 @@ public class JxAqjcglBo extends BaseEntity { */ private String participants; + + /** + * 整改状态 + */ + private String abarbeitungState; + + /** + * 选择分包还是班组 + */ + private String rectificationUnit; + + /** + * 整改单位 + */ + private Long rectificationId; + /** * 所属项目(如田东) */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/vo/JxAqjcglVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/vo/JxAqjcglVo.java index 224e2f0d..73f1729b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/vo/JxAqjcglVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/domain/vo/JxAqjcglVo.java @@ -71,6 +71,26 @@ public class JxAqjcglVo implements Serializable { @ExcelProperty(value = "检查人") private Long inspector; + + /** + * 整改状态 + */ + private String abarbeitungState; + + /** + * 选择分包还是班组 + */ + private String rectificationUnit; + + /** + * 整改单位 + */ + private Long rectificationId; + + /** + * 整改单位 + */ + private String rectificationName; /** * 检查人 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/service/impl/JxAqjcglServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/service/impl/JxAqjcglServiceImpl.java index ddbc94f0..ad85eb0c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/service/impl/JxAqjcglServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxaqgl/service/impl/JxAqjcglServiceImpl.java @@ -1,9 +1,11 @@ package org.dromara.mechanical.jxaqgl.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.enums.InspectionRectificationUnitType; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -11,6 +13,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import org.dromara.common.utils.BatchNumberGenerator; +import org.dromara.contractor.domain.SubContractor; +import org.dromara.contractor.service.ISubContractorService; import org.dromara.mechanical.jxaqgl.domain.JxAqjcglJcnr; import org.dromara.mechanical.jxaqgl.domain.JxAqjcglWtxq; import org.dromara.mechanical.jxaqgl.domain.MonthDateRange; @@ -25,6 +29,9 @@ import org.dromara.mechanical.jxzgbh.domain.bo.JxYhzgbhBo; import org.dromara.mechanical.jxzgbh.domain.bo.JxZgxxBo; import org.dromara.mechanical.jxzgbh.service.IJxYhzgbhService; import org.dromara.mechanical.jxzgbh.service.IJxZgxxService; +import org.dromara.project.domain.BusProjectTeam; +import org.dromara.project.service.IBusProjectService; +import org.dromara.project.service.IBusProjectTeamService; import org.dromara.system.service.impl.SysOssServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -58,6 +65,12 @@ public class JxAqjcglServiceImpl extends ServiceImpl i private final SysOssServiceImpl sysOssService; + @Resource + private ISubContractorService contractorService; + + @Resource + private IBusProjectTeamService projectTeamService; + @Lazy @Autowired private IJxYhzgbhService jxYhzgbhService; @@ -82,6 +95,23 @@ public class JxAqjcglServiceImpl extends ServiceImpl i List jxAqjcglJcnrs = jxAqjcglJcnrService.getBaseMapper().selectList(new LambdaQueryWrapper().eq(JxAqjcglJcnr::getMasterId, jxAqjcglVo.getId())); jxAqjcglVo.setWtxqBoList(jxAqjcglWtxqs); jxAqjcglVo.setJcnrList(jxAqjcglJcnrs); + + // 关联整改单位信息 + Long rectificationId = jxAqjcglVo.getRectificationId(); + String rectificationUnit = jxAqjcglVo.getRectificationUnit(); + if (rectificationId != null && rectificationUnit != null) { + if (rectificationUnit.equals(InspectionRectificationUnitType.CONTRACTOR.getValue())) { + SubContractor contractor = contractorService.getById(rectificationId); + jxAqjcglVo.setRectificationName(contractor.getName()); + } else if (rectificationUnit.equals(InspectionRectificationUnitType.TEAM.getValue())) { + BusProjectTeam team = projectTeamService.getById(rectificationId); + if (team != null) { + jxAqjcglVo.setRectificationName(team.getTeamName()); + } + } + } + + } } @@ -179,6 +209,7 @@ public class JxAqjcglServiceImpl extends ServiceImpl i JxAqjcgl update = MapstructUtils.convert(bo, JxAqjcgl.class); validEntityBeforeSave(update); if ("2".equals(bo.getInspectionResult())){ + update.setAbarbeitungState("1"); JxYhzgbh jxYhzgbh = jxYhzgbhService.getBaseMapper().selectOne(new LambdaQueryWrapper().eq(JxYhzgbh::getMasterId, update.getId())); if (jxYhzgbh != null) throw new ServiceException("该数据已存在整改数据"); // 不通过转为整改数据 diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/domain/vo/JxFcxxVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/domain/vo/JxFcxxVo.java index f77c7a10..8eff49c5 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/domain/vo/JxFcxxVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/domain/vo/JxFcxxVo.java @@ -1,5 +1,7 @@ package org.dromara.mechanical.jxzgbh.domain.vo; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.constant.TransConstant; import org.dromara.mechanical.jxzgbh.domain.JxFcxx; @@ -103,4 +105,15 @@ public class JxFcxxVo implements Serializable { private Integer sort; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + + + + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/service/impl/JxYhzgbhServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/service/impl/JxYhzgbhServiceImpl.java index 6c7f2818..1a3315fe 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/service/impl/JxYhzgbhServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/mechanical/jxzgbh/service/impl/JxYhzgbhServiceImpl.java @@ -14,6 +14,7 @@ import lombok.RequiredArgsConstructor; import org.dromara.mechanical.jxaqgl.domain.JxAqjcgl; import org.dromara.mechanical.jxaqgl.domain.JxAqjcglWtxq; import org.dromara.mechanical.jxaqgl.domain.MonthDateRange; +import org.dromara.mechanical.jxaqgl.service.IJxAqjcglService; import org.dromara.mechanical.jxaqgl.service.IJxAqjcglWtxqService; import org.dromara.mechanical.jxzgbh.domain.JxFcxx; import org.dromara.mechanical.jxzgbh.domain.JxZgxx; @@ -53,6 +54,8 @@ public class JxYhzgbhServiceImpl extends ServiceImpl i private final IJxAqjcglWtxqService jxAqjcglWtxqService; + private final IJxAqjcglService jxAqjcglService; + /** * 查询机械隐患整改与闭环 * @@ -98,6 +101,7 @@ public class JxYhzgbhServiceImpl extends ServiceImpl i public TableDataInfo queryPageList(JxYhzgbhBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + result.getRecords().forEach(this::saveValue); return TableDataInfo.build(result); } @@ -200,6 +204,11 @@ public class JxYhzgbhServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public Boolean zgPutBo(JxZgxxBo bo) { +// 安全检查记录 + if (bo.getMasterId() == null) throw new RuntimeException("主表id不能为空"); + JxYhzgbhVo jxYhzgbhVo = this.getBaseMapper().selectVoOne(new LambdaQueryWrapper().eq(JxYhzgbh::getId, bo.getMasterId())); + jxAqjcglService.getBaseMapper().update(new LambdaUpdateWrapper().eq(JxAqjcgl::getId, jxYhzgbhVo.getMasterId()).set(JxAqjcgl::getAbarbeitungState, "2")); + Long l = jxZgxxService.getBaseMapper().selectCount(new LambdaQueryWrapper().eq(JxZgxx::getMasterId, bo.getMasterId())); bo.setSort(Integer.parseInt(l+"") + 1); // 将状态修改为已整改 @@ -210,8 +219,14 @@ public class JxYhzgbhServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public Boolean fcPutBo(JxFcxxBo bo) { +// 不通过修改整改信息状态 if (bo.getReviewOpinion().equals("2")) { + if (bo.getMasterId() == null) throw new RuntimeException("主表id不能为空"); this.getBaseMapper().update(new LambdaUpdateWrapper().eq(JxYhzgbh::getId, bo.getMasterId()).set(JxYhzgbh::getAbarbeitungState,"1")); + // 安全检查记录 + JxYhzgbhVo jxYhzgbhVo = this.getBaseMapper().selectVoOne(new LambdaQueryWrapper().eq(JxYhzgbh::getId, bo.getMasterId())); + jxAqjcglService.getBaseMapper().update(new LambdaUpdateWrapper().eq(JxAqjcgl::getId, jxYhzgbhVo.getMasterId()).set(JxAqjcgl::getAbarbeitungState, "1")); + } this.getBaseMapper().update(new LambdaUpdateWrapper().eq(JxYhzgbh::getId, bo.getMasterId()).set(JxYhzgbh::getReviewOpinion,bo.getReviewOpinion())); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusProjectTeamAppController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusProjectTeamAppController.java index 8b976f97..3bf54a6d 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusProjectTeamAppController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/app/BusProjectTeamAppController.java @@ -4,12 +4,17 @@ import jakarta.annotation.Resource; import jakarta.validation.constraints.NotNull; import org.dromara.common.core.domain.R; import org.dromara.common.web.core.BaseController; +import org.dromara.contractor.domain.dto.contractor.SubContractorQueryReq; +import org.dromara.contractor.domain.vo.contractor.SubContractorVo; +import org.dromara.contractor.service.ISubContractorService; import org.dromara.project.domain.dto.projectteam.BusProjectTeamQueryReq; import org.dromara.project.domain.vo.projectteam.BusProjectTeamAppVo; import org.dromara.project.domain.vo.projectteam.BusProjectTeamForemanVo; import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo; import org.dromara.project.domain.vo.projectteam.TeamManageVo; import org.dromara.project.service.IBusProjectTeamService; +import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.service.ISysUserService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -32,6 +37,12 @@ public class BusProjectTeamAppController extends BaseController { @Resource private IBusProjectTeamService projectTeamService; + @Resource + private ISysUserService userService; + + @Resource + private ISubContractorService contractorService; + /** * 根据id查询项目班组班组长信息列表 */ @@ -76,4 +87,21 @@ public class BusProjectTeamAppController extends BaseController { return R.ok(projectTeamService.getManager(teamId)); } + /** + * 查询分包单位列表 + */ + @GetMapping("/contractorList") + public R> contractorList(SubContractorQueryReq req) { + return R.ok(contractorService.queryList(req)); + } + + + /** + * 获取所有分包管理人员 + */ + @GetMapping("/listSubContractor") + public R> listSubContractor(Long projectId, Long contractorId) { + return R.ok(userService.selectUserListByAppUserType("2",projectId,contractorId)); + } + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitConfig.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitConfig.java new file mode 100644 index 00000000..c5761106 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitConfig.java @@ -0,0 +1,57 @@ +package org.dromara.rabbitmq.config; + +import jakarta.annotation.Resource; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author xbhog + */ +@Configuration +public class RabbitConfig { + + @Resource + private RabbitProperties rabbitProperties; + + /** + * 创建交换机 + * ExchangeBuilder有四种交换机模式 + * Direct Exchange:直连交换机,根据Routing Key(路由键)进行投递到不同队列。 + * Fanout Exchange:扇形交换机,采用广播模式,根据绑定的交换机,路由到与之对应的所有队列。 + * Topic Exchange:主题交换机,对路由键进行模式匹配后进行投递,符号#表示一个或多个词,*表示一个词。 + * Header Exchange:头交换机,不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。 + * durable 交换器是否持久化(false 不持久化,true 持久化) + **/ + @Bean + public TopicExchange exchange() { + return new TopicExchange(rabbitProperties.getExchangeName()); + } + + /** + * 创建队列 + * durable 队列是否持久化 队列调用此方法就是持久化 可查看方法的源码 + * deliveryMode 消息是否持久化(1 不持久化,2 持久化) + **/ + @Bean + public Queue queue() { + return new Queue(rabbitProperties.getQueueName(), false); + } + + /** + * 绑定交换机和队列 + * bing 方法参数可以是队列和交换机 + * to 方法参数必须是交换机 + * with 方法参数是路由Key 这里是以rabbit.开头 + * noargs 就是不要参数的意思 + * 这个方法的意思是把rabbit开头的消息 和 上面的队列 和 上面的交换机绑定 + **/ + @Bean + public Binding binding(Queue queue, TopicExchange exchange) { + return BindingBuilder.bind(queue).to(exchange).with(rabbitProperties.getRoutingKey()); + } + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitProperties.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitProperties.java new file mode 100644 index 00000000..868667df --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitProperties.java @@ -0,0 +1,60 @@ +package org.dromara.rabbitmq.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author lilemy + * @date 2025-12-05 16:25 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "rabbitmq") +public class RabbitProperties { + + /** + * 交换机名称 + */ + private String exchangeName; + + /** + * 队列名称 + */ + private String queueName; + + /** + * 路由键名称 + */ + private String routingKey; + + /** + * 延迟交换机名称 + */ + private String delayExchangeName; + + /** + * 延迟队列名称 + */ + private String delayQueueName; + + /** + * 延迟路由键名称 + */ + private String delayRoutingKey; + + /** + * 死信交换机名称 + */ + private String deadLetterExchange; + + /** + * 死信队列名称 + */ + private String deadLetterQueue; + + /** + * 死信路由键名称 + */ + private String deadLetterRoutingKey; +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitTtlQueueConfig.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitTtlQueueConfig.java new file mode 100644 index 00000000..94abf3cb --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/config/RabbitTtlQueueConfig.java @@ -0,0 +1,75 @@ +package org.dromara.rabbitmq.config; + +import jakarta.annotation.Resource; +import org.springframework.amqp.core.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; + + +/** + * RabbitTTL队列 + * + * @author xbhog + */ +@Configuration +public class RabbitTtlQueueConfig { + + @Resource + private RabbitProperties rabbitProperties; + + /** + * 声明延迟队列 + */ + @Bean + public Queue delayQueue() { + return QueueBuilder.durable(rabbitProperties.getDelayQueueName()) + .deadLetterExchange(rabbitProperties.getDeadLetterExchange()) + .deadLetterRoutingKey(rabbitProperties.getDeadLetterRoutingKey()) + .build(); + } + + /** + * 声明延迟交换机 + */ + @Bean + public CustomExchange delayExchange() { + return new CustomExchange(rabbitProperties.getDelayExchangeName(), "x-delayed-message", + true, false, Map.of("x-delayed-type", "direct")); + } + + /** + * 将延迟队列绑定到延迟交换机 + */ + @Bean + public Binding delayBinding(Queue delayQueue, CustomExchange delayExchange) { + return BindingBuilder.bind(delayQueue).to(delayExchange).with(rabbitProperties.getDelayRoutingKey()).noargs(); + } + + /** + * 声明死信队列 + */ + @Bean + public Queue deadLetterQueue() { + return new Queue(rabbitProperties.getDeadLetterQueue()); + } + + /** + * 声明死信交换机 + */ + @Bean + public DirectExchange deadLetterExchange() { + return new DirectExchange(rabbitProperties.getDeadLetterExchange()); + } + + /** + * 将死信队列绑定到死信交换机 + */ + @Bean + public Binding deadLetterBinding(Queue deadLetterQueue, DirectExchange deadLetterExchange) { + return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with(rabbitProperties.getDeadLetterRoutingKey()); + } + +} + diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/consumer/RabbitConsumer.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/consumer/RabbitConsumer.java new file mode 100644 index 00000000..1f1b5bd1 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/consumer/RabbitConsumer.java @@ -0,0 +1,65 @@ +package org.dromara.rabbitmq.consumer; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.rabbitmq.service.IMqDelayTaskService; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +/** + * @author lilemy + * @date 2025-12-05 14:09 + */ +@Slf4j +@Component +public class RabbitConsumer { + + @Resource + private IMqDelayTaskService mqDelayTaskService; + + /** + * 普通消息 + */ + @RabbitListener(queues = "${rabbitmq.queue-name}") + public void listenQueue(Message message) { + log.info("【消费者】Start consuming data:{}", new String(message.getBody())); + } + + /** + * 处理延迟队列消息 + */ + @RabbitListener(queues = "${rabbitmq.delay-queue-name}") + public void receiveDelayMessage(String message) { + log.info("【消费者】Received delayed message:{}", message); + if (StringUtils.isNotBlank(message) && isLong(message)) { + mqDelayTaskService.executeTask(Long.parseLong(message)); + } + } + + /** + * 处理死信队列消息 + * 当消息在延迟队列中未能被正确处理(例如因消费者逻辑错误、超时未ACK等原因) + * 它会被自动转发到死信队列中,以便后续的特殊处理或重新尝试。 + */ + @RabbitListener(queues = "${rabbitmq.dead-letter-queue}") + public void receiveDeadMessage(String message) { + log.info("【消费者】Received dead message:{}", message); + } + + /** + * 判断字符串是否为Long + * + * @param str 字符串 + * @return 是否为Long + */ + private static boolean isLong(String str) { + try { + Long.parseLong(str); + return true; + } catch (Exception e) { + return false; + } + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/MqDelayTask.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/MqDelayTask.java new file mode 100644 index 00000000..3a7499ba --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/MqDelayTask.java @@ -0,0 +1,66 @@ +package org.dromara.rabbitmq.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 延迟任务对象 mq_delay_task + * + * @author lilemy + * @date 2025-12-05 + */ +@Data +@TableName("mq_delay_task") +public class MqDelayTask implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id") + private Long id; + + /** + * 业务类型 + */ + private String bizType; + + /** + * 业务ID + */ + private Long bizId; + + /** + * 执行的时间点 + */ + private LocalDateTime executeTime; + + /** + * 任务状态 0未执行 1执行中 2执行成功 3执行失败 + */ + private Integer status; + + /** + * 重试次数 + */ + private Integer retryCount; + + /** + * 最大重试次数 + */ + private Integer maxRetry; + + /** + * 失败原因 + */ + private String failReason; + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/vo/MqDelayTaskVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/vo/MqDelayTaskVo.java new file mode 100644 index 00000000..99287526 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/domain/vo/MqDelayTaskVo.java @@ -0,0 +1,76 @@ +package org.dromara.rabbitmq.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.rabbitmq.domain.MqDelayTask; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + + +/** + * 延迟任务视图对象 mq_delay_task + * + * @author lilemy + * @date 2025-12-05 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = MqDelayTask.class) +public class MqDelayTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @ExcelProperty(value = "主键") + private Long id; + + /** + * 业务类型 + */ + @ExcelProperty(value = "业务类型") + private String bizType; + + /** + * 业务ID + */ + @ExcelProperty(value = "业务ID") + private Long bizId; + + /** + * 执行的时间点 + */ + @ExcelProperty(value = "执行的时间点") + private LocalDateTime executeTime; + + /** + * 任务状态 0未执行 1执行中 2执行成功 3执行失败 + */ + @ExcelProperty(value = "任务状态 0未执行 1执行中 2执行成功 3执行失败") + private Integer status; + + /** + * 重试次数 + */ + @ExcelProperty(value = "重试次数") + private Integer retryCount; + + /** + * 最大重试次数 + */ + @ExcelProperty(value = "最大重试次数") + private Integer maxRetry; + + /** + * 失败原因 + */ + @ExcelProperty(value = "失败原因") + private String failReason; + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/enums/MqDelayTaskTypeEnum.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/enums/MqDelayTaskTypeEnum.java new file mode 100644 index 00000000..c7e7fc67 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/enums/MqDelayTaskTypeEnum.java @@ -0,0 +1,35 @@ +package org.dromara.rabbitmq.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author lilemy + * @date 2025-12-05 18:26 + */ +@Getter +@AllArgsConstructor +public enum MqDelayTaskTypeEnum { + + /** + * 安全隐患 + */ + HIDDEN_DANGER("aqyh"); + + private final String type; + + /** + * 根据业务类型获取枚举 + * + * @param type 业务类型 + * @return 枚举 + */ + public static MqDelayTaskTypeEnum getByType(String type) { + for (MqDelayTaskTypeEnum value : values()) { + if (value.getType().equals(type)) { + return value; + } + } + return null; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/mapper/MqDelayTaskMapper.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/mapper/MqDelayTaskMapper.java new file mode 100644 index 00000000..b817c06c --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/mapper/MqDelayTaskMapper.java @@ -0,0 +1,15 @@ +package org.dromara.rabbitmq.mapper; + +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.rabbitmq.domain.MqDelayTask; +import org.dromara.rabbitmq.domain.vo.MqDelayTaskVo; + +/** + * 延迟任务Mapper接口 + * + * @author lilemy + * @date 2025-12-05 + */ +public interface MqDelayTaskMapper extends BaseMapperPlus { + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/producer/RabbitProducer.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/producer/RabbitProducer.java new file mode 100644 index 00000000..13dcbe08 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/producer/RabbitProducer.java @@ -0,0 +1,51 @@ +package org.dromara.rabbitmq.producer; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.dromara.rabbitmq.config.RabbitProperties; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Component; + +/** + * @author lilemy + * @date 2025-12-05 11:40 + */ +@Slf4j +@Component +public class RabbitProducer { + + @Resource + private RabbitTemplate rabbitTemplate; + + @Resource + private RabbitProperties rabbitProperties; + + /** + * 发送消息 + * + * @param message 消息 + */ + public void send(String message) { + rabbitTemplate.convertAndSend(rabbitProperties.getExchangeName(), rabbitProperties.getRoutingKey(), message); + log.info("【生产者】Message send: {}", message); + } + + /** + * 发送延迟消息 + * + * @param message 消息 + * @param delayMs 延迟时间(毫秒) + */ + public void sendDelayMessage(String message, long delayMs) { + rabbitTemplate.convertAndSend( + rabbitProperties.getDelayExchangeName(), + rabbitProperties.getDelayRoutingKey(), + message, + message1 -> { + message1.getMessageProperties().setDelayLong(delayMs); + return message1; + } + ); + log.info("【生产者】Delay Message send: {} delay: {}ms", message, delayMs); + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/IMqDelayTaskService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/IMqDelayTaskService.java new file mode 100644 index 00000000..5842da36 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/IMqDelayTaskService.java @@ -0,0 +1,27 @@ +package org.dromara.rabbitmq.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.rabbitmq.domain.MqDelayTask; + +/** + * 延迟任务Service接口 + * + * @author lilemy + * @date 2025-12-05 + */ +public interface IMqDelayTaskService extends IService { + + /** + * 添加延迟任务 + * + * @param task 延迟任务 + */ + void addDelayTask(MqDelayTask task); + + /** + * 执行任务 + * + * @param id 主键id + */ + void executeTask(Long id); +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/impl/MqDelayTaskServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/impl/MqDelayTaskServiceImpl.java new file mode 100644 index 00000000..54bdfe83 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/rabbitmq/service/impl/MqDelayTaskServiceImpl.java @@ -0,0 +1,114 @@ +package org.dromara.rabbitmq.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.rabbitmq.domain.MqDelayTask; +import org.dromara.rabbitmq.enums.MqDelayTaskTypeEnum; +import org.dromara.rabbitmq.mapper.MqDelayTaskMapper; +import org.dromara.rabbitmq.producer.RabbitProducer; +import org.dromara.rabbitmq.service.IMqDelayTaskService; +import org.dromara.safety.service.IHazardHiddenDangerRectifyService; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * 延迟任务Service业务层处理 + * + * @author lilemy + * @date 2025-12-05 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class MqDelayTaskServiceImpl extends ServiceImpl + implements IMqDelayTaskService { + + @Resource + private RabbitProducer rabbitProducer; + + @Lazy + @Resource + private IHazardHiddenDangerRectifyService hazardHiddenDangerRectifyService; + + /** + * 添加延迟任务 + * + * @param task 延迟任务 + */ + @Override + public void addDelayTask(MqDelayTask task) { + String bizType = task.getBizType(); + Long bizId = task.getBizId(); + LocalDateTime executeTime = task.getExecuteTime(); + if (StringUtils.isBlank(bizType) || bizId == null || executeTime == null) { + throw new ServiceException("参数错误"); + } + // 保存延迟任务 + boolean save = this.save(task); + if (!save) { + throw new ServiceException("添加延迟任务失败"); + } + // 计算超时时间 + ZoneId zone = ZoneId.systemDefault(); + long diffMillis = Duration.between( + LocalDateTime.now().atZone(zone), + executeTime.atZone(zone) + ).toMillis(); + if (diffMillis <= 0) { + throw new ServiceException("延迟时间不能小于当前时间"); + } + // 添加延迟任务 + rabbitProducer.sendDelayMessage(String.valueOf(task.getId()), diffMillis); + } + + /** + * 执行任务 + * + * @param id 主键id + */ + @Override + public void executeTask(Long id) { + MqDelayTask task = this.getById(id); + if (task == null) { + return; + } + if (task.getStatus() == 1 || task.getStatus() == 2) { + return; + } + try { + // 执行中 + task.setStatus(1); + this.updateById(task); + // 业务逻辑:发送通知 + String bizType = task.getBizType(); + MqDelayTaskTypeEnum type = MqDelayTaskTypeEnum.getByType(bizType); + switch (type) { + case HIDDEN_DANGER -> hazardHiddenDangerRectifyService.sendTimeoutNotify(task.getBizId()); + case null, default -> { + } + } + // 成功 + task.setStatus(2); + this.updateById(task); + } catch (Exception e) { + // 更新失败状态 + task.setRetryCount(task.getRetryCount() + 1); + task.setFailReason(e.getMessage()); + task.setStatus(3); + this.updateById(task); + // 重试机制 + if (task.getRetryCount() < task.getMaxRetry()) { + // 1分钟后重试 + rabbitProducer.sendDelayMessage(String.valueOf(id), 60 * 1000); + } + } + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardHiddenDangerRectifyService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardHiddenDangerRectifyService.java index 45a4eb06..96adfbe0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardHiddenDangerRectifyService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardHiddenDangerRectifyService.java @@ -87,4 +87,11 @@ public interface IHazardHiddenDangerRectifyService extends IService ids, Boolean isValid); + + /** + * 发送超时通知 + * + * @param bizId 业务id + */ + void sendTimeoutNotify(Long bizId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardRuleNotifyObjectService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardRuleNotifyObjectService.java index 6f5b2f51..da32ace9 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardRuleNotifyObjectService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/IHazardRuleNotifyObjectService.java @@ -6,6 +6,7 @@ import org.dromara.safety.domain.vo.HazardRuleNotifyObjectVo; import org.dromara.safety.domain.vo.HazardRuleVo; import java.util.List; +import java.util.Set; /** * 隐患规则通知对象Service接口 @@ -31,6 +32,15 @@ public interface IHazardRuleNotifyObjectService extends IService queryVo(List objectList); + /** + * 根据规则查询所有通知对象id + * + * @param ruleId 规则id + * @param projectId 项目id + * @return 通知对象id + */ + Set queryNotifyObjectIds(Long ruleId, Long projectId); + /** * 补充数据 * diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerRectifyServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerRectifyServiceImpl.java index c3e345a4..8bd887dd 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerRectifyServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerRectifyServiceImpl.java @@ -5,12 +5,15 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.sse.dto.SseMessageDto; +import org.dromara.common.sse.utils.SseMessageUtils; import org.dromara.safety.domain.HazardHiddenDanger; import org.dromara.safety.domain.HazardHiddenDangerRectify; import org.dromara.safety.domain.bo.HazardHiddenDangerBo; @@ -24,6 +27,8 @@ import org.dromara.safety.domain.vo.RectifyTimesVo; import org.dromara.safety.mapper.HazardHiddenDangerRectifyMapper; import org.dromara.safety.service.IHazardHiddenDangerRectifyService; import org.dromara.safety.service.IHazardHiddenDangerService; +import org.dromara.safety.service.IHazardRuleNotifyObjectService; +import org.dromara.websocket.ChatServerHandler; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +37,7 @@ import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; /** * 隐患整改情况Service业务层处理 @@ -39,6 +45,7 @@ import java.util.Map; * @author lilemy * @date 2025-12-04 */ +@Slf4j @RequiredArgsConstructor @Service public class HazardHiddenDangerRectifyServiceImpl extends ServiceImpl @@ -46,6 +53,10 @@ public class HazardHiddenDangerRectifyServiceImpl extends ServiceImpl 0; } + + /** + * 发送超时通知 + * + * @param bizId 业务id + */ + @Override + public void sendTimeoutNotify(Long bizId) { + HazardHiddenDanger hiddenDanger = hazardHiddenDangerService.getById(bizId); + if (hiddenDanger == null) { + throw new ServiceException("未找到该数据"); + } + if (!HazardHiddenDanger.RECTIFY.equals(hiddenDanger.getStatus())) { + return; + } + // 发送消息 + String dangerCode = hiddenDanger.getDangerCode(); + Long rectifyUserId = hiddenDanger.getRectifyUserId(); + Long projectId = hiddenDanger.getProjectId(); + String titleRectify = "您的安全隐患工单[" + dangerCode + "]已超时,请及时处理!"; + try { + chatServerHandler.sendSystemMessageToUser(rectifyUserId, titleRectify, "2"); + SseMessageUtils.sendMessage(rectifyUserId, titleRectify); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", rectifyUserId, titleRectify, e); + } + // 发送给需要通知的对象 + Set userIds = hazardRuleNotifyObjectService.queryNotifyObjectIds(hiddenDanger.getDangerLevelId(), projectId); + SseMessageDto sseDto = new SseMessageDto(); + String title = "安全隐患工单[" + dangerCode + "]未进行整改,请及时关注!"; + for (Long userId : userIds) { + try { + chatServerHandler.sendSystemMessageToUser(userId, title, "2"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", userId, title, e); + } + } + sseDto.setUserIds(userIds.stream().toList()); + sseDto.setMessage(title); + sseDto.setRoute(""); + sseDto.setProjectId(projectId); + sseDto.setIsRecord(true); + SseMessageUtils.publishMessage(sseDto); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerServiceImpl.java index dadeaba8..4152b2c0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardHiddenDangerServiceImpl.java @@ -8,11 +8,17 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.sse.dto.SseMessageDto; +import org.dromara.common.sse.utils.SseMessageUtils; +import org.dromara.rabbitmq.domain.MqDelayTask; +import org.dromara.rabbitmq.enums.MqDelayTaskTypeEnum; +import org.dromara.rabbitmq.service.IMqDelayTaskService; import org.dromara.safety.domain.HazardHiddenDanger; import org.dromara.safety.domain.HazardHiddenDangerRectify; import org.dromara.safety.domain.HazardRule; @@ -24,7 +30,9 @@ import org.dromara.safety.domain.vo.HiddenDangerCountVo; import org.dromara.safety.mapper.HazardHiddenDangerMapper; import org.dromara.safety.mapper.HazardHiddenDangerRectifyMapper; import org.dromara.safety.service.IHazardHiddenDangerService; +import org.dromara.safety.service.IHazardRuleNotifyObjectService; import org.dromara.safety.service.IHazardRuleService; +import org.dromara.websocket.ChatServerHandler; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +40,8 @@ import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; /** * 隐患信息Service业务层处理 @@ -39,6 +49,7 @@ import java.util.Map; * @author Lion Li * @date 2025-12-03 */ +@Slf4j @RequiredArgsConstructor @Service public class HazardHiddenDangerServiceImpl extends ServiceImpl @@ -50,6 +61,12 @@ public class HazardHiddenDangerServiceImpl extends ServiceImpl { + // 发送给整改人员 + String titleRectify = "您有新的安全隐患工单[" + dangerCode + "]需要整改,请及时处理!"; + try { + chatServerHandler.sendSystemMessageToUser(rectifyUserId, titleRectify, "2"); + SseMessageUtils.sendMessage(rectifyUserId, titleRectify); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", rectifyUserId, titleRectify, e); + } + // 发送给需要通知的对象 + Set userIds = hazardRuleNotifyObjectService.queryNotifyObjectIds(hazardHiddenDanger.getDangerLevelId(), projectId); + SseMessageDto sseDto = new SseMessageDto(); + String title = "您有新的安全隐患工单[" + dangerCode + "],请及时查看!"; + for (Long userId : userIds) { + try { + chatServerHandler.sendSystemMessageToUser(userId, title, "2"); + } catch (Exception e) { + log.error("异步发送系统消息失败,用户ID: {}, 消息: {}", userId, title, e); + } + } + sseDto.setUserIds(userIds.stream().toList()); + sseDto.setMessage(title); + sseDto.setRoute(""); + sseDto.setProjectId(projectId); + sseDto.setIsRecord(true); + SseMessageUtils.publishMessage(sseDto); + // 发送整改期限数据到消息队列 + MqDelayTask task = new MqDelayTask(); + task.setBizType(MqDelayTaskTypeEnum.HIDDEN_DANGER.getType()); + task.setBizId(dto.getId()); + task.setExecuteTime(rectifyTime); + try { + mqDelayTaskService.addDelayTask(task); + } catch (Exception e) { + log.error("添加延迟任务失败,延迟任务: {}", task, e); + } + }); return true; } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleNotifyObjectServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleNotifyObjectServiceImpl.java index 779f7e17..f5baf6ef 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleNotifyObjectServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleNotifyObjectServiceImpl.java @@ -8,6 +8,7 @@ import org.dromara.safety.domain.vo.HazardRuleNotifyObjectVo; import org.dromara.safety.domain.vo.HazardRuleVo; import org.dromara.safety.mapper.HazardRuleNotifyObjectMapper; import org.dromara.safety.service.IHazardRuleNotifyObjectService; +import org.dromara.system.domain.SysUser; import org.dromara.system.domain.vo.SysDeptVo; import org.dromara.system.domain.vo.SysPostVo; import org.dromara.system.domain.vo.SysRoleVo; @@ -18,9 +19,7 @@ import org.dromara.system.service.ISysRoleService; import org.dromara.system.service.ISysUserService; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -135,6 +134,52 @@ public class HazardRuleNotifyObjectServiceImpl extends ServiceImpl queryNotifyObjectIds(Long ruleId, Long projectId) { + List objectList = this.lambdaQuery() + .eq(HazardRuleNotifyObject::getRuleId, ruleId) + .list(); + if (CollUtil.isEmpty(objectList)) { + return Collections.emptySet(); + } + Set userIds = new HashSet<>(); + Map> map = objectList.stream() + .collect(Collectors.groupingBy(HazardRuleNotifyObject::getNotifyType)); + for (Map.Entry> entry : map.entrySet()) { + String key = entry.getKey(); + List value = entry.getValue(); + List ids = value.stream() + .map(HazardRuleNotifyObject::getNotifyId) + .toList(); + switch (key) { + case "1" -> userIds.addAll(ids); + case "2" -> { + List userVos = userService.selectUserByRoleIdsAndProjectId(ids, projectId); + Set userSet = userVos.stream().map(SysUser::getUserId).collect(Collectors.toSet()); + userIds.addAll(userSet); + } + case "3" -> { + List userVos = userService.selectUserListByDeptList(ids); + Set userSet = userVos.stream().map(SysUserVo::getUserId).collect(Collectors.toSet()); + userIds.addAll(userSet); + } + case "4" -> { + List userVos = userService.selectUserListByPostList(ids); + Set userSet = userVos.stream().map(SysUserVo::getUserId).collect(Collectors.toSet()); + userIds.addAll(userSet); + } + } + } + return userIds; + } + /** * 补充数据 * diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleServiceImpl.java index 1fd75b8b..e6d118b0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HazardRuleServiceImpl.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.exception.ServiceException; @@ -11,6 +12,7 @@ import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.safety.domain.HazardHiddenDanger; import org.dromara.safety.domain.HazardRule; import org.dromara.safety.domain.HazardRuleNotifyObject; import org.dromara.safety.domain.bo.HazardRuleBo; @@ -18,8 +20,10 @@ import org.dromara.safety.domain.bo.HazardRuleNotifyObjectBo; import org.dromara.safety.domain.vo.HazardRuleNotifyObjectVo; import org.dromara.safety.domain.vo.HazardRuleVo; import org.dromara.safety.mapper.HazardRuleMapper; +import org.dromara.safety.service.IHazardHiddenDangerService; import org.dromara.safety.service.IHazardRuleNotifyObjectService; import org.dromara.safety.service.IHazardRuleService; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -39,6 +43,10 @@ public class HazardRuleServiceImpl extends ServiceImpl lqw = Wrappers.lambdaQuery(); lqw.orderByDesc(HazardRule::getId); lqw.eq(bo.getProjectId() != null, HazardRule::getProjectId, bo.getProjectId()); - lqw.eq(StringUtils.isNotBlank(bo.getHazardLevel()), HazardRule::getHazardLevel, bo.getHazardLevel()); + lqw.like(StringUtils.isNotBlank(bo.getHazardLevel()), HazardRule::getHazardLevel, bo.getHazardLevel()); lqw.eq(bo.getHazardWeight() != null, HazardRule::getHazardWeight, bo.getHazardWeight()); lqw.eq(bo.getResponseTime() != null, HazardRule::getResponseTime, bo.getResponseTime()); lqw.eq(StringUtils.isNotBlank(bo.getResponseUnit()), HazardRule::getResponseUnit, bo.getResponseUnit()); @@ -202,6 +210,11 @@ public class HazardRuleServiceImpl extends ServiceImpl ids, Boolean isValid) { if (isValid) { //TODO 做一些业务上的校验,判断是否需要校验 + if (hazardHiddenDangerService.lambdaQuery() + .in(HazardHiddenDanger::getDangerLevelId, ids) + .count() > 0) { + throw new ServiceException("请先删除该等级下的隐患信息", HttpStatus.ERROR); + } } return baseMapper.deleteByIds(ids) > 0; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java index 3a7726bb..e5d32aff 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java @@ -41,6 +41,11 @@ public class SysRole extends TenantEntity { */ private String roleKey; + /** + * 角色标识 + */ + private String roleIdentity; + /** * 角色排序 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java index f3f4ef0e..428b6fa9 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java @@ -47,6 +47,11 @@ public class SysRoleBo extends BaseEntity { @Size(min = 0, max = 100, message = "权限字符长度不能超过{max}个字符") private String roleKey; + /** + * 角色身份 + */ + private String roleIdentity; + /** * 显示顺序 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ProjectRolesItem.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ProjectRolesItem.java index 5d8be2a9..5cd3ded1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ProjectRolesItem.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ProjectRolesItem.java @@ -17,4 +17,5 @@ public class ProjectRolesItem { private String dataScope; private String status; private String isSpecial; + private String roleIdentity; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java index 580a9229..20152355 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java @@ -126,4 +126,9 @@ public class SysRoleVo implements Serializable { * 角色类型 1-web 2-app */ private String roleSource; + + /** + * 角色身份 + */ + private String roleIdentity; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java index c91f9c1f..b0e3e3ed 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java @@ -248,6 +248,14 @@ public interface ISysUserService { */ List selectUserListByDept(Long deptId); + /** + * 通过部门id列表查询当前部门所有用户 + * + * @param deptIds 部门id列表 + * @return 列表 + */ + List selectUserListByDeptList(List deptIds); + /** * 通过岗位id列表查询岗位所有用户 * diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index d540863a..1a3059b8 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -839,6 +839,23 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return baseMapper.selectVoList(lqw); } + /** + * 通过部门id列表查询当前部门所有用户 + * + * @param deptIds 部门id列表 + * @return 列表 + */ + @Override + public List selectUserListByDeptList(List deptIds) { + if (CollUtil.isEmpty(deptIds)) { + return List.of(); + } + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.in(SysUser::getDeptId, deptIds); + lqw.orderByAsc(SysUser::getUserId); + return baseMapper.selectVoList(lqw); + } + /** * 通过岗位id列表查询岗位所有用户 * diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/contractManagement/jixiehetongxinxi/service/impl/XzdContractMachineryServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/contractManagement/jixiehetongxinxi/service/impl/XzdContractMachineryServiceImpl.java index 108f6b64..e983e34f 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/contractManagement/jixiehetongxinxi/service/impl/XzdContractMachineryServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/contractManagement/jixiehetongxinxi/service/impl/XzdContractMachineryServiceImpl.java @@ -333,6 +333,16 @@ public class XzdContractMachineryServiceImpl extends ServiceImpl().eq(XzdBusinessChange::getContractChangeId, update.getId())); + if (bo.getSealInfo() != null && !bo.getSealInfo().isEmpty()){ + for (XzdBusinessChange sealInfo : bo.getSealInfo()) { + sealInfo.setContractChangeId(update.getId()); + sealInfo.setType("13"); + } + xzdBusinessChangeService.saveBatch(bo.getSealInfo()); + } /** * 扣款与奖励项 */ @@ -366,7 +376,6 @@ public class XzdContractMachineryServiceImpl extends ServiceImpl 0; } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/rabbitmq/MqDelayTaskMapper.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/rabbitmq/MqDelayTaskMapper.xml new file mode 100644 index 00000000..8a474e61 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/rabbitmq/MqDelayTaskMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml index 9e019a89..045c96d6 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -21,7 +21,8 @@ r.create_time, r.remark, r.is_special, - r.role_source + r.role_source, + r.role_identity from sys_role r left join sys_user_role sur on sur.role_id = r.role_id left join sys_user u on u.user_id = sur.user_id diff --git a/xinnengyuan/script/sql/xinnengyuan.sql b/xinnengyuan/script/sql/xinnengyuan.sql index 84807ca3..2c28c315 100644 --- a/xinnengyuan/script/sql/xinnengyuan.sql +++ b/xinnengyuan/script/sql/xinnengyuan.sql @@ -2107,15 +2107,15 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, values (1996413868087308295, '隐患整改情况导出', 1996413868087308290, '5', '#', '', 1, 0, 'F', '0', '0', 'safety:hiddenDangerRectify:export', '#', 103, 1, sysdate(), null, null, ''); - -CREATE TABLE `hazard_delay_task` +DROP TABLE IF EXISTS mq_delay_task; +CREATE TABLE `mq_delay_task` ( `id` BIGINT PRIMARY KEY COMMENT '主键', - `biz_type` VARCHAR(50) NOT NULL COMMENT '业务类型', + `biz_type` VARCHAR(64) NOT NULL COMMENT '业务类型', `biz_id` BIGINT NOT NULL COMMENT '业务ID', `execute_time` DATETIME NOT NULL COMMENT '执行的时间点', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '任务状态 0未执行 1执行中 2执行成功 3执行失败', `retry_count` INT NOT NULL DEFAULT 0 COMMENT '重试次数', `max_retry` INT NOT NULL DEFAULT 3 COMMENT '最大重试次数', `fail_reason` VARCHAR(1024) NULL COMMENT '失败原因' -); +) comment '延迟任务表';