From ce13e25ed685ba5c961832d023ceafecf4f30d47 Mon Sep 17 00:00:00 2001
From: Junjie <DELL@qq.com>
Date: 星期六, 10 一月 2026 15:27:33 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/asrs/controller/DeviceLogController.java |  219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 218 insertions(+), 1 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/DeviceLogController.java b/src/main/java/com/zy/asrs/controller/DeviceLogController.java
index d5537e9..6640886 100644
--- a/src/main/java/com/zy/asrs/controller/DeviceLogController.java
+++ b/src/main/java/com/zy/asrs/controller/DeviceLogController.java
@@ -1,24 +1,29 @@
 package com.zy.asrs.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.core.annotations.ManagerAuth;
 import com.core.common.Cools;
 import com.core.common.R;
+import com.zy.asrs.entity.DeviceDataLog;
 import com.zy.common.web.BaseController;
 import com.zy.core.enums.SlaveType;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
-
 import javax.servlet.http.HttpServletResponse;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+@Slf4j
 @RestController
 public class DeviceLogController extends BaseController {
 
@@ -130,6 +135,186 @@
             return R.ok(res);
         } catch (Exception e) {
             return R.error("璇诲彇璁惧鍒楄〃澶辫触");
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/day/{day}/preview/auth")
+    @ManagerAuth
+    public R preview(@PathVariable("day") String day,
+                     @RequestParam("type") String type,
+                     @RequestParam("deviceNo") String deviceNo,
+                     @RequestParam(value = "offset", required = false) Integer offset,
+                     @RequestParam(value = "limit", required = false) Integer limit) {
+        try {
+            String dayClean = day == null ? null : day.replaceAll("\\D", "");
+            if (dayClean == null || dayClean.length() != 8 || !dayClean.chars().allMatch(Character::isDigit)) {
+                return R.error("鏃ユ湡鏍煎紡閿欒");
+            }
+            if (type == null || SlaveType.findInstance(type) == null) {
+                return R.error("璁惧绫诲瀷閿欒");
+            }
+            if (deviceNo == null || !deviceNo.chars().allMatch(Character::isDigit)) {
+                return R.error("璁惧缂栧彿閿欒");
+            }
+            Path dayDir = Paths.get(loggingPath, dayClean);
+            if (!Files.exists(dayDir) || !Files.isDirectory(dayDir)) {
+                return R.ok(new ArrayList<>());
+            }
+            String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+            List<Path> files = Files.list(dayDir)
+                    .filter(p -> {
+                        String name = p.getFileName().toString();
+                        return name.endsWith(".log") && name.startsWith(prefix);
+                    }).collect(Collectors.toList());
+            
+            files.sort(Comparator.comparingInt(p -> {
+                String n = p.getFileName().toString();
+                try {
+                    String suf = n.substring(prefix.length(), n.length() - 4);
+                    return Integer.parseInt(suf);
+                } catch (Exception e) {
+                    return Integer.MAX_VALUE;
+                }
+            }));
+            
+            int from = offset == null || offset < 0 ? 0 : offset;
+            int max = limit == null || limit <= 0 ? 5 : limit; // 榛樿璇诲彇5涓枃浠�
+            if (max > 10) max = 10; // 闄愬埗鏈�澶ф枃浠舵暟锛岄槻姝㈣秴鏃�
+            int to = Math.min(files.size(), from + max);
+            
+            if (from >= files.size()) {
+                return R.ok(new ArrayList<>());
+            }
+            
+            List<Path> targetFiles = files.subList(from, to);
+            List<DeviceDataLog> resultLogs = new ArrayList<>();
+            
+            for (Path f : targetFiles) {
+                try (Stream<String> lines = Files.lines(f, StandardCharsets.UTF_8)) {
+                    lines.forEach(line -> {
+                        if (line != null && !line.trim().isEmpty()) {
+                            try {
+                                DeviceDataLog logItem = JSON.parseObject(line, DeviceDataLog.class);
+                                resultLogs.add(logItem);
+                            } catch (Exception e) {
+                                // 蹇界暐瑙f瀽閿欒
+                            }
+                        }
+                    });
+                } catch (Exception e) {
+                    log.error("璇诲彇鏃ュ織鏂囦欢澶辫触: " + f, e);
+                }
+            }
+            // 鎸夋椂闂存帓搴�
+            resultLogs.sort(Comparator.comparing(DeviceDataLog::getCreateTime, Comparator.nullsLast(Date::compareTo)));
+            
+            return R.ok(resultLogs);
+        } catch (Exception e) {
+            log.error("棰勮鏃ュ織澶辫触", e);
+            return R.error("棰勮鏃ュ織澶辫触");
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/day/{day}/seek/auth")
+    @ManagerAuth
+    public R seek(@PathVariable("day") String day,
+                  @RequestParam("type") String type,
+                  @RequestParam("deviceNo") String deviceNo,
+                  @RequestParam("timestamp") Long timestamp) {
+        try {
+            String dayClean = day == null ? null : day.replaceAll("\\D", "");
+            if (dayClean == null || dayClean.length() != 8 || !dayClean.chars().allMatch(Character::isDigit)) {
+                return R.error("鏃ユ湡鏍煎紡閿欒");
+            }
+            if (type == null || SlaveType.findInstance(type) == null) {
+                return R.error("璁惧绫诲瀷閿欒");
+            }
+            if (deviceNo == null || !deviceNo.chars().allMatch(Character::isDigit)) {
+                return R.error("璁惧缂栧彿閿欒");
+            }
+            Path dayDir = Paths.get(loggingPath, dayClean);
+            if (!Files.exists(dayDir) || !Files.isDirectory(dayDir)) {
+                return R.error("鏈壘鍒版棩蹇楁枃浠�");
+            }
+            
+            String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+            List<Path> files = Files.list(dayDir)
+                    .filter(p -> {
+                        String name = p.getFileName().toString();
+                        return name.endsWith(".log") && name.startsWith(prefix);
+                    }).collect(Collectors.toList());
+            
+            files.sort(Comparator.comparingInt(p -> {
+                String n = p.getFileName().toString();
+                try {
+                    String suf = n.substring(prefix.length(), n.length() - 4);
+                    return Integer.parseInt(suf);
+                } catch (Exception e) {
+                    return Integer.MAX_VALUE;
+                }
+            }));
+            
+            if (files.isEmpty()) {
+                return R.error("鏈壘鍒版棩蹇楁枃浠�");
+            }
+            
+            // Binary search for the file containing the timestamp
+            // We want to find the LAST file that has startTime <= targetTime.
+            // Because files are sequential: [t0, t1), [t1, t2), ...
+            // If we find file[i].startTime <= target < file[i+1].startTime, then target is in file[i].
+            
+            int low = 0;
+            int high = files.size() - 1;
+            int foundIndex = -1;
+            
+            while (low <= high) {
+                int mid = (low + high) >>> 1;
+                Path midFile = files.get(mid);
+                
+                // Read start time of this file
+                Long midStart = getFileStartTime(midFile);
+                if (midStart == null) {
+                    low = mid + 1;
+                    continue;
+                }
+                
+                if (midStart <= timestamp) {
+                    // This file starts before or at target. It COULD be the one.
+                    // But maybe a later file also starts before target?
+                    foundIndex = mid;
+                    low = mid + 1; // Try to find a later start time
+                } else {
+                    // This file starts AFTER target. So target must be in an earlier file.
+                    high = mid - 1;
+                }
+            }
+            
+            if (foundIndex == -1) {
+                foundIndex = 0;
+            }
+            
+            // Return the file index (offset)
+            Map<String, Object> result = new HashMap<>();
+            result.put("offset", foundIndex);
+            return R.ok(result);
+            
+        } catch (Exception e) {
+            log.error("瀵诲潃澶辫触", e);
+            return R.error("瀵诲潃澶辫触");
+        }
+    }
+    
+    private Long getFileStartTime(Path file) {
+        try {
+            String firstLine = null;
+            try (Stream<String> lines = Files.lines(file, StandardCharsets.UTF_8)) {
+                firstLine = lines.findFirst().orElse(null);
+            }
+            if (firstLine == null) return null;
+            DeviceDataLog firstLog = JSON.parseObject(firstLine, DeviceDataLog.class);
+            return firstLog.getCreateTime().getTime();
+        } catch (Exception e) {
+            return null;
         }
     }
 
@@ -335,4 +520,36 @@
         res.put("finished", info.finished);
         return R.ok(res);
     }
+
+    @RequestMapping(value = "/deviceLog/enums/auth")
+    @ManagerAuth
+    public R getEnums() {
+        Map<String, Map<String, String>> enums = new HashMap<>();
+        
+        enums.put("CrnModeType", Arrays.stream(com.zy.core.enums.CrnModeType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+        
+        enums.put("CrnStatusType", Arrays.stream(com.zy.core.enums.CrnStatusType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+        
+        enums.put("CrnForkPosType", Arrays.stream(com.zy.core.enums.CrnForkPosType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+        
+        enums.put("CrnLiftPosType", Arrays.stream(com.zy.core.enums.CrnLiftPosType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+
+        enums.put("DualCrnForkPosType", Arrays.stream(com.zy.core.enums.DualCrnForkPosType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+
+        enums.put("DualCrnLiftPosType", Arrays.stream(com.zy.core.enums.DualCrnLiftPosType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+
+        enums.put("RgvModeType", Arrays.stream(com.zy.core.enums.RgvModeType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+
+        enums.put("RgvStatusType", Arrays.stream(com.zy.core.enums.RgvStatusType.values())
+                .collect(Collectors.toMap(e -> String.valueOf(e.id), e -> e.desc)));
+        
+        return R.ok(enums);
+    }
 }

--
Gitblit v1.9.1