feat(plugin): 优化EMQX插件功能并增强设备管理

- 在application.yml中将运行模式从prod改为dev
- 在application-dev.yml中添加generate_statistics配置项以关闭统计信息
- 在AuthVerticle.java中添加MQTT ACL主题路径转换逻辑
- 在DeviceInfoDataCache.java和DeviceInfoDataImpl.java中增加设备状态查询方法
- 在DeviceInfoExpordVo和DeviceInfoImportVo中新增site字段用于设备位置导出导入
- 在DeviceInstallInfo.java中添加多个图片相关字段如泡沫水测漏图片、设备信息图片、门牌号图片
- 在DeviceInstallInfoDataImpl.java中实现findById方法
- 在DeviceInstallInfoExpordVo和DeviceInstallInfoVo中添加切断阀编号和报警器编号导出功能
- 在DeviceInstallInfoServiceImpl.java中完善安装信息查询逻辑
- 在DeviceManagerServiceImpl.java中支持设备状态查询参数
- 在DeviceQueryBo.java中新增deviceStatus字段用于设备状态筛选
- 在feijialuo-emqx-plugin中优化线程池配置并提升并发处理能力
- 在iot-iita-emqx-plugin中调整设备识别规则适配不同平台需求
master
alsszer 2 months ago
parent 145fc94b34
commit 34c2a5f8b4

@ -77,6 +77,8 @@ public class DeviceInstallInfo extends TenantModel implements Owned<String>,Seri
private String workingOfTheDetectorImage;
// @ApiModelProperty(value = "测漏图片")
private String sideLeakageImage;
// @ApiModelProperty(value = "泡沫水测漏图片")
private String formSideLeakageImage;
// @ApiModelProperty(value = "点火图片")
private String ignitionPictureImage;
// @ApiModelProperty(value = "装完成全景图片")
@ -87,6 +89,10 @@ public class DeviceInstallInfo extends TenantModel implements Owned<String>,Seri
private String workOrderImage;
//@ApiModelProperty(value = "打孔图片")
private String punchingImage;
//@ApiModelProperty(value = "设备信息图片")
private String deviceInfoImage;
//@ApiModelProperty(value = "门牌号图片")
private String houseNumberImage;
// @ApiModelProperty(value = "用户id")
private String uid;
// @ApiModelProperty(value = "租户编号")

@ -114,6 +114,9 @@ public interface IDeviceInfoData extends IOwnedData<DeviceInfo, String> {
* @param page
* @param size
*/
Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey,
String groupId, Boolean online, String keyword,
int page, int size,Long areaDepeId,String startTime,String endTime,String deviceName,Integer deviceStatus);
Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey,
String groupId, Boolean online, String keyword,
int page, int size,Long areaDepeId,String startTime,String endTime,String deviceName);

@ -33,4 +33,6 @@ public interface IDeviceInstallInfoData extends IOwnedData<DeviceInstallInfo, St
DeviceInstallInfo findByDeviceNameAndUid(String deviceName,String uid);
DeviceInstallInfo findByDeviceNameAndUidAndState(String deviceName,String uid,Integer state);
DeviceInstallInfo findById(String id);
}

@ -85,4 +85,6 @@ public interface ISysRoleData extends ICommonData<SysRole, Long> {
List<SysRole> selectRoleList(SysRole role);
List<SysRole> findByUserId(Long id);
List<SysRole> selectByTenantId(Long tenantId);
}

@ -244,6 +244,12 @@ public class DeviceInfoDataCache implements IDeviceInfoData, SmartInitializingSi
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime,String deviceName) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId,startTime,endTime,deviceName);
}
@Override
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey,
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime,String deviceName,Integer deviceStatus) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId,startTime,endTime,deviceName,deviceStatus);
}
@Override
public Paging<DeviceInfo> findByConditionsExcel(String name,String uid, String subUid, String productKey,
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {

@ -202,6 +202,11 @@ public class DeviceInfoPropertyDataCache implements IDeviceInfoData {
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime,String deviceName) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime,endTime,deviceName);
}
@Override
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime,String deviceName,Integer deviceStatus) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime,endTime,deviceName,deviceStatus);
}
@Override
public Paging<DeviceInfo> findByConditionsExcel(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditionsExcel(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime,endTime);

@ -86,6 +86,8 @@ public class TbDeviceInstallInfo extends BaseEntity implements TenantAware {
private String workingOfTheDetectorImage;
@ApiModelProperty(value = "测漏图片")
private String sideLeakageImage;
@ApiModelProperty(value = "泡沫水测漏图片")
private String formSideLeakageImage;
@ApiModelProperty(value = "点火图片")
private String ignitionPictureImage;
@ApiModelProperty(value = "装完成全景图片")
@ -98,6 +100,10 @@ public class TbDeviceInstallInfo extends BaseEntity implements TenantAware {
private String punchingImage;
@ApiModelProperty(value = "装电源线照片")
private String fiexImage;
@ApiModelProperty(value = "设备信息图片")
private String deviceInfoImage;
@ApiModelProperty(value = "门牌号图片")
private String houseNumberImage;
@ApiModelProperty(value = "用户id")
private String uid;

@ -637,7 +637,7 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
public Paging<DeviceInfo> findByConditions(String name, String uid, String subUid,
String productKey, String groupId,
Boolean online, String keyword,
int page, int size, Long deptAreaId,String startTime,String endTime,String deviceName) {
int page, int size, Long deptAreaId,String startTime,String endTime,String deviceName,Integer deviceStatus) {
JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
// 根据groupId, 如果groupId存在则关联查询TbDeviceGroupMapping, 根据groupId,查询对应的devices
@ -677,6 +677,21 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
if (ObjectUtil.isNotEmpty(areaIds)) {*/
if(deptAreaId != 0) {
query.where(tbDeviceInfo.deptAreaId.in(deptAreaId));
} else {
if(ObjectUtil.isNotEmpty(LoginHelper.getUserId())) {
SysUser user = isSysUserData.findById(LoginHelper.getUserId());
if (ObjectUtil.isNotNull(user)) {
if (ObjectUtil.isNotNull(user.getDeptAreaId())) {
Long deptAreaId1 = user.getDeptAreaId();
// 根据部门id获取部门对象
SysDept dept = sysDeptData.findById(deptAreaId1);
if(dept.getParentId()!=0l){
// 说明为子部门 筛选条件为部门id
query.where(tbDeviceInfo.deptAreaId.eq(deptAreaId1));
}
}
}
}
}
// query.where(tbDeviceInfo.deptAreaId.in(deptAreaId));
// }
@ -717,6 +732,128 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
query.where(tbDeviceInfo.productKey.eq(productKey));
}
if(ObjectUtil.isNotNull(deviceStatus)){
query.where(tbDeviceInfo.deviceStatus.eq(deviceStatus));
}
if (online != null) {
query.where(tbDeviceInfo.state.eq(online ? "online" : "offline"));
}
if (StringUtils.isNotBlank(keyword)) {
query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%")
.or(tbDeviceInfo.deviceName.like("%" + keyword + "%")));
}
if (ObjectUtil.isNotNull(startTime)&& ObjectUtil.isNotNull(endTime)) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDateTime = sdf.parse(startTime);
Date dateTime = sdf.parse(endTime);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime startDateTime = LocalDateTime.parse(dictData.getStartTime() , formatter);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime dateTime = LocalDateTime.parse(dictData.getEndTime(), formatter);
query.where(tbDeviceInfo.createTime.between(startDateTime, dateTime));
} catch (Exception e) {
}
}
query.orderBy(tbDeviceInfo.createAt.desc());
query.offset((page - 1) * size).limit(size);
List<TbDeviceInfo> tbDeviceInfos = query.fetch();
long total = query.fetchCount();
List<DeviceInfo> deviceInfos = new ArrayList<>(tbDeviceInfos.size());
for (TbDeviceInfo tbDeviceInfo : tbDeviceInfos) {
DeviceInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInfo.class);
fillDeviceInfo(tbDeviceInfo.getDeviceId(), tbDeviceInfo, deviceInfo);
deviceInfos.add(deviceInfo);
}
return new Paging<>(total, deviceInfos);
}
public Paging<DeviceInfo> findByConditions(String name, String uid, String subUid,
String productKey, String groupId,
Boolean online, String keyword,
int page, int size, Long deptAreaId,String startTime,String endTime,String deviceName) {
JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
// 根据groupId, 如果groupId存在则关联查询TbDeviceGroupMapping, 根据groupId,查询对应的devices
if (StringUtils.isNotBlank(groupId)) {
if(!groupId.equals("0")){
query.join(tbDeviceGroupMapping).on(tbDeviceGroupMapping.deviceId.eq(tbDeviceInfo.deviceId));
// query.where(tbDeviceGroupMapping.groupId.eq(groupId));
query.where(tbDeviceGroupMapping.groupId.eq(groupId));
}
}else{
query.join(tbDeviceGroupMapping).on(tbDeviceGroupMapping.deviceId.eq(tbDeviceInfo.deviceId));
query.where(tbDeviceGroupMapping.groupId.isNull());
}
if (StringUtils.isNotBlank(uid)) {
query.where(tbDeviceInfo.uid.eq(uid));
}
if (StringUtils.isNotBlank(name)) {
query.where(tbDeviceInfo.name.like("%" + name + "%"));
}
if (StringUtils.isNotBlank(deviceName)) {
query.where(tbDeviceInfo.deviceName.like("%" + deviceName + "%"));
}
System.out.println(TenantHelper.getTenantId());
if (ObjectUtil.isNotNull(TenantHelper.getTenantId()) && (!LoginHelper.isSuperAdmin() || TenantHelper.getTenantId()!=0)) {
query.where(tbDeviceInfo.tenantId.eq(TenantHelper.getTenantId()));
}
if (ObjectUtil.isNotNull(deptAreaId)) {
/* List<Long> areaIds;
// if (Objects.nonNull(user) && Objects.nonNull(user.getDeptAreaId())) {
Long areaId = deptAreaId;
List<SysDept> depts = sysDeptData.findByDeptId(areaId);
areaIds = StreamUtils.toList(depts, SysDept::getId);
areaIds.add(areaId);
if (ObjectUtil.isNotEmpty(areaIds)) {*/
if(deptAreaId != 0) {
query.where(tbDeviceInfo.deptAreaId.in(deptAreaId));
}
// query.where(tbDeviceInfo.deptAreaId.in(deptAreaId));
// }
}else{
if(!LoginHelper.isSuperAdmin()) {
if(ObjectUtil.isNotEmpty(LoginHelper.getUserId())) {
SysUser user = isSysUserData.findById(LoginHelper.getUserId());
if (ObjectUtil.isNotNull(user)) {
if (ObjectUtil.isNotNull(user.getDeptAreaId())) {
/* List<Long> areaIds;
// if (Objects.nonNull(user) && Objects.nonNull(user.getDeptAreaId())) {
Long areaId = user.getDeptAreaId();
List<SysDept> depts = sysDeptData.findByDeptId(areaId);
areaIds = StreamUtils.toList(depts, SysDept::getId);
areaIds.add(areaId);
if (ObjectUtil.isNotEmpty(areaIds)) {*/
query.where(tbDeviceInfo.deptAreaId.in(user.getDeptAreaId()));
// }
} else {
if(ObjectUtil.isNotEmpty(LoginHelper.getUserType()) && !LoginHelper.getUserType().equals(UserType.APP_USER)) {
//没有绑定区域查不到设备
query.where(tbDeviceInfo.id.eq("0"));
}
}
}
}
}else{
query.where(tbDeviceInfo.deptAreaId.isNull());
}
}
if (StringUtils.isNotBlank(subUid)) {
query.join(tbDeviceSubUser).on(tbDeviceSubUser.deviceId.eq(tbDeviceInfo.deviceId));
query.where(tbDeviceSubUser.uid.eq(subUid));
}
if (StringUtils.isNotBlank(productKey)) {
query.where(tbDeviceInfo.productKey.eq(productKey));
}
if (online != null) {
query.where(tbDeviceInfo.state.eq(online ? "online" : "offline"));
}

@ -77,4 +77,10 @@ public class DeviceInstallInfoDataImpl implements IDeviceInstallInfoData, IJPACo
public DeviceInstallInfo findByDeviceNameAndUidAndState(String deviceName, String uid, Integer state) {
return MapstructUtils.convert(homeRepository.findByDeviceNameAndUidAndState(deviceName,uid,state), DeviceInstallInfo.class);
}
@Override
public DeviceInstallInfo findById(String id) {
TbDeviceInstallInfo tbDeviceInstallInfo = homeRepository.findById(id).orElse(null);
return MapstructUtils.convert(tbDeviceInstallInfo, DeviceInstallInfo.class);
}
}

@ -222,6 +222,15 @@ public class SysRoleDataImpl implements ISysRoleData, IJPACommData<SysRole, Long
.fetch();
}
@Override
public List<SysRole> selectByTenantId(Long tenantId) {
return jpaQueryFactory.select(Projections.bean(SysRole.class, tbSysRole.id, tbSysRole.roleName, tbSysRole.roleKey, tbSysRole.roleSort, tbSysRole.dataScope, tbSysRole.status, tbSysRole.delFlag, tbSysRole.createTime, tbSysRole.remark))
.from(tbSysRole)
.where(PredicateBuilder.instance()
.and(tbSysRole.tenantId.eq(tenantId))
.build()).fetch();
}
private List<SysRole> buildQueryTitle(Predicate predicate) {
return jpaQueryFactory.selectDistinct(tbSysRole.id)
.select(Projections.fields(SysRole.class, tbSysRole.id, tbSysRole.roleName,

@ -13,13 +13,34 @@ import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class PDFGenerator {
// 缓存字体实例以避免重复加载
private static volatile PDType0Font cachedFont = null;
private static final Object fontLock = new Object();
// 缓存已处理的图片以避免重复下载和处理
private static final ConcurrentHashMap<String, PDImageXObject> imageCache = new ConcurrentHashMap<>();
// 线程池用于并发处理图片
private static final ExecutorService imageProcessingPool = Executors.newFixedThreadPool(4);
// 1. 表格参数配置
// 参数配置(优化后)
@ -33,9 +54,13 @@ public class PDFGenerator {
private static final float[] COLUMN_WIDTHS = {LEFT_COL_WIDTH, RIGHT_COL_WIDTH};
private static final float MIN_IMAGE_HEIGHT = 50;
public static void generateInstallationPDF(DeviceInstallInfo entity, OutputStream outputStream) throws IOException {
// 首先生成PDF内容到字节数组
ByteArrayOutputStream pdfBaos = new ByteArrayOutputStream();
try (PDDocument document = new PDDocument()) {
// 加载字体(需替换实际路径)
//PDType0Font font = PDType0Font.load(document, new File("D:\\NotoSansCJK-Regular.ttf"));
// PDType0Font font = PDType0Font.load(document, new File("D:\\NotoSansCJK-Regular.ttf"));
//PDType0Font font = PDType0Font.load(document, new File("/ttf/simsun.ttf"));
PDType0Font font = PDType0Font.load(document, new File("/ttf/NotoSansCJK-Regular.ttf"));
// 初始化第一页
@ -76,15 +101,18 @@ public class PDFGenerator {
// 图片处理(带自动分页)
// 图片处理(带自动分页)
List<String[]> imageGroups = Arrays.asList(
new String[]{entity.getDeviceInfoImage(), "设备信息图片"},
new String[]{entity.getBeforeInstallationImage(), "安装前图片"},
new String[]{entity.getWorkingOfTheDetectorImage(), "安装完成探测器工作图片"},
new String[]{entity.getSideLeakageImage(), "测漏图片"},
new String[]{entity.getFormSideLeakageImage(), "泡沫水测漏图片"},
new String[]{entity.getIgnitionPictureImage(), "点火图片"},
new String[]{entity.getInstallThePanoramicImage(), "安装完成全景图片"},
new String[]{entity.getOfGasMeterImage(), "燃气表图片"},
new String[]{entity.getOfGasMeterImage(), "燃气表图片"},
new String[]{entity.getWorkOrderImage(), "工单图片"},
new String[]{entity.getPunchingImage(), "打孔图片"},
new String[]{entity.getFiexImage(), "安装电源线图片"}
new String[]{entity.getFiexImage(), "安装电源线图片"},
new String[]{entity.getHouseNumberImage(), "门牌号图片"}
);
for (String[] group : imageGroups) {
@ -98,27 +126,61 @@ public class PDFGenerator {
.collect(Collectors.toList());
if (!validUrls.isEmpty()) {
// float totalHeight = calculateTotalHeight(validUrls);
List<String> wrappedTitleLines = wrapText(title,LEFT_COL_WIDTH - 2 * CELL_PADDING);
float titleHeight = wrappedTitleLines.size() * LINE_HEIGHT;
// 计算图片组的自适应高度
float imagesHeight = calculateAdjustedImagesHeight(document, validUrls,
RIGHT_COL_WIDTH - 2 * CELL_PADDING,
PDRectangle.A4.getHeight() - 2 * TABLE_MARGIN - titleHeight);
float totalHeight = Math.max(imagesHeight, titleHeight);
if (currentY < TABLE_MARGIN + Math.max(totalHeight, titleHeight)) {
cs.close();
currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
cs = new PDPageContentStream(document, currentPage);
currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
// 处理可能需要跨页的多图片情况
if (validUrls.size() > 2) {
// 对于多于2张的图片逐个或分组处理以支持跨页
for (int i = 0; i < validUrls.size(); i += 2) { // 每次处理最多2张图片
List<String> subList = validUrls.subList(i,
Math.min(i + 2, validUrls.size()));
List<String> wrappedTitleLines = wrapText(title,LEFT_COL_WIDTH - 2 * CELL_PADDING);
float titleHeight = wrappedTitleLines.size() * LINE_HEIGHT;
// 计算图片组的自适应高度
float imagesHeight = calculateAdjustedImagesHeight(document, subList,
RIGHT_COL_WIDTH - 2 * CELL_PADDING,
PDRectangle.A4.getHeight() - 2 * TABLE_MARGIN - titleHeight);
float totalHeight = Math.max(imagesHeight, titleHeight);
if (currentY < TABLE_MARGIN + Math.max(totalHeight, titleHeight)) {
cs.close();
currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
cs = new PDPageContentStream(document, currentPage);
currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
}
// 添加标识,表明这是多图片的一部分
String subTitle = title + " (" + (i+1) + "-" + Math.min(i+2, validUrls.size()) + "/" + validUrls.size() + ")";
List<String> subWrappedTitleLines = wrapText(subTitle, LEFT_COL_WIDTH - 2 * CELL_PADDING);
drawImageGroup(cs, document, font, subWrappedTitleLines, subList, currentY,
Math.max(totalHeight, titleHeight));
currentY -= Math.max(totalHeight, titleHeight);
}
} else {
// 原有的单/双图片处理逻辑
List<String> wrappedTitleLines = wrapText(title,LEFT_COL_WIDTH - 2 * CELL_PADDING);
float titleHeight = wrappedTitleLines.size() * LINE_HEIGHT;
// 计算图片组的自适应高度
float imagesHeight = calculateAdjustedImagesHeight(document, validUrls,
RIGHT_COL_WIDTH - 2 * CELL_PADDING,
PDRectangle.A4.getHeight() - 2 * TABLE_MARGIN - titleHeight);
float totalHeight = Math.max(imagesHeight, titleHeight);
if (currentY < TABLE_MARGIN + Math.max(totalHeight, titleHeight)) {
cs.close();
currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
cs = new PDPageContentStream(document, currentPage);
currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
}
drawImageGroup(cs, document, font, wrappedTitleLines, validUrls, currentY,
Math.max(totalHeight, titleHeight));
currentY -= Math.max(totalHeight, titleHeight);
}
drawImageGroup(cs, document, font, wrappedTitleLines, validUrls, currentY,
Math.max(totalHeight, titleHeight));
currentY -= Math.max(totalHeight, titleHeight);
}
}
}
@ -126,20 +188,94 @@ public class PDFGenerator {
} finally {
cs.close();
}
// document.save("D:/output.pdf");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
outputStream.flush();
baos.writeTo(outputStream);
// document.save(outputStream);
// 将PDF保存到ByteArrayOutputStream
document.save(pdfBaos);
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// document.save(baos);
// outputStream.flush();
// baos.writeTo(outputStream);
}
// 创建ZIP压缩包并将PDF写入输出流
try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
// 设置最高压缩级别
zipOut.setLevel(Deflater.BEST_COMPRESSION);
// 创建ZIP条目
ZipEntry entry = new ZipEntry(entity.getUserName()+entity.getCommunityName()+entity.getBuildingUnit()+entity.getRoomNo()+".pdf");
zipOut.putNextEntry(entry);
// 将PDF数据写入ZIP
byte[] pdfBytes = pdfBaos.toByteArray();
zipOut.write(pdfBytes, 0, pdfBytes.length);
// 关闭当前条目
zipOut.closeEntry();
}
}
// 加载字体,确保使用正确的文档实例
private static PDType0Font loadFont(PDDocument document) throws IOException {
// 尝试多个可能的字体路径
String[] fontPaths = {
"D:\\NotoSansCJK-Regular.ttf",
"C:\\Windows\\Fonts\\simsun.ttc",
"C:\\Windows\\Fonts\\msyh.ttc",
"/System/Library/Fonts/Helvetica.dfont", // macOS
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" // Linux
};
for (String path : fontPaths) {
if (Files.exists(Paths.get(path))) {
try {
return PDType0Font.load(document, new File(path));
} catch (IOException e) {
continue; // 尝试下一个字体文件
}
}
}
return PDType0Font.load(document, new File("/ttf/NotoSansCJK-Regular.ttf"));
}
// 缓存已处理的图片以避免重复下载和处理
private static final ConcurrentHashMap<String, byte[]> imageByteCache = new ConcurrentHashMap<>();
// 预加载图片以避免重复下载
private static PDImageXObject loadImageFromUrl(PDDocument document, String url) throws IOException {
byte[] imageBytes = imageByteCache.computeIfAbsent(url, key -> {
try {
return new URL(key).openStream().readAllBytes();
} catch (IOException e) {
return null; // 或者抛出异常
}
});
if (imageBytes == null) {
return null;
}
return PDImageXObject.createFromByteArray(document, imageBytes, "");
}
private static List<String> wrapText(String text, float maxWidth) {
List<String> lines = new ArrayList<>();
int maxCharsPerLine = (int)(maxWidth / (FONT_SIZE * 0.5f)); // 中文字符估算
if (text == null || text.isEmpty()) return lines;
// 优化的文本换行逻辑,减少计算量
int maxCharsPerLine = (int)(maxWidth / (FONT_SIZE * 0.4f)); // 调整字符估算系数
if (text.length() <= maxCharsPerLine) {
lines.add(text);
return lines;
}
StringBuilder currentLine = new StringBuilder();
for (String word : text.split("")) {
String[] words = text.split("");
for (String word : words) {
if (currentLine.length() + word.length() <= maxCharsPerLine) {
currentLine.append(word);
} else {
@ -152,6 +288,24 @@ public class PDFGenerator {
}
return lines;
}
// private static List<String> wrapText(String text, float maxWidth) {
// List<String> lines = new ArrayList<>();
// int maxCharsPerLine = (int)(maxWidth / (FONT_SIZE * 0.5f)); // 中文字符估算
//
// StringBuilder currentLine = new StringBuilder();
// for (String word : text.split("")) {
// if (currentLine.length() + word.length() <= maxCharsPerLine) {
// currentLine.append(word);
// } else {
// lines.add(currentLine.toString());
// currentLine = new StringBuilder(word);
// }
// }
// if (currentLine.length() > 0) {
// lines.add(currentLine.toString());
// }
// return lines;
// }
private static float calculateTotalHeight(List<String> imageUrls) throws IOException {
@ -263,7 +417,7 @@ public class PDFGenerator {
// 绘制标题(垂直居中)
float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
// 绘制第一行标题(顶部)
// float titleY = startY - CELL_PADDING - FONT_SIZE;
// float titleY = startY - CELL_PADDING - FONT_SIZE;
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
@ -275,19 +429,20 @@ public class PDFGenerator {
cs.endText();
// 绘制第一行图片(自动缩放)
PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
singleImageHeight / image1.getHeight()
);
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
PDImageXObject image1 = loadImageFromUrl(doc, imageUrls.get(0));
if (image1 != null) {
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
singleImageHeight / image1.getHeight()
);
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
}
} else if (imageUrls.size() == 2) {
// 双图片模式:改为上下布局
@ -306,34 +461,37 @@ public class PDFGenerator {
cs.endText();
// 绘制第一张图片(上)
PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
imageHeightPer / image1.getHeight()
);
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
PDImageXObject image1 = loadImageFromUrl(doc, imageUrls.get(0));
float scaledHeight1 = 0;
if (image1 != null) {
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
imageHeightPer / image1.getHeight()
);
scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
}
// 绘制第二张图片(下)
PDImageXObject image2 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(1)).openStream().readAllBytes(), "embedded-image");
float scale2 = Math.min(
imageAvailableWidth / image2.getWidth(),
imageHeightPer / image2.getHeight()
);
float scaledHeight2 = image2.getHeight() * scale2;
float scaledWidth2 = image2.getWidth() * scale2;
PDImageXObject image2 = loadImageFromUrl(doc, imageUrls.get(1));
if (image2 != null) {
float scale2 = Math.min(
imageAvailableWidth / image2.getWidth(),
imageHeightPer / image2.getHeight()
);
float scaledHeight2 = image2.getHeight() * scale2;
float scaledWidth2 = image2.getWidth() * scale2;
cs.drawImage(image2,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1 - CELL_PADDING - scaledHeight2,
scaledWidth2, scaledHeight2);
cs.drawImage(image2,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1 - CELL_PADDING - scaledHeight2,
scaledWidth2, scaledHeight2);
}
/* // 双图片模式:一行并列显示
float imageWidthPer = (imageAvailableWidth - CELL_PADDING) / 2;
@ -378,8 +536,239 @@ public class PDFGenerator {
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING + imageWidthPer + CELL_PADDING,
startY - CELL_PADDING - scaledHeight2,
scaledWidth2, scaledHeight2);*/
}else {
// 多图片模式超过2张图片垂直堆叠显示与双图片模式保持一致的样式
float imageHeightPer = (imageAvailableHeight - CELL_PADDING * (imageUrls.size() - 1)) / imageUrls.size();
// 绘制标题(垂直居中)
float titleY = startY - totalHeight / 2 + (titleLines.size() * LINE_HEIGHT) / 2;
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
for (String line : titleLines) {
cs.showText(line);
titleY -= LINE_HEIGHT;
cs.newLineAtOffset(0, -LINE_HEIGHT);
}
cs.endText();
// 绘制所有图片,采用与单/双图片一致的样式
float currentY = startY - CELL_PADDING;
for (int i = 0; i < imageUrls.size(); i++) {
PDImageXObject image = loadImageFromUrl(doc, imageUrls.get(i));
if (image == null) continue; // 跳过加载失败的图片
float scale = Math.min(
imageAvailableWidth / image.getWidth(),
imageHeightPer / image.getHeight()
);
float scaledHeight = image.getHeight() * scale;
float scaledWidth = image.getWidth() * scale;
// 检查是否需要跨页
if (currentY - scaledHeight - CELL_PADDING < TABLE_MARGIN) {
// 当前页面空间不足,需要跨页
// 这里需要在实际应用中处理跨页逻辑
// 由于在单个drawImageGroup方法中无法直接创建新页面
// 需要在调用此方法的循环中处理跨页
break; // 暂停绘制剩余图片,由外部循环处理跨页
}
// 绘制当前图片
cs.drawImage(image,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
currentY - scaledHeight,
scaledWidth, scaledHeight);
// 更新下一个图片的起始Y坐标
currentY -= (scaledHeight + CELL_PADDING);
}
}
}
// private static void drawImageGroup(PDPageContentStream cs, PDDocument doc, PDType0Font font,
// List<String> titleLines, List<String> imageUrls,
// float startY, float totalHeight) throws IOException {
// // 绘制单元格边框
// cs.setLineWidth(0.5f);
// cs.addRect(TABLE_MARGIN, startY - totalHeight, LEFT_COL_WIDTH, totalHeight);
// cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, startY - totalHeight, RIGHT_COL_WIDTH, totalHeight);
// cs.stroke();
//
// // 计算每张图片的可用高度(根据图片数量动态调整)
// float imageAvailableHeight = totalHeight - 2 * CELL_PADDING;
// float imageAvailableWidth = RIGHT_COL_WIDTH - 2 * CELL_PADDING;
//
// if (imageUrls.size() == 1) {
// // 单图片模式:一页两行,每行占半页高度
// float singleImageHeight = imageAvailableHeight;
// // 绘制标题(垂直居中)
// float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
// // 绘制第一行标题(顶部)
// // float titleY = startY - CELL_PADDING - FONT_SIZE;
// cs.beginText();
// cs.setFont(font, FONT_SIZE);
// cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
// for (String line : titleLines) {
// cs.showText(line);
// titleY -= LINE_HEIGHT;
// cs.newLineAtOffset(0, -LINE_HEIGHT);
// }
// cs.endText();
//
// // 绘制第一行图片(自动缩放)
// PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
// float scale1 = Math.min(
// imageAvailableWidth / image1.getWidth(),
// singleImageHeight / image1.getHeight()
// );
// float scaledHeight1 = image1.getHeight() * scale1;
// float scaledWidth1 = image1.getWidth() * scale1;
//
// cs.drawImage(image1,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
// startY - CELL_PADDING - scaledHeight1,
// scaledWidth1, scaledHeight1);
//
// } else if (imageUrls.size() == 2) {
// // 双图片模式:改为上下布局
// float imageHeightPer = (imageAvailableHeight - CELL_PADDING) / 2;
//
// // 绘制标题(垂直居中)
// float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
// cs.beginText();
// cs.setFont(font, FONT_SIZE);
// cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
// for (String line : titleLines) {
// cs.showText(line);
// titleY -= LINE_HEIGHT;
// cs.newLineAtOffset(0, -LINE_HEIGHT);
// }
// cs.endText();
//
// // 绘制第一张图片(上)
// PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
// float scale1 = Math.min(
// imageAvailableWidth / image1.getWidth(),
// imageHeightPer / image1.getHeight()
// );
// float scaledHeight1 = image1.getHeight() * scale1;
// float scaledWidth1 = image1.getWidth() * scale1;
//
// cs.drawImage(image1,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
// startY - CELL_PADDING - scaledHeight1,
// scaledWidth1, scaledHeight1);
//
// // 绘制第二张图片(下)
// PDImageXObject image2 = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(1)).openStream().readAllBytes(), "embedded-image");
// float scale2 = Math.min(
// imageAvailableWidth / image2.getWidth(),
// imageHeightPer / image2.getHeight()
// );
// float scaledHeight2 = image2.getHeight() * scale2;
// float scaledWidth2 = image2.getWidth() * scale2;
//
// cs.drawImage(image2,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
// startY - CELL_PADDING - scaledHeight1 - CELL_PADDING - scaledHeight2,
// scaledWidth2, scaledHeight2);
// /* // 双图片模式:一行并列显示
// float imageWidthPer = (imageAvailableWidth - CELL_PADDING) / 2;
//
// // 绘制标题(垂直居中)
// float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
// cs.beginText();
// cs.setFont(font, FONT_SIZE);
// cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
// for (String line : titleLines) {
// cs.showText(line);
// titleY -= LINE_HEIGHT;
// cs.newLineAtOffset(0, -LINE_HEIGHT);
// }
// cs.endText();
//
// // 绘制第一张图片(左)
// PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
// float scale1 = Math.min(
// imageWidthPer / image1.getWidth(),
// imageAvailableHeight / image1.getHeight()
// );
// float scaledHeight1 = image1.getHeight() * scale1;
// float scaledWidth1 = image1.getWidth() * scale1;
//
// cs.drawImage(image1,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
// startY - CELL_PADDING - scaledHeight1,
// scaledWidth1, scaledHeight1);
//
// // 绘制第二张图片(右)
// PDImageXObject image2 = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(1)).openStream().readAllBytes(), "embedded-image");
// float scale2 = Math.min(
// imageWidthPer / image2.getWidth(),
// imageAvailableHeight / image2.getHeight()
// );
// float scaledHeight2 = image2.getHeight() * scale2;
// float scaledWidth2 = image2.getWidth() * scale2;
//
// cs.drawImage(image2,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING + imageWidthPer + CELL_PADDING,
// startY - CELL_PADDING - scaledHeight2,
// scaledWidth2, scaledHeight2);*/
// }else {
// // 多图片模式超过2张图片垂直堆叠显示与双图片模式保持一致的样式
// float imageHeightPer = (imageAvailableHeight - CELL_PADDING * (imageUrls.size() - 1)) / imageUrls.size();
//
// // 绘制标题(垂直居中)
// float titleY = startY - totalHeight / 2 + (titleLines.size() * LINE_HEIGHT) / 2;
// cs.beginText();
// cs.setFont(font, FONT_SIZE);
// cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
// for (String line : titleLines) {
// cs.showText(line);
// titleY -= LINE_HEIGHT;
// cs.newLineAtOffset(0, -LINE_HEIGHT);
// }
// cs.endText();
//
// // 绘制所有图片,采用与单/双图片一致的样式
// float currentY = startY - CELL_PADDING;
// for (int i = 0; i < imageUrls.size(); i++) {
// PDImageXObject image = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrls.get(i)).openStream().readAllBytes(), "embedded-image");
// float scale = Math.min(
// imageAvailableWidth / image.getWidth(),
// imageHeightPer / image.getHeight()
// );
// float scaledHeight = image.getHeight() * scale;
// float scaledWidth = image.getWidth() * scale;
//
// // 检查是否需要跨页
// if (currentY - scaledHeight - CELL_PADDING < TABLE_MARGIN) {
// // 当前页面空间不足,需要跨页
// // 这里需要在实际应用中处理跨页逻辑
// // 由于在单个drawImageGroup方法中无法直接创建新页面
// // 需要在调用此方法的循环中处理跨页
// break; // 暂停绘制剩余图片,由外部循环处理跨页
// }
//
// // 绘制当前图片
// cs.drawImage(image,
// TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
// currentY - scaledHeight,
// scaledWidth, scaledHeight);
//
// // 更新下一个图片的起始Y坐标
// currentY -= (scaledHeight + CELL_PADDING);
// }
// }
// }
private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
float maxWidth, float maxHeight) throws IOException {
if (imageUrls.isEmpty()) return 0;
@ -388,9 +777,23 @@ public class PDFGenerator {
if (imageUrls.size() == 1) {
// 单图片模式:占用半页高度
return maxHeight / 2;
} else {
} else if(imageUrls.size() == 2){
// 双图片模式:整页高度
return maxHeight;
}else {
// 多图片模式:根据图片数量动态计算高度
// 每张图片预留最小高度,防止页面过长
float minImageHeight = 50f; // 每张图片最小高度
float imageSpacing = 5f; // 图片间距
float totalSpacing = (imageUrls.size() - 1) * imageSpacing;
float estimatedHeight = (minImageHeight * imageUrls.size()) + totalSpacing;
// 如果估算高度超过页面可用高度,则返回最大高度,需要分页处理
if (estimatedHeight > maxHeight) {
return maxHeight;
}
return estimatedHeight;
}
}
@ -652,13 +1055,13 @@ public class PDFGenerator {
}
private static float addImageRow(PDPageContentStream cs, PDDocument doc,
PDType0Font font, String title, String imageUrl,
float startX, float startY) throws IOException {
// 加载图片
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(imageUrl).openStream().readAllBytes(), "embedded-image");
PDImageXObject image = loadImageFromUrl(doc, imageUrl);
if (image == null) return startY; // 如果图片加载失败,返回原位置
// 动态计算尺寸
float imageWidth = RIGHT_COL_WIDTH - 10;
float scale = imageWidth / image.getWidth();
@ -725,6 +1128,79 @@ public class PDFGenerator {
return startY - dynamicRowHeight - 10;*/
}
// private static float addImageRow(PDPageContentStream cs, PDDocument doc,
// PDType0Font font, String title, String imageUrl,
// float startX, float startY) throws IOException {
// // 加载图片
// PDImageXObject image = PDImageXObject.createFromByteArray(doc,
// new URL(imageUrl).openStream().readAllBytes(), "embedded-image");
// // 动态计算尺寸
// float imageWidth = RIGHT_COL_WIDTH - 10;
// float scale = imageWidth / image.getWidth();
// float imageHeight = image.getHeight() * scale;
// float rowHeight = imageHeight + 20;
//
// // 绘制单元格边框
// cs.setLineWidth(0.5f);
// cs.addRect(startX, startY - rowHeight, LEFT_COL_WIDTH, rowHeight);
// cs.addRect(startX + LEFT_COL_WIDTH, startY - rowHeight, RIGHT_COL_WIDTH, rowHeight);
// cs.stroke();
//
// // 垂直居中文本(改进算法)
// float textY = startY - rowHeight/2 + FONT_SIZE/2;
// //String title = "安装完成探测器工作图片\n检测时间2025-08-14";
//
// /* if(title.contains("\n")){
// String[] lines = title.split("\n");
// textY = startY - rowHeight/2 + FONT_SIZE/2 + (lines.length-1)*FONT_SIZE/2;
// }*/
// drawCenteredText(cs, font, FONT_SIZE, title,
// startX + LEFT_COL_WIDTH/2, textY);
//
// // 绘制图片带5pt边距
// cs.drawImage(image,
// startX + LEFT_COL_WIDTH + 5,
// startY - rowHeight + 10,
// imageWidth, imageHeight);
//
// return startY - rowHeight - 10;
// /*// 计算图片尺寸(保持比例)
// float imageWidth = RIGHT_COL_WIDTH - 10;
// float scale = imageWidth / image.getWidth();
// float imageHeight = image.getHeight() * scale;
//
// // 动态计算行高(图片高度+上下边距20
// float dynamicRowHeight = imageHeight + 20;
//
// // 绘制左侧标题单元格
// cs.setLineWidth(0.5f);
// cs.addRect(TABLE_MARGIN, startY - dynamicRowHeight, LEFT_COL_WIDTH, dynamicRowHeight);
//
// // 绘制右侧图片单元格(高度与左侧同步)
// cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, startY - dynamicRowHeight, RIGHT_COL_WIDTH, dynamicRowHeight);
// cs.stroke();
//
// // 居中绘制标题文本
// float titleWidth = font.getStringWidth(title) / 1000 * FONT_SIZE;
// float titleX = TABLE_MARGIN + (LEFT_COL_WIDTH - titleWidth) / 2;
// float titleY = startY - (dynamicRowHeight / 2) - (FONT_SIZE / 3);
//
// cs.beginText();
// cs.setFont(font, FONT_SIZE);
// cs.newLineAtOffset(titleX, titleY);
// cs.showText(title);
// cs.endText();
//
// // 居中绘制图片
// float imageX = TABLE_MARGIN + LEFT_COL_WIDTH + 5;
// float imageY = startY - dynamicRowHeight + 10;
// cs.drawImage(image, imageX, imageY, imageWidth, imageHeight);
//
// // 返回新的Y坐标当前位置减去行高和间距
// return startY - dynamicRowHeight - 10;*/
// }
/* private static float addImageRow(PDPageContentStream cs, PDDocument doc,
PDType0Font font, String title, String imageUrl, float x, float y) throws IOException {
// 绘制标题行

@ -90,5 +90,8 @@ public class DeviceQueryBo extends BaseDto {
private String endTime;
private String config;
//设备状态0正常1故障2报警3离线
private Integer deviceStatus;
}

@ -56,4 +56,7 @@ public class DeviceInfoExpordVo implements Serializable {
private Long tenantId;
@ExcelProperty(value = "设备区域")
private Long deptAreaId;
@ExcelProperty(value = "设备位置")
private String site;
}

@ -57,4 +57,6 @@ public class DeviceInfoImportVo implements Serializable {
private Long tenantId;
@ExcelProperty(value = "设备区域")
private Long deptAreaId;
@ExcelProperty(value = "设备位置")
private String site;
}

@ -61,6 +61,10 @@ public class DeviceInstallInfoExpordVo implements Serializable {
// @ApiModelProperty(value = "切断阀编号")
@ExcelProperty(value = "地址")
private String site;
@ExcelProperty(value = "切断阀编号")
private String shutValueNumber;
@ExcelProperty(value = "报警器编号")
private String deviceName;
// @ApiModelProperty(value = "燃气表号")
@ExcelProperty(value = "表号")
private String gasMeterNumber;

@ -64,6 +64,10 @@ public class DeviceInstallInfoVo implements Serializable {
// @ApiModelProperty(value = "切断阀编号")
@ExcelProperty(value = "地址")
private String site;
@ExcelProperty(value = "切断阀编号")
private String shutValueNumber;
@ExcelProperty(value = "报警器编号")
private String deviceName;
// @ApiModelProperty(value = "燃气表号")
@ExcelProperty(value = "表号")
private String gasMeterNumber;

@ -223,6 +223,8 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
DeviceInstallInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInstallInfo.class);
DeviceInstallInfoVo deviceInstallInfoVo = MapstructUtils.convert(deviceInfo, DeviceInstallInfoVo.class);
deviceInstallInfoVo.setXuhao(i);
deviceInstallInfoVo.setShutValueNumber(deviceInfo.getShutValueNumber());
deviceInstallInfoVo.setDeviceName(deviceInfo.getDeviceName());
deviceInstallInfoVo.setSite(tbDeviceInfo.getCommunityName() + tbDeviceInfo.getBuildingUnit() + tbDeviceInfo.getRoomNo());
deviceInstallInfoVo.setManufacturer("天津费加罗");
deviceInstallInfoVo.setPosition("成功");
@ -274,4 +276,4 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
return predicate.build();
}*/
}
}

@ -148,13 +148,14 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
String name = query.getName();
String deviceName = query.getDeviceName();
String pk = query.getProductKey();
Integer deviceStatus = query.getDeviceStatus();
//关键字查询
String keyword = query.getKeyword();
String group = query.getGroup();
Boolean online = query.getOnline();
Long areaDepeId = query.getDeptAreaId();
Paging<DeviceInfoVo> result = MapstructUtils.convert(deviceInfoData.findByConditions(name, uid, subUid, pk, group,
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId, query.getStartTime(), query.getEndTime(), deviceName), DeviceInfoVo.class);
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId, query.getStartTime(), query.getEndTime(), deviceName,deviceStatus), DeviceInfoVo.class);
List<Category> categorys = categoryData.findAll();
for (DeviceInfoVo row : result.getRows()) {
if (ObjectUtil.isNotEmpty(row.getProductKey())) {

@ -62,6 +62,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.security.PermitAll;
import java.time.LocalDateTime;
@ -163,6 +164,7 @@ public class ThingServiceImpl implements IThingService {
switch (type) {
case REGISTER:
//设备注册
// 根据
String deviceId = registerDevice(device, (DeviceRegister) action, null);
deviceUpdateLastTime(deviceId, lastTime);
@ -381,7 +383,11 @@ public class ThingServiceImpl implements IThingService {
List<Rule> rules = ruleMessageHandler.processMessage1(thingModelMessage);
for (Rule rule : rules) {
//这里也要加增加启用未启用条件查询
List<AlertConfig> config1 = iAlertConfigData.findByRuleInfoIdAndDeviceName(rule.getId(),device.getDeviceName());
if(CollectionUtils.isEmpty(config1)){
config1 = iAlertConfigData.findByRuleInfoIdAndDeviceName(rule.getId(),null);
}
for (int i = 0; i < config1.size(); i++) {
idAlertRecordData.save(AlertRecord.builder()
.level(config1.get(i).getLevel())
@ -974,7 +980,7 @@ public class ThingServiceImpl implements IThingService {
if (productKey != null && device.getProductKey() != null
&& !device.getProductKey().equals(productKey)) {
//防止设备变更了产品key
device.setProductKey(productKey);
// device.setProductKey(productKey);
// device.setModel(register.getModel());
deviceInfoData.save(device);
}

@ -362,7 +362,8 @@ public class SysTenantServiceImpl implements ISysTenantService {
//删除角色
SysRole querySysRole=new SysRole();
querySysRole.setTenantId(tenantId);
List<SysRole> roles =sysRoleData.selectRoleList(querySysRole);
// List<SysRole> roles =sysRoleData.selectRoleList(querySysRole);
List<SysRole> roles =sysRoleData.selectByTenantId(tenantId);
sysRoleData.deleteByIds(roles.stream().map(SysRole::getId).collect(Collectors.toList()));
//删除部门
List<SysDept> lsDepts = sysDeptData.findByTenantId(tenantId);

@ -52,6 +52,7 @@ spring:
hibernate:
format_sql: false
use_sql_comments: false # 输出SQL注释
generate_statistics: false # 关闭统计信息
session_factory:
# statement_inspector: com.example.TenantSQLInterceptor
# dialect: org.hibernate.dialect.MySQL5Dialect

Loading…
Cancel
Save