diff --git a/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/SpartaTest.java b/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/SpartaTest.java index 5cb4e8ad..54859839 100644 --- a/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/SpartaTest.java +++ b/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/SpartaTest.java @@ -3,9 +3,24 @@ package org.dromara.test; 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.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.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Date; +import java.util.List; + /** * @author lcj * @date 2025/6/20 19:40 @@ -17,9 +32,82 @@ 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 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 size = target.getSize(); // 宽高 + List 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)); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java index acd3f036..3040b963 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; * @date 2025/6/18 15:59 */ @Slf4j -//@Component +@Component public class IncSyncYs7DeviceCapturePicData { @Resource @@ -132,7 +132,7 @@ public class IncSyncYs7DeviceCapturePicData { log.error("主线程中断", e); } // 输出抓图结果日志 - log.info("获取图片完成,共 {} 张:{}", imgList.size(), imgList); + log.info("获取图片完成,共 {} 张", imgList.size()); ys7DeviceImgService.saveCapturePic(imgList); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaManager.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaManager.java index 0d0892f6..1eace728 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaManager.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaManager.java @@ -1,11 +1,28 @@ 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; /** @@ -39,7 +56,112 @@ public class SpartaManager { ); token = tokenVo.getToken(); Long expiresAt = tokenVo.getExpiresAt(); - stringRedisTemplate.opsForValue().set(SpartaConstant.TOKEN_REDIS_KEY, token, (expiresAt - 3600), TimeUnit.SECONDS); + // 当前时间戳(单位:秒) + 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 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 recTypeList) { + return recognize(capUrl, recTypeList, false, null, null); + } + + /** + * 绘制图片 + * + * @param imgUrl 图片地址 + * @param targets 识别结果 + * @return 绘制后的图片 + */ + public ImageStreamResult drawImageToStream(String imgUrl, List 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 (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); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaRequestUtils.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaRequestUtils.java index d6cb8cec..d0dbd47b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaRequestUtils.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/SpartaRequestUtils.java @@ -2,14 +2,19 @@ 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.manager.spartamanager.vo.SpartaResponseVo; +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 @@ -51,4 +56,55 @@ public class SpartaRequestUtils { 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 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 targetList = JSONUtil.toList(result.getJSONArray("targets"), SpartaTargetVo.class); + spartaRecognizeVo.setTargets(targetList); + } + return spartaRecognizeVo; + } + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaHasTargetEnum.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaHasTargetEnum.java new file mode 100644 index 00000000..a49cf867 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaHasTargetEnum.java @@ -0,0 +1,22 @@ +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; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaRecTypeEnum.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaRecTypeEnum.java new file mode 100644 index 00000000..0c504f8c --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/enums/SpartaRecTypeEnum.java @@ -0,0 +1,62 @@ +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"), + SMOKE("吸烟识别", "smoke"), + BELT("安全带识别", "belt"), + 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; + + SpartaRecTypeEnum(String text, String value) { + this.text = text; + this.value = value; + } + + 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 types) { + if (types == null || types.isEmpty()) { + return ""; + } + return types.stream() + .map(SpartaRecTypeEnum::getValue) + .collect(Collectors.joining(" ")); + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/ImageStreamResult.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/ImageStreamResult.java new file mode 100644 index 00000000..78c856bc --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/ImageStreamResult.java @@ -0,0 +1,31 @@ +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; + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaRecognizeVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaRecognizeVo.java new file mode 100644 index 00000000..3b7e170d --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaRecognizeVo.java @@ -0,0 +1,29 @@ +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 originalImgSize; + + /** + * 目标信息 + */ + private List targets; + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaResponseVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaResponseVo.java deleted file mode 100644 index 8d5712f9..00000000 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaResponseVo.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.dromara.manager.spartamanager.vo; - -import lombok.Data; - -/** - * @author lcj - * @date 2025/6/20 19:25 - */ -@Data -public class SpartaResponseVo { - - /** - * 响应码 - */ - private String code; - - /** - * 响应数据 - */ - private String data; - - /** - * 响应信息 - */ - private String msg; - -} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaTargetVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaTargetVo.java new file mode 100644 index 00000000..e43eb041 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/spartamanager/vo/SpartaTargetVo.java @@ -0,0 +1,37 @@ +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 size; + + /** + * 目标在画面中左上角位置信息 + */ + private List leftTopPoint; + + /** + * 置信度得分(0~1) + */ + private Double score; +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java index ab974d75..36d9940b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java @@ -88,7 +88,6 @@ public class Ys7RequestUtils { log.error("{},状态码:{},{}", errorMsg, responseVo.getCode(), responseVo.getMsg()); throw new ServiceException(errorMsg + responseVo.getMsg()); } - log.info("Ys7 分页查询设备列表 第{}页大小{} 响应数据:{}", pageStart, pageSize, responseVo.getData()); log.info("Ys7 分页查询设备列表 第{}页大小{} 请求成功:{}", pageStart, pageSize, responseVo.getPage()); return JSONUtil.toList(responseVo.getData(), Ys7QueryDeviceResponseVo.class); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/materials/controller/MatCompanyController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/materials/controller/MatCompanyController.java index a8d5e807..172948ee 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/materials/controller/MatCompanyController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/materials/controller/MatCompanyController.java @@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; /** - * 公司 + * 材料供应商 * * @author lcj * @date 2025-03-06 @@ -42,7 +42,7 @@ public class MatCompanyController extends BaseController { private final IMatCompanyService companyService; /** - * 查询公司列表 + * 查询材料供应商列表 */ @SaCheckPermission("materials:company:list") @GetMapping("/list") @@ -51,18 +51,18 @@ public class MatCompanyController extends BaseController { } /** - * 导出公司列表 + * 导出材料供应商列表 */ @SaCheckPermission("materials:company:export") - @Log(title = "公司", businessType = BusinessType.EXPORT) + @Log(title = "材料供应商", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(MatCompanyQueryReq req, HttpServletResponse response) { List list = companyService.queryList(req); - ExcelUtil.exportExcel(list, "公司", MatCompanyVo.class, response); + ExcelUtil.exportExcel(list, "材料供应商", MatCompanyVo.class, response); } /** - * 获取公司详细信息 + * 获取材料供应商详细信息 * * @param id 主键 */ @@ -74,10 +74,10 @@ public class MatCompanyController extends BaseController { } /** - * 新增公司 + * 新增材料供应商 */ @SaCheckPermission("materials:company:add") - @Log(title = "公司", businessType = BusinessType.INSERT) + @Log(title = "材料供应商", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody MatCompanyCreateReq req) { @@ -88,10 +88,10 @@ public class MatCompanyController extends BaseController { } /** - * 修改公司 + * 修改材料供应商 */ @SaCheckPermission("materials:company:edit") - @Log(title = "公司", businessType = BusinessType.UPDATE) + @Log(title = "材料供应商", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody MatCompanyUpdateReq req) { @@ -99,12 +99,12 @@ public class MatCompanyController extends BaseController { } /** - * 删除公司 + * 删除材料供应商 * * @param ids 主键串 */ @SaCheckPermission("materials:company:remove") - @Log(title = "公司", businessType = BusinessType.DELETE) + @Log(title = "材料供应商", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java index a7baa4e7..da21b055 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java @@ -29,4 +29,19 @@ public interface Ys7DeviceImgConstant { String fileName = String.format("%s_%s.%s", date, uuid, suffix); return DEVICE_IMG_OSS_URL_PREFIX + deviceSerial + "/" + fileName; } + + /** + * 获取设备图片oss路径 + * + * @param originalFilename 文件名原始名 + * @param deviceSerial 设备序列号 + * @return oss路径 + */ + static String getTargetImgOssPath(String originalFilename, String deviceSerial) { + String suffix = FileUtil.getSuffix(originalFilename); + String uuid = IdUtil.fastSimpleUUID(); + String date = DateUtils.getDate(); + String fileName = String.format("%s_%s.%s", date, uuid, suffix); + return DEVICE_IMG_OSS_URL_PREFIX + deviceSerial + "/target/" + fileName; + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java index f59417ae..955e6267 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java @@ -42,6 +42,31 @@ public class OthYs7DeviceImg implements Serializable { */ private String url; + /** + * 识别算法模型 + */ + private String recType; + + /** + * 是否监测到目标(1是 0否) + */ + private Integer isRecognize; + + /** + * 原始图片尺寸 + */ + private String imgSize; + + /** + * 目标信息 + */ + private String targets; + + /** + * 识别结果图片地址 + */ + private String recognizeUrl; + /** * 备注 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java index ccdf9e54..3955fa51 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java @@ -9,6 +9,7 @@ import org.dromara.other.domain.OthYs7DeviceImg; import java.io.Serial; import java.io.Serializable; import java.util.Date; +import java.util.List; /** @@ -49,6 +50,16 @@ public class OthYs7DeviceImgVo implements Serializable { @ExcelProperty(value = "图片地址") private String url; + /** + * 识别算法模型 + */ + private List recTypeList; + + /** + * 是否监测到目标(1是 0否) + */ + private Integer isRecognize; + /** * 备注 */ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/mapper/OthYs7DeviceImgMapper.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/mapper/OthYs7DeviceImgMapper.java new file mode 100644 index 00000000..6874d669 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/mapper/OthYs7DeviceImgMapper.java @@ -0,0 +1,15 @@ +package org.dromara.other.mapper; + +import org.dromara.other.domain.OthYs7DeviceImg; +import org.dromara.other.domain.vo.ys7deviceimg.OthYs7DeviceImgVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 萤石摄像头图片Mapper接口 + * + * @author lcj + * @date 2025-06-18 + */ +public interface OthYs7DeviceImgMapper extends BaseMapperPlus { + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java index ea760bbb..3593bca0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java @@ -1,15 +1,25 @@ package org.dromara.other.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.json.JSONUtil; 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.exception.ServiceException; 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.oss.core.OssClient; +import org.dromara.common.oss.factory.OssFactory; +import org.dromara.manager.spartamanager.SpartaManager; +import org.dromara.manager.spartamanager.enums.SpartaHasTargetEnum; +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.constant.Ys7DeviceImgConstant; import org.dromara.other.domain.OthYs7DeviceImg; import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture; @@ -23,13 +33,11 @@ import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.io.InputStream; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; +import java.util.*; /** * 萤石摄像头图片Service业务层处理 @@ -37,6 +45,7 @@ import java.util.List; * @author lcj * @date 2025-06-18 */ +@Slf4j @Service public class OthYs7DeviceImgServiceImpl extends ServiceImpl implements IOthYs7DeviceImgService { @@ -44,6 +53,9 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl ys7DeviceImgVoList = ys7DeviceImgList.stream().map(this::getVo).toList(); + List ys7DeviceImgVoList = ys7DeviceImgList.stream().map(deviceImg -> { + OthYs7DeviceImgVo vo = new OthYs7DeviceImgVo(); + if (deviceImg == null) { + return vo; + } + BeanUtils.copyProperties(deviceImg, vo); + if (deviceImg.getRecognizeUrl() != null) { + vo.setUrl(deviceImg.getRecognizeUrl()); + } + List recTypeList = JSONUtil.toList(deviceImg.getRecType(), String.class); + List list = recTypeList.stream().map(recType -> Objects.requireNonNull(SpartaRecTypeEnum.fromValue(recType)).getText()).toList(); + vo.setRecTypeList(list); + return vo; + }).toList(); ys7DeviceImgVoPage.setRecords(ys7DeviceImgVoList); return ys7DeviceImgVoPage; } @@ -177,6 +202,31 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl recTypes = List.of(SpartaRecTypeEnum.HEAD, SpartaRecTypeEnum.SMOKE); + SpartaRecognizeVo recognizeVo = spartaManager.recognize(ossUrl, recTypes); + if (recognizeVo != null && recognizeVo.getHasTarget().equals(SpartaHasTargetEnum.YES.getValue())) { + List targets = recognizeVo.getTargets(); + othYs7DeviceImg.setTargets(JSONUtil.toJsonStr(targets)); + othYs7DeviceImg.setImgSize(JSONUtil.toJsonStr(recognizeVo.getOriginalImgSize())); + othYs7DeviceImg.setIsRecognize(SpartaHasTargetEnum.YES.getValue()); + List recTypeList = targets.stream().map(SpartaTargetVo::getType).distinct().toList(); + othYs7DeviceImg.setRecType(JSONUtil.toJsonStr(recTypeList)); + try { + ImageStreamResult imageStreamResult = spartaManager.drawImageToStream(url, targets); + InputStream inputStream = imageStreamResult.getInputStream(); + String contentType = imageStreamResult.getContentType(); + long length = imageStreamResult.getLength(); + String targetImgPath = Ys7DeviceImgConstant.getTargetImgOssPath(originalFilename, deviceSerial); + SysOssUploadVo drawImageUploadVo = ossService.uploadFileUrlWithNoSave(inputStream, targetImgPath, contentType, length); + String targetUrl = drawImageUploadVo.getUrl(); + if (StringUtils.isNotBlank(targetUrl)) { + othYs7DeviceImg.setRecognizeUrl(targetUrl); + } + } catch (Exception e) { + log.error("图片识别失败", e); + } + } saveList.add(othYs7DeviceImg); } } @@ -195,10 +245,27 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl lqw = new LambdaQueryWrapper<>(); lqw.lt(OthYs7DeviceImg::getCreateTime, cutoffDate); - return baseMapper.delete(lqw); + // 删除对象存储中的图片 + List list = this.list(lqw); + if (CollUtil.isEmpty(list)) { + return 0; + } + OssClient storage = OssFactory.instance(); + for (OthYs7DeviceImg othYs7DeviceImg : list) { + storage.delete(othYs7DeviceImg.getUrl()); + if (othYs7DeviceImg.getRecognizeUrl() != null) { + storage.delete(othYs7DeviceImg.getRecognizeUrl()); + } + } + boolean result = this.removeBatchByIds(list); + if (!result) { + throw new ServiceException("删除图片失败,数据库异常", HttpStatus.ERROR); + } + return list.size(); } /** @@ -210,6 +277,17 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl ids) { + List ys7DeviceImgList = this.listByIds(ids); + if (CollUtil.isEmpty(ys7DeviceImgList)) { + return true; + } + OssClient storage = OssFactory.instance(); + for (OthYs7DeviceImg ys7DeviceImg : ys7DeviceImgList) { + storage.delete(ys7DeviceImg.getUrl()); + if (ys7DeviceImg.getRecognizeUrl() != null) { + storage.delete(ys7DeviceImg.getRecognizeUrl()); + } + } return this.removeBatchByIds(ids); } @@ -219,7 +297,7 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl 0 && end > start) { diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java index da02abca..e8bfd461 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java @@ -2,13 +2,11 @@ package org.dromara.project.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.json.JSONObject; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; @@ -49,17 +47,6 @@ public class BusProjectFileController extends BaseController { return busProjectFileService.queryPageList(req, pageQuery); } - /** - * 导出项目文件存储列表 - */ - @SaCheckPermission("project:projectFile:export") - @Log(title = "项目文件存储", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(BusProjectFileQueryReq req, HttpServletResponse response) { - List list = busProjectFileService.queryList(req); - ExcelUtil.exportExcel(list, "项目文件存储", BusProjectFileVo.class, response); - } - /** * 获取项目文件存储详细信息 * @@ -99,6 +86,7 @@ public class BusProjectFileController extends BaseController { /** * 上传 dxf 文件并解析为 json */ + @SaCheckPermission("project:projectFile:add") @Log(title = "项目文件存储", businessType = BusinessType.IMPORT) @PostMapping("/upload/dxf") public R uploadDxf2Json(@RequestParam("file") MultipartFile file, BusProjectFileUploadDxfReq req) { diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/projectfile/BusProjectFileVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/projectfile/BusProjectFileVo.java index 397f4a4d..6da3f469 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/projectfile/BusProjectFileVo.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/projectfile/BusProjectFileVo.java @@ -1,10 +1,8 @@ package org.dromara.project.domain.vo.projectfile; -import org.dromara.project.domain.BusProjectFile; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; +import org.dromara.project.domain.BusProjectFile; import java.io.Serial; import java.io.Serializable; @@ -17,7 +15,6 @@ import java.io.Serializable; * @date 2025-04-23 */ @Data -@ExcelIgnoreUnannotated @AutoMapper(target = BusProjectFile.class) public class BusProjectFileVo implements Serializable { @@ -27,19 +24,16 @@ public class BusProjectFileVo implements Serializable { /** * 文件类型 */ - @ExcelProperty(value = "文件类型") private String fileType; /** * 文件名称 */ - @ExcelProperty(value = "文件名称") private String fileName; /** * 文件路径 */ - @ExcelProperty(value = "文件路径") private String filePath; diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HseViolationLevelServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HseViolationLevelServiceImpl.java index 4c67c1a1..e2197c91 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HseViolationLevelServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/HseViolationLevelServiceImpl.java @@ -117,7 +117,7 @@ public class HseViolationLevelServiceImpl extends ServiceImpl 0) { throw new ServiceException("违章等级已存在", HttpStatus.BAD_REQUEST); @@ -284,8 +284,15 @@ public class HseViolationLevelServiceImpl extends ServiceImpl