吉安感知网项目-后端
b0b01b7302d2b9c6b2f5c6583d40b92b63e6b5f1..3ba4841f2f11d4fcadb78a4891595e9368323571
2026-06-09 linwei
fix(task): 修复任务更新日志和工单流转处理
3ba484 diff | tree
2026-06-09 linwei
feat(workorder): 根据执行结果动态设置巡查任务状态
ba4922 diff | tree
2026-06-09 linwei
fix(task): 优化星图飞行任务推送错误处理
eb3423 diff | tree
2026-06-09 linwei
fix(task): 优化星图飞行任务推送错误处理
3624ea diff | tree
2026-06-09 linwei
fix(xingtu): 完善星图接口调用的错误处理机制
c79309 diff | tree
2026-06-09 linwei
feat(workorder): 添加线索事件的geojson和附件类型字段
f6579c diff | tree
2026-06-09 linwei
fix(workorder): 修正线索事件附件类型字段映射
c5891a diff | tree
2026-06-09 linwei
feat(workorder): 添加事件地理信息和附件类型字段
beb202 diff | tree
2026-06-09 linwei
refactor(flyer): 修改飞手分页参数中的擅长任务类型字段
d8dc38 diff | tree
2026-06-09 linwei
fix(area): 修复派出所信息查询逻辑
04056b diff | tree
2026-06-09 linwei
feat(police-station): 添加派出所名称唯一性校验功能
8ae33e diff | tree
2026-06-09 linwei
``` fix(attach): 修复附件查询中resultType参数处理逻辑
938d8b diff | tree
2026-06-09 linwei
fix(workorder): 修复工单和巡检任务类型查询的逗号分隔值处理
1fe7ed diff | tree
2026-06-09 linwei
fix(odm): 修复任务信息中的结果类型设置问题
abe28f diff | tree
2026-06-09 linwei
refactor(flyer): 修改飞手表单和实体类中的擅长任务类型字段
b48687 diff | tree
29 files modified
250 ■■■■ changed files
drone-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/entity/Attach.java 4 ●●● 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/drone-resource/src/main/java/org/sxkj/resource/dto/AttachDto.java 3 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OssEndpoint.java 7 ●●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/feign/AttachClient.java 6 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/mapper/AttachMapper.xml 18 ●●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/param/AttachPageParam.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwPoliceStationServiceImpl.java 31 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/common/IdParam.java 8 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/entity/GdFlyerEntity.java 4 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/mapper/GdFlyerMapper.xml 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/param/GdFlyerAddParam.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/vo/GdFlyerVO.java 7 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdPatrolTaskController.java 14 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java 12 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdClueEventMapper.xml 10 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml 8 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.java 11 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml 8 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java 9 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java 19 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java 13 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventListVO.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventVO.java 7 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/xingtu/JianXingtuApiService.java 12 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/DeptServiceImpl.java 4 ●●●● 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-ops-api/drone-resource-api/src/main/java/org/sxkj/resource/entity/Attach.java
@@ -11,6 +11,7 @@
import org.springblade.core.tenant.mp.TenantEntity;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.util.StringUtils;
import org.sxkj.common.handler.GenericListTypeHandler;
import org.sxkj.common.utils.file.FileNameHarsher;
import java.util.List;
@@ -82,7 +83,8 @@
    private String patrolTaskId;
    @ApiModelProperty(value = "附件类型: 1=巡查类文档,2=巡检类文档,3=安保类文档,4=文旅类文档,5=采集数据类文档")
    private String resultType;
    @TableField(typeHandler = GenericListTypeHandler.class)
    private List<List<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 String type) throws IOException;
    BladeFile saveAttachFile(@RequestPart MultipartFile file, @RequestParam String fileName, @RequestParam List<List<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, String type) throws IOException {
    public BladeFile saveAttachFile(MultipartFile file, String fileName, List<List<String>> type) throws IOException {
        return null;
    }
drone-ops/drone-resource/src/main/java/org/sxkj/resource/dto/AttachDto.java
@@ -4,6 +4,7 @@
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class AttachDto {
@@ -35,7 +36,7 @@
    private String originalName;
    @ApiModelProperty(value = "附件类型: 1=巡查类文档,2=巡检类文档,3=安保类文档,4=文旅类文档,5=采集数据类文档")
    private Integer resultType;
    private List<List<String>> resultType;
    @ApiModelProperty(value = "附件大小")
    private Long attachSize;
drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OssEndpoint.java
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -188,7 +189,7 @@
    @PostMapping("/put-file-attach-by-name")
    @ApiOperation(value = "上传文件并保存至附件表", notes = "上传文件并保存至附件表-存储桶对象名称")
    public R<BladeFile> putFileAttach(@RequestParam String fileName,
                                      @RequestParam String resultType,
                                      @RequestParam List<List<String>> resultType,
                                      @RequestParam MultipartFile file) {
        BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
        Long attachId = buildAttach(fileName, resultType, file.getSize(), bladeFile);
@@ -224,7 +225,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, "", file.getSize(), bladeFile);
        Long attachId = buildAttach(fileName, null, file.getSize(), bladeFile);
        bladeFile.setAttachId(attachId);
        return bladeFile;
    }
@@ -237,7 +238,7 @@
     * @param bladeFile 对象存储文件
     * @return attachId
     */
    private Long buildAttach(String fileName, String resultType, Long fileSize, BladeFile bladeFile) {
    private Long buildAttach(String fileName, List<List<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
@@ -128,7 +128,7 @@
    }
    @Override
    public BladeFile saveAttachFile(MultipartFile file, String fileName, String type) throws IOException {
    public BladeFile saveAttachFile(MultipartFile file, String fileName, List<List<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, String type) {
    private Long buildAttach(String fileName, Long fileSize, BladeFile bladeFile, List<List<String>> type) {
        String fileExtension = FileUtil.getFileExtension(fileName);
        Attach attach = new Attach();
        attach.setDomainUrl(bladeFile.getDomain());
@@ -235,7 +235,7 @@
            saveAttachFile(new MockMultipartFile( mediaFile.getName(),
                mediaFile.getName(),
                "application/octet-stream",
                new FileInputStream(mediaFile)), name, Attach.RESULT_TYPE_VEDIO_SHOW);
                new FileInputStream(mediaFile)), name, null);
            log.info("第{}个视频保存入库完成...", (i + 1));
        }
drone-ops/drone-resource/src/main/java/org/sxkj/resource/mapper/AttachMapper.xml
@@ -18,10 +18,11 @@
        <result column="original_name" property="originalName"/>
        <result column="extension" property="extension"/>
        <result column="attach_size" property="attachSize"/>
        <result column="result_type" property="resultType" typeHandler="org.sxkj.common.handler.GenericListTypeHandler"/>
    </resultMap>
    <!--自定义分页查询-->
    <select id="selectAttachPage" resultType="org.sxkj.resource.vo.AttachVO">
    <select id="selectAttachPage" resultMap="attachResultMap" >
        select
        ba.*,
        bd.dept_name,
@@ -36,9 +37,14 @@
        <if test="attach.nickName!=null and attach.nickName!=''">
            and ba.nick_name like concat('%',#{attach.nickName},'%')
        </if>
        <if test="attach.resultType!=null">
            /* 修改点2:如果 resultType 是字符串传入,也需加权转 */
            and ba.result_type::text = #{attach.resultType}::text
        <if test="attach.resultType!=null and attach.resultType!='' ">
            /* 将逗号分隔的字符串转换为带引号的格式,如 "road,road1" 转为 "\"road\",\"road1\"" */
            and ba.result_type like concat('%',
            (
            select string_agg(concat('"', trim(arr_val), '"'), ',')
            from unnest(string_to_array(#{attach.resultType}, ',')) as arr_val
            ),
            '%')
        </if>
        <if test="attach.deptList != null and attach.deptList.size > 0">
            and ba.create_dept::text in
@@ -46,9 +52,7 @@
                #{deptId}::text
            </foreach>
        </if>
        /* 修改点3:result_type 如果是字符型字段,数字必须加单引号 */
        and ba.result_type::text in ('1','2','3','4','5')
        order by ba.create_time desc, ba.id desc
          order by ba.create_time desc, ba.id desc
    </select>
    <select id="findAiAttachImages" resultType="org.sxkj.resource.vo.AttachVO">
drone-ops/drone-resource/src/main/java/org/sxkj/resource/param/AttachPageParam.java
@@ -12,7 +12,7 @@
    private Long id;
    @ApiModelProperty(value = "附件类型: 1=巡查类文档,2=巡检类文档,3=安保类文档,4=文旅类文档,5=采集数据类文档")
    private Integer resultType;
    private String resultType;
    /**
     * 附件原名
     */
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwPoliceStationServiceImpl.java
@@ -17,6 +17,7 @@
package org.sxkj.fw.area.service.impl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.StringUtil;
import org.sxkj.common.utils.HeaderUtils;
import org.sxkj.fw.area.entity.FwPoliceStationEntity;
@@ -26,6 +27,7 @@
import org.sxkj.fw.area.mapper.FwPoliceStationMapper;
import org.sxkj.fw.area.service.IFwPoliceStationService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
@@ -71,18 +73,24 @@
    @Override
    public boolean save(FwPoliceStationEntity fwPoliceStation) {
        // 校验派出所名称唯一性
        checkStationNameUnique(fwPoliceStation.getStationName(), null);
        fillCreateFields(fwPoliceStation);
        return super.save(fwPoliceStation);
    }
    @Override
    public boolean updateById(FwPoliceStationEntity fwPoliceStation) {
        // 校验派出所名称唯一性(排除当前记录)
        checkStationNameUnique(fwPoliceStation.getStationName(), fwPoliceStation.getId());
        fillUpdateFields(fwPoliceStation);
        return super.updateById(fwPoliceStation);
    }
    @Override
    public boolean saveOrUpdate(FwPoliceStationEntity fwPoliceStation) {
        // 校验派出所名称唯一性
        checkStationNameUnique(fwPoliceStation.getStationName(), fwPoliceStation.getId());
        if (fwPoliceStation.getId() == null) {
            fillCreateFields(fwPoliceStation);
        } else {
@@ -91,6 +99,29 @@
        return super.saveOrUpdate(fwPoliceStation);
    }
    /**
     * 校验派出所名称唯一性
     *
     * @param stationName 派出所名称
     * @param excludeId   排除的ID(更新时使用,排除当前记录)
     * @throws RuntimeException 当名称已存在时抛出异常
     */
    private void checkStationNameUnique(String stationName, Long excludeId) {
        if (StringUtil.isBlank(stationName)) {
            return;
        }
        LambdaQueryWrapper<FwPoliceStationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FwPoliceStationEntity::getStationName, stationName);
        queryWrapper.eq(FwPoliceStationEntity::getIsDeleted, BladeConstant.DB_NOT_DELETED);
        if (excludeId != null) {
            queryWrapper.ne(FwPoliceStationEntity::getId, excludeId);
        }
        long count = count(queryWrapper);
        if (count > 0) {
            throw new RuntimeException("派出所名称 '" + stationName + "' 已存在");
        }
    }
    private void fillCreateFields(FwPoliceStationEntity fwPoliceStation) {
        // 创建/更新基础审计字段统一设置
        Long userId = AuthUtil.getUserId();
drone-service/drone-gd/src/main/java/org/sxkj/gd/common/IdParam.java
@@ -38,4 +38,12 @@
    @NotNull(message = "主键ID不能为空")
    private    Long id;
    /**
     * 执行是否成功(可选字段,仅用于特定接口)
     * true: 执行成功,状态设置为待验收(PENDING_ACCEPTANCE)
     * false: 执行失败,状态设置为待签收(PENDING_SIGNING)
     */
    @ApiModelProperty(value = "执行是否成功,true=成功(待验收),false=失败(待签收)")
    private Boolean success;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/entity/GdFlyerEntity.java
@@ -24,6 +24,7 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import org.sxkj.common.handler.GenericListTypeHandler;
import java.math.BigDecimal;
import java.util.List;
@@ -80,7 +81,8 @@
     * 擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)
     */
    @ApiModelProperty(value = "擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)")
    private String skilledTaskType;
    @TableField(typeHandler = GenericListTypeHandler.class)
    private List<List<String>> skilledTaskType;
    /**
     * 区域编码
     */
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/mapper/GdFlyerMapper.xml
@@ -11,7 +11,7 @@
        <result column="project_experience" property="projectExperience"/>
        <result column="technical_strength" property="technicalStrength"/>
        <result column="skilled_uav_type" property="skilledUavType"/>
        <result column="skilled_task_type" property="skilledTaskType"/>
        <result column="skilled_task_type" property="skilledTaskType" typeHandler="org.sxkj.common.handler.GenericListTypeHandler"/>
        <result column="area_code" property="areaCode"/>
        <result column="flyer_address" property="flyerAddress"/>
        <result column="certification" property="certification" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
@@ -33,7 +33,7 @@
        <result column="project_experience" property="projectExperience"/>
        <result column="technical_strength" property="technicalStrength"/>
        <result column="skilled_uav_type" property="skilledUavType"/>
        <result column="skilled_task_type" property="skilledTaskType"/>
        <result column="skilled_task_type" property="skilledTaskType" typeHandler="org.sxkj.common.handler.GenericListTypeHandler"/>
        <result column="area_code" property="areaCode"/>
        <result column="flyer_address" property="flyerAddress"/>
        <result column="certification" property="certification" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/param/GdFlyerAddParam.java
@@ -54,7 +54,7 @@
     * 擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)
     */
    @ApiModelProperty(value = "擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)")
    private String skilledTaskType;
    private List<List<String>> skilledTaskType;
    /**
     * 区域编码
     */
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/vo/GdFlyerVO.java
@@ -16,6 +16,7 @@
 */
package org.sxkj.gd.flyer.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -24,6 +25,7 @@
import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.sxkj.common.handler.GenericListTypeHandler;
/**
 * 飞手表 视图实体类
@@ -75,7 +77,8 @@
     * 擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)
     */
    @ApiModelProperty(value = "擅长任务类型(0:巡查类 1:安保类 2:文旅类 3:采集数据类)")
    private String skilledTaskType;
    @TableField(typeHandler = GenericListTypeHandler.class)
    private List<List<String>> skilledTaskType;
    /**
     * 区域编码
     */
@@ -91,7 +94,7 @@
     */
    @ApiModelProperty(value = "飞手资质证书地址列表")
    private List<String> certification;
    /**
     * 区域匹配标识(0:未匹配 1:匹配)
     */
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdPatrolTaskController.java
@@ -152,10 +152,13 @@
    /**
     * 巡查任务执行完成-对外
     * 根据执行结果设置不同状态:
     * - 执行成功(success=true或不传): 状态设置为待验收(PENDING_ACCEPTANCE)
     * - 执行失败(success=false): 状态设置为待签收(PENDING_SIGNING)
     */
    @PostMapping("/auditExternal")
    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "巡查任务执行完成-对外", notes = "只能使用执行完成操作")
    @ApiOperation(value = "巡查任务执行完成-对外", notes = "根据执行结果设置不同状态,不传success默认为成功")
    public R auditExternal(@Valid @RequestBody IdParam param) {
        log.info("巡查任务执行完成-对外:{}", param);
        if (param.getId() == null) {
@@ -163,7 +166,14 @@
        }
        GdPatrolTaskEntity auditParam = new GdPatrolTaskEntity();
        auditParam.setId(param.getId());
        auditParam.setTaskStatus(PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getValue());
        // 根据执行结果设置不同状态,不传success默认为成功
        if (param.getSuccess() == null || Boolean.TRUE.equals(param.getSuccess())) {
            // 执行成功(或不传),设置为待验收状态
            auditParam.setTaskStatus(PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getValue());
        } else {
            // 执行失败,设置为待签收状态
            auditParam.setTaskStatus(PatrolTaskStatusEnum.PENDING_SIGNING.getValue());
        }
        return R.status(gdPatrolTaskService.updatePatrolTaskById(auditParam));
    }
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java
@@ -79,12 +79,18 @@
    }
    /**
     * 成果表 列表
     *
     * @param patrolTaskId    巡查任务ID
     * @param attachmentTypes 附件类型列表:1媒体文件;2ai文件;3主视频;(可选,不传则查询全部,多个用逗号分隔)
     * @return 成果列表
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "列表", notes = "传入patrolTaskId")
    public R<List<GdTaskResultVO>> list(@ApiParam(value = "巡查任务ID", required = true) @RequestParam Long patrolTaskId) {
        return R.data(gdTaskResultService.listByPatrolTaskId(patrolTaskId));
    @ApiOperation(value = "列表", notes = "传入patrolTaskId和attachmentTypes")
    public R<List<GdTaskResultVO>> list(
            @ApiParam(value = "巡查任务ID", required = true) @RequestParam Long patrolTaskId,
            @ApiParam(value = "附件类型:1媒体文件;2ai文件;3主视频;多个用逗号分隔") @RequestParam(required = false) List<Integer> attachmentTypes) {
        return R.data(gdTaskResultService.listByPatrolTaskId(patrolTaskId, attachmentTypes));
    }
//    /**
//     * 成果表 分页
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdClueEventMapper.xml
@@ -49,12 +49,16 @@
        <result column="update_time" property="updateTime"/>
        <result column="status" property="status"/>
        <result column="is_deleted" property="isDeleted"/>
        <result column="geojson" property="geojson"/>
        <result column="attachment_type" property="attachmentType"/>
    </resultMap>
    <resultMap id="gdClueEventListVoResultMap" type="org.sxkj.gd.workorder.vo.GdClueEventListVO">
        <result column="id" property="id"/>
        <result column="event_image_url" property="eventImageUrl"/>
        <result column="create_time" property="createTime"/>
        <result column="geojson" property="geojson"/>
        <result column="attachment_type" property="attachmentType"/>
    </resultMap>
    <resultMap id="gdClueEventCountVoResultMap" type="org.sxkj.gd.workorder.vo.GdClueEventCountVO">
@@ -96,6 +100,8 @@
    <select id="selectGdClueEventSimpleList" resultMap="gdClueEventListVoResultMap">
        select ce.id as id,
        tr.result_url as event_image_url,
        tr.geojson as geojson,
        tr.attachment_type,
        ce.create_time as create_time
        from ja_gd_clue_event ce
        left join ja_gd_task_result tr on tr.id::VARCHAR = ce.result_id::VARCHAR and tr.is_deleted = 0
@@ -119,7 +125,9 @@
        concat(ce.longitude, ',', ce.latitude) as event_location,
        ce.event_num as event_num,
        tr.shoot_time as shoot_time,
        tr.result_url as event_image_url
        tr.result_url as event_image_url,
        tr.geojson as geojson,
        tr.attachment_type
        from ja_gd_clue_event ce
        left join blade_user bu on bu.id::VARCHAR = ce.dispose_user::VARCHAR and bu.is_deleted = 0
        left join blade_dept bd on bd.id::VARCHAR = ce.dispose_dept::VARCHAR and bd.is_deleted = 0
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml
@@ -65,7 +65,13 @@
                and pt.patrol_task_name like concat('%',#{param2.patrolTaskName},'%')
            </if>
            <if test="param2.patrolTaskType != null and param2.patrolTaskType != ''">
                and pt.patrol_task_type like concat('%',#{param2.patrolTaskType},'%')
                /* 将逗号分隔的字符串转换为带引号的格式,如 "road,road1" 转为 "\"road\",\"road1\"" */
                and pt.patrol_task_type like concat('%',
                (
                select string_agg(concat('"', trim(arr_val), '"'), ',')
                from unnest(string_to_array(#{param2.patrolTaskType}, ',')) as arr_val
                ),
                '%')
            </if>
            <if test="param2.taskStatus != null and param2.taskStatus != ''">
                /* 报错信息中出现了这个参数,务必加强转 */
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.java
@@ -42,7 +42,16 @@
     */
    List<GdTaskResultVO> selectGdTaskResultPage(IPage page, GdTaskResultVO gdTaskResult);
    List<GdTaskResultVO> selectGdTaskResultListByPatrolTaskId(@Param("patrolTaskId") Long patrolTaskId);
    /**
     * 根据巡查任务ID查询成果列表
     *
     * @param patrolTaskId    巡查任务ID
     * @param attachmentTypes 附件类型列表(可选,为null或空时查询全部)
     * @return 成果列表
     */
    List<GdTaskResultVO> selectGdTaskResultListByPatrolTaskId(
            @Param("patrolTaskId") Long patrolTaskId,
            @Param("attachmentTypes") List<Integer> attachmentTypes);
    /**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml
@@ -75,6 +75,9 @@
        <if test="gdTaskResult.createUser != null">
            AND tr.create_user = #{gdTaskResult.createUser}
        </if>
        <if test="gdTaskResult.attachmentType != null">
            AND tr.attachment_type = #{gdTaskResult.attachmentType}
        </if>
        ORDER BY tr.create_time DESC
    </select>
@@ -101,6 +104,12 @@
        WHERE
            tr.is_deleted = 0
          AND tr.patrol_task_id = #{patrolTaskId}
          <if test="attachmentTypes != null and attachmentTypes.size() > 0">
          AND tr.attachment_type IN
          <foreach collection="attachmentTypes" item="type" open="(" separator="," close=")">
              #{type}
          </foreach>
          </if>
    </select>
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml
@@ -115,7 +115,13 @@
                and wo.work_order_name like concat('%',#{param2.workOrderName},'%')
            </if>
            <if test="param2.workOrderType != null and param2.workOrderType != ''">
                 and wo.work_order_type like concat('%',#{param2.workOrderType},'%')
                /* 将逗号分隔的字符串转换为带引号的格式,如 "road,road1" 转为 "\"road\",\"road1\"" */
                and wo.work_order_type like concat('%',
                (
                select string_agg(concat('"', trim(arr_val), '"'), ',')
                from unnest(string_to_array(#{param2.workOrderType}, ',')) as arr_val
                ),
                '%')
            </if>
            <if test="param2.createUser != null ">
                /* 修改点2:过滤条件也进行类型对齐 */
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java
@@ -43,7 +43,14 @@
     */
    IPage<GdTaskResultVO> selectGdTaskResultPage(IPage<GdTaskResultVO> page, GdTaskResultVO gdTaskResult);
    List<GdTaskResultVO> listByPatrolTaskId(Long patrolTaskId);
    /**
     * 根据巡查任务ID查询成果列表
     *
     * @param patrolTaskId    巡查任务ID
     * @param attachmentTypes 附件类型列表(可选,为null或空时查询全部)
     * @return 成果列表
     */
    List<GdTaskResultVO> listByPatrolTaskId(Long patrolTaskId, List<Integer> attachmentTypes);
    /**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -256,7 +256,13 @@
        // 6. 判断是否审核成功,如果是,需要判断是否整个订单的子任务都审核成功了,除了被撤回和验收拒绝的
        if (auditStatus == 4) {
            // 将审核后的任务信息推送到星图
            pushXingtuFlyTask(auditParam.getId());
            R pushResult = pushXingtuFlyTask(auditParam.getId());
            // 检查推送结果,如果失败则抛出异常回滚事务
            if (pushResult != null && !pushResult.isSuccess()) {
                String errorMsg = pushResult.getMsg();
                log.error("推送星图飞行任务失败: {}", errorMsg);
                throw new RuntimeException(errorMsg + ",请更改执行时间重新提交。");
            }
            // 查询同一个工单下的所有子任务
            List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery()
                .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId()));
@@ -603,7 +609,7 @@
        attach.setOriginalName(bladeFile.getOriginalName());
        attach.setAttachSize(reportFile.length());
        attach.setExtension(FileUtil.getFileExtension(reportFile.getName()));
        attach.setResultType(JSON.toJSONString(resultType));
        attach.setResultType(resultType);
        attach.setPatrolTaskId(String.valueOf(taskEntity != null ? taskEntity.getId() : null));
        Long createUser = taskEntity != null ? taskEntity.getCreateUser() : null;
        Long updateUser = taskEntity != null ? taskEntity.getUpdateUser() : null;
@@ -740,7 +746,7 @@
        // 1. 更新当前任务状态
        boolean updateResult = updateById(auditParam);
        if (!updateResult) {
            log.warn("更新任务失败,任务ID: {}");
            log.warn("更新任务失败,任务ID: {}", auditParam.getId());
            return false;
        }
@@ -748,8 +754,11 @@
        GdPatrolTaskEntity patrolTaskEntity = Optional.ofNullable(getById(auditParam.getId()))
            .orElseThrow(() -> new RuntimeException("任务不存在,任务ID: " + auditParam.getId()));
        // 3. 保存巡查工单流转
        saveWorkOrderFlow(patrolTaskEntity.getWorkOrderId(), PatrolTaskStatusEnum.PENDING_ACCEPTANCE, null, null);
        // 3. 保存巡查工单流转(使用传入的实际状态)
        PatrolTaskStatusEnum statusEnum = PatrolTaskStatusEnum.getByValue(auditParam.getTaskStatus());
        if (statusEnum != null) {
            saveWorkOrderFlow(patrolTaskEntity.getId(), statusEnum, null, patrolTaskEntity.getAreaCode());
        }
        // 4. 查询同一个工单下的所有子任务
        List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery()
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java
@@ -85,9 +85,18 @@
        return page.setRecords(baseMapper.selectGdTaskResultPage(page, gdTaskResult));
    }
    /**
     * 根据巡查任务ID查询成果列表
     *
     * @param patrolTaskId    巡查任务ID
     * @param attachmentTypes 附件类型列表(可选,为null或空时查询全部)
     * @return 成果列表
     */
    @Override
    public List<GdTaskResultVO> listByPatrolTaskId(Long patrolTaskId) {
        List<GdTaskResultVO> gdTaskResultVOS = baseMapper.selectGdTaskResultListByPatrolTaskId(patrolTaskId);
    public List<GdTaskResultVO> listByPatrolTaskId(Long patrolTaskId, List<Integer> attachmentTypes) {
        // 步骤1:查询成果列表
        List<GdTaskResultVO> gdTaskResultVOS = baseMapper.selectGdTaskResultListByPatrolTaskId(patrolTaskId, attachmentTypes);
        // 步骤2:处理URL转义字符
        for (GdTaskResultVO gdTaskResultVO : gdTaskResultVOS) {
            gdTaskResultVO.setResultUrl(unescapeUrl(gdTaskResultVO.getResultUrl()));
        }
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventListVO.java
@@ -43,4 +43,10 @@
    @ApiModelProperty(value = "事件生成时间")
    private Date createTime;
    @ApiModelProperty(value = "事件geojson")
    private String geojson;
    @ApiModelProperty(value = "事件附件类型")
    private Integer attachmentType;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventVO.java
@@ -168,4 +168,11 @@
    @ApiModelProperty(value = "删除标志(0存在 1删除)")
    private Integer isDeleted;
    @ApiModelProperty(value = "事件geojson")
    private String geojson;
    @ApiModelProperty(value = "事件附件类型")
    private Integer attachmentType;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/xingtu/JianXingtuApiService.java
@@ -139,11 +139,21 @@
            if (response.getStatusCode().is2xxSuccessful()) {
                R responseBody = response.getBody();
                if (responseBody != null) {
                    // 检查接口内部返回的success状态
                    if (!responseBody.isSuccess()) {
                        // 提取错误信息,优先使用msg字段
                        String errorMsg = responseBody.getMsg();
                        if (StringUtil.isBlank(errorMsg)) {
                            errorMsg = "接口调用失败";
                        }
                        log.warn("外部接口返回失败: {}", errorMsg);
                        return R.fail(errorMsg);
                    }
                    return responseBody;
                }
                return R.fail("接口返回为空");
            }
            return R.fail("请求外部接口失败");
            return R.fail("请求外部接口失败,HTTP状态码: " + response.getStatusCode());
        } catch (Exception e) {
            log.error("请求外部接口异常: ", e);
            return R.fail("请求外部接口异常: " + e.getMessage());
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/DeptServiceImpl.java
@@ -185,9 +185,9 @@
            if (existingDept != null) {
                return updateById(dept);
            }
            return save(dept);
        }
        return false;
        return save(dept);
    }
    @Override
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().toString());
            attach.setResultType(null);
        }
        // 设置类型-三维白膜
        if (odmTaskInfo.getType() == OdmTypeEnum.ALB.getType().intValue()) {
            attach.setResultType(AttachResultTypeEnum.ALB.getType().toString());
            attach.setResultType(null);
        }
        // 设置区域编号
        attach.setAreaCode(odmTaskInfo.getAreaCode());
@@ -979,7 +979,7 @@
                attach.setPatrolTaskId(odmTaskInfo.getWaylineJobId());
            }
            // 设置类型
            attach.setResultType(AttachResultTypeEnum.ORT.getType().toString());
            attach.setResultType(null);
            // 设置设备编号
            if (!Strings.isBlank(odmTaskInfo.getDeviceSn())) {
                attach.setDeviceSn(odmTaskInfo.getDeviceSn());
@@ -2610,7 +2610,7 @@
        // 设置类型-三维白膜
        // 测试用,临时用,用后需要手动数据库修改
        attach.setResultType(AttachResultTypeEnum.ALB.getType().toString());
        attach.setResultType(null);
        log.info("发起远程调用保存三维白膜/倾斜附件信息,tif 路径:{}", path);
        Boolean isSaveAttach = attachClient.saveAttachInfo(attach);