吉安感知网项目-后端
linwei
2026-01-09 33ab5566da759239cdde4e80464ee293e4154fc3
数据驾驶舱
11 files modified
3 files added
444 ■■■■ changed files
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/controller/CockpitController.java 114 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/vo/AlarmStatisticsVO.java 61 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/vo/DeviceStatisticsVO.java 28 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/controller/FwEffectEvalController.java 46 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/dto/FwEffectEvalDTO.java 92 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/entity/FwDeviceConfigEntity.java 2 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/dto/FwDeviceDTO.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/controller/FwDroneFlightRecordController.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/dto/FwDroneAlarmRecordDTO.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/entity/FwDroneAlarmRecordEntity.java 7 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/entity/FwDroneFlightRecordEntity.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/excel/FwDroneFlightRecordExcel.java 55 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneAlarmRecordMapper.xml 3 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneFlightRecordMapper.xml 16 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/controller/CockpitController.java
New file
@@ -0,0 +1,114 @@
package org.sxkj.fw.cockpit.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springframework.web.bind.annotation.*;
import org.sxkj.fw.cockpit.vo.AlarmStatisticsVO;
import org.sxkj.fw.cockpit.vo.DeviceStatisticsVO;
import org.sxkj.fw.detection.dto.FwEffectEvalDTO;
import org.sxkj.fw.detection.entity.FwEffectEvalEntity;
import org.sxkj.fw.detection.service.IFwEffectEvalService;
import org.sxkj.fw.device.dto.FwDeviceDTO;
import org.sxkj.fw.device.entity.FwDeviceEntity;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.fw.device.vo.FwDeviceVO;
import org.sxkj.fw.device.wrapper.FwDeviceWrapper;
import org.sxkj.fw.record.dto.FwDroneAlarmRecordDTO;
import org.sxkj.fw.record.service.IFwDroneAlarmRecordService;
import org.sxkj.fw.record.vo.FwDroneAlarmRecordVO;
import javax.validation.Valid;
import java.util.Objects;
/**
 * 数据驾驶舱
 *
 * @author lw
 * @since 2026-01-08
 */
@RestController
@AllArgsConstructor
@RequestMapping("cockpit/dataCockpit")
@Api(value = "驾驶舱", tags = "数据驾驶舱")
public class CockpitController {
    private final IFwDroneAlarmRecordService fwDroneAlarmRecordService;
    private final IFwDeviceService fwDeviceService;
    private final IFwEffectEvalService fwEffectEvalService;
    /**
     * 历史告警、实时告警
     */
    @GetMapping("/alarmLog")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "历史告警/实时告警", notes = "传入fwDroneAlarmRecord")
    public R<IPage<FwDroneAlarmRecordVO>> page(FwDroneAlarmRecordDTO fwDroneAlarmRecord, Query query) {
        IPage<FwDroneAlarmRecordVO> pages = fwDroneAlarmRecordService.selectFwDroneAlarmRecordPage(Condition.getPage(query), fwDroneAlarmRecord);
        return R.data(pages);
    }
    /**
     * 设备查询 自定义分页
     */
    @GetMapping("/deviceSearch")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "设备查询", notes = "传入fwDevice")
    public R<IPage<FwDeviceVO>> page(FwDeviceDTO fwDevice, Query query) {
        IPage<FwDeviceEntity> pages = fwDeviceService.selectFwDevicePage(Condition.getPage(query), fwDevice);
        return R.data(FwDeviceWrapper.build().pageVO(pages));
    }
    /**
     * 设备统计接口
     */
    @GetMapping("/deviceStatistics")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "设备统计", notes = "返回设备统计、无线电、光电、雷达等数据")
    public R<DeviceStatisticsVO> getDeviceStatistics() {
        DeviceStatisticsVO statistics = new DeviceStatisticsVO();
        // 假设从服务层获取统计数据,这里仅示例填充数据
        statistics.setDetectCount(3);
        statistics.setCountermeasuresCount(4);
        return R.data(statistics);
    }
    /**
     * 告警记录统计接口
     */
    @GetMapping("/alarmStatistics")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "告警记录统计", notes = "返回实时告警、设备告警、历史告警数量")
    public R<AlarmStatisticsVO> getAlarmStatistics() {
        AlarmStatisticsVO statistics = new AlarmStatisticsVO();
        // 假设从服务层获取统计数据,这里仅示例填充数据
        statistics.setDeviceCount(5);
        statistics.setRadioCount(1);
        statistics.setOpticalCount(2);
        statistics.setRadarCount(2);
        statistics.setRealTimeAlarmCount(5);
        statistics.setDeviceAlarmCount(5);
        statistics.setHistoryAlarmCount(5);
        return R.data(statistics);
    }
    /**
     * 信号干扰,诱导驱离
     */
    @PostMapping("/interferenceAndExpulsion")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "信号干扰,诱导驱离", notes = "传入fwEffectEval")
    public R submit(@Valid @RequestBody FwEffectEvalDTO fwEffectEval) {
        FwEffectEvalEntity fwEffectEvalEntity = Objects.requireNonNull(BeanUtil.copy(fwEffectEval, FwEffectEvalEntity.class));
        return R.status(fwEffectEvalService.saveOrUpdate(fwEffectEvalEntity));
    }
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/vo/AlarmStatisticsVO.java
New file
@@ -0,0 +1,61 @@
package org.sxkj.fw.cockpit.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 告警记录统计视图对象
 *
 * @author lw
 * @since 2026-01-09
 */
@Data
public class AlarmStatisticsVO {
    /**
     * 告警总数
     */
    @ApiModelProperty(value = "告警总数")
    private Integer realTimeAlarmCount;
    /**
     * 设备告警数量
     */
    @ApiModelProperty(value = "设备告警数量")
    private Integer deviceAlarmCount;
    /**
     * 历史告警数量
     */
    @ApiModelProperty(value = "历史告警数量")
    private Integer historyAlarmCount;
    /**
     * 设备总数
     */
    @ApiModelProperty(value = "设备总数")
    private Integer deviceCount;
    /**
     * 无线电数量
     */
    @ApiModelProperty(value = "无线电数量")
    private Integer radioCount;
    /**
     * 光电数量
     */
    @ApiModelProperty(value = "光电数量")
    private Integer opticalCount;
    /**
     * 雷达数量
     */
    @ApiModelProperty(value = "雷达数量")
    private Integer radarCount;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/vo/DeviceStatisticsVO.java
New file
@@ -0,0 +1,28 @@
package org.sxkj.fw.cockpit.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 设备统计视图对象
 *
 * @author lw
 * @since 2026-01-09
 */
@Data
public class DeviceStatisticsVO {
    /**
     * 侦测设备数量
     */
    @ApiModelProperty(value = "侦测设备数量")
    private Integer detectCount;
    /**
     * 反制设备数量
     */
    @ApiModelProperty(value = "反制设备数量")
    private Integer countermeasuresCount;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/controller/FwEffectEvalController.java
@@ -27,10 +27,12 @@
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.sxkj.fw.detection.dto.FwEffectEvalDTO;
import org.sxkj.fw.detection.entity.FwEffectEvalEntity;
import org.sxkj.fw.detection.vo.FwEffectEvalVO;
import org.sxkj.fw.detection.excel.FwEffectEvalExcel;
@@ -43,6 +45,7 @@
import springfox.documentation.annotations.ApiIgnore;
import java.util.Map;
import java.util.List;
import java.util.Objects;
import javax.servlet.http.HttpServletResponse;
/**
@@ -72,13 +75,13 @@
    /**
     * 反制效果评估表 分页
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入fwEffectEval")
    public R<IPage<FwEffectEvalVO>> list(@ApiIgnore @RequestParam Map<String, Object> fwEffectEval, Query query) {
        IPage<FwEffectEvalEntity> pages = fwEffectEvalService.page(Condition.getPage(query), Condition.getQueryWrapper(fwEffectEval, FwEffectEvalEntity.class));
        return R.data(FwEffectEvalWrapper.build().pageVO(pages));
    }
    // @GetMapping("/list")
    // @ApiOperationSupport(order = 2)
    // @ApiOperation(value = "分页", notes = "传入fwEffectEval")
    // public R<IPage<FwEffectEvalVO>> list(@ApiIgnore @RequestParam Map<String, Object> fwEffectEval, Query query) {
    //     IPage<FwEffectEvalEntity> pages = fwEffectEvalService.page(Condition.getPage(query), Condition.getQueryWrapper(fwEffectEval, FwEffectEvalEntity.class));
    //     return R.data(FwEffectEvalWrapper.build().pageVO(pages));
    // }
    /**
     * 反制效果评估表 自定义分页
@@ -94,22 +97,22 @@
    /**
     * 反制效果评估表 新增
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入fwEffectEval")
    public R save(@Valid @RequestBody FwEffectEvalEntity fwEffectEval) {
        return R.status(fwEffectEvalService.save(fwEffectEval));
    }
    // @PostMapping("/save")
    // @ApiOperationSupport(order = 4)
    // @ApiOperation(value = "新增", notes = "传入fwEffectEval")
    // public R save(@Valid @RequestBody FwEffectEvalEntity fwEffectEval) {
    //     return R.status(fwEffectEvalService.save(fwEffectEval));
    // }
    /**
     * 反制效果评估表 修改
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改", notes = "传入fwEffectEval")
    public R update(@Valid @RequestBody FwEffectEvalEntity fwEffectEval) {
        return R.status(fwEffectEvalService.updateById(fwEffectEval));
    }
    // @PostMapping("/update")
    // @ApiOperationSupport(order = 5)
    // @ApiOperation(value = "修改", notes = "传入fwEffectEval")
    // public R update(@Valid @RequestBody FwEffectEvalEntity fwEffectEval) {
    //     return R.status(fwEffectEvalService.updateById(fwEffectEval));
    // }
    /**
     * 反制效果评估表 新增或修改
@@ -117,8 +120,9 @@
    @PostMapping("/submit")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增或修改", notes = "传入fwEffectEval")
    public R submit(@Valid @RequestBody FwEffectEvalEntity fwEffectEval) {
        return R.status(fwEffectEvalService.saveOrUpdate(fwEffectEval));
    public R submit(@Valid @RequestBody FwEffectEvalDTO fwEffectEval) {
        FwEffectEvalEntity fwEffectEvalEntity = Objects.requireNonNull(BeanUtil.copy(fwEffectEval, FwEffectEvalEntity.class));
        return R.status(fwEffectEvalService.saveOrUpdate(fwEffectEvalEntity));
    }
    /**
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/dto/FwEffectEvalDTO.java
@@ -16,9 +16,14 @@
 */
package org.sxkj.fw.detection.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import org.sxkj.fw.detection.entity.FwEffectEvalEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
 * 反制效果评估表 数据传输对象实体类
@@ -27,8 +32,91 @@
 * @since 2026-01-08
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class FwEffectEvalDTO extends FwEffectEvalEntity {
public class FwEffectEvalDTO {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键id")
    private Long id;
    /**
     * 告警记录ID(ja_fw_drone_alarm_record.id)
     */
    @ApiModelProperty(value = "告警记录ID(ja_fw_drone_alarm_record.id)")
    private Long alarmRecordId;
    /**
     * 反制设备ID(ja_fw_device.id)
     */
    @ApiModelProperty(value = "反制设备ID(ja_fw_device.id)")
    private Long deviceId;
    /**
     * 反制设备编码(快照)
     */
    @ApiModelProperty(value = "反制设备编码(快照)")
    private String deviceCode;
    /**
     * 反制设备名称(快照)
     */
    @ApiModelProperty(value = "反制设备名称(快照)")
    private String deviceName;
    /**
     * 反制设备型号(快照)
     */
    @ApiModelProperty(value = "反制设备型号(快照)")
    private String deviceModel;
    /**
     * 反制设备类型(快照)
     */
    @ApiModelProperty(value = "反制设备类型(快照)")
    private String deviceType;
    /**
     * 无人机名称
     */
    @ApiModelProperty(value = "无人机名称")
    private String droneName;
    /**
     * 无人机类型
     */
    @ApiModelProperty(value = "无人机类型")
    private String droneType;
    /**
     * 无人机设备编码
     */
    @ApiModelProperty(value = "无人机设备编码")
    private String droneDeviceCode;
    /**
     * 发现时间
     */
    @ApiModelProperty(value = "发现时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date findTime;
    /**
     * 反制效果(success/fail)
     */
    @ApiModelProperty(value = "反制效果(success/fail)")
    private String counterEffect;
    /**
     * 部署经度(冗余)
     */
    @ApiModelProperty(value = "部署经度(冗余)")
    private Double deployLongitude;
    /**
     * 部署纬度(冗余)
     */
    @ApiModelProperty(value = "部署纬度(冗余)")
    private Double deployLatitude;
    /**
     * 覆盖范围(米)
     */
    @ApiModelProperty(value = "覆盖范围(米)")
    private Integer coverRadiusM;
    /**
     * 工作模式(机动/固定)
     */
    @ApiModelProperty(value = "工作模式(机动/固定)")
    private String workMode;
    /**
     * 区域编码
     */
    @ApiModelProperty(value = "区域编码")
    private String areaCode;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/entity/FwDeviceConfigEntity.java
@@ -16,6 +16,8 @@
 */
package org.sxkj.fw.detection.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/dto/FwDeviceDTO.java
@@ -91,4 +91,10 @@
    @ApiModelProperty(value = "联系电话")
    private String contactPhone;
    /**
     * 设备状态,多个状态用逗号隔
     */
    @ApiModelProperty(value = "设备状态,多个状态用逗号隔开")
    private String deviceStatus;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/controller/FwDroneFlightRecordController.java
@@ -16,6 +16,9 @@
 */
package org.sxkj.fw.record.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -36,6 +39,7 @@
import org.springframework.web.bind.annotation.*;
import org.sxkj.fw.record.dto.FwDroneFlightRecordDTO;
import org.sxkj.fw.record.entity.FwDroneFlightRecordEntity;
import org.sxkj.fw.record.excel.FwDroneAlarmRecordExcel;
import org.sxkj.fw.record.excel.FwDroneFlightRecordExcel;
import org.sxkj.fw.record.service.IFwDroneFlightRecordService;
import org.sxkj.fw.record.vo.FwDroneFlightRecordVO;
@@ -44,6 +48,8 @@
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/dto/FwDroneAlarmRecordDTO.java
@@ -61,7 +61,7 @@
    /**
     * 告警类型:实时告警/历史告警
     */
    @ApiModelProperty(value = "告警类型:实时告警/历史告警")
    @ApiModelProperty(value = "告警类型:1.实时告警/2.历史告警")
    private String alarmType;
    /**
     * 告警时间
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/entity/FwDroneAlarmRecordEntity.java
@@ -158,4 +158,11 @@
    @ApiModelProperty(value = "设备类型(察打一体/便捷侦测箱/反制枪)")
    private String deviceType;
    /**
     * 区域名称
     */
    @TableField("area_name")
    @ApiModelProperty(value = "区域名称")
    private String areaName;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/entity/FwDroneFlightRecordEntity.java
@@ -86,4 +86,10 @@
    @ApiModelProperty(value = "区域编码")
    private String areaCode;
    /**
     * 区域名称
     */
    @TableField("area_name")
    @ApiModelProperty(value = "区域名称")
    private String areaName;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/excel/FwDroneFlightRecordExcel.java
@@ -42,53 +42,42 @@
    private static final long serialVersionUID = 1L;
    /**
     * 反无设备ID(关联ja_fw_device.id)
     */
    @ColumnWidth(20)
    @ExcelProperty("反无设备ID(关联ja_fw_device.id)")
    private Long deviceId;
    /**
     * 无人机名称
     */
    @ColumnWidth(20)
    @ExcelProperty("无人机名称")
    private String droneName;
    /**
     * 序列号
     */
    @ColumnWidth(20)
    @ExcelProperty("序列号")
    private String serialNo;
    /**
     * 首次告警时间
     */
    @ColumnWidth(20)
    @ExcelProperty("首次告警时间")
    private Date alarmTime;
    /**
     * 触发原因/类型
     */
    @ColumnWidth(20)
    @ExcelProperty("触发原因/类型")
    private String triggerType;
    /**
     * 停留时长(HH:MM:SS)
     */
    @ColumnWidth(20)
    @ExcelProperty("停留时长(HH:MM:SS)")
    private LocalTime stayDuration;
    /**
     * 区域编码
     */
    @ExcelProperty("停留时长")
    private String stayDuration;
    @ColumnWidth(20)
    @ExcelProperty("区域编码")
    private String areaCode;
    /**
     * 删除标志(0存在 1删除)
     */
    @ExcelProperty("区域名称")
    private String areaName;
    @ColumnWidth(20)
    @ExcelProperty("删除标志(0存在 1删除)")
    private Byte isDeleted;
    @ExcelProperty("经度")
    private Double longitude;
    @ColumnWidth(20)
    @ExcelProperty("纬度")
    private Double latitude;
    @ColumnWidth(20)
    @ExcelProperty("时间")
    private Date pointTime;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneAlarmRecordMapper.xml
@@ -36,7 +36,6 @@
    <select id="selectFwDroneAlarmRecordPage" resultType="org.sxkj.fw.record.vo.FwDroneAlarmRecordVO">
        select dar.*,d.device_name,d.device_model from
        ja_fw_drone_alarm_record dar
        left join ja_fw_area_divide ad on dar.area_divide_id = ad.id
        left join ja_fw_device d on dar.device_id = d.id
        <where>
            dar.is_deleted = 0
@@ -98,7 +97,7 @@
                and dar.device_type = #{param2.deviceType}
            </if>
            <if test="param2.areaName != null and param2.areaName != ''">
                and ad.area_name like CONCAT('%', #{param2.areaName}, '%')
                and dar.area_name like CONCAT('%', #{param2.areaName}, '%')
            </if>
        </where>
    </select>
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneFlightRecordMapper.xml
@@ -24,7 +24,6 @@
    <select id="selectFwDroneFlightRecordPage" resultMap="fwDroneFlightRecordResultMap">
        select dfr.* from ja_fw_drone_flight_record dfr
        left join ja_fw_area_divide ad on dfr.area_divide_id = ad.id
        <where>
            dfr.is_deleted = 0
            <if test="param2.deviceId != null and param2.deviceId != ''">
@@ -55,14 +54,25 @@
                and dfr.device_type = #{param2.deviceType}
            </if>
            <if test="param2.areaName != null and param2.areaName != ''">
                and ad.area_name like CONCAT('%', #{param2.areaName}, '%')
                and dfr.area_name like CONCAT('%', #{param2.areaName}, '%')
            </if>
        </where>
    </select>
    <select id="exportFwDroneFlightRecord" resultType="org.sxkj.fw.record.excel.FwDroneFlightRecordExcel">
        SELECT * FROM ja_fw_drone_flight_record ${ew.customSqlSegment}
        SELECT dfr.drone_name,
               dfr.serial_no,
               dfr.alarm_time,
               dfr.area_name,
               dfr.trigger_type,
               dfr.stay_duration,
               dfrd.longitude,
               dfrd.latitude,
               dfrd.point_time
        FROM ja_fw_drone_flight_record dfr
                 left join ja_fw_drone_flight_record_detail dfrd on dfr.id = dfrd.flight_record_id
        where dfr.is_deleted = 0
    </select>
</mapper>