大图光伏板识别、填报

This commit is contained in:
lcj
2025-11-11 19:40:03 +08:00
parent 8478cd2997
commit b96cc95741
34 changed files with 226 additions and 497 deletions

View File

@ -110,6 +110,8 @@ sa-token:
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
active-timeout: 86400
# 同一账号最大登录数量,-1代表不限
max-login-count: -1
# security配置
security:

View File

@ -24,6 +24,7 @@ import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.manager.ys7manager.Ys7Constant;
import org.dromara.manager.ys7manager.Ys7Manager;
@ -403,7 +404,8 @@ public class DemoTest {
@Test
void testImport() {
photovoltaicPanelService.updateFinishNumberByCoordinate(List.of(1968510961294921730L),
List.of(new RecognizeConvertCoordinateResult("107.124334530", "23.830557974")));
List.of(new RecognizeConvertCoordinateResult("107.124334530", "23.830557974")),
RecognizerTypeEnum.BRACKET.getValue());
}
@Test

View File

@ -1,58 +0,0 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class BusAttendanceByGo {
private Long id; // 主键ID
private String userName; // 人员姓名
private String pacePhoto; // 人脸照
private Long projectId; // 项目id
private String createBy; // 创建者
private String updateBy; // 更新者
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String clockOn; // 上午打卡
private String clockOff; // 下午打卡
private String printingDate; // 年月日打卡时间
private String isPinch; // 1正常,2迟到,3早退,4缺勤,5补卡
private String openid; // 微信id
private String pinchOpenId; // 代打id
private String clockRecord; // 多次打卡时间记录
private String pinchUserName; // 代打人姓名
private String commuter; // 上下班1上班 2下班
private String punchRange; // 打卡范围
private BigDecimal dailyWage; // 日薪
private String lng; // 经度
private String lat; // 纬度
private String location; // 逆编码地址信息
private LocalDateTime missing; // 缺卡统一处理时间
}

View File

@ -1,91 +0,0 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("bus_construction_user")
public class BusConstructionUser {
@TableId(type = IdType.AUTO)
private Long id; // 主键ID
private String openid; // 微信id
private String nickName; // 微信名称
private Long teamId; // 班组id
private String headIcon; // 登陆照片
private String pacePhoto; // 人脸照
private String userName; // 人员姓名
private Long projectId; // 项目id
private String status; // 状态0在职 1离职-字典position_status
private String isPinch; // 是否代打
private String ifManagement; // 是否班组管理
private String createBy; // 创建者
private String updateBy; // 更新者
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String phone; // 电话
private String sex; // 1:男,2女,3保密
private String sfzNation; // 身份证民族
private String sfzNumber; // 身份证号码
private String sfzStart; // 身份证有效开始期
private String sfzEnd; // 身份证有效结束期
private String sfzSite; // 身份证地址
private String sfzBirth; // 身份证出生日期
private String nativePlace; // 籍贯
private String yhkNumber; // 银行卡号
private String yhkOpeningBank; // 开户行
private String yhkCardholder; // 持卡人
private String typeOfWork; // 工种(字典)
private String clock; // 打卡(1启用打卡 2禁止打卡)
private Long labourserviceId; // 劳务公司id
private String entryDate; // 入场时间
private String leaveDate; // 离场时间
private BigDecimal salary; // 薪水为0表示无效
private String projectRecord; // 是否开启项目备案1开启 2不开启
private String wxOrPc; // 哪添加的1表示pc 2表示小程序
private String subscription; // 消息订阅状态1订阅 2无订阅
private String devNum; // 安全帽设备标识
}

View File

@ -1,52 +0,0 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 企业大事记
*/
@Data
@TableName("bus_corporate_events")
public class BusCorporateEvents {
@TableId(type = IdType.AUTO)
private Long id;
/**
* 标题
*/
private String headline;
/**
* 内容
*/
private String content;
/**
* 创建人
*/
private Long createdBy;
/**
* 更新人
*/
private Long updatedBy;
/**
* 创建时间
*/
private LocalDateTime createdAt;
/**
* 更新时间
*/
private LocalDateTime updatedAt;
/**
* 删除时间(软删除标记)
*/
private LocalDateTime deletedAt;
}

View File

@ -1,31 +0,0 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BusProjectTeamByGo {
private Long id; // 主键id
private Long projectId; // 项目id
private String name; // 班组名称
private String isClockIn; // 范围内打卡0范围内打卡 1任何地点打卡
private String punchRange; // 打卡范围(id串)
private String remark; // 备注
private String createBy; // 创建者
private String updateBy; // 更新者
private Long createDept; // 创建部门
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
}

View File

@ -1,25 +0,0 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BusProjectTeamMemberByGo {
private Long id; // 主键id
private Long teamId; // 班组id
private Long projectId; // 项目id
private Long memberId; // 施工人员id
private String postId; // 岗位0普通员工1组长
private String remark; // 备注
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
}

View File

@ -1,35 +0,0 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.util.Date;
@Data
public class BusTour {
private Long id; // 主键ID
private Long projectId; // 项目id
private String tourCategory; // 类别字典(如:无人机识别、监控拍摄)
private String tourType; // 类型字典(如:安全帽、安全带)
private String picture; // 图片路径
private Integer num; // 违规数量
private String describe; // 故障描述
private Date createdAt; // 创建时间
private Date updatedAt; // 更新时间
private Date deletedAt; // 删除时间
private String tableName; // 表名
private Long tableId; // 表id
private String sxtName; // 摄像头名称
}

View File

@ -1,34 +0,0 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_project_introduce")
public class SysProjectIntroduce {
@TableId(type = IdType.AUTO)
private Long id; // 主键id
private Long projectId; // 项目id
private String headline; // 标题
private String richText; // 富文本
private String createdBy; // 创建人
private String updatedBy; // 更新人
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String files; // 附件
}

View File

@ -43,7 +43,7 @@ public class AsyncMessageHandlerServiceImpl implements IAsyncMessageHandlerServi
try {
// 1. 解析消息体(只解析一次,避免重复操作)
byte[] messageBody = message.getBody();
if (messageBody == null || messageBody.length == 0) {
if (messageBody.length == 0) {
log.warn("【异步消息处理】消息体为空,忽略处理");
return;
}
@ -76,8 +76,8 @@ public class AsyncMessageHandlerServiceImpl implements IAsyncMessageHandlerServi
return;
}
String key = "";
DroProjectDrone droProjectDrone = null;
String key;
DroProjectDrone droProjectDrone;
boolean isOsd4 = false;
// 5. 根据data字段内容判断key类型并查询无人机信息
@ -130,7 +130,7 @@ public class AsyncMessageHandlerServiceImpl implements IAsyncMessageHandlerServi
System.out.println("大屏已推送消息");
}
int onlineCount = InitOnStartWebSocketServer.getOnlineCount();
if (onlineCount > 0){
if (onlineCount > 0) {
String modleId = b ? droProjectDrone.getAirplaneModleId() : droProjectDrone.getDroneModleId();
if (modleId != null) {
String ued = ueStructureJsonMessage(message, modleId);
@ -143,14 +143,14 @@ public class AsyncMessageHandlerServiceImpl implements IAsyncMessageHandlerServi
private String buildPushMessage(String key, String message, Long projectId) {
JSONObject messageObj = new JSONObject();
messageObj.put("type", "wrj_DATA_UPDATE");
messageObj.put("projectId",projectId.toString());
messageObj.put("clientId",key);
messageObj.set("type", "wrj_DATA_UPDATE");
messageObj.set("projectId", projectId.toString());
messageObj.set("clientId", key);
// 位置信息
JSONObject locationObj = new JSONObject();
locationObj.put("latitude", JSONUtil.parseObj(message).getJSONObject("data").get("latitude").toString()); // 纬度
locationObj.put("longitude", JSONUtil.parseObj(message).getJSONObject("data").get("longitude").toString()); // 经度
messageObj.put("location", locationObj);
locationObj.set("latitude", JSONUtil.parseObj(message).getJSONObject("data").get("latitude").toString()); // 纬度
locationObj.set("longitude", JSONUtil.parseObj(message).getJSONObject("data").get("longitude").toString()); // 经度
messageObj.set("location", locationObj);
return messageObj.toString();
}
@ -161,19 +161,19 @@ public class AsyncMessageHandlerServiceImpl implements IAsyncMessageHandlerServi
private String ueStructureJsonMessage(String message, String modelId) {
// 构造消息对象(包含关键信息)
JSONObject messageObj = new JSONObject();
messageObj.put("type", "location"); // 消息类型
messageObj.set("type", "location"); // 消息类型
JSONObject data = new JSONObject();
data.put("id", modelId);
data.set("id", modelId);
// 位置信息
JSONObject position = new JSONObject();
position.put("lat", JSONUtil.parseObj(message).getJSONObject("data").get("latitude")); // 纬度
position.put("lng", JSONUtil.parseObj(message).getJSONObject("data").get("longitude")); // 经度
position.put("alt", JSONUtil.parseObj(message).getJSONObject("data").get("height")); // 海拔
position.set("lat", JSONUtil.parseObj(message).getJSONObject("data").get("latitude")); // 纬度
position.set("lng", JSONUtil.parseObj(message).getJSONObject("data").get("longitude")); // 经度
position.set("alt", JSONUtil.parseObj(message).getJSONObject("data").get("height")); // 海拔
data.put("position", position);
messageObj.put("data", data); // 设备唯一标识
data.set("position", position);
messageObj.set("data", data); // 设备唯一标识
// 转换为String类型返回
return messageObj.toString();

View File

@ -18,6 +18,11 @@ public class IdCoordinatePoint {
*/
private Long id;
/**
* 名称
*/
private String name;
/**
* 点位置 107.13162414986301,23.817601041770256
*/

View File

@ -358,14 +358,14 @@ public class JSTUtil {
}
public static String getLocationName(String lat, String lng){
String a = lng+","+lat;
public static String getLocationName(String lat, String lng) {
String a = lng + "," + lat;
String s = HttpUtil.get("https://restapi.amap.com/v3/geocode/regeo?location=" + a + "&Key=2a769e5362ac9a7d7db12e85b640124c");
JSONObject jsonObject = JSONUtil.parseObj(s);
JSONObject jsonObject = JSONUtil.parseObj(s);
String address = null;
if(jsonObject.getInt("status") == 1){
address = jsonObject.getJSONObject("regeocode").getStr("formatted_address");
}
if (jsonObject.getInt("status") == 1) {
address = jsonObject.getJSONObject("regeocode").getStr("formatted_address");
}
return address;
}

View File

@ -1,5 +1,7 @@
package org.dromara.common.utils;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.domain.IdCoordinatePoint;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
@ -8,8 +10,11 @@ import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.util.GeometricShapeFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Slf4j
public class JtsPointMatcher {
private static final GeometryFactory geometryFactory = new GeometryFactory();
@ -43,19 +48,30 @@ public class JtsPointMatcher {
* @param radiusMeter 半径(米)
* @return 匹配到的 pointsB 的 id
*/
public static List<Long> matchPoints(List<Coordinate> pointsA, List<IdCoordinatePoint> pointsB, double radiusMeter) {
List<Long> matched = new ArrayList<>();
public static Set<Long> matchPoints(List<Coordinate> pointsA, List<IdCoordinatePoint> pointsB, double radiusMeter) {
Set<Long> matched = new HashSet<>();
for (Coordinate pA : pointsA) {
Point pointA = geometryFactory.createPoint(pA);
for (IdCoordinatePoint pvPoint : pointsB) {
// positions 字段 -> Coordinate
String[] posArr = pvPoint.getPositions().split(",");
double lon = Double.parseDouble(posArr[0]);
double lat = Double.parseDouble(posArr[1]);
String positions = pvPoint.getPositions();
double lon;
double lat;
if (positions.startsWith("[") && positions.endsWith("]")) {
// 是数组形式,例如 [1231515.141,3123123.3123]
List<Double> doubles = JSONUtil.toList(positions, Double.class);
lon = doubles.get(0);
lat = doubles.get(1);
} else {
// 是单个坐标,例如 1231515.141,3123123.3123
String[] posArr = positions.split(",");
lon = Double.parseDouble(posArr[0]);
lat = Double.parseDouble(posArr[1]);
}
Polygon circle = createCircle(lon, lat, radiusMeter);
if (circle.contains(pointA)) {
matched.add(pvPoint.getId());
log.info("匹配到桩点:{}", pvPoint.getName());
break; // 找到一个就够
}
}
@ -83,7 +99,7 @@ public class JtsPointMatcher {
p2.setPositions("107.08827916132982,23.877744707721714"); // 很远
listB.add(p2);
List<Long> result = matchPoints(listA, listB, 4.4);
Set<Long> result = matchPoints(listA, listB, 4.4);
System.out.println("匹配到的桩点ID");
for (Long id : result) {

View File

@ -8,23 +8,18 @@ import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.io.IOUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dromara.bigscreen.domain.BusConstructionUser;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
@ -35,19 +30,15 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.utils.IdCardEncryptorUtil;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.SubUserSalaryDetail;
import org.dromara.contractor.domain.SubUserSalaryPeriod;
import org.dromara.contractor.domain.dto.constructionuser.SubConstructionUserQueryReq;
import org.dromara.contractor.domain.dto.usersalarydetail.SubUserSalaryDetailQueryReq;
import org.dromara.contractor.domain.dto.usersalaryperiod.SubConstructionUserSalaryDto;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.contractor.domain.vo.usersalarydetail.SubUserSalaryDetailVo;
import org.dromara.contractor.domain.vo.usersalaryperiod.SubConstructionUserSalaryVo;
import org.dromara.contractor.excel.DynamicSalaryData;
import org.dromara.contractor.excel.SalaryExcelReader;
import org.dromara.contractor.mapper.SubUserSalaryDetailMapper;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.contractor.service.ISubUserSalaryDetailService;
import org.dromara.gps.domain.vo.ConstructionUser;
import org.dromara.project.domain.BusAttendance;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusProjectTeam;
@ -57,7 +48,6 @@ import org.dromara.project.service.IBusAttendanceService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamService;
import org.dromara.project.service.IBusWorkWageService;
import org.dromara.project.service.impl.BusProjectTeamServiceImpl;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
@ -66,7 +56,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.utils.CollectionUtils;
import java.io.*;
import java.math.BigDecimal;
@ -78,7 +67,6 @@ import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.dromara.contractor.excel.SalaryExcelReader;
/**
* 员工每日工资Service业务层处理

View File

@ -35,7 +35,7 @@ public class DroDroneBigPicture implements Serializable {
/**
* 大图
*/
private Long bigPic;
private String bigPic;
/**
* 识别结果图片
@ -45,17 +45,7 @@ public class DroDroneBigPicture implements Serializable {
/**
* tif文件
*/
private Long tifFile;
/**
* 识别信息
*/
private String recognizeMessage;
/**
* 坐标信息
*/
private String coordinateMessage;
private String tifFile;
/**
* 备注

View File

@ -1,19 +1,15 @@
package org.dromara.drone.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.drone.domain.DroDroneBigPicture;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
@ -48,11 +44,6 @@ public class DroDroneBigPictureVo implements Serializable {
@ExcelProperty(value = "大图")
private String bigPic;
/**
* 大图Url
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "bigPic")
private String bigPicUrl;
/**
* 识别结果图片
*/
@ -64,24 +55,13 @@ public class DroDroneBigPictureVo implements Serializable {
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "recognizePic")
private String recognizePicUrl;
/**
* tif文件
*/
@ExcelProperty(value = "tif文件")
private String tifFile;
/**
* 识别信息
*/
@ExcelProperty(value = "识别信息")
private String recognizeMessage;
/**
* 坐标信息
*/
@ExcelProperty(value = "坐标信息")
private String coordinateMessage;
/**
* 备注
*/

View File

@ -16,6 +16,7 @@ import org.dromara.progress.domain.PgsProgressCategory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* 设施-光伏板立柱Service接口
@ -123,5 +124,5 @@ public interface IFacPhotovoltaicPanelColumnService extends IService<FacPhotovol
* @param projectIds 项目id列表
* @param matchPoints 匹配的坐标点id
*/
void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints);
void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints);
}

View File

@ -16,6 +16,7 @@ import org.dromara.progress.domain.PgsProgressCategory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* 设施-光伏板桩点Service接口
@ -123,5 +124,5 @@ public interface IFacPhotovoltaicPanelPointService extends IService<FacPhotovolt
* @param projectIds 项目id列表
* @param matchPoints 匹配的坐标点id
*/
void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints);
void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints);
}

View File

@ -134,6 +134,9 @@ public interface IFacPhotovoltaicPanelService extends IService<FacPhotovoltaicPa
*
* @param projectIds 项目id列表
* @param coordinateList 坐标列表
* @param type 类型
*/
void updateFinishNumberByCoordinate(List<Long> projectIds, List<RecognizeConvertCoordinateResult> coordinateList);
void updateFinishNumberByCoordinate(List<Long> projectIds,
List<RecognizeConvertCoordinateResult> coordinateList,
String type);
}

View File

@ -16,6 +16,7 @@ import org.dromara.progress.domain.PgsProgressCategory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* 设施-光伏板支架Service接口
@ -123,5 +124,5 @@ public interface IFacPhotovoltaicPanelSupportService extends IService<FacPhotovo
* @param projectIds 项目id列表
* @param matchPoints 匹配的坐标点id
*/
void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints);
void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints);
}

View File

@ -421,7 +421,7 @@ public class FacPhotovoltaicPanelColumnServiceImpl extends ServiceImpl<FacPhotov
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints) {
public void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints) {
// 获取数据
List<FacPhotovoltaicPanelColumn> finishList = this.listByIds(matchPoints);
// 更新完成状态

View File

@ -44,6 +44,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -824,6 +825,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
* @param coordinateList 识别结果
* @param type 类型
*/
@Async
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(List<Long> projectIds,
@ -837,10 +839,11 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
return;
}
// 判断识别出来的坐标是否包含某个点
List<Coordinate> coordinates = coordinateList.stream().map(coordinate -> {
return new Coordinate(Double.parseDouble(coordinate.getLng()), Double.parseDouble(coordinate.getLat()));
}).toList();
List<Long> matchPoints = JtsPointMatcher.matchPoints(coordinates, idCoordinatePointList, 1.0);
List<Coordinate> coordinates = coordinateList.stream().map(coordinate ->
new Coordinate(Double.parseDouble(coordinate.getLng()), Double.parseDouble(coordinate.getLat()))).toList();
// 匹配距离
final double distance = 1.0;
Set<Long> matchPoints = JtsPointMatcher.matchPoints(coordinates, idCoordinatePointList, distance);
if (CollUtil.isEmpty(matchPoints)) {
return;
}
@ -869,7 +872,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
.list();
if (CollUtil.isNotEmpty(list)) {
return list.stream().map(point ->
new IdCoordinatePoint(point.getId(), point.getPositions())).toList();
new IdCoordinatePoint(point.getId(), point.getName(), point.getPositions())).toList();
}
} else if (type.equals(RecognizerTypeEnum.COLUMN.getValue())) {
List<FacPhotovoltaicPanelColumn> list = photovoltaicPanelColumnService.lambdaQuery()
@ -878,7 +881,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
.list();
if (CollUtil.isNotEmpty(list)) {
return list.stream().map(column ->
new IdCoordinatePoint(column.getId(), column.getPositions())).toList();
new IdCoordinatePoint(column.getId(), column.getName(), column.getPositions())).toList();
}
} else if (type.equals(RecognizerTypeEnum.BRACKET.getValue())) {
List<FacPhotovoltaicPanelSupport> list = photovoltaicPanelSupportService.lambdaQuery()
@ -886,8 +889,8 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
.ne(FacPhotovoltaicPanelSupport::getStatus, FacFinishStatusEnum.FINISH.getValue())
.list();
if (CollUtil.isNotEmpty(list)) {
return list.stream().map(column ->
new IdCoordinatePoint(column.getId(), column.getPositions())).toList();
return list.stream().map(support ->
new IdCoordinatePoint(support.getId(), support.getName(), support.getPositions())).toList();
}
}
return List.of();

View File

@ -421,7 +421,7 @@ public class FacPhotovoltaicPanelPointServiceImpl extends ServiceImpl<FacPhotovo
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints) {
public void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints) {
// 获取数据
List<FacPhotovoltaicPanelPoint> finishList = this.listByIds(matchPoints);
// 更新完成状态

View File

@ -34,6 +34,7 @@ import org.dromara.facility.mapper.FacPhotovoltaicPanelMapper;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
@ -49,6 +50,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -760,24 +762,31 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
*
* @param projectIds 项目id列表
* @param coordinateList 坐标列表
* @param type 类型
*/
@Async
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(List<Long> projectIds, List<RecognizeConvertCoordinateResult> coordinateList) {
public void updateFinishNumberByCoordinate(List<Long> projectIds,
List<RecognizeConvertCoordinateResult> coordinateList,
String type) {
// 获取项目下的所有未完成的光伏板
List<FacPhotovoltaicPanel> panelList = this.lambdaQuery()
.in(FacPhotovoltaicPanel::getProjectId, projectIds)
.ne(FacPhotovoltaicPanel::getStatus, FacFinishStatusEnum.FINISH.getValue())
.eq(type.equals(RecognizerTypeEnum.BRACKET.getValue()), FacPhotovoltaicPanel::getProgressCategoryName, "支架安装")
.eq(type.equals(RecognizerTypeEnum.PANEL.getValue()), FacPhotovoltaicPanel::getProgressCategoryName, "组件安装")
.list();
if (CollUtil.isEmpty(panelList)) {
return;
}
// 判断识别出来的坐标是否包含在某个面内
List<FacPhotovoltaicPanel> finishPanelList = new ArrayList<>();
Set<FacPhotovoltaicPanel> finishPanelList = new HashSet<>();
for (RecognizeConvertCoordinateResult result : coordinateList) {
// 获取包含该坐标的面
FacPhotovoltaicPanel containingPanel = JSTUtil.findContainingPanel(result, panelList);
if (containingPanel != null) {
log.info("识别到的光伏板:{}", containingPanel.getName());
finishPanelList.add(containingPanel);
}
}

View File

@ -421,7 +421,7 @@ public class FacPhotovoltaicPanelSupportServiceImpl extends ServiceImpl<FacPhoto
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(List<Long> projectIds, List<Long> matchPoints) {
public void updateFinishNumberByCoordinate(List<Long> projectIds, Set<Long> matchPoints) {
// 获取数据
List<FacPhotovoltaicPanelSupport> finishList = this.listByIds(matchPoints);
// 更新完成状态

View File

@ -11,4 +11,9 @@ public interface RecognizerConstant {
*/
String RECOGNIZE_API_PATH_POST = "/detect_image";
/**
* 光伏板识别 api 路径
*/
String RECOGNIZE_PANEL_API_PATH_POST = "/detect_process";
}

View File

@ -13,18 +13,16 @@ import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.util.ArrayList;
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.Objects;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* @author lilemy
* @date 2025/7/21 10:56
@ -61,6 +59,16 @@ public class RecognizerManager {
return recognize(capUrl, recTypeList, false);
}
/**
* 光伏板识别
*
* @param capUrl 图片地址
* @return 识别结果
*/
public RecognizeVo recognize(String capUrl) {
return RecognizerUtils.recognize(recognizerProperties.getUrl(), capUrl);
}
/**
* 绘制图片
*

View File

@ -25,6 +25,9 @@ import java.util.List;
@Slf4j
public class RecognizerUtils {
/**
* 坐标转换接口
*/
private final static String CONVERT_COORDINATE = "http://192.168.110.2:8895/yjearth4.0/api/v1/vector/convert";
/**
@ -44,8 +47,41 @@ public class RecognizerUtils {
paramMap.put("type", type);
paramMap.put("url", capUrl);
paramMap.put("extract", extract != null && extract ? "true" : "false");
log.info("图片识别请求参数:{}", paramMap);
String errorMsg = "图片识别请求失败";
String url = host + RecognizerConstant.RECOGNIZE_API_PATH_POST;
return getRecognizeVo(capUrl, paramMap, errorMsg, url);
}
/**
* 光伏板识别
*
* @param host 域名
* @param capUrl 在线图片地址
* @return 识别结果
*/
public static RecognizeVo recognize(String host, String capUrl) {
if (StringUtils.isAnyBlank(host, capUrl)) {
throw new ServiceException("光伏板图片识别参数为空", HttpStatus.HTTP_BAD_REQUEST);
}
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("url", capUrl);
log.info("光伏板图片识别请求参数:{}", paramMap);
String errorMsg = "光伏板图片识别请求失败";
String url = host + RecognizerConstant.RECOGNIZE_PANEL_API_PATH_POST;
return getRecognizeVo(capUrl, paramMap, errorMsg, url);
}
/**
* 获取识别结果
*
* @param capUrl 图片地址
* @param paramMap 参数
* @param errorMsg 错误信息
* @param url 请求地址
* @return 识别结果
*/
private static RecognizeVo getRecognizeVo(String capUrl, HashMap<String, Object> paramMap, String errorMsg, String url) {
try (HttpResponse response = HttpRequest.post(url)
.body(JSONUtil.toJsonStr(paramMap))
.execute()) {
@ -91,8 +127,8 @@ public class RecognizerUtils {
List<Integer> size = targetVo.getSize();
JSONObject pos = new JSONObject();
// 中心点
pos.set("x", point.get(0) + size.get(0) / 2);
pos.set("y", point.get(1) + size.get(1) / 2);
pos.set("x", (point.get(0) + size.get(0)) / 2);
pos.set("y", (point.get(1) + size.get(1)) / 2);
positions.add(pos);
}
reqJson.set("positions", positions);

View File

@ -19,11 +19,12 @@ public enum RecognizerTypeEnum {
NO_VEST("未穿反光衣", "novest", "4"),
SMOKE("吸烟", "smoke", "5"),
FIRE("火焰", "fire", "6"),
SMOGGY("烟雾", "smoggy", "7"),
// SMOGGY("烟雾", "smoggy", "7"),
PANEL("光伏板", "solar", "8"),
BRACKET("光伏板支架", "bracket", "9"),
COLUMN("光伏板桩", "column", "10"),
HOLE("光伏板孔", "hole", "11");
HOLE("光伏板孔", "hole", "11"),
;
private final String text;

View File

@ -184,7 +184,7 @@ public class OutConstructionValueVo implements Serializable {
/**
* 上报人
*/
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
private String createByName;
/**

View File

@ -1148,13 +1148,10 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
return true;
}
List<Long> projectIds = projects.stream().map(BusProject::getId).distinct().toList();
// 识别类型:洞、桩、架、架子
List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.HOLE, RecognizerTypeEnum.PANEL,
RecognizerTypeEnum.COLUMN, RecognizerTypeEnum.BRACKET);
// 调用识别算法
RecognizeVo recognizeVo = null;
try {
recognizeVo = recognizerManager.recognize(fileUrl, enumList);
recognizeVo = recognizerManager.recognize(fileUrl);
} catch (Exception e) {
log.error("识别失败:{}", e.getMessage());
}
@ -1170,7 +1167,6 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
// 根据识别到的类型进行分组
Map<String, List<RecognizeTargetVo>> typeMap = targets.stream()
.collect(Collectors.groupingBy(RecognizeTargetVo::getType));
List<RecognizeConvertCoordinateResult> allConvertCoordinateList = new ArrayList<>();
for (Map.Entry<String, List<RecognizeTargetVo>> entry : typeMap.entrySet()) {
String type = entry.getKey();
List<RecognizeTargetVo> value = entry.getValue();
@ -1181,17 +1177,16 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
if (CollUtil.isEmpty(coordinateList)) {
continue;
}
allConvertCoordinateList.addAll(coordinateList);
} catch (Exception e) {
log.error("转换坐标失败:{}", e.getMessage());
}
log.info("类型:{},识别到的设施:{},转换坐标:{}", type, value, coordinateList);
// 处理对应设施
if (type.equals(RecognizerTypeEnum.PANEL.getValue())) {
photovoltaicPanelService.updateFinishNumberByCoordinate(projectIds, coordinateList);
} else if (type.equals(RecognizerTypeEnum.HOLE.getValue())
|| type.equals(RecognizerTypeEnum.COLUMN.getValue())
if (type.equals(RecognizerTypeEnum.PANEL.getValue())
|| type.equals(RecognizerTypeEnum.BRACKET.getValue())) {
photovoltaicPanelService.updateFinishNumberByCoordinate(projectIds, coordinateList, type);
} else if (type.equals(RecognizerTypeEnum.HOLE.getValue())
|| type.equals(RecognizerTypeEnum.COLUMN.getValue())) {
photovoltaicPanelPartsService.updateFinishNumberByCoordinate(projectIds, coordinateList, type);
} else {
log.error("未知设施类型:{}", type);
@ -1200,7 +1195,7 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
// 将识别数据同步到图片上
Long recognizePic = null;
try {
RecognizeImageStreamResult drawnImage = recognizerManager.drawImageToStream(fileUrl, targets);
RecognizeImageStreamResult drawnImage = RecognizerManager.drawImageToStream(fileUrl, targets);
InputStream inputStream = drawnImage.getInputStream();
String contentType = drawnImage.getContentType();
long length = drawnImage.getLength();
@ -1211,18 +1206,12 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
} catch (IOException | URISyntaxException e) {
throw new ServiceException("将识别数据同步到图片上失败", HttpStatus.ERROR);
}
// 文件上传
SysOssVo fileVo = ossService.uploadFileUrl(fileUrl, fileName);
String tifName = FileNameUtil.getName(tifUrl);
SysOssVo tifVo = ossService.uploadFileUrl(tifUrl, tifName);
// 保存识别数据
DroDroneBigPicture droDroneBigPicture = new DroDroneBigPicture();
droDroneBigPicture.setProjectId(projectId);
droDroneBigPicture.setBigPic(fileVo.getOssId());
droDroneBigPicture.setTifFile(tifVo.getOssId());
droDroneBigPicture.setBigPic(fileUrl);
droDroneBigPicture.setTifFile(tifUrl);
droDroneBigPicture.setRecognizePic(recognizePic);
droDroneBigPicture.setRecognizeMessage(JSONUtil.toJsonStr(targets));
droDroneBigPicture.setCoordinateMessage(JSONUtil.toJsonStr(allConvertCoordinateList));
droDroneBigPictureService.save(droDroneBigPicture);
return true;
}

View File

@ -1,19 +1,16 @@
package org.dromara.safety.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.LocalDate;
import java.io.Serial;
/**
* 题库对象 wgz_question_bank
@ -21,37 +18,55 @@ import java.time.LocalDate;
* @author ruoyi
* @date 2025-02-17
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("wgz_question_bank")
public class WgzQuestionBank extends BaseEntity {
private static final long serialVersionUID=1L;
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 题目类别(外键关联到类别表) */
/**
* 题目类别(外键关联到类别表)
*/
private Long categoryId;
/** 题目类型1单选、2多选、3判断、4填空、5问答 */
/**
* 题目类型1单选、2多选、3判断、4填空、5问答
*/
private String questionType;
/** 题目内容 */
/**
* 题目内容
*/
private String questionText;
/** 选项对单选、多选、判断这种固定答案有效以JSON数组形式存储 */
/**
* 选项对单选、多选、判断这种固定答案有效以JSON数组形式存储
*/
private String options;
/** 正确答案 */
/**
* 正确答案
*/
private String correctAnswer;
/** 得分 */
/**
* 得分
*/
private Long score;
/** 备注 */
/**
* 备注
*/
private String remark;
}

View File

@ -1,18 +1,15 @@
package org.dromara.safety.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.LocalDate;
import java.io.Serial;
/**
* 题库_题库类别对象 wgz_question_category
@ -20,19 +17,25 @@ import java.time.LocalDate;
* @author ruoyi
* @date 2025-02-17
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("wgz_question_category")
public class WgzQuestionCategory extends BaseEntity {
private static final long serialVersionUID=1L;
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 题库类别 */
/**
* 题库类别
*/
private String categoryName;
}

View File

@ -1,26 +1,22 @@
package org.dromara.xzd.paymentsReceipts.domain.vo;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.xzd.paymentsReceipts.domain.XzdSfkFapiao;
import org.dromara.xzd.paymentsReceipts.domain.XzdSfkFukuan;
import org.dromara.xzd.paymentsReceipts.domain.XzdSfkZonhefuwuFk;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
@ -30,6 +26,7 @@ import java.util.List;
* @author Lion Li
* @date 2025-10-16
*/
@EqualsAndHashCode(callSuper = true)
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XzdSfkZonhefuwuFk.class)