留样记录修改、TCP探查设备是否在线修改
This commit is contained in:
parent
65ea4760b7
commit
1cb208570c
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 xuexiangjys(xuexiangjys@163.com)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.bonus.canteen.core.healthmachine.config;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping工具类,用于检测服务器连通性(Spring Boot后端版本,修复中文编码及解析问题)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class PingUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PingUtil.class);
|
||||||
|
|
||||||
|
// 线程池配置(可根据实际需求调整)
|
||||||
|
private static final ThreadPoolTaskExecutor executor;
|
||||||
|
|
||||||
|
static {
|
||||||
|
executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(5);
|
||||||
|
executor.setMaxPoolSize(10);
|
||||||
|
executor.setQueueCapacity(25);
|
||||||
|
executor.setThreadNamePrefix("ping-task-");
|
||||||
|
executor.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping结果回调接口
|
||||||
|
*/
|
||||||
|
public interface PingCallback {
|
||||||
|
void onSuccess(float avgDelay);
|
||||||
|
void onFailure(String errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行Ping操作(异步)
|
||||||
|
* @param host 主机地址(域名或IP)
|
||||||
|
* @param count Ping次数
|
||||||
|
* @param timeout 超时时间(秒)
|
||||||
|
* @param callback 结果回调
|
||||||
|
*/
|
||||||
|
public static void ping(String host, int count, int timeout, PingCallback callback) {
|
||||||
|
if (host == null || host.trim().isEmpty()) {
|
||||||
|
callback.onFailure("主机地址不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.submit(() -> {
|
||||||
|
Process process = null;
|
||||||
|
try {
|
||||||
|
// 1. 根据操作系统构建命令
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
String[] command = buildPingCommand(os, host, count, timeout);
|
||||||
|
if (command == null) {
|
||||||
|
callback.onFailure("不支持的操作系统: " + os);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 执行命令并处理输出(关键:解决中文编码问题)
|
||||||
|
process = Runtime.getRuntime().exec(command);
|
||||||
|
Charset charset = os.contains("win") ? Charset.forName("GBK") : Charset.defaultCharset();
|
||||||
|
|
||||||
|
try (InputStream inputStream = process.getInputStream();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))) {
|
||||||
|
|
||||||
|
String line;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
int totalDelay = 0;
|
||||||
|
int successCount = 0;
|
||||||
|
|
||||||
|
// 3. 解析响应内容(修复延迟解析逻辑)
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
result.append(line).append("\n");
|
||||||
|
String delayStr = parseDelay(line, os);
|
||||||
|
if (delayStr != null) {
|
||||||
|
try {
|
||||||
|
float delay = Float.parseFloat(delayStr);
|
||||||
|
totalDelay += delay;
|
||||||
|
successCount++;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("解析延迟失败 [{}]: {}", line, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 优化判定逻辑(以退出码为主,兼容解析失败场景)
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode == 0) {
|
||||||
|
// 退出码为0表示网络可达,即使延迟解析失败也判定为成功
|
||||||
|
float avgDelay = successCount > 0 ? (float) totalDelay / successCount : 0f;
|
||||||
|
callback.onSuccess(avgDelay);
|
||||||
|
} else {
|
||||||
|
String error = "Ping失败(退出码=" + exitCode + "),响应: " + result;
|
||||||
|
callback.onFailure(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.onFailure("执行Ping命令失败: " + e.getMessage());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
callback.onFailure("Ping被中断: " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行Ping操作(同步)
|
||||||
|
* @param host 主机地址
|
||||||
|
* @param count Ping次数
|
||||||
|
* @param timeout 超时时间(秒)
|
||||||
|
* @return 平均延迟(ms)
|
||||||
|
*/
|
||||||
|
public CompletableFuture<Float> pingSync(String host, int count, int timeout) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
Process process = null;
|
||||||
|
try {
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
String[] command = buildPingCommand(os, host, count, timeout);
|
||||||
|
if (command == null) {
|
||||||
|
throw new RuntimeException("不支持的操作系统: " + os);
|
||||||
|
}
|
||||||
|
|
||||||
|
process = Runtime.getRuntime().exec(command);
|
||||||
|
Charset charset = os.contains("win") ? Charset.forName("GBK") : Charset.defaultCharset();
|
||||||
|
|
||||||
|
try (InputStream inputStream = process.getInputStream();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))) {
|
||||||
|
|
||||||
|
String line;
|
||||||
|
int totalDelay = 0;
|
||||||
|
int successCount = 0;
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String delayStr = parseDelay(line, os);
|
||||||
|
if (delayStr != null) {
|
||||||
|
totalDelay += Float.parseFloat(delayStr);
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException("Ping失败(退出码=" + exitCode + ")");
|
||||||
|
}
|
||||||
|
return successCount > 0 ? (float) totalDelay / successCount : 0f;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Ping操作失败: " + e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建跨平台Ping命令
|
||||||
|
*/
|
||||||
|
private static String[] buildPingCommand(String os, String host, int count, int timeout) {
|
||||||
|
if (os.contains("win")) {
|
||||||
|
// Windows: -n 次数 -w 毫秒(超时时间)
|
||||||
|
return new String[]{"ping", "-n", String.valueOf(count), "-w", String.valueOf(timeout * 1000), host};
|
||||||
|
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
|
||||||
|
// Linux/Unix/Mac: -c 次数 -W 秒(超时时间)
|
||||||
|
return new String[]{"ping", "-c", String.valueOf(count), "-W", String.valueOf(timeout), host};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析延迟(兼容Windows/Linux,支持特殊格式如"时间=<1ms")
|
||||||
|
*/
|
||||||
|
private static String parseDelay(String line, String os) {
|
||||||
|
// Windows格式处理(时间=xxxms 或 时间=<1ms)
|
||||||
|
if (os.contains("win") && line.contains("时间=")) {
|
||||||
|
int timeIndex = line.indexOf("时间=") + 3;
|
||||||
|
String delayPart = line.substring(timeIndex).replaceAll("[^0-9.]", "");
|
||||||
|
return delayPart.isEmpty() ? null : delayPart;
|
||||||
|
}
|
||||||
|
// Linux格式处理(time=xxx ms)
|
||||||
|
else if ((os.contains("nix") || os.contains("nux") || os.contains("mac")) && line.contains("time=")) {
|
||||||
|
int timeIndex = line.indexOf("time=") + 5;
|
||||||
|
int msIndex = line.indexOf("ms", timeIndex);
|
||||||
|
if (msIndex != -1) {
|
||||||
|
String delayPart = line.substring(timeIndex, msIndex).trim().replaceAll("[^0-9.]", "");
|
||||||
|
return delayPart.isEmpty() ? null : delayPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简化调用:默认Ping 3次,超时3秒(异步)
|
||||||
|
*/
|
||||||
|
public void ping(String host, PingCallback callback) {
|
||||||
|
ping(host, 3, 3, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简化调用:默认Ping 3次,超时3秒(同步)
|
||||||
|
*/
|
||||||
|
public CompletableFuture<Float> pingSync(String host) {
|
||||||
|
return pingSync(host, 3, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ public class SchedulingConfig {
|
||||||
* 定时任务 检测设备在线状态
|
* 定时任务 检测设备在线状态
|
||||||
* 每60秒(1分钟)执行一次
|
* 每60秒(1分钟)执行一次
|
||||||
*/
|
*/
|
||||||
// @Scheduled(fixedRate = 60000)
|
@Scheduled(fixedRate = 2 * 60000)
|
||||||
public void scheduledTask() {
|
public void scheduledTask() {
|
||||||
tcpMonitorService.checkAllDevicesAsyncByScheduled();
|
tcpMonitorService.checkAllDevicesAsyncByScheduled();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
package com.bonus.canteen.core.healthmachine.service;
|
package com.bonus.canteen.core.healthmachine.service;
|
||||||
|
import com.bonus.canteen.core.healthmachine.config.PingUtil;
|
||||||
import com.bonus.canteen.core.healthmachine.mapper.TCPMonitorMapper;
|
import com.bonus.canteen.core.healthmachine.mapper.TCPMonitorMapper;
|
||||||
import com.bonus.canteen.core.healthmachine.bean.CheckDevice;
|
import com.bonus.canteen.core.healthmachine.bean.CheckDevice;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
@ -22,6 +23,7 @@ import java.util.concurrent.Executors;
|
||||||
public class TCPMonitorService {
|
public class TCPMonitorService {
|
||||||
|
|
||||||
private final Map<String, CheckDevice> devices = new ConcurrentHashMap<>();
|
private final Map<String, CheckDevice> devices = new ConcurrentHashMap<>();
|
||||||
|
private final Map<String, CheckDevice> pingDevices = new ConcurrentHashMap<>();
|
||||||
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
|
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
|
||||||
private static final int TIMEOUT = 3000;
|
private static final int TIMEOUT = 3000;
|
||||||
|
|
||||||
|
|
@ -49,10 +51,16 @@ public class TCPMonitorService {
|
||||||
private void initializeDevices() {
|
private void initializeDevices() {
|
||||||
try {
|
try {
|
||||||
List<CheckDevice> initialDevices = mapper.selectDeviceList();
|
List<CheckDevice> initialDevices = mapper.selectDeviceList();
|
||||||
initialDevices.forEach(device -> devices.put(device.getId(), device));
|
initialDevices.forEach(device -> {
|
||||||
|
if (device.getPort().equals("8080")){
|
||||||
|
devices.put(device.getId(), device);
|
||||||
|
}else{
|
||||||
|
pingDevices.put(device.getId(), device);
|
||||||
|
}
|
||||||
|
});
|
||||||
System.out.println("从数据库加载了 " + initialDevices.size() + " 个设备");
|
System.out.println("从数据库加载了 " + initialDevices.size() + " 个设备");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("初始化设备列表失败: " + e.getMessage());
|
System.err.println("初始化设备设备列表失败: " + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,17 +77,17 @@ public class TCPMonitorService {
|
||||||
try (Socket socket = new Socket()) {
|
try (Socket socket = new Socket()) {
|
||||||
socket.connect(new java.net.InetSocketAddress(ip, port), TIMEOUT);
|
socket.connect(new java.net.InetSocketAddress(ip, port), TIMEOUT);
|
||||||
long responseTime = System.currentTimeMillis() - startTime;
|
long responseTime = System.currentTimeMillis() - startTime;
|
||||||
System.out.println("✅ TCP端口探测成功,ip:" + ip + ",端口:" + port + ",响应时间:" + responseTime + "ms");
|
// System.out.println("✅ TCP端口探测成功,ip:" + ip + ",端口:" + port + ",响应时间:" + responseTime + "ms");
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// 优化错误日志输出
|
// 优化错误日志输出
|
||||||
if (e.getMessage().contains("Connection refused")) {
|
// if (e.getMessage().contains("Connection refused")) {
|
||||||
System.out.println("❌ TCP端口探测失败,ip:" + ip + ",端口:" + port + ",错误:连接被拒绝");
|
// System.out.println("❌ TCP端口探测失败,ip:" + ip + ",端口:" + port + ",错误:连接被拒绝");
|
||||||
} else if (e.getMessage().contains("connect timed out")) {
|
// } else if (e.getMessage().contains("connect timed out")) {
|
||||||
System.out.println("⏰ TCP端口探测超时,ip:" + ip + ",端口:" + port);
|
// System.out.println("⏰ TCP端口探测超时,ip:" + ip + ",端口:" + port);
|
||||||
} else {
|
// } else {
|
||||||
System.out.println("❌ TCP端口探测异常,ip:" + ip + ",端口:" + port + ",错误:" + e.getMessage());
|
// System.out.println("❌ TCP端口探测异常,ip:" + ip + ",端口:" + port + ",错误:" + e.getMessage());
|
||||||
}
|
// }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,18 +98,45 @@ public class TCPMonitorService {
|
||||||
public void checkDevice(String deviceId) {
|
public void checkDevice(String deviceId) {
|
||||||
CheckDevice device = devices.get(deviceId);
|
CheckDevice device = devices.get(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
System.out.println("⚠️ 设备不存在:" + deviceId);
|
// System.out.println("⚠️ 设备不存在:" + deviceId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (8080 == device.getPort()){
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
boolean isOnline = tcpProbe(device.getIp(), device.getPort());
|
boolean isOnline = tcpProbe(device.getIp(), device.getPort());
|
||||||
long responseTime = System.currentTimeMillis() - startTime;
|
long responseTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
||||||
|
device.setStatus(isOnline ? "online" : "offline");
|
||||||
|
device.setResponseTime(isOnline ? responseTime : null);
|
||||||
|
device.setLastCheck(new Date());
|
||||||
|
devices.put(deviceId, device);
|
||||||
|
// System.out.println("设备:" + device.getName() + ",状态:" + device.getStatus() + ",响应时间:" + responseTime + "ms");
|
||||||
|
}else{
|
||||||
|
PingUtil.ping(device.getIp(), 3, 3, new PingUtil.PingCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(float avgDelay) {
|
||||||
|
long responseTime = (long) avgDelay;
|
||||||
|
device.setStatus("online");
|
||||||
|
device.setResponseTime(responseTime);
|
||||||
|
device.setLastCheck(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(String errorMsg) {
|
||||||
|
device.setStatus("offline");
|
||||||
|
device.setResponseTime(null);
|
||||||
|
device.setLastCheck(new Date());
|
||||||
|
System.out.println("设备:" + device.getName() + ",Ping失败,错误信息:" + errorMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// System.out.println("设备:" + device.getName() + ",状态:" + device.getStatus() + ",响应时间:" + device.getResponseTime() + "ms");
|
||||||
|
}
|
||||||
|
boolean isOnline = device.getStatus().equals("online");
|
||||||
// 记录状态变化
|
// 记录状态变化
|
||||||
String previousStatus = device.getStatus();
|
String previousStatus = device.getStatus();
|
||||||
device.setStatus(isOnline ? "online" : "offline");
|
device.setStatus(isOnline ? "online" : "offline");
|
||||||
device.setResponseTime(isOnline ? responseTime : null);
|
device.setResponseTime(isOnline ? device.getResponseTime() : null);
|
||||||
device.setLastCheck(new Date());
|
device.setLastCheck(new Date());
|
||||||
|
|
||||||
// 更新数据库状态
|
// 更新数据库状态
|
||||||
|
|
@ -112,18 +147,18 @@ public class TCPMonitorService {
|
||||||
} else {
|
} else {
|
||||||
mapper.updateCanteenMachineStatus(deviceId);
|
mapper.updateCanteenMachineStatus(deviceId);
|
||||||
}
|
}
|
||||||
System.out.println("✅ 更新数据库状态成功:" + deviceId);
|
// System.out.println("✅ 更新数据库状态成功:" + deviceId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("❌ 更新数据库状态失败:" + deviceId + ",错误:" + e.getMessage());
|
// System.err.println("❌ 更新数据库状态失败:" + deviceId + ",错误:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果状态发生变化,记录日志
|
// 如果状态发生变化,记录日志
|
||||||
if (previousStatus != null && !device.getStatus().equals(previousStatus)) {
|
if (previousStatus != null && !device.getStatus().equals(previousStatus)) {
|
||||||
System.out.println("🔄 设备状态变化:" + device.getName() + " [" + previousStatus + " → " + device.getStatus() + "]");
|
// System.out.println("🔄 设备状态变化:" + device.getName() + " [" + previousStatus + " → " + device.getStatus() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("设备:" + deviceId + ",状态:" + device.getStatus() + ",响应时间:" + responseTime + "ms");
|
// System.out.println("设备:" + deviceId + ",状态:" + device.getStatus() + ",响应时间:" + device.getResponseTime() + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -137,7 +172,7 @@ public class TCPMonitorService {
|
||||||
* 手动触发设备检查
|
* 手动触发设备检查
|
||||||
*/
|
*/
|
||||||
public CheckDevice checkDeviceImmediately(String deviceId) {
|
public CheckDevice checkDeviceImmediately(String deviceId) {
|
||||||
System.out.println("🔍 手动触发设备检查:" + deviceId);
|
// System.out.println("🔍 手动触发设备检查:" + deviceId);
|
||||||
checkDevice(deviceId);
|
checkDevice(deviceId);
|
||||||
return getDevice(deviceId);
|
return getDevice(deviceId);
|
||||||
}
|
}
|
||||||
|
|
@ -151,8 +186,8 @@ public class TCPMonitorService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("\n=== 开始定时设备检查 ===");
|
// System.out.println("\n=== 开始定时设备检查 ===");
|
||||||
System.out.println("检查时间:" + new Date() + ",设备数量:" + devices.size());
|
// System.out.println("检查时间:" + new Date() + ",设备数量:" + devices.size());
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
@ -165,7 +200,7 @@ public class TCPMonitorService {
|
||||||
try {
|
try {
|
||||||
checkDevice(deviceId);
|
checkDevice(deviceId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("❌ 检查设备异常:" + deviceId + ",错误:" + e.getMessage());
|
// System.err.println("❌ 检查设备异常:" + deviceId + ",错误:" + e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
@ -176,11 +211,11 @@ public class TCPMonitorService {
|
||||||
try {
|
try {
|
||||||
boolean completed = latch.await(30, java.util.concurrent.TimeUnit.SECONDS);
|
boolean completed = latch.await(30, java.util.concurrent.TimeUnit.SECONDS);
|
||||||
if (!completed) {
|
if (!completed) {
|
||||||
System.out.println("⚠️ 设备检查超时,部分设备可能未完成检查");
|
// System.out.println("⚠️ 设备检查超时,部分设备可能未完成检查");
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
System.err.println("❌ 设备检查被中断");
|
// System.err.println("❌ 设备检查被中断");
|
||||||
}
|
}
|
||||||
|
|
||||||
long totalTime = System.currentTimeMillis() - startTime;
|
long totalTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
@ -190,9 +225,9 @@ public class TCPMonitorService {
|
||||||
.filter(device -> "online".equals(device.getStatus()))
|
.filter(device -> "online".equals(device.getStatus()))
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
System.out.println("=== 定时检查完成 ===");
|
// System.out.println("=== 定时检查完成 ===");
|
||||||
System.out.println("总计耗时:" + totalTime + "ms,在线设备:" + onlineCount + "/" + deviceCount);
|
// System.out.println("总计耗时:" + totalTime + "ms,在线设备:" + onlineCount + "/" + deviceCount);
|
||||||
System.out.println("下次检查时间:" + new Date(System.currentTimeMillis() + 60000) + "\n");
|
// System.out.println("下次检查时间:" + new Date(System.currentTimeMillis() + 60000) + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import com.bonus.canteen.core.kitchen.dto.KitchenSampleDishesRecordDTO;
|
||||||
import com.bonus.common.log.enums.OperaType;
|
import com.bonus.common.log.enums.OperaType;
|
||||||
//import com.bonus.canteen.core.kitchen.common.annotation.PreventRepeatSubmit;
|
//import com.bonus.canteen.core.kitchen.common.annotation.PreventRepeatSubmit;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
|
|
@ -98,7 +99,7 @@ public class KitchenSampleDishesRecordController extends BaseController {
|
||||||
//@RequiresPermissions("kitchen:record:add")
|
//@RequiresPermissions("kitchen:record:add")
|
||||||
@SysLog(title = "留样机留样清单", businessType = OperaType.INSERT, logType = 1,module = "仓储管理->新增留样机留样清单")
|
@SysLog(title = "留样机留样清单", businessType = OperaType.INSERT, logType = 1,module = "仓储管理->新增留样机留样清单")
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@RequestBody KitchenSampleDishesRecord kitchenSampleDishesRecord) {
|
public AjaxResult add(@RequestBody KitchenSampleDishesRecordDTO kitchenSampleDishesRecord) {
|
||||||
try {
|
try {
|
||||||
return AjaxResult.success(kitchenSampleDishesRecordService.insertKitchenSampleDishesRecord(kitchenSampleDishesRecord));
|
return AjaxResult.success(kitchenSampleDishesRecordService.insertKitchenSampleDishesRecord(kitchenSampleDishesRecord));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
package com.bonus.canteen.core.kitchen.dto;
|
||||||
|
|
||||||
|
import com.bonus.common.core.annotation.Excel;
|
||||||
|
import com.bonus.common.core.web.domain.BaseEntity;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 留样机留样清单对象 kitchen_sample_dishes_record
|
||||||
|
*
|
||||||
|
* @author xsheng
|
||||||
|
* @date 2025-06-16
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@ToString
|
||||||
|
public class KitchenSampleDishesRecordDTO extends BaseEntity {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 留样清单id */
|
||||||
|
private Long recordId;
|
||||||
|
|
||||||
|
/** 餐次id */
|
||||||
|
@Excel(name = "餐次id")
|
||||||
|
@ApiModelProperty(value = "餐次id")
|
||||||
|
private Long mealtimeType;
|
||||||
|
|
||||||
|
/** 设备id */
|
||||||
|
@Excel(name = "设备id")
|
||||||
|
@ApiModelProperty(value = "设备id")
|
||||||
|
private Long deviceId;
|
||||||
|
|
||||||
|
/** 店铺档口id */
|
||||||
|
@Excel(name = "店铺档口id")
|
||||||
|
@ApiModelProperty(value = "店铺档口id")
|
||||||
|
private Long stallId;
|
||||||
|
|
||||||
|
/** 食堂编号 */
|
||||||
|
@Excel(name = "食堂编号")
|
||||||
|
@ApiModelProperty(value = "食堂编号")
|
||||||
|
private Long canteenId;
|
||||||
|
|
||||||
|
/** 菜品id */
|
||||||
|
@Excel(name = "菜品id")
|
||||||
|
@ApiModelProperty(value = "菜品id")
|
||||||
|
private Long dishesId;
|
||||||
|
|
||||||
|
/** 留样菜品图片url(仅一张) */
|
||||||
|
@Excel(name = "留样菜品图片url(仅一张)")
|
||||||
|
@ApiModelProperty(value = "留样菜品图片url(仅一张)")
|
||||||
|
private String imageUrl;
|
||||||
|
|
||||||
|
/** 设备编号 */
|
||||||
|
@Excel(name = "设备编号")
|
||||||
|
@ApiModelProperty(value = "设备编号")
|
||||||
|
private String machineNo;
|
||||||
|
|
||||||
|
/** 设备sn */
|
||||||
|
@Excel(name = "设备sn")
|
||||||
|
@ApiModelProperty(value = "设备sn")
|
||||||
|
private String machineSn;
|
||||||
|
|
||||||
|
/** 留样重量 */
|
||||||
|
@Excel(name = "留样重量")
|
||||||
|
@ApiModelProperty(value = "留样重量")
|
||||||
|
private Long sampleWeight;
|
||||||
|
|
||||||
|
/** 留样时间 */
|
||||||
|
@ApiModelProperty(value = "留样时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "留样时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date sampleSaveTime;
|
||||||
|
|
||||||
|
/** 厨师id */
|
||||||
|
@Excel(name = "厨师id")
|
||||||
|
@ApiModelProperty(value = "厨师id")
|
||||||
|
private Long chefId;
|
||||||
|
|
||||||
|
/** 留样员工id */
|
||||||
|
@Excel(name = "留样员工id")
|
||||||
|
@ApiModelProperty(value = "留样员工id")
|
||||||
|
private String sampleSaveStaffId;
|
||||||
|
|
||||||
|
/** 取样员工id */
|
||||||
|
@Excel(name = "取样员工id")
|
||||||
|
@ApiModelProperty(value = "取样员工id")
|
||||||
|
private Long sampleTakeStaffId;
|
||||||
|
|
||||||
|
/** 打印时间 */
|
||||||
|
@ApiModelProperty(value = "打印时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "打印时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date printRecordTime;
|
||||||
|
|
||||||
|
/** 进入留样柜时间 */
|
||||||
|
@ApiModelProperty(value = "进入留样柜时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "进入留样柜时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date enterCabinetTime;
|
||||||
|
|
||||||
|
/** 离开留样柜时间 */
|
||||||
|
@ApiModelProperty(value = "离开留样柜时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "离开留样柜时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date leaveCabinetTime;
|
||||||
|
|
||||||
|
/** 过期时间 */
|
||||||
|
@ApiModelProperty(value = "过期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "过期时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date expirationTime;
|
||||||
|
|
||||||
|
/** 重量是否达到标准 1是2否 */
|
||||||
|
@Excel(name = "重量是否达到标准 1是2否")
|
||||||
|
@ApiModelProperty(value = "重量是否达到标准 1是2否")
|
||||||
|
private Integer weightStandard;
|
||||||
|
|
||||||
|
/** 有效时长 */
|
||||||
|
@Excel(name = "有效时长")
|
||||||
|
@ApiModelProperty(value = "有效时长")
|
||||||
|
private Long validDuration;
|
||||||
|
|
||||||
|
/** 留样时长是否达到标准 1是2否 */
|
||||||
|
@Excel(name = "留样时长是否达到标准 1是2否")
|
||||||
|
@ApiModelProperty(value = "留样时长是否达到标准 1是2否")
|
||||||
|
private Integer durationStandard;
|
||||||
|
|
||||||
|
/** 样品状态 */
|
||||||
|
@Excel(name = "样品状态")
|
||||||
|
@ApiModelProperty(value = "样品状态")
|
||||||
|
private Long status;
|
||||||
|
|
||||||
|
/** 柜门编号 */
|
||||||
|
@Excel(name = "柜门编号")
|
||||||
|
@ApiModelProperty(value = "柜门编号")
|
||||||
|
private Long cabinetNo;
|
||||||
|
|
||||||
|
/** 存放状态 1未入柜 2在柜 3离柜 4超时自动离柜 */
|
||||||
|
@Excel(name = "存放状态 1未入柜 2在柜 3离柜 4超时自动离柜")
|
||||||
|
@ApiModelProperty(value = "存放状态 1未入柜 2在柜 3离柜 4超时自动离柜")
|
||||||
|
private Integer saveStatus;
|
||||||
|
|
||||||
|
@Excel(name = "存放状态 1未入柜 2在柜 3离柜 4超时自动离柜")
|
||||||
|
@ApiModelProperty(value = "存放状态 1未入柜 2在柜 3离柜 4超时自动离柜")
|
||||||
|
private String saveStatusName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "查询类型 1 今日 2 昨日 3 历史")
|
||||||
|
@NotNull(message = "查询类型不能为空")
|
||||||
|
private Integer searchType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "违规状态 重量未达标 时长未达标 正常")
|
||||||
|
private String illegalStatusName;
|
||||||
|
|
||||||
|
@ApiModelProperty("开始时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime startDateTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("结束时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime endDateTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("食堂名称")
|
||||||
|
private String canteenName;
|
||||||
|
|
||||||
|
@ApiModelProperty("档口名称")
|
||||||
|
private String stallName;
|
||||||
|
|
||||||
|
@ApiModelProperty("菜品名称")
|
||||||
|
private String dishesName;
|
||||||
|
|
||||||
|
@ApiModelProperty("菜品图片")
|
||||||
|
private String dishesImgUrl;
|
||||||
|
|
||||||
|
@ApiModelProperty("设备名称")
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
@ApiModelProperty("留样人")
|
||||||
|
private String staffName;
|
||||||
|
|
||||||
|
@ApiModelProperty("取样人")
|
||||||
|
private String takeStaffName;
|
||||||
|
|
||||||
|
private String searchValue;
|
||||||
|
|
||||||
|
private LocalDate applyDate;
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package com.bonus.canteen.core.kitchen.mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.bonus.canteen.core.kitchen.domain.KitchenSampleDishesRecord;
|
import com.bonus.canteen.core.kitchen.domain.KitchenSampleDishesRecord;
|
||||||
|
import com.bonus.canteen.core.kitchen.dto.KitchenSampleDishesRecordDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 留样机留样清单Mapper接口
|
* 留样机留样清单Mapper接口
|
||||||
|
|
@ -32,7 +33,7 @@ public interface KitchenSampleDishesRecordMapper {
|
||||||
* @param kitchenSampleDishesRecord 留样机留样清单
|
* @param kitchenSampleDishesRecord 留样机留样清单
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecord kitchenSampleDishesRecord);
|
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecordDTO kitchenSampleDishesRecord);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改留样机留样清单
|
* 修改留样机留样清单
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.bonus.canteen.core.kitchen.service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.bonus.canteen.core.kitchen.domain.KitchenSampleDishesRecord;
|
import com.bonus.canteen.core.kitchen.domain.KitchenSampleDishesRecord;
|
||||||
|
import com.bonus.canteen.core.kitchen.dto.KitchenSampleDishesRecordDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 留样机留样清单Service接口
|
* 留样机留样清单Service接口
|
||||||
|
|
@ -32,7 +33,7 @@ public interface IKitchenSampleDishesRecordService {
|
||||||
* @param kitchenSampleDishesRecord 留样机留样清单
|
* @param kitchenSampleDishesRecord 留样机留样清单
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecord kitchenSampleDishesRecord);
|
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecordDTO kitchenSampleDishesRecord);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改留样机留样清单
|
* 修改留样机留样清单
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import com.bonus.canteen.core.basic.mapper.BasicStallMealtimeMapper;
|
||||||
import com.bonus.canteen.core.kitchen.domain.constants.CommonFlagEnum;
|
import com.bonus.canteen.core.kitchen.domain.constants.CommonFlagEnum;
|
||||||
import com.bonus.canteen.core.kitchen.domain.constants.SampleDishesSaveStatusEnum;
|
import com.bonus.canteen.core.kitchen.domain.constants.SampleDishesSaveStatusEnum;
|
||||||
import com.bonus.canteen.core.kitchen.domain.constants.SampleDishesSearchType;
|
import com.bonus.canteen.core.kitchen.domain.constants.SampleDishesSearchType;
|
||||||
|
import com.bonus.canteen.core.kitchen.dto.KitchenSampleDishesRecordDTO;
|
||||||
import com.bonus.common.core.exception.ServiceException;
|
import com.bonus.common.core.exception.ServiceException;
|
||||||
import com.bonus.common.core.utils.DateUtils;
|
import com.bonus.common.core.utils.DateUtils;
|
||||||
import com.bonus.common.core.utils.StringUtils;
|
import com.bonus.common.core.utils.StringUtils;
|
||||||
|
|
@ -93,7 +94,7 @@ public class KitchenSampleDishesRecordServiceImpl implements IKitchenSampleDishe
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecord kitchenSampleDishesRecord) {
|
public long insertKitchenSampleDishesRecord(KitchenSampleDishesRecordDTO kitchenSampleDishesRecord) {
|
||||||
kitchenSampleDishesRecord.setCreateTime(DateUtils.getNowDate());
|
kitchenSampleDishesRecord.setCreateTime(DateUtils.getNowDate());
|
||||||
kitchenSampleDishesRecord.setRecordId(null);
|
kitchenSampleDishesRecord.setRecordId(null);
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
where record_id = #{recordId}
|
where record_id = #{recordId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insertKitchenSampleDishesRecord" parameterType="com.bonus.canteen.core.kitchen.domain.KitchenSampleDishesRecord" keyProperty="recordId" useGeneratedKeys="true">
|
<insert id="insertKitchenSampleDishesRecord" parameterType="com.bonus.canteen.core.kitchen.dto.KitchenSampleDishesRecordDTO" keyProperty="recordId" useGeneratedKeys="true">
|
||||||
insert into kitchen_sample_dishes_record
|
insert into kitchen_sample_dishes_record
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
<if test="recordId != null">record_id,</if>
|
<if test="recordId != null">record_id,</if>
|
||||||
|
|
@ -143,7 +143,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<if test="stallId != null">#{stallId},</if>
|
<if test="stallId != null">#{stallId},</if>
|
||||||
<if test="canteenId != null">#{canteenId},</if>
|
<if test="canteenId != null">#{canteenId},</if>
|
||||||
<if test="dishesId != null">#{dishesId},</if>
|
<if test="dishesId != null">#{dishesId},</if>
|
||||||
<if test="imageUrl != null and imageUrl != ''">#{imageUrl},</if>
|
<if test="imageUrl != null and imageUrl != ''">#{photoUrl},</if>
|
||||||
<if test="machineNo != null">#{machineNo},</if>
|
<if test="machineNo != null">#{machineNo},</if>
|
||||||
<if test="machineSn != null">#{machineSn},</if>
|
<if test="machineSn != null">#{machineSn},</if>
|
||||||
<if test="sampleWeight != null">#{sampleWeight},</if>
|
<if test="sampleWeight != null">#{sampleWeight},</if>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue