吉安感知网项目-后端
26 files modified
1 files added
526 ■■■■ changed files
drone-common/src/main/java/org/sxkj/common/handler/GenericListTypeHandler.java 42 ●●●●● patch | view | raw | blame | history
drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/entity/Attach.java 10 ●●●● patch | view | raw | blame | history
drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/feign/IAttachClient.java 2 ●●● patch | view | raw | blame | history
drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/feign/IAttachClientFallback.java 2 ●●● patch | view | raw | blame | history
drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/vo/AttachVO.java 2 ●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OssEndpoint.java 6 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/feign/AttachClient.java 10 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java 10 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdTaskResultDTO.java 12 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuFlyTaskSaveDTO.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdPatrolTaskEntity.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdTaskResultEntity.java 10 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdWorkOrderEntity.java 8 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml 12 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdPatrolTaskAddParam.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/WorkOrderAddParam.java 5 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java 5 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java 18 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java 274 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdPatrolTaskVO.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdWorkOrderVO.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/wrapper/GdTaskResultWrapper.java 49 ●●●●● patch | view | raw | blame | history
drone-task/drone-odm/src/main/java/org/sxkj/odm/service/impl/OdmTaskInfoServiceImpl.java 8 ●●●● patch | view | raw | blame | history
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
@@ -36,7 +36,7 @@
    @ApiModelProperty("主键id")
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
    private String id;
    /**
     * 关联巡查任务表ID
@@ -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;
        }
    }
}
drone-task/drone-odm/src/main/java/org/sxkj/odm/service/impl/OdmTaskInfoServiceImpl.java
@@ -774,11 +774,11 @@
        }
        // 设置类型-切斜摄影
        if (odmTaskInfo.getType() == OdmTypeEnum.TILT.getType().intValue()) {
            attach.setResultType(AttachResultTypeEnum.TILT.getType());
            attach.setResultType(AttachResultTypeEnum.TILT.getType().toString());
        }
        // 设置类型-三维白膜
        if (odmTaskInfo.getType() == OdmTypeEnum.ALB.getType().intValue()) {
            attach.setResultType(AttachResultTypeEnum.ALB.getType());
            attach.setResultType(AttachResultTypeEnum.ALB.getType().toString());
        }
        // 设置区域编号
        attach.setAreaCode(odmTaskInfo.getAreaCode());
@@ -979,7 +979,7 @@
                attach.setPatrolTaskId(odmTaskInfo.getWaylineJobId());
            }
            // 设置类型
            attach.setResultType(AttachResultTypeEnum.ORT.getType());
            attach.setResultType(AttachResultTypeEnum.ORT.getType().toString());
            // 设置设备编号
            if (!Strings.isBlank(odmTaskInfo.getDeviceSn())) {
                attach.setDeviceSn(odmTaskInfo.getDeviceSn());
@@ -2610,7 +2610,7 @@
        // 设置类型-三维白膜
        // 测试用,临时用,用后需要手动数据库修改
        attach.setResultType(AttachResultTypeEnum.ALB.getType());
        attach.setResultType(AttachResultTypeEnum.ALB.getType().toString());
        log.info("发起远程调用保存三维白膜/倾斜附件信息,tif 路径:{}", path);
        Boolean isSaveAttach = attachClient.saveAttachInfo(attach);