add:图片预览

This commit is contained in:
zhangzq
2025-09-18 16:00:57 +08:00
parent 523f8e69b0
commit 6821240f1c
10 changed files with 133 additions and 14 deletions

View File

@@ -3,12 +3,16 @@ package org.nl.common.domain.constant;
import lombok.Data;
import lombok.ToString;
import org.nl.common.hikvision.HikvisionSnapshotUtil;
import org.nl.config.thread.ThreadPoolExecutorUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.ThreadPoolExecutor;
/**
* s
@@ -36,6 +40,9 @@ public class DictConstantPool {
@Value("${hikvison.channelSdk}")
public Integer channel;
@Resource( name = "meshandlerPool")
private ThreadPoolExecutor threadPoolExecutor;
public static final String DICT_SYS_CODE = "system_type";
public static final String DICT_SYS_NAME = "所属系统";
@@ -49,5 +56,6 @@ public class DictConstantPool {
HikvisionSnapshotUtil.username = this.username;
HikvisionSnapshotUtil.channelHttp = this.channelHttp;
HikvisionSnapshotUtil.channel = this.channel;
HikvisionSnapshotUtil.threadPoolExecutor = this.threadPoolExecutor;
}
}

View File

@@ -1,12 +1,17 @@
package org.nl.common.hikvision;
import cn.hutool.core.date.DateUtil;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.concurrent.ThreadPoolExecutor;
@Service
@Slf4j
public class HikvisionSnapshotUtil {
public static String ins; //HCNetSDK.dll文件路径
@@ -17,6 +22,7 @@ public class HikvisionSnapshotUtil {
public static String password;//海康威视设备网络搜索应用中摄像头管理账密码nl1314520
public static String channelHttp;//默认
public static Integer channel;//默认1
public static ThreadPoolExecutor threadPoolExecutor;
// HCNetSDK 接口映射
public interface HCNetSDK extends Library {
Hikvision截图Demo.HCNetSDK INSTANCE = Native.load(ins, Hikvision截图Demo.HCNetSDK.class);
@@ -68,7 +74,8 @@ public class HikvisionSnapshotUtil {
}
//HCNetSDK 抓图,图片路径允许指定,不指定则走配置
public static SdkResponse 截图(String imagePath, String imageName) {
public static SdkResponse 截图( String imageName) {
String imagePath = "D://vehicle/"+DateUtil.thisYear();
if (StringUtils.isEmpty(imageName)){
return SdkResponse.requestFail("图片名称未知");
}
@@ -104,4 +111,46 @@ public class HikvisionSnapshotUtil {
Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Cleanup();
return result?SdkResponse.requestOk():SdkResponse.requestFail("[SDK] 最终抓图失败");
}
public static void sync截图(String imageName,String taskCode) {
if (threadPoolExecutor!=null){
if (StringUtils.isEmpty(imageName)){
log.warn("图片名称未定义");
}
String imagePath = HikvisionSnapshotUtil.path+DateUtil.thisYear();
String sFileUrl = imagePath+"\\"+imageName+"_"+taskCode;
String newFileUrl = imagePath+"\\"+imageName;
if (!Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Init()) {
}
Hikvision截图Demo.NET_DVR_DEVICEINFO_V30 deviceInfo = new Hikvision截图Demo.NET_DVR_DEVICEINFO_V30();
int userId = Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Login_V30(ip, port, username, password, deviceInfo);
if (userId < 0) {
log.warn("[SDK] 登录失败");
Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Cleanup();
}
Hikvision截图Demo.NET_DVR_JPEGPARA jpegPara = new Hikvision截图Demo.NET_DVR_JPEGPARA();
// D1
jpegPara.wPicSize = 2;
// 一般质量
jpegPara.wPicQuality = 0;
//命名规则:任务号+载具号+时间.jpg
try {
boolean result = Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_CaptureJPEGPicture(userId, channel, jpegPara, sFileUrl);
if (!result) {
result = Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_CaptureJPEGPicture(userId, channel, jpegPara, sFileUrl);
if (result) {
boolean result2 = Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_CaptureJPEGPicture(userId, channel, jpegPara, newFileUrl);
log.info("[SDK] 抓图成功"+imagePath+":"+imageName);
} else {
log.warn("[SDK] 抓图失败");
}
}
}finally {
Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Logout(userId);
Hikvision截图Demo.HCNetSDK.INSTANCE.NET_DVR_Cleanup();
}
}else {
log.warn("线程池未定义");
}
}
}

View File

@@ -114,7 +114,7 @@ public class Hikvision截图Demo {
int channelSdk = 1;
Hikvision截图Demo.snapshotSdk(ip, (short) port, username, password, channelSdk);
SdkResponse response = HikvisionSnapshotUtil.截图("C://12312/dd", "照片名字");
SdkResponse response = HikvisionSnapshotUtil.截图("照片名字");
if (!response.getSuc()){
System.out.println(response.getMessage());
}

View File

@@ -5,6 +5,7 @@
## 2.测试
1.输入配置摄像头配置ip及账号密码调用Main测试代码确认能否获取到照片
2.如果照片指定的目录不存在,照片捕捉会失败
3.照片路径默认String imagePath = "D://vehicle/"+DateUtil.thisYear();
## 3.项目
yml配置
### hikvision:

View File

@@ -17,6 +17,8 @@ package org.nl.config.thread;
import org.nl.config.SpringContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -27,16 +29,17 @@ import java.util.concurrent.TimeUnit;
* @author Zheng Jie
* @date 2019年10月31日18:16:47
*/
@Configuration
public class ThreadPoolExecutorUtil {
public static ThreadPoolExecutor getPoll(){
AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class);
@Bean(name = "meshandlerPool")
public ThreadPoolExecutor meshandlerPool(){
return new ThreadPoolExecutor(
properties.getCorePoolSize(),
properties.getMaxPoolSize(),
properties.getKeepAliveSeconds(),
4,
16,
30,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(properties.getQueueCapacity()),
new ArrayBlockingQueue<>(64),
new TheadFactoryName()
);
}

View File

@@ -1,22 +1,31 @@
package org.nl.wms.basedata_manage.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.base.TableDataInfo;
import org.nl.common.domain.query.PageQuery;
import org.nl.common.exception.BadRequestException;
import org.nl.common.hikvision.HikvisionSnapshotUtil;
import org.nl.common.logging.annotation.Log;
import org.nl.wms.basedata_manage.service.IBsrealStorattrService;
import org.nl.wms.basedata_manage.service.dao.BsrealStorattr;
import org.springframework.core.io.UrlResource;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
@@ -75,4 +84,24 @@ public class BsrealStorattrController {
iBsrealStorattrService.changeActive(json);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@GetMapping(value = "/image/{filename}")
@SaIgnore
public ResponseEntity<Object> getFile(@PathVariable String filename) {
try {
String imagePath = HikvisionSnapshotUtil.path+ DateUtil.thisYear();
Path file = Paths.get(imagePath).resolve(filename+".jpg");
org.springframework.core.io.Resource resource = new UrlResource(file.toUri());
if (resource.exists() && resource.isReadable()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, Files.probeContentType(file))
.body(resource);
} else {
throw new BadRequestException("文件不存在");
}
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
}
}

View File

@@ -1,11 +1,15 @@
package org.nl.wms.ext.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.BadRequestException;
import org.nl.common.hikvision.HikvisionSnapshotUtil;
import org.nl.wms.basedata_manage.service.IMdPbStoragevehicleinfoService;
import org.nl.wms.basedata_manage.service.dao.MdPbStoragevehicleinfo;
import org.nl.wms.ext.enums.ResultAcsStatus;
@@ -176,7 +180,8 @@ public class AcsToWmsServiceImpl implements AcsToWmsService {
// 调用任务类重量反馈方法
AbstractTask task = taskFactory.getTask(taskDao.getConfig_code());
JSONObject resultWeigh = task.resultWeigh(taskDao);
//调用相机服务保存照片
HikvisionSnapshotUtil.sync截图(vehicleDao.getStoragevehicle_code(),taskDao.getTask_code());
log.info("ACS向WMS反馈重量返回参数--------------------------------------" + BaseResponse.responseOk(resultWeigh).toString());
return BaseResponse.responseOk(resultWeigh);
}

View File

@@ -4,10 +4,10 @@ server:
nl:
config:
mysql:
ip: 127.0.0.1
ip: 192.168.81.251
port: 3306
username: root
password: root
password: P@ssw0rd.
database: xujiang_hanyun_wms
redis:
ip: 127.0.0.1

View File

@@ -86,7 +86,11 @@
<el-table-column prop="material_name" label="物料名称" :min-width="flexWidth('material_name',crud.data,'物料名称')" />
<el-table-column prop="material_spec" label="物料规格" :min-width="flexWidth('material_spec',crud.data,'物料规格')" />
<el-table-column prop="pcsn" label="批次号" :min-width="flexWidth('pcsn',crud.data,'批次号')" />
<el-table-column prop="storagevehicle_code" label="载具号" :min-width="flexWidth('storagevehicle_code',crud.data,'载具号')" />
<el-table-column prop="storagevehicle_code" label="载具号">
<template slot-scope="scope">
<el-link type="warning" @click="toView(scope.row.vehicle_code)">{{ scope.row.storagevehicle_code }}</el-link>
</template>
</el-table-column>
<el-table-column prop="canuse_qty" label="可用数" :formatter="crud.formatNum3" :min-width="100" />
<el-table-column prop="frozen_qty" label="冻结数" :formatter="crud.formatNum3" :min-width="100" />
<el-table-column prop="qty_unit_name" label="计量单位" :min-width="flexWidth('qty_unit_name',crud.data,'计量单位')" />
@@ -98,6 +102,7 @@
</el-table>
<!--分页组件-->
<pagination />
<image-modal :visible.sync="showModal" :image-url="imageUrl" />
</div>
</div>
</template>
@@ -111,10 +116,11 @@ import pagination from '@crud/Pagination'
import crudSectattr from '@/views/wms/basedata/sectattr/sectattr'
import { download } from '@/api/data'
import { downloadFile } from '@/utils'
import imageModal from './image'
export default {
name: 'Structivt',
components: { pagination, crudOperation, rrOperation },
components: { pagination, crudOperation, rrOperation, imageModal },
mixins: [presenter(), header(), crud()],
cruds() {
return CRUD({
@@ -133,6 +139,8 @@ export default {
data() {
return {
sects: [],
showModal: false,
imageUrl: '',
permission: {},
rules: {}
}
@@ -150,6 +158,14 @@ export default {
hand(value) {
this.crud.toQuery()
},
toView(vehicle) {
this.showModal = true
crudStructivt.imageLoad('110').then(response => {
const blob = new Blob([response]) // 尽可能根据响应头确定类型
this.imageUrl = URL.createObjectURL(blob)
}
)
},
sectQueryChange(val) {
if (val.length === 1) {
this.query.stor_id = val[0]

View File

@@ -86,4 +86,12 @@ export function unIvtLock(data) {
})
}
export default { add, edit, del, getStruct, getStructById, getUnits, save, excelImport, statusChange, ivtLock, unIvtLock }
export function imageLoad(name) {
return request({
url: '/api/Storattr/image/' + name,
method: 'get',
responseType: 'blob'
})
}
export default { add, edit, del, getStruct, imageLoad, getStructById, getUnits, save, excelImport, statusChange, ivtLock, unIvtLock }