接入无人机大图,AI进度填报

This commit is contained in:
lcj
2025-09-17 22:46:34 +08:00
parent 928ba9783b
commit 25690503e5
43 changed files with 1591 additions and 119 deletions

View File

@ -13,7 +13,7 @@ spring.boot.admin.client:
--- # snail-job 配置
snail-job:
enabled: true
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
@ -300,3 +300,6 @@ recognizer:
qrCode:
url: http://192.168.110.151:7788
# 无人机大图
drone:
big-image: http://192.168.110.2:9512

View File

@ -290,3 +290,6 @@ recognizer:
qrCode:
url: http://xny.yj-3d.com:7171
# 无人机大图
drone:
big-image: http://192.168.110.2:9512

View File

@ -307,3 +307,6 @@ recognizer:
qrCode:
url: http://xny.yj-3d.com:7788
# 无人机大图
drone:
big-image: http://192.168.110.2:9512

View File

@ -127,6 +127,7 @@ security:
- /**/changxie/callback/**
- /gps/equipment/dataAcceptance
- /resource/oss/upload
- /progress/progressPlanDetail/insert/numberAI
# 多租户配置
tenant:
@ -250,8 +251,6 @@ springdoc:
packages-to-scan: org.dromara.design
- group: 13.工作流模块
packages-to-scan: org.dromara.workflow
# - group: 14.罗成模块
# packages-to-scan: org.dromara.cory
- group: 15.无人机模块
packages-to-scan: org.dromara.drone
- group: 20.代码生成模块
@ -264,8 +263,6 @@ springdoc:
packages-to-scan: org.dromara.out
- group: 19.消息模块
packages-to-scan: org.dromara.message
# - group: 20.手续模块
# packages-to-scan: org.dromara.formalities
- group: 21.分标策划模块
packages-to-scan: org.dromara.tender
- group: 22.大屏模块
@ -274,9 +271,6 @@ springdoc:
packages-to-scan: org.dromara.bidding
- group: 23.GPS定位模块
packages-to-scan: org.dromara.gps
# - group: 20.合同模块
# packages-to-scan: org.dromara.ctr
- group: 24.招标模块
packages-to-scan: org.dromara.tender
- group: 25.app版本模块

View File

@ -1,14 +1,17 @@
package org.dromara.common.utils;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import org.dromara.common.constant.GeoJsonConstant;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.domain.GeoPoint;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPlane;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeometry;
import org.dromara.facility.domain.dto.geojson.FacGeometryByPoint;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.index.strtree.STRtree;
@ -313,4 +316,43 @@ public class JSTUtil {
return geometryFactory.createPolygon(shell);
}
/**
* 判断点在哪个面内
*/
public static FacPhotovoltaicPanel findContainingPanel(
RecognizeConvertCoordinateResult pointEntity,
List<FacPhotovoltaicPanel> panels
) {
double lng = Double.parseDouble(pointEntity.getLng());
double lat = Double.parseDouble(pointEntity.getLat());
Point point = geometryFactory.createPoint(new Coordinate(lng, lat));
for (FacPhotovoltaicPanel panel : panels) {
Polygon polygon = parsePolygon(panel.getPositions());
if (polygon.covers(point)) { // covers 包含边界
return panel;
}
}
return null;
}
/**
* 将 FacPhotovoltaicPanel.positions 转成 Polygon
*/
private static Polygon parsePolygon(String positionsJson) {
// positions 是形如 [[lng,lat],[lng,lat],...] 的字符串
JSONArray array = JSONUtil.parseArray(positionsJson);
Coordinate[] coords = new Coordinate[array.size()];
for (int i = 0; i < array.size(); i++) {
JSONArray point = array.getJSONArray(i);
double lng = point.getDouble(0);
double lat = point.getDouble(1);
coords[i] = new Coordinate(lng, lat);
}
// 构建 Polygon
LinearRing ring = geometryFactory.createLinearRing(coords);
return geometryFactory.createPolygon(ring, null);
}
}

View File

@ -31,7 +31,6 @@ import org.dromara.project.domain.BusConstructionBlacklist;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusConstructionBlacklistService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.safety.domain.WgzQuestionSavePdf;
import org.dromara.safety.service.IWgzQuestionSavePdfService;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.domain.vo.SysOssVo;
@ -119,52 +118,17 @@ public class SubConstructionUserFileServiceImpl extends ServiceImpl<SubConstruct
List<SubConstructionUserFileVo> listVo = new ArrayList<>();
for (SubConstructionUserFileVo file : list) {
if (Objects.equals(file.getFileType(), "11")) {
// 安全考试
WgzQuestionSavePdf wgzQuestionSavePdf = wgzQuestionSavePdfService.queryByUserId(file.getUserId());
if (wgzQuestionSavePdf != null) {
List<SysOssVo> ossVos = ossService.listByIds(Arrays.stream(wgzQuestionSavePdf
.getPath()
.split(","))
.map(Long::parseLong)
.toList());
for (SysOssVo ossVo : ossVos) {
SubConstructionUserFileVo vo = new SubConstructionUserFileVo();
BeanUtils.copyProperties(file, vo);
vo.setUrl(ossVo.getUrl());
vo.setFileName(ossVo.getOriginalName());
vo.setFileSize(ossService.formatFileSize(ossVo.getFileSize()));
listVo.add(vo);
}
}
} else if (Objects.equals(file.getFileType(), "12")) {
// 特种工作证
SubConstructionUser constructionUser = constructionUserService.getBySysUserId(file.getUserId());
List<SysOssVo> ossVos = ossService.listByIds(Arrays.stream(constructionUser
.getSpecialWorkPic()
.split(","))
.map(Long::parseLong).toList());
for (SysOssVo ossVo : ossVos) {
SubConstructionUserFileVo vo = new SubConstructionUserFileVo();
List<Long> ossIds = Arrays.stream(file.getPath().split(",")).map(Long::parseLong).toList();
for (Long ossId : ossIds) {
SubConstructionUserFileVo vo = new SubConstructionUserFileVo();
if (ossVoMap.containsKey(ossId)) {
BeanUtils.copyProperties(file, vo);
SysOssVo ossVo = ossVoMap.get(ossId);
vo.setUrl(ossVo.getUrl());
vo.setFileName(ossVo.getOriginalName());
vo.setFileSize(ossService.formatFileSize(ossVo.getFileSize()));
listVo.add(vo);
}
} else {
List<Long> ossIds = Arrays.stream(file.getPath().split(",")).map(Long::parseLong).toList();
for (Long ossId : ossIds) {
SubConstructionUserFileVo vo = new SubConstructionUserFileVo();
if (ossVoMap.containsKey(ossId)) {
BeanUtils.copyProperties(file, vo);
SysOssVo ossVo = ossVoMap.get(ossId);
vo.setUrl(ossVo.getUrl());
vo.setFileName(ossVo.getOriginalName());
vo.setFileSize(ossService.formatFileSize(ossVo.getFileSize()));
}
listVo.add(vo);
}
listVo.add(vo);
}
}
return listVo;

View File

@ -1,6 +1,5 @@
package org.dromara.contractor.service.impl;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
@ -361,13 +360,20 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
sysUser.setNickName(req.getUserName());
sysUser.setPhonenumber(phone);
sysUser.setUserType(UserType.APP_USER.getUserType());
Long sysUserId = userService.save(sysUser);
Long sysUserId = userService.save(sysUser);
constructionUser.setSysUserId(sysUserId);
// 操作数据库
boolean save = this.save(constructionUser);
if (!save) {
throw new ServiceException("新增施工人员失败,数据库异常", HttpStatus.ERROR);
}
// 同步更新特种证
if (req.getSpecialWorkPic() != null) {
SubConstructionUserFile file = new SubConstructionUserFile();
file.setUserId(sysUserId);
file.setFileType("12");
file.setPath(req.getSpecialWorkPic());
}
return constructionUser.getId();
}
@ -392,6 +398,26 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
// 判断当前操作用户是否有权限
Long userId = LoginHelper.getUserId();
projectService.validAuth(oldConstructionUser.getProjectId(), userId);
// 同步更新特种证
if (req.getSpecialWorkPic() != null) {
boolean save = true;
if (oldConstructionUser.getSpecialWorkPic() == null) {
SubConstructionUserFile file = new SubConstructionUserFile();
file.setUserId(oldConstructionUser.getSysUserId());
file.setFileType("12");
file.setPath(req.getSpecialWorkPic());
save = constructionUserFileService.save(file);
} else if (!req.getSpecialWorkPic().equals(oldConstructionUser.getSpecialWorkPic())) {
save = constructionUserFileService.lambdaUpdate()
.eq(SubConstructionUserFile::getUserId, oldConstructionUser.getSysUserId())
.eq(SubConstructionUserFile::getFileType, "12")
.set(SubConstructionUserFile::getPath, req.getSpecialWorkPic())
.update();
}
if (!save) {
throw new ServiceException("新增施工人员特种证失败,数据库异常", HttpStatus.ERROR);
}
}
// 操作数据库
return this.updateById(constructionUser);
}
@ -890,7 +916,7 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
String decrypt = constructionUserVo.getSfzNumber();
try {
decrypt = idCardEncryptorUtil.decrypt(constructionUserVo.getSfzNumber());
}catch (Exception e){
} catch (Exception e) {
log.warn("身份证解密失败");
}
@ -912,12 +938,12 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
constructionUserVo.setAge(age);
}
//添加岗位
if(constructionUser.getTeamId()!=null){
if (constructionUser.getTeamId() != null) {
BusProjectTeamMember one = projectTeamMemberService.getOne(Wrappers.<BusProjectTeamMember>lambdaQuery()
.eq(BusProjectTeamMember::getTeamId, constructionUser.getTeamId())
.last("limit 1")
);
if(one != null){
if (one != null) {
constructionUserVo.setPostId(one.getPostId());
}
@ -1193,7 +1219,7 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
//验证身份证是否使用
List<SubConstructionUser> list = list(Wrappers.lambdaQuery(SubConstructionUser.class)
.eq(SubConstructionUser::getSfzNumber, encrypt));
if(CollectionUtil.isNotEmpty(list)){
if (CollectionUtil.isNotEmpty(list)) {
throw new ServiceException("身份证已被注册", HttpStatus.BAD_REQUEST);
}

View File

@ -0,0 +1,105 @@
package org.dromara.drone.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import org.dromara.drone.domain.bo.DroDroneBigPictureBo;
import org.dromara.drone.service.IDroDroneBigPictureService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 无人机大图信息
*
* @author lilemy
* @date 2025-09-17
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/drone/droneBigPicture")
public class DroDroneBigPictureController extends BaseController {
private final IDroDroneBigPictureService droDroneBigPictureService;
/**
* 查询无人机大图信息列表
*/
@SaCheckPermission("drone:droneBigPicture:list")
@GetMapping("/list")
public TableDataInfo<DroDroneBigPictureVo> list(DroDroneBigPictureBo bo, PageQuery pageQuery) {
return droDroneBigPictureService.queryPageList(bo, pageQuery);
}
/**
* 导出无人机大图信息列表
*/
@SaCheckPermission("drone:droneBigPicture:export")
@Log(title = "无人机大图信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(DroDroneBigPictureBo bo, HttpServletResponse response) {
List<DroDroneBigPictureVo> list = droDroneBigPictureService.queryList(bo);
ExcelUtil.exportExcel(list, "无人机大图信息", DroDroneBigPictureVo.class, response);
}
/**
* 获取无人机大图信息详细信息
*
* @param id 主键
*/
@SaCheckPermission("drone:droneBigPicture:query")
@GetMapping("/{id}")
public R<DroDroneBigPictureVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(droDroneBigPictureService.queryById(id));
}
/**
* 新增无人机大图信息
*/
@SaCheckPermission("drone:droneBigPicture:add")
@Log(title = "无人机大图信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody DroDroneBigPictureBo bo) {
return toAjax(droDroneBigPictureService.insertByBo(bo));
}
/**
* 修改无人机大图信息
*/
@SaCheckPermission("drone:droneBigPicture:edit")
@Log(title = "无人机大图信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody DroDroneBigPictureBo bo) {
return toAjax(droDroneBigPictureService.updateByBo(bo));
}
/**
* 删除无人机大图信息
*
* @param ids 主键串
*/
@SaCheckPermission("drone:droneBigPicture:remove")
@Log(title = "无人机大图信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(droDroneBigPictureService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,105 @@
package org.dromara.drone.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.drone.domain.vo.DroProjectDroneVo;
import org.dromara.drone.domain.bo.DroProjectDroneBo;
import org.dromara.drone.service.IDroProjectDroneService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 项目无人机信息
*
* @author lilemy
* @date 2025-09-17
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/drone/projectDrone")
public class DroProjectDroneController extends BaseController {
private final IDroProjectDroneService droProjectDroneService;
/**
* 查询项目无人机信息列表
*/
@SaCheckPermission("drone:projectDrone:list")
@GetMapping("/list")
public TableDataInfo<DroProjectDroneVo> list(DroProjectDroneBo bo, PageQuery pageQuery) {
return droProjectDroneService.queryPageList(bo, pageQuery);
}
/**
* 导出项目无人机信息列表
*/
@SaCheckPermission("drone:projectDrone:export")
@Log(title = "项目无人机信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(DroProjectDroneBo bo, HttpServletResponse response) {
List<DroProjectDroneVo> list = droProjectDroneService.queryList(bo);
ExcelUtil.exportExcel(list, "项目无人机信息", DroProjectDroneVo.class, response);
}
/**
* 获取项目无人机信息详细信息
*
* @param id 主键
*/
@SaCheckPermission("drone:projectDrone:query")
@GetMapping("/{id}")
public R<DroProjectDroneVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(droProjectDroneService.queryById(id));
}
/**
* 新增项目无人机信息
*/
@SaCheckPermission("drone:projectDrone:add")
@Log(title = "项目无人机信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody DroProjectDroneBo bo) {
return toAjax(droProjectDroneService.insertByBo(bo));
}
/**
* 修改项目无人机信息
*/
@SaCheckPermission("drone:projectDrone:edit")
@Log(title = "项目无人机信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody DroProjectDroneBo bo) {
return toAjax(droProjectDroneService.updateByBo(bo));
}
/**
* 删除项目无人机信息
*
* @param ids 主键串
*/
@SaCheckPermission("drone:projectDrone:remove")
@Log(title = "项目无人机信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(droProjectDroneService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,75 @@
package org.dromara.drone.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 无人机大图信息对象 dro_drone_big_picture
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@TableName("dro_drone_big_picture")
public class DroDroneBigPicture implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 大图
*/
private Long bigPic;
/**
* 识别结果图片
*/
private Long recognizePic;
/**
* tif文件
*/
private Long tifFile;
/**
* 识别信息
*/
private String recognizeMessage;
/**
* 坐标信息
*/
private String coordinateMessage;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -0,0 +1,45 @@
package org.dromara.drone.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 项目无人机信息对象 dro_project_drone
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@TableName("dro_project_drone")
public class DroProjectDrone implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 无人机SN
*/
private String droneSn;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,42 @@
package org.dromara.drone.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.drone.domain.DroDroneBigPicture;
import java.io.Serial;
import java.io.Serializable;
/**
* 无人机大图信息业务对象 dro_drone_big_picture
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@AutoMapper(target = DroDroneBigPicture.class, reverseConvertGenerate = false)
public class DroDroneBigPictureBo implements Serializable {
@Serial
private static final long serialVersionUID = -2648698305265339936L;
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
private Long id;
/**
* 项目ID
*/
@NotNull(message = "项目ID不能为空", groups = {EditGroup.class})
private Long projectId;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,47 @@
package org.dromara.drone.domain.bo;
import org.dromara.drone.domain.DroProjectDrone;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 项目无人机信息业务对象 dro_project_drone
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = DroProjectDrone.class, reverseConvertGenerate = false)
public class DroProjectDroneBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 项目ID
*/
@NotNull(message = "项目ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long projectId;
/**
* 无人机SN
*/
@NotBlank(message = "无人机SN不能为空", groups = { AddGroup.class, EditGroup.class })
private String droneSn;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,92 @@
package org.dromara.drone.domain.vo;
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;
/**
* 无人机大图信息视图对象 dro_drone_big_picture
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = DroDroneBigPicture.class)
public class DroDroneBigPictureVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* 大图
*/
@ExcelProperty(value = "大图")
private String bigPic;
/**
* 大图Url
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "bigPic")
private String bigPicUrl;
/**
* 识别结果图片
*/
@ExcelProperty(value = "识别结果图片")
private String recognizePic;
/**
* 识别结果图片Url
*/
@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;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,56 @@
package org.dromara.drone.domain.vo;
import org.dromara.drone.domain.DroProjectDrone;
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;
/**
* 项目无人机信息视图对象 dro_project_drone
*
* @author lilemy
* @date 2025-09-17
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = DroProjectDrone.class)
public class DroProjectDroneVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* 无人机SN
*/
@ExcelProperty(value = "无人机SN")
private String droneSn;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,15 @@
package org.dromara.drone.mapper;
import org.dromara.drone.domain.DroDroneBigPicture;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 无人机大图信息Mapper接口
*
* @author lilemy
* @date 2025-09-17
*/
public interface DroDroneBigPictureMapper extends BaseMapperPlus<DroDroneBigPicture, DroDroneBigPictureVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.drone.mapper;
import org.dromara.drone.domain.DroProjectDrone;
import org.dromara.drone.domain.vo.DroProjectDroneVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 项目无人机信息Mapper接口
*
* @author lilemy
* @date 2025-09-17
*/
public interface DroProjectDroneMapper extends BaseMapperPlus<DroProjectDrone, DroProjectDroneVo> {
}

View File

@ -0,0 +1,70 @@
package org.dromara.drone.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.drone.domain.DroDroneBigPicture;
import org.dromara.drone.domain.bo.DroDroneBigPictureBo;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import java.util.Collection;
import java.util.List;
/**
* 无人机大图信息Service接口
*
* @author lilemy
* @date 2025-09-17
*/
public interface IDroDroneBigPictureService extends IService<DroDroneBigPicture> {
/**
* 查询无人机大图信息
*
* @param id 主键
* @return 无人机大图信息
*/
DroDroneBigPictureVo queryById(Long id);
/**
* 分页查询无人机大图信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 无人机大图信息分页列表
*/
TableDataInfo<DroDroneBigPictureVo> queryPageList(DroDroneBigPictureBo bo, PageQuery pageQuery);
/**
* 查询符合条件的无人机大图信息列表
*
* @param bo 查询条件
* @return 无人机大图信息列表
*/
List<DroDroneBigPictureVo> queryList(DroDroneBigPictureBo bo);
/**
* 新增无人机大图信息
*
* @param bo 无人机大图信息
* @return 是否新增成功
*/
Boolean insertByBo(DroDroneBigPictureBo bo);
/**
* 修改无人机大图信息
*
* @param bo 无人机大图信息
* @return 是否修改成功
*/
Boolean updateByBo(DroDroneBigPictureBo bo);
/**
* 校验并批量删除无人机大图信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,70 @@
package org.dromara.drone.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.drone.domain.DroProjectDrone;
import org.dromara.drone.domain.bo.DroProjectDroneBo;
import org.dromara.drone.domain.vo.DroProjectDroneVo;
import java.util.Collection;
import java.util.List;
/**
* 项目无人机信息Service接口
*
* @author lilemy
* @date 2025-09-17
*/
public interface IDroProjectDroneService extends IService<DroProjectDrone> {
/**
* 查询项目无人机信息
*
* @param id 主键
* @return 项目无人机信息
*/
DroProjectDroneVo queryById(Long id);
/**
* 分页查询项目无人机信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目无人机信息分页列表
*/
TableDataInfo<DroProjectDroneVo> queryPageList(DroProjectDroneBo bo, PageQuery pageQuery);
/**
* 查询符合条件的项目无人机信息列表
*
* @param bo 查询条件
* @return 项目无人机信息列表
*/
List<DroProjectDroneVo> queryList(DroProjectDroneBo bo);
/**
* 新增项目无人机信息
*
* @param bo 项目无人机信息
* @return 是否新增成功
*/
Boolean insertByBo(DroProjectDroneBo bo);
/**
* 修改项目无人机信息
*
* @param bo 项目无人机信息
* @return 是否修改成功
*/
Boolean updateByBo(DroProjectDroneBo bo);
/**
* 校验并批量删除项目无人机信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,127 @@
package org.dromara.drone.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.drone.domain.DroDroneBigPicture;
import org.dromara.drone.domain.bo.DroDroneBigPictureBo;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import org.dromara.drone.mapper.DroDroneBigPictureMapper;
import org.dromara.drone.service.IDroDroneBigPictureService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
/**
* 无人机大图信息Service业务层处理
*
* @author lilemy
* @date 2025-09-17
*/
@RequiredArgsConstructor
@Service
public class DroDroneBigPictureServiceImpl extends ServiceImpl<DroDroneBigPictureMapper, DroDroneBigPicture>
implements IDroDroneBigPictureService {
/**
* 查询无人机大图信息
*
* @param id 主键
* @return 无人机大图信息
*/
@Override
public DroDroneBigPictureVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询无人机大图信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 无人机大图信息分页列表
*/
@Override
public TableDataInfo<DroDroneBigPictureVo> queryPageList(DroDroneBigPictureBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<DroDroneBigPicture> lqw = buildQueryWrapper(bo);
Page<DroDroneBigPictureVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的无人机大图信息列表
*
* @param bo 查询条件
* @return 无人机大图信息列表
*/
@Override
public List<DroDroneBigPictureVo> queryList(DroDroneBigPictureBo bo) {
LambdaQueryWrapper<DroDroneBigPicture> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<DroDroneBigPicture> buildQueryWrapper(DroDroneBigPictureBo bo) {
LambdaQueryWrapper<DroDroneBigPicture> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(DroDroneBigPicture::getId);
lqw.eq(bo.getProjectId() != null, DroDroneBigPicture::getProjectId, bo.getProjectId());
return lqw;
}
/**
* 新增无人机大图信息
*
* @param bo 无人机大图信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(DroDroneBigPictureBo bo) {
DroDroneBigPicture add = MapstructUtils.convert(bo, DroDroneBigPicture.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改无人机大图信息
*
* @param bo 无人机大图信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(DroDroneBigPictureBo bo) {
DroDroneBigPicture update = MapstructUtils.convert(bo, DroDroneBigPicture.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(DroDroneBigPicture entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除无人机大图信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,129 @@
package org.dromara.drone.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.drone.domain.DroProjectDrone;
import org.dromara.drone.domain.bo.DroProjectDroneBo;
import org.dromara.drone.domain.vo.DroProjectDroneVo;
import org.dromara.drone.mapper.DroProjectDroneMapper;
import org.dromara.drone.service.IDroProjectDroneService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
/**
* 项目无人机信息Service业务层处理
*
* @author lilemy
* @date 2025-09-17
*/
@RequiredArgsConstructor
@Service
public class DroProjectDroneServiceImpl extends ServiceImpl<DroProjectDroneMapper, DroProjectDrone>
implements IDroProjectDroneService {
/**
* 查询项目无人机信息
*
* @param id 主键
* @return 项目无人机信息
*/
@Override
public DroProjectDroneVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询项目无人机信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目无人机信息分页列表
*/
@Override
public TableDataInfo<DroProjectDroneVo> queryPageList(DroProjectDroneBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<DroProjectDrone> lqw = buildQueryWrapper(bo);
Page<DroProjectDroneVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的项目无人机信息列表
*
* @param bo 查询条件
* @return 项目无人机信息列表
*/
@Override
public List<DroProjectDroneVo> queryList(DroProjectDroneBo bo) {
LambdaQueryWrapper<DroProjectDrone> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<DroProjectDrone> buildQueryWrapper(DroProjectDroneBo bo) {
LambdaQueryWrapper<DroProjectDrone> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(DroProjectDrone::getId);
lqw.eq(bo.getProjectId() != null, DroProjectDrone::getProjectId, bo.getProjectId());
lqw.eq(StringUtils.isNotBlank(bo.getDroneSn()), DroProjectDrone::getDroneSn, bo.getDroneSn());
return lqw;
}
/**
* 新增项目无人机信息
*
* @param bo 项目无人机信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(DroProjectDroneBo bo) {
DroProjectDrone add = MapstructUtils.convert(bo, DroProjectDrone.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改项目无人机信息
*
* @param bo 项目无人机信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(DroProjectDroneBo bo) {
DroProjectDrone update = MapstructUtils.convert(bo, DroProjectDrone.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(DroProjectDrone entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除项目无人机信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -11,6 +11,7 @@ import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCre
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelQueryReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelUpdateReq;
import org.dromara.facility.domain.vo.photovoltaicpanel.FacPhotovoltaicPanelVo;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.progress.domain.PgsProgressCategory;
import java.util.Collection;
@ -128,4 +129,11 @@ public interface IFacPhotovoltaicPanelService extends IService<FacPhotovoltaicPa
*/
Page<FacPhotovoltaicPanelVo> getVoPage(Page<FacPhotovoltaicPanel> photovoltaicPanelPage);
/**
* 根据坐标更新完成数量
*
* @param projectId 项目id
* @param coordinateList 坐标列表
*/
void updateFinishNumberByCoordinate(Long projectId, List<RecognizeConvertCoordinateResult> coordinateList);
}

View File

@ -28,14 +28,20 @@ import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCre
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelQueryReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelUpdateReq;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
import org.dromara.facility.domain.enums.FacFinishTypeEnum;
import org.dromara.facility.domain.vo.photovoltaicpanel.FacPhotovoltaicPanelVo;
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.vo.RecognizeConvertCoordinateResult;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.dromara.project.service.IBusProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
@ -47,6 +53,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
@ -76,6 +83,14 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Lazy
@Resource
private IPgsProgressPlanService progressPlanService;
@Lazy
@Resource
private IPgsProgressPlanDetailService progressPlanDetailService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@ -708,4 +723,74 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
return photovoltaicPanelVoPage;
}
/**
* 根据坐标更新完成数量
*
* @param projectId 项目id
* @param coordinateList 坐标列表
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFinishNumberByCoordinate(Long projectId, List<RecognizeConvertCoordinateResult> coordinateList) {
// 获取项目下的所有未完成的光伏板
List<FacPhotovoltaicPanel> panelList = this.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId)
.ne(FacPhotovoltaicPanel::getStatus, FacFinishStatusEnum.FINISH.getValue())
.list();
if (CollUtil.isEmpty(panelList)) {
return;
}
// 判断识别出来的坐标是否包含在某个面内
List<FacPhotovoltaicPanel> finishPanelList = new ArrayList<>();
for (RecognizeConvertCoordinateResult result : coordinateList) {
// 获取包含该坐标的面
FacPhotovoltaicPanel containingPanel = JSTUtil.findContainingPanel(result, panelList);
if (containingPanel != null) {
finishPanelList.add(containingPanel);
}
}
if (CollUtil.isNotEmpty(finishPanelList)) {
// 更新完成状态
boolean update = this.lambdaUpdate()
.in(FacPhotovoltaicPanel::getId, finishPanelList.stream().map(FacPhotovoltaicPanel::getId).toList())
.set(FacPhotovoltaicPanel::getStatus, FacFinishStatusEnum.FINISH.getValue())
.set(FacPhotovoltaicPanel::getFinishType, FacFinishTypeEnum.AI.getValue())
.update();
if (update) {
Map<Long, List<FacPhotovoltaicPanel>> mapByCategory = finishPanelList.stream()
.collect(Collectors.groupingBy(FacPhotovoltaicPanel::getProgressCategoryId));
// 判断当天是否有存在的计划
LocalDate now = LocalDate.now();
for (Map.Entry<Long, List<FacPhotovoltaicPanel>> entry : mapByCategory.entrySet()) {
Long categoryId = entry.getKey();
List<FacPhotovoltaicPanel> categoryList = entry.getValue();
int size = categoryList.size();
PgsProgressPlanDetail planDetail = progressPlanDetailService.lambdaQuery()
.eq(PgsProgressPlanDetail::getProjectId, projectId)
.eq(PgsProgressPlanDetail::getProgressCategoryId, categoryId)
.eq(PgsProgressPlanDetail::getDate, now)
.one();
if (planDetail != null) {
// 存在,则更新对应计划详情的数量
planDetail.setAiFill(planDetail.getAiFill().add(BigDecimal.valueOf(size)));
planDetail.setFinishedNumber(planDetail.getFinishedNumber().add(BigDecimal.valueOf(size)));
// 添加完成详情
String finishedDetail = planDetail.getFinishedDetail();
List<PgsProgressPlanDetailFinishedVo> finishedVos = categoryList.stream().map(panel ->
new PgsProgressPlanDetailFinishedVo(panel.getId(), panel.getName(), FacFinishTypeEnum.AI.getValue())).toList();
if (StringUtils.isNotBlank(finishedDetail)) {
List<PgsProgressPlanDetailFinishedVo> finishedVoList = JSONUtil.toList(finishedDetail, PgsProgressPlanDetailFinishedVo.class);
finishedVoList.addAll(finishedVos);
planDetail.setFinishedDetail(JSONUtil.toJsonStr(finishedVoList));
} else {
planDetail.setFinishedDetail(JSONUtil.toJsonStr(finishedVos));
}
} else {
// 如果不存在,则创建计划
}
}
}
}
}
}

View File

@ -26,7 +26,7 @@ import java.util.stream.Collectors;
* @date 2025/6/18 15:59
*/
@Slf4j
//@Component
@Component
public class IncSyncYs7DeviceCapturePicData {
@Resource

View File

@ -17,7 +17,7 @@ import java.util.List;
* @date 2025/6/17 9:33
*/
@Slf4j
//@Component
@Component
public class IncSyncYs7DeviceData {
@Resource

View File

@ -0,0 +1,21 @@
package org.dromara.manager.recognizermanager;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author lilemy
* @date 2025-09-17 18:43
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "drone")
public class DroneBigImageProperties {
/**
* 大图请求地址
*/
private String bigImage;
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.manager.recognizermanager.vo.RecognizeImageStreamResult;
import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo;
import org.dromara.manager.recognizermanager.vo.RecognizeVo;
@ -93,6 +94,17 @@ public class RecognizerManager {
return new RecognizeImageStreamResult(new ByteArrayInputStream(baos.toByteArray()), baos.size(), getContentTypeByFilename(filename));
}
/**
* 转换坐标
*
* @param imgUrl 图片地址
* @param targets 识别结果
* @return 转换后的坐标
*/
public List<RecognizeConvertCoordinateResult> convertCoordinate(String imgUrl, List<RecognizeTargetVo> targets) {
return RecognizerUtils.convertCoordinate(imgUrl, targets);
}
/**
* 提取文件名
*

View File

@ -1,14 +1,17 @@
package org.dromara.manager.recognizermanager;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.manager.recognizermanager.enums.RecognizerHasTargetEnum;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo;
import org.dromara.manager.recognizermanager.vo.RecognizeVo;
@ -22,6 +25,8 @@ 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";
/**
* 识别图片
*
@ -66,4 +71,63 @@ public class RecognizerUtils {
}
}
/**
* 坐标转换
*
* @param tifUrl tif文件地址
* @param targets 识别结果
* @return 坐标转换结果
*/
public static List<RecognizeConvertCoordinateResult> convertCoordinate(String tifUrl, List<RecognizeTargetVo> targets) {
if (StringUtils.isBlank(tifUrl) || CollUtil.isEmpty(targets)) {
throw new ServiceException("坐标转换参数为空", HttpStatus.HTTP_BAD_REQUEST);
}
// 构建请求 JSON
JSONObject reqJson = new JSONObject();
reqJson.set("tif", tifUrl);
JSONArray positions = new JSONArray();
for (RecognizeTargetVo targetVo : targets) {
List<Integer> point = targetVo.getLeftTopPoint();
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);
positions.add(pos);
}
reqJson.set("positions", positions);
String errorMsg = "坐标转换请求失败";
log.info("坐标转换请求参数:{}", reqJson);
try (HttpResponse response = HttpRequest.post(CONVERT_COORDINATE)
.header("Content-Type", "application/json")
.body(reqJson.toString())
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
if (body == null) {
log.error("{}{}", errorMsg, "返回参数为空");
}
// 解析 JSON
JSONObject jsonObj = JSONUtil.parseObj(body);
if (jsonObj.getInt("code") != 0) {
log.error("{}{}", errorMsg, jsonObj.get("message"));
}
JSONArray positionList = JSONUtil.parseObj(jsonObj.get("data")).getJSONArray("positions");
// 映射到实体类
List<RecognizeConvertCoordinateResult> results = positionList.stream()
.map(o -> (JSONObject) o)
.map(p -> new RecognizeConvertCoordinateResult(
String.valueOf(p.getDouble("x")), // x 映射到 lng
String.valueOf(p.getDouble("y")) // y 映射到 lat
))
.toList();
log.info("坐标转换请求成功:{}", body);
return results;
}
}
}

View File

@ -0,0 +1,25 @@
package org.dromara.manager.recognizermanager.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lilemy
* @date 2025-09-17 17:23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RecognizeConvertCoordinateResult {
/**
* 经度
*/
private String lng;
/**
* 纬度
*/
private String lat;
}

View File

@ -13,10 +13,7 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.*;
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
import org.springframework.validation.annotation.Validated;
@ -123,15 +120,13 @@ public class PgsConstructionSchedulePlanController extends BaseController {
/**
* 修改施工进度计划为完成状态
*
* @param id 主键
*/
@SaCheckPermission("progress:constructionSchedulePlan:editFinish")
@Log(title = "施工进度计划", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/finish/{id}")
public R<Void> editFinish(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return toAjax(pgsConstructionSchedulePlanService.updateFinish(id));
@PutMapping("/finish")
public R<Void> editFinish(@Validated @RequestBody PgsConstructionSchedulePlanFinishReq req) {
return toAjax(pgsConstructionSchedulePlanService.updateFinish(req));
}
/**

View File

@ -8,17 +8,13 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailFinishedCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.dto.progressplandetail.*;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 进度计划详情
@ -67,8 +63,8 @@ public class PgsProgressPlanDetailController extends BaseController {
* 新增进度计划详情AI 填报)
*/
@PostMapping("/insert/numberAI")
public R<Void> insertNumberDetailByAI(@RequestPart("file") MultipartFile file, Long projectId, String url) {
return toAjax(pgsProgressPlanDetailService.insertNumberDetailByAI(file, projectId, url));
public R<Void> insertNumberDetailByAI(@Validated @RequestBody PgsProgressPlanDetailAINumberReq req) {
return toAjax(pgsProgressPlanDetailService.insertNumberDetailByAI(req));
}
/**

View File

@ -0,0 +1,31 @@
package org.dromara.progress.domain.dto.constructionscheduleplan;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author lilemy
* @date 2025-09-17 10:15
*/
@Data
public class PgsConstructionSchedulePlanFinishReq implements Serializable {
@Serial
private static final long serialVersionUID = 8139653508791280689L;
/**
* 主键
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 完成时间
*/
@NotNull(message = "完成时间不能为空")
private LocalDate finishDate;
}

View File

@ -0,0 +1,37 @@
package org.dromara.progress.domain.dto.progressplandetail;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-17 11:31
*/
@Data
public class PgsProgressPlanDetailAINumberReq implements Serializable {
@Serial
private static final long serialVersionUID = 3841996878560555843L;
/**
* 大图
*/
@NotBlank(message = "大图不能为空")
private String file;
/**
* tif文件
*/
@NotBlank(message = "tif文件不能为空")
private String tif;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
}

View File

@ -24,7 +24,7 @@ public class PgsProgressPlanDetailFinishedVo {
private String name;
/**
* 设施完成类型
* 设施完成类型1手动填报 2AI填报
*/
private String finishType;

View File

@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.*;
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
import org.springframework.web.multipart.MultipartFile;
@ -57,10 +54,10 @@ public interface IPgsConstructionSchedulePlanService extends IService<PgsConstru
/**
* 修改施工进度计划为完成状态
*
* @param id 主键
* @param req 施工进度计划
* @return 是否修改成功
*/
Boolean updateFinish(Long id);
Boolean updateFinish(PgsConstructionSchedulePlanFinishReq req);
/**
* 批量删除施工进度计划信息

View File

@ -6,15 +6,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailFinishedCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.dto.progressplandetail.*;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.util.List;
@ -135,9 +131,8 @@ public interface IPgsProgressPlanDetailService extends IService<PgsProgressPlanD
/**
* 使用AI识别计划详情设施数量
*
* @param file 文件
* @param projectId 项目id
* @param req AI识别计划详情设施数量参数
* @return 是否成功
*/
Boolean insertNumberDetailByAI(MultipartFile file, Long projectId,String url);
Boolean insertNumberDetailByAI(PgsProgressPlanDetailAINumberReq req);
}

View File

@ -16,10 +16,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.design.domain.bo.DesUserBo;
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
import org.dromara.progress.domain.dto.constructionscheduleplan.*;
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
import org.dromara.progress.mapper.PgsConstructionSchedulePlanMapper;
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
@ -117,19 +114,28 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
/**
* 修改施工进度计划为完成状态
*
* @param id 主键
* @param req 施工进度计划
* @return 是否修改成功
*/
@Override
public Boolean updateFinish(Long id) {
PgsConstructionSchedulePlan plan = this.getById(id);
public Boolean updateFinish(PgsConstructionSchedulePlanFinishReq req) {
PgsConstructionSchedulePlan plan = this.getById(req.getId());
if (plan == null) {
throw new ServiceException("施工进度计划信息不存在", HttpStatus.NOT_FOUND);
}
if (plan.getStatus().equals("4")) {
throw new ServiceException("施工进度计划已完成", HttpStatus.NOT_FOUND);
}
LocalDate practicalStartDate = plan.getPracticalStartDate();
LocalDate finishDate = req.getFinishDate();
if (practicalStartDate == null) {
throw new ServiceException("请先填写实际开始时间", HttpStatus.NOT_FOUND);
}
if (finishDate.isBefore(practicalStartDate)) {
throw new ServiceException("实际结束时间不能早于实际开始时间", HttpStatus.NOT_FOUND);
}
plan.setStatus("4");
plan.setPracticalEndDate(finishDate);
return this.updateById(plan);
}
@ -253,6 +259,13 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
for (int i = 0; i < headers.length; i++) {
Cell cell = sheetRow.createCell(i);
cell.setCellValue(headers[i]);
if (i == 0) {
CellStyle css = workbook.createCellStyle();
DataFormat format = workbook.createDataFormat();
css.setDataFormat(format.getFormat("@"));
cell.setCellStyle(css);
}
}
// 6. 设置专业下拉列表(第二列)
setMajorDropdown(mainSheet, projectStructureMap.size());
@ -488,8 +501,8 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
entity.setRemark(dto.getRemark());
// 确定父ID
String number = dto.getNumber();
if (number != null && number.contains("-")) {
String parentNumber = number.substring(0, number.lastIndexOf("-"));
if (number != null && number.contains(".")) {
String parentNumber = number.substring(0, number.lastIndexOf("."));
Long parentId = numberIdMap.get(parentNumber);
if (parentId == null) {
throw new ServiceException("未找到父编号:" + parentNumber, HttpStatus.BAD_REQUEST);
@ -500,7 +513,7 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
}
// 保存当前编号对应的id
numberIdMap.put(number, entity.getId());
numberIdMap.put(number, id);
result.add(entity);
}
@ -541,7 +554,12 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
return date.toString();
} else {
// 处理数字类型,避免科学计数法
return String.valueOf((long) cell.getNumericCellValue());
// 处理数字,移除不必要的.0后缀
String numericValue = String.valueOf(cell.getNumericCellValue());
if (numericValue.endsWith(".0")) {
return numericValue.substring(0, numericValue.length() - 2);
}
return numericValue;
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());

View File

@ -1,6 +1,7 @@
package org.dromara.progress.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -17,13 +18,18 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.utils.PageConvertUtil;
import org.dromara.drone.domain.DroDroneBigPicture;
import org.dromara.drone.service.IDroDroneBigPictureService;
import org.dromara.facility.domain.*;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
import org.dromara.facility.domain.enums.FacFinishTypeEnum;
import org.dromara.facility.service.*;
import org.dromara.manager.recognizermanager.DroneBigImageProperties;
import org.dromara.manager.recognizermanager.RecognizerManager;
import org.dromara.manager.recognizermanager.enums.RecognizerHasTargetEnum;
import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.manager.recognizermanager.vo.RecognizeImageStreamResult;
import org.dromara.manager.recognizermanager.vo.RecognizeTargetVo;
import org.dromara.manager.recognizermanager.vo.RecognizeVo;
import org.dromara.out.domain.OutConstructionValue;
@ -32,10 +38,7 @@ import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailFinishedCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.dto.progressplandetail.*;
import org.dromara.progress.domain.enums.PgsFinishStatusEnum;
import org.dromara.progress.domain.enums.PgsProgressUnitTypeEnum;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
@ -48,14 +51,18 @@ import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@ -104,9 +111,18 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
@Resource
private IOutConstructionValueService constructionValueService;
@Resource
private IDroDroneBigPictureService droDroneBigPictureService;
@Resource
private RecognizerManager recognizerManager;
@Resource
private ISysOssService ossService;
@Resource
private DroneBigImageProperties droneBigImageProperties;
/**
* 分页查询进度计划详情列表
*
@ -899,27 +915,94 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
/**
* 使用AI识别计划详情设施数量
*
* @param file 文件
* @param projectId 项目id
* @param req AI识别计划详情设施数量参数
* @return 是否成功
*/
@Override
public Boolean insertNumberDetailByAI(MultipartFile file, Long projectId,String url) {
public Boolean insertNumberDetailByAI(PgsProgressPlanDetailAINumberReq req) {
String file = req.getFile();
String tif = req.getTif();
String fileUrl = droneBigImageProperties.getBigImage() + file;
String tifUrl = droneBigImageProperties.getBigImage() + tif;
Long projectId = req.getProjectId();
// 识别类型:洞、桩、架、架子
List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.PHO);
/* List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.HOLE, RecognizerTypeEnum.PHO,
RecognizerTypeEnum.PILE, RecognizerTypeEnum.SHELVES);*/
List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.HOLE, RecognizerTypeEnum.PHO,
RecognizerTypeEnum.PILE, RecognizerTypeEnum.SHELVES);
// 调用识别算法
RecognizeVo recognize = recognizerManager.recognize(url, enumList);
if (recognize == null) {
RecognizeVo recognizeVo = null;
try {
recognizeVo = recognizerManager.recognize(fileUrl, enumList);
} catch (Exception e) {
log.error("识别失败:{}", e.getMessage());
}
if (recognizeVo == null) {
return false;
}
if (recognize.getHasTarget().equals(RecognizerHasTargetEnum.NO.getValue())) {
if (recognizeVo.getHasTarget().equals(RecognizerHasTargetEnum.NO.getValue())) {
log.info("没有识别到设施");
return true;
}
// 处理设施
List<RecognizeTargetVo> targets = recognize.getTargets();
String fileName = FileNameUtil.getName(fileUrl);
List<RecognizeTargetVo> targets = recognizeVo.getTargets();
// 根据识别到的类型进行分组
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();
// 调用工具获取经纬度
List<RecognizeConvertCoordinateResult> coordinateList = new ArrayList<>();
try {
coordinateList = recognizerManager.convertCoordinate(tifUrl, targets);
if (CollUtil.isEmpty(coordinateList)) {
continue;
}
allConvertCoordinateList.addAll(coordinateList);
} catch (Exception e) {
log.error("转换坐标失败:{}", e.getMessage());
}
log.info("类型:{},识别到的设施:{},转换坐标:{}", type, value, coordinateList);
// 处理对应设施
if (type.equals(RecognizerTypeEnum.PHO.getValue())) {
photovoltaicPanelService.updateFinishNumberByCoordinate(projectId, coordinateList);
} else if (type.equals(RecognizerTypeEnum.HOLE.getValue())) {
} else if (type.equals(RecognizerTypeEnum.PILE.getValue())) {
} else if (type.equals(RecognizerTypeEnum.SHELVES.getValue())) {
} else {
log.error("未知设施类型:{}", type);
}
}
// 将识别数据同步到图片上
Long recognizePic = null;
try {
RecognizeImageStreamResult drawnImage = recognizerManager.drawImageToStream(fileUrl, targets);
InputStream inputStream = drawnImage.getInputStream();
String contentType = drawnImage.getContentType();
long length = drawnImage.getLength();
SysOssVo drawnVo = ossService.upload(inputStream, fileName, contentType, length);
if (drawnVo != null) {
recognizePic = drawnVo.getOssId();
}
} 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.setRecognizePic(recognizePic);
droDroneBigPicture.setRecognizeMessage(JSONUtil.toJsonStr(targets));
droDroneBigPicture.setCoordinateMessage(JSONUtil.toJsonStr(allConvertCoordinateList));
droDroneBigPictureService.save(droDroneBigPicture);
return true;
}

View File

@ -17,10 +17,13 @@ import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.contractor.domain.SubConstructionUserFile;
import org.dromara.contractor.service.ISubConstructionUserFileService;
import org.dromara.safety.bo.req.WgzAppSubmitATestPaperReq;
import org.dromara.safety.bo.res.WgzAppSubmitATestPaperRes;
import org.dromara.safety.bo.res.WgzAppUserScoreQuery;
@ -58,11 +61,10 @@ import java.util.regex.Pattern;
* @author ruoyi
* @date 2025-02-17
*/
@Slf4j
@Service
public class WgzQuestionSaveServiceImpl extends ServiceImpl<WgzQuestionSaveMapper, WgzQuestionSave> implements IWgzQuestionSaveService {
@Autowired
private IWgzQuestionsConfigurationService iWgzQuestionsConfigurationService;
@ -75,6 +77,9 @@ public class WgzQuestionSaveServiceImpl extends ServiceImpl<WgzQuestionSaveMappe
@Resource
private ISysOssService ossService;
@Resource
private ISubConstructionUserFileService constructionUserFileService;
@Override
public WgzQuestionSave queryById(Long id) {
return getById(id);
@ -265,8 +270,23 @@ public class WgzQuestionSaveServiceImpl extends ServiceImpl<WgzQuestionSaveMappe
.setTakeTime(coryTakeTime)
.setSumScore(corySumScore);
wgzQuestionSavePdfService.insert(wgzQuestionSavePdf);
// 保存文件信息到施工人员文件表中
SubConstructionUserFile one = constructionUserFileService.lambdaQuery()
.eq(SubConstructionUserFile::getUserId, req.getUserId())
.eq(SubConstructionUserFile::getFileType, "11")
.one();
if (one == null) {
SubConstructionUserFile constructionUserFile = new SubConstructionUserFile();
constructionUserFile.setUserId(req.getUserId());
constructionUserFile.setFileType("11");
constructionUserFile.setPath(xdPath);
constructionUserFileService.save(constructionUserFile);
} else {
one.setPath(xdPath);
constructionUserFileService.updateById(one);
}
} catch (Exception e1) {
System.out.println("--------!!! "+e1);
System.out.println("--------!!! " + e1);
throw new RuntimeException("生成PDF试卷出现了意外请重新提交");
}
return res;

View File

@ -100,6 +100,15 @@ public interface ISysOssService {
*/
SysOssVo upload(InputStream inputStream, String originalFileName, String contentType, long length);
/**
* 通过 url 上传到对象存储服务,并保存文件信息到数据库
*
* @param fileUrl 要上传的文件url
* @param originalFileName 文件名
* @return 上传成功后的 SysOssVo 对象,包含文件信息
*/
SysOssVo uploadFileUrl(String fileUrl, String originalFileName);
/**
* 通过输入流上传到对象存储服务,不保存文件信息到数据库
*

View File

@ -341,6 +341,40 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
return buildResultEntity(originalFileName, suffix, storage.getConfigKey(), length, uploadResult);
}
/**
* 通过 url 上传到对象存储服务,并保存文件信息到数据库
*
* @param fileUrl 要上传的文件url
* @param originalFileName 文件名
* @return 上传成功后的 SysOssVo 对象,包含文件信息
*/
@Override
public SysOssVo uploadFileUrl(String fileUrl, String originalFileName) {
String suffix = StringUtils.substring(originalFileName, originalFileName.lastIndexOf("."), originalFileName.length());
try {
// 1. 打开远程连接获取 InputStream
URI uri = URI.create(fileUrl);
URL url = uri.toURL();
URLConnection conn = url.openConnection();
InputStream inputStream = conn.getInputStream();
// 2. 获取内容长度和类型(部分服务器可能返回为 -1
long length = conn.getContentLengthLong(); // 有些服务可能为 -1需要兜底处理
String contentType = conn.getContentType();
if (length <= 0) {
byte[] bytes = IoUtil.readBytes(inputStream);
length = bytes.length;
inputStream = new ByteArrayInputStream(bytes); // 重置为 ByteArrayInputStream
}
// 3. 上传
OssClient storage = OssFactory.instance();
UploadResult uploadResult = storage.uploadSuffix(inputStream, suffix, length, contentType);
// 保存文件信息
return buildResultEntity(originalFileName, suffix, storage.getConfigKey(), length, uploadResult);
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
/**
* 通过 url 上传到对象存储服务,不保存文件信息到数据库
*

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.drone.mapper.DroDroneBigPictureMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.drone.mapper.DroProjectDroneMapper">
</mapper>