Browse Source

Merge remote-tracking branch 'origin/master'

S0025136190 1 year ago
parent
commit
6972685cab
51 changed files with 515 additions and 399 deletions
  1. 1 0
      Backend/sample/src/main/java/com/dji/sample/component/redis/RedisConst.java
  2. 6 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceRedisService.java
  3. 16 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceRedisServiceImpl.java
  4. 73 66
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/SDKDeviceService.java
  5. 0 2
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
  6. 8 0
      Web/env/.env.subsystem
  7. 2 1
      Web/package.json
  8. 15 17
      Web/src/api/custom/index.ts
  9. 7 9
      Web/src/api/device-log/index.ts
  10. 4 5
      Web/src/api/device-setting/index.ts
  11. 7 8
      Web/src/api/drc.ts
  12. 6 8
      Web/src/api/drone-control/drone.ts
  13. 5 7
      Web/src/api/drone-control/payload.ts
  14. 13 15
      Web/src/api/flight-area/index.ts
  15. 10 19
      Web/src/api/layer.ts
  16. 3 3
      Web/src/api/manage.ts
  17. 26 0
      Web/src/assets/icons/jk_icon_white.svg
  18. 16 17
      Web/src/components/MediaPanel.vue
  19. 27 32
      Web/src/components/devices/DeviceFirmwareStatus.vue
  20. 8 4
      Web/src/components/devices/changeRecord/index.vue
  21. 8 5
      Web/src/components/devices/device-hms/DeviceHmsDrawer.vue
  22. 10 5
      Web/src/components/devices/deviceList/index.vue
  23. 8 4
      Web/src/components/devices/feedbackRecord/index.vue
  24. 32 15
      Web/src/components/flight-area/FlightAreaDevicePanel.vue
  25. 1 1
      Web/src/components/flight-area/FlightAreaItem.vue
  26. 5 6
      Web/src/components/task/CreatePlan.vue
  27. 8 12
      Web/src/components/task/TaskPanel.vue
  28. 17 17
      Web/src/hooks/use-g-map-trajectory.ts
  29. 3 2
      Web/src/hooks/use-g-map-tsa.ts
  30. 7 1
      Web/src/hooks/use-mouse-tool.ts
  31. 24 19
      Web/src/pages/page-pilot/pilot-bind.vue
  32. 7 6
      Web/src/pages/page-pilot/pilot-home.vue
  33. 3 3
      Web/src/pages/page-pilot/pilot-index.vue
  34. 1 2
      Web/src/pages/page-pilot/pilot-liveshare.vue
  35. 1 2
      Web/src/pages/page-pilot/pilot-media.vue
  36. 4 2
      Web/src/pages/page-web/home.vue
  37. 5 6
      Web/src/pages/page-web/projects/Firmwares.vue
  38. 3 3
      Web/src/pages/page-web/projects/dock.vue
  39. 3 1
      Web/src/pages/page-web/projects/layer/index.vue
  40. 15 7
      Web/src/pages/page-web/projects/media/detail/components/FileInfo.vue
  41. 3 2
      Web/src/pages/page-web/projects/media/detail/components/Search.vue
  42. 12 14
      Web/src/pages/page-web/projects/media/detail/index.vue
  43. 8 4
      Web/src/pages/page-web/projects/media/index/index.vue
  44. 3 4
      Web/src/pages/page-web/projects/member/components/Search.vue
  45. 41 26
      Web/src/pages/page-web/projects/member/index.vue
  46. 8 4
      Web/src/pages/page-web/projects/trajectory/index.vue
  47. 4 3
      Web/src/pages/page-web/projects/tsa.vue
  48. 6 6
      Web/src/pages/page-web/projects/wayline.vue
  49. 1 0
      Web/src/router/index.ts
  50. 7 0
      Web/src/utils/index.ts
  51. 4 4
      Web/src/utils/logger.ts

+ 1 - 0
Backend/sample/src/main/java/com/dji/sample/component/redis/RedisConst.java

@@ -64,6 +64,7 @@ public final class RedisConst {
     public static final String DRONE_CONTROL_PREFiX = "control_source" + DELIMITER;
     //飞行任务(轨迹)
     public static final String DRONE_FLIGHT_TASK = "drone_flight_task" + DELIMITER;
+    public static final String DRONE_FLIGHT_TASK_LOCK = "drone_flight_task_lock" + DELIMITER;
     //飞行航点采集
     public static final String DRONE_LAST_TRACK = "drone_last_track" + DELIMITER;
     //Home点

+ 6 - 0
Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceRedisService.java

@@ -121,6 +121,12 @@ public interface IDeviceRedisService {
 
     Boolean delDroneFlightTask(String sn);
 
+    void setDroneFlightTaskLock(String deviceSn);
+
+    Optional<String> getDroneFlightTaskLock(String sn);
+
+    Boolean delDroneFlightTaskLock(String sn);
+
     void setLastDroneTrack(String deviceSn, FlightTrackEntity flightTrackEntity);
 
     Optional<FlightTrackEntity> getLastDroneTrack(String sn);

+ 16 - 0
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceRedisServiceImpl.java

@@ -127,6 +127,22 @@ public class DeviceRedisServiceImpl implements IDeviceRedisService {
         return RedisOpsUtils.del(RedisConst.DRONE_FLIGHT_TASK + sn);
     }
 
+    @Override
+    public void setDroneFlightTaskLock(String deviceSn) {
+        RedisOpsUtils.setWithExpire(RedisConst.DRONE_FLIGHT_TASK_LOCK + deviceSn, deviceSn, RedisConst.DEVICE_ALIVE_SECOND);
+    }
+
+    @Override
+    public Optional<String> getDroneFlightTaskLock(String sn) {
+        return Optional.ofNullable((String) RedisOpsUtils.get(RedisConst.DRONE_FLIGHT_TASK_LOCK + sn));
+    }
+
+    @Override
+    public Boolean delDroneFlightTaskLock(String sn) {
+        return RedisOpsUtils.del(RedisConst.DRONE_FLIGHT_TASK_LOCK + sn);
+    }
+
+
     @Override
     public void setLastDroneTrack(String deviceSn, FlightTrackEntity flightTrackEntity) {
         RedisOpsUtils.setWithExpire(RedisConst.DRONE_LAST_TRACK + deviceSn, flightTrackEntity, RedisConst.DEVICE_ALIVE_SECOND);

+ 73 - 66
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/SDKDeviceService.java

@@ -39,6 +39,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
+import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
@@ -71,9 +72,6 @@ public class SDKDeviceService extends AbstractDeviceService {
     @Autowired
     private IFlightTrackTaskService flightTaskService;
 
-    // 定义一个静态变量来存储上次调用的时间戳
-    private static long lastInvocationTimestamp = 0;
-
     @Override
     public TopicStatusResponse<MqttReply> updateTopoOnline(TopicStatusRequest<UpdateTopo> request, MessageHeaders headers) {
         UpdateTopoSubDevice updateTopoSubDevice = request.getData().getSubDevices().get(0);
@@ -263,7 +261,6 @@ public class SDKDeviceService extends AbstractDeviceService {
     private void toAddFilghtPoint(String from, DeviceDTO device,OsdRcDrone data) {
 
         switch (data.getModeCode()) {
-            //case IDLE:
             case TAKEOFF_FINISHED:
             case MANUAL:
             case TAKEOFF_AUTO:
@@ -274,75 +271,87 @@ public class SDKDeviceService extends AbstractDeviceService {
             case RETURN_AUTO:
             case LIVE_FLIGHT_CONTROLS:
             case LANDING_THREE_PROPELLER:
+                FlightTaskDTO flightTask = getFlightTask(device);
+                if(flightTask == null) {
+                    Optional<String> lockOpt = deviceRedisService.getDroneFlightTaskLock(device.getDeviceSn());
+                    if(lockOpt.isPresent()) {
+                        return;
+                    }
+                    log.info("==============创建飞行任务====:" + data.toString());
+                    deviceRedisService.setDroneFlightTaskLock(device.getDeviceSn());
+                    flightTask = createFlightTask(device);
+                }
                 //添加飞行轨迹
-                addFlightPoint(device,data);
+                addFlightPoint(flightTask, device,data);
                 //推送实时轨迹信息
-                pushFlyTrackToWeb(from,device,data);
+                List<FlightTrackDTO> trackList = getRedisFlightPoint(flightTask,device,data);
+                pushFlyTrackToWeb(from,device,trackList);
 
                 break;
             case LANDING_AUTO:
             case LANDING_FORCED:
                 //飞行结束
+                log.info("==============飞机降落====:" + data.toString());
+                Optional<FlightTaskDTO> opt = deviceRedisService.getDroneFlightTask(device.getDeviceSn());
+                if(opt.isPresent()) {
+                    //移除redis 任务
+                    deviceRedisService.delDroneFlightTask(device.getDeviceSn());
+
+                    flightTask = opt.get();
+                    log.info("==============飞机降落 执行添加飞行轨迹====:" + flightTask.toString());
+                    //添加飞行轨迹
+                    FlightTaskDTO task = addFlightPoint(flightTask,device,data);
+                    //更新飞行任务
+                    updateFlightTask(task);
 
-                //添加飞行轨迹
-                FlightTaskDTO task = addFlightPoint(device,data);
-                //推送实时轨迹信息
-                pushFlyTrackToWeb(from,device,data);
+                    //推送实时轨迹信息
+                    trackList = getRedisFlightPoint(flightTask,device,data);
+                    pushFlyTrackToWeb(from,device,trackList);
 
-                //更新飞行任务
-                if(task != null) {
-                    updateFlightTask(task);
+                    //移除redis航线
+                    deviceRedisService.delDroneFlyTrack(device.getDeviceSn());
                 }
-                //移除redis
-                deviceRedisService.delDroneFlightTask(device.getDeviceSn());
-                deviceRedisService.delDroneFlyTrack(device.getDeviceSn());
+                break;
+            default:
                 break;
 
         }
     }
 
-    private void pushFlyTrackToWeb(String from, DeviceDTO device,OsdRcDrone data) {
+    private void pushFlyTrackToWeb(String from, DeviceDTO device,List<FlightTrackDTO> trackList) {
         //推送实时轨迹信息
-        List<FlightTrackDTO> trackList = getFlightLine(device);
-        if (System.currentTimeMillis() - lastInvocationTimestamp >= 2000) {
-            if(!CollectionUtils.isEmpty(trackList)) {
-                lastInvocationTimestamp = System.currentTimeMillis();
-                deviceService.pushOsdDataToWeb(device.getWorkspaceId(), BizCodeEnum.DRONE_FLY_TRACK, from, trackList);
-            }
-            //模拟第二条实时航线
-            List<FlightTrackDTO> flightPoints =  flightTaskService.getRTFlightTrackByTaskId(44);
+        if(!CollectionUtils.isEmpty(trackList)) {
             deviceService.pushOsdDataToWeb(device.getWorkspaceId(), BizCodeEnum.DRONE_FLY_TRACK, from, trackList);
         }
-
     }
 
-    private List<FlightTrackDTO> getFlightLine(DeviceDTO device) {
+    private List<FlightTrackDTO> getRedisFlightPoint(FlightTaskDTO task,DeviceDTO device,OsdRcDrone data) {
+        List<FlightTrackDTO> flightPoints = null;
         Optional<List<FlightTrackDTO>> optList = deviceRedisService.getDroneFlyTrack(device.getDeviceSn());
-        if(!optList.isPresent() || optList.get().isEmpty()) {
-            //获取飞行任务(轨迹)
-            FlightTaskDTO task = getFlightTask(device, false);
-            if(task == null) {
-                return null;
-            }
-            List<FlightTrackDTO> flightPoints =  flightTaskService.getRTFlightTrackByTaskId(task.getId());
-            deviceRedisService.setDroneFlyTrack(device.getDeviceSn(),flightPoints);
-            return flightPoints;
+        if(optList.isPresent()) {
+            flightPoints = optList.get();
         } else {
-            return optList.get();
+            flightPoints = new ArrayList<FlightTrackDTO>();
         }
+        addRedisFlightPoint(task,flightPoints,device,data);
+        return flightPoints;
     }
 
-    private void addRedisFlightPoint(String sn,FlightTrackDTO point) {
-        List<FlightTrackDTO> flightPoints = new ArrayList<FlightTrackDTO>();
-        Optional<List<FlightTrackDTO>> optList = deviceRedisService.getDroneFlyTrack(sn);
-        if(optList.isPresent()) {
-            flightPoints = optList.get();
-        }
+    private void addRedisFlightPoint(FlightTaskDTO task, List<FlightTrackDTO> flightPoints, DeviceDTO device,OsdRcDrone data) {
+        FlightTrackDTO point = FlightTrackDTO.builder()
+                .taskId(task.getId())
+                .modeCode(data.getModeCode().getCode())
+                .longitude(data.getLongitude().doubleValue())
+                .latitude(data.getLatitude().doubleValue())
+                .altitude(data.getHeight().doubleValue())
+                .elevation(data.getElevation().doubleValue())
+                .type(FlightPointTypeEnum.HAND.getType())
+                .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault())).build();
         flightPoints.add(point);
-        deviceRedisService.setDroneFlyTrack(sn,flightPoints);
+        deviceRedisService.setDroneFlyTrack(device.getDeviceSn(),flightPoints);
     }
 
-    private FlightTaskDTO addFlightPoint(DeviceDTO device,OsdRcDrone data) {
+    private FlightTaskDTO addFlightPoint(FlightTaskDTO task, DeviceDTO device,OsdRcDrone data) {
         synchronized (device.getDeviceSn().intern()) {
             Optional<FlightTrackEntity> lastPoint = deviceRedisService.getLastDroneTrack(device.getDeviceSn());
             long curTime = System.currentTimeMillis();
@@ -371,8 +380,6 @@ public class SDKDeviceService extends AbstractDeviceService {
                 }
             }
             if(isAdd) {
-                //获取飞行任务(轨迹)
-                FlightTaskDTO task = getFlightTask(device, true);
                 log.info("获取飞行轨迹任务:" + task.toString());
                 //添加Home信息
                 if(!lastPoint.isPresent()) {
@@ -386,7 +393,6 @@ public class SDKDeviceService extends AbstractDeviceService {
                                 .type(FlightPointTypeEnum.HOME.getType())
                                 .createTime(System.currentTimeMillis()).build();
                         flightTaskService.addHomePoint(flightTrackEntity);
-                        addRedisFlightPoint(device.getDeviceSn(),flightTaskService.flightTrackEntityToDto(flightTrackEntity));
                     }
                 }
                 //添加轨迹信息
@@ -400,7 +406,6 @@ public class SDKDeviceService extends AbstractDeviceService {
                         .type(FlightPointTypeEnum.HAND.getType())
                         .createTime(System.currentTimeMillis()).build();
                 flightTaskService.addFlightPoint(flightTrackEntity);
-                addRedisFlightPoint(device.getDeviceSn(),flightTaskService.flightTrackEntityToDto(flightTrackEntity));
                 log.info("添加轨迹完成: task:" + task.getTaskName());
                 //记录添加时间
                 deviceRedisService.setLastDroneTrack(device.getDeviceSn(), flightTrackEntity);
@@ -432,7 +437,7 @@ public class SDKDeviceService extends AbstractDeviceService {
         return 0;
     }
 
-    private FlightTaskDTO getFlightTask(DeviceDTO device,boolean isCreate) {
+    private FlightTaskDTO getFlightTask(DeviceDTO device) {
         //获取任务名称
         FlightTaskDTO flightTaskDTO = null;
         Optional<FlightTaskDTO> opt = deviceRedisService.getDroneFlightTask(device.getDeviceSn());
@@ -442,25 +447,27 @@ public class SDKDeviceService extends AbstractDeviceService {
             //查询当天未完成的任务
             flightTaskDTO = flightTaskService.getCurrentFlightTask(device.getWorkspaceId(),device.getDeviceSn());
         }
-        if(flightTaskDTO == null && isCreate) {
-            Date curTime = new Date();
-            String taskName = getTaskName(curTime, device.getDeviceSn());
-            flightTaskDTO = flightTaskService.createFlightTask(FlightTaskEntity.builder()
-                    .taskName(taskName)
-                    .workspaceId(device.getWorkspaceId())
-                    .deviceSn(device.getDeviceSn())
-                    .deviceName(device.getDeviceName())
-                    .payload(device.getPayloadsList() == null ? null : device.getPayloadsList().get(0).getPayloadName())
-                    .beginTime(curTime.getTime())
-                    .createTime(curTime.getTime())
-                    .username(UserRequest.getCurrentUser() != null ? UserRequest.getCurrentUser().getUsername() : "system")
-                    .build());
-
-        }
-        deviceRedisService.setDroneFlightTask(device.getDeviceSn(),flightTaskDTO);
+        if(flightTaskDTO != null) {
+            deviceRedisService.setDroneFlightTask(device.getDeviceSn(), flightTaskDTO);
+        }
         return flightTaskDTO;
     }
 
+    private FlightTaskDTO createFlightTask(DeviceDTO device) {
+        Date curTime = new Date();
+        String taskName = getTaskName(curTime, device.getDeviceSn());
+        return flightTaskService.createFlightTask(FlightTaskEntity.builder()
+                .taskName(taskName)
+                .workspaceId(device.getWorkspaceId())
+                .deviceSn(device.getDeviceSn())
+                .deviceName(device.getDeviceName())
+                .payload(device.getPayloadsList() == null ? null : device.getPayloadsList().get(0).getPayloadName())
+                .beginTime(curTime.getTime())
+                .createTime(curTime.getTime())
+                .username(UserRequest.getCurrentUser() != null ? UserRequest.getCurrentUser().getUsername() : "system")
+                .build());
+    }
+
     //飞行器sn yyyy-MM-dd HH:mm:ss
     private String getTaskName(Date curTime,String droneSn) {
         String format = DateUtil.format(curTime, "yyyy-MM-dd HH:mm:ss");

+ 0 - 2
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java

@@ -323,8 +323,6 @@ public class UserServiceImpl implements IUserService {
         if (entity != null) {
             builder.userId(entity.getUserId())
                     .username(entity.getUsername())
-                    .mqttUsername(entity.getMqttUsername())
-                    .mqttPassword(entity.getMqttPassword())
                     .userType(UserTypeEnum.find(entity.getUserType()).getDesc())
                     .createTime(LocalDateTime.ofInstant(
                             Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()));

+ 8 - 0
Web/env/.env.subsystem

@@ -0,0 +1,8 @@
+# 生产环境配置
+VITE_ENV = 'subsystem'
+
+# Api 地址
+VITE_API_URL = 'http://49.234.30.234:6789'
+
+# WebSocket 地址
+VITE_WEBSOCKET_URL = 'ws://49.234.30.234:6789/api/v1/ws'

+ 2 - 1
Web/package.json

@@ -8,7 +8,8 @@
     "start": "vite --mode development",
     "start:test": "vite --mode test",
     "start:prod": "vite --mode production",
-    "build": "vite build --mode production"
+    "build": "vite build --mode production",
+    "build:subsystem": "vite build --mode subsystem"
   },
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",

+ 15 - 17
Web/src/api/custom/index.ts

@@ -1,7 +1,5 @@
 import request from '/@/api/http/request';
-import { ELocalStorageKey } from "/@/types";
-
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '';
+import { getWorkspaceId } from '/@/utils/index';
 
 // Api参数类型
 export type SignLoginApiParams = {
@@ -105,7 +103,7 @@ const signLoginApi: SignLoginApi = async (data) => {
 
 // 获取负载列表
 const fetchPayloadListApi: FetchPayloadListApi = async () => {
-    const res = await request.get(`/manage/api/v1/devices/${workspaceId}/payloads`);
+    const res = await request.get(`/manage/api/v1/devices/${getWorkspaceId()}/payloads`);
     return res.data;
 };
 
@@ -117,7 +115,7 @@ const fetchFeedbackRecordListApi: FetchFeedbackRecordListApi = async (data) => {
 
 // 获取变化记录列表
 const fetchChangeRecordListApi: FetchChangeRecordListApi = async (params) => {
-    const res = await request.get(`/manage/api/v1/oprlogs/${workspaceId}/devices/logs`, { params: params });
+    const res = await request.get(`/manage/api/v1/oprlogs/${getWorkspaceId()}/devices/logs`, { params: params });
     return res.data;
 };
 
@@ -129,13 +127,13 @@ const fetchProjectListApi: FetchProjectListApi = async () => {
 
 // 获取文件夹列表
 const fetchMediaFileListApi: FetchMediaFileListApi = async (params) => {
-    const res = await request.get(`/media/api/v1/files/${workspaceId}/dirs`, { params: params });
+    const res = await request.get(`/media/api/v1/files/${getWorkspaceId()}/dirs`, { params: params });
     return res.data;
 };
 
 // 批量下载文件夹
 const batchDownloadMediaFileApi: BatchDownloadMediaFileApi = async (params) => {
-    const res = await request.get(`/media/api/v1/files/${workspaceId}/fileDownList`, {
+    const res = await request.get(`/media/api/v1/files/${getWorkspaceId()}/fileDownList`, {
         responseType: 'blob',
         params: params
     });
@@ -144,19 +142,19 @@ const batchDownloadMediaFileApi: BatchDownloadMediaFileApi = async (params) => {
 
 // 获取文件夹下所有文件
 const fetchFileListByFolderApi: FetchFileListByFolderApi = async (dirId, params) => {
-    const res = await request.get(`/media/api/v1/files/${workspaceId}/files/${dirId}`, { params: params });
+    const res = await request.get(`/media/api/v1/files/${getWorkspaceId()}/files/${dirId}`, { params: params });
     return res.data;
 };
 
 // 获取文件详情
 const fetchFileDetailApi: FetchFileDetailApi = async (fileId) => {
-    const res = await request.get(`/media/api/v1/files/${workspaceId}/file/${fileId}`);
+    const res = await request.get(`/media/api/v1/files/${getWorkspaceId()}/file/${fileId}`);
     return res.data;
 };
 
 // 批量下载文件
 const batchDownloadFileApi: BatchDownloadFileApi = async (params) => {
-    const res = await request.get(`/media/api/v1/files/${workspaceId}/downloadFiles`, {
+    const res = await request.get(`/media/api/v1/files/${getWorkspaceId()}/downloadFiles`, {
         responseType: 'blob',
         params: params
     });
@@ -165,48 +163,48 @@ const batchDownloadFileApi: BatchDownloadFileApi = async (params) => {
 
 // 添加图片元素
 const createMapElementApi: CreateMapElementApi = async (fileId) => {
-    const url = `/media/api/v1/files/workspaces/${workspaceId}/createMapElement/${fileId}`
+    const url = `/media/api/v1/files/workspaces/${getWorkspaceId()}/createMapElement/${fileId}`
     const result = await request.post(url)
     return result.data;
 }
 
 // 删除图片元素
 const deleteMapElementApi: DeleteMapElementApi = async (fileId) => {
-    const url = `/media/api/v1/files/workspaces/${workspaceId}/deleteMapElement/${fileId}`
+    const url = `/media/api/v1/files/workspaces/${getWorkspaceId()}/deleteMapElement/${fileId}`
     const result = await request.delete(url)
     return result.data;
 }
 
 // 更新文件名称
 const updateFileNameApi: UpdateFileNameApi = async (fileId, data) => {
-    const url = `/media/api/v1/files/${workspaceId}/updateFile/${fileId}`
+    const url = `/media/api/v1/files/${getWorkspaceId()}/updateFile/${fileId}`
     const result = await request.put(url, data)
     return result.data
 }
 
 // 批量删除图片
 const batchDeletePictureApi: BatchDeletePictureApi = async (data) => {
-    const res = await request.delete(`/media/api/v1/files/${workspaceId}/deleteFiles`, { params: data });
+    const res = await request.delete(`/media/api/v1/files/${getWorkspaceId()}/deleteFiles`, { params: data });
     return res.data;
 };
 
 // 获取轨迹列表
 const fetchTrajectoryListApi: FetchTrajectoryListApi = async (params) => {
-    const url = `/map/api/v1/workspaces/${workspaceId}/flight-tasks`
+    const url = `/map/api/v1/workspaces/${getWorkspaceId()}/flight-tasks`
     const res = await request.get(url, { params: params });
     return res.data;
 };
 
 // 获取轨迹地图
 const fetchTrajectoryMapApi: FetchTrajectoryMapApi = async (taskId) => {
-    const url = `/map/api/v1/workspaces/${workspaceId}/flight-task/${taskId}`
+    const url = `/map/api/v1/workspaces/${getWorkspaceId()}/flight-task/${taskId}`
     const res = await request.get(url);
     return res.data;
 };
 
 // 添加飞行员
 const addPilotApi: AddPilotApi = async (data) => {
-    const url = `/manage/api/v1/users/${workspaceId}/savePilotUser`
+    const url = `/manage/api/v1/users/${getWorkspaceId()}/savePilotUser`
     const res = await request.post(url, data);
     return res.data;
 };

+ 7 - 9
Web/src/api/device-log/index.ts

@@ -1,12 +1,10 @@
 import request, { IWorkspaceResponse, IListWorkspaceResponse } from '/@/api/http/request'
 import { DeviceValue, DOMAIN } from '/@/types/device'
 import { DeviceLogUploadStatusEnum } from '/@/types/device-log'
-import { ELocalStorageKey } from '/@/types'
+import { getWorkspaceId } from '/@/utils/index';
 
 const MNG_API_PREFIX = '/manage/api/v1'
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
-
 export interface GetDeviceUploadLogListParams {
   device_sn: string,
   page: number,
@@ -73,7 +71,7 @@ export interface GetDeviceUploadLogListRsp {
  * @returns
  */
 export async function getDeviceUploadLogList(params: GetDeviceUploadLogListParams): Promise<IListWorkspaceResponse<GetDeviceUploadLogListRsp>> {
-  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${workspaceId}/devices/${params.device_sn}/logs-uploaded`, {
+  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/devices/${params.device_sn}/logs-uploaded`, {
     params: params
   })
   return resp.data
@@ -91,7 +89,7 @@ export interface GetDeviceLogListParams {
  */
 export async function getDeviceLogList(params: GetDeviceLogListParams): Promise<IWorkspaceResponse<DeviceLogFileListInfo>> {
   const domain = params.domain ? params.domain : []
-  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${workspaceId}/devices/${params.device_sn}/logs`, {
+  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/devices/${params.device_sn}/logs`, {
     params: {
       domain_list: domain.join(',')
     }
@@ -116,7 +114,7 @@ export interface UploadDeviceLogBody {
  * @returns
  */
 export async function postDeviceUpgrade(body: UploadDeviceLogBody): Promise<IWorkspaceResponse<{}>> {
-  const resp = await request.post(`${MNG_API_PREFIX}/workspaces/${workspaceId}/devices/${body.device_sn}/logs`, body)
+  const resp = await request.post(`${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/devices/${body.device_sn}/logs`, body)
   return resp.data
 }
 
@@ -130,7 +128,7 @@ export interface CancelDeviceLogUploadBody {
 
 // 取消上传
 export async function cancelDeviceLogUpload(body: CancelDeviceLogUploadBody): Promise<IWorkspaceResponse<{}>> {
-  const url = `${MNG_API_PREFIX}/workspaces/${workspaceId}/devices/${body.device_sn}/logs`
+  const url = `${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/devices/${body.device_sn}/logs`
   const result = await request.delete(url, {
     data: body
   })
@@ -144,7 +142,7 @@ export interface DeleteDeviceLogUploadBody {
 
 // 取消上传
 export async function deleteDeviceLogUpload(body: DeleteDeviceLogUploadBody): Promise<IWorkspaceResponse<{}>> {
-  const url = `${MNG_API_PREFIX}/workspaces/${workspaceId}/devices/${body.device_sn}/logs/${body.logs_id}`
+  const url = `${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/devices/${body.device_sn}/logs/${body.logs_id}`
   const result = await request.delete(url, {
     data: body
   })
@@ -166,6 +164,6 @@ export interface GetUploadDeviceLogUrlParams {
  * @returns
  */
 export async function getUploadDeviceLogUrl(params: GetUploadDeviceLogUrlParams): Promise<IWorkspaceResponse<string>> {
-  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${workspaceId}/logs/${params.logs_id}/url/${params.file_id}`)
+  const resp = await request.get(`${MNG_API_PREFIX}/workspaces/${getWorkspaceId()}/logs/${params.logs_id}/url/${params.file_id}`)
   return resp.data
 }

+ 4 - 5
Web/src/api/device-setting/index.ts

@@ -1,9 +1,8 @@
 import request, { IWorkspaceResponse } from '/@/api/http/request'
-import { ELocalStorageKey } from '/@/types'
 import { NightLightsStateEnum, DistanceLimitStatus, ObstacleAvoidance } from '/@/types/device-setting'
+import { getWorkspaceId } from '/@/utils/index';
 
 const MNG_API_PREFIX = '/manage/api/v1'
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
 
 export interface PutDevicePropsBody {
   night_lights_state?: NightLightsStateEnum;// 夜航灯开关
@@ -18,7 +17,7 @@ export interface PutDevicePropsBody {
  * @returns
  */
 //  /manage/api/v1/devices/{{workspace_id}}/devices/{{device_sn}}/property
-export async function putDeviceProps (deviceSn: string, body: PutDevicePropsBody): Promise<IWorkspaceResponse<{}>> {
-  const resp = await request.put(`${MNG_API_PREFIX}/devices/${workspaceId}/devices/${deviceSn}/property`, body)
+export async function putDeviceProps(deviceSn: string, body: PutDevicePropsBody): Promise<IWorkspaceResponse<{}>> {
+  const resp = await request.put(`${MNG_API_PREFIX}/devices/${getWorkspaceId()}/devices/${deviceSn}/property`, body)
   return resp.data
-}
+}

+ 7 - 8
Web/src/api/drc.ts

@@ -1,9 +1,8 @@
 import request, { IWorkspaceResponse } from '/@/api/http/request'
-import { ELocalStorageKey } from '/@/types'
+import { getWorkspaceId } from '/@/utils/index';
 
 // DRC 链路
 const DRC_API_PREFIX = '/control/api/v1'
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
 
 export interface PostDrcBody {
   client_id?: string // token过期时,用于续期则必填
@@ -20,8 +19,8 @@ export interface DrcParams {
 }
 
 // 获取 mqtt 连接认证
-export async function postDrc (body: PostDrcBody): Promise<IWorkspaceResponse<DrcParams>> {
-  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/connect`, body)
+export async function postDrc(body: PostDrcBody): Promise<IWorkspaceResponse<DrcParams>> {
+  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${getWorkspaceId()}/drc/connect`, body)
   return resp.data
 }
 
@@ -41,8 +40,8 @@ export interface DrcEnterResp {
 }
 
 // 进入飞行控制 (建立drc连接&获取云控控制权)
-export async function postDrcEnter (body: DrcEnterBody): Promise<IWorkspaceResponse<DrcEnterResp>> {
-  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/enter`, body)
+export async function postDrcEnter(body: DrcEnterBody): Promise<IWorkspaceResponse<DrcEnterResp>> {
+  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${getWorkspaceId()}/drc/enter`, body)
   return resp.data
 }
 
@@ -52,7 +51,7 @@ export interface DrcExitBody {
 }
 
 // 退出飞行控制 (退出drc连接&退出云控控制权)
-export async function postDrcExit (body: DrcExitBody): Promise<IWorkspaceResponse<null>> {
-  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/exit`, body)
+export async function postDrcExit(body: DrcExitBody): Promise<IWorkspaceResponse<null>> {
+  const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${getWorkspaceId()}/drc/exit`, body)
   return resp.data
 }

+ 6 - 8
Web/src/api/drone-control/drone.ts

@@ -1,11 +1,9 @@
-import request, { IWorkspaceResponse } from '/@/api/http/request'
-// import { ELocalStorageKey } from '/@/types'
+import request, { IWorkspaceResponse } from '/@/api/http/request';
 
 const API_PREFIX = '/control/api/v1'
-// const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '
 
 // 获取飞行控制权
-export async function postFlightAuth (sn: string): Promise<IWorkspaceResponse<null>> {
+export async function postFlightAuth(sn: string): Promise<IWorkspaceResponse<null>> {
   const resp = await request.post(`${API_PREFIX}/devices/${sn}/authority/flight`)
   return resp.data
 }
@@ -41,18 +39,18 @@ export interface PostFlyToPointBody {
 }
 
 // 飞向目标点
-export async function postFlyToPoint (sn: string, body: PostFlyToPointBody): Promise<IWorkspaceResponse<null>> {
+export async function postFlyToPoint(sn: string, body: PostFlyToPointBody): Promise<IWorkspaceResponse<null>> {
   const resp = await request.post(`${API_PREFIX}/devices/${sn}/jobs/fly-to-point`, body)
   return resp.data
 }
 
 // 停止飞向目标点
-export async function deleteFlyToPoint (sn: string): Promise<IWorkspaceResponse<null>> {
+export async function deleteFlyToPoint(sn: string): Promise<IWorkspaceResponse<null>> {
   const resp = await request.delete(`${API_PREFIX}/devices/${sn}/jobs/fly-to-point`)
   return resp.data
 }
 
-export interface PostTakeoffToPointBody{
+export interface PostTakeoffToPointBody {
   target_height: number;
   target_latitude: number;
   target_longitude: number;
@@ -68,7 +66,7 @@ export interface PostTakeoffToPointBody{
 }
 
 // 一键起飞
-export async function postTakeoffToPoint (sn: string, body: PostTakeoffToPointBody): Promise<IWorkspaceResponse<null>> {
+export async function postTakeoffToPoint(sn: string, body: PostTakeoffToPointBody): Promise<IWorkspaceResponse<null>> {
   const resp = await request.post(`${API_PREFIX}/devices/${sn}/jobs/takeoff-to-point`, body)
   return resp.data
 }

+ 5 - 7
Web/src/api/drone-control/payload.ts

@@ -1,17 +1,15 @@
 import request, { IWorkspaceResponse } from '/@/api/http/request'
 import { CameraType, CameraMode } from '/@/types/live-stream'
 import { GimbalResetMode } from '/@/types/drone-control'
-// import { ELocalStorageKey } from '/@/types'
 
 const API_PREFIX = '/control/api/v1'
-// const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '
 
 export interface PostPayloadAuthBody {
   payload_index: string
 }
 
 // 获取负载控制权
-export async function postPayloadAuth (sn: string, body: PostPayloadAuthBody): Promise<IWorkspaceResponse<null>> {
+export async function postPayloadAuth(sn: string, body: PostPayloadAuthBody): Promise<IWorkspaceResponse<null>> {
   const resp = await request.post(`${API_PREFIX}/devices/${sn}/authority/payload`, body)
   return resp.data
 }
@@ -50,12 +48,12 @@ export interface PostCameraFocalLengthBody {
   zoom_factor: number
 }
 
-export interface PostGimbalResetBody{
+export interface PostGimbalResetBody {
   payload_index: string,
   reset_mode: GimbalResetMode,
 }
 
-export interface PostCameraAimBody{
+export interface PostCameraAimBody {
   payload_index: string,
   camera_type: CameraType,
   locked: boolean,
@@ -87,7 +85,7 @@ export type PostPayloadCommandsBody = {
 }
 
 // 发送负载名称
-export async function postPayloadCommands (sn: string, body: PostPayloadCommandsBody): Promise<IWorkspaceResponse<null>> {
+export async function postPayloadCommands(sn: string, body: PostPayloadCommandsBody): Promise<IWorkspaceResponse<null>> {
   const resp = await request.post(`${API_PREFIX}/devices/${sn}/payload/commands`, body)
   return resp.data
-}
+}

+ 13 - 15
Web/src/api/flight-area/index.ts

@@ -1,8 +1,8 @@
 import request from '../http/request'
 import { IWorkspaceResponse } from '../http/type'
 import { EFlightAreaType, ESyncStatus, FlightAreaContent } from './../../types/flight-area'
-import { ELocalStorageKey } from '/@/types/enums'
 import { GeojsonCoordinate } from '/@/utils/genjson'
+import { getWorkspaceId } from '/@/utils/index';
 
 export interface GetFlightArea {
   area_id: string,
@@ -48,34 +48,32 @@ export interface GetDeviceStatus {
 
 const MAP_API_PREFIX = '/map/api/v1'
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
-
-export async function getFlightAreaList (): Promise<IWorkspaceResponse<GetFlightArea[]>> {
-  const resp = await request.get(`${MAP_API_PREFIX}/workspaces/${workspaceId}/flight-areas`)
+export async function getFlightAreaList(): Promise<IWorkspaceResponse<GetFlightArea[]>> {
+  const resp = await request.get(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/flight-areas`)
   return resp.data
 }
 
-export async function changeFlightAreaStatus (area_id: string, status: boolean): Promise<IWorkspaceResponse<any>> {
-  const resp = await request.put(`${MAP_API_PREFIX}/workspaces/${workspaceId}/flight-area/${area_id}`, { status })
+export async function changeFlightAreaStatus(area_id: string, status: boolean): Promise<IWorkspaceResponse<any>> {
+  const resp = await request.put(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/flight-area/${area_id}`, { status })
   return resp.data
 }
 
-export async function saveFlightArea (body: PostFlightAreaBody): Promise<IWorkspaceResponse<any>> {
-  const resp = await request.post(`${MAP_API_PREFIX}/workspaces/${workspaceId}/flight-area`, body)
+export async function saveFlightArea(body: PostFlightAreaBody): Promise<IWorkspaceResponse<any>> {
+  const resp = await request.post(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/flight-area`, body)
   return resp.data
 }
 
-export async function deleteFlightArea (area_id: string): Promise<IWorkspaceResponse<any>> {
-  const resp = await request.delete(`${MAP_API_PREFIX}/workspaces/${workspaceId}/flight-area/${area_id}`)
+export async function deleteFlightArea(area_id: string): Promise<IWorkspaceResponse<any>> {
+  const resp = await request.delete(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/flight-area/${area_id}`)
   return resp.data
 }
 
-export async function syncFlightArea (device_sn: string[]): Promise<IWorkspaceResponse<any>> {
-  const resp = await request.post(`${MAP_API_PREFIX}/workspaces/${workspaceId}/flight-area/sync`, { device_sn })
+export async function syncFlightArea(device_sn: string[]): Promise<IWorkspaceResponse<any>> {
+  const resp = await request.post(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/flight-area/sync`, { device_sn })
   return resp.data
 }
 
-export async function getDeviceStatus (): Promise<IWorkspaceResponse<GetDeviceStatus[]>> {
-  const resp = await request.get(`${MAP_API_PREFIX}/workspaces/${workspaceId}/device-status`)
+export async function getDeviceStatus(): Promise<IWorkspaceResponse<GetDeviceStatus[]>> {
+  const resp = await request.get(`${MAP_API_PREFIX}/workspaces/${getWorkspaceId()}/device-status`)
   return resp.data
 }

+ 10 - 19
Web/src/api/layer.ts

@@ -1,53 +1,44 @@
-import { ELocalStorageKey } from '../types/enums'
 import request, { IWorkspaceResponse } from '/@/api/http/request'
 import { mapLayers } from '/@/constants/mock-layers'
 import { elementGroupsReq, PostElementsBody, PutElementsBody } from '/@/types/mapLayer'
+import { getWorkspaceId } from '/@/utils/index';
+
 const PREFIX = '/map/api/v1'
-const workspace_id = localStorage.getItem(ELocalStorageKey.WorkspaceId)
+
 type UnknownResponse = Promise<IWorkspaceResponse<unknown>>
-// get elements group
-// export const getLayers = async (reqParams: elementGroupsReq): UnknownResponse => {
-//   const url = `${PREFIX}/workspaces/${workspace_id}/element_groups`
-//   const result = await request.get(url, {
-//     params: {
-//       group_id: reqParams.groupId,
-//       is_distributed: reqParams.isDistributed
-//     },
-//   })
-//   return result.data
-// }
+
 export const getLayers = async (reqParams: elementGroupsReq): UnknownResponse => {
   return mapLayers
 }
 
 // Get elements groups request
 export const getElementGroupsReq = async (body: elementGroupsReq): Promise<IWorkspaceResponse<any>> => {
-  const url = `${PREFIX}/workspaces/` + workspace_id + '/element-groups'
+  const url = `${PREFIX}/workspaces/` + getWorkspaceId() + '/element-groups'
   const result = await request.get(url, body)
   return result.data
 }
 // add element
 export const postElementsReq = async (pid: string, body: PostElementsBody): Promise<IWorkspaceResponse<{ id: string }>> => {
-  const url = `${PREFIX}/workspaces/` + workspace_id + `/element-groups/${pid}/elements`
+  const url = `${PREFIX}/workspaces/` + getWorkspaceId() + `/element-groups/${pid}/elements`
   const result = await request.post(url, body)
   return result.data
 }
 // Update map element request
 export const updateElementsReq = async (id: string, body: PutElementsBody): Promise<IWorkspaceResponse<{ id: string }>> => {
-  const url = `${PREFIX}/workspaces/` + workspace_id + `/elements/${id}`
+  const url = `${PREFIX}/workspaces/` + getWorkspaceId() + `/elements/${id}`
   const result = await request.put(url, body)
   return result.data
 }
 // Delete map element
 export const deleteElementReq = async (id: string, body: {}): Promise<any> => {
-  const url = `${PREFIX}/workspaces/` + workspace_id + `/elements/${id}`
+  const url = `${PREFIX}/workspaces/` + getWorkspaceId() + `/elements/${id}`
   const result = await request.delete(url, body)
   return result.data
 }
 
 // Delete layer elements
 export const deleteLayerEleReq = async (id: string, body: {}): Promise<any> => {
-  const url = `${PREFIX}/workspaces/` + workspace_id + `/element-groups/${id}/elements`
+  const url = `${PREFIX}/workspaces/` + getWorkspaceId() + `/element-groups/${id}/elements`
   const result = await request.delete(url, body)
   return result.data
-}
+}

+ 3 - 3
Web/src/api/manage.ts

@@ -90,9 +90,9 @@ export const setLivestreamQuality = async function (body: {}): Promise<IWorkspac
   return result.data
 }
 
-export const getAllUsersInfo = async function (wid: string, body: { page: number, page_size: number }): Promise<CommonListResponse<any>> {
-  const url = `${HTTP_PREFIX}/users/${wid}/users?&page=${body.page}&page_size=${body.page_size}`
-  const result = await request.get(url)
+export const getAllUsersInfo = async function (wid: string, body: { page: number, page_size: number, search_info: string }): Promise<CommonListResponse<any>> {
+  const url = `${HTTP_PREFIX}/users/${wid}/users`
+  const result = await request.get(url, { params: body })
   return result.data
 }
 

+ 26 - 0
Web/src/assets/icons/jk_icon_white.svg

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="251px" height="251px" viewBox="0 0 251 251" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>jk_icon</title>
+    <defs>
+        <filter x="-8.0%" y="-5.7%" width="116.0%" height="111.3%" filterUnits="objectBoundingBox" id="filter-1">
+            <feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
+            <feMerge>
+                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
+                <feMergeNode in="SourceGraphic"></feMergeNode>
+            </feMerge>
+        </filter>
+        <radialGradient cx="13.6659223%" cy="62.3104639%" fx="13.6659223%" fy="62.3104639%" r="131.982363%" gradientTransform="translate(0.136659,0.623105),scale(1.000000,0.378788),rotate(-50.925180),translate(-0.136659,-0.623105)" id="radialGradient-2">
+            <stop stop-color="#00A0C7" offset="0%"></stop>
+            <stop stop-color="#08A84C" offset="100%"></stop>
+        </radialGradient>
+    </defs>
+    <g id="jk_icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <rect id="矩形" x="0" y="0" width="251" height="251" rx="26"></rect>
+        <g id="shjk_logo" filter="url(#filter-1)" transform="translate(51.000000, 12.000000)" fill-rule="nonzero">
+            <path d="M75.4603621,105.845419 C72.6648895,128.402658 82.9600933,131.750898 96.5956723,111.716164 L143.396227,46.0388144 L88.7798308,14 L75.4603621,105.84515 L75.4603621,105.845419 Z M99.429745,131.760611 C92.9618743,138.233803 88.1125313,147.974478 103.598818,157.109304 L150,182.260493 L150,77.0055529 L99.4299233,131.760253 L99.429745,131.760611 Z M78.5169423,179.310393 L88.9154213,212 L149.999777,212 L103.940468,173.115684 C95.6605348,165.758564 89.1120319,162.747002 84.5463057,162.747002 C77.5173526,162.747002 75.1990318,169.900262 78.5168977,179.310393 L78.5169423,179.310393 Z" id="形状" fill="url(#radialGradient-2)"></path>
+            <polygon id="路径" fill="#005D80" points="18.8263249 45.05655 18.8005458 127.045898 0 146.711309 0 212 45.1671295 212 45.1671295 211.996826 64 211.996826 64 0 18.8261456 45.0573099 18.8261456 45.0569523"></polygon>
+        </g>
+    </g>
+</svg>

+ 16 - 17
Web/src/components/MediaPanel.vue

@@ -6,8 +6,8 @@
         :pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData">
         <template v-for="col in ['name', 'path']" #[col]="{ text }" :key="col">
           <a-tooltip :title="text">
-              <a v-if="col === 'name'">{{ text }}</a>
-              <span v-else>{{ text }}</span>
+            <a v-if="col === 'name'">{{ text }}</a>
+            <span v-else>{{ text }}</span>
           </a-tooltip>
         </template>
         <template #original="{ text }">
@@ -15,7 +15,9 @@
         </template>
         <template #action="{ record }">
           <a-tooltip title="download">
-            <a class="fz18" @click="downloadMedia(record)"><DownloadOutlined /></a>
+            <a class="fz18" @click="downloadMedia(record)">
+              <DownloadOutlined />
+            </a>
           </a-tooltip>
         </template>
       </a-table>
@@ -24,17 +26,15 @@
 </template>
 
 <script setup lang="ts">
+import { onMounted, reactive, ref } from 'vue'
+import { Pagination } from 'ant-design-vue'
 import { TableState } from 'ant-design-vue/lib/table/interface'
-import { onMounted, reactive,ref} from 'vue'
 import { IPage } from '../api/http/type'
-import { ELocalStorageKey } from '../types/enums'
 import { downloadFile } from '../utils/common'
 import { downloadMediaFile, getMediaFiles } from '/@/api/media'
 import { DownloadOutlined } from '@ant-design/icons-vue'
-import { message, Pagination } from 'ant-design-vue'
-import { load } from '@amap/amap-jsapi-loader'
+import { getWorkspaceId } from '/@/utils/index';
 
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
 const loading = ref(false)
 
 const columns = [
@@ -50,10 +50,6 @@ const columns = [
     ellipsis: true,
     slots: { customRender: 'path' }
   },
-  // {
-  //   title: 'FileSize',
-  //   dataIndex: 'size',
-  // },
   {
     title: '设备',
     dataIndex: 'drone'
@@ -111,8 +107,8 @@ onMounted(() => {
   getFiles()
 })
 
-function getFiles () {
-  getMediaFiles(workspaceId, body).then(res => {
+function getFiles() {
+  getMediaFiles(getWorkspaceId(), body).then(res => {
     mediaData.data = res.data.list
     paginationProp.total = res.data.pagination.total
     paginationProp.current = res.data.pagination.page
@@ -120,15 +116,15 @@ function getFiles () {
   })
 }
 
-function refreshData (page: Pagination) {
+function refreshData(page: Pagination) {
   body.page = page?.current!
   body.page_size = page?.pageSize!
   getFiles()
 }
 
-function downloadMedia (media: MediaFile) {
+function downloadMedia(media: MediaFile) {
   loading.value = true
-  downloadMediaFile(workspaceId, media.file_id).then(res => {
+  downloadMediaFile(getWorkspaceId(), media.file_id).then(res => {
     if (!res) {
       return
     }
@@ -145,15 +141,18 @@ function downloadMedia (media: MediaFile) {
 .media-panel-wrapper {
   width: 100%;
   padding: 16px;
+
   .media-table {
     background: #fff;
     margin-top: 10px;
   }
+
   .action-area {
     color: $primary;
     cursor: pointer;
   }
 }
+
 .header {
   width: 100%;
   height: 60px;

+ 27 - 32
Web/src/components/devices/DeviceFirmwareStatus.vue

@@ -1,45 +1,38 @@
 <template>
-<div>
-  <span class="status-tag pointer">
-    <a-popconfirm
-      :title="getTitle()"
-      ok-text="Yes"
-      cancel-text="No"
-      placement="left"
-      @confirm="onFirmwareStatusClick(firmware)"
-    >
-      <a-tag :color="firmware.firmware_status ? commonColor.NORMAL : commonColor.FAIL"
+  <div>
+    <span class="status-tag pointer">
+      <a-popconfirm :title="getTitle()" ok-text="Yes" cancel-text="No" placement="left"
+        @confirm="onFirmwareStatusClick(firmware)">
+        <a-tag :color="firmware.firmware_status ? commonColor.NORMAL : commonColor.FAIL"
           :class="firmware.firmware_status ? 'border-corner ' : 'status-disable border-corner'">
-        {{ getText(firmware.firmware_status) }}
-      </a-tag>
-    </a-popconfirm>
-  </span>
-</div>
+          {{ getText(firmware.firmware_status) }}
+        </a-tag>
+      </a-popconfirm>
+    </span>
+  </div>
 </template>
 
 <script lang="ts" setup>
-import { defineProps, defineEmits, ref, watch, computed } from 'vue'
+import { defineProps } from 'vue'
 import { changeFirmareStatus } from '/@/api/manage'
-import { ELocalStorageKey } from '/@/types'
 import { Firmware, FirmwareStatusEnum } from '/@/types/device-firmware'
 import { commonColor } from '/@/utils/color'
+import { getWorkspaceId } from '/@/utils/index'
 
 const props = defineProps<{
   firmware: Firmware
 }>()
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
-
-function getTitle () {
+function getTitle() {
   return `Are you sure to set this firmware to ${getText(!props.firmware.firmware_status)}?`
 }
 
-function getText (status: boolean) {
+function getText(status: boolean) {
   return status ? FirmwareStatusEnum.TRUE : FirmwareStatusEnum.FALSE
 }
 
-function onFirmwareStatusClick (record: Firmware) {
-  changeFirmareStatus(workspaceId, record.firmware_id, { status: !record.firmware_status }).then((res) => {
+function onFirmwareStatusClick(record: Firmware) {
+  changeFirmareStatus(getWorkspaceId(), record.firmware_id, { status: !record.firmware_status }).then((res) => {
     if (res.code === 0) {
       record.firmware_status = !record.firmware_status
     }
@@ -49,13 +42,15 @@ function onFirmwareStatusClick (record: Firmware) {
 </script>
 
 <style lang="scss" scoped>
-  .status-disable{
-    opacity: 0.4;
-  }
-  .border-corner {
-    border-radius: 3px;
-  }
-  .pointer {
-    cursor: pointer;
-  }
+.status-disable {
+  opacity: 0.4;
+}
+
+.border-corner {
+  border-radius: 3px;
+}
+
+.pointer {
+  cursor: pointer;
+}
 </style>

+ 8 - 4
Web/src/components/devices/changeRecord/index.vue

@@ -29,11 +29,13 @@ import CustomCell from './components/CustomCell.vue';
 import { apis } from '/@/api/custom/index';
 
 interface State {
+  query: any,
   listLoading: boolean,
   list: any[],
 };
 
 const state: State = reactive({
+  query: undefined,
   listLoading: false,
   list: [],
 });
@@ -47,11 +49,11 @@ const paginationConfig = reactive({
   total: 0
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const res = await apis.fetchChangeRecordList({
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize
     });
@@ -137,12 +139,14 @@ const refreshData = async (page: any) => {
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 </script>
 

+ 8 - 5
Web/src/components/devices/device-hms/DeviceHmsDrawer.vue

@@ -58,21 +58,22 @@
 
 <!-- 暂时只抽取该组件 -->
 <script lang="ts" setup>
-import { watchEffect, reactive, ref, defineProps, defineEmits, watch } from 'vue'
+import { reactive, ref, defineProps, defineEmits, watch } from 'vue'
 import { getDeviceHms, HmsQueryBody } from '/@/api/manage'
-import moment from 'moment'
 import { ColumnProps, TableState } from 'ant-design-vue/lib/table/interface'
 import { Device, DeviceHms } from '/@/types/device'
 import { IPage } from '/@/api/http/type'
-import { EDeviceTypeName, EHmsLevel, ELocalStorageKey } from '/@/types'
+import { EDeviceTypeName, EHmsLevel } from '/@/types'
+import { getWorkspaceId } from '/@/utils/index'
+import moment from 'moment'
 
 const props = defineProps<{
   visible: boolean,
   device: null | Device,
 }>()
+
 const emit = defineEmits(['update:visible', 'ok', 'cancel'])
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
 // 健康状态
 const sVisible = ref(false)
 
@@ -206,7 +207,7 @@ const time = ref([moment(param.begin_time), moment(param.end_time)])
 
 function getHms() {
   loading.value = true
-  getDeviceHms(param, workspaceId, getPaginationBody())
+  getDeviceHms(param, getWorkspaceId(), getPaginationBody())
     .then(res => {
       hmsPaginationProp.total = res.data.pagination.total
       hmsPaginationProp.current = res.data.pagination.page
@@ -249,3 +250,5 @@ function onLevelSelect(val: number) {
   getHms()
 }
 </script>
+
+<style lang="scss" scoped></style>

+ 10 - 5
Web/src/components/devices/deviceList/index.vue

@@ -84,9 +84,11 @@ import DeviceFirmwareUpgrade from '/@/components/devices/device-upgrade/DeviceFi
 import DeviceLogUploadRecordDrawer from '/@/components/devices/device-log/DeviceLogUploadRecordDrawer.vue';
 import DeviceHmsDrawer from '/@/components/devices/device-hms/DeviceHmsDrawer.vue';
 import { getBindingDevices, updateDevice, unbindDevice } from '/@/api/manage';
+import { getWorkspaceId } from '/@/utils/index';
 
 interface State {
   workspaceId: string,
+  query: any,
   listLoading: boolean,
   list: any[],
   selectedRowKeys: string[],
@@ -99,7 +101,8 @@ interface State {
 };
 
 const state: State = reactive({
-  workspaceId: localStorage.getItem('workspace_id') || '',
+  workspaceId: getWorkspaceId(),
+  query: undefined,
   listLoading: false,
   list: [],
   selectedRowKeys: [],
@@ -118,11 +121,11 @@ const paginationConfig = reactive({
   total: 0
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const res = await getBindingDevices(state.workspaceId, {
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize,
     });
@@ -236,12 +239,14 @@ const onClickBatchDelete = async () => {
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击设备日志

+ 8 - 4
Web/src/components/devices/feedbackRecord/index.vue

@@ -53,6 +53,7 @@ import Drawer from './components/Drawer.vue';
 import { apis } from '/@/api/custom/index';
 
 interface State {
+  query: any,
   listLoading: boolean,
   list: any[],
   currentId: string,
@@ -60,6 +61,7 @@ interface State {
 };
 
 const state: State = reactive({
+  query: undefined,
   listLoading: false,
   list: [],
   currentId: '',
@@ -75,11 +77,11 @@ const paginationConfig = reactive({
   total: 0
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const res = await apis.fetchChangeRecordList({
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize
     });
@@ -177,12 +179,14 @@ const refreshData = async (page: any) => {
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击详情

+ 32 - 15
Web/src/components/flight-area/FlightAreaDevicePanel.vue

@@ -2,21 +2,27 @@
   <div class="flight-area-device-panel">
     <Title title="Choose Synchronous Devices">
       <div style="position: absolute; right: 10px;">
-        <a style="color: white;" @click="closePanel"><CloseOutlined /></a>
+        <a style="color: white;" @click="closePanel">
+          <CloseOutlined />
+        </a>
       </div>
     </Title>
     <div class="scrollbar">
       <div id="data" v-if="data.length !== 0">
         <div v-for="dock in data" :key="dock.device_sn">
-          <div class="pt5 panel flex-row" @click="selectDock(dock)" :style="{opacity: selectedDocksMap[dock.device_sn] ? 1 : 0.5 }">
+          <div class="pt5 panel flex-row" @click="selectDock(dock)"
+            :style="{ opacity: selectedDocksMap[dock.device_sn] ? 1 : 0.5 }">
             <div style="width: 88%">
               <div class="title">
-                <RobotFilled class="fz20"/>
+                <RobotFilled class="fz20" />
                 <a-tooltip :title="dock.nickname">
-                  <div class="pr10 ml5" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{ dock.nickname }}</div>
+                  <div class="pr10 ml5"
+                    style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{
+                      dock.nickname }}</div>
                 </a-tooltip>
               </div>
-              <div class="ml10 mr10 pr5 pl5 flex-align-center flex-row flex-justify-between" style="background: #595959;">
+              <div class="ml10 mr10 pr5 pl5 flex-align-center flex-row flex-justify-between"
+                style="background: #595959;">
                 <div>
                   Custom Flight Area
                 </div>
@@ -26,19 +32,21 @@
                       <ApiOutlined />
                     </a-tooltip>
                   </div>
-                  <div v-else-if="deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.SYNCHRONIZED">
+                  <div
+                    v-else-if="deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.SYNCHRONIZED">
                     <a-tooltip title="Data synced">
-                      <CheckCircleTwoTone twoToneColor="#28d445"/>
+                      <CheckCircleTwoTone twoToneColor="#28d445" />
                     </a-tooltip>
                   </div>
                   <div v-else-if="deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.SYNCHRONIZING
-                                  || deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.WAIT_SYNC">
+                    || deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.WAIT_SYNC">
                     <a-tooltip title="To be synced">
                       <SyncOutlined spin />
                     </a-tooltip>
                   </div>
                   <div v-else>
-                    <a-tooltip :title="deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_msg || 'No synchronization'">
+                    <a-tooltip
+                      :title="deviceStatusMap[dock.device_sn]?.flight_area_status?.sync_msg || 'No synchronization'">
                       <ExclamationCircleTwoTone twoToneColor="#e70102" />
                     </a-tooltip>
                   </div>
@@ -67,22 +75,25 @@
 </template>
 
 <script lang="ts" setup>
+import { defineEmits, onMounted, ref, defineProps, computed } from 'vue'
+import { message } from 'ant-design-vue'
 import { CloseOutlined, RobotFilled, CheckOutlined, ApiOutlined, CheckCircleTwoTone, SyncOutlined, ExclamationCircleTwoTone } from '@ant-design/icons-vue'
 import Title from '/@/components/workspace/Title.vue'
-import { defineEmits, onMounted, ref, defineProps, computed } from 'vue'
 import { getBindingDevices } from '/@/api/manage'
-import { EDeviceTypeName, ELocalStorageKey } from '/@/types'
+import { EDeviceTypeName } from '/@/types'
 import { IPage } from '/@/api/http/type'
 import { Device } from '/@/types/device'
 import DividerLine from '../workspace/DividerLine.vue'
-import { message } from 'ant-design-vue'
 import { GetDeviceStatus, syncFlightArea } from '/@/api/flight-area'
 import { ESyncStatus } from '/@/types/flight-area'
+import { getWorkspaceId } from '/@/utils/index'
 
 const props = defineProps<{
   data: GetDeviceStatus[]
 }>()
+
 const emit = defineEmits(['closePanel'])
+
 const closePanel = () => {
   emit('closePanel', false)
 }
@@ -93,17 +104,19 @@ const deviceStatusMap = computed(() => props.data.reduce((obj: Record<string, Ge
   obj[val.device_sn] = val
   return obj
 }, {} as Record<string, GetDeviceStatus>))
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
+
 const body: IPage = {
   page: 1,
   total: 0,
   page_size: 10,
 }
+
 const data = ref<Device[]>([])
+
 const selectedDocksMap = ref<Record<string, boolean>>({})
 
 const getDocks = async () => {
-  await getBindingDevices(workspaceId, body, EDeviceTypeName.Dock).then(res => {
+  await getBindingDevices(getWorkspaceId(), body, EDeviceTypeName.Dock).then(res => {
     if (res.code !== 0) {
       return
     }
@@ -120,7 +133,7 @@ const selectDock = (dock: Device) => {
     return
   }
   if (deviceStatusMap.value[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.SYNCHRONIZING ||
-      deviceStatusMap.value[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.WAIT_SYNC) {
+    deviceStatusMap.value[dock.device_sn]?.flight_area_status?.sync_status === ESyncStatus.WAIT_SYNC) {
     message.info('The dock is synchronizing.')
     return
   }
@@ -175,20 +188,24 @@ const syncDeviceFlightArea = () => {
   z-index: 1000;
   color: white;
   background: #282828;
+
   .footer {
     position: absolute;
     width: 100%;
     bottom: 10px;
     padding: 10px;
+
     button {
       width: 45%;
       border: 0;
     }
   }
+
   .scrollbar {
     overflow-y: auto;
     height: calc(100vh - 150px);
   }
+
   .box {
     font-size: 22px;
     line-height: 60px;

+ 1 - 1
Web/src/components/flight-area/FlightAreaItem.vue

@@ -86,4 +86,4 @@ const clickLocation = () => {
   opacity: 50%;
 }
 
-</style>
+</style>

+ 5 - 6
Web/src/components/task/CreatePlan.vue

@@ -159,21 +159,20 @@
 
 <script lang="ts" setup>
 import { computed, reactive, ref } from 'vue'
-import { ELocalStorageKey, ERouterName } from '/@/types'
+import { ERouterName } from '/@/types'
 import { useMyStore } from '/@/store'
-import { WaylineType, WaylineFile } from '/@/types/wayline'
+import { WaylineFile } from '/@/types/wayline'
 import { Device, DEVICE_NAME } from '/@/types/device'
 import { createPlan, CreatePlan } from '/@/api/wayline'
 import { getRoot } from '/@/root'
 import { TaskType, OutOfControlActionOptions, OutOfControlAction, TaskTypeOptions } from '/@/types/task'
-import moment from 'moment';
 import { RuleObject } from 'ant-design-vue/es/form/interface'
+import { getWorkspaceId } from '/@/utils/index'
+import moment from 'moment';
 
 const root = getRoot()
 const store = useMyStore()
 
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
-
 const wayline = computed<WaylineFile>(() => {
   return store.state.waylineInfo
 })
@@ -295,7 +294,7 @@ function onSubmit() {
     if (wayline.value && wayline.value.template_types && wayline.value.template_types.length > 0) {
       createPlanBody.wayline_type = wayline.value.template_types[0]
     }
-    createPlan(workspaceId, createPlanBody)
+    createPlan(getWorkspaceId(), createPlanBody)
       .then(res => {
         disabled.value = false
       }).finally(() => {

+ 8 - 12
Web/src/components/task/TaskPanel.vue

@@ -86,20 +86,16 @@
 <script setup lang="ts">
 import { message } from 'ant-design-vue'
 import { TableState } from 'ant-design-vue/lib/table/interface'
-import { onMounted, reactive} from 'vue'
+import { onMounted, reactive } from 'vue'
 import { IPage } from '/@/api/http/type'
 import { deleteTask, updateTaskStatus, UpdateTaskStatus, getWaylineJobs, Task, uploadMediaFileNow } from '/@/api/wayline'
-import { useMyStore } from '/@/store'
-import { ELocalStorageKey } from '/@/types/enums'
 import { useFormatTask } from './use-format-task'
 import { TaskStatus, TaskProgressInfo, TaskProgressStatus, TaskProgressWsStatusMap, MediaStatus, MediaStatusProgressInfo, TaskMediaHighestPriorityProgressInfo } from '/@/types/task'
 import { useTaskWsEvent } from './use-task-ws-event'
 import { getErrorMessage } from '/@/utils/error-code/index'
 import { commonColor } from '/@/utils/color'
 import { ExclamationCircleOutlined, UploadOutlined } from '@ant-design/icons-vue'
-
-const store = useMyStore()
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
+import { getWorkspaceId } from '/@/utils/index'
 
 const body: IPage = {
   page: 1,
@@ -249,7 +245,7 @@ onMounted(() => {
 })
 
 function getPlans() {
-  getWaylineJobs(workspaceId, body).then(res => {
+  getWaylineJobs(getWorkspaceId(), body).then(res => {
     if (res.code !== 0) {
       return
     }
@@ -267,7 +263,7 @@ function refreshData(page: Pagination) {
 
 // 删除任务
 async function onDeleteTask(jobId: string) {
-  const { code } = await deleteTask(workspaceId, {
+  const { code } = await deleteTask(getWorkspaceId(), {
     job_id: jobId
   })
   if (code === 0) {
@@ -278,7 +274,7 @@ async function onDeleteTask(jobId: string) {
 
 // 挂起任务
 async function onSuspendTask(jobId: string) {
-  const { code } = await updateTaskStatus(workspaceId, {
+  const { code } = await updateTaskStatus(getWorkspaceId(), {
     job_id: jobId,
     status: UpdateTaskStatus.Suspend
   })
@@ -290,7 +286,7 @@ async function onSuspendTask(jobId: string) {
 
 // 解除挂起任务
 async function onResumeTask(jobId: string) {
-  const { code } = await updateTaskStatus(workspaceId, {
+  const { code } = await updateTaskStatus(getWorkspaceId(), {
     job_id: jobId,
     status: UpdateTaskStatus.Resume
   })
@@ -302,7 +298,7 @@ async function onResumeTask(jobId: string) {
 
 // 立即上传媒体
 async function onUploadMediaFileNow(jobId: string) {
-  const { code } = await uploadMediaFileNow(workspaceId, jobId)
+  const { code } = await uploadMediaFileNow(getWorkspaceId(), jobId)
   if (code === 0) {
     message.success('Upload Media File successfully')
     getPlans()
@@ -348,4 +344,4 @@ async function onUploadMediaFileNow(jobId: string) {
   text-align: start;
   color: #000;
 }
-</style>
+</style>

+ 17 - 17
Web/src/hooks/use-g-map-trajectory.ts

@@ -179,23 +179,23 @@ export function useGMapTrajectory() {
       })
       other.push(startMarker);
     }
-    // 绘制小飞机图标
-    if (list.length) {
-      const path = list[list.length - 1].paths;
-      const angle = deviceInfo.attitude_head;// 角度
-      const startIcon = new AMap.Icon({
-        size: new AMap.Size(40, 40),
-        image: droneIcon,
-        imageSize: new AMap.Size(40, 40)
-      })
-      const endMarker = new AMap.Marker({
-        position: new AMap.LngLat(path[0], path[path.length - 1]),
-        icon: startIcon,
-        offset: new AMap.Pixel(-20, -20),// 位置偏移
-        angle: angle,// 旋转角度
-      })
-      other.push(endMarker);
-    }
+    // // 绘制小飞机图标
+    // if (list.length) {
+    //   const path = list[list.length - 1].paths;
+    //   const angle = deviceInfo.attitude_head;// 角度
+    //   const startIcon = new AMap.Icon({
+    //     size: new AMap.Size(40, 40),
+    //     image: droneIcon,
+    //     imageSize: new AMap.Size(40, 40)
+    //   })
+    //   const endMarker = new AMap.Marker({
+    //     position: new AMap.LngLat(path[0], path[path.length - 1]),
+    //     icon: startIcon,
+    //     offset: new AMap.Pixel(-20, -20),// 位置偏移
+    //     angle: angle,// 旋转角度
+    //   })
+    //   other.push(endMarker);
+    // }
     root.$map.add(other)
     coverMap[sn] = [other]
   }

+ 3 - 2
Web/src/hooks/use-g-map-tsa.ts

@@ -1,11 +1,12 @@
 import store from '/@/store'
 import { getRoot } from '/@/root'
-import { ELocalStorageKey, EDeviceTypeName } from '/@/types'
+import { EDeviceTypeName } from '/@/types'
 import { getDeviceBySn } from '/@/api/manage'
 import { message } from 'ant-design-vue'
 import dockIcon from '/@/assets/icons/dock.png'
 import rcIcon from '/@/assets/icons/rc.png'
 import droneIcon from '/@/assets/icons/drone.png'
+import { getWorkspaceId } from '/@/utils/index'
 
 export function deviceTsaUpdate() {
   const root = getRoot()
@@ -75,7 +76,7 @@ export function deviceTsaUpdate() {
   }
 
   function addMarker(sn: string, lng?: number, lat?: number) {
-    getDeviceBySn(localStorage.getItem(ELocalStorageKey.WorkspaceId)!, sn)
+    getDeviceBySn(getWorkspaceId(), sn)
       .then(data => {
         if (data.code !== 0) {
           message.error(data.message)

+ 7 - 1
Web/src/hooks/use-mouse-tool.ts

@@ -136,7 +136,13 @@ export function useMouseTool() {
     const AMap = root.$aMap;
     const map = root.$map
 
-    map.remove(map.getLayers());
+    // 移除所有背景图层
+    map.getLayers().forEach((layer: any) => {
+      if (layer instanceof AMap.TileLayer) {
+        map.remove(layer);
+      }
+    });
+
     if (type === 0) {
       // 标准图层
       map.add(new AMap.createDefaultLayer());

+ 24 - 19
Web/src/pages/page-pilot/pilot-bind.vue

@@ -1,33 +1,36 @@
 <template>
   <a-layout class="flex-display" style="height: 100vh; background-color: white;">
-  <div class="height100 width100 flex-column flex-justify-start flex-align-start">
-    <a-row class="pt20 pl20" style="height: 45px; width: 100vw" align="middle">
-      <a-col :span="1">
-        <span style="color: #1fa3f6" class="fz26"><SendOutlined rotate="90" /></span>
-      </a-col>
-      <a-col :span="20">
-        <span class="fz20 pl5">{{ drone.data.model }}</span>
-      </a-col>
-      <a-col :span="3">
-        <span class="fz16" v-if="drone.data.bound_status" style="color: #737373">Bound</span>
-        <a-button type="primary" @click="onBindDevice" v-else>Bind</a-button>
-      </a-col>
-    </a-row>
-  </div>
+    <div class="height100 width100 flex-column flex-justify-start flex-align-start">
+      <a-row class="pt20 pl20" style="height: 45px; width: 100vw" align="middle">
+        <a-col :span="1">
+          <span style="color: #1fa3f6" class="fz26">
+            <SendOutlined rotate="90" />
+          </span>
+        </a-col>
+        <a-col :span="20">
+          <span class="fz20 pl5">{{ drone.data.model }}</span>
+        </a-col>
+        <a-col :span="3">
+          <span class="fz16" v-if="drone.data.bound_status" style="color: #737373">Bound</span>
+          <a-button type="primary" @click="onBindDevice" v-else>Bind</a-button>
+        </a-col>
+      </a-row>
+    </div>
   </a-layout>
 </template>
 
 <script lang="ts" setup>
-import { SendOutlined } from '@ant-design/icons-vue'
+import { reactive } from 'vue'
 import { message } from 'ant-design-vue'
-import { onMounted, reactive, ref } from 'vue'
+import { SendOutlined } from '@ant-design/icons-vue'
 import { BindBody, bindDevice } from '/@/api/manage'
-import apiPilot from '/@/api/pilot-bridge'
 import { getRoot } from '/@/root'
 import { ELocalStorageKey } from '/@/types'
 import { DeviceStatus } from '/@/types/device'
+import { getWorkspaceId } from '/@/utils'
 
 const root = getRoot()
+
 interface DeviceStatusData {
   data: DeviceStatus
 }
@@ -35,11 +38,11 @@ const drone = reactive<DeviceStatusData>({
   data: JSON.parse(localStorage.getItem(ELocalStorageKey.Device)!)
 })
 
-function onBindDevice () {
+function onBindDevice() {
   const bindParam: BindBody = {
     device_sn: drone.data.sn,
     user_id: localStorage.getItem(ELocalStorageKey.UserId)!,
-    workspace_id: localStorage.getItem(ELocalStorageKey.WorkspaceId)!
+    workspace_id: getWorkspaceId()
   }
   bindDevice(bindParam).then(bindRes => {
     if (bindRes.code !== 0) {
@@ -52,3 +55,5 @@ function onBindDevice () {
   })
 }
 </script>
+
+<style lang="scss" scoped></style>

+ 7 - 6
Web/src/pages/page-pilot/pilot-home.vue

@@ -4,7 +4,7 @@
       <div style="width:90%; height: 90%; margin: 4vh">
         <a-layout style="height: 20%; margin-top: 3vh; background-color: white; ">
           <a-layout-sider width="25%" theme="light" align="center">
-            <a-avatar :size="60" :src="cloudapi">
+            <a-avatar :size="60" :src="jkIcon">
             </a-avatar>
           </a-layout-sider>
           <a-layout-content style="margin-left: 1vw;">
@@ -79,7 +79,7 @@
         <a-row style="border-bottom: 1px solid #f4f8f9; height: 45px;" align="middle"
           v-if="device.data.online_status && device.data.sn">
           <a-col :span="1"></a-col>
-          <a-col :span="9">Aircraft Sn</a-col>
+          <a-col :span="9">飞行器SN</a-col>
           <a-col :span="13" class="flex-align-end flex-column">
             <span style="color: #737373">{{ device.data.sn }}</span>
           </a-col>
@@ -132,12 +132,13 @@ import { BindBody, bindDevice, getDeviceBySn, getPlatformInfo, getUserInfo, unbi
 import apiPilot, { ApiParam, MapParam, ThingParam, WsParam } from '/@/api/pilot-bridge'
 import { getRoot } from '/@/root'
 import { EBizCode, EComponentName, EDownloadOwner, ELocalStorageKey, ERouterName, EStatusValue } from '/@/types'
-import cloudapi from '/@/assets/icons/cloudapi.png'
-import { SwapOutlined, RightOutlined, CloudSyncOutlined, SyncOutlined } from '@ant-design/icons-vue'
+import jkIcon from '/@/assets/icons/jk_icon_white.svg'
+import { RightOutlined, CloudSyncOutlined, SyncOutlined } from '@ant-design/icons-vue'
 import { useMyStore } from '/@/store'
 import { DeviceStatus } from '/@/types/device'
 import { useConnectWebSocket } from '/@/hooks/use-connect-websocket'
 import { apis } from "/@/api/custom/index";
+import { getWorkspaceId } from '/@/utils'
 
 const root = getRoot()
 const gatewayState = ref<boolean>(localStorage.getItem(ELocalStorageKey.GatewayOnline) === 'true')
@@ -151,7 +152,7 @@ const mediaState = ref(EStatusValue.DISCONNECT)
 const waylineState = ref(EStatusValue.DISCONNECT)
 const workspaceName = ref<string>(localStorage.getItem(ELocalStorageKey.WorkspaceName)!)
 const username = ref(localStorage.getItem(ELocalStorageKey.Username)!)
-const wsId = ref(localStorage.getItem(ELocalStorageKey.WorkspaceId)!)
+const wsId = ref(getWorkspaceId())
 const components = apiPilot.init()
 const exitVisible = ref(false)
 const drawerVisible = ref(false)
@@ -574,4 +575,4 @@ function getDeviceInfo() {
   left: 15vw;
   line-height: 10vh;
 }
-</style>
+</style>

+ 3 - 3
Web/src/pages/page-pilot/pilot-index.vue

@@ -41,8 +41,8 @@ import djiLogo from '/@/assets/icons/dji_logo.png'
 const root = getRoot()
 
 const formState: UnwrapRef<LoginBody> = reactive({
-  username: 'pilot',
-  password: 'pilot123',
+  username: '',
+  password: '',
   flag: EUserType.Pilot,
   gateway_sn: apiPilot.getRemoteControllerSN()
 })
@@ -132,4 +132,4 @@ function verifyLicense() {
 .logo {
   color: $primary;
 }
-</style>
+</style>

+ 1 - 2
Web/src/pages/page-pilot/pilot-liveshare.vue

@@ -313,5 +313,4 @@ const onStop = () => {
 }
 </script>
 
-<style lang="scss" scoped>
-// @import '/@/styles/index.scss';</style>
+<style lang="scss" scoped></style>

+ 1 - 2
Web/src/pages/page-pilot/pilot-media.vue

@@ -74,5 +74,4 @@ onMounted(() => {
 })
 </script>
 
-<style lang="scss" scoped>
-// @import '/@/styles/index.scss';</style>
+<style lang="scss" scoped></style>

+ 4 - 2
Web/src/pages/page-web/home.vue

@@ -1,8 +1,8 @@
 <template>
   <a-layout class="width-100 flex-display" style="height: 100vh">
-    <Nav></Nav>
+    <Nav v-if="env !== 'subsystem'"></Nav>
     <a-layout>
-      <a-layout-header class="header">
+      <a-layout-header class="header" v-if="env !== 'subsystem'">
         <Topbar />
       </a-layout-header>
       <a-layout-content class="content">
@@ -26,6 +26,8 @@ interface FormState {
   password: string
 }
 
+const env = import.meta.env.VITE_ENV;
+
 const root = getRoot()
 
 const messageHandler = async (payload: any) => {

+ 5 - 6
Web/src/pages/page-web/projects/Firmwares.vue

@@ -79,17 +79,17 @@
   </div>
 </template>
 <script lang="ts" setup>
+import { onMounted, reactive, ref } from 'vue'
 import { message, notification } from 'ant-design-vue'
+import { UploadOutlined } from '@ant-design/icons-vue'
 import { TableState } from 'ant-design-vue/lib/table/interface'
-import { onMounted, reactive, ref } from 'vue'
 import { IPage } from '/@/api/http/type'
 import { getFirmwares, importFirmareFile } from '/@/api/manage'
 import DeviceFirmwareStatus from '/@/components/devices/DeviceFirmwareStatus.vue'
-import { ELocalStorageKey } from '/@/types'
-import { UploadOutlined } from '@ant-design/icons-vue'
 import { Firmware, FirmwareQueryParam, FirmwareStatusEnum, DeviceNameEnum, FirmwareUploadParam } from '/@/types/device-firmware'
 import { commonColor } from '/@/utils/color'
 import { bytesToSize } from '/@/utils/bytes'
+import { getWorkspaceId } from '/@/utils'
 import moment from 'moment'
 
 interface FirmwareData {
@@ -129,7 +129,6 @@ const pageParam: IPage = {
   total: 0,
   page_size: 50
 }
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
 
 const param = reactive<FirmwareQueryParam>({
   product_version: '',
@@ -152,7 +151,7 @@ function refreshData(page: Pagination) {
 }
 
 function getAllFirmwares(page: IPage) {
-  getFirmwares(workspaceId, page, param).then(res => {
+  getFirmwares(getWorkspaceId(), page, param).then(res => {
     const firmwareList: Firmware[] = res.data.list
     data.firmware = firmwareList
     paginationProp.total = res.data.pagination.total
@@ -232,7 +231,7 @@ const uploadFile = async () => {
       description: `[${file.name}] is uploading... `,
       duration: null
     })
-    importFirmareFile(workspaceId, fileData).then((res) => {
+    importFirmareFile(getWorkspaceId(), fileData).then((res) => {
       if (res.code === 0) {
         notification.success({
           message: `Uploaded  ${moment().format()}`,

+ 3 - 3
Web/src/pages/page-web/projects/dock.vue

@@ -36,12 +36,13 @@
 <script lang="ts" setup>
 import { onMounted, reactive, ref } from 'vue'
 import { deleteWaylineFile, downloadWaylineFile, getWaylineFiles } from '/@/api/wayline'
-import { EDeviceTypeName, ELocalStorageKey } from '/@/types'
+import { EDeviceTypeName } from '/@/types'
 import { RocketOutlined } from '@ant-design/icons-vue'
 import { Device } from '/@/types/device'
 import { useMyStore } from '/@/store'
 import { getBindingDevices } from '/@/api/manage'
 import { IPage } from '/@/api/http/type'
+import { getWorkspaceId } from '/@/utils'
 
 const store = useMyStore()
 
@@ -49,7 +50,6 @@ const docksData = reactive({
   data: [] as Device[]
 })
 
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
 const scorllHeight = ref()
 const canRefresh = ref(true)
 
@@ -80,7 +80,7 @@ async function getDocks() {
   }
   canRefresh.value = false
 
-  await getBindingDevices(workspaceId, body, EDeviceTypeName.Dock).then(res => {
+  await getBindingDevices(getWorkspaceId(), body, EDeviceTypeName.Dock).then(res => {
     if (res.code !== 0) {
       return
     }

+ 3 - 1
Web/src/pages/page-web/projects/layer/index.vue

@@ -21,7 +21,7 @@
           <span class="mr30">纬度:</span>
           {{ layerState.latitude || '--' }}
         </div>
-        <div class="element-item" v-if="layerState.element_from === 2">
+        <div class="element-item" v-if="layerState.element_from === 2 && layerState.currentType === geoType.Point">
           <span class="mr30">高度:</span>
           {{ layerState.height || '--' }}
         </div>
@@ -248,6 +248,8 @@ function selectLayer(keys: string[], e) {
       setBaseInfo()
       visible.value = true;
     } else if (type === 'PHOTO') {// 图片标注
+      const coordinates = selectedLayer.value.resource.content.geometry.coordinates
+      root.$map.setCenter(coordinates);
       state.photoDrawerVisible = true;
     }
   }

+ 15 - 7
Web/src/pages/page-web/projects/media/detail/components/FileInfo.vue

@@ -153,8 +153,9 @@ import Panoramic from '/@/components/panoramic/index.vue';
 import { useGMapManage } from '/@/hooks/use-g-map';
 import { apis } from '/@/api/custom';
 import { downloadFile } from '/@/utils/common';
-import { ELocalStorageKey } from '/@/types';
 import { downloadMediaFile } from '/@/api/media';
+import { wgs84togcj02 } from '/@/vendors/coordtransform'
+import { getWorkspaceId } from '/@/utils/index'
 
 interface Props {
   fileId: string,
@@ -186,6 +187,7 @@ const state = reactive({
     picture_time: '',
     longitude: '',// 经度
     latitude: '',// 纬度
+    coordinates: [],
   },
   map: null, // 高德地图实例
 })
@@ -198,7 +200,12 @@ const AmapHook = useGMapManage();
 const init = async () => {
   try {
     const res = await apis.fetchFileDetail(state.currentId);
-    state.info = res.data;
+    state.info = {
+      ...res.data,
+      longitude: res.data.longitude ? res.data.longitude.toFixed(6) : '',
+      latitude: res.data.latitude ? res.data.latitude.toFixed(6) : '',
+      coordinates: (res.data.longitude && res.data.latitude) ? wgs84togcj02(res.data.longitude, res.data.latitude) : [],
+    };
     if (res.data.media_type !== 4) {
       state.imgLoading = true;
       const img = new Image();
@@ -207,7 +214,7 @@ const init = async () => {
         state.imgLoading = false;
       };
     }
-    if (state.info.longitude && state.info.latitude) {
+    if (state.info.coordinates.length) {
       const AMap = await AmapHook.asyncInitMap();
       const map = new AMap.Map('photoPositionMap', {
         layers: [new AMap.TileLayer.Satellite()],// 卫星图-图层
@@ -215,14 +222,14 @@ const init = async () => {
         rotateEnable: true,// 开启地图旋转交互
         pitchEnable: true,// 开启地图倾斜交互
         zoom: 17, // 初始化地图层级
-        center: [state.info.longitude, state.info.latitude],// 中心点
+        center: state.info.coordinates,// 中心点
       })
       state.map = map;
       // 创建一个标记并将其添加到地图上
       new AMap.Marker({
         map: map,
         cursor: 'pointer',
-        position: [state.info.longitude, state.info.latitude],
+        position: state.info.coordinates,
       });
     }
   } catch (e) {
@@ -238,7 +245,7 @@ onMounted(async () => {
 const onClickDownload = async () => {
   state.downloadLoading = true;
   try {
-    const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '';
+    const workspaceId: string = getWorkspaceId();
     const res = await downloadMediaFile(workspaceId, state.info.file_id)
     if (!res) {
       return
@@ -278,7 +285,7 @@ const onClickDeleteMapElement = async () => {
 
 // 点击地图位置重置
 const onClickMapLocationReset = () => {
-  const markerPosition = [state.info.longitude, state.info.latitude];
+  const markerPosition = state.info.coordinates;
   const map: any = state.map;
   map.setCenter(markerPosition);
   map.setZoom(17);
@@ -316,6 +323,7 @@ const onClickSelected = async (id: string) => {
     picture_time: '',
     longitude: '',// 经度
     latitude: '',// 纬度
+    coordinates: [],
   }
   await init()
 }

+ 3 - 2
Web/src/pages/page-web/projects/media/detail/components/Search.vue

@@ -67,6 +67,7 @@ import { message } from 'ant-design-vue'
 import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue';
 import router from '/@/router';
 import { ELocalStorageKey } from '/@/types'
+import { getWorkspaceId } from '/@/utils/index'
 import moment from 'moment';
 
 interface Props {
@@ -88,14 +89,14 @@ const formModel = reactive({
   rangeDate: [],
   media_type: undefined,
   device_name: undefined,
-  search_info: '',
+  search_info: undefined,
 })
 
 const state = reactive({
   visible: false,
 })
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '';
+const workspaceId: string = getWorkspaceId();
 const dirId = router.currentRoute.value.params?.id;
 const uploadUrl = `/api/media/api/v1/files/${workspaceId}/file/${dirId}/upload`
 

+ 12 - 14
Web/src/pages/page-web/projects/media/detail/index.vue

@@ -102,7 +102,7 @@ import { apis } from '/@/api/custom';
 import router from '/@/router/index';
 import { downloadFile } from '/@/utils/common';
 import { downloadMediaFile } from '/@/api/media';
-import { ELocalStorageKey } from '/@/types';
+import { getWorkspaceId } from '/@/utils/index'
 
 interface State {
   query: any,
@@ -147,12 +147,12 @@ const paginationConfig = reactive({
   }
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const dirId = router.currentRoute.value.params?.id;
     const res = await apis.fetchFileListByFolder(dirId as string, {
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize,
     });
@@ -258,18 +258,19 @@ const onClickBatchDelete = async () => {
     id: canDeleteList.map(item => item.file_id).join(',')
   }
   await apis.batchDeletePicture(data);
-  await fetchList(state.query)
+  await fetchList()
 }
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
   state.query = query;
-  await fetchList(query);
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击返回
@@ -292,16 +293,14 @@ const onClickLookFile = (record: any) => {
 const fileInfoOnClickClose = async () => {
   state.fileId = '';
   state.fileInfoVisible = false;
-  const query = state.query;
-  await fetchList(query);
+  await fetchList();
 }
 
 // 点击在地图上加载
 const onClickCreateMapElement = async (id: string) => {
   try {
     await apis.createMapElement(id);
-    const query = state.query;
-    await fetchList(query);
+    await fetchList();
     message.success('在地图上加载成功');
   } catch (e: any) {
     console.error(e);
@@ -312,8 +311,7 @@ const onClickCreateMapElement = async (id: string) => {
 const onClickDeleteMapElement = async (id: string) => {
   try {
     await apis.deleteMapElement(id);
-    const query = state.query;
-    await fetchList(query);
+    await fetchList();
     message.success('在地图上取消加载成功');
   } catch (e: any) {
     console.error(e);
@@ -329,7 +327,7 @@ const onClickRechristen = (record: any) => {
 const onClickSave = async (record: any) => {
   delete state.editableData[record.file_id];
   await apis.updateFileName(record.file_id, { file_name: record.file_name })
-  await fetchList(state.query);
+  await fetchList();
 }
 
 // 点击删除
@@ -344,7 +342,7 @@ const onClickDelete = async (record: any) => {
 const onClickDownload = async (record: any) => {
   state.downloadLoading = true;
   try {
-    const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '';
+    const workspaceId: string = getWorkspaceId();
     const res = await downloadMediaFile(workspaceId, record.file_id)
     if (!res) {
       return

+ 8 - 4
Web/src/pages/page-web/projects/media/index/index.vue

@@ -91,6 +91,7 @@ import { downloadFile } from '/@/utils/common';
 import moment from 'moment';
 
 interface State {
+  query: any,
   listLoading: boolean,
   list: any[],
   selectedRowKeys: string[],
@@ -99,6 +100,7 @@ interface State {
 };
 
 const state: State = reactive({
+  query: undefined,
   listLoading: false,
   list: [],
   selectedRowKeys: [],
@@ -123,11 +125,11 @@ const paginationConfig = reactive({
   }
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const res = await apis.fetchMediaFileList({
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize,
     });
@@ -256,12 +258,14 @@ const onClickBatchDownload = async () => {
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击文件夹

+ 3 - 4
Web/src/pages/page-web/projects/member/components/Search.vue

@@ -7,8 +7,8 @@
     </a-col>
     <a-col>
       <a-form ref="formRef" layout="inline" :model="formModel" :colon="false">
-        <a-form-item name="keyword">
-          <a-input style="width: 200px;" placeholder="用户名称" v-model:value="formModel.keyword" />
+        <a-form-item name="search_info">
+          <a-input style="width: 200px;" placeholder="用户名称" v-model:value="formModel.search_info" />
         </a-form-item>
         <a-form-item>
           <a-button style="margin-right: 10px;" @click="handleClicSekarch">
@@ -44,8 +44,7 @@ const props = withDefaults(defineProps<Props>(), {
 const formRef = ref();
 
 const formModel = reactive({
-  device_name: undefined,
-  keyword: '',
+  search_info: undefined,
 })
 
 // 点击查询

+ 41 - 26
Web/src/pages/page-web/projects/member/index.vue

@@ -3,12 +3,15 @@
     <Search :onClickAddUser="onClickAddUser" :onClickSearch="onClickSearch" :onClickReset="onClickReset" />
     <div class="mediaList-table">
       <a-table :scroll="{ x: '100%', y: 500 }" rowKey="user_id" :loading="state.listLoading" :columns="columns"
-        @change="refreshData" :rowClassName="rowClassName" :dataSource="state.list" :pagination="paginationConfig">
+        :rowClassName="rowClassName" :dataSource="state.list" :pagination="paginationConfig">
         <!-- 操作 -->
         <template #action="{ record }">
-          <a-tooltip title="查看密码">
+          <a-tooltip title="显示密码" v-if="!record.password">
             <EyeOutlined style="color: #2d8cf0;" @click="onClickLookPassword(record.user_id)" />
           </a-tooltip>
+          <a-tooltip title="隐藏密码" v-else>
+            <EyeInvisibleOutlined style="color: #2d8cf0;" @click="onClickClosePassword(record.user_id)" />
+          </a-tooltip>
         </template>
       </a-table>
     </div>
@@ -19,12 +22,12 @@
 
 <script lang="ts" setup>
 import { onMounted, reactive } from 'vue';
-import { EyeOutlined } from '@ant-design/icons-vue';
+import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue';
 import Search from './components/Search.vue';
 import AddModal from './components/AddModal.vue';
 import { getAllUsersInfo } from '/@/api/manage';
 import { apis } from '/@/api/custom/index';
-import { ELocalStorageKey } from '/@/types';
+import { getWorkspaceId } from '/@/utils/index'
 
 export interface Member {
   user_id: string,
@@ -57,16 +60,22 @@ const paginationConfig = reactive({
   showSizeChanger: true,
   pageSize: 20,
   current: 1,
-  total: 0
+  total: 0,
+  onChange: async (current: number) => {
+    paginationConfig.current = current;
+    await fetchList();
+  },
+  onShowSizeChange: async (current: number, pageSize: number) => {
+    paginationConfig.pageSize = pageSize;
+    await fetchList();
+  }
 })
 
-const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
-
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
-    const res = await getAllUsersInfo(workspaceId, {
-      ...query,
+    const res = await getAllUsersInfo(getWorkspaceId(), {
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize,
     });
@@ -117,9 +126,9 @@ const columns = [
   {
     title: '密码',
     dataIndex: 'password',
-    width: 150,
+    width: 100,
     customRender: ({ text }: any) => {
-      return text || '--';
+      return text || '****';
     }
   },
   {
@@ -140,12 +149,6 @@ const rowClassName = (record: any, index: number) => {
   return className.toString().replaceAll(',', ' ')
 }
 
-const refreshData = async (page: any) => {
-  paginationConfig.current = page?.current!
-  paginationConfig.pageSize = page?.pageSize!
-  await fetchList();
-}
-
 // 点击添加飞行员
 const onClickAddUser = () => {
   state.visible = true;
@@ -155,7 +158,7 @@ const onClickAddUser = () => {
 const addModalOnClickConfirm = async (data: any) => {
   state.visible = false;
   await apis.AddPilot(data);
-  await fetchList(state.query)
+  await fetchList()
 }
 
 // 添加飞行员弹出层-点击取消
@@ -166,27 +169,39 @@ const addModalOnClickCancel = () => {
 // 点击搜索
 const onClickSearch = async (query: any) => {
   state.query = query;
-  await fetchList(query);
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击查看密码
 const onClickLookPassword = async (id: string) => {
   try {
     const res = await apis.fetchPilotPassword({ userId: id });
-    const item = state.list.find((item) => item.user_id === id);
-    if (!item) {
-      return;
-    }
-    item.password = res.data;
+    const list = state.list.map(item => {
+      return {
+        ...item,
+        password: item.user_id === id ? res.data : '',// 显示当前密码,关闭其他密码
+      }
+    })
+    state.list = list;
   } catch (e) {
     console.error(e);
   }
 }
+
+// 点击关闭密码
+const onClickClosePassword = (id: string) => {
+  const item = state.list.find((item) => item.user_id === id);
+  if (!item) {
+    return;
+  }
+  item.password = '';
+}
 </script>
 
 <style lang="scss">

+ 8 - 4
Web/src/pages/page-web/projects/trajectory/index.vue

@@ -28,11 +28,13 @@ import { wgs84togcj02 } from '/@/vendors/coordtransform'
 const store = useMyStore()
 
 interface State {
+  query: any,
   listLoading: boolean,
   list: any[],
 };
 
 const state: State = reactive({
+  query: undefined,
   listLoading: false,
   list: [],
 });
@@ -46,11 +48,11 @@ const paginationConfig = reactive({
   total: 0
 })
 
-const fetchList = async (query?: any) => {
+const fetchList = async () => {
   state.listLoading = true;
   try {
     const res = await apis.fetchTrajectoryList({
-      ...query,
+      ...state.query,
       page: paginationConfig.current,
       page_size: paginationConfig.pageSize
     });
@@ -150,12 +152,14 @@ const refreshData = async (page: any) => {
 
 // 点击搜索
 const onClickSearch = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击重置
 const onClickReset = async (query: any) => {
-  await fetchList(query);
+  state.query = query;
+  await fetchList();
 }
 
 // 点击查看轨迹

+ 4 - 3
Web/src/pages/page-web/projects/tsa.vue

@@ -96,7 +96,7 @@
                           style="width: 18px; height: 16px; text-align: center;">
                           <span :style="hmsInfo[dock.sn].length > 99 ? 'font-size: 11px' : 'font-size: 12px'">{{
                             hmsInfo[dock.sn].length
-                          }}</span>
+                            }}</span>
                           <span class="fz10">{{ hmsInfo[dock.sn].length > 99 ? '+' : '' }}</span>
                         </div>
                         <a-popover trigger="click" placement="bottom" color="black"
@@ -247,13 +247,14 @@ import { useMyStore } from '/@/store'
 import { getDeviceTopo, getUnreadDeviceHms, updateDeviceHms } from '/@/api/manage'
 import { EHmsLevel, ERouterName } from '/@/types/enums'
 import { OnlineDevice, EModeCode, EDockModeCode } from '/@/types/device'
-import { EDeviceTypeName, ELocalStorageKey } from '/@/types'
+import { EDeviceTypeName } from '/@/types'
 import { getRoot } from '/@/root'
 import { wgs84togcj02 } from '/@/vendors/coordtransform'
 import { getTextByModeCode } from '/@/utils/index'
+import { getWorkspaceId } from '/@/utils/index'
 
 const store = useMyStore()
-const workspaceId = ref(localStorage.getItem(ELocalStorageKey.WorkspaceId)!)
+const workspaceId = ref(getWorkspaceId())
 const osdVisible = computed(() => store.state.osdVisible)
 const hmsVisible = new Map<string, boolean>()
 const scorllHeight = ref()

+ 6 - 6
Web/src/pages/page-web/projects/wayline.vue

@@ -90,7 +90,7 @@
 import { message } from 'ant-design-vue'
 import { onMounted, reactive, ref } from 'vue'
 import { deleteWaylineFile, downloadWaylineFile, getWaylineFiles, importKmzFile } from '/@/api/wayline'
-import { ELocalStorageKey, ERouterName } from '/@/types'
+import { ERouterName } from '/@/types'
 import { EllipsisOutlined, RocketOutlined, CameraFilled, UserOutlined, SelectOutlined } from '@ant-design/icons-vue'
 import { DEVICE_NAME } from '/@/types/device'
 import { useMyStore } from '/@/store'
@@ -98,6 +98,7 @@ import { WaylineFile } from '/@/types/wayline'
 import { downloadFile } from '/@/utils/common'
 import { IPage } from '/@/api/http/type'
 import { getRoot } from '/@/root'
+import { getWorkspaceId } from '/@/utils/index'
 
 const loading = ref(false)
 const store = useMyStore()
@@ -112,7 +113,6 @@ const waylinesData = reactive({
 })
 
 const root = getRoot()
-const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)!
 const deleteTip = ref(false)
 const deleteWaylineId = ref<string>('')
 const canRefresh = ref(true)
@@ -140,7 +140,7 @@ function getWaylines() {
     return
   }
   canRefresh.value = false
-  getWaylineFiles(workspaceId, {
+  getWaylineFiles(getWorkspaceId(), {
     page: pagination.page,
     page_size: pagination.page_size,
     order_by: 'update_time desc'
@@ -162,7 +162,7 @@ function showWaylineTip(waylineId: string) {
 }
 
 function deleteWayline() {
-  deleteWaylineFile(workspaceId, deleteWaylineId.value).then(res => {
+  deleteWaylineFile(getWorkspaceId(), deleteWaylineId.value).then(res => {
     if (res.code === 0) {
       message.success('Wayline file deleted')
     }
@@ -177,7 +177,7 @@ function deleteWayline() {
 
 function downloadWayline(waylineId: string, fileName: string) {
   loading.value = true
-  downloadWaylineFile(workspaceId, waylineId).then(res => {
+  downloadWaylineFile(getWorkspaceId(), waylineId).then(res => {
     if (!res) {
       return
     }
@@ -223,7 +223,7 @@ const uploadFile = async () => {
   fileList.value.forEach(async (file: FileItem) => {
     const fileData = new FormData()
     fileData.append('file', file, file.name)
-    await importKmzFile(workspaceId, fileData).then((res) => {
+    await importKmzFile(getWorkspaceId(), fileData).then((res) => {
       if (res.code === 0) {
         message.success(`${file.name} file uploaded successfully`)
         canRefresh.value = true

+ 1 - 0
Web/src/router/index.ts

@@ -123,6 +123,7 @@ const updateToken = async (data: SignLoginApiParams) => {
 router.beforeEach(async (to, from, next) => {
   const { username, client_id, timestamp, workspace_id, workspace_name, signature } = to.query as any;
   if (username && client_id && timestamp && workspace_id && workspace_name && signature) {
+    localStorage.clear()
     await updateToken({ username, client_id, timestamp, workspace_id, workspace_name, signature })
     next();
   } else {

+ 7 - 0
Web/src/utils/index.ts

@@ -1,3 +1,5 @@
+import { ELocalStorageKey } from "../types";
+
 export const getTextByModeCode = (code: number) => {
     let text = '';
     switch (code) {
@@ -62,4 +64,9 @@ export const getTextByModeCode = (code: number) => {
             break;
     }
     return text;
+}
+
+// 获取项目ID
+export const getWorkspaceId = () => {
+    return localStorage.getItem(ELocalStorageKey.WorkspaceId) || '';
 }

+ 4 - 4
Web/src/utils/logger.ts

@@ -4,25 +4,25 @@
  * @param args
  */
 export function consoleLog(...args: Parameters<typeof console.log>) {
-  if (import.meta.env.VITE_ENV !== 'production') {
+  if (import.meta.env.VITE_ENV !== 'production' && import.meta.env.VITE_ENV !== 'subsystem') {
     window.console.log.apply(null, args)
   }
 }
 
 export function consoleWarn(...args: Parameters<typeof console.warn>) {
-  if (import.meta.env.VITE_ENV !== 'production') {
+  if (import.meta.env.VITE_ENV !== 'production' && import.meta.env.VITE_ENV !== 'subsystem') {
     console.warn.apply(null, args)
   }
 }
 
 export function consoleError(...args: Parameters<typeof console.error>) {
-  if (import.meta.env.VITE_ENV !== 'production') {
+  if (import.meta.env.VITE_ENV !== 'production' && import.meta.env.VITE_ENV !== 'subsystem') {
     console.error.apply(null, args)
   }
 }
 
 export function testEnvLog(...args: Parameters<typeof console.log>) {
-  if (import.meta.env.VITE_ENV !== 'production') {
+  if (import.meta.env.VITE_ENV !== 'production' && import.meta.env.VITE_ENV !== 'subsystem') {
     console.log.apply(null, args)
   }
 }