From be3af2bd647f672f4f284cfaa27daff27b7f7195 Mon Sep 17 00:00:00 2001 From: xyc <3422692813@qq.com> Date: Wed, 7 May 2025 16:07:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/config/entity/ReminderMessage.java | 14 ++++ .../service/RedisDelayedQueueService.java | 43 +++++++++++ .../config/service/ReminderHandler.java | 22 ++++++ .../config/task/AppointmentReminderTask.java | 45 ++++++++++++ .../module/constant/InspectionConstants.java | 5 ++ .../inspection/entity/InspectionInfo.java | 2 + .../inspection/entity/InspectionWorkNode.java | 5 ++ .../impl/AppInspectionPartnerServiceImpl.java | 1 + .../InspectionAppointmentServiceImpl.java | 40 +++++++++- .../impl/InspectionInfoServiceImpl.java | 30 +++++++- .../InspectionMeetCarOrderServiceImpl.java | 17 ++++- .../impl/InspectionWorkNodeServiceImpl.java | 73 ++++++++++++++++--- .../inspection/vo/InspectionInfoVo.java | 1 + .../inspection/AppInspectionPartnerMapper.xml | 9 ++- 14 files changed, 288 insertions(+), 19 deletions(-) create mode 100644 dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/entity/ReminderMessage.java create mode 100644 dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/RedisDelayedQueueService.java create mode 100644 dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/ReminderHandler.java create mode 100644 dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/task/AppointmentReminderTask.java diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/entity/ReminderMessage.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/entity/ReminderMessage.java new file mode 100644 index 00000000..92a18af2 --- /dev/null +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/entity/ReminderMessage.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.config.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ReminderMessage { + private Long taskId; // 任务id + private Long userId; // 用户id + private String message; // 消息 +} diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/RedisDelayedQueueService.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/RedisDelayedQueueService.java new file mode 100644 index 00000000..753c67b0 --- /dev/null +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/RedisDelayedQueueService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.config.service; + +import cn.iocoder.yudao.module.config.entity.ReminderMessage; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Set; + +/** + * Redis 延迟队列服务 + */ +@Service +public class RedisDelayedQueueService { + + private static final String REDIS_KEY = "appointment:reminder:queue"; + + @Autowired + private StringRedisTemplate redisTemplate; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public void addToQueue(ReminderMessage message, long triggerTimeMillis) { + try { + String json = objectMapper.writeValueAsString(message); + redisTemplate.opsForZSet().add(REDIS_KEY, json, triggerTimeMillis); + } catch (JsonProcessingException e) { + throw new RuntimeException("Failed to add reminder to Redis", e); + } + } + + public Set fetchDueMessages(long currentTimeMillis) { + return redisTemplate.opsForZSet() + .rangeByScore(REDIS_KEY, 0, currentTimeMillis); + } + + public void removeMessage(String json) { + redisTemplate.opsForZSet().remove(REDIS_KEY, json); + } +} + diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/ReminderHandler.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/ReminderHandler.java new file mode 100644 index 00000000..9217a1b9 --- /dev/null +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/service/ReminderHandler.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.config.service; + +import cn.iocoder.yudao.module.appBase.controller.admin.InspectionSocket; +import cn.iocoder.yudao.module.config.entity.ReminderMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class ReminderHandler { + + @Autowired + private InspectionSocket inspectionSocket; + + public void handleReminder(ReminderMessage message) { + + // 调用websocket发送消息 + inspectionSocket.sendMessage(message.getMessage(), String.valueOf(message.getUserId())); + } +} + diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/task/AppointmentReminderTask.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/task/AppointmentReminderTask.java new file mode 100644 index 00000000..b4459736 --- /dev/null +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/config/task/AppointmentReminderTask.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.config.task; + +import cn.iocoder.yudao.module.config.entity.ReminderMessage; +import cn.iocoder.yudao.module.config.service.ReminderHandler; +import cn.iocoder.yudao.module.config.service.RedisDelayedQueueService; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Set; + +@Slf4j +@Component +public class AppointmentReminderTask { + + @Autowired + private RedisDelayedQueueService queueService; + + @Autowired + private ReminderHandler reminderHandler; + + @Scheduled(fixedRate = 60_000) + public void checkReminderQueue() { + long now = System.currentTimeMillis(); + Set dueMessages = queueService.fetchDueMessages(now); + + for (String json : dueMessages) { + try { + ReminderMessage message = new ObjectMapper().readValue(json, ReminderMessage.class); + + // 执行提醒 + reminderHandler.handleReminder(message); + log.info("处理提醒成功:{}", message); + + // 移除已处理任务 + queueService.removeMessage(json); + } catch (Exception e) { + log.error("解析或处理提醒失败", e); + } + } + } +} + diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/constant/InspectionConstants.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/constant/InspectionConstants.java index ba449e4e..145f21f0 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/constant/InspectionConstants.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/constant/InspectionConstants.java @@ -62,4 +62,9 @@ public class InspectionConstants { * 接车完成类型 - 接车订单表 */ public static final Integer INSPECTION_MEET_CAR_ORDER_IS_MEET_CAR_COMPLETE_TYPE_MEET_CAR_ORDER = 1; + + /** + * 检测websocket消息内容-客户即将到店 + */ + public static final String INSPECTION_WEBSOCKET_MESSAGE_CONTENT_CUSTOMER_ARRIVE = "客户即将到店"; } diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionInfo.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionInfo.java index 60c284bc..e120966e 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionInfo.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionInfo.java @@ -65,6 +65,8 @@ public class InspectionInfo extends TenantBaseDO //是否重审 private String isRetrial; private String remark; + /** 检测次数 */ + private Integer infoCount; /** 0进行中1已结束 */ @Excel(name = "0进行中1已结束") diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionWorkNode.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionWorkNode.java index a89d2802..d4ac0fe1 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionWorkNode.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/entity/InspectionWorkNode.java @@ -85,6 +85,11 @@ public class InspectionWorkNode extends TenantBaseDO { */ private String status; + /** + * 检测次数 + */ + private Integer nodeCount; + /** * 1-退办理 2-选择重审 3-项目完成 diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/AppInspectionPartnerServiceImpl.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/AppInspectionPartnerServiceImpl.java index f2a69ffc..7c0ada58 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/AppInspectionPartnerServiceImpl.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/AppInspectionPartnerServiceImpl.java @@ -1576,6 +1576,7 @@ public class AppInspectionPartnerServiceImpl extends ServiceImpl userListByCodes = roleService.getUserListByCodes(codes); for (UserDTO userListByCode : userListByCodes) { inspectionSocket.sendMessage("客户预约", userListByCode.getId().toString()); + ReminderMessage message = new ReminderMessage(appointment.getId(), userListByCode.getId(), INSPECTION_WEBSOCKET_MESSAGE_CONTENT_CUSTOMER_ARRIVE); + + long triggerTimeMillis = getArrivalTime(appointment.getAppointmentDay(), appointment.getAppointmentPeriod()).minusMinutes(10).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + redisDelayedQueueService.addToQueue(message, triggerTimeMillis); } + return appointment.getId(); } + /** + * 将 appointmentDay 和 appointmentPeriod 转为 LocalDateTime + * @return LocalDateTime 类型的到店时间 + */ + public static LocalDateTime getArrivalTime(String appointmentDay, String appointmentPeriod) { + LocalDate date = LocalDate.parse(appointmentDay); // 例如 2025-05-08 + LocalTime time; + + if ("0".equals(appointmentPeriod)) { + time = LocalTime.of(9, 0); // 上午 9:00 + } else if ("1".equals(appointmentPeriod)) { + time = LocalTime.of(14, 0); // 下午 2:00 + } else { + throw new IllegalArgumentException("appointmentPeriod 非法: " + appointmentPeriod); + } + + return LocalDateTime.of(date, time); + } + + @Override public Long editAppointment(InspectionAppointment appointment) { diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionInfoServiceImpl.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionInfoServiceImpl.java index 33db0250..a982a4cf 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionInfoServiceImpl.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionInfoServiceImpl.java @@ -209,7 +209,7 @@ public class InspectionInfoServiceImpl extends ServiceImpllambdaUpdate() .eq(OrderInfo::getId, orderInfo.getId()) .set(OrderInfo::getValidationTime, new Date())); + } else { + orderInfo.setPartnerId(partners.getPartnerId()); + orderInfo.setGoodsId(Long.parseLong(goods.getId().toString())); + orderInfo.setGoodsTitle(goods.getTitle()); + orderInfo.setGoodsType("jc"); + orderInfo.setGoodNum(1); + orderInfo.setSkuId(Long.parseLong(sku.getId().toString())); + orderInfo.setSkuName(sku.getSkuName()); + orderInfo.setGoodsPrice(goods.getPrice()); + orderInfo.setStartTime(new Date()); + orderInfo.setOrderTime(new Date()); + orderInfo.setOrderType("jc"); + orderInfo.setUserId(user.getId()); + orderInfo.setRealName(user.getNickname()); + orderInfo.setIsOnline("0"); + orderInfo.setPhonenumber(user.getMobile()); + orderInfo.setPartnerName(partner.getPartnerName()); + orderInfo.setOrderNo("线下订单-" + System.currentTimeMillis()); + //赊账的情况 + orderInfo.setOrderStatus("0"); + orderInfoService.save(orderInfo); + + //修改预约信息表的orderId + InspectionAppointment appointment = new InspectionAppointment(); + appointment.setOrderId(orderInfo.getId()); + inspectionAppointmentService.update(Wrappers.lambdaUpdate() + .eq(InspectionAppointment::getId, inspectionInfo.getAppointmentId()) + .set(InspectionAppointment::getOrderId, orderInfo.getId())); } inspectionInfo.setInspectionOrderId(orderInfo.getId()); inspectionInfo.setPartnerId(partners.getPartnerId()); diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionMeetCarOrderServiceImpl.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionMeetCarOrderServiceImpl.java index 9e4d6f02..f1b79494 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionMeetCarOrderServiceImpl.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionMeetCarOrderServiceImpl.java @@ -6,6 +6,8 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.appBase.controller.admin.InspectionSocket; +import cn.iocoder.yudao.module.config.entity.ReminderMessage; +import cn.iocoder.yudao.module.config.service.RedisDelayedQueueService; import cn.iocoder.yudao.module.inspection.entity.*; import cn.iocoder.yudao.module.inspection.mapper.AppInspectionGoodsMapper; import cn.iocoder.yudao.module.inspection.mapper.InspectionMeetCarOrderMapper; @@ -18,8 +20,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.time.ZoneId; import java.util.Date; +import static cn.iocoder.yudao.module.constant.InspectionConstants.INSPECTION_WEBSOCKET_MESSAGE_CONTENT_CUSTOMER_ARRIVE; +import static cn.iocoder.yudao.module.inspection.service.impl.InspectionAppointmentServiceImpl.getArrivalTime; + /** * @Description: 接车订单 * @Author: 86187 @@ -42,6 +48,8 @@ public class InspectionMeetCarOrderServiceImpl extends ServiceImpllambdaUpdate() .eq(InspectionMeetCarOrder::getId, order.getId()) .set(InspectionMeetCarOrder::getAppointmentDay, appointment.getAppointmentDay())); + + // 设置消息提醒 + ReminderMessage message = new ReminderMessage(appointment.getId(), order.getMeetManId(), INSPECTION_WEBSOCKET_MESSAGE_CONTENT_CUSTOMER_ARRIVE); + + long triggerTimeMillis = getArrivalTime(appointment.getAppointmentDay(), appointment.getAppointmentPeriod()).minusMinutes(10).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + redisDelayedQueueService.addToQueue(message, triggerTimeMillis); } } - inspectionSocket.sendMessage("接工单", order.getMeetManId().toString()); } if (StrUtil.isNotEmpty(order.getContent()) || StrUtil.isNotEmpty(order.getImages())) { diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionWorkNodeServiceImpl.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionWorkNodeServiceImpl.java index 56504e2a..441f664f 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionWorkNodeServiceImpl.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/service/impl/InspectionWorkNodeServiceImpl.java @@ -196,6 +196,11 @@ public class InspectionWorkNodeServiceImpl extends ServiceImpl() .eq(DlInspectionProject::getId, workNode.getProjectId())); + // 判断检测项目是否包含制证 + if (ObjectUtil.isNotEmpty(project)) { + if (project.getProjectName().contains("制证")) { + flag = false; + } + } List stepInfos = inspectionStepService.list(new LambdaQueryWrapper() .and(i -> i.eq(InspectionStepInfo::getInspectionInfoId, workNode.getInspectionInfoId()) .eq(InspectionStepInfo::getWorkNodeId, workNode.getId()) @@ -361,6 +372,12 @@ public class InspectionWorkNodeServiceImpl extends ServiceImpl workNodeIds = inspectionWorkNode.getWorkNodes().stream().map(InspectionWorkNode::getId).collect(Collectors.toList()); - // 将所有项目重新走一遍 + // 将复检的项目重走一遍 this.update(new UpdateWrapper() - .set("status", "0") + .set("status", "3") .set("type", null) - .eq("inspection_info_id", inspectionWorkNode.getInspectionInfoId())); + .in("id", workNodeIds)); //跟新工单表 inspectionInfoService.updateById(info); @@ -590,20 +607,52 @@ public class InspectionWorkNodeServiceImpl extends ServiceImpl inspectionWorkNodes = baseMapper.selectBatchIds(workNodeIds); + List projectIds = inspectionWorkNodes.stream().map(InspectionWorkNode::getProjectId).collect(Collectors.toList()); + List projectList = inspectionProjectService.list(Wrappers.lambdaQuery() + .in(DlInspectionProject::getId, projectIds)); + // 将项目名称以逗号隔开 + String projectNames = projectList.stream().map(DlInspectionProject::getProjectName).collect(Collectors.joining("、")); + + +// /*将当前步骤修改完已完成*/ +// if (ObjectUtil.isNotNull(workNodes.getId())) { +// workNodes.setStatus("2"); +// baseMapper.updateById(workNodes); +// } + // 添加步骤信息表 InspectionStepInfo stepInfo = new InspectionStepInfo(); stepInfo.setInspectionInfoId(Integer.parseInt(inspectionWorkNode.getInspectionInfoId().toString())); - stepInfo.setWorkNodeId(inspectionWorkNode.getId()); - stepInfo.setTitle("重检"); + stepInfo.setTitle("复检"); + stepInfo.setCreateTime(DateUtil.date()); + stepInfo.setCreator(Integer.parseInt(loginUser.getId().toString())); if (ObjectUtil.isNotEmpty(inspectionWorkNode.getRemark())) { stepInfo.setContent(inspectionWorkNode.getRemark()); + } else { + stepInfo.setContent("复检了" + projectNames + "项目"); } if (ObjectUtil.isNotEmpty(inspectionWorkNode.getDealImages())) { stepInfo.setImages(inspectionWorkNode.getDealImages()); } - stepInfo.setCreateTime(DateUtil.date()); - stepInfo.setCreator(Integer.parseInt(loginUser.getId().toString())); inspectionStepService.save(stepInfo); + + // 添加步骤信息表 +// InspectionStepInfo stepInfo = new InspectionStepInfo(); +// stepInfo.setInspectionInfoId(Integer.parseInt(inspectionWorkNode.getInspectionInfoId().toString())); +// stepInfo.setWorkNodeId(inspectionWorkNode.getId()); +// stepInfo.setTitle("复检"); +// if (ObjectUtil.isNotEmpty(inspectionWorkNode.getRemark())) { +// stepInfo.setContent(inspectionWorkNode.getRemark()); +// } +// if (ObjectUtil.isNotEmpty(inspectionWorkNode.getDealImages())) { +// stepInfo.setImages(inspectionWorkNode.getDealImages()); +// } +// stepInfo.setCreateTime(DateUtil.date()); +// stepInfo.setCreator(Integer.parseInt(loginUser.getId().toString())); +// inspectionStepService.save(stepInfo); } public void sendSocketMessage(List userIds) { diff --git a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/vo/InspectionInfoVo.java b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/vo/InspectionInfoVo.java index 4a026e6e..2bd21d2c 100644 --- a/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/vo/InspectionInfoVo.java +++ b/dl-module-inspection/src/main/java/cn/iocoder/yudao/module/inspection/vo/InspectionInfoVo.java @@ -34,6 +34,7 @@ public class InspectionInfoVo { private String remark; private String buyUserName; private String buyUserPhone; + private Integer infoCount; @TableField(exist = false) private String buyName; diff --git a/dl-module-inspection/src/main/resources/mapper/inspection/AppInspectionPartnerMapper.xml b/dl-module-inspection/src/main/resources/mapper/inspection/AppInspectionPartnerMapper.xml index 5af1271b..9d33cf9c 100644 --- a/dl-module-inspection/src/main/resources/mapper/inspection/AppInspectionPartnerMapper.xml +++ b/dl-module-inspection/src/main/resources/mapper/inspection/AppInspectionPartnerMapper.xml @@ -475,10 +475,15 @@ FROM SELECT count(1) allNum, IFNULL(SUM(ii.status='0'),0) jxzNum, - IFNULL(SUM(ii.status='1'),0) ywcNum + IFNULL(SUM(ii.status='1'),0) ywcNum, + IFNULL(SUM(oi.sku_name LIKE '%年审%'),0) nsNum, + IFNULL(SUM(oi.sku_name LIKE '%上户%'),0) shNum, + IFNULL(SUM(oi.sku_name LIKE '%非定检%'),0) fdjNum, + IFNULL(SUM(oi.sku_name LIKE '%双燃料%'),0) srlNum FROM inspection_info ii - WHERE ii.partner_id =#{partnerId} and ii.deleted = 0 + LEFT JOIN order_info oi on oi.id = ii.inspection_order_id + WHERE ii.partner_id =#{partnerId} and ii.deleted = 0 and oi.deleted = 0 and ii.create_time BETWEEN #{startTime} and #{endTime}