工单等bug优化

This commit is contained in:
guoshengxiong 2025-09-30 17:15:17 +08:00
parent d617e8c499
commit ff4d31c0e2
17 changed files with 178 additions and 17 deletions

View File

@ -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) {
//避免报错返回200data为null
result = Result.ok();
log.info("不允许访问");
} else {
result.error500(ex.getMessage() == null ? "操作中出现空指针!" : ex.getMessage());
}

View File

@ -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<String, Object> map = new HashMap<>(16);
map.put("url", url);

View File

@ -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<String> 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();
}
}

View File

@ -64,6 +64,7 @@ public class PoliceCameraItemFileController {
})
@GetMapping(value = "/page")
public Result<IPage<PoliceCameraItemFileVo>> queryPageList(@ApiIgnore @RequestParam HashMap<String, Object> 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<List<PoliceCameraItemFileVo>> queryList(@ApiIgnore @RequestParam HashMap<String, Object> param) {
param.put("isDeleted", 0);
return Result.success(policeCameraItemFileService.queryList(param));
}

View File

@ -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<String> idList = Arrays.asList(ids.split(","));
if (CollUtil.isNotEmpty(idList)) {
for (String id : idList) {
workTicketService.delete(id);
}
}
Result.success("删除成功!");
}
return result;

View File

@ -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;
}

View File

@ -13,6 +13,7 @@
<if test="param.devSn != null and param.devSn != ''">
and t.dev_sn = #{param.devSn}
</if>
group by t.id
)t
${ew.customSqlSegment}
</select>

View File

@ -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<PoliceCameraItemFileMapper, PoliceCameraItemFile> implements IPoliceCameraItemFileService {
@Lazy
@Autowired
FileStorageService fileStorageService;
@Autowired
private PoliceCameraItemFileMapper policeCameraItemFileMapper;
@Lazy
@ -62,9 +72,32 @@ public class PoliceCameraItemFileServiceImpl extends ServiceImpl<PoliceCameraIte
@Override
public void add(PoliceCameraItemFileDto policeCameraItemFileDto) {
policeCameraItemFileDto.setId(null);
setVideoScreenshot(policeCameraItemFileDto);
baseMapper.insert(policeCameraItemFileDto);
}
private void setVideoScreenshot(PoliceCameraItemFileDto policeCameraItemFileDto) {
try {
if (Objects.equals(policeCameraItemFileDto.getFileType(), 3) && StrUtil.isBlank(policeCameraItemFileDto.getExternalId())) {
List<FileUtils.FileObj> 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());

View File

@ -319,7 +319,7 @@ public class PoliceCameraItemServiceImpl extends ServiceImpl<PoliceCameraItemMap
//海康ISC
String url = HikVideoUtil.callPostApiGetPreviewURL(item.getMonitoringNumber(), MapUtils.getString(map, "type"),
MapUtils.getInteger(map, "streamType"), config.getIp(),
config.getPort(), config.getAppId(), config.getAppSecret());
config.getPort(), config.getAppId(), config.getAppSecret(), 1);
VideoInfo videoInfo = new VideoInfo();
BeanUtil.copyProperties(item, videoInfo);
videoInfo.setUrl(url);

View File

@ -196,6 +196,19 @@ public class WorkTicketServiceImpl extends ServiceImpl<WorkTicketMapper, WorkTic
workTicketCameraRelService.remove(new LambdaQueryWrapper<WorkTicketCameraRel>()
.eq(WorkTicketCameraRel::getWorkTicketId, workTicketDto.getId()));
addWorkTicketCameraRel(workTicketDto);
updateOrder(workTicketDto);
}
private void updateOrder(WorkTicketDto workTicketDto) {
workTicketOrderService.update(null, new LambdaUpdateWrapper<WorkTicketOrder>()
.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<WorkTicketMapper, WorkTic
throw new OpenAlertException("未找到对应实体");
}
baseMapper.deleteById(id);
workTicketOrderService.remove(new LambdaQueryWrapper<WorkTicketOrder>()
.eq(WorkTicketOrder::getWorkTicketId, id));
}
@Override

View File

@ -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, "操作成功");
}
}

View File

@ -123,7 +123,7 @@ public class RtWorkTicketServiceImpl extends ServiceImpl<RtWorkTicketMapper, RtW
//设置视频
if (StringUtils.isNotEmpty(videoItem.getSerialNumber()) && StringUtils.isNotEmpty(videoConfig.getAppId()) && StringUtils.isNotEmpty(videoConfig.getAppSecret())) {
String url = HikVideoUtil.callPostApiGetPreviewURL(videoItem.getSerialNumber(), "hls", null, videoConfig.getAccount(),
videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret());
videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret(), videoItem.getTransmode());
videoItem.setPlayUrl(url);
}
} catch (Exception e) {
@ -265,7 +265,7 @@ public class RtWorkTicketServiceImpl extends ServiceImpl<RtWorkTicketMapper, RtW
for (VideoItem videoItem : videoList) {
if (StringUtils.isNotEmpty(videoItem.getSerialNumber())) {
String url = HikVideoUtil.callPostApiGetPreviewURL(videoItem.getSerialNumber(), "hls", null, videoConfig.getAccount(),
videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret());
videoConfig.getPassword(), videoConfig.getAppId(), videoConfig.getAppSecret(), videoItem.getTransmode());
videoItem.setPlayUrl(url);
}
}

View File

@ -171,6 +171,11 @@ public class VideoItem implements Serializable {
*/
@ApiModelProperty(value = "智能广播设备devSns(多个,分隔)")
private String broadcastDevs;
/**
* transmode:传输协议传输层协议0:UDP 1:TCP默认是TCP注GB28181 2011及以前版本只支持UDP传输
*/
@ApiModelProperty(value = "transmode:传输协议传输层协议0:UDP 1:TCP默认是TCP注GB28181 2011及以前版本只支持UDP传输")
private Integer transmode;
/**
* 项目sn

View File

@ -344,7 +344,7 @@ public class VideoItemServiceImpl extends ServiceImpl<VideoItemMapper, VideoItem
//海康ISC
String url = HikVideoUtil.callPostApiGetPreviewURL(videoItem.getSerialNumber(), type,
streamType, projectVideoConfig.getAccount(),
projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret());
projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret(), videoItem.getTransmode());
Map<String, Object> result = new HashMap<>(16);
result.put("url", url);
result.put("serialNumber", videoItem.getSerialNumber());
@ -832,7 +832,7 @@ public class VideoItemServiceImpl extends ServiceImpl<VideoItemMapper, VideoItem
if (Objects.equals(projectVideoConfig.getVideoType(), 3)) {
url = HikVideoUtil.callPostApiGetPreviewURL(MapUtils.getString(map, "serialNumber"), MapUtils.getString(map, "type"),
MapUtils.getInteger(map, "streamType"), projectVideoConfig.getAccount(),
projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret());
projectVideoConfig.getPassword(), projectVideoConfig.getAppId(), projectVideoConfig.getAppSecret(), 1);
} else {
throw new OpenAlertException("未启用海康视频配置");
}
@ -843,7 +843,7 @@ public class VideoItemServiceImpl extends ServiceImpl<VideoItemMapper, VideoItem
//海康ISC
url = HikVideoUtil.callPostApiGetPreviewURL(MapUtils.getString(map, "serialNumber"), MapUtils.getString(map, "type"),
MapUtils.getInteger(map, "streamType"), MapUtils.getString(videoInfo, "account"),
MapUtils.getString(videoInfo, "password"), MapUtils.getString(videoInfo, "appId"), MapUtils.getString(videoInfo, "appSecret"));
MapUtils.getString(videoInfo, "password"), MapUtils.getString(videoInfo, "appId"), MapUtils.getString(videoInfo, "appSecret"), 1);
}
}

View File

@ -78,6 +78,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
http.authorizeRequests()
//请求路径允许访问
.antMatchers("/xmgl/videoScreenshot/captureScreenshotSync").permitAll()
.antMatchers("/xmgl/policeCameraItemFile/*").permitAll()
.antMatchers("/xmgl/workTicketOrderApp/*").permitAll()
.antMatchers("/xmgl/policeCameraItem/*").permitAll()

View File

@ -36,9 +36,10 @@ public class HikVideoUtil {
* @param port
* @param appke
* @param appSecret
* @param transmode
* @return
*/
public static String callPostApiGetPreviewURL(String cameraIndexCode, String type, Integer streamType, String Ip, String port, String appke, String appSecret) {
public static String callPostApiGetPreviewURL(String cameraIndexCode, String type, Integer streamType, String Ip, String port, String appke, String appSecret, Integer transmode) {
String url = null;
final String getCamsApi = ARTEMIS_PATH + "/api/video/v2/cameras/previewURLs";
Map<String, Object> paramMap = new HashMap<String, Object>();// 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);

View File

@ -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;
}
}