Browse Source

Merge remote-tracking branch 'origin/master'

S0025136190 1 year ago
parent
commit
c69199cbc9
36 changed files with 738 additions and 518 deletions
  1. 13 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementCircleGeometry.java
  2. 169 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementLineStringGeometry.java
  3. 52 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/common/AMap.java
  4. 46 51
      Backend/cloud-sdk/src/main/java/com/dji/sdk/common/CoordinateUtil.java
  5. 8 31
      Backend/sample/src/main/java/com/dji/sample/common/util/PicExifUtil.java
  6. 99 0
      Backend/sample/src/main/java/com/dji/sample/component/AuthInterceptor.java
  7. 10 0
      Backend/sample/src/main/java/com/dji/sample/configuration/CustomConfiguration.java
  8. 0 29
      Backend/sample/src/main/java/com/dji/sample/manage/model/common/AMap.java
  9. 1 1
      Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceRedisService.java
  10. 1 1
      Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceService.java
  11. 3 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/IUserService.java
  12. 1 1
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceRedisServiceImpl.java
  13. 1 1
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
  14. 5 8
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/SDKDeviceService.java
  15. 4 3
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
  16. 1 0
      Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
  17. 2 1
      Backend/sample/src/main/resources/application.yml
  18. 1 1
      Web/index.html
  19. 158 112
      Web/package-lock.json
  20. 1 0
      Web/package.json
  21. 0 11
      Web/public/EasyPlayer-element.min.js
  22. BIN
      Web/public/EasyPlayer.wasm
  23. 0 0
      Web/public/liveplayer-lib.min.js
  24. 24 4
      Web/src/api/http/request.ts
  25. 18 129
      Web/src/components/LayersTree.vue
  26. 3 3
      Web/src/components/deviceLive/index.vue
  27. 0 15
      Web/src/components/easyPlayer/index.vue
  28. 17 0
      Web/src/components/livePlayer/index.vue
  29. 18 2
      Web/src/hooks/use-g-map-trajectory.ts
  30. 6 2
      Web/src/pages/page-web/projects/layer/index.vue
  31. 3 72
      Web/src/pages/page-web/projects/member/index.vue
  32. 7 1
      Web/src/pages/page-web/projects/trajectory/index.vue
  33. 25 18
      Web/src/pages/page-web/projects/tsa.vue
  34. 3 2
      Web/src/pages/page-web/projects/workspace.vue
  35. 17 5
      Web/src/router/index.ts
  36. 21 14
      Web/src/types/mapLayer.ts

+ 13 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementCircleGeometry.java

@@ -61,4 +61,17 @@ public class ElementCircleGeometry extends ElementPointGeometry {
         this.radius = radius;
         return this;
     }
+
+    /**
+     * Calculates the area of the circle.
+     *
+     * @return The area of the circle in square units.
+     */
+    public double calculateArea() {
+        if (radius != null) {
+            return Math.PI * Math.pow(radius, 2);
+        } else {
+            throw new IllegalStateException("Radius is not set.");
+        }
+    }
 }

+ 169 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementLineStringGeometry.java

@@ -1,5 +1,7 @@
 package com.dji.sdk.cloudapi.map;
 
+import com.dji.sdk.common.AMap;
+import com.dji.sdk.common.CoordinateUtil;
 import com.dji.sdk.exception.CloudSDKErrorEnum;
 import com.dji.sdk.exception.CloudSDKException;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -78,4 +80,171 @@ public class ElementLineStringGeometry extends ElementGeometryType {
     public String getType() {
         return type;
     }
+
+    /**
+     * Calculates the distance between two points on Earth using the Haversine formula.
+     *
+     * @return The distance in meters.
+     */
+    public double getCalculateSegmentLength() {
+        List<ElementCoordinate> list = convertToList();
+        ElementCoordinate coord1 = list.get(0);
+        ElementCoordinate coord2 = list.get(1);
+        final double EARTH_RADIUS = 6371000; // Earth radius in meters
+        double lat1 = Math.toRadians(coord1.getLatitude());
+        double lon1 = Math.toRadians(coord1.getLongitude());
+        double lat2 = Math.toRadians(coord2.getLatitude());
+        double lon2 = Math.toRadians(coord2.getLongitude());
+
+        double dLat = lat2 - lat1;
+        double dLon = lon2 - lon1;
+
+        double a = Math.pow(Math.sin(dLat / 2), 2) +
+                Math.cos(lat1) * Math.cos(lat2) *
+                        Math.pow(Math.sin(dLon / 2), 2);
+        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+
+        return EARTH_RADIUS * c;
+    }
+
+    public double calculateSegmentLength(ElementCoordinate coord1, ElementCoordinate coord2) {
+        final double EARTH_RADIUS = 6371000; // Earth radius in meters
+        double lat1 = Math.toRadians(coord1.getLatitude());
+        double lon1 = Math.toRadians(coord1.getLongitude());
+        double lat2 = Math.toRadians(coord2.getLatitude());
+        double lon2 = Math.toRadians(coord2.getLongitude());
+
+        double dLat = lat2 - lat1;
+        double dLon = lon2 - lon1;
+
+        double a = Math.pow(Math.sin(dLat / 2), 2) +
+                Math.cos(lat1) * Math.cos(lat2) *
+                        Math.pow(Math.sin(dLon / 2), 2);
+        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+
+        return EARTH_RADIUS * c;
+    }
+
+    /**
+     * Calculates the distance between two points on Earth using Vincenty's formula.
+     *
+     * @param coord1 The first coordinate.
+     * @param coord2 The second coordinate.
+     * @return The distance in meters.
+     */
+    private double calculateSegmentLengthVincenty(ElementCoordinate coord1, ElementCoordinate coord2) {
+        final double EARTH_RADIUS_EQUATOR = 6378137; // Semi-major axis of the WGS84 ellipsoid
+        final double EARTH_RADIUS_POLE = 6356752.314245; // Semi-minor axis of the WGS84 ellipsoid
+        final double FLATTENING = (EARTH_RADIUS_EQUATOR - EARTH_RADIUS_POLE) / EARTH_RADIUS_EQUATOR; // Flattening factor
+        final double EARTH_RADIUS = (EARTH_RADIUS_EQUATOR + EARTH_RADIUS_POLE) / 2.0;
+
+        double lat1 = Math.toRadians(coord1.getLatitude());
+        double lon1 = Math.toRadians(coord1.getLongitude());
+        double lat2 = Math.toRadians(coord2.getLatitude());
+        double lon2 = Math.toRadians(coord2.getLongitude());
+
+        double U1 = Math.atan((1 - FLATTENING) * Math.tan(lat1));
+        double U2 = Math.atan((1 - FLATTENING) * Math.tan(lat2));
+        double L = lon2 - lon1;
+        double lambda = L;
+        double lambdaP = 0.0;
+        double iterLimit = 100;
+        double sinLambda = 0.0;
+        double cosLambda = 0.0;
+        double sinSigma = 0.0;
+        double cosSigma = 0.0;
+        double sigma = 0.0;
+        double sinAlpha = 0.0;
+        double cosSqAlpha = 0.0;
+        double cos2SigmaM = 0.0;
+        double uSquared = 0.0;
+        double A = 0.0;
+        double B = 0.0;
+        double deltaSigma = 0.0;
+        double sinU1 = Math.sin(U1);
+        double cosU1 = Math.cos(U1);
+        double sinU2 = Math.sin(U2);
+        double cosU2 = Math.cos(U2);
+
+        do {
+            sinLambda = Math.sin(lambda);
+            cosLambda = Math.cos(lambda);
+            sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +
+                    (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
+            if (sinSigma == 0.0) {
+                return 0.0; // coincident points
+            }
+            cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
+            sigma = Math.atan2(sinSigma, cosSigma);
+            sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
+            cosSqAlpha = 1 - sinAlpha * sinAlpha;
+            cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
+            if (Double.isNaN(cos2SigmaM)) {
+                cos2SigmaM = 0; // equatorial line: cosSqAlpha = 0 (§6)
+            }
+            uSquared = cosSqAlpha * (EARTH_RADIUS_EQUATOR * EARTH_RADIUS_EQUATOR - EARTH_RADIUS_POLE * EARTH_RADIUS_POLE) / (EARTH_RADIUS_POLE * EARTH_RADIUS_POLE);
+            A = 1 + uSquared / 16384 * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)));
+            B = uSquared / 1024 * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)));
+            deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
+                    B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
+            lambdaP = lambda;
+            lambda = L + (1 - B) * FLATTENING * sinAlpha * (sigma + deltaSigma); // Use the flattening factor here
+        } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
+
+        if (iterLimit == 0) {
+            return 0.0; // formula failed to converge
+        }
+
+        double s = EARTH_RADIUS * (sigma - deltaSigma);
+
+        return s;
+    }
+
+    /**
+     * Calculates the total length of the line string.
+     *
+     * @return The total length in meters.
+     */
+    public double getCalculateTotalLength() {
+        double totalLength = 0.0;
+        List<ElementCoordinate> coordinateList = convertToList();
+
+        for (int i = 0; i < coordinateList.size() - 1; i++) {
+            ElementCoordinate coord1 = coordinateList.get(i);
+            AMap aMap = CoordinateUtil.transform(coord1.getLongitude(),coord1.getLatitude());
+            coord1.setLongitude(aMap.getLongitude());
+            coord1.setLatitude(aMap.getLatitude());
+
+            ElementCoordinate coord2 = coordinateList.get(i + 1);
+            aMap = CoordinateUtil.transform(coord2.getLongitude(),coord2.getLatitude());
+            coord2.setLongitude(aMap.getLongitude());
+            coord2.setLatitude(aMap.getLatitude());
+
+            totalLength += calculateSegmentLengthVincenty(coord1, coord2);
+        }
+
+        return totalLength;
+    }
+
+    public static void main(String[] args) {
+        ElementLineStringGeometry lineStringGeometry = new ElementLineStringGeometry();
+        AMap aMap = CoordinateUtil.transform(121.59529228016724, 31.2771648028396);
+        AMap aMap2 = CoordinateUtil.transform(121.55949257988347, 31.27563389661576);
+        AMap aMap3 = CoordinateUtil.transform(121.55866186357967, 31.27687211836336);
+        Double[][] coordinates = new Double[][]{
+                {aMap.getLongitude(),aMap.getLatitude()},
+                {aMap2.getLongitude(),aMap2.getLatitude()},
+                {aMap3.getLongitude(),aMap3.getLatitude()}
+//                {121.59529228016724, 31.2771648028396},
+//                {121.55949257988347, 31.27563389661576},
+//                {121.55866186357967, 31.27687211836336}
+
+
+        };
+        lineStringGeometry.setCoordinates(coordinates);
+
+        double totalLength = lineStringGeometry.getCalculateTotalLength();
+        System.out.println("The total length of the line string is: " + totalLength + " meters");
+    }
+
 }

+ 52 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/common/AMap.java

@@ -0,0 +1,52 @@
+package com.dji.sdk.common;
+
+
+/**
+ * 高德经纬度类
+ * @author hqjiang
+ * @version 1.0
+ * @date 2024/7/2
+ */
+public class AMap {
+    /**
+     * 经度
+     */
+    private double longitude;
+
+    /**
+     * 维度
+     */
+    private double latitude;
+
+    public AMap(double wgLon, double wgLat) {
+        this.longitude = wgLon;
+        this.latitude = wgLat;
+    }
+
+
+
+
+    @Override
+    public String toString() {
+        return "AMap{" +
+                "longitude=" + longitude +
+                ", latitude=" + latitude +
+                '}';
+    }
+
+    public double getLongitude() {
+        return longitude;
+    }
+
+    public void setLongitude(double longitude) {
+        this.longitude = longitude;
+    }
+
+    public void setLatitude(double latitude) {
+        this.latitude = latitude;
+    }
+
+    public double getLatitude() {
+        return latitude;
+    }
+}

+ 46 - 51
Backend/sample/src/main/java/com/dji/sample/common/util/CoordinateUtil.java → Backend/cloud-sdk/src/main/java/com/dji/sdk/common/CoordinateUtil.java

@@ -1,14 +1,6 @@
-package com.dji.sample.common.util;
+package com.dji.sdk.common;
 
 
-import com.dji.sample.manage.model.common.AMap;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
 import org.springframework.stereotype.Component;
 
 import java.text.DecimalFormat;
@@ -19,56 +11,59 @@ import java.text.DecimalFormat;
  * @date 2024/7/2
  */
 
-@Slf4j
 @Component
 public class CoordinateUtil {
     private static final String GAODE_API_URL = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=经度,纬度&coordsys=gps&key=96d7df07675b274a4078b107e56b2a4a";// + AMapProperties.key;
 
     public static void main(String[] args) {
-        double lon = 116.481499;
-        double lat = 39.990475;
-        log.info("GPS转高德之前:" + lon + "," + lat);
-        AMap aMap = CoordinateUtil.convertToAMapCoord(lon,lat);
-        log.info("GPS转高德之后(WEBAPI):" + aMap.getLongitude() + "," + aMap.getLatitude());
-        aMap = transform(lon,lat);
-        log.info("GPS转高德之后:" + aMap.getLongitude() + "," + aMap.getLatitude());
+
+//        {121.59529228016724, 31.2771648028396},
+//        {121.55949257988347, 31.27563389661576},
+//        {121.55866186357967, 31.27687211836336}
+        double lon = 121.55866186357967;
+        double lat = 31.27687211836336;
+//        log.info("GPS转高德之前:" + lon + "," + lat);
+//        AMap aMap = CoordinateUtil.convertToAMapCoord(lon,lat);
+//        log.info("GPS转高德之后(WEBAPI):" + aMap.getLongitude() + "," + aMap.getLatitude());
+        AMap aMap = transform(lon,lat);
+        //log.info("GPS转高德之后:" + aMap.getLongitude() + "," + aMap.getLatitude());
         /**
          * 高德API(https://lbs.amap.com/api/webservice/guide/api/convert)经纬度转换之后.
          * 两者误差不是很大
          */
     }
 
-    public static AMap convertToAMapCoord(double originalLng, double originalLat) {
-        String response = sendRequest(originalLng,originalLat);
-        log.info("GPS转高德之后(WEBAPI):" + response);
-        JsonElement element = JsonParser.parseString(response);
-        String status = element.getAsJsonObject().get("status").getAsString();
-        if("1".equals(status)) {
-            String locations = element.getAsJsonObject().get("locations").getAsString();
-            String[] locArray =  locations.split(",");
-            double lon = Double.parseDouble(String.format("%.5f", Double.parseDouble(locArray[0])));
-            double lat = Double.parseDouble(String.format("%.5f", Double.parseDouble(locArray[1])));
-            return new AMap(lon, lat);
-        }
-
-        return null;
-
-    }
-
-    private static String sendRequest(double longitude, double latitude) {
-        HttpGet request = new HttpGet(GAODE_API_URL
-                .replace("经度", Double.toString(longitude))
-                .replace("纬度", Double.toString(latitude)));
-
-        try {
-            org.apache.http.client.HttpClient client = HttpClients.createDefault();
-            HttpResponse httpResponse = client.execute(request);
-            return EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
+//    public static AMap convertToAMapCoord(double originalLng, double originalLat) {
+//        String response = sendRequest(originalLng,originalLat);
+//        log.info("GPS转高德之后(WEBAPI):" + response);
+//        JsonElement element = JsonParser.parseString(response);
+//        String status = element.getAsJsonObject().get("status").getAsString();
+//        if("1".equals(status)) {
+//            String locations = element.getAsJsonObject().get("locations").getAsString();
+//            String[] locArray =  locations.split(",");
+//            double lon = Double.parseDouble(String.format("%.5f", Double.parseDouble(locArray[0])));
+//            double lat = Double.parseDouble(String.format("%.5f", Double.parseDouble(locArray[1])));
+//            return new AMap(lon, lat);
+//        }
+//
+//        return null;
+//
+//    }
+
+//    private static String sendRequest(double longitude, double latitude) {
+//        HttpGet request = new HttpGet(GAODE_API_URL
+//                .replace("经度", Double.toString(longitude))
+//                .replace("纬度", Double.toString(latitude)));
+//
+//        try {
+//            org.apache.http.client.HttpClient client = HttpClients.createDefault();
+//            HttpResponse httpResponse = client.execute(request);
+//            return EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//            return null;
+//        }
+//    }
 
     /**
      * 椭球参数
@@ -117,9 +112,9 @@ public class CoordinateUtil {
         double transLat = wgLat + dLat;
         double transLon = wgLon + dLon;
 
-        DecimalFormat df = new DecimalFormat("#.000000");
-        transLon = Double.parseDouble(df.format(transLon));
-        transLat = Double.parseDouble(df.format(transLat));
+//        DecimalFormat df = new DecimalFormat("#.000000");
+//        transLon = Double.parseDouble(df.format(transLon));
+//        transLat = Double.parseDouble(df.format(transLat));
 
 
         return new AMap(transLon, transLat);

+ 8 - 31
Backend/sample/src/main/java/com/dji/sample/common/util/PicExifUtil.java

@@ -3,10 +3,8 @@ package com.dji.sample.common.util;
 
 import com.dji.sample.component.oss.model.OssConfiguration;
 import com.dji.sample.component.oss.service.impl.OssServiceContext;
-import com.dji.sample.manage.model.common.AMap;
 import com.dji.sample.media.model.MediaExifDTO;
 import com.drew.imaging.ImageMetadataReader;
-import com.drew.imaging.mp4.Mp4MetadataReader;
 import com.drew.metadata.Metadata;
 import com.drew.metadata.exif.*;
 import com.drew.metadata.file.FileTypeDirectory;
@@ -24,7 +22,9 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.stereotype.Component;
 
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
 import java.text.DecimalFormat;
 
 /**
@@ -56,28 +56,12 @@ public class PicExifUtil {
         return getPicExif(inputStream,objectKey.endsWith(MP4));
     }
 
-    public static void main(String[] args) {
-        //全景图
-//        File file = new File("C:\\Users\\86139\\Desktop\\DJI_20240709132723_0001_V.JPG");
-        File file = new File("C:\\Users\\86139\\Desktop\\DJI_20231011154344_0003_V.jpg");
-
-
-//        File file = new File("C:\\Users\\86139\\Desktop\\DJI_20240711181155_0001_V.JPG");
-        try {
-            InputStream inputStream = new FileInputStream(file);
-            MediaExifDTO mediaExifDTO = getPicExif(inputStream,false);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-    }
-
     public static MediaExifDTO getPicExif(InputStream inputStream,boolean isVideo) {
         try {
             MediaExifDTO.MediaExifDTOBuilder builder = MediaExifDTO.builder();
-
+            Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
             //视频
             if(isVideo) {
-                Metadata metadata = Mp4MetadataReader.readMetadata(inputStream);
                 //视频宽高
                 Mp4VideoDirectory mp4VideoDirectory = metadata.getFirstDirectoryOfType(Mp4VideoDirectory.class);
                 builder.imageWidth(mp4VideoDirectory.getInteger(Mp4VideoDirectory.TAG_WIDTH));
@@ -90,13 +74,7 @@ public class PicExifUtil {
                 builder.durationSeconds(mp4Directory.getInteger(Mp4Directory.TAG_DURATION_SECONDS));
                 builder.createTime(mp4Directory.getDate(Mp4Directory.TAG_CREATION_TIME).getTime());
 
-                //媒体类型
-                FileTypeDirectory fileTypeDirectory = metadata.getFirstDirectoryOfType(FileTypeDirectory.class);
-                builder.mediaType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE));
-                builder.pictureType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME));
-
             } else {
-                Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
                 //经纬度
                 GpsDirectory gpsDirectory = metadata.getFirstDirectoryOfType(GpsDirectory.class);
                 builder.absoluteAltitude(gpsDirectory.getDouble(GpsDirectory.TAG_ALTITUDE));
@@ -112,12 +90,11 @@ public class PicExifUtil {
                 ExifSubIFDDirectory exifSubIFDDirectory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
                 builder.imageWidth(exifSubIFDDirectory.getInteger(ExifSubIFDDirectory.TAG_EXIF_IMAGE_WIDTH));
                 builder.imageHeight(exifSubIFDDirectory.getInteger(ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT));
-                //媒体类型
-                FileTypeDirectory fileTypeDirectory = metadata.getFirstDirectoryOfType(FileTypeDirectory.class);
-                builder.mediaType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE));
-                builder.pictureType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME));
             }
-
+            //媒体类型
+            FileTypeDirectory fileTypeDirectory = metadata.getFirstDirectoryOfType(FileTypeDirectory.class);
+            builder.mediaType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE));
+            builder.pictureType(fileTypeDirectory.getString(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME));
             return builder.build();
         } catch (Exception e) {
             e.printStackTrace();

+ 99 - 0
Backend/sample/src/main/java/com/dji/sample/component/AuthInterceptor.java

@@ -1,9 +1,17 @@
 package com.dji.sample.component;
 
+import cn.hutool.Hutool;
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.digest.DigestUtil;
 import com.dji.sample.common.error.CommonErrorEnum;
 import com.dji.sample.common.model.CustomClaim;
 import com.dji.sample.common.util.JwtUtil;
+import com.dji.sample.configuration.CustomConfiguration;
+import com.dji.sample.manage.model.entity.UserEntity;
+import com.dji.sample.manage.service.IUserService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Component;
@@ -13,7 +21,14 @@ import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 
 @Slf4j
 @Component
@@ -23,6 +38,16 @@ public class AuthInterceptor implements HandlerInterceptor {
 
     public static final String TOKEN_CLAIM = "customClaim";
 
+    public static final String SIGN = "sign";
+
+    public static final String KEY = "key";
+
+    public static final String USER_CODE = "userCode";
+
+    @Autowired
+    private IUserService userService;
+
+
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         String uri = request.getRequestURI();
@@ -33,6 +58,46 @@ public class AuthInterceptor implements HandlerInterceptor {
             return false;
         }
         String token = request.getHeader(PARAM_TOKEN);
+        String sign = request.getHeader(SIGN);
+        if (StringUtils.hasText(sign)) {
+            if ("GET".equalsIgnoreCase(request.getMethod())) {
+                // Get sign from the query string
+                String key = request.getHeader(KEY);
+                String userCode = request.getHeader(USER_CODE);
+                UserEntity userEntity = userService.getUserByUsername(userCode);
+                if (userEntity == null) {
+                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                    log.error(CommonErrorEnum.NO_TOKEN.getMessage());
+                    return false;
+                }
+                byte[] decodedBytes = Base64.decode(key);
+                String decodedString = new String(decodedBytes);
+                // Step 1: Parse the date-time string
+                String dateTimeString = extractDateTime(decodedString,userCode);
+                // Step 2: Convert the date-time string to LocalDateTime
+                LocalDateTime dateTime = parseTimestamp(dateTimeString);
+                // Step 3: Calculate the difference between the current time and the extracted time
+                LocalDateTime currentTime = LocalDateTime.now();
+                Duration duration = Duration.between(dateTime, currentTime);
+
+                // Step 4: Check if the difference is greater than 5 minutes
+                boolean isMoreThanFiveMinutes = duration.toMinutes() > 5;
+                if (isMoreThanFiveMinutes) {
+                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                    log.error(CommonErrorEnum.NO_TOKEN.getMessage());
+                    return false;
+                }
+                String generatedHash = DigestUtil.sha256Hex(userCode+decodedString+ CustomConfiguration.signKey);
+                // Verify the hash
+                boolean isMatch = StrUtil.equals(generatedHash, sign);
+                if(!isMatch) {
+                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                    log.error(CommonErrorEnum.NO_TOKEN.getMessage());
+                    return false;
+                }
+                return true;
+            }
+        }
         // Check if the token exists.
         if (!StringUtils.hasText(token)) {
             response.setStatus(HttpStatus.UNAUTHORIZED.value());
@@ -57,4 +122,38 @@ public class AuthInterceptor implements HandlerInterceptor {
         // Delete the custom data in the request after the request ends.
         request.removeAttribute(TOKEN_CLAIM);
     }
+
+    private static String extractDateTime(String inputString,String userCode) {
+        // Step 1: Define the pattern
+        Pattern pattern = Pattern.compile(userCode+"(\\d+)"+userCode);
+        // Step 2: Create a matcher for the input string
+        Matcher matcher = pattern.matcher(inputString);
+        // Step 3: Check if the pattern matches
+        if (matcher.find()) {
+            // Step 4: Extract the number
+            String number = matcher.group(1); // group(1) refers to the first capturing group
+            return number;
+        } else {
+            return null;
+        }
+    }
+
+    private static LocalDateTime parseTimestamp(String timestampString) {
+        // Convert the timestamp to LocalDateTime
+        long timestamp = Long.parseLong(timestampString);
+        return LocalDateTime.ofInstant(
+                Instant.ofEpochSecond(timestamp),
+                ZoneId.systemDefault()
+        );
+    }
+
+    public static void main(String[] args) {
+        String aa = "adminPC1722596411adminPC";
+        String ab = Base64.encode(aa);
+        String ac =DigestUtil.sha256Hex("adminPC"+aa+CustomConfiguration.signKey);
+        System.out.println("base:"+ab+"ac"+ac);
+        System.out.println("adminPC"+aa+CustomConfiguration.signKey);
+        System.out.println("adminPC"+aa+CustomConfiguration.signKey);
+        System.out.println(DigestUtil.sha256Hex("adminPCadminPC1722596411adminPC7e92430eb1f949e9a750fadf68777c44"));
+    }
 }

+ 10 - 0
Backend/sample/src/main/java/com/dji/sample/configuration/CustomConfiguration.java

@@ -24,6 +24,16 @@ public class CustomConfiguration {
      */
     public static String key;
 
+    public void setSignKey(String signKey) {
+        CustomConfiguration.signKey = signKey;
+    }
+
+    /**
+     * 加密密钥
+     * @param frequency
+     */
+    public static String signKey;
+
     public void setFrequency(int frequency) {
         CustomConfiguration.frequency = frequency;
     }

+ 0 - 29
Backend/sample/src/main/java/com/dji/sample/manage/model/common/AMap.java

@@ -1,29 +0,0 @@
-package com.dji.sample.manage.model.common;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 高德经纬度类
- * @author hqjiang
- * @version 1.0
- * @date 2024/7/2
- */
-@Data
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class AMap {
-    /**
-     * 经度
-     */
-    private double longitude;
-
-    /**
-     * 维度
-     */
-    private double latitude;
-
-}

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

@@ -1,7 +1,7 @@
 package com.dji.sample.manage.service;
 
 import com.dji.sample.component.mqtt.model.EventsReceiver;
-import com.dji.sample.manage.model.common.AMap;
+import com.dji.sdk.common.AMap;
 import com.dji.sample.manage.model.dto.DeviceDTO;
 import com.dji.sample.map.model.dto.FlightTaskDTO;
 import com.dji.sample.map.model.dto.FlightTrackDTO;

+ 1 - 1
Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceService.java

@@ -2,7 +2,7 @@ package com.dji.sample.manage.service;
 
 import com.dji.sample.common.model.CustomClaim;
 import com.dji.sample.component.websocket.model.BizCodeEnum;
-import com.dji.sample.manage.model.common.AMap;
+import com.dji.sdk.common.AMap;
 import com.dji.sample.manage.model.dto.DeviceDTO;
 import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO;
 import com.dji.sample.manage.model.dto.TopologyDeviceDTO;

+ 3 - 0
Backend/sample/src/main/java/com/dji/sample/manage/service/IUserService.java

@@ -2,6 +2,7 @@ package com.dji.sample.manage.service;
 
 import com.dji.sample.manage.model.dto.UserDTO;
 import com.dji.sample.manage.model.dto.UserListDTO;
+import com.dji.sample.manage.model.entity.UserEntity;
 import com.dji.sdk.common.HttpResultResponse;
 import com.dji.sdk.common.PaginationData;
 
@@ -53,4 +54,6 @@ public interface IUserService {
      * @return
      */
     Boolean updateUserWorkspace(String newWorkspaceId, String userId);
+
+    UserEntity getUserByUsername(String username);
 }

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

@@ -3,7 +3,7 @@ package com.dji.sample.manage.service.impl;
 import com.dji.sample.component.mqtt.model.EventsReceiver;
 import com.dji.sample.component.redis.RedisConst;
 import com.dji.sample.component.redis.RedisOpsUtils;
-import com.dji.sample.manage.model.common.AMap;
+import com.dji.sdk.common.AMap;
 import com.dji.sample.manage.model.dto.DeviceDTO;
 import com.dji.sample.manage.service.ICapacityCameraService;
 import com.dji.sample.manage.service.IDeviceRedisService;

+ 1 - 1
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java

@@ -10,7 +10,7 @@ import com.dji.sample.component.websocket.model.BizCodeEnum;
 import com.dji.sample.component.websocket.service.IWebSocketMessageService;
 import com.dji.sample.control.model.enums.DroneAuthorityEnum;
 import com.dji.sample.manage.dao.IDeviceMapper;
-import com.dji.sample.manage.model.common.AMap;
+import com.dji.sdk.common.AMap;
 import com.dji.sample.manage.model.dto.*;
 import com.dji.sample.manage.model.entity.DeviceEntity;
 import com.dji.sample.manage.model.enums.DeviceFirmwareStatusEnum;

+ 5 - 8
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/SDKDeviceService.java

@@ -1,12 +1,13 @@
 package com.dji.sample.manage.service.impl;
 
 import cn.hutool.core.date.DateUtil;
-import com.dji.sample.common.util.CoordinateUtil;
+import com.dji.sample.map.model.dto.FlightTrackDTO;
+import com.dji.sdk.common.CoordinateUtil;
 import com.dji.sample.common.util.UserRequest;
 import com.dji.sample.component.websocket.model.BizCodeEnum;
 import com.dji.sample.component.websocket.service.IWebSocketMessageService;
 import com.dji.sample.configuration.CustomConfiguration;
-import com.dji.sample.manage.model.common.AMap;
+import com.dji.sdk.common.AMap;
 import com.dji.sample.manage.model.dto.DeviceDTO;
 import com.dji.sample.manage.model.dto.DevicePayloadReceiver;
 import com.dji.sample.manage.model.enums.DeviceFirmwareStatusEnum;
@@ -16,7 +17,6 @@ import com.dji.sample.manage.service.IDevicePayloadService;
 import com.dji.sample.manage.service.IDeviceRedisService;
 import com.dji.sample.manage.service.IDeviceService;
 import com.dji.sample.map.model.dto.FlightTaskDTO;
-import com.dji.sample.map.model.dto.FlightTrackDTO;
 import com.dji.sample.map.model.entity.FlightTaskEntity;
 import com.dji.sample.map.model.entity.FlightTrackEntity;
 import com.dji.sample.map.model.enums.FlightPointTypeEnum;
@@ -34,7 +34,6 @@ import com.dji.sdk.mqtt.status.TopicStatusRequest;
 import com.dji.sdk.mqtt.status.TopicStatusResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.support.AbstractCacheManager;
 import org.springframework.messaging.MessageHeaders;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -546,11 +545,9 @@ public class SDKDeviceService extends AbstractDeviceService {
             return;
         }
 
+        AMap aMap = new AMap(CoordinateUtil.checkValidVal(request.getData().getHomeLongitude()),CoordinateUtil.checkValidVal(request.getData().getHomeLatitude()));
         //home点更新
-        deviceService.updateHome(deviceOpt.get(), AMap.builder()
-                .longitude(CoordinateUtil.checkValidVal(request.getData().getHomeLongitude()))
-                .latitude(CoordinateUtil.checkValidVal(request.getData().getHomeLatitude()))
-                .build());
+        deviceService.updateHome(deviceOpt.get(), aMap);
         deviceService.updateFlightControl(rcOpt.get(), request.getData().getControlSource());
         devicePayloadService.updatePayloadControl(deviceOpt.get(),
                 request.getData().getPayloads().stream()

+ 4 - 3
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java

@@ -142,8 +142,8 @@ public class UserServiceImpl implements IUserService {
         }
 
         //密码加密
-        String encryptPsw = DesUtil.getEncryptData(password,userEntity.getSalt());
-        if (!encryptPsw.equals(userEntity.getPassword()) || !username.equals(userEntity.getUsername())) {
+        //String encryptPsw = DesUtil.getEncryptData(password,userEntity.getSalt());
+        if (!password.equals(userEntity.getPassword()) || !username.equals(userEntity.getUsername())) {
             return new HttpResultResponse()
                     .setCode(HttpStatus.UNAUTHORIZED.value())
                     .setMessage("用户名或密码不匹配");
@@ -317,7 +317,8 @@ public class UserServiceImpl implements IUserService {
      * @param username
      * @return
      */
-    private UserEntity getUserByUsername(String username) {
+    @Override
+    public UserEntity getUserByUsername(String username) {
         return mapper.selectOne(new QueryWrapper<UserEntity>()
                 .eq("username", username));
     }

+ 1 - 0
Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

@@ -27,6 +27,7 @@ import com.dji.sdk.cloudapi.map.*;
 import com.dji.sdk.cloudapi.media.MediaSubFileTypeEnum;
 import com.dji.sdk.cloudapi.media.MediaUploadCallbackRequest;
 import com.dji.sdk.cloudapi.wayline.GetWaylineListResponse;
+import com.dji.sdk.common.CoordinateUtil;
 import com.dji.sdk.common.Pagination;
 import com.dji.sdk.common.PaginationData;
 import lombok.extern.slf4j.Slf4j;

+ 2 - 1
Backend/sample/src/main/resources/application.yml

@@ -181,4 +181,5 @@ livestream:
 custom-config:
   #航点采集频次(秒)
   frequency: 3
-  key: b1uruk98vuk40cdego6jw5yv9tygjm3s
+  key: b1uruk98vuk40cdego6jw5yv9tygjm3s
+  signKey: 7e92430eb1f949e9a750fadf68777c44

+ 1 - 1
Web/index.html

@@ -6,7 +6,7 @@
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <link rel="icon" href="/src/assets/public/favicon.ico" />
   <title>上云无人机管理平台</title>
-  <script type="text/javascript" src="EasyPlayer-element.min.js"></script>
+  <script src="liveplayer-lib.min.js"></script>
 </head>
 
 <body>

+ 158 - 112
Web/package-lock.json

@@ -10,6 +10,7 @@
       "license": "ISC",
       "dependencies": {
         "@amap/amap-jsapi-loader": "^1.0.1",
+        "@liveqing/liveplayer-v3": "^3.7.24",
         "ant-design-vue": "^2.2.8",
         "axios": "^0.21.1",
         "eventemitter3": "^5.0.0",
@@ -62,10 +63,29 @@
         "vue": ">=3.0.3"
       }
     },
-    "node_modules/@babel/parser": {
+    "node_modules/@babel/helper-string-parser": {
       "version": "7.24.8",
-      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.8.tgz",
-      "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
+      "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
+      "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.25.3",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.3.tgz",
+      "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==",
+      "dependencies": {
+        "@babel/types": "^7.25.2"
+      },
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -74,9 +94,9 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.24.8",
-      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.24.8.tgz",
-      "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==",
+      "version": "7.25.0",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.25.0.tgz",
+      "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
       "dependencies": {
         "regenerator-runtime": "^0.14.0"
       },
@@ -84,6 +104,19 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@babel/types": {
+      "version": "7.25.2",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.2.tgz",
+      "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.24.8",
+        "@babel/helper-validator-identifier": "^7.24.7",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/@ctrl/tinycolor": {
       "version": "3.6.1",
       "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
@@ -466,10 +499,15 @@
       "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
       "peer": true
     },
+    "node_modules/@liveqing/liveplayer-v3": {
+      "version": "3.7.24",
+      "resolved": "https://registry.npmmirror.com/@liveqing/liveplayer-v3/-/liveplayer-v3-3.7.24.tgz",
+      "integrity": "sha512-s7/R0qd/WbuN4Hf1YlSPAsC9a08ei+71wjD+Zn6d96UKD9XTHBgMEL7GSu3hP3SCDmZOQWR0vusQRhiFcIDvLg=="
+    },
     "node_modules/@rollup/rollup-android-arm-eabi": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
-      "integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.2.tgz",
+      "integrity": "sha512-OHflWINKtoCFSpm/WmuQaWW4jeX+3Qt3XQDepkkiFTsoxFc5BpF3Z5aDxFZgBqRjO6ATP5+b1iilp4kGIZVWlA==",
       "cpu": [
         "arm"
       ],
@@ -480,9 +518,9 @@
       ]
     },
     "node_modules/@rollup/rollup-android-arm64": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
-      "integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.2.tgz",
+      "integrity": "sha512-k0OC/b14rNzMLDOE6QMBCjDRm3fQOHAL8Ldc9bxEWvMo4Ty9RY6rWmGetNTWhPo+/+FNd1lsQYRd0/1OSix36A==",
       "cpu": [
         "arm64"
       ],
@@ -493,9 +531,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-arm64": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
-      "integrity": "sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.2.tgz",
+      "integrity": "sha512-IIARRgWCNWMTeQH+kr/gFTHJccKzwEaI0YSvtqkEBPj7AshElFq89TyreKNFAGh5frLfDCbodnq+Ye3dqGKPBw==",
       "cpu": [
         "arm64"
       ],
@@ -506,9 +544,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-x64": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
-      "integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.2.tgz",
+      "integrity": "sha512-52udDMFDv54BTAdnw+KXNF45QCvcJOcYGl3vQkp4vARyrcdI/cXH8VXTEv/8QWfd6Fru8QQuw1b2uNersXOL0g==",
       "cpu": [
         "x64"
       ],
@@ -519,9 +557,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
-      "integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.2.tgz",
+      "integrity": "sha512-r+SI2t8srMPYZeoa1w0o/AfoVt9akI1ihgazGYPQGRilVAkuzMGiTtexNZkrPkQsyFrvqq/ni8f3zOnHw4hUbA==",
       "cpu": [
         "arm"
       ],
@@ -532,9 +570,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-musleabihf": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
-      "integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.2.tgz",
+      "integrity": "sha512-+tYiL4QVjtI3KliKBGtUU7yhw0GMcJJuB9mLTCEauHEsqfk49gtUBXGtGP3h1LW8MbaTY6rSFIQV1XOBps1gBA==",
       "cpu": [
         "arm"
       ],
@@ -545,9 +583,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-gnu": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
-      "integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.2.tgz",
+      "integrity": "sha512-OR5DcvZiYN75mXDNQQxlQPTv4D+uNCUsmSCSY2FolLf9W5I4DSoJyg7z9Ea3TjKfhPSGgMJiey1aWvlWuBzMtg==",
       "cpu": [
         "arm64"
       ],
@@ -558,9 +596,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-musl": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
-      "integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.2.tgz",
+      "integrity": "sha512-Hw3jSfWdUSauEYFBSFIte6I8m6jOj+3vifLg8EU3lreWulAUpch4JBjDMtlKosrBzkr0kwKgL9iCfjA8L3geoA==",
       "cpu": [
         "arm64"
       ],
@@ -571,9 +609,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
-      "integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.2.tgz",
+      "integrity": "sha512-rhjvoPBhBwVnJRq/+hi2Q3EMiVF538/o9dBuj9TVLclo9DuONqt5xfWSaE6MYiFKpo/lFPJ/iSI72rYWw5Hc7w==",
       "cpu": [
         "ppc64"
       ],
@@ -584,9 +622,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-riscv64-gnu": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
-      "integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.2.tgz",
+      "integrity": "sha512-EAz6vjPwHHs2qOCnpQkw4xs14XJq84I81sDRGPEjKPFVPBw7fwvtwhVjcZR6SLydCv8zNK8YGFblKWd/vRmP8g==",
       "cpu": [
         "riscv64"
       ],
@@ -597,9 +635,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-s390x-gnu": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
-      "integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.2.tgz",
+      "integrity": "sha512-IJSUX1xb8k/zN9j2I7B5Re6B0NNJDJ1+soezjNojhT8DEVeDNptq2jgycCOpRhyGj0+xBn7Cq+PK7Q+nd2hxLA==",
       "cpu": [
         "s390x"
       ],
@@ -610,9 +648,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
-      "integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.2.tgz",
+      "integrity": "sha512-OgaToJ8jSxTpgGkZSkwKE+JQGihdcaqnyHEFOSAU45utQ+yLruE1dkonB2SDI8t375wOKgNn8pQvaWY9kPzxDQ==",
       "cpu": [
         "x64"
       ],
@@ -623,9 +661,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
-      "integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.2.tgz",
+      "integrity": "sha512-5V3mPpWkB066XZZBgSd1lwozBk7tmOkKtquyCJ6T4LN3mzKENXyBwWNQn8d0Ci81hvlBw5RoFgleVpL6aScLYg==",
       "cpu": [
         "x64"
       ],
@@ -636,9 +674,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-arm64-msvc": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
-      "integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.2.tgz",
+      "integrity": "sha512-ayVstadfLeeXI9zUPiKRVT8qF55hm7hKa+0N1V6Vj+OTNFfKSoUxyZvzVvgtBxqSb5URQ8sK6fhwxr9/MLmxdA==",
       "cpu": [
         "arm64"
       ],
@@ -649,9 +687,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-ia32-msvc": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
-      "integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.2.tgz",
+      "integrity": "sha512-Mda7iG4fOLHNsPqjWSjANvNZYoW034yxgrndof0DwCy0D3FvTjeNo+HGE6oGWgvcLZNLlcp0hLEFcRs+UGsMLg==",
       "cpu": [
         "ia32"
       ],
@@ -662,9 +700,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-x64-msvc": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
-      "integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.2.tgz",
+      "integrity": "sha512-DPi0ubYhSow/00YqmG1jWm3qt1F8aXziHc/UNy8bo9cpCacqhuWu+iSq/fp2SyEQK7iYTZ60fBU9cat3MXTjIQ==",
       "cpu": [
         "x64"
       ],
@@ -699,9 +737,9 @@
       }
     },
     "node_modules/@vitejs/plugin-vue": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.0.tgz",
-      "integrity": "sha512-QMRxARyrdiwi1mj3AW4fLByoHTavreXq0itdEW696EihXglf1MB3D4C2gBvE0jMPH29ZjC3iK8aIaUMLf4EOGA==",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.2.tgz",
+      "integrity": "sha512-nY9IwH12qeiJqumTCLJLE7IiNx7HZ39cbHaysEUd+Myvbz9KAqd2yq+U01Kab1R/H1BmiyM2ShTYlNH32Fzo3A==",
       "dev": true,
       "engines": {
         "node": "^18.0.0 || >=20.0.0"
@@ -712,53 +750,53 @@
       }
     },
     "node_modules/@vue/compiler-core": {
-      "version": "3.4.34",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.34.tgz",
-      "integrity": "sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==",
+      "version": "3.4.35",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.35.tgz",
+      "integrity": "sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==",
       "peer": true,
       "dependencies": {
         "@babel/parser": "^7.24.7",
-        "@vue/shared": "3.4.34",
+        "@vue/shared": "3.4.35",
         "entities": "^4.5.0",
         "estree-walker": "^2.0.2",
         "source-map-js": "^1.2.0"
       }
     },
     "node_modules/@vue/compiler-dom": {
-      "version": "3.4.34",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.34.tgz",
-      "integrity": "sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==",
+      "version": "3.4.35",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.35.tgz",
+      "integrity": "sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==",
       "peer": true,
       "dependencies": {
-        "@vue/compiler-core": "3.4.34",
-        "@vue/shared": "3.4.34"
+        "@vue/compiler-core": "3.4.35",
+        "@vue/shared": "3.4.35"
       }
     },
     "node_modules/@vue/compiler-sfc": {
-      "version": "3.4.34",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.34.tgz",
-      "integrity": "sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==",
+      "version": "3.4.35",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.35.tgz",
+      "integrity": "sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==",
       "peer": true,
       "dependencies": {
         "@babel/parser": "^7.24.7",
-        "@vue/compiler-core": "3.4.34",
-        "@vue/compiler-dom": "3.4.34",
-        "@vue/compiler-ssr": "3.4.34",
-        "@vue/shared": "3.4.34",
+        "@vue/compiler-core": "3.4.35",
+        "@vue/compiler-dom": "3.4.35",
+        "@vue/compiler-ssr": "3.4.35",
+        "@vue/shared": "3.4.35",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.30.10",
-        "postcss": "^8.4.39",
+        "postcss": "^8.4.40",
         "source-map-js": "^1.2.0"
       }
     },
     "node_modules/@vue/compiler-ssr": {
-      "version": "3.4.34",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.34.tgz",
-      "integrity": "sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==",
+      "version": "3.4.35",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.35.tgz",
+      "integrity": "sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==",
       "peer": true,
       "dependencies": {
-        "@vue/compiler-dom": "3.4.34",
-        "@vue/shared": "3.4.34"
+        "@vue/compiler-dom": "3.4.35",
+        "@vue/shared": "3.4.35"
       }
     },
     "node_modules/@vue/devtools-api": {
@@ -891,9 +929,9 @@
       "integrity": "sha512-vPV6Cq+NIWbH5pZu+V+2QHE9y1qfuTq49uNWw4f7FDEeZaDU2H2cx5jcUZOAKW7qTrUS4k6qZPbMy1x4N96nbA=="
     },
     "node_modules/@vue/shared": {
-      "version": "3.4.34",
-      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.34.tgz",
-      "integrity": "sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==",
+      "version": "3.4.35",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.35.tgz",
+      "integrity": "sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==",
       "peer": true
     },
     "node_modules/ant-design-vue": {
@@ -1137,9 +1175,9 @@
       "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
     },
     "node_modules/debug": {
-      "version": "4.3.5",
-      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz",
-      "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz",
+      "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
       "dependencies": {
         "ms": "2.1.2"
       },
@@ -1477,12 +1515,12 @@
       }
     },
     "node_modules/magic-string": {
-      "version": "0.30.10",
-      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz",
-      "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+      "version": "0.30.11",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz",
+      "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
       "peer": true,
       "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.4.15"
+        "@jridgewell/sourcemap-codec": "^1.5.0"
       }
     },
     "node_modules/minimatch": {
@@ -1749,9 +1787,9 @@
       "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
     },
     "node_modules/rollup": {
-      "version": "4.19.0",
-      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.19.0.tgz",
-      "integrity": "sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==",
+      "version": "4.19.2",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.19.2.tgz",
+      "integrity": "sha512-6/jgnN1svF9PjNYJ4ya3l+cqutg49vOZ4rVgsDKxdl+5gpGPnByFXWGyfH9YGx9i3nfBwSu1Iyu6vGwFFA0BdQ==",
       "dev": true,
       "dependencies": {
         "@types/estree": "1.0.5"
@@ -1764,22 +1802,22 @@
         "npm": ">=8.0.0"
       },
       "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.19.0",
-        "@rollup/rollup-android-arm64": "4.19.0",
-        "@rollup/rollup-darwin-arm64": "4.19.0",
-        "@rollup/rollup-darwin-x64": "4.19.0",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.19.0",
-        "@rollup/rollup-linux-arm-musleabihf": "4.19.0",
-        "@rollup/rollup-linux-arm64-gnu": "4.19.0",
-        "@rollup/rollup-linux-arm64-musl": "4.19.0",
-        "@rollup/rollup-linux-powerpc64le-gnu": "4.19.0",
-        "@rollup/rollup-linux-riscv64-gnu": "4.19.0",
-        "@rollup/rollup-linux-s390x-gnu": "4.19.0",
-        "@rollup/rollup-linux-x64-gnu": "4.19.0",
-        "@rollup/rollup-linux-x64-musl": "4.19.0",
-        "@rollup/rollup-win32-arm64-msvc": "4.19.0",
-        "@rollup/rollup-win32-ia32-msvc": "4.19.0",
-        "@rollup/rollup-win32-x64-msvc": "4.19.0",
+        "@rollup/rollup-android-arm-eabi": "4.19.2",
+        "@rollup/rollup-android-arm64": "4.19.2",
+        "@rollup/rollup-darwin-arm64": "4.19.2",
+        "@rollup/rollup-darwin-x64": "4.19.2",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.19.2",
+        "@rollup/rollup-linux-arm-musleabihf": "4.19.2",
+        "@rollup/rollup-linux-arm64-gnu": "4.19.2",
+        "@rollup/rollup-linux-arm64-musl": "4.19.2",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.19.2",
+        "@rollup/rollup-linux-riscv64-gnu": "4.19.2",
+        "@rollup/rollup-linux-s390x-gnu": "4.19.2",
+        "@rollup/rollup-linux-x64-gnu": "4.19.2",
+        "@rollup/rollup-linux-x64-musl": "4.19.2",
+        "@rollup/rollup-win32-arm64-msvc": "4.19.2",
+        "@rollup/rollup-win32-ia32-msvc": "4.19.2",
+        "@rollup/rollup-win32-x64-msvc": "4.19.2",
         "fsevents": "~2.3.2"
       }
     },
@@ -1880,6 +1918,14 @@
       "resolved": "https://registry.npmmirror.com/three/-/three-0.147.0.tgz",
       "integrity": "sha512-LPTOslYQXFkmvceQjFTNnVVli2LaVF6C99Pv34fJypp8NbQLbTlu3KinZ0zURghS5zEehK+VQyvWuPZ/Sm8fzw=="
     },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -2011,11 +2057,11 @@
       }
     },
     "node_modules/vue-router": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.4.0.tgz",
-      "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==",
+      "version": "4.4.2",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.4.2.tgz",
+      "integrity": "sha512-1qNybkn2L7QsLzaXs8nvlQmRKp8XF8DCxZys/Jr1JpQcHsKUxTKzTxCVA1G7NfBfwRIBgCJPoujOG5lHCCNUxw==",
       "dependencies": {
-        "@vue/devtools-api": "^6.5.1"
+        "@vue/devtools-api": "^6.6.3"
       },
       "funding": {
         "url": "https://github.com/sponsors/posva"

+ 1 - 0
Web/package.json

@@ -12,6 +12,7 @@
   },
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",
+    "@liveqing/liveplayer-v3": "^3.7.24",
     "ant-design-vue": "^2.2.8",
     "axios": "^0.21.1",
     "eventemitter3": "^5.0.0",

File diff suppressed because it is too large
+ 0 - 11
Web/public/EasyPlayer-element.min.js


BIN
Web/public/EasyPlayer.wasm


File diff suppressed because it is too large
+ 0 - 0
Web/public/liveplayer-lib.min.js


+ 24 - 4
Web/src/api/http/request.ts

@@ -7,9 +7,29 @@ export * from './type'
 
 const REQUEST_ID = 'X-Request-Id'
 
-function getAuthToken() {
-  return localStorage.getItem(ELocalStorageKey.Token)
-}
+export const getHeaders = () => {
+  const headers: {
+    'x-auth-token'?: string,
+    'sign': string,
+    'key': string,
+    'userCode': string,
+  } = {
+    'sign': '',
+    'key': '',
+    'userCode': '',
+  };
+  const token = localStorage.getItem(ELocalStorageKey.Token)
+  if (token) {
+    headers['x-auth-token'] = token;
+  }
+  const sign = localStorage.getItem('sign') || '';
+  const key = localStorage.getItem('key') || '';
+  const userCode = localStorage.getItem('userCode') || '';
+  headers['sign'] = sign;
+  headers['key'] = key;
+  headers['userCode'] = userCode;
+  return headers;
+};
 
 const instance = axios.create({
   headers: {
@@ -19,7 +39,7 @@ const instance = axios.create({
 
 instance.interceptors.request.use(
   config => {
-    config.headers[ELocalStorageKey.Token] = getAuthToken()
+    config.headers = getHeaders();
     config.baseURL = '/api';
     return config
   },

+ 18 - 129
Web/src/components/LayersTree.vue

@@ -3,20 +3,16 @@
     <a-empty :image="noData" :image-style="{ height: '60px' }" />
   </div>
   <div v-else>
-    <a-tree class="device-map-layers" v-bind="$attrs" v-if="getTreeData.length">
-      <a-tree-node :id="layer.id" v-for="layer in getTreeData" :key="layer.id" :disabled="true">
+    <a-directory-tree class="device-map-layers" v-bind="$attrs" :multiple="false" v-if="getTreeData.length">
+      <a-tree-node :id="layer.id" v-for="layer in getTreeData" :key="layer.id" :selectable="false">
         <template #title>
-          <div style="display: flex;align-items: center;">
-            <FolderOutlined />
-            <div style="margin-left: 10px;">
-              {{ layer.name }}
-            </div>
-          </div>
+          {{ layer.name }}
         </template>
         <template v-if="layer.elements">
-          <a-tree-node v-for="resource in layer.elements" :type="resource.resource ? 'DEFAULT' : 'PHOTO'"
-            :id="getLayerTreeKey('resource', resource.id)" :key="getLayerTreeKey('resource', resource.id)"
-            :disabled="!resource.resource">
+          <a-tree-node v-for="resource in layer.elements" :id="getLayerTreeKey('resource', resource.id)"
+            :key="getLayerTreeKey('resource', resource.id)" :selectable="resource.resource ? true : false"
+            :label="resource.resource ? 'DEFAULT' : 'PHOTO'">
+            <template #icon></template>
             <template #title>
               <div style="display: flex;align-items: center;" v-if="resource.resource">
                 <Icon v-if="resource.resource.type === 0">
@@ -42,8 +38,9 @@
               </div>
             </template>
             <template v-if="layer.elements">
-              <a-tree-node v-for="item in resource.elements" :type="'PHOTO'" :id="getLayerTreeKey('resource', item.id)"
-                :key="getLayerTreeKey('resource', item.id)">
+              <a-tree-node v-for="item in resource.elements" :id="getLayerTreeKey('resource', item.id)"
+                :key="getLayerTreeKey('resource', item.id)" :label="'PHOTO'">
+                <template #icon></template>
                 <template #title>
                   {{ item.name }}
                 </template>
@@ -52,7 +49,7 @@
           </a-tree-node>
         </template>
       </a-tree-node>
-    </a-tree>
+    </a-directory-tree>
   </div>
 </template>
 
@@ -74,122 +71,14 @@ const getTreeData = computed(() => {
 </script>
 
 <style lang="scss">
-$antPrefix: 'ant';
-
-.device-map-layers.#{$antPrefix}-tree {
-  color: #fff;
-
-  .#{$antPrefix}-tree-checkbox:not(.#{$antPrefix}-tree-checkbox-checked) .#{$antPrefix}-tree-checkbox-inner {
-    background-color: unset;
-  }
-
-  .anticon {
-    font-size: 16px;
-  }
-
-  // 第一个层级的 li,有左边距 16px
-  >li {
-    padding-left: 16px;
-    padding-right: 16px;
-  }
-
-  li {
-    display: flex;
-    flex-wrap: wrap;
-    align-items: center;
-    padding-top: 0;
-    padding-bottom: 0;
-
-    &:first-child {
-      padding-top: 4px;
-    }
-
-    &.#{$antPrefix}-tree-treenode-disabled>.#{$antPrefix}-tree-node-content-wrapper {
-      height: 20px;
-
-      span {
-        color: #fff;
-      }
-    }
-
-    >ul {
-      width: 100%;
-    }
-
-    .#{$antPrefix}-tree-switcher {
-      z-index: 1;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-
-    .#{$antPrefix}-tree-checkbox {
-      z-index: 1;
-    }
-
-    .#{$antPrefix}-tree-checkbox:hover::after,
-    .#{$antPrefix}-tree-checkbox-wrapper:hover .#{$antPrefix}-tree-checkbox::after {
-      visibility: collapse;
-    }
-
-    .#{$antPrefix}-tree-title {
-      display: block;
-    }
-
-    .#{$antPrefix}-tree-node-content-wrapper {
-      color: #fff;
-      width: calc(100% - 46px);
-      flex: 1;
-      box-sizing: content-box;
-      height: 20px;
-      min-width: 0; // 解决文字溢出不会省略的问题
-      padding-right: 0;
-
-      &:not([draggable='true']) {
-        border-top: 2px transparent solid;
-        border-bottom: 2px transparent solid;
-      }
-
-      &:hover {
-        background-color: transparent;
-      }
-
-      >span {
-        &::before {
-          // position: absolute;
-          // right: 0;
-          // left: 0;
-          height: 28px;
-          transition: all 0.3s;
-          content: '';
-        }
-
-        // 进度条组件需要相对最外层定位,进度条组件的position不能设置为relative
-        >*:not(.progress-wrapper) {
-          position: relative;
-          z-index: 1;
-        }
-      }
-
-      &.#{$antPrefix}-tree-node-selected {
-        background-color: transparent;
-        color: #2d8cf0;
-
-        >span {
-          &::before {
-            background-color: #4f4f4f;
-          }
-        }
-      }
-    }
-  }
-
-  span.#{$antPrefix}-tree-switcher.#{$antPrefix}-tree-switcher_open .#{$antPrefix}-tree-switcher-icon {
-    transform: rotate(0deg) !important;
+.device-map-layers {
+  span {
+    color: #FFFFFF;
   }
+}
 
-  span.#{$antPrefix}-tree-switcher.#{$antPrefix}-tree-switcher_close .#{$antPrefix}-tree-switcher-icon {
-    transform: rotate(0deg) !important;
-  }
+.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper:hover::before,
+.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper:hover::before {
+  background: #1890ff;
 }
 </style>

+ 3 - 3
Web/src/components/deviceLive/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="deviceLive">
     <div class="deviceLive-frames">
-      <EasyPlayer :url="state.playerUrl" />
+      <LivePlayer :url="state.playerUrl" />
     </div>
     <div class="deviceLive-operation">
       <a-select style="width:150px;margin-right: 13px;" placeholder="摄像头" v-model:value="state.cameraValue">
@@ -25,7 +25,7 @@
 <script lang="ts" setup>
 import { reactive, onMounted } from 'vue';
 import { message } from 'ant-design-vue';
-import EasyPlayer from '/@/components/easyPlayer/index.vue';
+import LivePlayer from '/@/components/livePlayer/index.vue';
 import { CURRENT_CONFIG as config } from '/@/api/http/config';
 import { getLiveCapacity, startLivestream, stopLivestream } from '/@/api/manage';
 
@@ -181,7 +181,7 @@ const onStop = async () => {
 
   &-frames {
     width: 100%;
-    height: 300px;
+    height: 270px;
   }
 
   &-operation {

+ 0 - 15
Web/src/components/easyPlayer/index.vue

@@ -1,15 +0,0 @@
-<template>
-    <easy-player :reconnection="true" alt=" " :video-url="url" />
-</template>
-
-<script lang="ts" setup>
-interface Props {
-    url: string,
-};
-
-const props = withDefaults(defineProps<Props>(), {
-
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 17 - 0
Web/src/components/livePlayer/index.vue

@@ -0,0 +1,17 @@
+<template>
+    <LivePlayer alt=" " :live="true" :hide-big-play-button="true" :hide-stretch-button="true" :video-url="url" />
+</template>
+
+<script lang="ts" setup>
+import LivePlayer from '@liveqing/liveplayer-v3'
+
+interface Props {
+    url: string,
+};
+
+const props = withDefaults(defineProps<Props>(), {
+
+});
+</script>
+
+<style lang="scss" scoped></style>

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

@@ -6,7 +6,8 @@ export function useGMapTrajectory() {
   let AMap = root.$aMap;
 
   // 绘制轨迹
-  const drawTrajectory = (paths: any[]) => {
+  const drawTrajectory = (list: any[]) => {
+    const paths = list.map(item => item.paths)
     // 绘制起点图标
     const startPosition = paths[0];
     const startIcon = new AMap.Icon({
@@ -28,7 +29,22 @@ export function useGMapTrajectory() {
       strokeWeight: 6,//线宽
       strokeStyle: 'solid',
     })
-    root.$map.add([startMarker, polyline]);
+    // 渲染序号
+    const serialList = list.filter(item => [2, 3].includes(item.type));
+    const text = serialList.map((item, index) => {
+      return new AMap.Text({
+        position: new AMap.LngLat(item.paths[0], item.paths[1]),
+        // offset: new AMap.Pixel(-30, -30),
+        text: index + 1,
+        style: {
+          fontSize: 12,
+          padding: 0,
+          backgroundColor: 'transparent',
+          borderColor: 'transparent',
+        }
+      })
+    })
+    root.$map.add([startMarker, polyline, ...text]);
     // 自动缩放地图到合适的视野级别
     root.$map.setFitView([startMarker, polyline]);
   }

+ 6 - 2
Web/src/pages/page-web/projects/layer/index.vue

@@ -75,6 +75,9 @@ import {
 } from '/@/api/layer'
 import { useMyStore } from '/@/store'
 import { gcj02towgs84, wgs84togcj02 } from '/@/vendors/coordtransform'
+import { getRoot } from '/@/root'
+
+const root = getRoot()
 
 interface Props {
   mapClickElement: {
@@ -118,6 +121,8 @@ watch(() => props.mapClickElement, (newValue, oldValue) => {
       list.elements.forEach((item: any) => {
         item.elements.forEach((element: any) => {
           if (element.id === newValue.id) {
+            const coordinates = element.resource.content.geometry.coordinates;
+            root.$map.setCenter(coordinates);
             expandedKeyList.push(element.pid)
             expandedKeys.value = expandedKeyList;
             selectedKeys.value = [`resource__${newValue.id}`];
@@ -233,8 +238,7 @@ function selectLayer(keys: string[], e) {
   if (e.selected) {
     selectedKey.value = e.node.eventKey
     selectedLayer.value = getCurrentLayer(selectedKey.value)
-    const info = e.selectedNodes[0];
-    const type = info.props.type;
+    const type = e.node.label;
     if (type === 'DEFAULT') {// 默认文件夹
       setBaseInfo()
       visible.value = true;

+ 3 - 72
Web/src/pages/page-web/projects/member/index.vue

@@ -3,49 +3,16 @@
     <Search :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">
-        <template v-for="col in ['mqtt_username', 'mqtt_password']" #[col]="{ text, record }" :key="col">
-          <div>
-            <a-input v-if="state.editableData[record.user_id]" v-model:value="state.editableData[record.user_id][col]"
-              style="margin: -5px 0" />
-            <template v-else>
-              {{ text }}
-            </template>
-          </div>
-        </template>
-        <template #action="{ record }">
-          <div class="editable-row-operations">
-            <span v-if="state.editableData[record.user_id]">
-              <a-tooltip title="确定">
-                <span @click="save(record)" style="color: #28d445;">
-                  <CheckOutlined />
-                </span>
-              </a-tooltip>
-              <a-tooltip title="取消">
-                <span @click="() => delete state.editableData[record.user_id]" class="ml15" style="color: #e70102;">
-                  <CloseOutlined />
-                </span>
-              </a-tooltip>
-            </span>
-            <span v-else class="fz18 flex-align-center flex-row" style="color: #2d8cf0">
-              <a-tooltip title="编辑">
-                <EditOutlined @click="edit(record)" />
-              </a-tooltip>
-            </span>
-          </div>
-        </template>
-      </a-table>
+        @change="refreshData" :rowClassName="rowClassName" :dataSource="state.list" :pagination="paginationConfig" />
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { message } from 'ant-design-vue'
-import { onMounted, reactive, UnwrapRef } from 'vue'
+import { onMounted, reactive } from 'vue'
 import Search from './components/Search.vue';
-import { getAllUsersInfo, updateUserInfo } from '/@/api/manage'
+import { getAllUsersInfo } from '/@/api/manage'
 import { ELocalStorageKey } from '/@/types'
-import { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue'
 
 export interface Member {
   user_id: string
@@ -60,15 +27,11 @@ export interface Member {
 interface State {
   listLoading: boolean,
   list: Member[],
-  editableData: {
-    [key: string]: any,
-  },
 }
 
 const state: State = reactive({
   listLoading: false,
   list: [],
-  editableData: {},
 })
 
 const paginationConfig = reactive({
@@ -121,29 +84,11 @@ const columns = [
     dataIndex: 'workspace_name',
     width: 150,
   },
-  {
-    title: 'Mqtt 用户',
-    dataIndex: 'mqtt_username',
-    width: 150,
-    slots: { customRender: 'mqtt_username' },
-  },
-  {
-    title: 'Mqtt 密码',
-    dataIndex: 'mqtt_password',
-    width: 150,
-    slots: { customRender: 'mqtt_password' },
-  },
   {
     title: '创建时间',
     dataIndex: 'create_time',
     width: 150,
     sorter: (a: Member, b: Member) => a.create_time.localeCompare(b.create_time),
-  },
-  {
-    title: '操作',
-    dataIndex: 'action',
-    width: 80,
-    slots: { customRender: 'action' },
   }
 ]
 
@@ -160,20 +105,6 @@ const refreshData = async (page: any) => {
   paginationConfig.pageSize = page?.pageSize!
   await fetchList();
 }
-// 点击编辑
-const edit = (record: Member) => {
-  state.editableData[record.user_id] = record;
-}
-
-// 点击保存
-const save = (record: Member) => {
-  delete state.editableData[record.user_id]
-  updateUserInfo(workspaceId, record.user_id, record).then(res => {
-    if (res.code !== 0) {
-      message.error(res.message)
-    }
-  })
-}
 
 // 点击搜索
 const onClickSearch = async (query: any) => {

+ 7 - 1
Web/src/pages/page-web/projects/trajectory/index.vue

@@ -163,7 +163,13 @@ const onClickLookTrajectory = async (id: string) => {
   router.push({ path: '/workspace' });
   const res = await apis.fetchTrajectoryMap(id);
   const list = res.data.map((item: any) => {
-    return wgs84togcj02(item.longitude, item.latitude);
+    const data = {
+      ...item,
+      paths: wgs84togcj02(item.longitude, item.latitude),
+    }
+    delete data.latitude;
+    delete data.longitude;
+    return data;
   });
   store.commit('SET_TRAJECTORY_LIST', list)
 }

+ 25 - 18
Web/src/pages/page-web/projects/tsa.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="project-tsa-wrapper ">
-    <div class="scrollbar" :style="{ height: scorllHeight + 'px' }">
+    <div class="scrollbar" :style="{ height: '100%' }">
       <a-collapse style="background: #232323;" :bordered="false" expandIconPosition="right" accordion
         v-model:activeKey="state.activeKey">
         <a-collapse-panel style="border-bottom: 1px solid #4f4f4f;" :key="EDeviceTypeName.Dock" header="机场">
@@ -8,8 +8,7 @@
             <a-empty :image="noData" :image-style="{ height: '60px' }" />
           </div>
           <div v-else class="fz12" style="color: white;">
-            <div v-for="dock in onlineDocks.data" :key="dock.sn"
-              style="background: #3c3c3c; height: 90px; width: 250px; margin-bottom: 10px;">
+            <div class="airport-item" v-for="dock in onlineDocks.data" :key="dock.sn">
               <div style="border-radius: 2px; height: 100%; width: 100%;"
                 class="flex-row flex-justify-between flex-align-center">
                 <div style="float: left; padding: 0px 5px 8px 8px; width: 88%">
@@ -97,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"
@@ -159,8 +158,7 @@
             <a-empty :image="noData" :image-style="{ height: '60px' }" />
           </div>
           <div v-else class="fz12" style="color: white;">
-            <div
-              :class="['device-item', (state.selectedDeviceList.includes(device.gateway.sn) && 'device-item-selected')]"
+            <div :class="['device-item', (state.selectedDevice === device.gateway.sn && 'device-item-selected')]"
               v-for="device in onlineDevices.data" :key="device.sn" @click="onClickSelectedDevice(device)">
               <div class="battery-slide" v-if="deviceInfo[device.sn]">
                 <div style="background: #535759; width: 100%;"></div>
@@ -230,11 +228,11 @@
         </a-collapse-panel>
       </a-collapse>
     </div>
-    <div style="width: 100%;padding-top: 10px; display: flex;justify-content: center;align-items: center;">
+    <!-- <div style="width: 100%;padding-top: 10px; display: flex;justify-content: center;align-items: center;">
       <a-button style="margin-right: 10px;" type="primary" @click="onClickGoHome">
         返回
       </a-button>
-    </div>
+    </div> -->
   </div>
 </template>
 
@@ -269,7 +267,7 @@ const onlineDocks = reactive({
 
 const state = reactive({
   activeKey: -1,
-  selectedDeviceList: [] as string[],
+  selectedDevice: '',
 })
 
 const mapClickElement = computed(() => store.state.mapClickElement)
@@ -309,17 +307,14 @@ onMounted(() => {
 // 点击选中设备
 const onClickSelectedDevice = (record: OnlineDevice) => {
   const sn = record.gateway.sn;
-  const list = state.selectedDeviceList;
-  if (list.includes(sn)) {// 取消选中
-    state.selectedDeviceList = list.filter(item => item != sn)
-  } else {// 选中后
-    state.selectedDeviceList = [...list, sn]
-    const gatewayInfo = store.state.deviceState.gatewayInfo[sn]
+  if (state.selectedDevice === sn) {
+    state.selectedDevice = '';
+  } else {
+    state.selectedDevice = sn;
+    const gatewayInfo = store.state.deviceState.gatewayInfo[sn];
     if (gatewayInfo) {
-      const coordinate = wgs84togcj02(gatewayInfo.longitude, gatewayInfo.latitude)
-      // 最后点击的进行地图视角跟进
+      const coordinate = wgs84togcj02(gatewayInfo.longitude, gatewayInfo.latitude);
       root.$map.setCenter(coordinate)
-      console.log('触发绘画实时轨迹');
     }
   }
 }
@@ -438,6 +433,18 @@ function openLivestreamAgora() {
 </script>
 
 <style lang="scss">
+.airport-item {
+  background: #3c3c3c;
+  width: 100%;
+  height: 100px;
+  box-sizing: border-box;
+  padding-top: 10px;
+  border-radius: 2px;
+  border: 2px solid transparent;
+  cursor: pointer;
+  margin-top: 10px;
+}
+
 .device-item {
   background: #3c3c3c;
   width: 100%;

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

@@ -135,10 +135,11 @@ useConnectWebSocket(messageHandler)
 }
 
 .project-app-wrapper {
-  display: flex;
-  transition: width 0.2s ease;
   height: 100%;
   width: 100%;
+  display: flex;
+  transition: width 0.2s ease;
+  overflow: hidden;
 
   .left {
     display: flex;

+ 17 - 5
Web/src/router/index.ts

@@ -24,6 +24,11 @@ const routes: Array<RouteRecordRaw> = [
         name: ERouterName.DEVICES,
         component: () => import('/@/pages/page-web/projects/devices.vue')
       },
+      {
+        path: '/' + ERouterName.WORKSPACE,
+        name: ERouterName.WORKSPACE,
+        component: () => import('/@/pages/page-web/projects/workspace.vue'),
+      },
       {
         path: '/' + ERouterName.TASK,
         name: ERouterName.TASK,
@@ -68,11 +73,6 @@ const routes: Array<RouteRecordRaw> = [
       },
     ]
   },
-  {
-    path: '/' + ERouterName.WORKSPACE,
-    name: ERouterName.WORKSPACE,
-    component: () => import('/@/pages/page-web/projects/workspace.vue'),
-  },
   {
     path: '/' + ERouterName.PILOT,
     name: ERouterName.PILOT,
@@ -101,4 +101,16 @@ const router = createRouter({
   routes
 })
 
+router.beforeEach((to, from, next) => {
+  const { sign, key, userCode } = from.query as any
+  if (sign && key && userCode) {
+    localStorage.setItem('sign', sign);
+    localStorage.setItem('key', key);
+    localStorage.setItem('userCode', userCode);
+    next();
+  } else {
+    next();
+  }
+})
+
 export default router

+ 21 - 14
Web/src/types/mapLayer.ts

@@ -30,35 +30,39 @@ export interface DropEvent {
   dropPosition: number
   dropToGap: boolean
 }
+
 export interface mapLayer {
   key?: string
   title: string
   id: string
   name: string
+  type: number
   style: mapLayerStyle
   elements: any
 }
-export interface elementGroupsReq{
+
+export interface elementGroupsReq {
   groupId: string
   isDistributed: boolean
 }
+
 export interface PostElementsBody {
   id: string
   name: string
   resource: {
-   type: MapElementEnum,
-   user_name?: string,
-   content: {
-    type:string,
-    properties:{
-      color:string,
-      clampToGround:boolean
+    type: MapElementEnum,
+    user_name?: string,
+    content: {
+      type: string,
+      properties: {
+        color: string,
+        clampToGround: boolean
+      },
+      geometry: {
+        type: string,
+        coordinates: unknown
+      }
     },
-    geometry:{
-      type:string,
-      coordinates:unknown
-    }
-   },
   }
 }
 
@@ -74,6 +78,7 @@ export enum GeoType {
   Polygon = 'Polygon',
   Point = 'Point'
 }
+
 export enum ResourceStatus {
   NotShow,
   Show
@@ -83,6 +88,7 @@ export enum LayerElevationLoadStatus {
   Unload,
   Load
 }
+
 export interface PutElementsBody {
   name?: string
   status?: ResourceStatus
@@ -90,9 +96,10 @@ export interface PutElementsBody {
   display?: number
   elevation_load_status?: LayerElevationLoadStatus
 }
+
 export enum LayerType {
   Normal,
   Default,
   Share,
   Reconstruction
-}
+}

Some files were not shown because too many files changed in this diff