drone-common/src/main/java/org/sxkj/common/handler/GenericListTypeHandler.java
New file @@ -0,0 +1,42 @@ package org.sxkj.common.handler; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedTypes; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; @MappedTypes(List.class) public class GenericListTypeHandler extends BaseTypeHandler<List<?>> { @Override public void setNonNullParameter(PreparedStatement ps, int i, List<?> parameter, JdbcType jdbcType) throws SQLException { String json = JSON.toJSONString(parameter, SerializerFeature.WriteMapNullValue); ps.setString(i, json); } @Override public List<?> getNullableResult(ResultSet rs, String columnName) throws SQLException { String json = rs.getString(columnName); return json == null ? null : JSON.parseArray(json, Object.class); } @Override public List<?> getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String json = rs.getString(columnIndex); return json == null ? null : JSON.parseArray(json, Object.class); } @Override public List<?> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String json = cs.getString(columnIndex); return json == null ? null : JSON.parseArray(json, Object.class); } } drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/entity/Attach.java
@@ -30,19 +30,19 @@ /** * ai类型 */ public static final Integer RESULT_TYPE_AI = 2; public static final String RESULT_TYPE_AI = "2"; /** * 图片类型 */ public static final Integer RESULT_TYPE_IMG = 0; public static final String RESULT_TYPE_IMG = "0"; /** * 视频类型(压缩) */ public static final Integer RESULT_TYPE_VEDIO_SHOW = 9; public static final String RESULT_TYPE_VEDIO_SHOW = "9"; /** * 视频类型 */ public static final Integer RESULT_TYPE_VEDIO = 1; public static final String RESULT_TYPE_VEDIO = "1"; private static final long serialVersionUID = 1L; @@ -82,7 +82,7 @@ private String patrolTaskId; @ApiModelProperty(value = "附件类型: 1=巡查类文档,2=巡检类文档,3=安保类文档,4=文旅类文档,5=采集数据类文档") private Integer resultType; private String resultType; @ApiModelProperty(value = "设备SN") private String deviceSn; drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/feign/IAttachClient.java
@@ -83,7 +83,7 @@ * @throws IOException */ @PostMapping(value = SAVE_ATTACH_FILE_2, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) BladeFile saveAttachFile(@RequestPart MultipartFile file, @RequestParam String fileName, @RequestParam Integer type) throws IOException; BladeFile saveAttachFile(@RequestPart MultipartFile file, @RequestParam String fileName, @RequestParam String type) throws IOException; /** * 附件上传 drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/feign/IAttachClientFallback.java
@@ -36,7 +36,7 @@ } @Override public BladeFile saveAttachFile(MultipartFile file, String fileName, Integer type) throws IOException { public BladeFile saveAttachFile(MultipartFile file, String fileName, String type) throws IOException { return null; } drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/vo/AttachVO.java
@@ -53,7 +53,7 @@ private String photoType; @ApiModelProperty(value = "照片结果类型") private List<Integer> resultTypes; private List<String> resultTypes; @ApiModelProperty(value = "排序方式 true:任务执行时间 false:附件创建时间") private Boolean orderByCreateTime; drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OssEndpoint.java
@@ -188,7 +188,7 @@ @PostMapping("/put-file-attach-by-name") @ApiOperation(value = "上传文件并保存至附件表", notes = "上传文件并保存至附件表-存储桶对象名称") public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam Integer resultType, @RequestParam String resultType, @RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, resultType, file.getSize(), bladeFile); @@ -224,7 +224,7 @@ private BladeFile getBladeFile(@RequestParam MultipartFile file) throws IOException { String fileName = file.getOriginalFilename(); BladeFile bladeFile = ossBuilder.template("estack").putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, null, file.getSize(), bladeFile); Long attachId = buildAttach(fileName, "", file.getSize(), bladeFile); bladeFile.setAttachId(attachId); return bladeFile; } @@ -237,7 +237,7 @@ * @param bladeFile 对象存储文件 * @return attachId */ private Long buildAttach(String fileName, Integer resultType, Long fileSize, BladeFile bladeFile) { private Long buildAttach(String fileName, String resultType, Long fileSize, BladeFile bladeFile) { String fileExtension = FileUtil.getFileExtension(fileName); Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); drone-ops/drone-resource/src/main/java/org/sxkj/resource/feign/AttachClient.java
@@ -73,9 +73,9 @@ attach.setOrderByCreateTime(true); attach.setAreaCode(HeaderUtils.getAreaCode()); List<Integer> integers = Arrays.asList(0, 2, 4, 5); List<String> integers = Arrays.asList("0", "2", "4", "5"); attach.setResultTypes(integers); List<Integer> resultTypes = attach.getResultTypes(); List<String> resultTypes = attach.getResultTypes(); String wordOrderType = attach.getWordOrderType(); settingResultType(attach, wordOrderType, resultTypes); @@ -104,7 +104,7 @@ * @param wordOrderType * @param resultTypes */ private static void settingResultType(AttachVO attach, String wordOrderType, List<Integer> resultTypes) { private static void settingResultType(AttachVO attach, String wordOrderType, List<String> resultTypes) { if (!StringUtils.isEmpty(wordOrderType) && !CollectionUtils.isEmpty(resultTypes)) { if ("-1".equals(wordOrderType)) { attach.setWordOrderType(null); @@ -128,7 +128,7 @@ } @Override public BladeFile saveAttachFile(MultipartFile file, String fileName, Integer type) throws IOException { public BladeFile saveAttachFile(MultipartFile file, String fileName, String type) throws IOException { BladeFile bladeFile = ossBuilder.template().putFile(pojo.getBucket(),fileName, file.getInputStream()); Long attachId = buildAttach(fileName, file.getSize(), bladeFile, type); bladeFile.setAttachId(attachId); @@ -148,7 +148,7 @@ return bladeFile; } private Long buildAttach(String fileName, Long fileSize, BladeFile bladeFile, Integer type) { private Long buildAttach(String fileName, Long fileSize, BladeFile bladeFile, String type) { String fileExtension = FileUtil.getFileExtension(fileName); Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java
@@ -131,11 +131,11 @@ attach.setAreaCode(HeaderUtils.getAreaCodeHeaderAreaCode(attach.getAreaCode())); if (Objects.isNull(attach.getResultTypes())) { // 使用常量定义避免魔法数字 attach.setResultTypes(Arrays.asList(TypeOfOutcome.IMAGE.getType(), TypeOfOutcome.VIDEO.getType(), TypeOfOutcome.AI.getType(), TypeOfOutcome.SURVEY.getType(), TypeOfOutcome.PANORAMA.getType())); // attach.setResultTypes(Arrays.asList(TypeOfOutcome.IMAGE.getType(), // TypeOfOutcome.VIDEO.getType(), // TypeOfOutcome.AI.getType(), // TypeOfOutcome.SURVEY.getType(), // TypeOfOutcome.PANORAMA.getType())); } List<Long> deptIdList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId())); String permissionCondition = permissionBuilder.buildDataPermissionCondition(AuthUtil.getUserId(), "attach"); drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java
@@ -146,7 +146,7 @@ @ApiOperation(value = "批量新增", notes = "传入gdTaskResult") public R batchSaveExternal(@Valid @RequestBody List<GdTaskResultDTO> gdTaskResults) { log.info("批量新增-对外接口{}", JSON.toJSONString(gdTaskResults)); return R.status(gdTaskResultService.saveBatchTaskResult(GdTaskResultWrapper.build().listEntity(gdTaskResults))); return R.status(gdTaskResultService.saveBatchTaskResult(gdTaskResults)); } /** drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdTaskResultDTO.java
@@ -85,16 +85,16 @@ private String areaCode; /** * 数据类型:1实时回传、2历史补传 * 媒体文件; 2ai文件; 3主视频; 4日志 ; */ @ApiModelProperty(value = "数据类型:1实时回传、2历史补传") @ApiModelProperty(value = " 1媒体文件; 2ai文件; 3主视频; 4日志 ;") private Integer dateType; /** * 文件类型:1可见光、2热成像、3点云、4全景 * 文件类型:照片 视频 图片 */ @ApiModelProperty(value = "文件类型:1可见光、2热成像、3点云、4全景") private Integer fileType; @ApiModelProperty(value = "文件类型:照片 视频 图片") private String fileType; /** * GeoJSON格式数据 drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuFlyTaskSaveDTO.java
@@ -45,8 +45,8 @@ @ApiModelProperty("巡检类型,字典") private String inspectionType; // @ApiModelProperty("巡检类型,字典-数组格式") // private String inspectionTypeArr; @ApiModelProperty("巡检类型,字典-数组格式") private List<List<String>> inspectionTypeArr; @ApiModelProperty("任务类型:定时飞行、航线飞行") private String taskType; drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdPatrolTaskEntity.java
@@ -25,6 +25,7 @@ import org.springblade.core.mp.base.BaseEntity; import org.sxkj.common.handler.ListToStringTypeHandler; import org.sxkj.common.handler.GenericListTypeHandler; import org.sxkj.common.handler.StringToIntegerTypeHandler; import java.util.Date; @@ -61,8 +62,9 @@ /** * 巡查任务类型(巡查类/安检类等) */ @ApiModelProperty(value = "巡查任务类型 1.巡查类 2.巡检类 3.安保类 4.文旅类 5.采集数据类 ") private String patrolTaskType; @ApiModelProperty(value = "巡查任务类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") @TableField(value = "patrol_task_type", typeHandler = GenericListTypeHandler.class) private List<List<String>> patrolTaskType; /** * 执行时间 */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdTaskResultEntity.java
@@ -82,9 +82,15 @@ @ApiModelProperty(value = "区域编码") private String areaCode; /** * 附件类型:0图片 1视频 2其他 * 附件类型:1媒体文件; 2ai文件; 3主视频; */ @ApiModelProperty(value = "附件类型:0图片 1视频 2其他") @ApiModelProperty(value = "附件类型:1媒体文件; 2ai文件; 3主视频;") private Integer attachmentType; /** * GeoJSON格式数据 */ @ApiModelProperty(value = "GeoJSON格式数据") private String geojson; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdWorkOrderEntity.java
@@ -24,9 +24,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.springblade.core.mp.base.BaseEntity; import org.sxkj.common.handler.GenericListTypeHandler; import org.sxkj.gd.config.GeometryTypeHandler; import java.util.Date; import java.util.List; /** * 工单任务表 实体类 @@ -55,9 +57,9 @@ /** * 工单类型(巡查类/安检类等) */ @ApiModelProperty(value = "工单类型(巡查类/安检类等)") @TableField("work_order_type") private String workOrderType; @ApiModelProperty(value = "工单类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") @TableField(value = "work_order_type", typeHandler = GenericListTypeHandler.class) private List<List<String>> workOrderType; /** * 设备负载需求(红外、喊话器、探照灯) */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml
@@ -8,7 +8,7 @@ <result column="work_order_id" property="workOrderId"/> <result column="work_order_name" property="workOrderName"/> <result column="patrol_task_name" property="patrolTaskName"/> <result column="patrol_task_type" property="patrolTaskType"/> <result column="patrol_task_type" property="patrolTaskType" typeHandler="org.sxkj.common.handler.GenericListTypeHandler"/> <result column="execute_time" property="executeTime"/> <result column="patrol_route_url" property="patrolRouteUrl"/> <result column="recommend_flyer_name" property="recommendFlyerName"/> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml
@@ -92,11 +92,11 @@ ja_gd_clue_event ce1 WHERE ce1.is_deleted = 0 AND ce1.create_time = ( SELECT MAX( create_time ) FROM ja_gd_clue_event ce2 WHERE ce2.result_id :: VARCHAR = ce1.result_id :: VARCHAR AND ce2.is_deleted = 0 ) ) ce ON ce.result_id :: VARCHAR = tr.id :: VARCHAR LEFT JOIN blade_user bu ON bu.id :: VARCHAR = ce.create_user :: VARCHAR AND ce1.create_time = ( SELECT MAX( create_time ) FROM ja_gd_clue_event ce2 WHERE CAST(ce2.result_id AS VARCHAR) = CAST(ce1.result_id AS VARCHAR) AND ce2.is_deleted = 0 ) ) ce ON CAST(ce.result_id AS VARCHAR) = CAST(tr.id AS VARCHAR) LEFT JOIN blade_user bu ON CAST(bu.id AS VARCHAR) = CAST(ce.create_user AS VARCHAR) AND bu.is_deleted = 0 LEFT JOIN blade_dept bd ON bd.id :: VARCHAR = ce.create_dept :: VARCHAR LEFT JOIN blade_dept bd ON CAST(bd.id AS VARCHAR) = CAST(ce.create_dept AS VARCHAR) AND bd.is_deleted = 0 WHERE tr.is_deleted = 0 @@ -115,7 +115,7 @@ result_code = #{resultCode}, result_url = #{resultUrl}, shoot_time = #{shootTime}, photo_data = #{photoData}::jsonb, photo_data = CAST(#{photoData} AS JSONB), longitude = #{longitude}, latitude = #{latitude}, distribute_status = #{distributeStatus}, @@ -138,7 +138,7 @@ <foreach collection="list" item="item" separator=","> ( #{item.patrolTaskId}, #{item.resultCode}, #{item.resultUrl}, #{item.shootTime}, CASE WHEN #{item.photoData} IS NULL THEN NULL ELSE #{item.photoData}::jsonb END, #{item.longitude}, #{item.latitude}, #{item.distributeStatus}, #{item.areaCode}, CASE WHEN #{item.photoData} IS NULL THEN NULL ELSE CAST(#{item.photoData} AS JSONB) END, #{item.longitude}, #{item.latitude}, #{item.distributeStatus}, #{item.areaCode}, #{item.createUser}, #{item.createDept}, #{item.createTime}, #{item.updateUser}, #{item.updateTime}, #{item.status}, #{item.isDeleted} ) drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml
@@ -7,7 +7,7 @@ <result column="id" property="id"/> <result column="work_order_name" property="workOrderName"/> <result column="work_order_code" property="workOrderCode"/> <result column="work_order_type" property="workOrderType"/> <result column="work_order_type" property="workOrderType" typeHandler="org.sxkj.common.handler.GenericListTypeHandler"/> <result column="device_load_demand" property="deviceLoadDemand"/> <result column="recommend_device_ids" property="recommendDeviceIds"/> <result column="work_order_status" property="workOrderStatus"/> @@ -26,7 +26,7 @@ <result column="is_deleted" property="isDeleted"/> </resultMap> <select id="getWorkOrderDetail" resultType="org.sxkj.gd.workorder.entity.GdWorkOrderEntity"> <select id="getWorkOrderDetail" resultMap="gdWorkOrderResultMap"> select id, work_order_name, work_order_code, drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdPatrolTaskAddParam.java
@@ -23,8 +23,8 @@ /** * 巡查任务类型(巡查类/安检类等) */ @ApiModelProperty(value = "巡查任务类型 1.巡查类 2.巡检类 3.安保类 4.文旅类 5.采集数据类 ") private String patrolTaskType; @ApiModelProperty(value = "巡查任务类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") private List<List<String>> patrolTaskType; /** * 执行时间 */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/WorkOrderAddParam.java
@@ -6,6 +6,7 @@ import javax.validation.constraints.NotNull; import java.util.Date; import java.util.List; @Data public class WorkOrderAddParam { @@ -23,9 +24,9 @@ /** * 工单类型(巡查类/安检类等) */ @ApiModelProperty(value = "工单类型(1.巡查类/2.安检类等)") @ApiModelProperty(value = "工单类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") // @NotNull private String workOrderType; private List<List<String>> workOrderType; /** * 设备负载需求(红外、喊话器、探照灯) */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java
@@ -17,6 +17,7 @@ package org.sxkj.gd.workorder.service; import com.baomidou.mybatisplus.core.conditions.Wrapper; import org.sxkj.gd.workorder.dto.GdTaskResultDTO; import org.sxkj.gd.workorder.entity.GdTaskResultEntity; import org.sxkj.gd.workorder.vo.GdTaskResultVO; import org.sxkj.gd.workorder.excel.GdTaskResultExcel; @@ -55,10 +56,10 @@ /** * * @param gdTaskResultEntities * @param gdTaskResults * @return */ boolean saveBatchTaskResult(List<GdTaskResultEntity> gdTaskResultEntities); boolean saveBatchTaskResult(List<GdTaskResultDTO> gdTaskResults); /** * 根据ID更新成果信息(更新所有字段) drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -547,8 +547,8 @@ if (bladeFile == null || StringUtil.isBlank(bladeFile.getLink())) { throw new RuntimeException("附件上传失败"); } Integer resultType = parseResultType(taskEntity != null ? taskEntity.getPatrolTaskType() : null); Attach attach = buildAttachInfo(taskEntity, reportFile, bladeFile, resultType, desiredName); // Integer resultType = parseResultType(taskEntity != null ? taskEntity.getPatrolTaskType() : null); Attach attach = buildAttachInfo(taskEntity, reportFile, bladeFile, taskEntity.getPatrolTaskType(), desiredName); Boolean saved = attachClient.saveAttachInfo(attach); if (!Boolean.TRUE.equals(saved)) { log.error("附件信息保存失败,报告文件:" + desiredName); @@ -567,7 +567,7 @@ * @param desiredName 期望文件名 * @return 附件信息 */ private Attach buildAttachInfo(GdPatrolTaskEntity taskEntity, File reportFile, BladeFile bladeFile, Integer resultType, String desiredName) { private Attach buildAttachInfo(GdPatrolTaskEntity taskEntity, File reportFile, BladeFile bladeFile, List<List<String>> resultType, String desiredName) { Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); attach.setLink(bladeFile.getLink()); @@ -575,7 +575,7 @@ attach.setOriginalName(bladeFile.getOriginalName()); attach.setAttachSize(reportFile.length()); attach.setExtension(FileUtil.getFileExtension(reportFile.getName())); attach.setResultType(resultType); attach.setResultType(JSON.toJSONString(resultType)); attach.setPatrolTaskId(String.valueOf(taskEntity != null ? taskEntity.getId() : null)); Long createUser = taskEntity != null ? taskEntity.getCreateUser() : null; Long updateUser = taskEntity != null ? taskEntity.getUpdateUser() : null; @@ -660,9 +660,9 @@ } else if (StringUtil.isNotBlank(gdPatrolTaskVO.getTaskNo())) { param.setName(gdPatrolTaskVO.getTaskNo()); } if (StringUtil.isNotBlank(gdPatrolTaskVO.getPatrolTaskType())) { param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); } // if (StringUtil.isNotBlank(gdPatrolTaskVO.getPatrolTaskType())) { // param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); // } if ((gdPatrolTaskVO.getId() != null)) { param.setPatrolTaskId(String.valueOf(gdPatrolTaskVO.getId())); } @@ -690,8 +690,8 @@ // 机构 param.setDeptId(gdPatrolTaskVO.getCreateDept()); // 巡检类型 // param.setInspectionTypeArr(gdPatrolTaskVO.getPatrolTaskType()); param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); param.setInspectionTypeArr(gdPatrolTaskVO.getPatrolTaskType()); // param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); // 机巢名称 param.setAirportName(gdPatrolTaskVO.getDeviceName()); param.setStatus("待执行"); drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java
@@ -16,25 +16,43 @@ */ package org.sxkj.gd.workorder.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.sxkj.gd.workorder.dto.GdTaskResultDTO; import org.sxkj.gd.workorder.entity.GdDeviceCallDetailEntity; import org.sxkj.gd.workorder.entity.GdDeviceCallEntity; import org.sxkj.gd.workorder.entity.GdManageDeviceEntity; import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; import org.sxkj.gd.workorder.entity.GdTaskResultEntity; import org.sxkj.gd.workorder.service.IGdDeviceCallDetailService; import org.sxkj.gd.workorder.service.IGdDeviceCallService; import org.sxkj.gd.workorder.service.IGdManageDeviceService; import org.sxkj.gd.workorder.service.IGdPatrolTaskService; import org.sxkj.gd.workorder.service.IGdTaskResultService; import org.sxkj.gd.workorder.vo.GdTaskResultVO; import org.sxkj.gd.workorder.excel.GdTaskResultExcel; import org.sxkj.gd.workorder.mapper.GdTaskResultMapper; import org.sxkj.gd.workorder.service.IGdTaskResultService; import org.sxkj.common.utils.HeaderUtils; import org.sxkj.common.utils.SpringContextUtil; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.StringUtil; import org.sxkj.gd.workorder.wrapper.GdTaskResultWrapper; import org.sxkj.system.cache.SysCache; import org.sxkj.system.cache.UserCache; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.*; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -44,8 +62,23 @@ * @author lw * @since 2026-01-14 */ @Slf4j @Service public class GdTaskResultServiceImpl extends BaseServiceImpl<GdTaskResultMapper, GdTaskResultEntity> implements IGdTaskResultService { /** * 日志数据解析后的内部类 */ @lombok.Data private static class DeviceCallLogItem { private String content; private String createTime; private String createUserName; private String delFlag; private String flyDataId; private String id; private String pilotSn; } @Override public IPage<GdTaskResultVO> selectGdTaskResultPage(IPage<GdTaskResultVO> page, GdTaskResultVO gdTaskResult) { @@ -72,30 +105,239 @@ } @Override public boolean saveBatchTaskResult(List<GdTaskResultEntity> gdTaskResultEntities) { if (gdTaskResultEntities == null || gdTaskResultEntities.isEmpty()) { public boolean saveBatchTaskResult(List<GdTaskResultDTO> gdTaskResults) { if (gdTaskResults == null || gdTaskResults.isEmpty()) { log.error("saveBatchTaskResult-批量新增-对外接口数据为空"); return false; } // 按dateType分组处理 Map<Integer, List<GdTaskResultDTO>> groupedByDateType = gdTaskResults.stream() .collect(Collectors.groupingBy(dto -> dto.getDateType() != null ? dto.getDateType() : 0)); // 处理 dateType != 4 的数据,保存到成果表 List<GdTaskResultDTO> normalResults = groupedByDateType.entrySet().stream() .filter(entry -> entry.getKey() != 4) .flatMap(entry -> entry.getValue().stream()) .collect(Collectors.toList()); if (!normalResults.isEmpty()) { saveNormalTaskResults(normalResults); } // 处理 dateType == 4 的数据,保存到设备调用表和设备调用详情表 List<GdTaskResultDTO> logResults = groupedByDateType.get(4); if (logResults != null && !logResults.isEmpty()) { saveDeviceCallData(logResults); } return true; } /** * 保存普通成果数据(dateType != 4) * * @param gdTaskResults 成果DTO列表 */ private void saveNormalTaskResults(List<GdTaskResultDTO> gdTaskResults) { List<GdTaskResultEntity> gdTaskResultEntities = GdTaskResultWrapper.build().listEntity(gdTaskResults); IGdPatrolTaskService patrolTaskService = SpringContextUtil.getBean(IGdPatrolTaskService.class); // 查询巡查任务信息 GdPatrolTaskEntity patrolTask = patrolTaskService.getById(gdTaskResultEntities.get(0).getPatrolTaskId()); if (patrolTask == null) { log.warn("巡查任务不存在:" + patrolTask.getId()); return; } gdTaskResultEntities.forEach(gdTaskResult -> { String resultUrl = gdTaskResult.getResultUrl(); // 使用HeaderUtils处理区域代码 // resultUrl = http://220.177.172.27:8100/S3/xcy010.eoshlw.internal.jazwy.cn/2026/04/23/DJI_20260128135433_0005_V_20260423111422A015.jpeg // resultUrl = http://220.177.172.27:8100/S3/xcy010.eoshlw.internal.jazwy.cn/2026/04/23/2026-04-23-09-50-29-0_20260423190046A001.mp4 gdTaskResult.setAttachmentType(HeaderUtils.getAttachmentType(resultUrl)); String processedAreaCode = HeaderUtils.processAreaCode(gdTaskResult.getAreaCode()); String processedAreaCode = HeaderUtils.processAreaCode(gdTaskResult.getAreaCode()); gdTaskResult.setAreaCode(processedAreaCode); // 如果resultCode为空,生成时间戳作为默认值 if (StringUtil.isEmpty(gdTaskResult.getResultCode())) { gdTaskResult.setResultCode(String.valueOf(System.currentTimeMillis())); } if (gdTaskResult.getShootTime() == null) { gdTaskResult.setShootTime(new Date()); } gdTaskResult.setStatus(0); gdTaskResult.setUpdateTime(new Date()); gdTaskResult.setCreateTime(new Date()); gdTaskResult.setIsDeleted(0); gdTaskResult.setCreateDept(1L); gdTaskResult.setUpdateUser(1L); gdTaskResult.setCreateDept(patrolTask.getCreateDept()); gdTaskResult.setUpdateUser(patrolTask.getCreateUser()); gdTaskResult.setDistributeStatus(0); }); // 执行批量保存并返回结果 int result = baseMapper.insertBatch(gdTaskResultEntities); return result > 0; int i = baseMapper.insertBatch(gdTaskResultEntities); } /** * 保存设备调用数据(dateType == 4) * geojson字段解析后保存到设备调用详情表,同时创建一条设备调用主表记录 * * @param logResults 日志类型的成果DTO列表 */ private void saveDeviceCallData(List<GdTaskResultDTO> logResults) { // 使用SpringContextUtil动态获取服务,避免循环依赖 IGdPatrolTaskService patrolTaskService = SpringContextUtil.getBean(IGdPatrolTaskService.class); IGdDeviceCallService deviceCallService = SpringContextUtil.getBean(IGdDeviceCallService.class); IGdDeviceCallDetailService deviceCallDetailService = SpringContextUtil.getBean(IGdDeviceCallDetailService.class); IGdManageDeviceService manageDeviceService = SpringContextUtil.getBean(IGdManageDeviceService.class); for (GdTaskResultDTO logResult : logResults) { Long patrolTaskId = logResult.getPatrolTaskId(); String geojson = logResult.getGeojson(); if (patrolTaskId == null || StringUtil.isEmpty(geojson)) { log.warn("设备调用数据不完整,patrolTaskId: {}, geojson: {}", patrolTaskId, geojson); continue; } // 查询巡查任务信息 GdPatrolTaskEntity patrolTask = patrolTaskService.getById(patrolTaskId); if (patrolTask == null) { log.warn("巡查任务不存在:" + patrolTaskId); continue; } // 解析geojson数据 List<DeviceCallLogItem> logItems = parseGeojson(geojson); if (logItems == null || logItems.isEmpty()) { log.warn("geojson解析结果为空:" + geojson); continue; } // 保存设备调用主表记录 GdDeviceCallEntity callEntity = buildDeviceCallEntity(patrolTask, logItems, manageDeviceService); boolean b = deviceCallService.saveOrUpdate(callEntity); // 保存设备调用详情记录 List<GdDeviceCallDetailEntity> detailEntities = buildDeviceCallDetailEntities(callEntity.getId(), logItems); boolean b1 = deviceCallDetailService.saveBatch(detailEntities); } } /** * 解析geojson字段,提取设备调用日志列表 * * @param geojson geojson字符串 * @return 日志项列表 */ private List<DeviceCallLogItem> parseGeojson(String geojson) { try { return JSON.parseObject(geojson, new TypeReference<List<DeviceCallLogItem>>() {}); } catch (Exception e) { log.error("解析geojson失败: " + geojson, e); return null; } } /** * 构建设备调用主表实体 * * @param patrolTask 巡查任务实体 * @param logItems 日志项列表 * @param manageDeviceService 设备管理服务 * @return 设备调用实体 */ private GdDeviceCallEntity buildDeviceCallEntity(GdPatrolTaskEntity patrolTask, List<DeviceCallLogItem> logItems, IGdManageDeviceService manageDeviceService) { GdDeviceCallEntity callEntity = new GdDeviceCallEntity(); callEntity.setPatrolTaskName(patrolTask.getPatrolTaskName()); callEntity.setTaskDepartment(SysCache.getDeptName(patrolTask.getCreateDept())); callEntity.setTaskDepartmentId(patrolTask.getCreateDept()); callEntity.setTaskInitiator(String.valueOf(patrolTask.getCreateUser())); callEntity.setTaskInitiatorId(patrolTask.getCreateUser()); callEntity.setPlanExecuteTime(patrolTask.getExecuteTime()); // 从日志项中获取设备SN String deviceSn = logItems.stream() .map(DeviceCallLogItem::getPilotSn) .filter(StringUtil::hasText) .findFirst() .orElse(null); if (StringUtil.hasText(deviceSn)) { GdManageDeviceEntity device = manageDeviceService.getOne( Wrappers.lambdaQuery(GdManageDeviceEntity.class) .eq(GdManageDeviceEntity::getDeviceSn, deviceSn), false ); if (device != null) { callEntity.setDeviceId(device.getId()); callEntity.setDeviceName(device.getDeviceName()); } } // 计算飞行时长(使用日志中最小时间和最大时间做差值计算) if (!logItems.isEmpty()) { try { List<Date> validDates = logItems.stream() .map(item -> parseDateTime(item.getCreateTime())) .filter(Objects::nonNull) .sorted() .collect(Collectors.toList()); if (!validDates.isEmpty()) { Date startTime = validDates.get(0); Date endTime = validDates.get(validDates.size() - 1); long durationSeconds = (endTime.getTime() - startTime.getTime()) / 1000; callEntity.setFlightDuration(durationSeconds); callEntity.setActualExecuteTime(startTime); } } catch (Exception e) { log.warn("计算飞行时长失败", e); callEntity.setFlightDuration(0L); } } return callEntity; } /** * 构建设备调用详情实体列表 * * @param patrolTaskId 巡查任务ID * @param logItems 日志项列表 * @return 设备调用详情实体列表 */ private List<GdDeviceCallDetailEntity> buildDeviceCallDetailEntities(Long patrolTaskId, List<DeviceCallLogItem> logItems) { List<GdDeviceCallDetailEntity> detailEntities = new ArrayList<>(); int sort = 1; for (DeviceCallLogItem logItem : logItems) { GdDeviceCallDetailEntity detailEntity = new GdDeviceCallDetailEntity(); detailEntity.setCallId(patrolTaskId); detailEntity.setDeviceStatus(logItem.getContent()); detailEntity.setOccurTime(parseDateTime(logItem.getCreateTime())); detailEntity.setSort(sort++); detailEntities.add(detailEntity); } return detailEntities; } /** * 解析日期时间字符串 * * @param dateTimeStr 日期时间字符串 * @return Date对象 */ private Date parseDateTime(String dateTimeStr) { if (StringUtil.isEmpty(dateTimeStr)) { return null; } try { if (dateTimeStr.contains("T")) { dateTimeStr = dateTimeStr.replace("T", " "); } if (dateTimeStr.contains(".")) { dateTimeStr = dateTimeStr.substring(0, dateTimeStr.indexOf(".")); } return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateTimeStr); } catch (Exception e) { log.warn("日期解析失败: " + dateTimeStr, e); return null; } } @Override drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java
@@ -77,12 +77,6 @@ return gdWorkOrderList; } /** * 保存工单任务表 * * @param workOrderParam * @return */ @Override @Transactional(rollbackFor = Exception.class) public boolean saveOrUpdateWorkOrder(WorkOrderAddParam workOrderParam) { drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdPatrolTaskVO.java
@@ -63,8 +63,8 @@ /** * 巡查任务类型(巡查类/安检类等) */ @ApiModelProperty(value = "巡查任务类型 1.巡查类 2.巡检类 3.安保类 4.文旅类 5.采集数据类 ") private String patrolTaskType; @ApiModelProperty(value = "巡查任务类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") private List<List<String>> patrolTaskType; /** * 执行时间 */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdWorkOrderVO.java
@@ -20,6 +20,7 @@ import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; @@ -47,10 +48,10 @@ @ApiModelProperty(value = "工单编号(唯一)") private String workOrderCode; /** * 工单类型(巡查类/安检类等) */ @ApiModelProperty(value = "工单类型(巡查类/安检类等)") private String workOrderType; * 工单类型(巡查类/安检类等) */ @ApiModelProperty(value = "工单类型(二维数组,如:[[\"road\",\"road1\"],[\"bridge\",\"bridge2\"]])") private List<List<String>> workOrderType; /** * 设备负载需求(红外、喊话器、探照灯) */ drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/wrapper/GdTaskResultWrapper.java
@@ -24,6 +24,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * 成果表 包装类,返回视图层所需的字段 @@ -39,12 +40,56 @@ @Override public GdTaskResultVO entityVO(GdTaskResultEntity gdTaskResult) { return Objects.requireNonNull(BeanUtil.copy(gdTaskResult, GdTaskResultVO.class)); } /** * 将DTO列表转换为Entity列表 * * @param gdTaskResultDTOList DTO列表 * @return Entity列表 */ public List<GdTaskResultEntity> listEntity(List<GdTaskResultDTO> gdTaskResultDTOList) { return BeanUtil.copyWithConvert(gdTaskResultDTOList, GdTaskResultEntity.class); return gdTaskResultDTOList.stream() .map(this::convertDtoToEntity) .collect(Collectors.toList()); } /** * 将单个DTO转换为Entity * * @param dto DTO对象 * @return Entity对象 */ private GdTaskResultEntity convertDtoToEntity(GdTaskResultDTO dto) { GdTaskResultEntity entity = BeanUtil.copy(dto, GdTaskResultEntity.class); if (dto.getFileType() != null) { entity.setAttachmentType(dto.getDateType()); } return entity; } /** * 将文件类型字符串转换为附件类型编码 * * @param fileType 文件类型字符串(图片/视频/照片) * @return 附件类型编码:0-图片,1-视频,2-其他 */ private Integer convertFileTypeToAttachmentType(String fileType) { if (fileType == null) { return 2; } switch (fileType.trim()) { case "图片": case "照片": return 0; case "视频": return 1; default: return 2; } } }