Merge remote-tracking branch 'origin/lcj' into lcj
This commit is contained in:
		| @ -1,591 +0,0 @@ | |||||||
| package org.dromara.test; |  | ||||||
|  |  | ||||||
| import cn.hutool.json.JSONUtil; |  | ||||||
| import jakarta.annotation.Resource; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| import org.dromara.manager.spartamanager.SpartaManager; |  | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaRecTypeEnum; |  | ||||||
| import org.dromara.manager.spartamanager.vo.ImageStreamResult; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaRecognizeVo; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaTargetVo; |  | ||||||
| import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture; |  | ||||||
| import org.dromara.other.service.IOthYs7DeviceImgService; |  | ||||||
| import org.junit.jupiter.api.Test; |  | ||||||
| import org.springframework.boot.test.context.SpringBootTest; |  | ||||||
|  |  | ||||||
| import javax.imageio.ImageIO; |  | ||||||
| import java.awt.*; |  | ||||||
| import java.awt.image.BufferedImage; |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.FileOutputStream; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.OutputStream; |  | ||||||
| import java.net.URI; |  | ||||||
| import java.net.URISyntaxException; |  | ||||||
| import java.util.Date; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:40 |  | ||||||
|  */ |  | ||||||
| @Slf4j |  | ||||||
| @SpringBootTest |  | ||||||
| public class SpartaTest { |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private SpartaManager spartaManager; |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private IOthYs7DeviceImgService othYs7DeviceImgService; |  | ||||||
|  |  | ||||||
|     @Test |  | ||||||
|     public void test() { |  | ||||||
|         String token = spartaManager.getToken(); |  | ||||||
|         log.info("token: {}", token); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Test |  | ||||||
|     public void test2() throws URISyntaxException, IOException { |  | ||||||
|         String url = "http://58.17.134.85:9000/xinnengyuan-dev/ys7/device/img/sxt_1750583731809_227.jpg"; |  | ||||||
| //        List<SpartaRecTypeEnum> hat = List.of(SpartaRecTypeEnum.HAT, SpartaRecTypeEnum.HEAD); |  | ||||||
| //        SpartaRecognizeVo recognize = spartaManager.recognize( |  | ||||||
| //            url, |  | ||||||
| //            hat, |  | ||||||
| //            null, |  | ||||||
| //            null, |  | ||||||
| //            null |  | ||||||
| //        ); |  | ||||||
| //        log.info("识别结果: {}", recognize); |  | ||||||
|         SpartaRecognizeVo vo = new SpartaRecognizeVo(); |  | ||||||
|         vo.setHasTarget(1); |  | ||||||
|         vo.setOriginalImgSize(List.of(2560, 1440)); |  | ||||||
|  |  | ||||||
|         SpartaTargetVo targets = new SpartaTargetVo(); |  | ||||||
|         targets.setType("hat"); |  | ||||||
|         targets.setSize(List.of(59, 78)); |  | ||||||
|         targets.setLeftTopPoint(List.of(880, 597)); |  | ||||||
|         targets.setScore(0.41687846183776855); |  | ||||||
|  |  | ||||||
|         vo.setTargets(List.of(targets)); |  | ||||||
|         // 1. 读取图片 |  | ||||||
|         URI uri = new URI(url); |  | ||||||
|         BufferedImage image = ImageIO.read(uri.toURL()); |  | ||||||
|         // 2. 创建画布 |  | ||||||
|         Graphics2D g = image.createGraphics(); |  | ||||||
|         g.setColor(Color.RED); |  | ||||||
|         g.setStroke(new BasicStroke(5)); |  | ||||||
|         g.setFont(new Font("SansSerif", Font.BOLD, 18)); |  | ||||||
|         // 3. 遍历目标并画框 |  | ||||||
|         for (SpartaTargetVo target : vo.getTargets()) { |  | ||||||
|             List<Integer> size = target.getSize(); // 宽高 |  | ||||||
|             List<Integer> leftTop = target.getLeftTopPoint(); // x y |  | ||||||
|  |  | ||||||
|             int x = leftTop.get(0); |  | ||||||
|             int y = leftTop.get(1); |  | ||||||
|             int width = size.get(0); |  | ||||||
|             int height = size.get(1); |  | ||||||
|  |  | ||||||
|             // 画矩形框 |  | ||||||
|             g.drawRect(x, y, width, height); |  | ||||||
|  |  | ||||||
|             // 写文字(类型 + 置信度) |  | ||||||
|             String label = SpartaRecTypeEnum.fromValue(target.getType()).getText() + " (" + String.format("%.2f", target.getScore()) + ")"; |  | ||||||
|             g.drawString(label, x, y - 5); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         g.dispose(); |  | ||||||
|  |  | ||||||
|         // 4. 保存标记后的图片 |  | ||||||
|         File outFile = new File("marked_output.jpg"); |  | ||||||
|         ImageIO.write(image, "jpg", outFile); |  | ||||||
|  |  | ||||||
|         System.out.println("标记完成,保存路径: " + "marked_output.jpg"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Test |  | ||||||
|     public void test3() { |  | ||||||
|         String url = "http://58.17.134.85:9000/xinnengyuan-dev/ys7/device/img/sxt_1750583731809_227.jpg"; |  | ||||||
|         OthYs7DeviceImgCreateByCapture img = new OthYs7DeviceImgCreateByCapture(); |  | ||||||
|         img.setCreateTime(new Date()); |  | ||||||
|         img.setUrl(url); |  | ||||||
|         img.setDeviceName("摄像头1"); |  | ||||||
|         img.setDeviceSerial("sxt_1750583731809_227"); |  | ||||||
|         log.info("识别结果: {}", img); |  | ||||||
|         othYs7DeviceImgService.saveCapturePic(List.of(img)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Test |  | ||||||
|     public void test4() throws IOException, URISyntaxException { |  | ||||||
|         String url = "http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png"; |  | ||||||
|         String targetStr = "[\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                344,\n" + |  | ||||||
|             "                149\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3787,\n" + |  | ||||||
|             "                3241\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9511\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                334,\n" + |  | ||||||
|             "                147\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4276,\n" + |  | ||||||
|             "                3590\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9498\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                330,\n" + |  | ||||||
|             "                149\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3459,\n" + |  | ||||||
|             "                3183\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9496\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                353,\n" + |  | ||||||
|             "                148\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4226,\n" + |  | ||||||
|             "                3714\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9495\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                339,\n" + |  | ||||||
|             "                132\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4276,\n" + |  | ||||||
|             "                2678\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9486\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                340,\n" + |  | ||||||
|             "                145\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4565,\n" + |  | ||||||
|             "                2982\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9486\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                335,\n" + |  | ||||||
|             "                142\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3695,\n" + |  | ||||||
|             "                3360\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9475\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                336,\n" + |  | ||||||
|             "                145\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4446,\n" + |  | ||||||
|             "                3357\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9473\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                338,\n" + |  | ||||||
|             "                140\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4248,\n" + |  | ||||||
|             "                2803\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9466\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                343,\n" + |  | ||||||
|             "                155\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4565,\n" + |  | ||||||
|             "                3769\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9464\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                346,\n" + |  | ||||||
|             "                148\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4233,\n" + |  | ||||||
|             "                2925\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9462\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                327,\n" + |  | ||||||
|             "                159\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4000,\n" + |  | ||||||
|             "                2484\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.946\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                336,\n" + |  | ||||||
|             "                145\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4906,\n" + |  | ||||||
|             "                2908\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9457\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                339,\n" + |  | ||||||
|             "                150\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3618,\n" + |  | ||||||
|             "                3477\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9456\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                318,\n" + |  | ||||||
|             "                147\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                5241,\n" + |  | ||||||
|             "                3883\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9448\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                328,\n" + |  | ||||||
|             "                147\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4934,\n" + |  | ||||||
|             "                3702\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.943\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                312,\n" + |  | ||||||
|             "                142\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3633,\n" + |  | ||||||
|             "                2557\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9428\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                340,\n" + |  | ||||||
|             "                137\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4576,\n" + |  | ||||||
|             "                2856\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9406\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                335,\n" + |  | ||||||
|             "                138\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4316,\n" + |  | ||||||
|             "                2548\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9398\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                345,\n" + |  | ||||||
|             "                146\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4890,\n" + |  | ||||||
|             "                3829\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9378\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                332,\n" + |  | ||||||
|             "                153\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4126,\n" + |  | ||||||
|             "                3304\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9371\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                325,\n" + |  | ||||||
|             "                137\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3581,\n" + |  | ||||||
|             "                2944\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9318\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                320,\n" + |  | ||||||
|             "                145\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3879,\n" + |  | ||||||
|             "                3123\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9304\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                343,\n" + |  | ||||||
|             "                143\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4601,\n" + |  | ||||||
|             "                3645\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9258\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                335,\n" + |  | ||||||
|             "                142\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4673,\n" + |  | ||||||
|             "                3528\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9255\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                312,\n" + |  | ||||||
|             "                144\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4800,\n" + |  | ||||||
|             "                3411\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.923\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                337,\n" + |  | ||||||
|             "                139\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4016,\n" + |  | ||||||
|             "                3412\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9225\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                340,\n" + |  | ||||||
|             "                141\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4605,\n" + |  | ||||||
|             "                2729\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9191\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                298,\n" + |  | ||||||
|             "                325\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3249,\n" + |  | ||||||
|             "                2576\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9185\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                338,\n" + |  | ||||||
|             "                156\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4537,\n" + |  | ||||||
|             "                2451\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9118\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                334,\n" + |  | ||||||
|             "                143\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4933,\n" + |  | ||||||
|             "                2783\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9114\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                339,\n" + |  | ||||||
|             "                141\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4464,\n" + |  | ||||||
|             "                2308\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9107\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                343,\n" + |  | ||||||
|             "                143\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3890,\n" + |  | ||||||
|             "                3000\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.9064\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                313,\n" + |  | ||||||
|             "                139\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3593,\n" + |  | ||||||
|             "                2810\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.902\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                259,\n" + |  | ||||||
|             "                131\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                4000,\n" + |  | ||||||
|             "                2755\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.8869\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                345,\n" + |  | ||||||
|             "                149\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3901,\n" + |  | ||||||
|             "                2864\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.8841\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                345,\n" + |  | ||||||
|             "                150\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                3945,\n" + |  | ||||||
|             "                2610\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.8632\n" + |  | ||||||
|             "        },\n" + |  | ||||||
|             "        {\n" + |  | ||||||
|             "            \"type\": \"pho\",\n" + |  | ||||||
|             "            \"size\": [\n" + |  | ||||||
|             "                199,\n" + |  | ||||||
|             "                110\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"leftTopPoint\": [\n" + |  | ||||||
|             "                5166,\n" + |  | ||||||
|             "                3661\n" + |  | ||||||
|             "            ],\n" + |  | ||||||
|             "            \"score\": 0.8225\n" + |  | ||||||
|             "        }\n" + |  | ||||||
|             "    ]"; |  | ||||||
|         List<SpartaTargetVo> list = JSONUtil.toList(targetStr, SpartaTargetVo.class); |  | ||||||
|         log.info("list:{}", list); |  | ||||||
|         ImageStreamResult imageStreamResult = spartaManager.drawImageToStream(url, list); |  | ||||||
|         log.info("imageStreamResult:{}", imageStreamResult); |  | ||||||
|         try (OutputStream outputStream = new FileOutputStream("D:/images/save.png")) { |  | ||||||
|             byte[] buffer = new byte[4096]; |  | ||||||
|             int bytesRead; |  | ||||||
|             while ((bytesRead = imageStreamResult.getInputStream().read(buffer)) != -1) { |  | ||||||
|                 outputStream.write(buffer, 0, bytesRead); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
|  | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025/7/22 15:36 | ||||||
|  |  */ | ||||||
|  | @SpringBootTest | ||||||
|  | public class ViolationRecordTest { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationRecordService violationRecordService; | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         List<HseViolationRecordCreateDto> list = new ArrayList<>(); | ||||||
|  |         HseViolationRecordCreateDto dto1 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto1.setProjectId(1897160897167638529L); | ||||||
|  |         dto1.setRecognizeId(1937451365735419905L); | ||||||
|  |         dto1.setViolationType("3"); | ||||||
|  |         dto1.setViolationTime(new Date()); | ||||||
|  |         list.add(dto1); | ||||||
|  |         HseViolationRecordCreateDto dto2 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto2.setProjectId(1897160897167638529L); | ||||||
|  |         dto2.setRecognizeId(1937451365735419906L); | ||||||
|  |         dto2.setViolationType("1,2,3"); | ||||||
|  |         dto2.setViolationTime(new Date()); | ||||||
|  |         list.add(dto2); | ||||||
|  |         HseViolationRecordCreateDto dto3 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto3.setProjectId(1897160897167638529L); | ||||||
|  |         dto3.setRecognizeId(1937451365735419907L); | ||||||
|  |         dto3.setViolationType("2,7,8"); | ||||||
|  |         dto3.setViolationTime(new Date()); | ||||||
|  |         list.add(dto3); | ||||||
|  |         HseViolationRecordCreateDto dto4 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto4.setProjectId(1897160897167638529L); | ||||||
|  |         dto4.setRecognizeId(1937451365735419908L); | ||||||
|  |         dto4.setViolationType("5,8"); | ||||||
|  |         dto4.setViolationTime(new Date()); | ||||||
|  |         list.add(dto4); | ||||||
|  |         HseViolationRecordCreateDto dto5 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto5.setProjectId(1897160897167638529L); | ||||||
|  |         dto5.setRecognizeId(1937451365735419909L); | ||||||
|  |         dto5.setViolationType("3,9"); | ||||||
|  |         dto5.setViolationTime(new Date()); | ||||||
|  |         list.add(dto5); | ||||||
|  |         violationRecordService.insertByMonitor(list); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -26,7 +26,7 @@ import java.util.stream.Collectors; | |||||||
|  * @date 2025/6/18 15:59 |  * @date 2025/6/18 15:59 | ||||||
|  */ |  */ | ||||||
| @Slf4j | @Slf4j | ||||||
| //@Component | @Component | ||||||
| public class IncSyncYs7DeviceCapturePicData { | public class IncSyncYs7DeviceCapturePicData { | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ public class FullSyncYs7DeviceData implements CommandLineRunner { | |||||||
|     @Override |     @Override | ||||||
|     public void run(String... args) throws Exception { |     public void run(String... args) throws Exception { | ||||||
|         log.info("开始同步摄像头设备数据"); |         log.info("开始同步摄像头设备数据"); | ||||||
|  |         try { | ||||||
|             List<Ys7QueryDeviceResponseVo> ys7QueryDeviceList = ys7Manager.queryAllDeviceList(); |             List<Ys7QueryDeviceResponseVo> ys7QueryDeviceList = ys7Manager.queryAllDeviceList(); | ||||||
|             Boolean result = ys7DeviceService.saveOrUpdateByDeviceList(ys7QueryDeviceList); |             Boolean result = ys7DeviceService.saveOrUpdateByDeviceList(ys7QueryDeviceList); | ||||||
|             if (result) { |             if (result) { | ||||||
| @ -36,5 +37,9 @@ public class FullSyncYs7DeviceData implements CommandLineRunner { | |||||||
|             } else { |             } else { | ||||||
|                 log.info("没有需要同步的设备"); |                 log.info("没有需要同步的设备"); | ||||||
|             } |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             log.info("摄像头设备数据同步失败", e); | ||||||
|  |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,10 +12,10 @@ import java.util.stream.Collectors; | |||||||
| @Getter | @Getter | ||||||
| public enum RecognizerTypeEnum { | public enum RecognizerTypeEnum { | ||||||
|  |  | ||||||
|     HARDHAT("安全帽识别", "hardhat", ""), |     HARDHAT("安全帽识别", "nohelmet", "1"), | ||||||
|     VEST("反光背心", "vest", "1"), |     VEST("反光背心识别", "novest", ""), | ||||||
|     SMOKING("吸烟识别", "smoking", "3"), |     SMOKING("吸烟识别", "smoking", "3"), | ||||||
|     FIRE("火焰识别", "fire", "2"), |     FIRE("火焰识别", "fire", "16"), | ||||||
|     PHO("光伏板识别", "pho", ""), |     PHO("光伏板识别", "pho", ""), | ||||||
|     SHELVES("光伏板支架识别", "shelves", ""), |     SHELVES("光伏板支架识别", "shelves", ""), | ||||||
|     PILE("光伏板立柱识别", "pile", ""), |     PILE("光伏板立柱识别", "pile", ""), | ||||||
|  | |||||||
| @ -1,24 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:05 |  | ||||||
|  */ |  | ||||||
| public interface SpartaConstant { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * token redis 缓存 key 前缀 |  | ||||||
|      */ |  | ||||||
|     String TOKEN_REDIS_KEY = "sparta:token"; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 获取 token api 路径 |  | ||||||
|      */ |  | ||||||
|     String GET_TOKEN_API_PATH_GET = "/token"; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 识别 api 路径 |  | ||||||
|      */ |  | ||||||
|     String RECOGNIZE_API_PATH_GET = "/api/recognize"; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,170 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager; |  | ||||||
|  |  | ||||||
| import cn.hutool.core.io.FileUtil; |  | ||||||
| import jakarta.annotation.Resource; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| import org.dromara.common.core.exception.ServiceException; |  | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaRecTypeEnum; |  | ||||||
| import org.dromara.manager.spartamanager.vo.ImageStreamResult; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaRecognizeVo; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaTargetVo; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaTokenVo; |  | ||||||
| import org.springframework.data.redis.core.StringRedisTemplate; |  | ||||||
| import org.springframework.stereotype.Component; |  | ||||||
|  |  | ||||||
| import javax.imageio.ImageIO; |  | ||||||
| import java.awt.*; |  | ||||||
| import java.awt.image.BufferedImage; |  | ||||||
| import java.io.ByteArrayInputStream; |  | ||||||
| import java.io.ByteArrayOutputStream; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.net.FileNameMap; |  | ||||||
| import java.net.URI; |  | ||||||
| import java.net.URISyntaxException; |  | ||||||
| import java.net.URLConnection; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.concurrent.TimeUnit; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:27 |  | ||||||
|  */ |  | ||||||
| @Slf4j |  | ||||||
| @Component |  | ||||||
| public class SpartaManager { |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private SpartaProperties spartaProperties; |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private StringRedisTemplate stringRedisTemplate; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 获取token |  | ||||||
|      * |  | ||||||
|      * @return token |  | ||||||
|      */ |  | ||||||
|     public String getToken() { |  | ||||||
|         String token = stringRedisTemplate.opsForValue().get(SpartaConstant.TOKEN_REDIS_KEY); |  | ||||||
|         if (token != null) { |  | ||||||
|             return token; |  | ||||||
|         } |  | ||||||
|         SpartaTokenVo tokenVo = SpartaRequestUtils.getToken( |  | ||||||
|             spartaProperties.getUrl(), |  | ||||||
|             spartaProperties.getClientId(), |  | ||||||
|             spartaProperties.getClientSecret() |  | ||||||
|         ); |  | ||||||
|         token = tokenVo.getToken(); |  | ||||||
|         Long expiresAt = tokenVo.getExpiresAt(); |  | ||||||
|         // 当前时间戳(单位:秒) |  | ||||||
|         long now = System.currentTimeMillis() / 1000; |  | ||||||
|         // 相差秒数 |  | ||||||
|         long diff = expiresAt - now; |  | ||||||
|         if (diff <= 0) { |  | ||||||
|             throw new ServiceException("token已过期"); |  | ||||||
|         } |  | ||||||
|         stringRedisTemplate.opsForValue().set(SpartaConstant.TOKEN_REDIS_KEY, token, (diff - 3600), TimeUnit.SECONDS); |  | ||||||
|         return token; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 识别图片 |  | ||||||
|      * |  | ||||||
|      * @param capUrl      图片地址 |  | ||||||
|      * @param recTypeList 识别类型 |  | ||||||
|      * @param async       是否异步 |  | ||||||
|      * @param callBackUrl 回调地址 |  | ||||||
|      * @param areaHigh    区域高 |  | ||||||
|      * @return 识别结果 |  | ||||||
|      */ |  | ||||||
|     public SpartaRecognizeVo recognize(String capUrl, List<SpartaRecTypeEnum> recTypeList, Boolean async, String callBackUrl, String areaHigh) { |  | ||||||
|         String token = getToken(); |  | ||||||
|         String recType = SpartaRecTypeEnum.joinRecTypes(recTypeList); |  | ||||||
|         return SpartaRequestUtils.recognize( |  | ||||||
|             spartaProperties.getUrl(), |  | ||||||
|             token, |  | ||||||
|             capUrl, |  | ||||||
|             recType, |  | ||||||
|             async, |  | ||||||
|             callBackUrl, |  | ||||||
|             areaHigh |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 识别图片 |  | ||||||
|      * |  | ||||||
|      * @param capUrl      图片地址 |  | ||||||
|      * @param recTypeList 识别类型 |  | ||||||
|      * @return 识别结果 |  | ||||||
|      */ |  | ||||||
|     public SpartaRecognizeVo recognize(String capUrl, List<SpartaRecTypeEnum> recTypeList) { |  | ||||||
|         return recognize(capUrl, recTypeList, false, null, null); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 绘制图片 |  | ||||||
|      * |  | ||||||
|      * @param imgUrl  图片地址 |  | ||||||
|      * @param targets 识别结果 |  | ||||||
|      * @return 绘制后的图片 |  | ||||||
|      */ |  | ||||||
|     public ImageStreamResult drawImageToStream(String imgUrl, List<SpartaTargetVo> targets) throws IOException, URISyntaxException { |  | ||||||
|         // 1. 加载图片 |  | ||||||
|         URI uri = new URI(imgUrl); |  | ||||||
|         BufferedImage image = ImageIO.read(uri.toURL()); |  | ||||||
|         // 2. 开始绘图 |  | ||||||
|         Graphics2D g = image.createGraphics(); |  | ||||||
|         g.setColor(Color.RED); |  | ||||||
|         g.setStroke(new BasicStroke(5)); |  | ||||||
|         // 设置中文兼容字体(或使用指定字体) |  | ||||||
|         g.setFont(new Font("SansSerif", Font.BOLD, 18)); |  | ||||||
|         for (SpartaTargetVo target : targets) { |  | ||||||
|             int x = target.getLeftTopPoint().get(0); |  | ||||||
|             int y = target.getLeftTopPoint().get(1); |  | ||||||
|             int w = target.getSize().get(0); |  | ||||||
|             int h = target.getSize().get(1); |  | ||||||
|             // 画矩形框 |  | ||||||
|             g.drawRect(x, y, w, h); |  | ||||||
|             // 写文字(类型 + 置信度) |  | ||||||
|             String label = target.getType() + " (" + String.format("%.2f", target.getScore()) + ")"; |  | ||||||
|             g.drawString(label, x, y - 5); |  | ||||||
|         } |  | ||||||
|         g.dispose(); |  | ||||||
|         // 3. 输出为 InputStream |  | ||||||
|         ByteArrayOutputStream baos = new ByteArrayOutputStream(); |  | ||||||
|         String filename = extractFilename(imgUrl); |  | ||||||
|         String suffix = FileUtil.getSuffix(filename); |  | ||||||
|         ImageIO.write(image, suffix == null ? "jpg" : suffix, baos); |  | ||||||
|         return new ImageStreamResult(new ByteArrayInputStream(baos.toByteArray()), baos.size(), getContentTypeByFilename(filename)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 提取文件名 |  | ||||||
|      * |  | ||||||
|      * @param url 文件路径 |  | ||||||
|      * @return 文件名 |  | ||||||
|      */ |  | ||||||
|     private static String extractFilename(String url) { |  | ||||||
|         int start = url.lastIndexOf("/") + 1; |  | ||||||
|         int end = url.indexOf("?", start); |  | ||||||
|         if (end == -1) { |  | ||||||
|             return url.substring(start); |  | ||||||
|         } |  | ||||||
|         if (start > 0 && end > start) { |  | ||||||
|             return url.substring(start, end); |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 根据文件名获取文件类型 |  | ||||||
|      * |  | ||||||
|      * @param filename 文件名 |  | ||||||
|      * @return 文件类型 |  | ||||||
|      */ |  | ||||||
|     private static String getContentTypeByFilename(String filename) { |  | ||||||
|         FileNameMap fileNameMap = URLConnection.getFileNameMap(); |  | ||||||
|         return fileNameMap.getContentTypeFor(filename); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,30 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager; |  | ||||||
|  |  | ||||||
| import lombok.Data; |  | ||||||
| import org.springframework.boot.context.properties.ConfigurationProperties; |  | ||||||
| import org.springframework.context.annotation.Configuration; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:01 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Configuration |  | ||||||
| @ConfigurationProperties(prefix = "sparta") |  | ||||||
| public class SpartaProperties { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 请求地址 |  | ||||||
|      */ |  | ||||||
|     private String url; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 客户端id |  | ||||||
|      */ |  | ||||||
|     private String clientId; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 客户端密钥 |  | ||||||
|      */ |  | ||||||
|     private String clientSecret; |  | ||||||
| } |  | ||||||
| @ -1,110 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager; |  | ||||||
|  |  | ||||||
| import cn.hutool.http.HttpRequest; |  | ||||||
| import cn.hutool.http.HttpResponse; |  | ||||||
| import cn.hutool.http.HttpStatus; |  | ||||||
| import cn.hutool.json.JSONObject; |  | ||||||
| import cn.hutool.json.JSONUtil; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| import org.dromara.common.core.exception.ServiceException; |  | ||||||
| import org.dromara.common.core.utils.StringUtils; |  | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaHasTargetEnum; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaRecognizeVo; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaTargetVo; |  | ||||||
| import org.dromara.manager.spartamanager.vo.SpartaTokenVo; |  | ||||||
|  |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:06 |  | ||||||
|  */ |  | ||||||
| @Slf4j |  | ||||||
| public class SpartaRequestUtils { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 获取斯巴达 Token |  | ||||||
|      * |  | ||||||
|      * @param host         域名 |  | ||||||
|      * @param clientId     客户端id |  | ||||||
|      * @param clientSecret 客户端密钥 |  | ||||||
|      * @return token |  | ||||||
|      */ |  | ||||||
|     public static SpartaTokenVo getToken(String host, String clientId, String clientSecret) { |  | ||||||
|         HashMap<String, Object> paramMap = new HashMap<>(); |  | ||||||
|         paramMap.put("clientId", clientId); |  | ||||||
|         paramMap.put("clientSecret", clientSecret); |  | ||||||
|         String errorMsg = "斯巴达 Token 请求失败"; |  | ||||||
|         String url = host + SpartaConstant.GET_TOKEN_API_PATH_GET; |  | ||||||
|         try (HttpResponse response = HttpRequest.get(url) |  | ||||||
|             .form(paramMap) |  | ||||||
|             .execute()) { |  | ||||||
|             if (!response.isOk()) { |  | ||||||
|                 log.error("{}:{}", errorMsg, response.getStatus()); |  | ||||||
|                 throw new ServiceException(errorMsg + response.getStatus()); |  | ||||||
|             } |  | ||||||
|             String body = response.body(); |  | ||||||
|             if (body == null) { |  | ||||||
|                 log.error("{}:{}", errorMsg, "返回参数为空"); |  | ||||||
|             } |  | ||||||
|             log.info("斯巴达 Token 请求成功:{}", body); |  | ||||||
|             JSONObject jsonObject = JSONUtil.parseObj(body); |  | ||||||
|             SpartaTokenVo tokenVo = new SpartaTokenVo(); |  | ||||||
|             tokenVo.setToken(jsonObject.get("token", String.class)); |  | ||||||
|             tokenVo.setExpiresAt(jsonObject.get("expires_at", Long.class)); |  | ||||||
|             return tokenVo; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 识别图片 |  | ||||||
|      * |  | ||||||
|      * @param host        域名 |  | ||||||
|      * @param token       token |  | ||||||
|      * @param capUrl      在线图片地址 |  | ||||||
|      * @param recType     识别算法模型,多选模式每个参数之间用空格隔开例 |  | ||||||
|      * @param async       是否异步处理 |  | ||||||
|      * @param callBackUrl 回调地址(Post) |  | ||||||
|      * @param areaHigh    高空识别项目,格式为:勾选范围的左上角x,y坐标以及宽,高,中间用空格隔开 |  | ||||||
|      * @return 识别结果 |  | ||||||
|      */ |  | ||||||
|     public static SpartaRecognizeVo recognize(String host, String token, String capUrl, |  | ||||||
|                                               String recType, Boolean async, String callBackUrl, String areaHigh) { |  | ||||||
|         if (StringUtils.isAnyBlank(host, token, capUrl)) { |  | ||||||
|             throw new ServiceException("斯巴达识别图片参数为空", HttpStatus.HTTP_BAD_REQUEST); |  | ||||||
|         } |  | ||||||
|         HashMap<String, Object> paramMap = new HashMap<>(); |  | ||||||
|         paramMap.put("capUrl", capUrl); |  | ||||||
|         paramMap.put("recType", recType); |  | ||||||
|         paramMap.put("async", async != null && async ? "True" : "False"); |  | ||||||
|         paramMap.put("callBackUrl", callBackUrl); |  | ||||||
|         paramMap.put("area_high", areaHigh); |  | ||||||
|         String errorMsg = "斯巴达识别图片请求失败"; |  | ||||||
|         String url = host + SpartaConstant.RECOGNIZE_API_PATH_GET; |  | ||||||
|         try (HttpResponse response = HttpRequest.get(url) |  | ||||||
|             .header("Authorization", "Basic " + token) |  | ||||||
|             .form(paramMap) |  | ||||||
|             .execute()) { |  | ||||||
|             if (!response.isOk()) { |  | ||||||
|                 log.error("{}:{}", errorMsg, response.getStatus()); |  | ||||||
|                 throw new ServiceException(errorMsg + response.getStatus()); |  | ||||||
|             } |  | ||||||
|             String body = response.body(); |  | ||||||
|             if (body == null) { |  | ||||||
|                 log.error("{}:{}", errorMsg, "返回参数为空"); |  | ||||||
|             } |  | ||||||
|             JSONObject result = JSONUtil.parseObj(response.body()); |  | ||||||
|             log.info("斯巴达识别图片请求成功:{}", body); |  | ||||||
|             SpartaRecognizeVo spartaRecognizeVo = new SpartaRecognizeVo(); |  | ||||||
|             Integer hasTarget = result.getInt("hasTarget"); |  | ||||||
|             spartaRecognizeVo.setHasTarget(hasTarget); |  | ||||||
|             if (hasTarget.equals(SpartaHasTargetEnum.YES.getValue())) { |  | ||||||
|                 spartaRecognizeVo.setOriginalImgSize(result.getJSONArray("originalImgSize").toList(Integer.class)); |  | ||||||
|                 List<SpartaTargetVo> targetList = JSONUtil.toList(result.getJSONArray("targets"), SpartaTargetVo.class); |  | ||||||
|                 spartaRecognizeVo.setTargets(targetList); |  | ||||||
|             } |  | ||||||
|             return spartaRecognizeVo; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.enums; |  | ||||||
|  |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/23 9:51 |  | ||||||
|  */ |  | ||||||
| @Getter |  | ||||||
| public enum SpartaHasTargetEnum { |  | ||||||
|  |  | ||||||
|     YES("是", 1), |  | ||||||
|     NO("否", 0); |  | ||||||
|  |  | ||||||
|     private final String text; |  | ||||||
|     private final int value; |  | ||||||
|  |  | ||||||
|     SpartaHasTargetEnum(String text, int value) { |  | ||||||
|         this.text = text; |  | ||||||
|         this.value = value; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.enums; |  | ||||||
|  |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.stream.Collectors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/23 9:42 |  | ||||||
|  */ |  | ||||||
| @Getter |  | ||||||
| public enum SpartaRecTypeEnum { |  | ||||||
|  |  | ||||||
|     HAT("安全帽识别", "hat", ""), |  | ||||||
|     HEAD("不戴安全帽识别", "head", "1"), |  | ||||||
|     SMOKE("吸烟识别", "smoke", "3"), |  | ||||||
|     BELT("安全带识别", "belt", "2"), |  | ||||||
|     WASTE("工程垃圾识别(暂无)", "waste", ""), |  | ||||||
|     EXCAVATOR("挖掘机", "excavator", ""), |  | ||||||
|     ROLLER("压路机", "Roller", ""), |  | ||||||
|     TRUCK_CRANE("汽车吊", "Truck_crane", ""), |  | ||||||
|     LOADER("装载机", "Loader", ""), |  | ||||||
|     SUBMERSIBLE_DRILLING_RIG("潜挖钻机", "Submersible_drilling_rig", ""), |  | ||||||
|     SPRINKLER("洒水车", "Sprinkler", ""), |  | ||||||
|     TRUCK_MOUNTED_CRANE("随车吊", "Truck_mounted_crane", ""), |  | ||||||
|     TRUCK("货车", "Truck", ""), |  | ||||||
|     PHO("光伏板", "pho", ""), |  | ||||||
|     HOLE("洞", "hole", ""), |  | ||||||
|     SHELVES("架子", "shelves", ""), |  | ||||||
|     PILE("桩", "pile", ""); |  | ||||||
|  |  | ||||||
|     private final String text; |  | ||||||
|  |  | ||||||
|     private final String value; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 描述:对应字典violation_level_type |  | ||||||
|      */ |  | ||||||
|     private final String code; |  | ||||||
|  |  | ||||||
|     SpartaRecTypeEnum(String text, String value, String code) { |  | ||||||
|         this.text = text; |  | ||||||
|         this.value = value; |  | ||||||
|         this.code = code; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static SpartaRecTypeEnum fromValue(String value) { |  | ||||||
|         for (SpartaRecTypeEnum type : SpartaRecTypeEnum.values()) { |  | ||||||
|             if (type.getValue().equals(value)) { |  | ||||||
|                 return type; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 将多个 SpartaRecTypeEnum 拼接为接口识别参数字符串(空格分隔) |  | ||||||
|      * 示例:hat belt Truck |  | ||||||
|      */ |  | ||||||
|     public static String joinRecTypes(List<SpartaRecTypeEnum> types) { |  | ||||||
|         if (types == null || types.isEmpty()) { |  | ||||||
|             return ""; |  | ||||||
|         } |  | ||||||
|         return types.stream() |  | ||||||
|             .map(SpartaRecTypeEnum::getValue) |  | ||||||
|             .collect(Collectors.joining(" ")); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.vo; |  | ||||||
|  |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Data; |  | ||||||
|  |  | ||||||
| import java.io.InputStream; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/23 14:44 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class ImageStreamResult { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 图片输入流 |  | ||||||
|      */ |  | ||||||
|     private InputStream inputStream; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 图片长度 |  | ||||||
|      */ |  | ||||||
|     private long length; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 图片类型 |  | ||||||
|      */ |  | ||||||
|     private String contentType; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,29 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.vo; |  | ||||||
|  |  | ||||||
| import lombok.Data; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:25 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| public class SpartaRecognizeVo { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 是否监测到目标:1:是;0:否 |  | ||||||
|      */ |  | ||||||
|     private Integer hasTarget; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 原始图片尺寸([宽,高]),ex:[1920,1080] |  | ||||||
|      */ |  | ||||||
|     private List<Integer> originalImgSize; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 目标信息 |  | ||||||
|      */ |  | ||||||
|     private List<SpartaTargetVo> targets; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.vo; |  | ||||||
|  |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.NoArgsConstructor; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/23 11:22 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @NoArgsConstructor |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class SpartaTargetVo { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 目标类型 |  | ||||||
|      */ |  | ||||||
|     private String type; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 目标外接矩形像素 |  | ||||||
|      */ |  | ||||||
|     private List<Integer> size; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 目标在画面中左上角位置信息 |  | ||||||
|      */ |  | ||||||
|     private List<Integer> leftTopPoint; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 置信度得分(0~1) |  | ||||||
|      */ |  | ||||||
|     private Double score; |  | ||||||
| } |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| package org.dromara.manager.spartamanager.vo; |  | ||||||
|  |  | ||||||
| import lombok.Data; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lcj |  | ||||||
|  * @date 2025/6/20 19:36 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| public class SpartaTokenVo { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * token |  | ||||||
|      */ |  | ||||||
|     private String token; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 过期时间 |  | ||||||
|      */ |  | ||||||
|     private Long expiresAt; |  | ||||||
| } |  | ||||||
| @ -20,8 +20,6 @@ import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum; | |||||||
| import org.dromara.manager.recognizermanager.vo.RecognizeImageStreamResult; | import org.dromara.manager.recognizermanager.vo.RecognizeImageStreamResult; | ||||||
| import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo; | import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo; | ||||||
| import org.dromara.manager.recognizermanager.vo.RecognizeVo; | import org.dromara.manager.recognizermanager.vo.RecognizeVo; | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaHasTargetEnum; |  | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaRecTypeEnum; |  | ||||||
| import org.dromara.other.constant.Ys7DeviceImgConstant; | import org.dromara.other.constant.Ys7DeviceImgConstant; | ||||||
| import org.dromara.other.domain.OthYs7DeviceImg; | import org.dromara.other.domain.OthYs7DeviceImg; | ||||||
| import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture; | import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture; | ||||||
| @ -180,7 +178,7 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl<OthYs7DeviceImgMappe | |||||||
|                 vo.setUrl(deviceImg.getRecognizeUrl()); |                 vo.setUrl(deviceImg.getRecognizeUrl()); | ||||||
|             } |             } | ||||||
|             List<String> recTypeList = JSONUtil.toList(deviceImg.getRecType(), String.class); |             List<String> recTypeList = JSONUtil.toList(deviceImg.getRecType(), String.class); | ||||||
|             List<String> list = recTypeList.stream().map(recType -> Objects.requireNonNull(SpartaRecTypeEnum.fromValue(recType)).getText()).toList(); |             List<String> list = recTypeList.stream().map(recType -> Objects.requireNonNull(RecognizerTypeEnum.fromValue(recType)).getText()).toList(); | ||||||
|             vo.setRecTypeList(list); |             vo.setRecTypeList(list); | ||||||
|             return vo; |             return vo; | ||||||
|         }).toList(); |         }).toList(); | ||||||
| @ -214,7 +212,7 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl<OthYs7DeviceImgMappe | |||||||
|                 // 将抓取的图片进行识别 |                 // 将抓取的图片进行识别 | ||||||
|                 List<RecognizerTypeEnum> recTypes = List.of(RecognizerTypeEnum.HARDHAT, RecognizerTypeEnum.SMOKING, RecognizerTypeEnum.FIRE); |                 List<RecognizerTypeEnum> recTypes = List.of(RecognizerTypeEnum.HARDHAT, RecognizerTypeEnum.SMOKING, RecognizerTypeEnum.FIRE); | ||||||
|                 RecognizeVo recognizeVo = recognizerManager.recognize(ossUrl, recTypes); |                 RecognizeVo recognizeVo = recognizerManager.recognize(ossUrl, recTypes); | ||||||
|                 if (recognizeVo != null && recognizeVo.getHasTarget().equals(SpartaHasTargetEnum.YES.getValue())) { |                 if (recognizeVo != null && recognizeVo.getHasTarget().equals(RecognizerHasTargetEnum.YES.getValue())) { | ||||||
|                     // 记录识别信息 |                     // 记录识别信息 | ||||||
|                     HseRecognizeRecordCreateDto record = new HseRecognizeRecordCreateDto(); |                     HseRecognizeRecordCreateDto record = new HseRecognizeRecordCreateDto(); | ||||||
|                     record.setCreateTime(new Date()); |                     record.setCreateTime(new Date()); | ||||||
|  | |||||||
| @ -31,4 +31,6 @@ public interface HseSafetyConstant { | |||||||
|         return String.format("安全生产监督检查通知书(%s).docx", createDate); |         return String.format("安全生产监督检查通知书(%s).docx", createDate); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     String VIOLATION_LEVEL_TYPE = "violation_level_type"; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,81 @@ | |||||||
|  | package org.dromara.safety.controller; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import jakarta.validation.constraints.NotEmpty; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import org.dromara.common.core.domain.R; | ||||||
|  | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
|  | import org.dromara.common.log.annotation.Log; | ||||||
|  | import org.dromara.common.log.enums.BusinessType; | ||||||
|  | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
|  | import org.dromara.common.web.core.BaseController; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateHandlerReq; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordQueryReq; | ||||||
|  | import org.dromara.safety.domain.vo.violationrecord.HseViolationRecordVo; | ||||||
|  | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录 | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | @Validated | ||||||
|  | @RestController | ||||||
|  | @RequestMapping("/safety/violationRecord") | ||||||
|  | public class HseViolationRecordController extends BaseController { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationRecordService hseViolationRecordService; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询违规记录列表 | ||||||
|  |      */ | ||||||
|  |     @SaCheckPermission("safety:violationRecord:list") | ||||||
|  |     @GetMapping("/list") | ||||||
|  |     public TableDataInfo<HseViolationRecordVo> list(HseViolationRecordQueryReq req, PageQuery pageQuery) { | ||||||
|  |         return hseViolationRecordService.queryPageList(req, pageQuery); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录详细信息 | ||||||
|  |      * | ||||||
|  |      * @param id 主键 | ||||||
|  |      */ | ||||||
|  |     @SaCheckPermission("safety:violationRecord:query") | ||||||
|  |     @GetMapping("/{id}") | ||||||
|  |     public R<HseViolationRecordVo> getInfo(@NotNull(message = "主键不能为空") | ||||||
|  |                                            @PathVariable Long id) { | ||||||
|  |         return R.ok(hseViolationRecordService.queryById(id)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新增违规记录处理人 | ||||||
|  |      */ | ||||||
|  |     @SaCheckPermission("safety:violationRecord:insertHandler") | ||||||
|  |     @Log(title = "违规记录", businessType = BusinessType.INSERT) | ||||||
|  |     @RepeatSubmit() | ||||||
|  |     @PostMapping("/handler") | ||||||
|  |     public R<Void> insertHandler(@Validated @RequestBody HseViolationRecordCreateHandlerReq req) { | ||||||
|  |         return toAjax(hseViolationRecordService.insertHandler(req)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除违规记录 | ||||||
|  |      * | ||||||
|  |      * @param ids 主键串 | ||||||
|  |      */ | ||||||
|  |     @SaCheckPermission("safety:violationRecord:remove") | ||||||
|  |     @Log(title = "违规记录", businessType = BusinessType.DELETE) | ||||||
|  |     @DeleteMapping("/{ids}") | ||||||
|  |     public R<Void> remove(@NotEmpty(message = "主键不能为空") | ||||||
|  |                           @PathVariable Long[] ids) { | ||||||
|  |         return toAjax(hseViolationRecordService.deleteWithValidByIds(List.of(ids))); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,112 @@ | |||||||
|  | package org.dromara.safety.domain; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableId; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  | import org.dromara.common.mybatis.core.domain.BaseEntity; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录对象 hse_violation_record | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | @TableName("hse_violation_record") | ||||||
|  | public class HseViolationRecord extends BaseEntity { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 主键id | ||||||
|  |      */ | ||||||
|  |     @TableId(value = "id") | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 项目id | ||||||
|  |      */ | ||||||
|  |     private Long projectId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章等级id | ||||||
|  |      */ | ||||||
|  |     private Long levelId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 识别记录id | ||||||
|  |      */ | ||||||
|  |     private Long recognizeId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章类型 | ||||||
|  |      */ | ||||||
|  |     private String violationType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章时间 | ||||||
|  |      */ | ||||||
|  |     private Date violationTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章处理人id | ||||||
|  |      */ | ||||||
|  |     private Long handlerId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理期限 | ||||||
|  |      */ | ||||||
|  |     private Date disposeDeadline; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理时间 | ||||||
|  |      */ | ||||||
|  |     private Date disposeTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 整改措施 | ||||||
|  |      */ | ||||||
|  |     private String measure; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 整改时间 | ||||||
|  |      */ | ||||||
|  |     private Date rectificationTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查情况 | ||||||
|  |      */ | ||||||
|  |     private String review; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查状态(1通过 2未通过) | ||||||
|  |      */ | ||||||
|  |     private String reviewType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查时间 | ||||||
|  |      */ | ||||||
|  |     private Date reviewTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理流程类型(0仅通知 1通知整改复查) | ||||||
|  |      */ | ||||||
|  |     private String processType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 工单状态(1通知 2整改 3复查) | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -48,6 +48,7 @@ public class HseViolationLevelCreateReq implements Serializable { | |||||||
|     /** |     /** | ||||||
|      * 违章类型(多个逗号分隔) |      * 违章类型(多个逗号分隔) | ||||||
|      */ |      */ | ||||||
|  |     @NotNull(message = "违章类型不能为空") | ||||||
|     private String violationType; |     private String violationType; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,44 @@ | |||||||
|  | package org.dromara.safety.domain.dto.violationrecord; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025/7/22 14:28 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class HseViolationRecordCreateDto implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 5895177891570353747L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 项目id | ||||||
|  |      */ | ||||||
|  |     private Long projectId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 识别记录id | ||||||
|  |      */ | ||||||
|  |     private Long recognizeId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章类型 | ||||||
|  |      */ | ||||||
|  |     private String violationType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章时间 | ||||||
|  |      */ | ||||||
|  |     private Date violationTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,49 @@ | |||||||
|  | package org.dromara.safety.domain.dto.violationrecord; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonFormat; | ||||||
|  | import jakarta.validation.constraints.Future; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import lombok.Data; | ||||||
|  | import org.springframework.format.annotation.DateTimeFormat; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025/7/22 11:07 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class HseViolationRecordCreateHandlerReq implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = -5274907523390625095L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 主键id | ||||||
|  |      */ | ||||||
|  |     @NotNull(message = "id不能为空") | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章处理人id | ||||||
|  |      */ | ||||||
|  |     @NotNull(message = "处理人不能为空") | ||||||
|  |     private Long handlerId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理期限 | ||||||
|  |      */ | ||||||
|  |     @NotNull(message = "处理期限不能为空") | ||||||
|  |     @Future(message = "处理期限不能小于当前时间") | ||||||
|  |     @DateTimeFormat(pattern = "yyyy-MM-dd") | ||||||
|  |     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") | ||||||
|  |     private Date disposeDeadline; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | package org.dromara.safety.domain.dto.violationrecord; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import org.springframework.format.annotation.DateTimeFormat; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025/7/22 11:06 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class HseViolationRecordQueryReq implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1084576574388146447L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 主键id | ||||||
|  |      */ | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 项目id | ||||||
|  |      */ | ||||||
|  |     private Long projectId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章类型 | ||||||
|  |      */ | ||||||
|  |     private String violationType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章时间 | ||||||
|  |      */ | ||||||
|  |     @DateTimeFormat(pattern = "yyyy-MM-dd") | ||||||
|  |     private Date violationTime; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,145 @@ | |||||||
|  | package org.dromara.safety.domain.vo.violationrecord; | ||||||
|  |  | ||||||
|  | import io.github.linpeilie.annotations.AutoMapper; | ||||||
|  | import lombok.Data; | ||||||
|  | import org.dromara.common.translation.annotation.Translation; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.safety.domain.HseViolationRecord; | ||||||
|  | import org.dromara.safety.domain.vo.recognizerecord.HseRecognizeRecordVo; | ||||||
|  | import org.dromara.safety.domain.vo.violationlevel.HseViolationLevelVo; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录视图对象 hse_violation_record | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @AutoMapper(target = HseViolationRecord.class) | ||||||
|  | public class HseViolationRecordVo implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 主键id | ||||||
|  |      */ | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 项目id | ||||||
|  |      */ | ||||||
|  |     private Long projectId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章等级id | ||||||
|  |      */ | ||||||
|  |     private Long levelId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章等级 | ||||||
|  |      */ | ||||||
|  |     private HseViolationLevelVo levelVo; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 识别记录id | ||||||
|  |      */ | ||||||
|  |     private Long recognizeId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 识别记录 | ||||||
|  |      */ | ||||||
|  |     private HseRecognizeRecordVo recognizeVo; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章类型 | ||||||
|  |      */ | ||||||
|  |     private String violationType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章时间 | ||||||
|  |      */ | ||||||
|  |     private Date violationTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章处理人id | ||||||
|  |      */ | ||||||
|  |     private Long handlerId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 违章处理人名称 | ||||||
|  |      */ | ||||||
|  |     private String handlerName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理期限 | ||||||
|  |      */ | ||||||
|  |     private Date disposeDeadline; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理时间 | ||||||
|  |      */ | ||||||
|  |     private Date disposeTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 整改措施 | ||||||
|  |      */ | ||||||
|  |     private String measure; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 整改时间 | ||||||
|  |      */ | ||||||
|  |     private Date rectificationTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查情况 | ||||||
|  |      */ | ||||||
|  |     private String review; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查状态(1通过 2未通过) | ||||||
|  |      */ | ||||||
|  |     private String reviewType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 复查时间 | ||||||
|  |      */ | ||||||
|  |     private Date reviewTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理流程类型(0仅通知 1通知整改复查) | ||||||
|  |      */ | ||||||
|  |     private String processType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 工单状态(1通知 2整改 3复查) | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建人 | ||||||
|  |      */ | ||||||
|  |     private Long createBy; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建人名字 | ||||||
|  |      */ | ||||||
|  |     @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") | ||||||
|  |     private String createByName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     private Date createTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,15 @@ | |||||||
|  | package org.dromara.safety.mapper; | ||||||
|  |  | ||||||
|  | import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | ||||||
|  | import org.dromara.safety.domain.HseViolationRecord; | ||||||
|  | import org.dromara.safety.domain.vo.violationrecord.HseViolationRecordVo; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录Mapper接口 | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | public interface HseViolationRecordMapper extends BaseMapperPlus<HseViolationRecord, HseViolationRecordVo> { | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -79,7 +79,15 @@ public interface IHseViolationLevelService extends IService<HseViolationLevel> { | |||||||
|      * @param violationLevel 违章等级对象 |      * @param violationLevel 违章等级对象 | ||||||
|      * @return 违章等级视图对象 |      * @return 违章等级视图对象 | ||||||
|      */ |      */ | ||||||
|     HseViolationLevelByPostVo getVo(HseViolationLevel violationLevel); |     HseViolationLevelByPostVo getByPostVo(HseViolationLevel violationLevel); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违章等级视图对象 | ||||||
|  |      * | ||||||
|  |      * @param violationLevel 违章等级对象 | ||||||
|  |      * @return 违章等级视图对象 | ||||||
|  |      */ | ||||||
|  |     HseViolationLevelVo getVo(HseViolationLevel violationLevel); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获取违章等级查询条件封装 |      * 获取违章等级查询条件封装 | ||||||
|  | |||||||
| @ -0,0 +1,97 @@ | |||||||
|  | package org.dromara.safety.service; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
|  | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
|  | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
|  | import org.dromara.safety.domain.HseViolationRecord; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateHandlerReq; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordQueryReq; | ||||||
|  | import org.dromara.safety.domain.vo.violationrecord.HseViolationRecordVo; | ||||||
|  |  | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录Service接口 | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | public interface IHseViolationRecordService extends IService<HseViolationRecord> { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询违规记录 | ||||||
|  |      * | ||||||
|  |      * @param id 主键 | ||||||
|  |      * @return 违规记录 | ||||||
|  |      */ | ||||||
|  |     HseViolationRecordVo queryById(Long id); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 分页查询违规记录列表 | ||||||
|  |      * | ||||||
|  |      * @param req       查询条件 | ||||||
|  |      * @param pageQuery 分页参数 | ||||||
|  |      * @return 违规记录分页列表 | ||||||
|  |      */ | ||||||
|  |     TableDataInfo<HseViolationRecordVo> queryPageList(HseViolationRecordQueryReq req, PageQuery pageQuery); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询符合条件的违规记录列表 | ||||||
|  |      * | ||||||
|  |      * @param req 查询条件 | ||||||
|  |      * @return 违规记录列表 | ||||||
|  |      */ | ||||||
|  |     List<HseViolationRecordVo> queryList(HseViolationRecordQueryReq req); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新增违规记录信息 | ||||||
|  |      * | ||||||
|  |      * @param dto 违规记录信息 | ||||||
|  |      */ | ||||||
|  |     void insertByMonitor(List<HseViolationRecordCreateDto> dto); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新增违章处理人 | ||||||
|  |      * | ||||||
|  |      * @param req 违章处理人 | ||||||
|  |      * @return 是否新增成功 | ||||||
|  |      */ | ||||||
|  |     Boolean insertHandler(HseViolationRecordCreateHandlerReq req); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 批量删除违规记录信息 | ||||||
|  |      * | ||||||
|  |      * @param ids 待删除的主键集合 | ||||||
|  |      * @return 是否删除成功 | ||||||
|  |      */ | ||||||
|  |     Boolean deleteWithValidByIds(Collection<Long> ids); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录视图对象 | ||||||
|  |      * | ||||||
|  |      * @param violationRecord 违规记录对象 | ||||||
|  |      * @return 违规记录视图对象 | ||||||
|  |      */ | ||||||
|  |     HseViolationRecordVo getVo(HseViolationRecord violationRecord); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录查询条件封装 | ||||||
|  |      * | ||||||
|  |      * @param req 违规记录查询条件 | ||||||
|  |      * @return 违规记录查询条件封装 | ||||||
|  |      */ | ||||||
|  |     LambdaQueryWrapper<HseViolationRecord> buildQueryWrapper(HseViolationRecordQueryReq req); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录分页对象视图 | ||||||
|  |      * | ||||||
|  |      * @param violationRecordPage 违规记录分页对象 | ||||||
|  |      * @return 违规记录分页对象视图 | ||||||
|  |      */ | ||||||
|  |     Page<HseViolationRecordVo> getVoPage(Page<HseViolationRecord> violationRecordPage); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -12,15 +12,17 @@ import org.dromara.common.core.utils.StringUtils; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.satoken.utils.LoginHelper; | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum; | ||||||
| import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo; | import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo; | ||||||
| import org.dromara.manager.spartamanager.enums.SpartaRecTypeEnum; |  | ||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
| import org.dromara.safety.domain.HseRecognizeRecord; | import org.dromara.safety.domain.HseRecognizeRecord; | ||||||
| import org.dromara.safety.domain.dto.recognizerecord.HseRecognizeRecordCreateDto; | import org.dromara.safety.domain.dto.recognizerecord.HseRecognizeRecordCreateDto; | ||||||
| import org.dromara.safety.domain.dto.recognizerecord.HseRecognizeRecordQueryReq; | import org.dromara.safety.domain.dto.recognizerecord.HseRecognizeRecordQueryReq; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
| import org.dromara.safety.domain.vo.recognizerecord.HseRecognizeRecordVo; | import org.dromara.safety.domain.vo.recognizerecord.HseRecognizeRecordVo; | ||||||
| import org.dromara.safety.mapper.HseRecognizeRecordMapper; | import org.dromara.safety.mapper.HseRecognizeRecordMapper; | ||||||
| import org.dromara.safety.service.IHseRecognizeRecordService; | import org.dromara.safety.service.IHseRecognizeRecordService; | ||||||
|  | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
| @ -46,6 +48,9 @@ public class HseRecognizeRecordServiceImpl extends ServiceImpl<HseRecognizeRecor | |||||||
|     @Resource |     @Resource | ||||||
|     private IBusProjectService projectService; |     private IBusProjectService projectService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationRecordService violationRecordService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询识别记录 |      * 查询识别记录 | ||||||
|      * |      * | ||||||
| @ -110,8 +115,8 @@ public class HseRecognizeRecordServiceImpl extends ServiceImpl<HseRecognizeRecor | |||||||
|             List<RecognizeTargetVo> targets = record.getTargets(); |             List<RecognizeTargetVo> targets = record.getTargets(); | ||||||
|             List<String> codeList = targets.stream() |             List<String> codeList = targets.stream() | ||||||
|                 .map(RecognizeTargetVo::getType).distinct() |                 .map(RecognizeTargetVo::getType).distinct() | ||||||
|                 .map(SpartaRecTypeEnum::fromValue).filter(Objects::nonNull) |                 .map(RecognizerTypeEnum::fromValue).filter(Objects::nonNull) | ||||||
|                 .map(SpartaRecTypeEnum::getCode).filter(Objects::nonNull) |                 .map(RecognizerTypeEnum::getCode).filter(Objects::nonNull) | ||||||
|                 .toList(); |                 .toList(); | ||||||
|             String codeStr = String.join(",", codeList); |             String codeStr = String.join(",", codeList); | ||||||
|             entity.setViolationType(codeStr); |             entity.setViolationType(codeStr); | ||||||
| @ -123,6 +128,20 @@ public class HseRecognizeRecordServiceImpl extends ServiceImpl<HseRecognizeRecor | |||||||
|             if (!result) { |             if (!result) { | ||||||
|                 throw new ServiceException("保存识别记录失败"); |                 throw new ServiceException("保存识别记录失败"); | ||||||
|             } |             } | ||||||
|  |             List<HseViolationRecordCreateDto> violationRecordList = new ArrayList<>(); | ||||||
|  |             for (HseRecognizeRecord entity : entityList) { | ||||||
|  |                 HseViolationRecordCreateDto violationRecord = new HseViolationRecordCreateDto(); | ||||||
|  |                 if (entity.getProjectId() != null) { | ||||||
|  |                     violationRecord.setProjectId(entity.getProjectId()); | ||||||
|  |                     violationRecord.setRecognizeId(entity.getId()); | ||||||
|  |                     violationRecord.setViolationType(entity.getViolationType()); | ||||||
|  |                     violationRecord.setViolationTime(entity.getCreateTime()); | ||||||
|  |                     violationRecordList.add(violationRecord); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if (CollUtil.isNotEmpty(violationRecordList)) { | ||||||
|  |                 violationRecordService.insertByMonitor(violationRecordList); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ import org.dromara.common.mybatis.core.page.PageQuery; | |||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.satoken.utils.LoginHelper; | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
|  | import org.dromara.safety.constant.HseSafetyConstant; | ||||||
| import org.dromara.safety.domain.HseViolationLevel; | import org.dromara.safety.domain.HseViolationLevel; | ||||||
| import org.dromara.safety.domain.HseViolationLevelPost; | import org.dromara.safety.domain.HseViolationLevelPost; | ||||||
| import org.dromara.safety.domain.dto.violationlevel.HseViolationLevelCreateReq; | import org.dromara.safety.domain.dto.violationlevel.HseViolationLevelCreateReq; | ||||||
| @ -24,15 +25,14 @@ import org.dromara.safety.mapper.HseViolationLevelMapper; | |||||||
| import org.dromara.safety.service.IHseViolationLevelPostService; | import org.dromara.safety.service.IHseViolationLevelPostService; | ||||||
| import org.dromara.safety.service.IHseViolationLevelService; | import org.dromara.safety.service.IHseViolationLevelService; | ||||||
| import org.dromara.system.domain.vo.SysPostVo; | import org.dromara.system.domain.vo.SysPostVo; | ||||||
| import org.dromara.system.service.ISysPostService; | import org.dromara.system.mapper.SysPostMapper; | ||||||
|  | import org.dromara.system.service.ISysDictDataService; | ||||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.*; | ||||||
| import java.util.HashSet; | import java.util.stream.Collectors; | ||||||
| import java.util.List; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 违章等级Service业务层处理 |  * 违章等级Service业务层处理 | ||||||
| @ -51,7 +51,10 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|     private IHseViolationLevelPostService violationLevelPostService; |     private IHseViolationLevelPostService violationLevelPostService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private ISysPostService postService; |     private SysPostMapper postMapper; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private ISysDictDataService dictDataService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询违章等级 |      * 查询违章等级 | ||||||
| @ -65,7 +68,7 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|         if (violationLevel == null) { |         if (violationLevel == null) { | ||||||
|             throw new ServiceException("违章等级信息不存在", HttpStatus.NOT_FOUND); |             throw new ServiceException("违章等级信息不存在", HttpStatus.NOT_FOUND); | ||||||
|         } |         } | ||||||
|         return this.getVo(violationLevel); |         return this.getByPostVo(violationLevel); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @ -107,6 +110,10 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     public Long insertByBo(HseViolationLevelCreateReq req) { |     public Long insertByBo(HseViolationLevelCreateReq req) { | ||||||
|  |         Long projectId = req.getProjectId(); | ||||||
|  |         if (projectService.getById(projectId) == null) { | ||||||
|  |             throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND); | ||||||
|  |         } | ||||||
|         HseViolationLevel violationLevel = new HseViolationLevel(); |         HseViolationLevel violationLevel = new HseViolationLevel(); | ||||||
|         BeanUtils.copyProperties(req, violationLevel); |         BeanUtils.copyProperties(req, violationLevel); | ||||||
|         // 校验参数 |         // 校验参数 | ||||||
| @ -115,13 +122,47 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|         if (CollUtil.isEmpty(postIdList)) { |         if (CollUtil.isEmpty(postIdList)) { | ||||||
|             throw new ServiceException("岗位不能为空", HttpStatus.BAD_REQUEST); |             throw new ServiceException("岗位不能为空", HttpStatus.BAD_REQUEST); | ||||||
|         } |         } | ||||||
|         // 判断违章等级是否存在 |         // 判断违章等级或风险等级是否存在 | ||||||
|         Long count = this.lambdaQuery() |         List<HseViolationLevel> existList = this.lambdaQuery() | ||||||
|  |             .eq(HseViolationLevel::getProjectId, projectId) | ||||||
|  |             .and(wrapper -> wrapper | ||||||
|                 .eq(HseViolationLevel::getViolationLevel, violationLevel.getViolationLevel()) |                 .eq(HseViolationLevel::getViolationLevel, violationLevel.getViolationLevel()) | ||||||
|             .count(); |                 .or() | ||||||
|         if (count > 0) { |                 .eq(HseViolationLevel::getRiskType, violationLevel.getRiskType()) | ||||||
|  |             ) | ||||||
|  |             .list(); | ||||||
|  |         for (HseViolationLevel exist : existList) { | ||||||
|  |             if (exist.getViolationLevel().equals(violationLevel.getViolationLevel())) { | ||||||
|                 throw new ServiceException("违章等级已存在", HttpStatus.BAD_REQUEST); |                 throw new ServiceException("违章等级已存在", HttpStatus.BAD_REQUEST); | ||||||
|             } |             } | ||||||
|  |             if (exist.getRiskType().equals(violationLevel.getRiskType())) { | ||||||
|  |                 throw new ServiceException("风险等级已存在", HttpStatus.BAD_REQUEST); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // 拆分 violationType | ||||||
|  |         Set<String> violationTypeList = Arrays.stream(req.getViolationType().split(",")) | ||||||
|  |             .map(String::trim) | ||||||
|  |             .filter(s -> !s.isEmpty()) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |         if (CollUtil.isEmpty(violationTypeList)) { | ||||||
|  |             throw new ServiceException("违章类型不能为空", HttpStatus.BAD_REQUEST); | ||||||
|  |         } | ||||||
|  |         // 判断违章类型是否存在 | ||||||
|  |         List<String> allViolationTypeList = this.lambdaQuery() | ||||||
|  |             .select(HseViolationLevel::getViolationType) | ||||||
|  |             .eq(HseViolationLevel::getProjectId, projectId) | ||||||
|  |             .list().stream() | ||||||
|  |             .flatMap(v -> Arrays.stream(v.getViolationType().split(","))) | ||||||
|  |             .map(String::trim) | ||||||
|  |             .distinct() | ||||||
|  |             .toList(); | ||||||
|  |         // 判断是否存在交集(只要一个存在就抛异常) | ||||||
|  |         for (String type : violationTypeList) { | ||||||
|  |             if (allViolationTypeList.contains(type)) { | ||||||
|  |                 String dictLabel = dictDataService.selectDictLabel(HseSafetyConstant.VIOLATION_LEVEL_TYPE, type); | ||||||
|  |                 throw new ServiceException("违章类型 [" + dictLabel + "] 已存在,不能重复添加", HttpStatus.BAD_REQUEST); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         boolean result = this.save(violationLevel); |         boolean result = this.save(violationLevel); | ||||||
|         if (!result) { |         if (!result) { | ||||||
|             throw new ServiceException("新增违章等级失败", HttpStatus.ERROR); |             throw new ServiceException("新增违章等级失败", HttpStatus.ERROR); | ||||||
| @ -158,6 +199,58 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|         if (oldViolationLevel == null) { |         if (oldViolationLevel == null) { | ||||||
|             throw new ServiceException("修改的违章等级信息不存在", HttpStatus.NOT_FOUND); |             throw new ServiceException("修改的违章等级信息不存在", HttpStatus.NOT_FOUND); | ||||||
|         } |         } | ||||||
|  |         // 判断违章等级是否存在 | ||||||
|  |         if (!oldViolationLevel.getViolationLevel().equals(violationLevel.getViolationLevel())) { | ||||||
|  |             Long count = this.lambdaQuery() | ||||||
|  |                 .eq(HseViolationLevel::getProjectId, oldViolationLevel.getProjectId()) | ||||||
|  |                 .eq(HseViolationLevel::getViolationLevel, violationLevel.getViolationLevel()) | ||||||
|  |                 .count(); | ||||||
|  |             if (count > 0) { | ||||||
|  |                 throw new ServiceException("该项目已存在同名违章等级", HttpStatus.CONFLICT); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // 判断风险等级是否存在 | ||||||
|  |         if (!oldViolationLevel.getRiskType().equals(violationLevel.getRiskType())) { | ||||||
|  |             Long count = this.lambdaQuery() | ||||||
|  |                 .eq(HseViolationLevel::getProjectId, oldViolationLevel.getProjectId()) | ||||||
|  |                 .eq(HseViolationLevel::getRiskType, violationLevel.getRiskType()) | ||||||
|  |                 .count(); | ||||||
|  |             if (count > 0) { | ||||||
|  |                 throw new ServiceException("该项目已存在同名风险等级", HttpStatus.CONFLICT); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Set<String> newTypeSet = Arrays.stream(req.getViolationType().split(",")) | ||||||
|  |             .map(String::trim) | ||||||
|  |             .filter(s -> !s.isEmpty()) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |         if (CollUtil.isEmpty(newTypeSet)) { | ||||||
|  |             throw new ServiceException("违章类型不能为空", HttpStatus.BAD_REQUEST); | ||||||
|  |         } | ||||||
|  |         Set<String> oldTypeSet = Arrays.stream(oldViolationLevel.getViolationType().split(",")) | ||||||
|  |             .map(String::trim) | ||||||
|  |             .filter(s -> !s.isEmpty()) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |         // 如果新旧类型完全相同,则不需要校验 | ||||||
|  |         if (!newTypeSet.equals(oldTypeSet)) { | ||||||
|  |             // 查询其他记录的 violationType(排除当前这条记录) | ||||||
|  |             List<String> otherViolationTypes = this.lambdaQuery() | ||||||
|  |                 .select(HseViolationLevel::getViolationType) | ||||||
|  |                 .eq(HseViolationLevel::getProjectId, oldViolationLevel.getProjectId()) | ||||||
|  |                 .ne(HseViolationLevel::getId, id) | ||||||
|  |                 .list().stream() | ||||||
|  |                 .flatMap(v -> Arrays.stream(v.getViolationType().split(","))) | ||||||
|  |                 .map(String::trim) | ||||||
|  |                 .filter(s -> !s.isEmpty()) | ||||||
|  |                 .distinct() | ||||||
|  |                 .toList(); | ||||||
|  |             // 检查是否有交集 | ||||||
|  |             for (String type : newTypeSet) { | ||||||
|  |                 if (otherViolationTypes.contains(type)) { | ||||||
|  |                     String dictLabel = dictDataService.selectDictLabel(HseSafetyConstant.VIOLATION_LEVEL_TYPE, type); | ||||||
|  |                     throw new ServiceException("违章类型 [" + dictLabel + "] 已存在,不能重复添加", HttpStatus.BAD_REQUEST); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         List<Long> postIdList = req.getPostIdList(); |         List<Long> postIdList = req.getPostIdList(); | ||||||
|         if (CollUtil.isNotEmpty(postIdList)) { |         if (CollUtil.isNotEmpty(postIdList)) { | ||||||
|             List<Long> oldPostIdList = violationLevelPostService.lambdaQuery() |             List<Long> oldPostIdList = violationLevelPostService.lambdaQuery() | ||||||
| @ -251,7 +344,7 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|      * @return 违章等级视图对象 |      * @return 违章等级视图对象 | ||||||
|      */ |      */ | ||||||
|     @Override |     @Override | ||||||
|     public HseViolationLevelByPostVo getVo(HseViolationLevel violationLevel) { |     public HseViolationLevelByPostVo getByPostVo(HseViolationLevel violationLevel) { | ||||||
|         HseViolationLevelByPostVo vo = new HseViolationLevelByPostVo(); |         HseViolationLevelByPostVo vo = new HseViolationLevelByPostVo(); | ||||||
|         if (violationLevel == null) { |         if (violationLevel == null) { | ||||||
|             return vo; |             return vo; | ||||||
| @ -262,12 +355,28 @@ public class HseViolationLevelServiceImpl extends ServiceImpl<HseViolationLevelM | |||||||
|             .list(); |             .list(); | ||||||
|         if (CollUtil.isNotEmpty(levelPostList)) { |         if (CollUtil.isNotEmpty(levelPostList)) { | ||||||
|             List<Long> postIdList = levelPostList.stream().map(HseViolationLevelPost::getPost).toList(); |             List<Long> postIdList = levelPostList.stream().map(HseViolationLevelPost::getPost).toList(); | ||||||
|             List<SysPostVo> postList = postService.selectPostByIds(postIdList); |             List<SysPostVo> postList = postMapper.selectVoByIds(postIdList); | ||||||
|             vo.setPostList(postList); |             vo.setPostList(postList); | ||||||
|         } |         } | ||||||
|         return vo; |         return vo; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违章等级视图对象 | ||||||
|  |      * | ||||||
|  |      * @param violationLevel 违章等级对象 | ||||||
|  |      * @return 违章等级视图对象 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public HseViolationLevelVo getVo(HseViolationLevel violationLevel) { | ||||||
|  |         HseViolationLevelVo vo = new HseViolationLevelVo(); | ||||||
|  |         if (violationLevel == null) { | ||||||
|  |             return vo; | ||||||
|  |         } | ||||||
|  |         BeanUtils.copyProperties(violationLevel, vo); | ||||||
|  |         return vo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获取违章等级查询条件封装 |      * 获取违章等级查询条件封装 | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -0,0 +1,361 @@ | |||||||
|  | package org.dromara.safety.service.impl; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
|  | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.HttpStatus; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.common.core.utils.ObjectUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
|  | import org.dromara.common.sse.dto.SseMessageDto; | ||||||
|  | import org.dromara.common.sse.utils.SseMessageUtils; | ||||||
|  | import org.dromara.safety.domain.HseRecognizeRecord; | ||||||
|  | import org.dromara.safety.domain.HseViolationLevel; | ||||||
|  | import org.dromara.safety.domain.HseViolationLevelPost; | ||||||
|  | import org.dromara.safety.domain.HseViolationRecord; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateHandlerReq; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordQueryReq; | ||||||
|  | import org.dromara.safety.domain.vo.violationrecord.HseViolationRecordVo; | ||||||
|  | import org.dromara.safety.mapper.HseViolationRecordMapper; | ||||||
|  | import org.dromara.safety.service.IHseRecognizeRecordService; | ||||||
|  | import org.dromara.safety.service.IHseViolationLevelPostService; | ||||||
|  | import org.dromara.safety.service.IHseViolationLevelService; | ||||||
|  | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.system.service.ISysUserService; | ||||||
|  | import org.springframework.beans.BeanUtils; | ||||||
|  | import org.springframework.context.annotation.Lazy; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.transaction.annotation.Transactional; | ||||||
|  |  | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.time.ZoneId; | ||||||
|  | import java.util.*; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 违规记录Service业务层处理 | ||||||
|  |  * | ||||||
|  |  * @author lcj | ||||||
|  |  * @date 2025-07-22 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service | ||||||
|  | public class HseViolationRecordServiceImpl extends ServiceImpl<HseViolationRecordMapper, HseViolationRecord> | ||||||
|  |     implements IHseViolationRecordService { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private ISysUserService userService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationLevelService violationLevelService; | ||||||
|  |  | ||||||
|  |     @Lazy | ||||||
|  |     @Resource | ||||||
|  |     private IHseRecognizeRecordService recognizeRecordService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationLevelPostService violationLevelPostService; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询违规记录 | ||||||
|  |      * | ||||||
|  |      * @param id 主键 | ||||||
|  |      * @return 违规记录 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public HseViolationRecordVo queryById(Long id) { | ||||||
|  |         HseViolationRecord violationRecord = this.getById(id); | ||||||
|  |         if (violationRecord == null) { | ||||||
|  |             throw new ServiceException("违规记录信息不存在", HttpStatus.NOT_FOUND); | ||||||
|  |         } | ||||||
|  |         return this.getVo(violationRecord); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 分页查询违规记录列表 | ||||||
|  |      * | ||||||
|  |      * @param req       查询条件 | ||||||
|  |      * @param pageQuery 分页参数 | ||||||
|  |      * @return 违规记录分页列表 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public TableDataInfo<HseViolationRecordVo> queryPageList(HseViolationRecordQueryReq req, PageQuery pageQuery) { | ||||||
|  |         Page<HseViolationRecord> violationRecordPage = this.page(pageQuery.build(), this.buildQueryWrapper(req)); | ||||||
|  |         return TableDataInfo.build(this.getVoPage(violationRecordPage)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询符合条件的违规记录列表 | ||||||
|  |      * | ||||||
|  |      * @param req 查询条件 | ||||||
|  |      * @return 违规记录列表 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public List<HseViolationRecordVo> queryList(HseViolationRecordQueryReq req) { | ||||||
|  |         LambdaQueryWrapper<HseViolationRecord> lqw = buildQueryWrapper(req); | ||||||
|  |         return this.list(lqw).stream().map(this::getVo).toList(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新增违规记录信息 | ||||||
|  |      * | ||||||
|  |      * @param dto 违规记录信息 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public void insertByMonitor(List<HseViolationRecordCreateDto> dto) { | ||||||
|  |         if (CollUtil.isEmpty(dto)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         List<HseViolationRecord> violationRecordList = new ArrayList<>(); | ||||||
|  |         // 1. 获取所有相关项目的风险等级配置 | ||||||
|  |         Set<Long> projectIds = dto.stream() | ||||||
|  |             .map(HseViolationRecordCreateDto::getProjectId) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |         List<HseViolationLevel> violationLevelList = violationLevelService.lambdaQuery() | ||||||
|  |             .in(HseViolationLevel::getProjectId, projectIds) | ||||||
|  |             .list(); | ||||||
|  |  | ||||||
|  |         // 2. 构建 "项目 -> (违规类型 -> 等级ID)" 的映射 | ||||||
|  |         Map<Long, Map<String, Long>> projectTypeToLevelIdMap = new HashMap<>(); | ||||||
|  |         for (HseViolationLevel level : violationLevelList) { | ||||||
|  |             Long projectId = level.getProjectId(); | ||||||
|  |             String[] types = level.getViolationType().split(","); | ||||||
|  |             Map<String, Long> typeMap = projectTypeToLevelIdMap.computeIfAbsent(projectId, k -> new HashMap<>()); | ||||||
|  |             for (String type : types) { | ||||||
|  |                 typeMap.put(type.trim(), level.getId()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // 3. 遍历DTO,按LevelId对ViolationType分组,然后创建记录 | ||||||
|  |         for (HseViolationRecordCreateDto dtoItem : dto) { | ||||||
|  |             if (dtoItem.getProjectId() == null) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             Map<String, Long> typeToLevelIdMap = projectTypeToLevelIdMap.get(dtoItem.getProjectId()); | ||||||
|  |             if (typeToLevelIdMap == null) { | ||||||
|  |                 log.warn("项目[{}]中找不到任何违章等级定义", dtoItem.getProjectId()); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             // 创建一个临时Map,用于根据LevelId对本次DTO中的types进行分组 | ||||||
|  |             Map<Long, List<String>> levelIdToTypesMap = new HashMap<>(); | ||||||
|  |             String[] typesFromDto = dtoItem.getViolationType().split(","); | ||||||
|  |             for (String type : typesFromDto) { | ||||||
|  |                 type = type.trim(); | ||||||
|  |                 Long levelId = typeToLevelIdMap.get(type); | ||||||
|  |                 if (levelId == null) { | ||||||
|  |                     log.warn("项目[{}]中找不到违章类型[{}]对应的违章等级", dtoItem.getProjectId(), type); | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 // 将当前type添加到对应levelId的列表中 | ||||||
|  |                 levelIdToTypesMap.computeIfAbsent(levelId, k -> new ArrayList<>()).add(type); | ||||||
|  |             } | ||||||
|  |             // 4. 为每个分组(即每个LevelId)创建一条合并后的记录 | ||||||
|  |             for (Map.Entry<Long, List<String>> entry : levelIdToTypesMap.entrySet()) { | ||||||
|  |                 Long levelId = entry.getKey(); | ||||||
|  |                 List<String> groupedTypesList = entry.getValue(); | ||||||
|  |                 HseViolationRecord record = new HseViolationRecord(); | ||||||
|  |                 record.setProjectId(dtoItem.getProjectId()); | ||||||
|  |                 record.setRecognizeId(dtoItem.getRecognizeId()); | ||||||
|  |                 record.setViolationTime(dtoItem.getViolationTime()); | ||||||
|  |                 record.setRemark(dtoItem.getRemark()); | ||||||
|  |                 record.setLevelId(levelId); // 设置分组的LevelId | ||||||
|  |                 // 将分组后的types用逗号拼接,设置为合并后的ViolationType | ||||||
|  |                 record.setViolationType(String.join(",", groupedTypesList)); | ||||||
|  |                 violationRecordList.add(record); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // 批量保存 | ||||||
|  |         if (CollUtil.isNotEmpty(violationRecordList)) { | ||||||
|  |             violationRecordList.forEach(violationRecord -> violationRecord.setCreateBy(SystemConstants.SUPER_ADMIN_ID)); | ||||||
|  |             boolean result = this.saveBatch(violationRecordList); | ||||||
|  |             if (!result) { | ||||||
|  |                 throw new ServiceException("批量新增违规记录失败,数据库异常", HttpStatus.ERROR); | ||||||
|  |             } | ||||||
|  |             // 通知对应人员 | ||||||
|  |             Set<Long> levelIds = violationRecordList.stream().map(HseViolationRecord::getLevelId).collect(Collectors.toSet()); | ||||||
|  |             List<HseViolationLevelPost> levelPostList = violationLevelPostService.lambdaQuery() | ||||||
|  |                 .in(HseViolationLevelPost::getLevel, levelIds) | ||||||
|  |                 .list(); | ||||||
|  |             List<Long> postIdList = levelPostList.stream().map(HseViolationLevelPost::getPost).distinct().toList(); | ||||||
|  |             List<SysUserVo> userVoList = userService.selectUserListByPostList(postIdList); | ||||||
|  |             if (CollUtil.isNotEmpty(userVoList)) { | ||||||
|  |                 // 通过 sse 向指定用户发送通知 | ||||||
|  |                 Set<Long> userIds = userVoList.stream().map(SysUserVo::getUserId).collect(Collectors.toSet()); | ||||||
|  |                 SseMessageDto messageDto = new SseMessageDto(); | ||||||
|  |                 messageDto.setUserIds(new ArrayList<>(userIds)); | ||||||
|  |                 for (HseViolationRecord violationRecord : violationRecordList) { | ||||||
|  |                     messageDto.setMessage("您有一份重要的违章需要处理!工单号为:" + violationRecord.getId()); | ||||||
|  |                     SseMessageUtils.publishMessage(messageDto); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新增违章处理人 | ||||||
|  |      * | ||||||
|  |      * @param req 违章处理人 | ||||||
|  |      * @return 是否新增成功 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public Boolean insertHandler(HseViolationRecordCreateHandlerReq req) { | ||||||
|  |         Long id = req.getId(); | ||||||
|  |         HseViolationRecord oldViolationRecord = this.getById(id); | ||||||
|  |         if (oldViolationRecord == null) { | ||||||
|  |             throw new ServiceException("违规记录信息不存在", HttpStatus.NOT_FOUND); | ||||||
|  |         } | ||||||
|  |         Long handlerId = req.getHandlerId(); | ||||||
|  |         SysUserVo user = userService.selectUserById(handlerId); | ||||||
|  |         if (user == null) { | ||||||
|  |             throw new ServiceException("处理人信息不存在", HttpStatus.NOT_FOUND); | ||||||
|  |         } | ||||||
|  |         HseViolationRecord violationRecord = new HseViolationRecord(); | ||||||
|  |         violationRecord.setId(id); | ||||||
|  |         violationRecord.setHandlerId(handlerId); | ||||||
|  |         violationRecord.setDisposeTime(req.getDisposeDeadline()); | ||||||
|  |         violationRecord.setRemark(req.getRemark()); | ||||||
|  |         boolean result = this.updateById(violationRecord); | ||||||
|  |         if (!result) { | ||||||
|  |             throw new ServiceException("更新处理人操作失败", HttpStatus.ERROR); | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 批量删除违规记录信息 | ||||||
|  |      * | ||||||
|  |      * @param ids 待删除的主键集合 | ||||||
|  |      * @return 是否删除成功 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public Boolean deleteWithValidByIds(Collection<Long> ids) { | ||||||
|  |         return this.removeBatchByIds(ids); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录视图对象 | ||||||
|  |      * | ||||||
|  |      * @param violationRecord 违规记录对象 | ||||||
|  |      * @return 违规记录视图对象 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public HseViolationRecordVo getVo(HseViolationRecord violationRecord) { | ||||||
|  |         HseViolationRecordVo violationRecordVo = new HseViolationRecordVo(); | ||||||
|  |         if (violationRecord == null) { | ||||||
|  |             return violationRecordVo; | ||||||
|  |         } | ||||||
|  |         BeanUtils.copyProperties(violationRecord, violationRecordVo); | ||||||
|  |         // 关联等级 | ||||||
|  |         Long levelId = violationRecord.getLevelId(); | ||||||
|  |         if (ObjectUtils.isNotEmpty(levelId)) { | ||||||
|  |             HseViolationLevel level = violationLevelService.getById(levelId); | ||||||
|  |             violationRecordVo.setLevelVo(violationLevelService.getVo(level)); | ||||||
|  |         } | ||||||
|  |         // 关联识别记录 | ||||||
|  |         Long recognizeId = violationRecord.getRecognizeId(); | ||||||
|  |         if (ObjectUtils.isNotEmpty(recognizeId)) { | ||||||
|  |             HseRecognizeRecord recognizeRecord = recognizeRecordService.getById(recognizeId); | ||||||
|  |             violationRecordVo.setRecognizeVo(recognizeRecordService.getVo(recognizeRecord)); | ||||||
|  |         } | ||||||
|  |         // 关联违章人信息 | ||||||
|  |         Long handlerId = violationRecord.getHandlerId(); | ||||||
|  |         if (ObjectUtils.isNotEmpty(handlerId)) { | ||||||
|  |             SysUserVo handler = userService.selectUserById(handlerId); | ||||||
|  |             violationRecordVo.setHandlerName(handler.getNickName()); | ||||||
|  |         } | ||||||
|  |         return violationRecordVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录查询条件封装 | ||||||
|  |      * | ||||||
|  |      * @param req 违规记录查询条件 | ||||||
|  |      * @return 违规记录查询条件封装 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public LambdaQueryWrapper<HseViolationRecord> buildQueryWrapper(HseViolationRecordQueryReq req) { | ||||||
|  |         LambdaQueryWrapper<HseViolationRecord> lqw = new LambdaQueryWrapper<>(); | ||||||
|  |         if (req == null) { | ||||||
|  |             return lqw; | ||||||
|  |         } | ||||||
|  |         Long id = req.getId(); | ||||||
|  |         Long projectId = req.getProjectId(); | ||||||
|  |         String violationType = req.getViolationType(); | ||||||
|  |         Date violationTime = req.getViolationTime(); | ||||||
|  |         lqw.eq(ObjectUtils.isNotEmpty(id), HseViolationRecord::getId, id); | ||||||
|  |         lqw.eq(ObjectUtils.isNotEmpty(projectId), HseViolationRecord::getProjectId, projectId); | ||||||
|  |         lqw.eq(StringUtils.isNotBlank(violationType), HseViolationRecord::getViolationType, violationType); | ||||||
|  |         if (violationTime != null) { | ||||||
|  |             // 构造当天的起始和结束时间 | ||||||
|  |             LocalDate localDate = violationTime.toInstant() | ||||||
|  |                 .atZone(ZoneId.systemDefault()) | ||||||
|  |                 .toLocalDate(); | ||||||
|  |             LocalDateTime startOfDay = localDate.atStartOfDay(); | ||||||
|  |             LocalDateTime startOfNextDay = localDate.plusDays(1).atStartOfDay(); | ||||||
|  |             Date start = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant()); | ||||||
|  |             Date end = Date.from(startOfNextDay.atZone(ZoneId.systemDefault()).toInstant()); | ||||||
|  |             lqw.ge(HseViolationRecord::getViolationTime, start) | ||||||
|  |                 .lt(HseViolationRecord::getViolationTime, end); | ||||||
|  |         } | ||||||
|  |         return lqw; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取违规记录分页对象视图 | ||||||
|  |      * | ||||||
|  |      * @param violationRecordPage 违规记录分页对象 | ||||||
|  |      * @return 违规记录分页对象视图 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public Page<HseViolationRecordVo> getVoPage(Page<HseViolationRecord> violationRecordPage) { | ||||||
|  |         List<HseViolationRecord> violationRecordList = violationRecordPage.getRecords(); | ||||||
|  |         Page<HseViolationRecordVo> violationRecordVoPage = new Page<>( | ||||||
|  |             violationRecordPage.getCurrent(), | ||||||
|  |             violationRecordPage.getSize(), | ||||||
|  |             violationRecordPage.getTotal()); | ||||||
|  |         if (CollUtil.isEmpty(violationRecordList)) { | ||||||
|  |             return violationRecordVoPage; | ||||||
|  |         } | ||||||
|  |         // 关联等级 | ||||||
|  |         Set<Long> levelIds = violationRecordList.stream().map(HseViolationRecord::getLevelId).collect(Collectors.toSet()); | ||||||
|  |         Map<Long, HseViolationLevel> levelIdLevelMap = violationLevelService.listByIds(levelIds).stream() | ||||||
|  |             .collect(Collectors.toMap(HseViolationLevel::getId, level -> level)); | ||||||
|  |         // 关联识别记录 | ||||||
|  |         Set<Long> recognizeIds = violationRecordList.stream().map(HseViolationRecord::getRecognizeId).collect(Collectors.toSet()); | ||||||
|  |         Map<Long, HseRecognizeRecord> recognizeIdRecognizeMap = recognizeRecordService.listByIds(recognizeIds).stream() | ||||||
|  |             .collect(Collectors.toMap(HseRecognizeRecord::getId, recognize -> recognize)); | ||||||
|  |         // 关联违章人信息 | ||||||
|  |         List<Long> handlerIds = violationRecordList.stream().map(HseViolationRecord::getHandlerId).distinct().toList(); | ||||||
|  |         Map<Long, SysUserVo> handlerIdUserMap = userService.selectUserByIds(handlerIds, null).stream() | ||||||
|  |             .collect(Collectors.toMap(SysUserVo::getUserId, user -> user)); | ||||||
|  |         List<HseViolationRecordVo> violationRecordVoList = violationRecordList.stream().map(violationLevel -> { | ||||||
|  |             HseViolationRecordVo vo = new HseViolationRecordVo(); | ||||||
|  |             BeanUtils.copyProperties(violationLevel, vo); | ||||||
|  |             // 关联等级 | ||||||
|  |             if (CollUtil.isNotEmpty(levelIdLevelMap) && levelIdLevelMap.containsKey(violationLevel.getLevelId())) { | ||||||
|  |                 vo.setLevelVo(violationLevelService.getVo(levelIdLevelMap.get(violationLevel.getLevelId()))); | ||||||
|  |             } | ||||||
|  |             // 关联识别记录 | ||||||
|  |             if (CollUtil.isNotEmpty(recognizeIdRecognizeMap) && recognizeIdRecognizeMap.containsKey(violationLevel.getRecognizeId())) { | ||||||
|  |                 vo.setRecognizeVo(recognizeRecordService.getVo(recognizeIdRecognizeMap.get(violationLevel.getRecognizeId()))); | ||||||
|  |             } | ||||||
|  |             // 违章人信息 | ||||||
|  |             if (CollUtil.isNotEmpty(handlerIdUserMap) && handlerIdUserMap.containsKey(violationLevel.getHandlerId())) { | ||||||
|  |                 vo.setHandlerName(handlerIdUserMap.get(violationLevel.getHandlerId()).getNickName()); | ||||||
|  |             } | ||||||
|  |             return vo; | ||||||
|  |         }).toList(); | ||||||
|  |         violationRecordVoPage.setRecords(violationRecordVoList); | ||||||
|  |         return violationRecordVoPage; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -219,4 +219,12 @@ public interface ISysUserService { | |||||||
|      * @return 结果 |      * @return 结果 | ||||||
|      */ |      */ | ||||||
|     List<SysUserVo> selectUserListByDept(Long deptId); |     List<SysUserVo> selectUserListByDept(Long deptId); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 通过岗位id列表查询岗位所有用户 | ||||||
|  |      * | ||||||
|  |      * @param postIds 岗位id列表 | ||||||
|  |      * @return 结果 | ||||||
|  |      */ | ||||||
|  |     List<SysUserVo> selectUserListByPostList(List<Long> postIds); | ||||||
| } | } | ||||||
|  | |||||||
| @ -614,6 +614,24 @@ public class SysUserServiceImpl implements ISysUserService, UserService { | |||||||
|         return baseMapper.selectVoList(lqw); |         return baseMapper.selectVoList(lqw); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 通过岗位id列表查询岗位所有用户 | ||||||
|  |      * | ||||||
|  |      * @param postIds 岗位id列表 | ||||||
|  |      * @return 结果 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public List<SysUserVo> selectUserListByPostList(List<Long> postIds) { | ||||||
|  |         LambdaQueryWrapper<SysUserPost> lqw = Wrappers.lambdaQuery(); | ||||||
|  |         lqw.in(SysUserPost::getPostId, postIds); | ||||||
|  |         List<SysUserPost> userPostList = userPostMapper.selectList(lqw); | ||||||
|  |         if (CollUtil.isNotEmpty(userPostList)){ | ||||||
|  |             List<Long> userIds = userPostList.stream().map(SysUserPost::getUserId).distinct().toList(); | ||||||
|  |             return baseMapper.selectVoByIds(userIds); | ||||||
|  |         } | ||||||
|  |         return List.of(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 通过用户ID查询用户账户 |      * 通过用户ID查询用户账户 | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" ?> | ||||||
|  | <!DOCTYPE mapper | ||||||
|  |     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||||||
|  |     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||||
|  | <mapper namespace="org.dromara.safety.mapper.HseViolationRecordMapper"> | ||||||
|  |  | ||||||
|  | </mapper> | ||||||
| @ -1743,44 +1743,34 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, | |||||||
| values (1942399191372275718, '无人机配置导出', 1942399191372275713, '5', '#', '', 1, 0, 'F', '0', '0', | values (1942399191372275718, '无人机配置导出', 1942399191372275713, '5', '#', '', 1, 0, 'F', '0', '0', | ||||||
|         'drone:droneConfig:export', '#', 103, 1, sysdate(), null, null, ''); |         'drone:droneConfig:export', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|  |  | ||||||
|  | -- 菜单 SQL | ||||||
|  | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|  |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|  | values (1947491501058625537, '违规记录', '1935597155897143297', '1', 'violationRecord', 'safety/violationRecord/index', | ||||||
|  |         1, 0, 'C', '0', '0', 'safety:violationRecord:list', '#', 103, 1, sysdate(), null, null, '违规记录菜单'); | ||||||
|  |  | ||||||
| CREATE TABLE `bus_violation_record` | -- 按钮 SQL | ||||||
| ( | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|     `id`                          bigint                                                   NOT NULL AUTO_INCREMENT COMMENT '主键ID', |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|     `pid`                         bigint                                                            DEFAULT '0' COMMENT '父级主键ID', | values (1947491501058625538, '违规记录查询', 1947491501058625537, '1', '#', '', 1, 0, 'F', '0', '0', | ||||||
|     `project_id`                  bigint                                                            DEFAULT NULL COMMENT '项目id', |         'safety:violationRecord:query', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|     `level_id`                    bigint                                                            DEFAULT NULL COMMENT '违章等级主键ID', |  | ||||||
|     `level`                       varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '违章等级(字符串)', | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|     `tour_type`                   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '违章类型(字典)', |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|     `tour_id`                     bigint                                                            DEFAULT NULL COMMENT '违章详情(关联bus_tour)', | values (1947491501058625539, '违规记录新增', 1947491501058625537, '2', '#', '', 1, 0, 'F', '0', '0', | ||||||
|     `data_source`                 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '数据来源(violation_record_data_source)', |         'safety:violationRecord:add', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|     `select_people`               bigint                                                            DEFAULT NULL COMMENT '选择人(后台用户ID)', |  | ||||||
|     `openid`                      varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT 'openid(施工人员)', | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|     `status`                      char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci          DEFAULT '1' COMMENT '工单状态(1通知 2整改 3复查)', |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|     `processing_period`           varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '处理期限(要求)', | values (1947491501058625540, '违规记录修改', 1947491501058625537, '3', '#', '', 1, 0, 'F', '0', '0', | ||||||
|     `processing_period_practical` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '处理期限(实际)', |         'safety:violationRecord:edit', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|     `measure`                     varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '整改措施', |  | ||||||
|     `review`                      varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '复查情况', | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|     `review_type`                 char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci          DEFAULT NULL COMMENT '复查状态(1通过 2未通过)', |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|     `rectification_time`          datetime                                                          DEFAULT NULL COMMENT '整改时间', | values (1947491501058625541, '违规记录删除', 1947491501058625537, '4', '#', '', 1, 0, 'F', '0', '0', | ||||||
|     `review_time`                 datetime                                                          DEFAULT NULL COMMENT '复查时间', |         'safety:violationRecord:remove', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|     `create_by`                   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '创建者', |  | ||||||
|     `update_by`                   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT '' COMMENT '更新者', | insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, | ||||||
|     `created_at`                  datetime                                                          DEFAULT NULL COMMENT '创建时间', |                       status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) | ||||||
|     `updated_at`                  datetime                                                          DEFAULT NULL COMMENT '更新时间', | values (1947491501058625542, '违规记录导出', 1947491501058625537, '5', '#', '', 1, 0, 'F', '0', '0', | ||||||
|     `deleted_at`                  datetime                                                          DEFAULT NULL COMMENT '删除时间', |         'safety:violationRecord:export', '#', 103, 1, sysdate(), null, null, ''); | ||||||
|     `remark`                      varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '备注', |  | ||||||
|     `wx_or_pc`                    varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '来源:1pc 2小程序', |  | ||||||
|     `picture`                     varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '图片', |  | ||||||
|     `processing_time`             date                                                              DEFAULT NULL COMMENT '处理日期', |  | ||||||
|     `is_dispose`                  char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '是否处理(1待处理 2已处理)', |  | ||||||
|     `labor_date`                  varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '人工日期(数据来源人工才会有此日期)', |  | ||||||
|     `sxt_name`                    varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '摄像头名称', |  | ||||||
|     PRIMARY KEY (`id`) USING BTREE, |  | ||||||
|     KEY `select_people` (`select_people`) USING BTREE, |  | ||||||
|     KEY `openid` (`openid`) USING BTREE |  | ||||||
| ) ENGINE = InnoDB |  | ||||||
|   AUTO_INCREMENT = 262 |  | ||||||
|   DEFAULT CHARSET = utf8mb4 |  | ||||||
|   COLLATE = utf8mb4_general_ci |  | ||||||
|   ROW_FORMAT = DYNAMIC COMMENT ='工单管理/违规记录'; |  | ||||||
|  | |||||||
| @ -1566,29 +1566,24 @@ CREATE TABLE `hse_violation_record` | |||||||
| ( | ( | ||||||
|     `id`                 bigint                             not null auto_increment comment '主键id', |     `id`                 bigint                             not null auto_increment comment '主键id', | ||||||
|     `project_id`         bigint                             not null comment '项目id', |     `project_id`         bigint                             not null comment '项目id', | ||||||
|     `level_id`                    bigint                                                            DEFAULT NULL COMMENT '违章等级主键ID', |     `level_id`           bigint                             not null comment '违章等级id', | ||||||
|     `level`                       varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '违章等级(字符串)', |     `recognize_id`       bigint                             not null comment '识别记录id', | ||||||
|     `tour_type`                   varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '违章类型(字典)', |     `violation_type`     varchar(32)                        null comment '违章类型', | ||||||
|     `tour_id`                     bigint                                                            DEFAULT NULL COMMENT '违章详情(关联bus_tour)', |     `violation_time`     datetime                           null comment '违章时间', | ||||||
|     `data_source`                 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '数据来源(violation_record_data_source)', |     `handler_id`         bigint                             null comment '违章处理人id', | ||||||
|     `select_people`               bigint                                                            DEFAULT NULL COMMENT '选择人(后台用户ID)', |     `dispose_deadline`   date                               null comment '处理期限', | ||||||
|     `openid`                      varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT 'openid(施工人员)', |     `dispose_time`       datetime                           null comment '处理时间', | ||||||
|     `status`                      char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci          DEFAULT '1' COMMENT '工单状态(1通知 2整改 3复查)', |     `measure`            varchar(300)                       null comment '整改措施', | ||||||
|     `processing_period`           varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '处理期限(要求)', |     `rectification_time` datetime                           null comment '整改时间', | ||||||
|     `processing_period_practical` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '处理期限(实际)', |     `review`             varchar(255)                       null comment '复查情况', | ||||||
|     `measure`                     varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '整改措施', |     `review_type`        char(1)                            null comment '复查状态(1通过 2未通过)', | ||||||
|     `review`                      varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '复查情况', |     `review_time`        datetime                           null comment '复查时间', | ||||||
|     `review_type`                 char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci          DEFAULT NULL COMMENT '复查状态(1通过 2未通过)', |     `process_type`       char(1)  default '1'               not null comment '处理流程类型(0仅通知 1通知整改复查)', | ||||||
|     `rectification_time`          datetime                                                          DEFAULT NULL COMMENT '整改时间', |     `status`             char(1)  default '1'               not null comment '工单状态(1通知 2整改 3复查)', | ||||||
|     `review_time`                 datetime                                                          DEFAULT NULL COMMENT '复查时间', |     `remark`             varchar(255)                       null comment '备注', | ||||||
|     `picture`                     varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '图片', |  | ||||||
|     `processing_time`             date                                                              DEFAULT NULL COMMENT '处理日期', |  | ||||||
|     `is_dispose`                  char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '是否处理(1待处理 2已处理)', |  | ||||||
|     `labor_date`                  varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci      DEFAULT NULL COMMENT '人工日期(数据来源人工才会有此日期)', |  | ||||||
|     `sxt_name`                    varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci     DEFAULT NULL COMMENT '摄像头名称', |  | ||||||
|     `remark`             text                               null comment '备注', |  | ||||||
|     `create_by`          bigint                             null comment '创建者', |     `create_by`          bigint                             null comment '创建者', | ||||||
|     `update_by`          bigint                             null comment '更新者', |     `update_by`          bigint                             null comment '更新者', | ||||||
|  |     `create_dept`        bigint                             null comment '创建部门', | ||||||
|     `create_time`        datetime default CURRENT_TIMESTAMP null comment '创建时间', |     `create_time`        datetime default CURRENT_TIMESTAMP null comment '创建时间', | ||||||
|     `update_time`        datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', |     `update_time`        datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', | ||||||
|     primary key (`id`) using btree, |     primary key (`id`) using btree, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user