From ff4d31c0e2daa88cd736f0390061c0ab778572a4 Mon Sep 17 00:00:00 2001 From: guoshengxiong <1923636941@qq.com> Date: Tue, 30 Sep 2025 17:15:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E5=8D=95=E7=AD=89bug=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ExceptionHandlerAdvice.java | 4 ++ .../java/com/zhgd/xmgl/async/AsyncCommon.java | 2 +- .../controller/VideoScreenshotController.java | 39 ++++++++++++++ .../PoliceCameraItemFileController.java | 2 + .../controller/WorkTicketController.java | 8 ++- .../entity/PoliceCameraItemFile.java | 5 ++ .../mapper/xml/WorkTicketOrderMapper.xml | 1 + .../impl/PoliceCameraItemFileServiceImpl.java | 37 ++++++++++++- .../impl/PoliceCameraItemServiceImpl.java | 2 +- .../service/impl/WorkTicketServiceImpl.java | 15 ++++++ .../controller/MonitorDevController.java | 6 +-- .../service/impl/RtWorkTicketServiceImpl.java | 4 +- .../xmgl/modules/video/entity/VideoItem.java | 5 ++ .../service/impl/VideoItemServiceImpl.java | 6 +-- .../zhgd/xmgl/security/WebSecurityConfig.java | 1 + .../java/com/zhgd/xmgl/util/HikVideoUtil.java | 6 ++- .../zhgd/xmgl/util/VideoScreenshotUtil.java | 52 +++++++++++++++++++ 17 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/zhgd/xmgl/modules/basicdata/controller/VideoScreenshotController.java create mode 100644 src/main/java/com/zhgd/xmgl/util/VideoScreenshotUtil.java diff --git a/src/main/java/com/zhgd/exception/ExceptionHandlerAdvice.java b/src/main/java/com/zhgd/exception/ExceptionHandlerAdvice.java index f57dd6f81..775574582 100644 --- a/src/main/java/com/zhgd/exception/ExceptionHandlerAdvice.java +++ b/src/main/java/com/zhgd/exception/ExceptionHandlerAdvice.java @@ -51,6 +51,10 @@ public class ExceptionHandlerAdvice { result.setCode(200); result.setMessage(appException.getMessage()); result.setResult(appException.getResult()); + } else if (ex instanceof org.springframework.security.access.AccessDeniedException) { + //避免报错,返回200,data为null + result = Result.ok(); + log.info("不允许访问"); } else { result.error500(ex.getMessage() == null ? "操作中出现空指针!" : ex.getMessage()); } diff --git a/src/main/java/com/zhgd/xmgl/async/AsyncCommon.java b/src/main/java/com/zhgd/xmgl/async/AsyncCommon.java index 4500ccf42..2e56f55ae 100644 --- a/src/main/java/com/zhgd/xmgl/async/AsyncCommon.java +++ b/src/main/java/com/zhgd/xmgl/async/AsyncCommon.java @@ -326,7 +326,7 @@ public class AsyncCommon { String serialNumber = MapUtils.getString(entityMap, "serialNumber"); if (StringUtils.isNotEmpty(serialNumber)) { String url = HikVideoUtil.callPostApiGetPreviewURL(serialNumber, "hls", null, videoConfig.getAccount(), - videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret()); + videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret(), 1); if (StringUtils.isNotEmpty(url)) { HashMap map = new HashMap<>(16); map.put("url", url); diff --git a/src/main/java/com/zhgd/xmgl/modules/basicdata/controller/VideoScreenshotController.java b/src/main/java/com/zhgd/xmgl/modules/basicdata/controller/VideoScreenshotController.java new file mode 100644 index 000000000..4b8343607 --- /dev/null +++ b/src/main/java/com/zhgd/xmgl/modules/basicdata/controller/VideoScreenshotController.java @@ -0,0 +1,39 @@ +package com.zhgd.xmgl.modules.basicdata.controller; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.io.IoUtil; +import com.zhgd.jeecg.common.api.vo.Result; +import com.zhgd.xmgl.util.VideoScreenshotUtil; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.InputStream; + +@RestController +@RequestMapping("/xmgl/videoScreenshot") +@Slf4j +public class VideoScreenshotController { + + @ApiOperation(value = "截取MP4视频第一帧并返回base64图片", notes = "截取MP4视频第一帧并返回base64图片", httpMethod = "GET") + @ApiImplicitParams({ + @ApiImplicitParam(name = "videoUrl", value = "视频URL", paramType = "body", required = false, dataType = "String"), + }) + @GetMapping("/captureScreenshotSync") + public Result captureScreenshotSync(@RequestParam String videoUrl) { + try (InputStream inputStream = VideoScreenshotUtil.getCaptureScreen(videoUrl);) { + String base64Str = Base64.encode(IoUtil.readBytes(inputStream)); + return Result.success(base64Str); + } catch (Exception e) { + log.warn("截取MP4视频第一帧并返回base64图片异常:", e); + } + return Result.ok(); + } + + +} diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/PoliceCameraItemFileController.java b/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/PoliceCameraItemFileController.java index a5207ab7e..4f1b97237 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/PoliceCameraItemFileController.java +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/PoliceCameraItemFileController.java @@ -64,6 +64,7 @@ public class PoliceCameraItemFileController { }) @GetMapping(value = "/page") public Result> queryPageList(@ApiIgnore @RequestParam HashMap param) { + param.put("isDeleted", 0); return Result.success(policeCameraItemFileService.queryPageList(param)); } @@ -76,6 +77,7 @@ public class PoliceCameraItemFileController { @ApiOperation(value = "列表查询执法记录仪文件信息", notes = "列表查询执法记录仪文件信息", httpMethod = "GET") @GetMapping(value = "/list") public Result> queryList(@ApiIgnore @RequestParam HashMap param) { + param.put("isDeleted", 0); return Result.success(policeCameraItemFileService.queryList(param)); } diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/WorkTicketController.java b/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/WorkTicketController.java index c976a984e..a2778e40e 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/WorkTicketController.java +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/controller/WorkTicketController.java @@ -1,5 +1,6 @@ package com.zhgd.xmgl.modules.policecamera.controller; +import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.zhgd.annotation.OperLog; import com.zhgd.jeecg.common.api.vo.Result; @@ -150,7 +151,12 @@ public class WorkTicketController { if (ids == null || "".equals(ids.trim())) { result.error500("参数不识别!"); } else { - workTicketService.removeByIds(Arrays.asList(ids.split(","))); + List idList = Arrays.asList(ids.split(",")); + if (CollUtil.isNotEmpty(idList)) { + for (String id : idList) { + workTicketService.delete(id); + } + } Result.success("删除成功!"); } return result; diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/entity/PoliceCameraItemFile.java b/src/main/java/com/zhgd/xmgl/modules/policecamera/entity/PoliceCameraItemFile.java index 7d5b19420..a7a7c9503 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/entity/PoliceCameraItemFile.java +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/entity/PoliceCameraItemFile.java @@ -125,4 +125,9 @@ public class PoliceCameraItemFile implements Serializable { @TableLogic // MyBatis-Plus逻辑删除标记(默认0=未删,1=已删) @ApiModelProperty(value = "1删除0未删除") private java.lang.Integer isDeleted; + /** + * 视频截图url + */ + @ApiModelProperty(value = "视频截图url") + private java.lang.String videoScreenshot; } diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/mapper/xml/WorkTicketOrderMapper.xml b/src/main/java/com/zhgd/xmgl/modules/policecamera/mapper/xml/WorkTicketOrderMapper.xml index 576290ace..39b47dfe2 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/mapper/xml/WorkTicketOrderMapper.xml +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/mapper/xml/WorkTicketOrderMapper.xml @@ -13,6 +13,7 @@ and t.dev_sn = #{param.devSn} + group by t.id )t ${ew.customSqlSegment} diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemFileServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemFileServiceImpl.java index c995f5374..df342bb26 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemFileServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemFileServiceImpl.java @@ -1,5 +1,9 @@ package com.zhgd.xmgl.modules.policecamera.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.xuyanwu.spring.file.storage.FileStorageService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -11,14 +15,16 @@ import com.zhgd.xmgl.modules.policecamera.entity.dto.PoliceCameraItemFileDto; import com.zhgd.xmgl.modules.policecamera.entity.vo.PoliceCameraItemFileVo; import com.zhgd.xmgl.modules.policecamera.mapper.PoliceCameraItemFileMapper; import com.zhgd.xmgl.modules.policecamera.service.IPoliceCameraItemFileService; -import com.zhgd.xmgl.util.PageUtil; -import com.zhgd.xmgl.util.RefUtil; +import com.zhgd.xmgl.util.*; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import java.io.InputStream; import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 执法记录仪文件 @@ -27,7 +33,11 @@ import java.util.List; * @version: V1.0 */ @Service +@Slf4j public class PoliceCameraItemFileServiceImpl extends ServiceImpl implements IPoliceCameraItemFileService { + @Lazy + @Autowired + FileStorageService fileStorageService; @Autowired private PoliceCameraItemFileMapper policeCameraItemFileMapper; @Lazy @@ -62,9 +72,32 @@ public class PoliceCameraItemFileServiceImpl extends ServiceImpl fileObjs = FileUtils.parseUrlString(policeCameraItemFileDto.getFileUrl()); + if (CollUtil.isNotEmpty(fileObjs)) { + String fileUrl = fileObjs.get(0).getFileUrl(); + String videoUrl = PathUtil.getServerUrl() + "/image/" + fileUrl; + log.info("添加执法记录仪文件信息videoUrl:{}", videoUrl); + InputStream inputStream = VideoScreenshotUtil.getCaptureScreen(videoUrl); + if (inputStream != null) { + // 生成带时间戳的文件名 + String filename = "screenshot_" + System.currentTimeMillis() + ".jpg"; + FileUtil.writeFromStream(inputStream, PathUtil.getBasePath() + "/" + filename); + policeCameraItemFileDto.setVideoScreenshot(filename); + } + } + } + } catch (Exception e) { + log.warn("添加执法记录仪文件信息获取视频截图url异常", e); + } + } + @Override public void edit(PoliceCameraItemFileDto policeCameraItemFileDto) { PoliceCameraItemFile oldPoliceCameraItemFile = baseMapper.selectById(policeCameraItemFileDto.getId()); diff --git a/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemServiceImpl.java index c52b68f97..a8f6c5d2d 100644 --- a/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/policecamera/service/impl/PoliceCameraItemServiceImpl.java @@ -319,7 +319,7 @@ public class PoliceCameraItemServiceImpl extends ServiceImpl() .eq(WorkTicketCameraRel::getWorkTicketId, workTicketDto.getId())); addWorkTicketCameraRel(workTicketDto); + updateOrder(workTicketDto); + } + + private void updateOrder(WorkTicketDto workTicketDto) { + workTicketOrderService.update(null, new LambdaUpdateWrapper() + .set(WorkTicketOrder::getWorkTicketNumber, workTicketDto.getWorkTicketNumber()) + .set(WorkTicketOrder::getConstructionAreas, workTicketDto.getConstructionAreas()) + .set(WorkTicketOrder::getOperator, workTicketDto.getOperator()) + .set(WorkTicketOrder::getWorkContent, workTicketDto.getWorkContent()) + .set(WorkTicketOrder::getSafetyMeasure, workTicketDto.getSafetyMeasure()) + .ne(WorkTicketOrder::getStatus, 3) + .eq(WorkTicketOrder::getWorkTicketId, workTicketDto.getId()) + ); } @Override @@ -205,6 +218,8 @@ public class WorkTicketServiceImpl extends ServiceImpl() + .eq(WorkTicketOrder::getWorkTicketId, id)); } @Override diff --git a/src/main/java/com/zhgd/xmgl/modules/review/controller/MonitorDevController.java b/src/main/java/com/zhgd/xmgl/modules/review/controller/MonitorDevController.java index 69b877ae3..208e06901 100644 --- a/src/main/java/com/zhgd/xmgl/modules/review/controller/MonitorDevController.java +++ b/src/main/java/com/zhgd/xmgl/modules/review/controller/MonitorDevController.java @@ -10,14 +10,10 @@ import com.zhgd.jeecg.common.api.vo.Result; import com.zhgd.jeecg.common.system.query.QueryGenerator; import com.zhgd.xmgl.modules.project.entity.ProjectVideoConfig; import com.zhgd.xmgl.modules.project.mapper.ProjectVideoConfigMapper; -import com.zhgd.xmgl.modules.review.entity.BaseMap; -import com.zhgd.xmgl.modules.review.entity.GltfModel; import com.zhgd.xmgl.modules.review.entity.MonitorDev; import com.zhgd.xmgl.modules.review.service.IMonitorDevService; -import com.zhgd.xmgl.modules.video.service.IVideoItemService; import com.zhgd.xmgl.util.HikVideoUtil; import com.zhgd.xmgl.util.PageUtil; -import io.loadkit.Res; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -230,7 +226,7 @@ public class MonitorDevController { ProjectVideoConfig projectVideoConfig = projectVideoConfigMapper.selectOne(queryWrapper); String url = HikVideoUtil.callPostApiGetPreviewURL(cameraIndexCodes, "hls", 1, projectVideoConfig.getAccount(), - projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret()); + projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret(), 1); return Result.success(url, "操作成功"); } } diff --git a/src/main/java/com/zhgd/xmgl/modules/rt/service/impl/RtWorkTicketServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/rt/service/impl/RtWorkTicketServiceImpl.java index 5b63b7fca..4d57e94d3 100644 --- a/src/main/java/com/zhgd/xmgl/modules/rt/service/impl/RtWorkTicketServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/rt/service/impl/RtWorkTicketServiceImpl.java @@ -123,7 +123,7 @@ public class RtWorkTicketServiceImpl extends ServiceImpl result = new HashMap<>(16); result.put("url", url); result.put("serialNumber", videoItem.getSerialNumber()); @@ -832,7 +832,7 @@ public class VideoItemServiceImpl extends ServiceImpl paramMap = new HashMap();// post请求Form表单参数 @@ -49,7 +50,7 @@ public class HikVideoUtil { paramMap.put("streamType", 0); paramMap.put("protocol", "rtsp"); paramMap.put("expand", "transcode=0"); - paramMap.put("transmode", 1); + paramMap.put("transmode", transmode); paramMap.put("streamform", "rtp"); } else { paramMap.put("cameraIndexCode", cameraIndexCode); @@ -63,6 +64,7 @@ public class HikVideoUtil { paramMap.put("streamType", streamType); paramMap.put("protocol", StringUtils.isNotEmpty(type) ? type : "hls"); paramMap.put("expand", "streamform=rtp&standard=rtsp"); + paramMap.put("transmode", transmode); } String body = JSON.toJSON(paramMap).toString(); log.info("callPostApiGetPreviewURL body:{}", body); diff --git a/src/main/java/com/zhgd/xmgl/util/VideoScreenshotUtil.java b/src/main/java/com/zhgd/xmgl/util/VideoScreenshotUtil.java new file mode 100644 index 000000000..d338622ee --- /dev/null +++ b/src/main/java/com/zhgd/xmgl/util/VideoScreenshotUtil.java @@ -0,0 +1,52 @@ +package com.zhgd.xmgl.util; + +import cn.hutool.core.util.URLUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.zhgd.jeecg.common.execption.OpenAlertException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; + +import java.io.InputStream; + +@Slf4j +public class VideoScreenshotUtil { + private static String captureScreenshotServiceHost; + + /** + * 截取MP4视频第一帧并返回流 + * + * @param videoUrl + * @return + */ + public static InputStream getCaptureScreen(String videoUrl) { + String remoteUrl = captureScreenshotServiceHost + "/api/video/screenshot?videoUrl=" + + URLUtil.encode(videoUrl); + log.info("remoteUrl:{}", remoteUrl); + HttpResponse httpResponse = null; + try { + httpResponse = HttpRequest.get(remoteUrl) + .timeout(30000) + .execute(); + + if (httpResponse.isOk()) { + return httpResponse.bodyStream(); + } else { + throw new OpenAlertException("远程服务响应错误: " + httpResponse.getStatus()); + } + + } catch (Exception e) { + log.warn("截取MP4视频第一帧并返回图片流异常:", e); + } finally { + if (httpResponse != null) { + httpResponse.close(); + } + } + return null; + } + + @Value("${captureScreenshotServiceHost:http://127.0.0.1:52222}") + public static void setCaptureScreenshotServiceHost(String captureScreenshotServiceHost) { + VideoScreenshotUtil.captureScreenshotServiceHost = captureScreenshotServiceHost; + } +}