大图合并、进度计划导出

This commit is contained in:
lcj
2025-11-17 09:08:58 +08:00
parent 57b662837d
commit b501965d25
20 changed files with 855 additions and 61 deletions

View File

@ -26,4 +26,9 @@ public class RecognizerTest {
RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.PANEL)); RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.PANEL));
log.info("recognize: {}", recognize); log.info("recognize: {}", recognize);
} }
@Test
void testChange() {
recognizerManager.convertCoordinate("http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/11/11/d48767a62bc04867a552e06ba6712004.tif", List.of());
}
} }

View File

@ -0,0 +1,40 @@
package org.dromara.common.excel.handler;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class LockColumnHandler implements CellWriteHandler {
private final Set<Integer> lockColumns;
public LockColumnHandler(Collection<Integer> lockColumns) {
this.lockColumns = new HashSet<>(lockColumns);
}
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
Cell cell = context.getCell();
if (cell == null) return;
Workbook workbook = cell.getSheet().getWorkbook();
// 必须为所有单元格创建一个新的 CellStyle
CellStyle style = workbook.createCellStyle();
// 锁定指定列
if (lockColumns.contains(cell.getColumnIndex())) {
style.setLocked(true);
} else {
style.setLocked(false); // 非锁定列必须明确设置为 false
}
cell.setCellStyle(style);
}
}

View File

@ -0,0 +1,26 @@
package org.dromara.common.excel.handler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.Sheet;
/**
* @author lilemy
* @date 2025-11-14 15:05
*/
public class SheetProtectHandler implements SheetWriteHandler {
private final String password;
public SheetProtectHandler(String password) {
this.password = password;
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder,
WriteSheetHolder writeSheetHolder) {
Sheet sheet = writeSheetHolder.getSheet();
sheet.protectSheet(password); // 可为空字符串
}
}

View File

@ -4,7 +4,10 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ClassPathResource; import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillConfig;
@ -14,26 +17,27 @@ import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.convert.ExcelBigNumberConvert;
import org.dromara.common.excel.core.*; import org.dromara.common.excel.core.*;
import org.dromara.common.excel.handler.DataWriteHandler; import org.dromara.common.excel.handler.DataWriteHandler;
import org.dromara.common.excel.handler.LockColumnHandler;
import org.dromara.common.excel.handler.SheetProtectHandler;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/** /**
* Excel相关处理 * Excel相关处理
* *
* @author Lion Li * @author Lion Li
*/ */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExcelUtil { public class ExcelUtil {
@ -47,6 +51,41 @@ public class ExcelUtil {
return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync(); return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
} }
/**
* 同步读取 Excel支持读取多个 Sheet
*
* @param is 输入流(一次性读取)
* @param clazz Excel 映射实体类
* @return 所有 Sheet 的数据汇总
*/
public static <T> List<T> importExcelAllSheet(InputStream is, Class<T> clazz) {
// 用于存放所有 sheet 的数据
List<T> allData = new ArrayList<>();
// 1. 构建 ExcelReader
ExcelReaderBuilder readerBuilder = EasyExcel.read(is);
ExcelReader reader = readerBuilder.build();
// 2. 获取 Excel 中全部 Sheet 信息(包含 SheetNo、页名等
List<ReadSheet> readSheets = reader.excelExecutor().sheetList();
// 3. 遍历每一个 Sheet
for (ReadSheet sheet : readSheets) {
// 为每个 Sheet 创建独立监听器,用于接收读取结果
DefaultExcelListener<T> listener = new DefaultExcelListener<>(false);
// 4. 构建当前 Sheet 的读取器 使用 sheet.getSheetNo() 指定当前 sheet
ReadSheet readSheet = EasyExcel.readSheet(sheet.getSheetNo())
// 设置头映射实体类
.head(clazz)
// 注册读取监听器
.registerReadListener(listener)
.build();
// 5. 开始读取当前 Sheet
reader.read(readSheet);
// 6. 收集当前 Sheet 读取的数据
allData.addAll(listener.getExcelResult().getList());
}
// 7. 关闭读取器,释放资源
reader.finish();
return allData;
}
/** /**
* 使用校验监听器 异步导入 同步返回 * 使用校验监听器 异步导入 同步返回
@ -204,6 +243,37 @@ public class ExcelUtil {
builder.doWrite(list); builder.doWrite(list);
} }
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param lockColumns 锁定列
* @param merge 是否合并单元格
* @param os 输出流
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, List<Integer> lockColumns,
boolean merge, OutputStream os, List<DropDownOptions> options) {
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
.registerWriteHandler(new LockColumnHandler(lockColumns)) // 锁定第3列
.registerWriteHandler(new SheetProtectHandler("dawdawdwad")) // 保护整张 sheet
.autoCloseStream(false)
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.registerWriteHandler(new DataWriteHandler(clazz))
.sheet(sheetName);
if (merge) {
// 合并处理器
builder.registerWriteHandler(new CellMergeStrategy(list, true));
}
// 添加下拉框操作
builder.registerWriteHandler(new ExcelDownHandler(options));
builder.doWrite(list);
}
/** /**
* 导出多sheet excel增强版解决XML安全问题 * 导出多sheet excel增强版解决XML安全问题
* *
@ -212,7 +282,9 @@ public class ExcelUtil {
* @param clazz 实体类 * @param clazz 实体类
* @param optionsList 级联下拉选内容列表 * @param optionsList 级联下拉选内容列表
*/ */
public static <T> void exportMultiSheetExcelEnhanced(List<List<T>> sheetData, List<String> sheetNames, Class<T> clazz, List<List<DropDownOptions>> optionsList, HttpServletResponse response) throws IOException { public static <T> void exportMultiSheetExcelEnhanced(List<List<T>> sheetData, List<String> sheetNames,
Class<T> clazz, List<List<DropDownOptions>> optionsList,
HttpServletResponse response) throws IOException {
resetResponse("file", response); resetResponse("file", response);
ExcelWriter excelWriter = null; ExcelWriter excelWriter = null;
ServletOutputStream os = response.getOutputStream(); ServletOutputStream os = response.getOutputStream();
@ -254,12 +326,71 @@ public class ExcelUtil {
excelWriter.finish(); excelWriter.finish();
} catch (Exception e) { } catch (Exception e) {
// 记录日志但不中断主流程 // 记录日志但不中断主流程
e.printStackTrace(); log.error("Excel 导出错误", e);
} }
} }
} }
} }
/**
* 导出多sheet excel增强版解决XML安全问题
*
* @param sheetData 多个sheet的数据
* @param sheetNames 多个sheet的名称
* @param clazz 实体类
* @param optionsList 级联下拉选内容列表
*/
public static <T> void exportExcel(List<List<T>> sheetData, List<String> sheetNames, List<Integer> lockColumns,
Class<T> clazz, List<List<DropDownOptions>> optionsList,
HttpServletResponse response) throws IOException {
resetResponse("file", response);
ExcelWriter excelWriter = null;
ServletOutputStream os = response.getOutputStream();
try {
// 使用SXSSFWorkbook避免内存问题并减少XML处理复杂度
excelWriter = EasyExcel.write(os)
.head(clazz)
.registerWriteHandler(new LockColumnHandler(lockColumns)) // 锁定第3列
// .registerWriteHandler(new SheetProtectHandler("dawdawdwad")) // 保护整张 sheet
.autoCloseStream(false)
.registerConverter(new ExcelBigNumberConvert())
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DataWriteHandler(clazz))
.build();
// 为每个sheet写入数据
for (int i = 0; i < sheetData.size(); i++) {
// 创建基本sheet配置
WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetNames.get(i))
.head(clazz)
.build();
// 添加下拉选项(如果存在)
if (optionsList != null && optionsList.size() > i && optionsList.get(i) != null) {
ExcelDownHandler handler = new ExcelDownHandler(optionsList.get(i));
writeSheet.setCustomWriteHandlerList(
Collections.singletonList(handler));
}
// 写入数据
excelWriter.write(sheetData.get(i), writeSheet);
}
} finally {
// 确保资源正确释放
if (excelWriter != null) {
try {
excelWriter.finish();
} catch (Exception e) {
// 记录日志但不中断主流程
log.error("Excel 导出错误", e);
}
}
}
}
/** /**
* 单表多数据模板导出 模板格式为 {.属性} * 单表多数据模板导出 模板格式为 {.属性}

View File

@ -1,32 +1,33 @@
package org.dromara.drone.controller; 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 cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.validation.annotation.Validated; import jakarta.validation.constraints.NotEmpty;
import org.dromara.common.idempotent.annotation.RepeatSubmit; import jakarta.validation.constraints.NotNull;
import org.dromara.common.log.annotation.Log; import lombok.RequiredArgsConstructor;
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.domain.R;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo; import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.drone.domain.bo.DroDroneBigPictureBo; import org.dromara.common.log.annotation.Log;
import org.dromara.drone.service.IDroDroneBigPictureService; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.drone.domain.bo.DroDroneBigPictureBo;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import org.dromara.drone.service.IDroDroneBigPictureService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/** /**
* 无人机大图信息 * 无人机大图信息
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
@Validated @Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@ -64,7 +65,7 @@ public class DroDroneBigPictureController extends BaseController {
@SaCheckPermission("drone:droneBigPicture:query") @SaCheckPermission("drone:droneBigPicture:query")
@GetMapping("/{id}") @GetMapping("/{id}")
public R<DroDroneBigPictureVo> getInfo(@NotNull(message = "主键不能为空") public R<DroDroneBigPictureVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) { @PathVariable Long id) {
return R.ok(droDroneBigPictureService.queryById(id)); return R.ok(droDroneBigPictureService.queryById(id));
} }
@ -90,6 +91,20 @@ public class DroDroneBigPictureController extends BaseController {
return toAjax(droDroneBigPictureService.updateByBo(bo)); return toAjax(droDroneBigPictureService.updateByBo(bo));
} }
/**
* 创建识别进度
*
* @param id 主键
*/
@SaCheckPermission("drone:droneBigPicture:add")
@Log(title = "无人机大图信息", businessType = BusinessType.OTHER)
@RepeatSubmit
@PostMapping("/createProgressRecognize/{id}")
public R<Void> createProgressRecognize(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return toAjax(droDroneBigPictureService.createProgressRecognize(id));
}
/** /**
* 删除无人机大图信息 * 删除无人机大图信息
* *

View File

@ -3,20 +3,21 @@ package org.dromara.drone.domain;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/** /**
* 无人机大图信息对象 dro_drone_big_picture * 无人机大图信息对象 dro_drone_big_picture
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
@TableName("dro_drone_big_picture") @TableName("dro_drone_big_picture")
public class DroDroneBigPicture implements Serializable { public class DroDroneBigPicture extends BaseEntity {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -32,6 +33,16 @@ public class DroDroneBigPicture implements Serializable {
*/ */
private Long projectId; private Long projectId;
/**
* 任务名称
*/
private String taskName;
/**
* 小图片列表
*/
private String smallPic;
/** /**
* 大图 * 大图
*/ */
@ -47,19 +58,14 @@ public class DroDroneBigPicture implements Serializable {
*/ */
private String tifFile; private String tifFile;
/**
* 状态
*/
private String status;
/** /**
* 备注 * 备注
*/ */
private String remark; private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
} }

View File

@ -1,26 +1,30 @@
package org.dromara.drone.domain.bo; package org.dromara.drone.domain.bo;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.drone.domain.DroDroneBigPicture; import org.dromara.drone.domain.DroDroneBigPicture;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable;
/** /**
* 无人机大图信息业务对象 dro_drone_big_picture * 无人机大图信息业务对象 dro_drone_big_picture
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = DroDroneBigPicture.class, reverseConvertGenerate = false) @AutoMapper(target = DroDroneBigPicture.class, reverseConvertGenerate = false)
public class DroDroneBigPictureBo implements Serializable { public class DroDroneBigPictureBo extends BaseEntity {
@Serial @Serial
private static final long serialVersionUID = -2648698305265339936L; private static final long serialVersionUID = 1498586685367891721L;
/** /**
* 主键ID * 主键ID
@ -31,9 +35,40 @@ public class DroDroneBigPictureBo implements Serializable {
/** /**
* 项目ID * 项目ID
*/ */
@NotNull(message = "项目ID不能为空", groups = {EditGroup.class}) @NotNull(message = "项目ID不能为空", groups = {AddGroup.class, EditGroup.class})
private Long projectId; private Long projectId;
/**
* 任务名称
*/
@NotBlank(message = "任务名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String taskName;
/**
* 小图片列表
*/
private String smallPic;
/**
* 大图
*/
private String bigPic;
/**
* 识别结果图片
*/
private Long recognizePic;
/**
* tif文件
*/
private String tifFile;
/**
* 状态
*/
private String status;
/** /**
* 备注 * 备注
*/ */

View File

@ -16,7 +16,7 @@ import java.io.Serializable;
* 无人机大图信息视图对象 dro_drone_big_picture * 无人机大图信息视图对象 dro_drone_big_picture
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
@ -38,6 +38,24 @@ public class DroDroneBigPictureVo implements Serializable {
@ExcelProperty(value = "项目ID") @ExcelProperty(value = "项目ID")
private Long projectId; private Long projectId;
/**
* 任务名称
*/
@ExcelProperty(value = "任务名称")
private String taskName;
/**
* 小图片列表
*/
@ExcelProperty(value = "小图片列表")
private String smallPic;
/**
* 小图片列表 Url
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "smallPic")
private String smallPicList;
/** /**
* 大图 * 大图
*/ */
@ -48,13 +66,7 @@ public class DroDroneBigPictureVo implements Serializable {
* 识别结果图片 * 识别结果图片
*/ */
@ExcelProperty(value = "识别结果图片") @ExcelProperty(value = "识别结果图片")
private String recognizePic; private Long recognizePic;
/**
* 识别结果图片Url
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "recognizePic")
private String recognizePicUrl;
/** /**
* tif文件 * tif文件
@ -62,11 +74,16 @@ public class DroDroneBigPictureVo implements Serializable {
@ExcelProperty(value = "tif文件") @ExcelProperty(value = "tif文件")
private String tifFile; private String tifFile;
/**
* 状态
*/
@ExcelProperty(value = "状态")
private String status;
/** /**
* 备注 * 备注
*/ */
@ExcelProperty(value = "备注") @ExcelProperty(value = "备注")
private String remark; private String remark;
} }

View File

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

View File

@ -14,7 +14,7 @@ import java.util.List;
* 无人机大图信息Service接口 * 无人机大图信息Service接口
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
public interface IDroDroneBigPictureService extends IService<DroDroneBigPicture> { public interface IDroDroneBigPictureService extends IService<DroDroneBigPicture> {
@ -59,6 +59,14 @@ public interface IDroDroneBigPictureService extends IService<DroDroneBigPicture>
*/ */
Boolean updateByBo(DroDroneBigPictureBo bo); Boolean updateByBo(DroDroneBigPictureBo bo);
/**
* 创建识别进度
*
* @param id 主键
* @return 是否创建成功
*/
Boolean createProgressRecognize(Long id);
/** /**
* 校验并批量删除无人机大图信息信息 * 校验并批量删除无人机大图信息信息
* *

View File

@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils; 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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.drone.domain.DroDroneBigPicture; import org.dromara.drone.domain.DroDroneBigPicture;
@ -13,22 +16,30 @@ import org.dromara.drone.domain.bo.DroDroneBigPictureBo;
import org.dromara.drone.domain.vo.DroDroneBigPictureVo; import org.dromara.drone.domain.vo.DroDroneBigPictureVo;
import org.dromara.drone.mapper.DroDroneBigPictureMapper; import org.dromara.drone.mapper.DroDroneBigPictureMapper;
import org.dromara.drone.service.IDroDroneBigPictureService; import org.dromara.drone.service.IDroDroneBigPictureService;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailAINumberReq;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 无人机大图信息Service业务层处理 * 无人机大图信息Service业务层处理
* *
* @author lilemy * @author lilemy
* @date 2025-09-17 * @date 2025-11-15
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class DroDroneBigPictureServiceImpl extends ServiceImpl<DroDroneBigPictureMapper, DroDroneBigPicture> public class DroDroneBigPictureServiceImpl extends ServiceImpl<DroDroneBigPictureMapper, DroDroneBigPicture>
implements IDroDroneBigPictureService { implements IDroDroneBigPictureService {
@Lazy
@Resource
private IPgsProgressPlanDetailService progressPlanDetailService;
/** /**
* 查询无人机大图信息 * 查询无人机大图信息
* *
@ -67,9 +78,16 @@ public class DroDroneBigPictureServiceImpl extends ServiceImpl<DroDroneBigPictur
} }
private LambdaQueryWrapper<DroDroneBigPicture> buildQueryWrapper(DroDroneBigPictureBo bo) { private LambdaQueryWrapper<DroDroneBigPicture> buildQueryWrapper(DroDroneBigPictureBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<DroDroneBigPicture> lqw = Wrappers.lambdaQuery(); LambdaQueryWrapper<DroDroneBigPicture> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(DroDroneBigPicture::getId); lqw.orderByDesc(DroDroneBigPicture::getId);
lqw.eq(bo.getProjectId() != null, DroDroneBigPicture::getProjectId, bo.getProjectId()); lqw.eq(bo.getProjectId() != null, DroDroneBigPicture::getProjectId, bo.getProjectId());
lqw.like(StringUtils.isNotBlank(bo.getTaskName()), DroDroneBigPicture::getTaskName, bo.getTaskName());
lqw.eq(StringUtils.isNotBlank(bo.getSmallPic()), DroDroneBigPicture::getSmallPic, bo.getSmallPic());
lqw.eq(StringUtils.isNotBlank(bo.getBigPic()), DroDroneBigPicture::getBigPic, bo.getBigPic());
lqw.eq(bo.getRecognizePic() != null, DroDroneBigPicture::getRecognizePic, bo.getRecognizePic());
lqw.eq(StringUtils.isNotBlank(bo.getTifFile()), DroDroneBigPicture::getTifFile, bo.getTifFile());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), DroDroneBigPicture::getStatus, bo.getStatus());
return lqw; return lqw;
} }
@ -103,6 +121,26 @@ public class DroDroneBigPictureServiceImpl extends ServiceImpl<DroDroneBigPictur
return baseMapper.updateById(update) > 0; return baseMapper.updateById(update) > 0;
} }
/**
* 创建识别进度
*
* @param id 主键
* @return 是否创建成功
*/
@Override
public Boolean createProgressRecognize(Long id) {
DroDroneBigPicture bigPicture = this.getById(id);
if (bigPicture == null) {
throw new ServiceException("无人机大图数据不存在");
}
// todo 创建识别进度
PgsProgressPlanDetailAINumberReq ai = new PgsProgressPlanDetailAINumberReq();
ai.setFileUrl(bigPicture.getBigPic());
ai.setTifUrl(bigPicture.getTifFile());
Boolean b = progressPlanDetailService.insertNumberDetailByAI(ai);
return true;
}
/** /**
* 保存前的数据校验 * 保存前的数据校验
*/ */

View File

@ -7,8 +7,26 @@ package org.dromara.manager.dronemanager;
public interface DroneConstant { public interface DroneConstant {
/** /**
* 添加无人机项目信息 * 添加无人机项目信息 POST
*/ */
String ADD_DRONE_INFO_BY_PROJECT = "/dj/project/addProjectAndGatewayInfo"; String ADD_DRONE_INFO_BY_PROJECT = "/dj/project/addProjectAndGatewayInfo";
/**
* 创建图片合成任务 POST
*
*/
String CREATE_IMG_MERGE_TASK = "/pure/image/synthesis/createTask";
/**
* 下载图片合成结果 GET
*
*/
String DOWNLOAD_MERGED_FILE = "/pure/image/synthesis/download";
/**
* 查询图片合成进度 GET
*
*/
String GET_IMG_MERGE_PROGRESS = "/pure/image/synthesis/queryProgress";
} }

View File

@ -27,4 +27,33 @@ public class DroneManager {
DroneRequestUtils.addAirportInfoByProject(droneProperties.getUrl(), gateways, projectId); DroneRequestUtils.addAirportInfoByProject(droneProperties.getUrl(), gateways, projectId);
} }
/**
* 创建图片合成任务
*
* @param businessName 业务名称
* @param imageUrls 图片URL列表
*/
public void createImageMergeTask(String businessName, List<String> imageUrls) {
DroneRequestUtils.createImgMergeTask(droneProperties.getUrl(), businessName, imageUrls);
}
/**
* 获取图片合成结果
*
* @param taskId 任务ID
* @param fileType 文件类型(png/tif)
*/
public void downloadMergedFile(String taskId, String fileType) {
DroneRequestUtils.downloadMergedFile(droneProperties.getUrl(), taskId, fileType);
}
/**
* 获取图片合成结果
*
* @param taskId 任务ID
*/
public void getImgMergeProgress(String taskId) {
DroneRequestUtils.getImgMergeProgress(droneProperties.getUrl(), taskId);
}
} }

View File

@ -3,11 +3,13 @@ package org.dromara.manager.dronemanager;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import java.util.List; import java.util.List;
@ -51,11 +53,104 @@ public class DroneRequestUtils {
String body = response.body(); String body = response.body();
JSONObject obj = JSONUtil.parseObj(body); JSONObject obj = JSONUtil.parseObj(body);
if (!obj.getStr("code").equals("200")) { if (!obj.getStr("code").equals("200")) {
log.error("{},状态码:{}{}", errorMsg, obj.get("code"), obj.get("msg")); log.error("{},状态码:{}错误信息:{}", errorMsg, obj.get("code"), obj.get("msg"));
throw new ServiceException(errorMsg + obj.get("msg")); throw new ServiceException(errorMsg + obj.get("msg"));
} }
log.info("添加项目机场信息请求成功"); log.info("添加项目机场信息请求成功");
} }
} }
/**
* 创建图片合成任务
*
* @param businessName 业务名称
* @param imageUrls 图片URL列表
*/
public static void createImgMergeTask(String url, String businessName, List<String> imageUrls) {
if (StringUtils.isBlank(businessName) || CollUtil.isEmpty(imageUrls)) {
throw new ServiceException("创建图片合成任务请求参数错误", HttpStatus.BAD_REQUEST);
}
// 完整 URL
String fullUrl = url + DroneConstant.CREATE_IMG_MERGE_TASK + "?" + "businessName=" + businessName;
// 构造 body 中的 imageUrls 数组
JSONArray urls = new JSONArray();
urls.addAll(imageUrls);
String errorMsg = "创建图片合成任务请求失败";
try (HttpResponse response = HttpRequest.post(fullUrl)
.body(urls.toString())
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
JSONObject obj = JSONUtil.parseObj(body);
if (!obj.getStr("code").equals("200")) {
log.error("{},状态码:{},错误信息:{}", errorMsg, obj.get("code"), obj.get("msg"));
throw new ServiceException(errorMsg + obj.get("msg"));
}
log.info("创建图片合成任务请求成功");
}
}
/**
* 下载图片合成结果
*
* @param taskId 任务ID
* @param fileType 文件类型(png/tif)
*/
public static void downloadMergedFile(String url, String taskId, String fileType) {
if (StringUtils.isAnyBlank(taskId, fileType)) {
throw new ServiceException("下载图片合成结果请求参数错误", HttpStatus.BAD_REQUEST);
}
if (!fileType.equals("png") && !fileType.equals("tif")) {
throw new ServiceException("无此文件类型", HttpStatus.BAD_REQUEST);
}
// 完整 URL
String fullUrl = url + DroneConstant.DOWNLOAD_MERGED_FILE + "/" + taskId + "/" + fileType;
String errorMsg = "下载图片合成结果请求失败";
try (HttpResponse response = HttpRequest.get(fullUrl)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
JSONObject obj = JSONUtil.parseObj(body);
if (!obj.getStr("code").equals("200")) {
log.error("{},状态码:{},错误信息:{}", errorMsg, obj.get("code"), obj.get("msg"));
throw new ServiceException(errorMsg + obj.get("msg"));
}
log.info("下载图片合成结果请求成功");
}
}
/**
* 查询图片合成进度
*
* @param taskId 任务ID
*/
public static void getImgMergeProgress(String url, String taskId) {
if (StringUtils.isBlank(taskId)) {
throw new ServiceException("查询图片合成进度请求参数错误", HttpStatus.BAD_REQUEST);
}
// 完整 URL
String fullUrl = url + DroneConstant.GET_IMG_MERGE_PROGRESS + "/" + taskId;
String errorMsg = "查询图片合成进度请求失败";
try (HttpResponse response = HttpRequest.get(fullUrl)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
JSONObject obj = JSONUtil.parseObj(body);
if (!obj.getStr("code").equals("200")) {
log.error("{},状态码:{},错误信息:{}", errorMsg, obj.get("code"), obj.get("msg"));
throw new ServiceException(errorMsg + obj.get("msg"));
}
log.info("查询图片合成进度请求成功");
}
}
} }

View File

@ -159,8 +159,8 @@ public class RecognizerUtils {
List<RecognizeConvertCoordinateResult> results = positionList.stream() List<RecognizeConvertCoordinateResult> results = positionList.stream()
.map(o -> (JSONObject) o) .map(o -> (JSONObject) o)
.map(p -> new RecognizeConvertCoordinateResult( .map(p -> new RecognizeConvertCoordinateResult(
String.valueOf(p.getDouble("x")), // x 映射到 lng p.getStr("x"), // x 映射到 lng
String.valueOf(p.getDouble("y")) // y 映射到 lat p.getStr("y") // y 映射到 lat
)) ))
.toList(); .toList();
log.info("坐标转换请求成功:{}", body); log.info("坐标转换请求成功:{}", body);

View File

@ -1,12 +1,14 @@
package org.dromara.progress.controller; package org.dromara.progress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
@ -18,6 +20,10 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -117,11 +123,34 @@ public class PgsProgressCategoryController extends BaseController {
pgsProgressCategoryService.exportTotalByNameParent(parentId, response); pgsProgressCategoryService.exportTotalByNameParent(parentId, response);
} }
/**
* 导出进度类别录入模板
*/
@SaIgnore
@SaCheckPermission("progress:progressCategory:export")
@Log(title = "进度类别", businessType = BusinessType.EXPORT)
@PostMapping("/export/enterTemplate/{projectId}")
public void exportEnterTemplate(@NotNull(message = "项目主键不能为空")
@PathVariable Long projectId, HttpServletResponse response) {
pgsProgressCategoryService.exportEnterTemplate(projectId, response);
}
/**
* 导入进度类别录入数据
*/
@SaIgnore
@SaCheckPermission("progress:progressCategory:import")
@Log(title = "进度类别", businessType = BusinessType.IMPORT)
@PostMapping("/import/enterData")
public R<Void> importEnterData(@RequestParam("file") MultipartFile file, Long projectId) {
return R.ok(pgsProgressCategoryService.importEnterData(projectId, file));
}
/*** /***
* 导入 * 导入
*/ */
@SaCheckPermission("progress:progressCategory:import") @SaCheckPermission("progress:progressCategory:import")
@Log(title = "进度类别导入", businessType = BusinessType.IMPORT) @Log(title = "进度类别", businessType = BusinessType.IMPORT)
@PostMapping("/import") @PostMapping("/import")
public R<Void> importData(@RequestParam("file") MultipartFile file) { public R<Void> importData(@RequestParam("file") MultipartFile file) {
return R.ok(pgsProgressCategoryService.importData(file)); return R.ok(pgsProgressCategoryService.importData(file));
@ -255,4 +284,41 @@ public class PgsProgressCategoryController extends BaseController {
return toAjax(pgsProgressCategoryService.deleteWithValidByIds(List.of(ids), true)); return toAjax(pgsProgressCategoryService.deleteWithValidByIds(List.of(ids), true));
} }
/**
* 获取进度类别日进度信息
*/
@SaIgnore
@GetMapping("/day/vo")
public R<PgsProgressCategoryDayTotalVo> getDayTotal() {
return R.ok(pgsProgressCategoryService.getProgressCategoryByDay(1897160897167638529L, LocalDate.now()));
}
/**
* 测试
*/
@SaIgnore
@GetMapping("/test")
public void getTest(HttpServletResponse response) throws IOException {
List<List<PgsProgressCategoryEnterTemplateVo>> list = new ArrayList<>();
List<String> sheetNames = new ArrayList<>();
for (int i = 0; i < 10; i++) {
List<PgsProgressCategoryEnterTemplateVo> list1 = new ArrayList<>();
for (int j = 0; j < 5; j++) {
PgsProgressCategoryEnterTemplateVo vo = new PgsProgressCategoryEnterTemplateVo();
vo.setName("测试" + i);
vo.setUnitType("1");
vo.setTotal(BigDecimal.ONE);
vo.setCompleted(BigDecimal.ONE);
vo.setStatus("1");
vo.setUnit("1");
vo.setRemark("测试" + i);
list1.add(vo);
}
sheetNames.add("测试" + i);
list.add(list1);
}
List<Integer> item = List.of(0, 1, 3);
ExcelUtil.exportExcel(list, sheetNames, item, PgsProgressCategoryEnterTemplateVo.class, null, response);
}
} }

View File

@ -0,0 +1,77 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-11-14 14:23
*/
@Data
public class PgsProgressCategoryEnterTemplateVo implements Serializable {
@Serial
private static final long serialVersionUID = 6899658199225024466L;
/**
* 主键id
*/
@ExcelProperty(value = "主键(请勿修改)")
private Long id;
/**
* 类别名称
*/
@ExcelProperty(value = "类别名称")
private String name;
/**
* 计量方式0无 1数量 2百分比
*/
@ExcelProperty(value = "计量方式", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=无,1=数量,2=百分比")
private String unitType;
/**
* 计量单位
*/
@ExcelProperty(value = "计量单位")
private String unit;
/**
* 总数量
*/
@ExcelProperty(value = "总数量")
private BigDecimal total;
/**
* 已完成数量
*/
@ExcelProperty(value = "已完成数量")
private BigDecimal completed;
/**
* 完成数量
*/
@ExcelProperty(value = "完成数量")
private BigDecimal completionCount;
/**
* 完成状态0未开始 1进行中 2已完成
*/
@ExcelProperty(value = "完成状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=未开始,1=进行中,2=已完成")
private String status;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -318,6 +318,22 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
*/ */
void exportTotalByNameParent(Long parentId, HttpServletResponse response); void exportTotalByNameParent(Long parentId, HttpServletResponse response);
/**
* 导出项目进度类别列表模板
*
* @param projectId 项目id
* @param response 响应
*/
void exportEnterTemplate(Long projectId, HttpServletResponse response);
/**
* 导入项目进度类别列表
*
* @param projectId 项目id
* @param file 文件
*/
String importEnterData(Long projectId, MultipartFile file);
/** /**
* 导入项目进度类别列表 * 导入项目进度类别列表
* *

View File

@ -54,6 +54,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -2531,6 +2532,166 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
ExcelUtil.exportExcel(total, parent.getName(), PgsProgressCategoryExportTotalVo.class, response); ExcelUtil.exportExcel(total, parent.getName(), PgsProgressCategoryExportTotalVo.class, response);
} }
/**
* 导出项目进度类别列表模板
*
* @param projectId 项目id
* @param response 响应
*/
@Override
public void exportEnterTemplate(Long projectId, HttpServletResponse response) {
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目的子项目
List<BusProject> projects = projectService.lambdaQuery()
.eq(BusProject::getPId, projectId)
.list();
projects.add(project);
List<Long> allProjectIds = projects.stream().map(BusProject::getId).toList();
// 获取当前项目的所有父级进度类别
List<PgsProgressCategory> allList = this.lambdaQuery()
.in(PgsProgressCategory::getProjectId, allProjectIds)
.eq(PgsProgressCategory::getParentId, PgsProgressCategoryConstant.TOP_PARENT_ID)
.list();
if (CollUtil.isEmpty(allList)) {
throw new ServiceException("没有数据");
}
List<Long> ids = allList.stream().map(PgsProgressCategory::getId).toList();
// 记录每个 sheet 的表名
List<String> names = new ArrayList<>();
// 获取当前父级下的所有子类
List<PgsProgressCategory> allChildren = this.getLeafNodesByTopIds(ids);
List<List<PgsProgressCategoryEnterTemplateVo>> list = allList.stream().map(p -> {
names.add(StringUtils.isNotBlank(p.getMatrixName()) ? p.getMatrixName() + " - " + p.getName() : p.getName());
List<PgsProgressCategory> c = this.getLeafNodesByTopId(p.getId(), allChildren);
if (CollUtil.isEmpty(c)) {
return new ArrayList<PgsProgressCategoryEnterTemplateVo>();
}
// 封装数据
return c.stream().map(cc -> {
PgsProgressCategoryEnterTemplateVo vo = new PgsProgressCategoryEnterTemplateVo();
vo.setId(cc.getId());
vo.setName(cc.getName());
vo.setUnitType(cc.getUnitType());
vo.setUnit(cc.getUnit());
vo.setTotal(cc.getTotal());
vo.setCompleted(cc.getCompleted());
vo.setCompletionCount(BigDecimal.ZERO);
vo.setStatus(cc.getStatus());
vo.setRemark(cc.getRemark());
return vo;
}).toList();
}).toList();
// 需要锁定的列
List<Integer> lockedColumns = new ArrayList<>();
try {
ExcelUtil.exportExcel(list, names, lockedColumns, PgsProgressCategoryEnterTemplateVo.class, null, response);
} catch (IOException e) {
log.error("导出失败", e);
throw new ServiceException("导出失败");
}
}
/**
* 导入项目进度类别列表
*
* @param projectId 项目id
* @param file 文件
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String importEnterData(Long projectId, MultipartFile file) {
// 检查文件是否为空
if (file == null || file.isEmpty()) {
throw new ServiceException("上传文件不能为空");
}
// 检查文件大小
if (file.getSize() == 0) {
throw new ServiceException("上传文件不能为空文件");
}
// 检查文件名
if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
throw new ServiceException("文件名不能为空");
}
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目不存在");
}
List<PgsProgressCategoryEnterTemplateVo> voList;
try {
// 获取所有 sheet 的数据
voList = ExcelUtil.importExcelAllSheet(file.getInputStream(), PgsProgressCategoryEnterTemplateVo.class);
} catch (IOException e) {
log.error("导入失败", e);
throw new ServiceException("导入失败");
}
if (CollUtil.isEmpty(voList)) {
throw new ServiceException("表格中没有数据");
}
log.info("导入数据:{}", voList);
// 获取当前的所有旧数据
List<Long> ids = voList.stream().map(PgsProgressCategoryEnterTemplateVo::getId).toList();
List<PgsProgressCategory> categoryList = this.listByIds(ids);
if (CollUtil.isEmpty(categoryList)) {
throw new ServiceException("数据错误,当前项目无此数据");
}
Map<Long, PgsProgressCategory> progressCategoryMap = categoryList.stream()
.collect(Collectors.toMap(PgsProgressCategory::getId, Function.identity()));
// 获取当前项目的子项目
List<BusProject> projects = projectService.lambdaQuery()
.eq(BusProject::getPId, projectId)
.list();
projects.add(project);
List<Long> allProjectIds = projects.stream().map(BusProject::getId).toList();
List<PgsProgressCategory> list = voList.stream().map(vo -> {
PgsProgressCategory update = new PgsProgressCategory();
Long id = vo.getId();
update.setId(id);
if (progressCategoryMap.containsKey(id)) {
PgsProgressCategory old = progressCategoryMap.get(id);
// 如果不是当前项目,或当前项目的子项目,则返回 null
if (!allProjectIds.contains(old.getProjectId())) {
return null;
}
// 当已完成数据等于总数,返回 null
if (old.getCompleted().compareTo(old.getTotal()) >= 0) {
return null;
}
// 如果完成数量小于等于0则返回 null
BigDecimal completionCount = vo.getCompletionCount();
if (completionCount == null || completionCount.compareTo(BigDecimal.ZERO) <= 0) {
return null;
}
// 计算完成数量
BigDecimal add = old.getCompleted().add(completionCount);
// 确保完成数量小于等于总数
BigDecimal minVal = add.min(old.getTotal());
update.setCompleted(minVal);
} else {
log.warn("未匹配的值 => id{}name{}", id, vo.getName());
return null;
}
return update;
}).filter(Objects::nonNull).toList();
if (CollUtil.isEmpty(list)) {
throw new ServiceException("没有需要更新的数据");
}
boolean b = this.updateBatchById(list);
if (!b) {
throw new ServiceException("更新失败");
}
List<Long> updateList = list.stream().map(PgsProgressCategory::getId).toList();
log.info("更新数据:{},共 {} 条", updateList, list.size());
// 获取需要更新的计划数据
List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
.in(PgsProgressPlanDetail::getProgressCategoryId, updateList)
.list();
return "导入成功,共更新" + list.size() + "条数据";
}
/** /**
* 导入项目进度类别列表 * 导入项目进度类别列表
* *

View File

@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.utils.PageConvertUtil; import org.dromara.common.utils.PageConvertUtil;
@ -1135,10 +1136,20 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
*/ */
@Override @Override
public Boolean insertNumberDetailByAI(PgsProgressPlanDetailAINumberReq req) { public Boolean insertNumberDetailByAI(PgsProgressPlanDetailAINumberReq req) {
String fileUrl;
String tifUrl;
String file = req.getFile(); String file = req.getFile();
String tif = req.getTif(); String tif = req.getTif();
String fileUrl = droneBigImageProperties.getUrl() + file; if (StringUtils.isNotBlank(file)) {
String tifUrl = droneBigImageProperties.getUrl() + tif; fileUrl = droneBigImageProperties.getUrl() + file;
} else {
fileUrl = req.getFileUrl();
}
if (StringUtils.isNotBlank(tif)) {
tifUrl = droneBigImageProperties.getUrl() + tif;
} else {
tifUrl = req.getTifUrl();
}
Long projectId = req.getProjectId(); Long projectId = req.getProjectId();
// 获取所有子项 // 获取所有子项
List<BusProject> projects = projectService.lambdaQuery() List<BusProject> projects = projectService.lambdaQuery()