| | |
| | | <!-- 日志存放路径 --> |
| | | <property name="log.path" value="./logs" /> |
| | | <!-- 日志输出格式 --> |
| | | <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> |
| | | <property name="log.pattern" value="%d{HH:mm:ss.SSS} %-5level %logger{20} - [%method,%line] - %msg%n" /> |
| | | <!-- 单个日志文件最大大小 --> |
| | | <property name="log.maxFileSize" value="100MB" /> |
| | | <!-- 日志文件总大小上限 --> |
| | |
| | | // 查询所有活跃车辆 |
| | | List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(new VehicleInfo()); |
| | | if (vehicles == null || vehicles.isEmpty()) { |
| | | log.debug("没有找到需要监控的车辆"); |
| | | log.info("没有找到需要监控的车辆"); |
| | | return; |
| | | } |
| | | |
| | |
| | | // 获取该车辆的配置(优先级:车辆 > 部门 > 全局) |
| | | AlertConfig config = getVehicleAlertConfig(vehicleId, deptId, globalConfig); |
| | | if (config == null) { |
| | | log.debug("车辆 {} 未找到有效配置,跳过监控", vehicleNo); |
| | | // log.info("车辆 {} 未找到有效配置,跳过监控", vehicleNo); |
| | | return false; |
| | | } |
| | | |
| | | // 1. 查询车辆在时间窗口内的总运行里程 |
| | | BigDecimal totalMileage = calculateVehicleMileage(vehicleId, startTime, endTime); |
| | | if (totalMileage == null || totalMileage.compareTo(BigDecimal.ZERO) == 0) { |
| | | log.debug("车辆 {} 在监控窗口内无运行里程", vehicleNo); |
| | | // log.info("车辆 {} 在监控窗口内无运行里程", vehicleNo); |
| | | return false; |
| | | } |
| | | |
| | |
| | | // 3. 计算非任务状态下的运行里程 |
| | | BigDecimal nonTaskMileage = totalMileage.subtract(taskMileage); |
| | | if (nonTaskMileage.compareTo(BigDecimal.ZERO) <= 0) { |
| | | log.debug("车辆 {} 在监控窗口内无非任务里程", vehicleNo); |
| | | // log.info("车辆 {} 在监控窗口内无非任务里程", vehicleNo); |
| | | return false; |
| | | } |
| | | |
| | | log.debug("车辆 {} 总里程: {}km, 任务里程: {}km, 非任务里程: {}km", |
| | | vehicleNo, totalMileage, taskMileage, nonTaskMileage); |
| | | // log.info("车辆 {} 总里程: {}km, 任务里程: {}km, 非任务里程: {}km", |
| | | // vehicleNo, totalMileage, taskMileage, nonTaskMileage); |
| | | |
| | | // 4. 检查非任务里程是否超过公里数阈值 |
| | | if (nonTaskMileage.compareTo(config.mileageThreshold) <= 0) { |
| | | log.debug("车辆 {} 非任务运行里程 {}km 未超过阈值 {}km", |
| | | vehicleNo, nonTaskMileage, config.mileageThreshold); |
| | | // log.info("车辆 {} 非任务运行里程 {}km 未超过阈值 {}km", |
| | | // vehicleNo, nonTaskMileage, config.mileageThreshold); |
| | | return false; |
| | | } |
| | | |
| | | // 5. 检查告警频率限制 |
| | | if (!checkAlertFrequency(vehicleId, config)) { |
| | | log.debug("车辆 {} 已达到告警频率限制", vehicleNo); |
| | | // log.info("车辆 {} 已达到告警频率限制", vehicleNo); |
| | | return false; |
| | | } |
| | | |
| | |
| | | vehicleId, vehicleNo, mileage, startTime, endTime, deptId, deptName); |
| | | |
| | | if (!created) { |
| | | // log.info("车辆 {} 今日已存在相同类型的告警,不再创建", vehicleNo); |
| | | return false; |
| | | } |
| | | |
| | | log.info("车辆 {} 产生异常告警:无任务运行 {}km,时间 {} 至 {}", |
| | | vehicleNo, mileage, |
| | | DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startTime), |
| | | DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endTime)); |
| | | // log.info("车辆 {} 产生异常告警:无任务运行 {}km,时间 {} 至 {}", |
| | | // vehicleNo, mileage, |
| | | // DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startTime), |
| | | // DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endTime)); |
| | | |
| | | // 发送通知 |
| | | sendAlertNotification(vehicle, mileage, deptId, config); |
| | |
| | | userService.selectUserByUserName(dept.getLeader()); |
| | | if (leaderUser != null) { |
| | | userIds.add(leaderUser.getUserId()); |
| | | log.info("使用部门 {} 负责人: {} (ID: {})", |
| | | dept.getDeptName(), dept.getLeader(), leaderUser.getUserId()); |
| | | // log.info("使用部门 {} 负责人: {} (ID: {})", |
| | | // dept.getDeptName(), dept.getLeader(), leaderUser.getUserId()); |
| | | } else { |
| | | log.warn("部门 {} 负责人 {} 未找到对应用户", |
| | | dept.getDeptName(), dept.getLeader()); |
| | |
| | | // 通知用户列表 |
| | | config.notifyUsers = configService.selectConfigByKey("vehicle.alert.notify.users"); |
| | | |
| | | log.debug("告警配置: 阈值={}km, 每日限制={}次, 间隔={}分钟, 时间窗口={}分钟", |
| | | config.mileageThreshold, config.dailyLimit, config.alertInterval, config.timeWindow); |
| | | // log.debug("告警配置: 阈值={}km, 每日限制={}次, 间隔={}分钟, 时间窗口={}分钟", |
| | | // config.mileageThreshold, config.dailyLimit, config.alertInterval, config.timeWindow); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("加载告警配置失败,使用默认值", e); |
| | |
| | | // 批量计算 |
| | | int successCount = segmentMileageService.batchCalculateSegmentMileage(startTime, endTime); |
| | | |
| | | // logger.info("GPS分段里程计算完成 - 成功处理 {} 辆车", successCount); |
| | | logger.info("GPS分段里程计算完成 - 成功处理 {} 辆车", successCount); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("GPS分段里程计算任务执行失败", e); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | log.info("[转运单同步] 开始同步,范围: 最近{}天", daysAgo); |
| | | // log.info("[转运单同步] 开始同步,范围: 最近{}天", daysAgo); |
| | | int totalSuccessCount = 0; |
| | | int totalDays = daysAgo + 1; |
| | | |
| | |
| | | String dayEndStr = DateUtils.parseDateToStr("yyyy-MM-dd", dayStart) + " 23:59:59"; |
| | | |
| | | int dayIndex = totalDays - i; |
| | | log.info("[转运单同步] 处理天 {}/{}: {}", dayIndex, totalDays, dayStartStr); |
| | | // log.info("[转运单同步] 处理天 {}/{}: {}", dayIndex, totalDays, dayStartStr); |
| | | int daySuccessCount = syncSingleDayOrders(dayStartStr, dayEndStr); |
| | | totalSuccessCount += daySuccessCount; |
| | | log.info("[转运单同步] {} 完成,新增同步: {}条,累计: {}条", dayStartStr, daySuccessCount, totalSuccessCount); |
| | | // log.info("[转运单同步] {} 完成,新增同步: {}条,累计: {}条", dayStartStr, daySuccessCount, totalSuccessCount); |
| | | } |
| | | |
| | | log.info("[转运单同步] 全部完成,共新增同步 {}条", totalSuccessCount); |
| | | // log.info("[转运单同步] 全部完成,共新增同步 {}条", totalSuccessCount); |
| | | return totalSuccessCount; |
| | | |
| | | } catch (Exception e) { |
| | |
| | | int totalCount = transferOrders.size(); |
| | | int processedCount = 0; |
| | | |
| | | log.info("[转运单同步] {} 第{}页,获取{}.条数据,lastId={}", startDateStr, pageNum, totalCount, lastId); |
| | | // log.info("[转运单同步] {} 第{}页,获取{}.条数据,lastId={}", startDateStr, pageNum, totalCount, lastId); |
| | | |
| | | for (Map<String, Object> order : transferOrders) { |
| | | processedCount++; |
| | |
| | | } |
| | | } |
| | | |
| | | log.info("[转运单同步] {} 分页完成,共处理: {}条,新增同步: {}条", startDateStr, totalProcessed, successCount); |
| | | // log.info("[转运单同步] {} 分页完成,共处理: {}条,新增同步: {}条", startDateStr, totalProcessed, successCount); |
| | | } catch (Exception e) { |
| | | log.error("同步单天转运单数据异常: date={}", startDateStr, e); |
| | | } |
| | |
| | | // 1. 获取执行人列表 |
| | | List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID); |
| | | if (assignees.isEmpty()) { |
| | | log.info("旧系统同步转运单无执行人,taskId={}", taskId); |
| | | // log.info("旧系统同步转运单无执行人,taskId={}", taskId); |
| | | return; |
| | | } |
| | | |
| | |
| | | } |
| | | // 该用户已有通知记录,跳过 |
| | | if (existingUserIds.contains(assignee.getUserId())) { |
| | | log.info("用户已有通知记录,跳过创建,taskId={}, userId={}", taskId, assignee.getUserId()); |
| | | // log.info("用户已有通知记录,跳过创建,taskId={}, userId={}", taskId, assignee.getUserId()); |
| | | continue; |
| | | } |
| | | |
| | |
| | | NotifyTask created = notifyTaskService.createNotifyTask(notifyTask); |
| | | if (created != null) { |
| | | notifyTasks.add(created); |
| | | log.info("创建通知任务成功,id={}, userId={}", created.getId(), user.getUserId()); |
| | | // log.info("创建通知任务成功,id={}, userId={}", created.getId(), user.getUserId()); |
| | | } |
| | | } |
| | | |
| | | // 6. 分发通知任务 |
| | | if (!notifyTasks.isEmpty()) { |
| | | int successCount = notifyDispatchService.dispatchNotifies(notifyTasks); |
| | | log.info("旧系统同步转运单通知分发完成,taskId={}, 分发数量={}, 成功数量={}", |
| | | taskId, notifyTasks.size(), successCount); |
| | | } else { |
| | | log.info("旧系统同步转运单无需新增通知,taskId={}", taskId); |
| | | // log.info("旧系统同步转运单通知分发完成,taskId={}, 分发数量={}, 成功数量={}", |
| | | // taskId, notifyTasks.size(), successCount); |
| | | } |
| | | // else { |
| | | // log.info("旧系统同步转运单无需新增通知,taskId={}", taskId); |
| | | // } |
| | | |
| | | // 5. 同时保留原有的微信通知服务(兼容) |
| | | // List<Long> userIds = new ArrayList<>(); |
| | |
| | | } |
| | | if (createVO.getPrice() != null) { |
| | | existingInfo.setTransferPrice(createVO.getPrice()); |
| | | log.info("任务ID:{},serviceOrdId:{} 更新价格:{}",existingInfo.getTaskId(),existingInfo.getLegacyServiceOrdId(), createVO.getPrice()); |
| | | // log.info("任务ID:{},serviceOrdId:{} 更新价格:{}",existingInfo.getTaskId(),existingInfo.getLegacyServiceOrdId(), createVO.getPrice()); |
| | | } |
| | | |
| | | // 更新单据类型ID |
| | |
| | | // logger.info("查询到 {} 辆活跃车辆,查询耗时: {}ms", vehicleIds != null ? vehicleIds.size() : 0, queryTime); |
| | | |
| | | if (vehicleIds == null || vehicleIds.isEmpty()) { |
| | | // logger.info("没有找到活跃车辆"); |
| | | logger.info("没有找到活跃车辆"); |
| | | return 0; |
| | | } |
| | | |
| | |
| | | List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, startTimeStr, endTimeStr); |
| | | |
| | | if (gpsList == null || gpsList.isEmpty()) { |
| | | // logger.debug("车辆ID: {} 在时间范围 {} 到 {} 内无GPS数据", vehicleId, startTime, endTime); |
| | | // logger.info("车辆ID: {} 在时间范围 {} 到 {} 内无GPS数据", vehicleId, startTime, endTime); |
| | | return 0; |
| | | } |
| | | |
| | |
| | | for (Date statDate : affectedDates) { |
| | | try { |
| | | mileageStatsService.aggregateFromSegmentMileage(vehicleId, statDate); |
| | | // logger.info("车辆 {} 日期 {} 的统计数据已自动汇总生成", vehicleId, statDate); |
| | | logger.info("车辆 {} 日期 {} 的统计数据已自动汇总生成", vehicleId, statDate); |
| | | } catch (Exception e) { |
| | | logger.error("车辆 {} 日期 {} 自动汇总统计失败", vehicleId, statDate, e); |
| | | } |
| | |
| | | List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, dayStartStr, dayEndStr); |
| | | |
| | | if (gpsList == null || gpsList.isEmpty()) { |
| | | logger.info("---> 车辆ID:{} 在日期:{} 无GPS数据", vehicleId, statDate); |
| | | // logger.info("---> 车辆ID:{} 在日期:{} 无GPS数据", vehicleId, statDate); |
| | | return null; |
| | | } |
| | | // logger.info("---> 车辆ID:{} GPS数据条数:{}", vehicleId, gpsList.size()); |
| | |
| | | // logger.info("车辆ID: {} 在日期: {} 有 {} 个任务", vehicleId, statDate, taskCount); |
| | | List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd).stream().filter(e -> e.getSegmentDistance() != null && e.getSegmentDistance().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()); |
| | | // logger.info("车辆ID: {} 在日期: {} 有 {} 个分段里程数据", vehicleId, statDate, mileages.size()); |
| | | Integer totalGpsPoints = mileages != null ? mileages.stream() |
| | | Integer totalGpsPoints = mileages.stream() |
| | | .filter(segment -> segment.getGpsPointCount() != null) |
| | | .mapToInt(VehicleGpsSegmentMileage::getGpsPointCount) |
| | | .sum() : 0; |
| | | .sum(); |
| | | BigDecimal taskDistance = getTaskDistance(taskIntervals, mileages); |
| | | BigDecimal totalDistance = calculateTotalMileage(segments); |
| | | BigDecimal nonTaskDistance = totalDistance.subtract(taskDistance); |
| | | |
| | | // 防止除零错误 |
| | | BigDecimal taskRatio = BigDecimal.ZERO; |
| | | if (totalDistance != null && totalDistance.compareTo(BigDecimal.ZERO) > 0) { |
| | | if (totalDistance.compareTo(BigDecimal.ZERO) > 0) { |
| | | taskRatio = taskDistance.divide(totalDistance, 4, RoundingMode.HALF_UP); |
| | | } |
| | | // 3. 汇总里程数据 |
| | |
| | | } |
| | | |
| | | // logger.info("车辆ID: {} 日期: {} 从分段汇总完成 - 总里程: {}km, 任务里程: {}km, 非任务里程: {}km, 分段数: {}", |
| | | // vehicleId, statDate, totalMileage, taskMileage, nonTaskMileage, segments.size()); |
| | | // vehicleId, statDate, stats.getTotalMileage(), stats.getTaskMileage(),stats.getNonTaskMileage(), segments.size()); |
| | | |
| | | return stats; |
| | | |
| | |
| | | segment_distance, gps_point_count, gps_ids, task_id, task_code, calculate_method |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = #{vehicleId} |
| | | AND segment_start_time between #{startDate} and #{endDate} |
| | | AND segment_start_time between #{startTime} and #{endTime} |
| | | AND segment_end_time >= #{startTime} |
| | | AND segment_distance > 0 |
| | | ORDER BY segment_start_time |