From 48c1de18235020edff108339ed1d12bade8a2b90 Mon Sep 17 00:00:00 2001
From: Junjie <DELL@qq.com>
Date: 星期一, 08 十二月 2025 16:37:02 +0800
Subject: [PATCH] #

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

diff --git a/src/main/java/com/zy/asrs/controller/DeviceLogController.java b/src/main/java/com/zy/asrs/controller/DeviceLogController.java
new file mode 100644
index 0000000..d5537e9
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/DeviceLogController.java
@@ -0,0 +1,338 @@
+package com.zy.asrs.controller;
+
+import com.core.annotations.ManagerAuth;
+import com.core.common.Cools;
+import com.core.common.R;
+import com.zy.common.web.BaseController;
+import com.zy.core.enums.SlaveType;
+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.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;
+
+@RestController
+public class DeviceLogController extends BaseController {
+
+    @Value("${deviceLogStorage.loggingPath}")
+    private String loggingPath;
+
+    private static class ProgressInfo {
+        long totalRaw;
+        long processedRaw;
+        int totalCount;
+        int processedCount;
+        boolean finished;
+    }
+
+    private static final Map<String, ProgressInfo> DOWNLOAD_PROGRESS = new ConcurrentHashMap<>();
+
+    @RequestMapping(value = "/deviceLog/dates/auth")
+    @ManagerAuth
+    public R dates() {
+        try {
+            Path baseDir = Paths.get(loggingPath);
+            if (!Files.exists(baseDir)) {
+                return R.ok(new ArrayList<>());
+            }
+            List<String> days = Files.list(baseDir)
+                    .filter(Files::isDirectory)
+                    .map(p -> p.getFileName().toString())
+                    .filter(name -> name.length() == 8 && name.chars().allMatch(Character::isDigit))
+                    .sorted()
+                    .collect(Collectors.toList());
+            Map<String, Map<String, List<String>>> grouped = new LinkedHashMap<>();
+            for (String day : days) {
+                String year = day.substring(0, 4);
+                String month = day.substring(4, 6);
+                grouped.computeIfAbsent(year, k -> new LinkedHashMap<>())
+                        .computeIfAbsent(month, k -> new ArrayList<>())
+                        .add(day);
+            }
+            List<Map<String, Object>> tree = new ArrayList<>();
+            for (Map.Entry<String, Map<String, List<String>>> yEntry : grouped.entrySet()) {
+                Map<String, Object> yNode = new HashMap<>();
+                yNode.put("title", yEntry.getKey());
+                yNode.put("id", yEntry.getKey());
+                List<Map<String, Object>> mChildren = new ArrayList<>();
+                for (Map.Entry<String, List<String>> mEntry : yEntry.getValue().entrySet()) {
+                    Map<String, Object> mNode = new HashMap<>();
+                    mNode.put("title", mEntry.getKey());
+                    mNode.put("id", yEntry.getKey() + "-" + mEntry.getKey());
+                    List<Map<String, Object>> dChildren = new ArrayList<>();
+                    for (String d : mEntry.getValue()) {
+                        Map<String, Object> dNode = new HashMap<>();
+                        dNode.put("title", d.substring(6, 8));
+                        dNode.put("id", d);
+                        dNode.put("day", d);
+                        dChildren.add(dNode);
+                    }
+                    mNode.put("children", dChildren);
+                    mChildren.add(mNode);
+                }
+                yNode.put("children", mChildren);
+                tree.add(yNode);
+            }
+            return R.ok(tree);
+        } catch (Exception e) {
+            return R.error("璇诲彇鏃ユ湡澶辫触");
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/day/{day}/devices/auth")
+    @ManagerAuth
+    public R devices(@PathVariable("day") String day) {
+        try {
+            if (day == null || day.length() != 8 || !day.chars().allMatch(Character::isDigit)) {
+                return R.error("鏃ユ湡鏍煎紡閿欒");
+            }
+            Path dayDir = Paths.get(loggingPath, day);
+            if (!Files.exists(dayDir) || !Files.isDirectory(dayDir)) {
+                return R.ok(new ArrayList<>());
+            }
+            List<Path> files = Files.list(dayDir)
+                    .filter(p -> !Files.isDirectory(p) && p.getFileName().toString().endsWith(".log"))
+                    .collect(Collectors.toList());
+            Map<String, Map<String, Object>> deviceMap = new HashMap<>();
+            for (Path p : files) {
+                String name = p.getFileName().toString();
+                String[] parts = name.split("_");
+                if (parts.length < 4) {
+                    continue;
+                }
+                String deviceNo = parts[1];
+                String type = parts[0];
+                Map<String, Object> info = deviceMap.computeIfAbsent(deviceNo, k -> {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put("deviceNo", deviceNo);
+                    map.put("types", new HashSet<String>());
+                    map.put("fileCount", 0);
+                    return map;
+                });
+                ((Set<String>) info.get("types")).add(type);
+                info.put("fileCount", ((Integer) info.get("fileCount")) + 1);
+            }
+            List<Map<String, Object>> res = deviceMap.values().stream().map(m -> {
+                Map<String, Object> x = new HashMap<>();
+                x.put("deviceNo", m.get("deviceNo"));
+                x.put("types", ((Set<String>) m.get("types")).stream().collect(Collectors.toList()));
+                x.put("fileCount", m.get("fileCount"));
+                return x;
+            }).collect(Collectors.toList());
+            return R.ok(res);
+        } catch (Exception e) {
+            return R.error("璇诲彇璁惧鍒楄〃澶辫触");
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/day/{day}/download/auth")
+    @ManagerAuth
+    public void download(@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,
+                         @RequestParam(value = "progressId", required = false) String progressId,
+                         HttpServletResponse response) {
+        try {
+            String dayClean = day == null ? null : day.replaceAll("\\D", "");
+            if (dayClean == null || dayClean.length() != 8 || !dayClean.chars().allMatch(Character::isDigit)) {
+                response.setStatus(400);
+                return;
+            }
+            if (type == null || SlaveType.findInstance(type) == null) {
+                response.setStatus(400);
+                return;
+            }
+            if (deviceNo == null || !deviceNo.chars().allMatch(Character::isDigit)) {
+                response.setStatus(400);
+                return;
+            }
+            Path dayDir = Paths.get(loggingPath, dayClean);
+            if (!Files.exists(dayDir) || !Files.isDirectory(dayDir)) {
+                response.setStatus(404);
+                return;
+            }
+            List<Path> files = Files.list(dayDir)
+                    .filter(p -> {
+                        String name = p.getFileName().toString();
+                        String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+                        return name.endsWith(".log") && name.startsWith(prefix);
+                    }).collect(Collectors.toList());
+            // 鎺掑簭锛堟寜鏂囦欢涓殑绱㈠紩鍙烽�掑锛�
+            String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+            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 ? 200 : limit;
+            int to = Math.min(files.size(), from + max);
+            if (from >= files.size()) {
+                response.setStatus(404);
+                return;
+            }
+            files = files.subList(from, to);
+            if (files.isEmpty()) {
+                response.setStatus(404);
+                return;
+            }
+            ProgressInfo info;
+            String id = progressId;
+            if (Cools.isEmpty(id)) {
+                id = UUID.randomUUID().toString();
+            }
+            List<Path> finalFiles = files;
+            info = DOWNLOAD_PROGRESS.computeIfAbsent(id, k -> {
+                ProgressInfo x = new ProgressInfo();
+                x.totalCount = finalFiles.size();
+                long sum = 0L;
+                for (Path f : finalFiles) {
+                    try { sum += Files.size(f); } catch (Exception ignored) {}
+                }
+                x.totalRaw = sum;
+                x.processedRaw = 0L;
+                x.processedCount = 0;
+                x.finished = false;
+                return x;
+            });
+            response.reset();
+            response.setContentType("application/zip");
+            String filename = type + "_" + deviceNo + "_" + dayClean + ".zip";
+            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
+            long totalRawSize = 0L;
+            for (Path f : files) {
+                try { totalRawSize += Files.size(f); } catch (Exception ignored) {}
+            }
+            response.setHeader("X-Total-Size", String.valueOf(totalRawSize));
+            response.setHeader("X-File-Count", String.valueOf(files.size()));
+            response.setHeader("X-Progress-Id", id);
+            try (java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(response.getOutputStream())) {
+                for (Path f : files) {
+                    java.util.zip.ZipEntry entry = new java.util.zip.ZipEntry(f.getFileName().toString());
+                    zos.putNextEntry(entry);
+                    Files.copy(f, zos);
+                    zos.closeEntry();
+                    try {
+                        info.processedRaw += Files.size(f);
+                    } catch (Exception ignored) {}
+                    info.processedCount += 1;
+                }
+                zos.finish();
+                info.finished = true;
+            }
+        } catch (Exception e) {
+            try { response.setStatus(500); } catch (Exception ignore) {}
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/download/init/auth")
+    @ManagerAuth
+    public R init(@org.springframework.web.bind.annotation.RequestBody com.alibaba.fastjson.JSONObject param) {
+        try {
+            String day = param.getString("day");
+            String type = param.getString("type");
+            String deviceNo = param.getString("deviceNo");
+            Integer offset = param.getInteger("offset");
+            Integer limit = param.getInteger("limit");
+            String dayClean = Cools.isEmpty(day) ? null : day.replaceAll("\\D", "");
+            if (Cools.isEmpty(dayClean) || dayClean.length() != 8 || !dayClean.chars().allMatch(Character::isDigit)) {
+                return R.error("鏃ユ湡鏍煎紡閿欒");
+            }
+            if (Cools.isEmpty(type) || SlaveType.findInstance(type) == null) {
+                return R.error("璁惧绫诲瀷閿欒");
+            }
+            if (Cools.isEmpty(deviceNo) || !deviceNo.chars().allMatch(Character::isDigit)) {
+                return R.error("璁惧缂栧彿閿欒");
+            }
+            Path dayDir = Paths.get(loggingPath, dayClean);
+            if (!Files.exists(dayDir) || !Files.isDirectory(dayDir)) {
+                return R.error("褰撴棩鐩綍涓嶅瓨鍦�");
+            }
+            List<Path> files = Files.list(dayDir)
+                    .filter(p -> {
+                        String name = p.getFileName().toString();
+                        String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+                        return name.endsWith(".log") && name.startsWith(prefix);
+                    }).collect(Collectors.toList());
+            String prefix = type + "_" + deviceNo + "_" + dayClean + "_";
+            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 ? 200 : limit;
+            int to = Math.min(files.size(), from + max);
+            if (from >= files.size()) {
+                return R.error("璧峰搴忓彿瓒呭嚭鑼冨洿");
+            }
+            files = files.subList(from, to);
+            String id = UUID.randomUUID().toString();
+            ProgressInfo info = new ProgressInfo();
+            info.totalCount = files.size();
+            long sum = 0L;
+            for (Path f : files) {
+                try { sum += Files.size(f); } catch (Exception ignored) {}
+            }
+            info.totalRaw = sum;
+            info.processedRaw = 0L;
+            info.processedCount = 0;
+            info.finished = false;
+            DOWNLOAD_PROGRESS.put(id, info);
+            Map<String, Object> res = new HashMap<>();
+            res.put("progressId", id);
+            res.put("totalSize", info.totalRaw);
+            res.put("fileCount", info.totalCount);
+            return R.ok(res);
+        } catch (Exception e) {
+            return R.error("鍒濆鍖栧け璐�");
+        }
+    }
+
+    @RequestMapping(value = "/deviceLog/download/progress/auth")
+    @ManagerAuth
+    public R progress(String id) {
+        ProgressInfo info = DOWNLOAD_PROGRESS.get(id);
+        if (info == null) {
+            return R.error("鏃犳晥杩涘害");
+        }
+        long total = info.totalRaw;
+        long done = info.processedRaw;
+        int percent;
+        if (info.finished) {
+            percent = 100;
+        } else if (total > 0) {
+            percent = (int) Math.min(99, (done * 100L) / total);
+        } else if (info.totalCount > 0) {
+            percent = (int) Math.min(99, (info.processedCount * 100L) / info.totalCount);
+        } else {
+            percent = 0;
+        }
+        Map<String, Object> res = new HashMap<>();
+        res.put("percent", percent);
+        res.put("processedSize", done);
+        res.put("totalSize", total);
+        res.put("processedCount", info.processedCount);
+        res.put("totalCount", info.totalCount);
+        res.put("finished", info.finished);
+        return R.ok(res);
+    }
+}

--
Gitblit v1.9.1