zhaowenyu
2026-02-04 fc7ee73b5f804116ada59048fdf6fb9265856a3f
Merge remote-tracking branch 'origin/dev' into dev
9 files modified
144 ■■■■■ changed files
ard-admin/src/main/java/com/ard/web/controller/inspection/BigFileUploadController.java 3 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java 7 ●●●●● patch | view | raw | blame | history
ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java 3 ●●●●● patch | view | raw | blame | history
ard-route/src/main/java/com/ard/route/domain/route/ArdRouteMission.java 10 ●●●●● patch | view | raw | blame | history
ard-route/src/main/java/com/ard/route/domain/route/ArdRoutePoint.java 3 ●●●●● patch | view | raw | blame | history
ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java 19 ●●●●● patch | view | raw | blame | history
ard-route/src/main/java/com/ard/route/service/impl/ArdRouteMissionServiceImpl.java 3 ●●●●● patch | view | raw | blame | history
ard-route/src/main/resources/mapper/ArdRouteMissionMapper.xml 17 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/work/service/control/UavControlService.java 79 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/controller/inspection/BigFileUploadController.java
@@ -1,5 +1,6 @@
package com.ard.web.controller.inspection;
import com.ard.common.core.controller.BaseController;
import io.lettuce.core.dynamic.annotation.Value;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -8,7 +9,7 @@
@Api(tags = "大文件上传")
@RestController
@RequestMapping("/inspection/bigfile")
public class BigFileUploadController {
public class BigFileUploadController extends BaseController {
    /** 若依文件上传根目录(从配置文件读取) */
    //@Value("${ruoyi.profile}")
ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java
@@ -35,8 +35,10 @@
    public AjaxResult handleControlRequest(
            @RequestParam String boxSn,
            @RequestParam String type,
            @RequestParam boolean approve) {
        return AjaxResult.success(uavControlService.handleControlResponse(boxSn, approve, type));
            @RequestParam boolean approve,
            @RequestParam Long requesterId
    ) {
        return AjaxResult.success(uavControlService.handleControlResponse(boxSn, approve, type, requesterId));
    }
    /**
@@ -56,6 +58,7 @@
    public AjaxResult getCurrentController(@RequestParam String boxSn, @RequestParam String type) {
        return AjaxResult.success(uavControlService.getCurrentController(boxSn, type));
    }
    /**
     * 获取全部类型当前控制者
     */
ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
@@ -33,8 +33,7 @@
     * 航线类型
     * 1:逐点巡检
     * 2:沿线巡检
     * 3:任务航线
     * 4:巡检航线
     * 3:巡检航线
     * */
    private String type;
ard-route/src/main/java/com/ard/route/domain/route/ArdRouteMission.java
@@ -39,7 +39,17 @@
    /** 执行时间 */
    private Date executeTime;
    /**
     * 任务类型
     * 1:报警任务
     * 2:巡检任务
     * */
    private String taskType;
    /** 航线任务航点列表 */
    private List<ArdRoutePoint> missionDetailList;
    /** 任务描述 */
    private String taskDescription;
}
ard-route/src/main/java/com/ard/route/domain/route/ArdRoutePoint.java
@@ -1,6 +1,5 @@
package com.ard.route.domain.route;
import com.ard.common.core.domain.BaseEntity;
import lombok.Data;
/**
@@ -11,8 +10,6 @@
 */
@Data
public class ArdRoutePoint{
    private static final long serialVersionUID = 1L;
    /** 航线任务ID */
    private String missionId;
ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
@@ -5,6 +5,7 @@
import com.ard.common.exception.ControlException;
import com.ard.common.utils.DateUtils;
import com.ard.common.utils.SecurityUtils;
import com.ard.common.utils.file.FileUtils;
import com.ard.common.utils.uuid.IdUtils;
import com.ard.data.noflyzone.domain.ArdNoFlyZone;
@@ -36,10 +37,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import static com.ard.common.utils.SecurityUtils.getUsername;
import static com.ard.route.enums.kml.DroneEnumValueEnums.M350_RTK;
import static com.ard.route.util.InitializationUtils.divided_23;
import static com.ard.route.util.ToolUtils.*;
@@ -165,6 +163,7 @@
     */
    private void checkRouteMissionStatus(ArdRouteInfo ardRouteInfo,String type){
        ArdRouteMission mission = ardRouteMissionMapper.selectArdRouteMissionById(ardRouteInfo.getMissionId());
        if (mission != null){
        switch(type){
            case "1":
                validateForCreate(mission);
@@ -173,10 +172,11 @@
                bindRoute(mission, ardRouteInfo);
                break;
            case "3":
                executeMission(mission);
                    executeMission(mission,ardRouteInfo);
                break;
            default:
                throw new RuntimeException("不支持的操作类型!!!");
            }
        }
    }
@@ -187,17 +187,18 @@
    }
    private void bindRoute(ArdRouteMission mission, ArdRouteInfo routeInfo) {
        if (!"0".equals(mission.getRouteId())) {
        if (mission.getRouteId() != null) {
            throw new RuntimeException("航线任务下已绑定航线,不可创建新航线信息!!!");
        }
        mission.setRouteId(routeInfo.getId());
        ardRouteMissionMapper.updateArdRouteMission(mission);
    }
    private void executeMission(ArdRouteMission mission) {
    private void executeMission(ArdRouteMission mission,ArdRouteInfo ardRouteInfo) {
        if ("0".equals(mission.getExecuteStatus())) {
            mission.setRouteId(ardRouteInfo.getId());
            mission.setExecuteStatus("1");
            mission.setExecuteBy(getUsername());
            mission.setExecuteBy(SecurityUtils.getUsername());
            mission.setExecuteTime(DateUtils.getNowDate());
            mission.setUpdateTime(DateUtils.getNowDate());
            ardRouteMissionMapper.updateArdRouteMission(mission);
@@ -472,9 +473,11 @@
    @Override
    public Boolean routeBegins(String id,String boxSn) {
        ArdRouteInfo route = ardRouteInfoMapper.selectArdRouteInfoById(id);
        if (null != route){
        // 判断是否循环航线
        if (null != route && "0".equals(route.getIsLoop())){
            if ("0".equals(route.getIsLoop())){
            deleteArdRouteInfoById(id);
            }
            checkRouteMissionStatus(route,"3");
        }
        WayLineBeginDTO wayLineBeginDTO = new WayLineBeginDTO(boxSn);
ard-route/src/main/java/com/ard/route/service/impl/ArdRouteMissionServiceImpl.java
@@ -2,6 +2,7 @@
import java.util.List;
import com.ard.common.utils.DateUtils;
import com.ard.common.utils.SecurityUtils;
import com.ard.common.utils.uuid.IdUtils;
import com.ard.route.domain.route.ArdRouteMission;
import com.ard.route.domain.route.ArdRoutePoint;
@@ -138,7 +139,7 @@
        ArdRouteMission ardRouteMission = new ArdRouteMission();
        ardRouteMission.setId(id);
        ardRouteMission.setExecuteStatus(status);
        ardRouteMission.setExecuteBy(getUsername());
        ardRouteMission.setExecuteBy(SecurityUtils.getUsername());
        ardRouteMission.setExecuteTime(DateUtils.getNowDate());
        ardRouteMission.setUpdateTime(DateUtils.getNowDate());
        return ardRouteMissionMapper.updateArdRouteMission(ardRouteMission);
ard-route/src/main/resources/mapper/ArdRouteMissionMapper.xml
@@ -15,6 +15,8 @@
        <result property="updateTime"    column="update_time"    />
        <result property="executeBy"    column="execute_by"    />
        <result property="executeTime"    column="execute_time"    />
        <result property="taskType"    column="task_type"    />
        <result property="taskDescription"    column="task_description"    />
    </resultMap>
    <sql id="selectArdRouteMissionVo">
@@ -27,7 +29,9 @@
               update_by,
               update_time,
               execute_by,
               execute_time
               execute_time,
               task_type,
               task_description
        from ard_route_mission
    </sql>
@@ -39,14 +43,15 @@
            <if test="executeStatus != null  and executeStatus != ''"> and execute_status = #{executeStatus}</if>
            <if test="executeBy != null  and executeBy != ''"> and execute_by = #{executeBy}</if>
            <if test="executeTime != null "> and execute_time = #{executeTime}</if>
            <if test="taskType != null  and taskType != ''"> and task_type = #{taskType}</if>
        </where>
        order by create_time asc
        order by create_time DESC
    </select>
    
    <select id="selectArdRouteMissionById" parameterType="String" resultMap="ArdRouteMissionResult">
        <include refid="selectArdRouteMissionVo"/>
        where id = #{id}
        order by create_time asc
        order by create_time DESC
    </select>
    <insert id="insertArdRouteMission" parameterType="ArdRouteMission">
@@ -62,6 +67,8 @@
            <if test="updateTime != null">update_time,</if>
            <if test="executeBy != null">execute_by,</if>
            <if test="executeTime != null">execute_time,</if>
            <if test="taskType != null">task_type,</if>
            <if test="taskDescription != null">task_description,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id},</if>
@@ -74,6 +81,8 @@
            <if test="updateTime != null">#{updateTime},</if>
            <if test="executeBy != null">#{executeBy},</if>
            <if test="executeTime != null">#{executeTime},</if>
            <if test="taskType != null">#{taskType},</if>
            <if test="taskDescription != null">#{taskDescription},</if>
         </trim>
    </insert>
@@ -89,6 +98,8 @@
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="executeBy != null">execute_by = #{executeBy},</if>
            <if test="executeTime != null">execute_time = #{executeTime},</if>
            <if test="taskType != null">task_type = #{taskType},</if>
            <if test="taskDescription != null">task_description = #{taskDescription},</if>
        </trim>
        where id = #{id}
    </update>
ard-work/src/main/java/com/ard/work/service/control/UavControlService.java
@@ -10,6 +10,7 @@
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -25,17 +26,26 @@
    @Resource
    private ISysUserService sysUserService;
    /** 当前飞行控制权限用户 */
    /**
     * 当前飞行控制权限用户
     */
    private final ConcurrentHashMap<String, Long> uavFlyControlMap = new ConcurrentHashMap<>();
    /** 当前载荷控制权限用户 */
    /**
     * 当前载荷控制权限用户
     */
    private final ConcurrentHashMap<String, Long> uavPayloadControlMap = new ConcurrentHashMap<>();
    /** 飞行控制请求 */
    private final ConcurrentHashMap<String, Long> flyControlRequests = new ConcurrentHashMap<>();
    /**
     * 飞行控制请求:boxSn -> 多个请求者
     */
    private final ConcurrentHashMap<String, Set<Long>> flyControlRequests = new ConcurrentHashMap<>();
    /** 载荷控制请求 */
    private final ConcurrentHashMap<String, Long> payloadControlRequests = new ConcurrentHashMap<>();
    /**
     * 载荷控制请求
     */
    private final ConcurrentHashMap<String, Set<Long>> payloadControlRequests = new ConcurrentHashMap<>();
    /**
     * 请求获取 UAV 控制权限
@@ -49,9 +59,13 @@
    /**
     * 处理单个控制类型的请求
     */
    /**
     * 处理单个控制类型的请求(支持多请求者)
     */
    private boolean requestSingleControl(String boxSn, UavControlType controlType, Long requester) {
        ConcurrentHashMap<String, Long> controlMap = getControlMap(controlType);
        ConcurrentHashMap<String, Long> requestMap = getRequestMap(controlType);
        ConcurrentHashMap<String, Set<Long>> requestMap = getRequestMap(controlType);
        Long controller = controlMap.get(boxSn);
@@ -76,49 +90,73 @@
            // 通知原控制者被抢占
            uavControlManager.sendControlTakeover(controller, requester, boxSn, controlType.getType());
            // 通知新控制者获得控制
            uavControlManager.sendControlApproval(requester, boxSn, controlType.getType(), requester);
            return true;
        }
        // 优先级相同或更低 → 申请流程
        requestMap.put(boxSn, requester);
        // ===== 以下是关键改动点 =====
        // 优先级相同或更低 → 加入请求集合(不覆盖)
        Set<Long> requesters = requestMap.computeIfAbsent(boxSn, k -> ConcurrentHashMap.newKeySet());
        requesters.add(requester);
        // 通知当前控制者:有新的请求者
        uavControlManager.sendControlRequest(controller, boxSn, controlType.getType(), requester);
        return false;
    }
    /**
     * 处理 UAV 控制请求的响应
     */
    public boolean handleControlResponse(String boxSn, boolean approve, String type) {
    public boolean handleControlResponse(String boxSn, boolean approve, String type, Long requester) {
        UavControlType controlType = UavControlType.fromString(type);
        Long controller = SecurityUtils.getUserId();
        return handleSingleControlResponse(boxSn, approve, controlType, controller);
        return handleSingleControlResponse(boxSn, approve, controlType, controller, requester);
    }
    /**
     * 处理单个控制类型请求响应
     */
    private boolean handleSingleControlResponse(String boxSn, boolean approve, UavControlType controlType,
                                                Long controller) {
        ConcurrentHashMap<String, Long> requestMap = getRequestMap(controlType);
        Long requester = requestMap.get(boxSn);
    private boolean handleSingleControlResponse(String boxSn,
                                                boolean approve,
                                                UavControlType controlType,
                                                Long controller,
                                                Long requester) {
        if (requester == null || requester.equals(controller)) {
        ConcurrentHashMap<String, Set<Long>> requestMap = getRequestMap(controlType);
        Set<Long> requesters = requestMap.get(boxSn);
        if (requesters == null || !requesters.contains(requester)) {
            throw new ControlException("无控制请求");
        }
        if (approve) {
            getControlMap(controlType).put(boxSn, requester);
            // 通知被批准者
            uavControlManager.sendControlApproval(requester, boxSn, controlType.getType(), controller);
            // 🚨 其他请求者自动拒绝(强烈建议)
            for (Long other : requesters) {
                if (!other.equals(requester)) {
                    requesters.remove(requester);
                    uavControlManager.sendControlRejection(other, boxSn, controlType.getType(), controller);
                }
            }
        } else {
            uavControlManager.sendControlRejection(requester, boxSn, controlType.getType(), controller);
        }
        requesters.remove(requester);
        if (requesters.isEmpty()) {
        requestMap.remove(boxSn);
        }
        return true;
    }
    /**
     * 释放 UAV 控制权限
@@ -184,7 +222,7 @@
    /**
     * 根据控制类型获取对应请求 Map
     */
    private ConcurrentHashMap<String, Long> getRequestMap(UavControlType controlType) {
    private ConcurrentHashMap<String, Set<Long>> getRequestMap(UavControlType controlType) {
        switch (controlType) {
            case FLY:
                return flyControlRequests;
@@ -195,6 +233,7 @@
        }
    }
    /**
     * 获取用户优先级
     */