Browse Source

1.媒体管理 图片元素地图显示
2.获取凭证,推送用户接口

S0025136190 1 year ago
parent
commit
67bafae13f
24 changed files with 469 additions and 20 deletions
  1. 14 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementContent.java
  2. 66 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementPicture.java
  3. 77 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementPictureGeometry.java
  4. 3 1
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementResourceTypeEnum.java
  5. 7 1
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementTypeEnum.java
  6. 15 0
      Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/MapGroupElement.java
  7. 1 0
      Backend/sample/src/main/java/com/dji/sample/configuration/mvc/GlobalMVCConfigurer.java
  8. 7 1
      Backend/sample/src/main/java/com/dji/sample/manage/controller/LoginController.java
  9. 23 0
      Backend/sample/src/main/java/com/dji/sample/manage/controller/UserController.java
  10. 6 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
  11. 2 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java
  12. 4 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/IUserService.java
  13. 55 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
  14. 4 0
      Backend/sample/src/main/java/com/dji/sample/map/service/IGroupElementService.java
  15. 2 1
      Backend/sample/src/main/java/com/dji/sample/map/service/IGroupService.java
  16. 2 2
      Backend/sample/src/main/java/com/dji/sample/map/service/impl/FlightAreaServiceImpl.java
  17. 14 5
      Backend/sample/src/main/java/com/dji/sample/map/service/impl/GroupElementServiceImpl.java
  18. 23 3
      Backend/sample/src/main/java/com/dji/sample/map/service/impl/GroupServiceImpl.java
  19. 9 0
      Backend/sample/src/main/java/com/dji/sample/map/service/impl/WorkspaceElementServiceImpl.java
  20. 43 0
      Backend/sample/src/main/java/com/dji/sample/media/controller/FileController.java
  21. 2 0
      Backend/sample/src/main/java/com/dji/sample/media/model/MediaFileDTO.java
  22. 3 0
      Backend/sample/src/main/java/com/dji/sample/media/model/MediaFileEntity.java
  23. 9 0
      Backend/sample/src/main/java/com/dji/sample/media/service/IFileService.java
  24. 78 6
      Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

+ 14 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementContent.java

@@ -25,6 +25,10 @@ public class ElementContent {
     @NotNull
     private ElementGeometryType geometry;
 
+    @Valid
+    private ElementPicture picture;
+
+
     public ElementContent() {
     }
 
@@ -34,6 +38,7 @@ public class ElementContent {
                 "type='" + type + '\'' +
                 ", properties=" + properties +
                 ", geometry=" + geometry +
+                ", picture=" + picture +
                 '}';
     }
 
@@ -58,4 +63,13 @@ public class ElementContent {
         this.geometry = geometry;
         return this;
     }
+
+    public ElementPicture getPicture() {
+        return picture;
+    }
+
+    public ElementContent setPicture(ElementPicture picture) {
+        this.picture = picture;
+        return this;
+    }
 }

+ 66 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementPicture.java

@@ -0,0 +1,66 @@
+package com.dji.sdk.cloudapi.map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+/**
+ * @author hqjiang
+ * @version 0.1
+ * @date 2024/7/29
+ */
+@Schema(description = "picture of the element")
+public class ElementPicture {
+
+    @NotNull
+    @Schema(description = "file id")
+    private String fileId;
+
+    @Schema(description = "缩略图Url")
+    private String thumbnailUrl;
+
+    @Schema(description = "媒体类型")
+    private String mediaType;
+
+
+    public ElementPicture() {
+    }
+
+    @Override
+    public String toString() {
+        return "ElementProperty{" +
+                "fileId='" + fileId + '\'' +
+                ", thumbnailUrl=" + thumbnailUrl +
+                ", mediaType=" + mediaType +
+                '}';
+    }
+
+    public String getFileId() {
+        return fileId;
+    }
+
+    public ElementPicture setFileId(String fileId) {
+        this.fileId = fileId;
+        return this;
+    }
+
+    public String getThumbnailUrl() {
+        return thumbnailUrl;
+    }
+
+    public ElementPicture setThumbnailUrl(String thumbnailUrl) {
+        this.thumbnailUrl = thumbnailUrl;
+        return this;
+    }
+
+    public String getMediaType() {
+        return mediaType;
+    }
+
+    public ElementPicture setMediaType(String mediaType) {
+        this.mediaType = mediaType;
+        return this;
+    }
+}

+ 77 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementPictureGeometry.java

@@ -0,0 +1,77 @@
+package com.dji.sdk.cloudapi.map;
+
+import com.dji.sdk.exception.CloudSDKErrorEnum;
+import com.dji.sdk.exception.CloudSDKException;
+import io.swagger.v3.oas.annotations.media.Schema;
+import org.springframework.util.CollectionUtils;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author hqjiang
+ * @version 0.1
+ * @date 2024/7/29
+ */
+@Schema(description = "picture geometry")
+public class ElementPictureGeometry extends ElementGeometryType {
+
+    @Schema(example = "MEDIA")
+    @NotNull
+    private final String type = ElementResourceTypeEnum.MEDIA.getTypeName();
+
+    @Schema(example = "[113.943109, 22.577378]")
+    @NotNull
+    @Size(min = 2, max = 3)
+    private Double[] coordinates;
+
+    public ElementPictureGeometry() {
+        super();
+    }
+
+    @Override
+    public List<ElementCoordinate> convertToList() {
+        List<ElementCoordinate> coordinateList = new ArrayList<>();
+        coordinateList.add(new ElementCoordinate()
+                .setLongitude(this.coordinates[0])
+                .setLatitude(this.coordinates[1])
+                .setAltitude(this.coordinates.length == 3 ? this.coordinates[2] : null));
+        return coordinateList;
+    }
+
+    @Override
+    public void adapterCoordinateType(List<ElementCoordinate> coordinateList) {
+        if (CollectionUtils.isEmpty(coordinateList)) {
+            throw new CloudSDKException(CloudSDKErrorEnum.INVALID_PARAMETER);
+        }
+        this.coordinates = new Double[]{
+                coordinateList.get(0).getLongitude(),
+                coordinateList.get(0).getLatitude(),
+                coordinateList.get(0).getAltitude()
+        };
+    }
+
+    @Override
+    public String toString() {
+        return "ElementPictureGeometry{" +
+                "coordinates=" + Arrays.toString(coordinates) +
+                '}';
+    }
+
+    public Double[] getCoordinates() {
+        return coordinates;
+    }
+
+    public ElementPictureGeometry setCoordinates(Double[] coordinates) {
+        this.coordinates = coordinates;
+        return this;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+}

+ 3 - 1
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementResourceTypeEnum.java

@@ -19,7 +19,9 @@ public enum ElementResourceTypeEnum {
 
     LINE_STRING(1, "LineString"),
 
-    POLYGON(2, "Polygon");
+    POLYGON(2, "Polygon"),
+
+    MEDIA(3,"Media");
 
     private final int type;
 

+ 7 - 1
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/ElementTypeEnum.java

@@ -15,7 +15,9 @@ public enum ElementTypeEnum {
 
     LINE_STRING(ElementResourceTypeEnum.LINE_STRING),
 
-    POLYGON(ElementResourceTypeEnum.POLYGON);
+    POLYGON(ElementResourceTypeEnum.POLYGON),
+
+    MEDIA(ElementResourceTypeEnum.MEDIA);
 
     private ElementResourceTypeEnum typeEnum;
 
@@ -36,6 +38,10 @@ public enum ElementTypeEnum {
             return Optional.of(new ElementPolygonGeometry());
         }
 
+        if(MEDIA.typeEnum.getType() == val) {
+            return Optional.of(new ElementPictureGeometry());
+        }
+
         return Optional.empty();
     }
 

+ 15 - 0
Backend/cloud-sdk/src/main/java/com/dji/sdk/cloudapi/map/MapGroupElement.java

@@ -42,6 +42,11 @@ public class MapGroupElement {
     @Min(123456789012L)
     private Long updateTime;
 
+    @NotNull
+    @Schema(description = "element type")
+    private Integer elementType;
+
+
     @NotNull
     @Valid
     private ElementResource resource;
@@ -58,6 +63,7 @@ public class MapGroupElement {
                 ", createTime=" + createTime +
                 ", updateTime=" + updateTime +
                 ", resource=" + resource +
+                ", elementType=" + elementType +
                 '}';
     }
 
@@ -114,4 +120,13 @@ public class MapGroupElement {
         this.elementFrom = elementFrom;
         return this;
     }
+
+    public Integer getElementType() {
+        return elementType;
+    }
+
+    public MapGroupElement setElementType(Integer elementType) {
+        this.elementType = elementType;
+        return this;
+    }
 }

+ 1 - 0
Backend/sample/src/main/java/com/dji/sample/configuration/mvc/GlobalMVCConfigurer.java

@@ -29,6 +29,7 @@ public class GlobalMVCConfigurer implements WebMvcConfigurer {
     public void addInterceptors(InterceptorRegistry registry) {
         // Exclude the login interface.
         excludePaths.add("/" + managePrefix + manageVersion + "/login");
+        excludePaths.add("/" + managePrefix + manageVersion + "/getToken");
         excludePaths.add("/" + managePrefix + manageVersion + "/token/refresh");
         excludePaths.add("/swagger-ui.html");
         excludePaths.add("/swagger-ui/**");

+ 7 - 1
Backend/sample/src/main/java/com/dji/sample/manage/controller/LoginController.java

@@ -1,7 +1,6 @@
 package com.dji.sample.manage.controller;
 
 import com.dji.sample.common.error.CommonErrorEnum;
-import com.dji.sample.component.AuthInterceptor;
 import com.dji.sample.manage.model.dto.UserDTO;
 import com.dji.sample.manage.model.dto.UserLoginDTO;
 import com.dji.sample.manage.service.IUserService;
@@ -33,6 +32,13 @@ public class LoginController {
         return userService.userLogin(username, password, loginDTO.getFlag(),loginDTO.getGateway_sn());
     }
 
+    @PostMapping("/getToken")
+    public HttpResultResponse getToken(@RequestBody UserLoginDTO loginDTO) {
+        String username = loginDTO.getUsername();
+        String password = loginDTO.getPassword();
+        return userService.getToken(username, password);
+    }
+
     @PostMapping("/token/refresh")
     public HttpResultResponse refreshToken(HttpServletRequest request, HttpServletResponse response) {
         String token = request.getHeader(PARAM_TOKEN);

+ 23 - 0
Backend/sample/src/main/java/com/dji/sample/manage/controller/UserController.java

@@ -2,10 +2,12 @@ package com.dji.sample.manage.controller;
 
 import com.dji.sample.common.model.CustomClaim;
 import com.dji.sample.manage.model.dto.UserListDTO;
+import com.dji.sample.manage.model.dto.UserLoginDTO;
 import com.dji.sample.manage.service.IUserService;
 import com.dji.sdk.common.HttpResultResponse;
 import com.dji.sdk.common.PaginationData;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
@@ -61,4 +63,25 @@ public class UserController {
         userService.updateUser(workspaceId, userId, user);
         return HttpResultResponse.success();
     }
+
+    @PostMapping("/saveApiUser")
+    public HttpResultResponse getToken(@RequestBody UserLoginDTO loginDTO) {
+        String username = loginDTO.getUsername();
+        String password = loginDTO.getPassword();
+        String message = "";
+        if(!StringUtils.hasText(username)) {
+            message = "用户名不能为空!";
+        }
+
+        if(!StringUtils.hasText(password)) {
+            message = "密码不能为空!";
+        }
+
+        if(StringUtils.hasText(message)) {
+            return HttpResultResponse.error(message);
+        }
+        boolean isSucc = userService.saveApiUser(username, password);
+        return isSucc ? HttpResultResponse.success() : HttpResultResponse.error("添加失败");
+    }
+
 }

+ 6 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java

@@ -1,12 +1,18 @@
 package com.dji.sample.manage.model.entity;
 
 import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
 
 @TableName(value = "manage_user")
 @Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class UserEntity implements Serializable {
 
     @TableId(type = IdType.AUTO)

+ 2 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java

@@ -11,6 +11,8 @@ public enum UserTypeEnum {
 
     PILOT(2, "Pilot"),
 
+    API(3,"API"),
+
     UNKNOWN(-1, "Unknown");
 
     private int val;

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

@@ -26,6 +26,8 @@ public interface IUserService {
      */
     HttpResultResponse userLogin(String username, String password, Integer flag, String gatewaySn);
 
+    HttpResultResponse getToken(String username, String password);
+
     /**
      * Create a user object containing a new token.
      * @param token
@@ -40,6 +42,8 @@ public interface IUserService {
      */
     PaginationData<UserListDTO> getUsersByWorkspaceId(long page, long pageSize, String workspaceId);
 
+    Boolean saveApiUser(String username, String password);
+
     Boolean updateUser(String workspaceId, String userId, UserListDTO user);
 
     /**

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

@@ -35,6 +35,7 @@ import java.time.ZoneId;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 @Service
@@ -121,6 +122,40 @@ public class UserServiceImpl implements IUserService {
         return HttpResultResponse.success(userDTO);
     }
 
+    @Override
+    public HttpResultResponse getToken(String username, String password) {
+        UserEntity userEntity = this.getUserByUsername(username);
+        if (userEntity == null) {
+            return new HttpResultResponse()
+                    .setCode(HttpStatus.UNAUTHORIZED.value())
+                    .setMessage("invalid username");
+        }
+        if (UserTypeEnum.API.getVal() != userEntity.getUserType().intValue()) {
+            return HttpResultResponse.error("The account type does not match.");
+        }
+        if (!password.equals(userEntity.getPassword())) {
+            return new HttpResultResponse()
+                    .setCode(HttpStatus.UNAUTHORIZED.value())
+                    .setMessage("invalid password");
+        }
+
+        Optional<WorkspaceDTO> workspaceOpt = workspaceService.getWorkspaceByWorkspaceId(userEntity.getWorkspaceId());
+        if (workspaceOpt.isEmpty()) {
+            return new HttpResultResponse()
+                    .setCode(HttpStatus.UNAUTHORIZED.value())
+                    .setMessage("invalid workspace id:" + userEntity.getWorkspaceId());
+        }
+
+        CustomClaim customClaim = new CustomClaim(userEntity.getUserId(),
+                userEntity.getUsername(), userEntity.getUserType(),
+                workspaceOpt.get().getWorkspaceId());
+
+        // create token
+        String token = JwtUtil.createToken(customClaim.convertToMap());
+
+        return HttpResultResponse.success(token);
+    }
+
     @Override
     public Optional<UserDTO> refreshToken(String token) {
         if (!StringUtils.hasText(token)) {
@@ -160,6 +195,26 @@ public class UserServiceImpl implements IUserService {
         return new PaginationData<>(usersList, new Pagination(userEntityPage.getCurrent(), userEntityPage.getSize(), userEntityPage.getTotal()));
     }
 
+    @Override
+    public Boolean saveApiUser(String username,String password) {
+        if(!StringUtils.hasText(username)) {
+            throw new RuntimeException("用户名不能为空!");
+        }
+
+        if(!StringUtils.hasText(password)) {
+            throw new RuntimeException("密码不能为空!");
+        }
+        long curTime = System.currentTimeMillis();
+        return mapper.insert(UserEntity.builder().
+                userId(UUID.randomUUID().toString())
+                .username(username)
+                .password(password)
+                .userType(UserTypeEnum.API.getVal())
+                .createTime(curTime)
+                .updateTime(curTime)
+                .build()) > 0;
+    }
+
     @Override
     public Boolean updateUser(String workspaceId, String userId, UserListDTO user) {
         UserEntity userEntity = mapper.selectOne(

+ 4 - 0
Backend/sample/src/main/java/com/dji/sample/map/service/IGroupElementService.java

@@ -1,7 +1,9 @@
 package com.dji.sample.map.service;
 
 import com.dji.sample.map.model.dto.GroupElementDTO;
+import com.dji.sample.map.model.entity.GroupElementEntity;
 import com.dji.sdk.cloudapi.map.CreateMapElementRequest;
+import com.dji.sdk.cloudapi.map.ElementCoordinate;
 import com.dji.sdk.cloudapi.map.MapGroupElement;
 import com.dji.sdk.cloudapi.map.UpdateMapElementRequest;
 
@@ -31,6 +33,8 @@ public interface IGroupElementService {
      */
     Boolean saveElement(String groupId, Integer elementFrom, CreateMapElementRequest elementCreate);
 
+    Boolean saveElement(String groupId, Integer elementFrom, GroupElementEntity groupElement, ElementCoordinate coordinate);
+
     /**
      * Query the element information based on the element id and update element.
      * @param elementId

+ 2 - 1
Backend/sample/src/main/java/com/dji/sample/map/service/IGroupService.java

@@ -1,6 +1,7 @@
 package com.dji.sample.map.service;
 
 import com.dji.sdk.cloudapi.map.GetMapElementsResponse;
+import com.dji.sdk.cloudapi.map.GroupTypeEnum;
 
 import java.util.List;
 import java.util.Optional;
@@ -27,5 +28,5 @@ public interface IGroupService {
      * @param workspaceId
      * @return
      */
-    Optional<GetMapElementsResponse> getCustomGroupByWorkspaceId(String workspaceId);
+    Optional<GetMapElementsResponse> getGroupByWorkspaceId(String workspaceId, GroupTypeEnum groupType);
 }

+ 2 - 2
Backend/sample/src/main/java/com/dji/sample/map/service/impl/FlightAreaServiceImpl.java

@@ -90,7 +90,7 @@ public class FlightAreaServiceImpl extends AbstractFlightAreaService implements
 
     @Override
     public List<FlightAreaDTO> getFlightAreaList(String workspaceId) {
-        Optional<List<GetMapElementsResponse>> elementsOpt = groupService.getCustomGroupByWorkspaceId(workspaceId)
+        Optional<List<GetMapElementsResponse>> elementsOpt = groupService.getGroupByWorkspaceId(workspaceId,GroupTypeEnum.CUSTOM)
                 .map(group -> workspaceElementService.getAllGroupsByWorkspaceId(workspaceId, group.getId(), null));
         if (elementsOpt.isEmpty()) {
             return Collections.emptyList();
@@ -104,7 +104,7 @@ public class FlightAreaServiceImpl extends AbstractFlightAreaService implements
 
     @Override
     public void createFlightArea(String workspaceId, String username, PostFlightAreaParam param) {
-        Optional<GetMapElementsResponse> groupOpt = groupService.getCustomGroupByWorkspaceId(workspaceId);
+        Optional<GetMapElementsResponse> groupOpt = groupService.getGroupByWorkspaceId(workspaceId,GroupTypeEnum.CUSTOM);
         if (groupOpt.isEmpty()) {
             throw new RuntimeException("The custom flight area group does not exist, please create it first.");
         }

+ 14 - 5
Backend/sample/src/main/java/com/dji/sample/map/service/impl/GroupElementServiceImpl.java

@@ -49,11 +49,6 @@ public class GroupElementServiceImpl implements IGroupElementService {
 
     @Override
     public Boolean saveElement(String groupId, Integer elementFrom, CreateMapElementRequest elementCreate) {
-        //获取序号
-//        Integer elementCount = mapper.selectCount(new LambdaQueryWrapper<GroupElementEntity>()
-//                .eq(GroupElementEntity::getGroupId, groupId)
-//                .eq(GroupElementEntity::getElementType,ElementTypeEnum.findVal(elementCreate.getResource().getContent().getGeometry().getType())));
-
         Optional<GroupElementEntity> groupElementOpt = this.getEntityByElementId(elementCreate.getId());
 
         if (groupElementOpt.isPresent()) {
@@ -71,6 +66,19 @@ public class GroupElementServiceImpl implements IGroupElementService {
                 elementCreate.getResource().getContent().getGeometry().convertToList(), elementCreate.getId());
     }
 
+    @Override
+    public Boolean saveElement(String groupId, Integer elementFrom, GroupElementEntity groupElement, ElementCoordinate coordinate) {
+        boolean saveElement = mapper.insert(groupElement) > 0;
+        if (!saveElement) {
+            return false;
+        }
+        List<ElementCoordinate> coordinateList = new ArrayList<ElementCoordinate>();
+        coordinateList.add(coordinate);
+        // save coordinate
+        return elementCoordinateService.saveCoordinate(
+                coordinateList, groupElement.getElementId());
+    }
+
     @Override
     public Boolean updateElement(String elementId, UpdateMapElementRequest elementUpdate, String username) {
         Optional<GroupElementEntity> groupElementOpt = this.getEntityByElementId(elementId);
@@ -178,6 +186,7 @@ public class GroupElementServiceImpl implements IGroupElementService {
                 .setId(entity.getElementId())
                 .setName(entity.getElementName())
                 .setElementFrom(entity.getElementFrom())
+                .setElementType(entity.getElementType())
                 .setCreateTime(entity.getCreateTime())
                 .setUpdateTime(entity.getUpdateTime())
                 .setResource(new ElementResource()

+ 23 - 3
Backend/sample/src/main/java/com/dji/sample/map/service/impl/GroupServiceImpl.java

@@ -58,7 +58,7 @@ public class GroupServiceImpl implements IGroupService {
     private void createDefaultGroups(String workspaceId) {
         int count = mapper.selectCount(new LambdaQueryWrapper<GroupEntity>()
                 .eq(GroupEntity::getWorkspaceId, workspaceId));
-        if(count <= 0) {
+        if(count <= 0 && StringUtils.hasText(workspaceId)) {
             //创建默认文件夹
             mapper.insert(GroupEntity.builder().groupId(UUID.randomUUID().toString())
                     .groupName(PILOT_SHARE_LAYER)
@@ -75,15 +75,35 @@ public class GroupServiceImpl implements IGroupService {
                     .createTime(System.currentTimeMillis())
                     .updateTime(System.currentTimeMillis())
                     .build());
+
+            //创建默认标注文件夹
+            mapper.insert(GroupEntity.builder().groupId(UUID.randomUUID().toString())
+                    .groupName(DEFAULT_LAYER)
+                    .groupType(GroupTypeEnum.DEFAULT.getType())
+                    .workspaceId(workspaceId)
+                    .createTime(System.currentTimeMillis())
+                    .updateTime(System.currentTimeMillis())
+                    .enabled(false)
+                    .build());
+
+            //创建自定义飞行范围文件夹
+            mapper.insert(GroupEntity.builder().groupId(UUID.randomUUID().toString())
+                    .groupName(CUSTOM_FLIGHT_AREA)
+                    .groupType(GroupTypeEnum.CUSTOM.getType())
+                    .workspaceId(workspaceId)
+                    .createTime(System.currentTimeMillis())
+                    .updateTime(System.currentTimeMillis())
+                    .enabled(false)
+                    .build());
         }
     }
 
     @Override
-    public Optional<GetMapElementsResponse> getCustomGroupByWorkspaceId(String workspaceId) {
+    public Optional<GetMapElementsResponse> getGroupByWorkspaceId(String workspaceId, GroupTypeEnum groupType) {
         return Optional.ofNullable(mapper.selectOne(
                 Wrappers.lambdaQuery(GroupEntity.class)
                         .eq(GroupEntity::getWorkspaceId, workspaceId)
-                        .eq(GroupEntity::getGroupType, GroupTypeEnum.CUSTOM.getType())
+                        .eq(GroupEntity::getGroupType, groupType.getType())
                         .last(" limit 1")))
                 .map(this::entityConvertToDto);
     }

+ 9 - 0
Backend/sample/src/main/java/com/dji/sample/map/service/impl/WorkspaceElementServiceImpl.java

@@ -7,6 +7,7 @@ import com.dji.sample.map.service.IElementCoordinateService;
 import com.dji.sample.map.service.IGroupElementService;
 import com.dji.sample.map.service.IGroupService;
 import com.dji.sample.map.service.IWorkspaceElementService;
+import com.dji.sample.media.service.IFileService;
 import com.dji.sdk.cloudapi.map.*;
 import com.dji.sdk.common.HttpResultResponse;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * @author sean
@@ -37,10 +39,17 @@ public class WorkspaceElementServiceImpl implements IWorkspaceElementService {
     @Autowired
     private IWebSocketMessageService webSocketMessageService;
 
+    @Autowired
+    private IFileService fileService;
+
     @Override
     public List<GetMapElementsResponse> getAllGroupsByWorkspaceId(String workspaceId, String groupId, Boolean isDistributed) {
         List<GetMapElementsResponse> groupList = groupService.getAllGroupsByWorkspaceId(workspaceId, groupId, isDistributed);
         groupList.forEach(group -> group.setElements(groupElementService.getElementsByGroupId(group.getId())));
+        groupList.forEach(group -> group.getElements().stream().filter(
+                e -> ElementResourceTypeEnum.MEDIA.getType() == e.getElementType()).collect(Collectors.toList())
+                .forEach(e -> e.getResource().getContent().setPicture(fileService.getMediaFileByElementId(workspaceId,e.getId()))));
+
         return groupList;
     }
 

+ 43 - 0
Backend/sample/src/main/java/com/dji/sample/media/controller/FileController.java

@@ -9,15 +9,19 @@ import com.dji.sample.media.model.MediaDirDTO;
 import com.dji.sample.media.model.MediaFileDTO;
 import com.dji.sample.media.service.IFileService;
 import com.dji.sample.media.service.IMediaDirService;
+import com.dji.sdk.cloudapi.map.CreateMapElementRequest;
+import com.dji.sdk.cloudapi.map.CreateMapElementResponse;
 import com.dji.sdk.common.HttpResultResponse;
 import com.dji.sdk.common.PaginationData;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import java.io.IOException;
@@ -180,4 +184,43 @@ public class FileController {
         boolean isUpd = fileService.updateFile(mediaFile);
         return isUpd ? HttpResultResponse.success() : HttpResultResponse.error();
     }
+
+    /**
+     * 创建图片元素
+     * @param workspaceId
+     * @param fileId
+     * @param req
+     * @return
+     */
+    @PostMapping("/workspaces/{workspace_id}/createMapElement/{file_id}")
+    HttpResultResponse<MediaFileDTO> createMapElement(
+            @PathVariable(name = "workspace_id") String workspaceId,
+            @PathVariable(name = "file_id") String fileId,
+            HttpServletRequest req) {
+        CustomClaim claims = (CustomClaim) req.getAttribute(TOKEN_CLAIM);
+        MediaFileDTO mediaFile = fileService.getMediaFileByFileId(workspaceId,fileId);
+        if(StringUtils.hasText(mediaFile.getElementId())) {
+            return HttpResultResponse.error("该图片已存在地图元素,请不要重复创建!");
+        }
+        boolean isSucc = fileService.createMediaElement(workspaceId,claims.getUserType(),mediaFile);
+        return isSucc ? HttpResultResponse.success(mediaFile) : HttpResultResponse.error();
+
+    }
+
+    /**
+     * 删除图片元素
+     * @param workspaceId
+     * @param fileId
+     * @return
+     */
+    @DeleteMapping("/workspaces/{workspace_id}/deleteMapElement/{file_id}")
+    public HttpResultResponse deleteMapElement(@PathVariable(name = "workspace_id") String workspaceId,
+                                               @PathVariable(name = "file_id") String fileId) {
+        MediaFileDTO mediaFile = fileService.getMediaFileByFileId(workspaceId,fileId);
+        if(!StringUtils.hasText(mediaFile.getElementId())) {
+            return HttpResultResponse.success();
+        }
+        fileService.deleteMediaElement(workspaceId,mediaFile);
+        return HttpResultResponse.success();
+    }
 }

+ 2 - 0
Backend/sample/src/main/java/com/dji/sample/media/model/MediaFileDTO.java

@@ -92,4 +92,6 @@ public class MediaFileDTO {
 
     private Integer durationSeconds;
 
+    private String elementId;
+
 }

+ 3 - 0
Backend/sample/src/main/java/com/dji/sample/media/model/MediaFileEntity.java

@@ -126,5 +126,8 @@ public class MediaFileEntity implements Serializable {
     @TableField("duration_seconds")
     private Integer durationSeconds;
 
+    @TableField(value = "element_id")
+    private String elementId;
+
 }
 

+ 9 - 0
Backend/sample/src/main/java/com/dji/sample/media/service/IFileService.java

@@ -3,6 +3,7 @@ package com.dji.sample.media.service;
 import com.dji.sample.map.model.param.MediaFileQueryParam;
 import com.dji.sample.media.model.MediaFileDTO;
 import com.dji.sample.media.model.MediaFileEntity;
+import com.dji.sdk.cloudapi.map.ElementPicture;
 import com.dji.sdk.cloudapi.media.MediaUploadCallbackRequest;
 import com.dji.sdk.common.PaginationData;
 import org.springframework.web.multipart.MultipartFile;
@@ -21,6 +22,8 @@ public interface IFileService {
 
     MediaFileDTO getMediaFileByFileId(String workspaceId, String fileId);
 
+    ElementPicture getMediaFileByElementId(String workspaceId, String elementId);
+
     /**
      * Query if the file already exists based on the workspace id and the fingerprint of the file.
      * @param workspaceId
@@ -93,4 +96,10 @@ public interface IFileService {
     Map<Integer,Long> getParentDirSize(List<Integer> dirIds);
 
     Boolean updateFile(MediaFileDTO mediaFileDTO);
+
+    Boolean updateElementId(MediaFileDTO mediaFileDTO);
+
+    boolean createMediaElement(String workspaceId, Integer elementFrom, MediaFileDTO mediaFileDTO);
+
+    boolean deleteMediaElement(String workspaceId, MediaFileDTO mediaFileDTO);
 }

+ 78 - 6
Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

@@ -10,10 +10,12 @@ import com.dji.sample.common.util.ThumbnailatorUtil;
 import com.dji.sample.common.util.UserRequest;
 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.manage.model.dto.DeviceDictionaryDTO;
 import com.dji.sample.manage.service.IDeviceDictionaryService;
+import com.dji.sample.map.model.entity.GroupElementEntity;
 import com.dji.sample.map.model.param.MediaFileQueryParam;
+import com.dji.sample.map.service.IGroupElementService;
+import com.dji.sample.map.service.IGroupService;
 import com.dji.sample.media.dao.IFileMapper;
 import com.dji.sample.media.dao.IFileSumMapper;
 import com.dji.sample.media.model.*;
@@ -21,6 +23,7 @@ import com.dji.sample.media.service.IFileService;
 import com.dji.sample.media.service.IMediaDirService;
 import com.dji.sample.wayline.service.IWaylineFileService;
 import com.dji.sdk.cloudapi.device.DeviceEnum;
+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;
@@ -76,6 +79,12 @@ public class FileServiceImpl implements IFileService {
     @Autowired
     private  IWaylineFileService waylineFileService;
 
+    @Autowired
+    private  IGroupElementService groupElementService;
+
+    @Autowired
+    private  IGroupService groupService;
+
     private static final String IMAGE = "image";
     private static final String VIDEO = "video";
     private static final String TAIL = "_100x100";
@@ -100,6 +109,16 @@ public class FileServiceImpl implements IFileService {
        return entityConvertToDto(fileEntity);
     }
 
+    @Override
+    public ElementPicture getMediaFileByElementId(String workspaceId, String elementId) {
+        MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
+                .eq(MediaFileEntity::getWorkspaceId, workspaceId)
+                .eq(MediaFileEntity::getElementId, elementId)
+                .last(" limit 1 "));
+        String thumbnailURL = getThumbnailURL(fileEntity);
+        return new ElementPicture().setFileId(fileEntity.getFileId()).setMediaType(fileEntity.getMediaType()).setThumbnailUrl(thumbnailURL);
+    }
+
     private Optional<MediaFileEntity> getMediaByFileId(String workspaceId, String fileId) {
         MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
                 .eq(MediaFileEntity::getWorkspaceId, workspaceId)
@@ -428,7 +447,8 @@ public class FileServiceImpl implements IFileService {
                     .mediaType(mediaTypeEnum.getVal())
                     .mediaTypeText(mediaTypeEnum.getText())
                     .pictureType(entity.getPictureType())
-                    .durationSeconds(entity.getDurationSeconds());
+                    .durationSeconds(entity.getDurationSeconds())
+                    .elementId(entity.getElementId());
 
         }
 
@@ -439,9 +459,9 @@ public class FileServiceImpl implements IFileService {
         String originFileName = entity.getFileName();
         //缩略图路径
         String tObjectKey = getThumbnailObjectKey(originFileName);
-        if(!putThumbnailImage(tObjectKey,entity.getObjectKey(),false)) {
-            return null;
-        }
+//        if(!putThumbnailImage(tObjectKey,entity.getObjectKey(),false)) {
+//            return null;
+//        }
         return ossService.getObjectUrl(OssConfiguration.bucket, tObjectKey).toString();
 
     }
@@ -631,6 +651,57 @@ public class FileServiceImpl implements IFileService {
         return update > 0;
     }
 
+    @Override
+    public Boolean updateElementId(MediaFileDTO mediaFileDTO) {
+        int update = mapper.update(null,
+                new LambdaUpdateWrapper<MediaFileEntity>().set(MediaFileEntity::getElementId,mediaFileDTO.getElementId())
+                        .eq(MediaFileEntity::getFileId, mediaFileDTO.getFileId()));
+        return update > 0;
+    }
+
+    @Override
+    public boolean createMediaElement(String workspaceId, Integer elementFrom, MediaFileDTO mediaFileDTO) {
+        Optional<GetMapElementsResponse> groupOpt = groupService.getGroupByWorkspaceId(workspaceId,GroupTypeEnum.PICTURE);
+        if (groupOpt.isEmpty()) {
+            throw new RuntimeException("图片标注文件夹不存在");
+        }
+        //保存图片地图元素
+        String elementId = UUID.randomUUID().toString();
+        GroupElementEntity groupElementEntity = GroupElementEntity.builder()
+                .groupId(groupOpt.get().getId())
+                .elementId(elementId)
+                .elementName(mediaFileDTO.getFileName())
+                .username(UserRequest.getCurrentUser().getUsername())
+                .elementType(ElementResourceTypeEnum.MEDIA.getType())
+                .elementFrom(elementFrom)
+                .build();
+        ElementCoordinate elementCoordinate = new ElementCoordinate();
+        elementCoordinate.setAltitude(mediaFileDTO.getRelativeAltitude().doubleValue());
+        elementCoordinate.setLatitude(mediaFileDTO.getLatitude().doubleValue());
+        elementCoordinate.setLongitude(mediaFileDTO.getLongitude().doubleValue());
+        boolean isSuccess = groupElementService.saveElement(groupOpt.get().getId(),elementFrom,groupElementEntity,elementCoordinate);
+        //更新图片中的elementId
+        if(isSuccess) {
+            mediaFileDTO.setElementId(elementId);
+            return updateFile(mediaFileDTO);
+        };
+        return false;
+    }
+
+    @Override
+    public boolean deleteMediaElement(String workspaceId, MediaFileDTO mediaFileDTO) {
+        if(!StringUtils.hasText(mediaFileDTO.getElementId())) {
+            return false;
+        }
+        boolean isSucc = groupElementService.deleteElement(mediaFileDTO.getElementId());
+        if(isSucc) {
+            mediaFileDTO.setElementId(null);
+            return updateElementId(mediaFileDTO);
+        }
+        return false;
+    }
+
+
     private MediaFileEntity dtoToEntity(MediaFileDTO mediaFileDTO) {
         MediaFileEntity.MediaFileEntityBuilder builder = MediaFileEntity.builder();
 
@@ -666,7 +737,8 @@ public class FileServiceImpl implements IFileService {
                     .longitudeRef(mediaFileDTO.getLongitudeRef())
                     .latitudeRef(mediaFileDTO.getLatitudeRef())
                     .pictureType(mediaFileDTO.getPictureType())
-                    .durationSeconds(mediaFileDTO.getDurationSeconds());
+                    .durationSeconds(mediaFileDTO.getDurationSeconds())
+                    .elementId(mediaFileDTO.getElementId());
         }
 
         return builder.build();