Browse Source

Merge branch 'release' into project-jmga-v1.4.0

# Conflicts:
#	src/main/java/com/fdkankan/openApi/generate/AutoGenerate.java
#	src/main/java/com/fdkankan/openApi/service/system/IAccountService.java
#	src/main/java/com/fdkankan/openApi/service/system/impl/AccountServiceImpl.java
dengsixing 1 năm trước cách đây
mục cha
commit
32e6d693bb
51 tập tin đã thay đổi với 1833 bổ sung47 xóa
  1. 26 2
      pom.xml
  2. 22 0
      src/main/java/com/fdkankan/openApi/bean/vo/SceneDataDownloadVO.java
  3. 48 0
      src/main/java/com/fdkankan/openApi/config/ScheduledConfig.java
  4. 7 0
      src/main/java/com/fdkankan/openApi/controller/system/SsoUserController.java
  5. 22 1
      src/main/java/com/fdkankan/openApi/controller/www/SceneController.java
  6. 50 0
      src/main/java/com/fdkankan/openApi/controller/www/SceneDynamicPanelController.java
  7. 44 5
      src/main/java/com/fdkankan/openApi/controller/www/SceneMarkShapeController.java
  8. 22 1
      src/main/java/com/fdkankan/openApi/controller/www/UserController.java
  9. 11 1
      src/main/java/com/fdkankan/openApi/controller/www/VirtualSceneController.java
  10. 24 0
      src/main/java/com/fdkankan/openApi/dto/SceneJsonDTO.java
  11. 38 0
      src/main/java/com/fdkankan/openApi/dto/SceneMarkShapeBoxPostDTO.java
  12. 48 0
      src/main/java/com/fdkankan/openApi/dto/SceneMarkShapeDTO.java
  13. 29 0
      src/main/java/com/fdkankan/openApi/dto/SceneMarkShapesDTO.java
  14. 15 0
      src/main/java/com/fdkankan/openApi/entity/laser/SceneEntity.java
  15. 37 0
      src/main/java/com/fdkankan/openApi/entity/system/SceneDataDownloadEntity.java
  16. 66 0
      src/main/java/com/fdkankan/openApi/entity/www/SceneDynamicPanel.java
  17. 57 0
      src/main/java/com/fdkankan/openApi/entity/www/SceneMarkShapeBox.java
  18. 2 1
      src/main/java/com/fdkankan/openApi/exception/OpenApiGlobalExceptionHandler.java
  19. 21 0
      src/main/java/com/fdkankan/openApi/httpclient/client/ShapesBoxClient.java
  20. 16 0
      src/main/java/com/fdkankan/openApi/mapper/system/SceneDataDownloadMapper.java
  21. 7 0
      src/main/java/com/fdkankan/openApi/mapper/www/IMarkShapeMapper.java
  22. 18 0
      src/main/java/com/fdkankan/openApi/mapper/www/ISceneDynamicPanelMapper.java
  23. 16 0
      src/main/java/com/fdkankan/openApi/mapper/www/MarkShapeBoxMapper.java
  24. 1 1
      src/main/java/com/fdkankan/openApi/service/laser/impl/SceneServiceImpl.java
  25. 2 1
      src/main/java/com/fdkankan/openApi/service/system/IAccountService.java
  26. 22 0
      src/main/java/com/fdkankan/openApi/service/system/SceneDataDownloadService.java
  27. 11 1
      src/main/java/com/fdkankan/openApi/service/system/impl/AccountServiceImpl.java
  28. 187 0
      src/main/java/com/fdkankan/openApi/service/system/impl/SceneDataDownloadServiceImpl.java
  29. 21 0
      src/main/java/com/fdkankan/openApi/service/www/ISceneDynamicPanelService.java
  30. 3 1
      src/main/java/com/fdkankan/openApi/service/www/ISceneEditInfoService.java
  31. 29 0
      src/main/java/com/fdkankan/openApi/service/www/ISceneMarkShapeBoxService.java
  32. 7 0
      src/main/java/com/fdkankan/openApi/service/www/ISceneMarkShapeService.java
  33. 2 0
      src/main/java/com/fdkankan/openApi/service/www/IScenePlusService.java
  34. 6 0
      src/main/java/com/fdkankan/openApi/service/www/IUserService.java
  35. 128 0
      src/main/java/com/fdkankan/openApi/service/www/impl/SceneDynamicPanelServiceImpl.java
  36. 11 1
      src/main/java/com/fdkankan/openApi/service/www/impl/SceneEditInfoServiceImpl.java
  37. 151 0
      src/main/java/com/fdkankan/openApi/service/www/impl/SceneMarkShapeBoxServiceImpl.java
  38. 31 4
      src/main/java/com/fdkankan/openApi/service/www/impl/SceneMarkShapeServiceImpl.java
  39. 141 6
      src/main/java/com/fdkankan/openApi/service/www/impl/ScenePlusServiceImpl.java
  40. 21 0
      src/main/java/com/fdkankan/openApi/service/www/impl/UserServiceImpl.java
  41. 69 0
      src/main/java/com/fdkankan/openApi/task/SceneOssDataTask.java
  42. 202 0
      src/main/java/com/fdkankan/openApi/util/DateUtils.java
  43. 55 0
      src/main/java/com/fdkankan/openApi/util/ExcelHutoolUtil.java
  44. 6 0
      src/main/java/com/fdkankan/openApi/vo/system/LoginParam.java
  45. 16 0
      src/main/java/com/fdkankan/openApi/vo/www/FdkkLoginParamVo.java
  46. 16 0
      src/main/java/com/fdkankan/openApi/vo/www/SceneDynamicPanelParamVO.java
  47. 20 19
      src/main/resources/bootstrap-dev.yml
  48. 1 1
      src/main/resources/bootstrap-test-eur.yml
  49. 6 1
      src/main/resources/bootstrap.yml
  50. 5 0
      src/main/resources/mapper/www/SceneDynamicPanelMapper.xml
  51. 17 0
      src/main/resources/mapper/www/SceneMarkShapeMapper.xml

+ 26 - 2
pom.xml

@@ -30,6 +30,7 @@
         <protobuf-java.version>3.2.0</protobuf-java.version>
         <commons-pool2.version>2.5.0</commons-pool2.version>
         <zxing.version>2.1</zxing.version>
+        <poi.version>4.1.2</poi.version>
     </properties>
     <dependencies>
         <dependency>
@@ -61,10 +62,28 @@
                     <groupId>com.aliyun</groupId>
                     <artifactId>aliyun-java-sdk-core</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.apache.poi</groupId>
+                    <artifactId>poi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.poi</groupId>
+                    <artifactId>poi-ooxml</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-web</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
         <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>5.2.16.RELEASE</version>
+        </dependency>
+
+        <dependency>
             <groupId>com.fdkankan</groupId>
             <artifactId>4dkankan-utils-redis</artifactId>
             <version>3.0.0-SNAPSHOT</version>
@@ -89,7 +108,7 @@
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
-            <version>3.6.1</version>
+            <version>4.2.0</version>
         </dependency>
         <dependency>
             <groupId>com.yomahub</groupId>
@@ -212,6 +231,12 @@
             <artifactId>guava</artifactId>
             <version>30.1-jre</version>
         </dependency>
+        <!-- excel工具 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
 
     </dependencies>
     <dependencyManagement>
@@ -318,7 +343,6 @@
                 <artifactId>log4j-to-slf4j</artifactId>
                 <version>2.17.0</version>
             </dependency>
-
         </dependencies>
     </dependencyManagement>
 

+ 22 - 0
src/main/java/com/fdkankan/openApi/bean/vo/SceneDataDownloadVO.java

@@ -0,0 +1,22 @@
+package com.fdkankan.openApi.bean.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+
+/**
+ * Created by Xiewj 2022年11月21日11:15:28
+ * 配置表
+ */
+@Data
+@AllArgsConstructor
+public class SceneDataDownloadVO  {
+
+   /** "文件名") */
+    private String fileName;
+
+   /** "oss路径") */
+    private String url;
+
+
+}

+ 48 - 0
src/main/java/com/fdkankan/openApi/config/ScheduledConfig.java

@@ -0,0 +1,48 @@
+package com.fdkankan.openApi.config;
+
+import org.springframework.boot.autoconfigure.batch.BatchProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+import org.springframework.util.CollectionUtils;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.concurrent.Executors;
+
+@Configuration
+public class ScheduledConfig implements SchedulingConfigurer {
+
+    /**
+     * 此配置实现:
+     * 1、同一个定时任务等待上一次执行完毕后再执行
+     * 2、不同定时任务同时执行
+     * @param taskRegistrar
+     */
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+        Method[] methods = BatchProperties.Job.class.getMethods();
+        int defaultPoolSize = 3;
+        int corePoolSize = 0;
+
+        if (!CollectionUtils.isEmpty(Arrays.asList(methods))) {
+
+            for (Method method : methods) {
+
+                Scheduled annotation = method.getAnnotation(Scheduled.class);
+
+                if (annotation != null) {
+
+                    corePoolSize++;
+                }
+            }
+            if (defaultPoolSize > corePoolSize) {
+
+                corePoolSize = defaultPoolSize;
+            }
+
+            taskRegistrar.setScheduler(Executors.newScheduledThreadPool(corePoolSize));
+        }
+    }
+}

+ 7 - 0
src/main/java/com/fdkankan/openApi/controller/system/SsoUserController.java

@@ -70,6 +70,13 @@ public class SsoUserController extends BaseController {
         return accountService.listApp(param);
     }
 
+    @SaIgnore
+    @PostMapping("app/delete")
+    public ResultData deleteApp(@RequestBody @Validated UpdateAppUserParamVo param){
+        accountService.deleteApp(param);
+        return ResultData.ok();
+    }
+
 
 }
 

+ 22 - 1
src/main/java/com/fdkankan/openApi/controller/www/SceneController.java

@@ -4,12 +4,14 @@ package com.fdkankan.openApi.controller.www;
 import cn.dev33.satoken.annotation.SaIgnore;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.exception.BusinessException;
-import com.fdkankan.openApi.common.PageInfo;
 import com.fdkankan.openApi.aop.RedisLimit;
 import com.fdkankan.openApi.aop.ValidateApi;
+import com.fdkankan.openApi.common.PageInfo;
 import com.fdkankan.openApi.controller.BaseController;
+import com.fdkankan.openApi.entity.laser.SceneEntity;
 import com.fdkankan.openApi.entity.www.ScenePlus;
 import com.fdkankan.openApi.service.laser.SceneService;
+import com.fdkankan.openApi.service.system.SceneDataDownloadService;
 import com.fdkankan.openApi.service.www.IScenePlusService;
 import com.fdkankan.openApi.vo.BaseSceneParamVo;
 import com.fdkankan.openApi.vo.www.PageScenesParamVo;
@@ -38,6 +40,8 @@ public class SceneController extends BaseController {
 
     @Autowired
     private SceneService sceneService;
+    @Autowired
+    private SceneDataDownloadService sceneDataDownloadService;
 
     /**
      * 获取场景列表
@@ -124,5 +128,22 @@ public class SceneController extends BaseController {
     public ResultData getSceneVideo(@RequestBody @Validated BaseSceneParamVo param) {
         return ResultData.ok(scenePlusService.getSceneVideo(param.getSceneCode(), this.getUserId()));
     }
+    /**
+     * 获取点云和深度图接口
+     * @return
+     */
+    @SaIgnore
+    @PostMapping("/getSceneRaw")
+    @RedisLimit(name = "scene/getSceneRaw", limitCount = 1, period = 1)
+    @ValidateApi(method = "scene:getSceneRaw")
+    public ResultData getSceneRaw(@RequestBody @Validated BaseSceneParamVo param) {
+        ScenePlus scenePlus = scenePlusService.getByNumAndUserId(this.getUserId(), param.getSceneCode());
+        if (ObjectUtils.isEmpty(scenePlus)) {
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005.code(),"未找到该场景");
+        }
+        SceneEntity sceneEntity = sceneService.findBySceneCode(param.getSceneCode());
+        return sceneDataDownloadService.sceneDownloadDepthMapAndPly(param.getSceneCode(),this.getUserId(),sceneEntity);
+    }
+
 }
 

+ 50 - 0
src/main/java/com/fdkankan/openApi/controller/www/SceneDynamicPanelController.java

@@ -0,0 +1,50 @@
+package com.fdkankan.openApi.controller.www;
+
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import com.fdkankan.openApi.aop.RedisLimit;
+import com.fdkankan.openApi.aop.ValidateApi;
+import com.fdkankan.openApi.controller.BaseController;
+import com.fdkankan.openApi.service.www.ISceneDynamicPanelService;
+import com.fdkankan.openApi.vo.www.SceneDynamicPanelParamVO;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.io.IOException;
+
+/**
+ * <p>
+ * 场景动态面板 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2024-05-21
+ */
+@RestController
+@RequestMapping("/scene/dynamicPanel")
+public class SceneDynamicPanelController extends BaseController {
+
+    @Autowired
+    private ISceneDynamicPanelService sceneDynamicPanelService;
+
+    /**
+     * 动态面板文本推送
+     * @param param
+     * @return
+     */
+    @SaIgnore
+    @PostMapping("/save")
+    @RedisLimit(name = "scene/dynamicPanel/save", limitCount = 1, period = 30)
+    @ValidateApi(method = "scene:dynamicPanel:save")
+    public ResultData save(@RequestBody @Valid SceneDynamicPanelParamVO param) throws IOException {
+        sceneDynamicPanelService.save(this.getUserId(), param);
+        return ResultData.ok();
+    }
+
+}
+

+ 44 - 5
src/main/java/com/fdkankan/openApi/controller/www/SceneMarkShapeController.java

@@ -4,6 +4,10 @@ import cn.dev33.satoken.annotation.SaIgnore;
 import com.fdkankan.openApi.aop.RedisLimit;
 import com.fdkankan.openApi.aop.ValidateApi;
 import com.fdkankan.openApi.controller.BaseController;
+import com.fdkankan.openApi.dto.SceneJsonDTO;
+import com.fdkankan.openApi.dto.SceneMarkShapesDTO;
+import com.fdkankan.openApi.entity.www.SceneMarkShapeBox;
+import com.fdkankan.openApi.service.www.ISceneMarkShapeBoxService;
 import com.fdkankan.openApi.service.www.ISceneMarkShapeService;
 import com.fdkankan.openApi.vo.www.SceneMarkShapeParamVO;
 import com.fdkankan.openApi.vo.www.SceneMarkShapeVO;
@@ -11,10 +15,10 @@ import com.fdkankan.web.response.ResultData;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
 /**
  * <p>
  *  标注信息前端控制器
@@ -30,6 +34,8 @@ public class SceneMarkShapeController extends BaseController
 {
     @Autowired
     private ISceneMarkShapeService sceneMarkShapeService;
+    @Autowired
+    private ISceneMarkShapeBoxService sceneMarkShapeBoxService;
 
     /**
      * 根据场景码和图片名称获取数据
@@ -50,9 +56,42 @@ public class SceneMarkShapeController extends BaseController
     @PostMapping("/saveOrEdit")
     @RedisLimit(limitCount = 100, period = 1)
     @ValidateApi(method = "scene:saveOrEdit")
-    public ResultData saveOrEdit(@RequestBody  @Validated  SceneMarkShapeVO param) {
+    public ResultData saveOrEdit(@RequestBody @Validated SceneMarkShapeVO param) {
         this.checkScene(param.getNum());
         return sceneMarkShapeService.saveOrEdit(param);
     }
 
+    /**
+     *
+     */
+    @SaIgnore
+    @RedisLimit(limitCount = 100, period = 1)
+    @PostMapping("/planeCovert")
+    @ValidateApi(method = "scene:planeCovert")
+    public ResultData planeCovert(@RequestBody @Valid SceneMarkShapesDTO param) {
+        this.checkScene(param.getNum());
+        sceneMarkShapeService.saveOrEditBatch(param);
+        SceneMarkShapeBox sceneMarkShapeBox = sceneMarkShapeBoxService.planeCovert(param.getNum());
+        return ResultData.ok(sceneMarkShapeBox);
+    }
+
+    @SaIgnore
+    @RedisLimit(limitCount = 100, period = 1)
+    @PostMapping("/saveExternalBoxes")
+    @ValidateApi(method = "scene:saveExternalBoxes")
+    public ResultData saveExternalBoxes(@RequestBody @Valid SceneJsonDTO param) {
+        this.checkScene(param.getNum());
+        sceneMarkShapeBoxService.saveExternalBox(param);
+        return ResultData.ok();
+    }
+
+
+    @SaIgnore
+    @GetMapping("/getShapBox")
+    @ValidateApi(method = "scene:getShapBox")
+    public ResultData getShapBox(@RequestParam("num") String num) {
+        this.checkScene(num);
+        return ResultData.ok(sceneMarkShapeBoxService.getShapBox(num));
+    }
+
 }

+ 22 - 1
src/main/java/com/fdkankan/openApi/controller/www/UserController.java

@@ -1,6 +1,16 @@
 package com.fdkankan.openApi.controller.www;
 
 
+import cn.dev33.satoken.annotation.SaIgnore;
+import com.fdkankan.openApi.aop.RedisLimit;
+import com.fdkankan.openApi.aop.ValidateApi;
+import com.fdkankan.openApi.service.www.IUserService;
+import com.fdkankan.openApi.vo.www.FdkkLoginParamVo;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
@@ -14,8 +24,19 @@ import org.springframework.web.bind.annotation.RestController;
  * @since 2023-03-27
  */
 @RestController
-@RequestMapping("/openApi/user")
+@RequestMapping("/user")
 public class UserController {
 
+    @Autowired
+    private IUserService userService;
+
+    @SaIgnore
+    @PostMapping("/v1/login")
+    @ValidateApi
+    @RedisLimit(name = "user/v1/login", limitCount = 1, period = 5)
+    public ResultData login(@RequestBody @Validated FdkkLoginParamVo param){
+        return userService.login(param);
+    }
+
 }
 

+ 11 - 1
src/main/java/com/fdkankan/openApi/controller/www/VirtualSceneController.java

@@ -39,6 +39,16 @@ public class VirtualSceneController {
         return scenePlusService.createVirtualScene(param);
     }
 
-
+    /**
+     * 创建虚拟场景
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @SaIgnore
+    @PostMapping("/v2/createVirtualScene")
+    public ResultData createVirtualSceneV2(@RequestBody @Validated CreateFicTitiousSceneParamVO param) throws Exception {
+        return scenePlusService.createVirtualSceneV2(param);
+    }
 }
 

+ 24 - 0
src/main/java/com/fdkankan/openApi/dto/SceneJsonDTO.java

@@ -0,0 +1,24 @@
+package com.fdkankan.openApi.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.openApi.vo.BaseSceneParamVo;
+import lombok.Data;
+import lombok.NonNull;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class SceneJsonDTO {
+
+    @NotBlank(message = "场景码不能为空")
+    private String num;
+
+    @NotEmpty(message = "数据不能为空")
+    private JSONObject data;
+
+
+
+}

+ 38 - 0
src/main/java/com/fdkankan/openApi/dto/SceneMarkShapeBoxPostDTO.java

@@ -0,0 +1,38 @@
+package com.fdkankan.openApi.dto;
+
+import com.fdkankan.openApi.entity.www.SceneMarkShape;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/1/19
+ **/
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SceneMarkShapeBoxPostDTO {
+
+    /**
+     * 场景码
+     */
+    @NotBlank(message = "场景码不能为空")
+    private String sceneNum;
+
+    /**
+     * 图片名称路径
+     */
+    private List<SceneMarkShape> imgBoxsList;
+
+
+}

+ 48 - 0
src/main/java/com/fdkankan/openApi/dto/SceneMarkShapeDTO.java

@@ -0,0 +1,48 @@
+package com.fdkankan.openApi.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * <p>
+ * 场景标记多边形识别数据
+ * </p>
+ *
+ * @author Xiewj
+ * @date 2023/3/30
+ */
+@Data
+public class SceneMarkShapeDTO {
+
+      /**
+       * 主键
+       */
+      private Long id;
+
+      @NotNull(message = "版本号不能为空")
+      private String version;
+
+      @NotEmpty(message = "标注数据不能为空")
+      private List<JSONObject> shapes;
+
+      @NotBlank(message = "场景路径图片名称不能为空")
+      private String imagePath;
+      @NotNull(message = "图片尺寸不能为空")
+      private Integer imageHeight;
+      @NotNull(message = "图片尺寸不能为空")
+      private Integer imageWidth;
+
+      private String num;
+
+      private Date createTime;
+
+      private Date updateTime;
+
+
+}

+ 29 - 0
src/main/java/com/fdkankan/openApi/dto/SceneMarkShapesDTO.java

@@ -0,0 +1,29 @@
+package com.fdkankan.openApi.dto;
+
+import com.fdkankan.openApi.vo.www.SceneMarkShapeVO;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * <p>
+ * 场景标记多边形识别数据
+ * </p>
+ *
+ * @author Xiewj
+ * @date 2023/3/30
+ */
+@Data
+public class SceneMarkShapesDTO {
+
+
+      @NotNull(message = "场景码不能为空")
+      private String num;
+
+      @NotEmpty(message = "list不能为空")
+      private List<SceneMarkShapeDTO> list;
+
+
+}

+ 15 - 0
src/main/java/com/fdkankan/openApi/entity/laser/SceneEntity.java

@@ -69,4 +69,19 @@ public class SceneEntity extends LaserBaseEntity {
     private Integer offlineStatus;
     private Integer offlineVer;
     private String offlineUrl;
+
+    /*
+        判断是否为slam场景,深光和深时 以前的场景都是4" +
+            "typedef enum SceneLocation {\n" +
+            "    Scene_Location_Slam  = 0, //slam\n" +
+            "    Scene_Location_SFM 1 ,   //sfm\n" +
+            "    Scene_Location_SFMAI  2,     //SFM + AI\n" +
+            "    Scene_Location_MutiFloor 3 ,    //多楼层\n" +
+            "    Scene_Location_PointCloud 4,    //点云\n" +
+            "    Scene_Location_SLAMPoint 5,    //slam实时拍\n" +
+            "    Scene_Location_SLAMPointAndSFMAI  6   //slam实时拍+站点\n" +
+            "} SceneLocation;
+     */
+    private Integer location;
+
 }

+ 37 - 0
src/main/java/com/fdkankan/openApi/entity/system/SceneDataDownloadEntity.java

@@ -0,0 +1,37 @@
+package com.fdkankan.openApi.entity.system;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+
+/**
+ * Created by Xiewj 2022年11月21日11:15:28
+ * 配置表
+ */
+@Data
+@TableName("t_scene_data_download")
+public class SceneDataDownloadEntity extends SystemBaseEntity {
+
+   /** "类别 1,点云和深度图") 2下载文档 */
+    private int type;
+   /** "场景码") */
+    private String sceneCode;
+   /** "文件名") */
+    private String fileName;
+
+   /** "oss路径") */
+    private String ossKey;
+
+   /** "bucket") */
+    private String bucket;
+
+   /** "删除状态 null未删除") */
+    private Date ossDelete;
+
+    private Long userId;
+
+    /** 场景版本号 */
+    private int sceneVer;
+}

+ 66 - 0
src/main/java/com/fdkankan/openApi/entity/www/SceneDynamicPanel.java

@@ -0,0 +1,66 @@
+package com.fdkankan.openApi.entity.www;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 场景动态面板
+ * </p>
+ *
+ * @author
+ * @since 2024-05-21
+ */
+@Getter
+@Setter
+@TableName("t_scene_dynamic_panel")
+public class SceneDynamicPanel implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * sid
+     */
+    @TableField("sid")
+    private String sid;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 删除状态(A-可用,I删除)
+     */
+    @TableField("rec_status")
+    @TableLogic(value = "A", delval = "I")
+    private String recStatus;
+
+
+}

+ 57 - 0
src/main/java/com/fdkankan/openApi/entity/www/SceneMarkShapeBox.java

@@ -0,0 +1,57 @@
+package com.fdkankan.openApi.entity.www;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * <p>
+ * 场景标记多边形识别数据
+ * </p>
+ *
+ * @author Xiewj
+ * @date 2023/3/30
+ */
+@Data
+@TableName(value = "t_scene_mark_shape_box",autoResultMap = true)
+@Accessors(chain = true)
+public class SceneMarkShapeBox implements Serializable {
+
+      /**
+       * 主键
+       */
+      @TableId(value = "id", type = IdType.AUTO)
+      private Long id;
+
+      @TableField(typeHandler = FastjsonTypeHandler.class, value = "boxes")
+      private List<JSONObject> boxes;
+
+      @TableField(typeHandler = FastjsonTypeHandler.class, value = "bounding_box")
+      private JSONObject boundingBox;
+
+      @TableField("scene_num")
+      private String sceneNum;
+
+      @TableField("create_time")
+      private Date createTime;
+
+      @TableField("update_time")
+      private Date updateTime;
+
+      /**
+       * 记录的状态,A: 生效,I: 禁用
+       */
+      @TableField("rec_status")
+      @TableLogic(value = "A", delval = "I")
+      private String recStatus;
+
+      //第三方
+      @TableField(typeHandler = FastjsonTypeHandler.class, value = "external_boxes")
+      private JSONObject externalBoxes;
+}

+ 2 - 1
src/main/java/com/fdkankan/openApi/exception/OpenApiGlobalExceptionHandler.java

@@ -43,7 +43,8 @@ public class OpenApiGlobalExceptionHandler extends GlobalExceptionHandler {
     @ResponseStatus(HttpStatus.BAD_REQUEST) // 这里非常关键,这是修改的状态吗
     public ResultData ApiBusinessExceptionHandler(ApiBusinessException e) {
         log.error("业务异常code:{},message:{}", e.getCode(), e.getMessage());
-        return ResultData.error(e.getCode(), e.getMessage());
+        ResultData error = ResultData.error(e.getCode(), e.getMessage());
+        return error;
     }
 
     @ResponseBody

+ 21 - 0
src/main/java/com/fdkankan/openApi/httpclient/client/ShapesBoxClient.java

@@ -0,0 +1,21 @@
+package com.fdkankan.openApi.httpclient.client;
+
+
+import com.dtflys.forest.annotation.JSONBody;
+import com.dtflys.forest.annotation.Post;
+import com.dtflys.forest.annotation.Var;
+import com.fdkankan.web.response.ResultData;
+
+public interface ShapesBoxClient {
+
+
+    /**
+     * 在方法上加上@DownloadFile注解
+     * dir属性表示文件下载到哪个目录
+     * filename属性表示文件下载成功后以什么名字保存,如果不填,这默认从URL中取得文件名
+     * OnProgress参数为监听上传进度的回调函数
+     */
+
+    @Post("${url}")
+    ResultData post(@Var("url") String url,@JSONBody String body);
+}

+ 16 - 0
src/main/java/com/fdkankan/openApi/mapper/system/SceneDataDownloadMapper.java

@@ -0,0 +1,16 @@
+package com.fdkankan.openApi.mapper.system;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.openApi.entity.system.SceneDataDownloadEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Xiewj
+ * @date 2021/11/22
+ */
+@Mapper
+@Component("SceneDataDownloadMapper")
+public interface SceneDataDownloadMapper extends BaseMapper<SceneDataDownloadEntity> {
+}
+

+ 7 - 0
src/main/java/com/fdkankan/openApi/mapper/www/IMarkShapeMapper.java

@@ -3,8 +3,12 @@ package com.fdkankan.openApi.mapper.www;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fdkankan.openApi.entity.www.SceneMarkShape;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
+import java.util.Set;
+
 /**
  * @author Xiewj
  * @date 2021/11/22
@@ -12,5 +16,8 @@ import org.springframework.stereotype.Component;
 @Mapper
 @Component("MarkShapeMapper")
 public interface IMarkShapeMapper extends BaseMapper<SceneMarkShape> {
+
+    List<SceneMarkShape> selectByNumAndImagePaths(@Param("num")String num, @Param("imagePaths") Set<String> imagePaths);
+
 }
 

+ 18 - 0
src/main/java/com/fdkankan/openApi/mapper/www/ISceneDynamicPanelMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.openApi.mapper.www;
+
+import com.fdkankan.openApi.entity.www.SceneDynamicPanel;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景动态面板 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2024-05-21
+ */
+@Mapper
+public interface ISceneDynamicPanelMapper extends BaseMapper<SceneDynamicPanel> {
+
+}

+ 16 - 0
src/main/java/com/fdkankan/openApi/mapper/www/MarkShapeBoxMapper.java

@@ -0,0 +1,16 @@
+package com.fdkankan.openApi.mapper.www;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.openApi.entity.www.SceneMarkShapeBox;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Xiewj
+ * @date 2023-8-31 10:43:49
+ */
+@Mapper
+@Component("MarkShapeBoxMapper")
+public interface MarkShapeBoxMapper extends BaseMapper<SceneMarkShapeBox> {
+}
+

+ 1 - 1
src/main/java/com/fdkankan/openApi/service/laser/impl/SceneServiceImpl.java

@@ -33,8 +33,8 @@ import java.util.stream.Collectors;
  * Created by Xiewj on 2021/7/28 0028 9:10
  */
 @Slf4j
-@DS("laser")
 @Service
+@DS("laser")
 public class SceneServiceImpl extends ServiceImpl<SceneMapper, SceneEntity> implements SceneService {
 
     @Autowired

+ 2 - 1
src/main/java/com/fdkankan/openApi/service/system/IAccountService.java

@@ -11,7 +11,7 @@ import com.fdkankan.web.response.ResultData;
  * 账号表 服务类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-05-18
  */
 public interface IAccountService extends IService<Account> {
@@ -32,4 +32,5 @@ public interface IAccountService extends IService<Account> {
 
     ResultData createApp4Jmga(CreateAppUser4JmgaParamVo param);
 
+    void deleteApp(UpdateAppUserParamVo param);
 }

+ 22 - 0
src/main/java/com/fdkankan/openApi/service/system/SceneDataDownloadService.java

@@ -0,0 +1,22 @@
+package com.fdkankan.openApi.service.system;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.openApi.entity.laser.SceneEntity;
+import com.fdkankan.openApi.entity.system.SceneDataDownloadEntity;
+import com.fdkankan.web.response.ResultData;
+
+import java.util.List;
+
+/**
+ * Created by Xiewj on 2022年11月21日11:22:02
+ */
+public interface SceneDataDownloadService extends IService<SceneDataDownloadEntity> {
+    ResultData sceneDownloadDepthMapAndPly(String sceneCode, Long userId, SceneEntity sceneEntity);
+    List<SceneDataDownloadEntity> findByOssDeleteIsNull();
+    void removeBySceneCode(String sceneCode);
+
+    List<SceneDataDownloadEntity>  findByOssDeleteIsNullBySceneCode(String sceneCode);
+    SceneDataDownloadEntity  findBySceneCodeAndFileNameAndOssDeleteIsNull(String sceneCode,String fileName);
+
+}

+ 11 - 1
src/main/java/com/fdkankan/openApi/service/system/impl/AccountServiceImpl.java

@@ -41,7 +41,7 @@ import java.util.Objects;
  * 账号表 服务实现类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-05-18
  */
 @Service
@@ -269,4 +269,14 @@ public class AccountServiceImpl extends ServiceImpl<IAccountMapper, Account> imp
 
         return ResultData.ok(userAuthInfo.getAppKey());
     }
+
+    @Override
+    public void deleteApp(UpdateAppUserParamVo param) {
+        Account account = new Account();
+        account.setId(param.getId());
+        account.setUpdaterId(param.getUpdaterId());
+        this.updateById(account);
+
+        this.removeById(account.getId());
+    }
 }

+ 187 - 0
src/main/java/com/fdkankan/openApi/service/system/impl/SceneDataDownloadServiceImpl.java

@@ -0,0 +1,187 @@
+package com.fdkankan.openApi.service.system.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.openApi.bean.vo.SceneDataDownloadVO;
+import com.fdkankan.openApi.entity.laser.SceneEntity;
+import com.fdkankan.openApi.entity.system.SceneDataDownloadEntity;
+import com.fdkankan.openApi.mapper.system.SceneDataDownloadMapper;
+import com.fdkankan.openApi.service.laser.SceneService;
+import com.fdkankan.openApi.service.system.SceneDataDownloadService;
+import com.fdkankan.web.response.ResultData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+/**
+ * Created by Xiewj on 2022年11月21日11:22:02
+ */
+@Slf4j
+@Service
+@DS("system")
+public class SceneDataDownloadServiceImpl extends ServiceImpl<SceneDataDownloadMapper, SceneDataDownloadEntity> implements SceneDataDownloadService {
+    @Value("${laserConfig.defaultFolder}")
+    private String laserDefaultFolder;
+    @Value("${laserConfig.ossUrl}")
+    private String laserOSSUrl;
+
+
+    @Value("${laserConfig.bucket}")
+    private String laserBucket;
+
+    @Autowired
+    private SceneService sceneService;
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public ResultData sceneDownloadDepthMapAndPly(String sceneCode, Long userId,SceneEntity sceneEntity) {
+        List<SceneDataDownloadEntity> sceneDataDownloadEntityList = findByOssDeleteIsNullBySceneCode(sceneCode);
+        if (ObjectUtil.isNotNull(sceneEntity)&&sceneEntity.getLocation()==6){
+            throw new BusinessException(-1,"不支持slam场景原始数据下载");
+        }
+        String e57Url=laserDefaultFolder + "/" + sceneCode + "/data/"+sceneCode+"_e57.zip";
+        boolean e57Flag=false;
+        if(fYunFileService.fileExist(laserBucket,e57Url)){
+            e57Flag=true;
+        }
+        boolean e57DBFlag=false;
+        boolean recountFlag=false;
+        for (SceneDataDownloadEntity sceneDataDownloadEntity : sceneDataDownloadEntityList) {
+            if (sceneDataDownloadEntity.getFileName().toLowerCase(Locale.ROOT).contains("e57")  && !e57DBFlag){
+                e57DBFlag=true;
+            }
+            if (sceneDataDownloadEntity.getSceneVer()<sceneEntity.getRecount() && !recountFlag){
+                recountFlag=true;
+            }
+            if (e57DBFlag&&recountFlag){
+                break; // 终止整个循环
+            }
+        }
+
+        if (CollectionUtil.isNotEmpty(sceneDataDownloadEntityList)&& e57Flag && e57DBFlag && !recountFlag ){
+            log.info("场景存在库");
+            List<SceneDataDownloadVO> sceneDataDownloadVOS = sceneDataDownloadEntityList.stream()
+                    .map(sceneData -> new SceneDataDownloadVO(sceneData.getFileName(),laserOSSUrl+sceneData.getOssKey()+"?t="+System.currentTimeMillis()))
+                    .collect(Collectors.toList());
+            return ResultData.ok(sceneDataDownloadVOS);
+        }else {
+            List<String> copyFiles=new ArrayList<>();
+            //先检查e57
+            if(e57Flag){
+                String e57CopyUrl="sceneRawData/"+sceneCode+"/"+ FileUtil.getName(e57Url);
+                fYunFileService.copyFileInBucket(laserBucket,e57Url,e57CopyUrl);
+                copyFiles.add(e57CopyUrl);
+                e57Flag=true;
+            }
+            List<String> strings = fYunFileService.listRemoteFiles(laserBucket, laserDefaultFolder + "/" + sceneCode + "/data/" + sceneCode + "/depthmap/");
+            boolean has_cloud=false;
+            boolean has_png=false;
+            ArrayList<Map<String, Object>> rows =new ArrayList<>();
+            for (String file : strings) {
+                String name = FileUtil.getName(file);
+                if (name.contains("ply")&&e57Flag){
+                    continue;
+                }
+                if (FileUtil.extName(file).equalsIgnoreCase("png")&& !has_png){
+                    has_png=true;
+                }
+                if (FileUtil.extName(file).equalsIgnoreCase("ply")&& !has_cloud){
+                    has_cloud=true;
+                }
+                String copyUrl="sceneRawData/"+sceneCode+"/"+ FileUtil.getName(file);
+                fYunFileService.copyFileInBucket(laserBucket,file,copyUrl);
+                copyFiles.add(copyUrl);
+            }
+            if ((has_png && has_cloud )|| (has_png && e57Flag)){
+                removeBySceneCode(sceneCode);
+                return  saveAndDownLoad(sceneCode, copyFiles,userId,sceneEntity.getRecount());
+            }else if (!has_png  && !has_cloud ){
+                throw new BusinessException(-1,"数据不全,请重算后再尝试下载");
+            }else if (has_png && (!has_cloud||!e57Flag  )){
+                throw new BusinessException(-1,"点云数据不全,请重算后再尝试下载");
+            }else if (!has_png  && has_cloud){
+                throw new BusinessException(-1,"深度图数据不全,请重算后再尝试下载");
+            }
+        }
+        return ResultData.ok();
+    }
+    private ResultData saveAndDownLoad(String sceneCode,   List<String> data,Long userId,int ver) {
+        List<SceneDataDownloadEntity> dataDownloadEntities=new ArrayList<>();
+        for (String file : data) {
+             String name = FileUtil.getName(file);
+             //上传OSS并且入库
+            dataDownloadEntities.add(findAndSave(sceneCode, userId, file, name, 1,ver));
+        }
+        List<SceneDataDownloadVO> sceneDataDownloadVOS = dataDownloadEntities.stream()
+                .map(sceneData -> new SceneDataDownloadVO(sceneData.getFileName(),laserOSSUrl+sceneData.getOssKey()+"?t="+System.currentTimeMillis()))
+                .collect(Collectors.toList());
+        return ResultData.ok(sceneDataDownloadVOS);
+    }
+
+    private SceneDataDownloadEntity findAndSave(String sceneCode, Long userId, String xlsxUrl,String fileName,int type,int ver) {
+        SceneDataDownloadEntity sceneDataDownload = findBySceneCodeAndFileNameAndOssDeleteIsNull( sceneCode,fileName);
+        if (ObjectUtil.isNull(sceneDataDownload)){
+            sceneDataDownload=new SceneDataDownloadEntity();
+            sceneDataDownload.setOssKey(xlsxUrl);
+            sceneDataDownload.setFileName(fileName);
+            sceneDataDownload.setType(type);
+            sceneDataDownload.setSceneCode(sceneCode);
+            sceneDataDownload.setBucket(laserBucket);
+            sceneDataDownload.setSceneVer(ver);
+            sceneDataDownload.setUserId(userId);
+            save(sceneDataDownload);
+            return sceneDataDownload;
+        }
+        return sceneDataDownload;
+    }
+
+
+//
+
+    @Override
+    public List<SceneDataDownloadEntity> findByOssDeleteIsNull() {
+        return list(Wrappers.<SceneDataDownloadEntity>lambdaQuery().isNull(SceneDataDownloadEntity::getOssDelete));
+    }
+
+    @Override
+    public List<SceneDataDownloadEntity> findByOssDeleteIsNullBySceneCode(String sceneCode) {
+        LambdaQueryWrapper<SceneDataDownloadEntity> wrapper = Wrappers.lambdaQuery();
+        wrapper.isNull(SceneDataDownloadEntity::getOssDelete);
+        wrapper.eq(SceneDataDownloadEntity::getSceneCode,sceneCode);
+        return list(wrapper);
+    }
+
+    @Override
+    public SceneDataDownloadEntity findBySceneCodeAndFileNameAndOssDeleteIsNull(String sceneCode, String fileName) {
+        LambdaQueryWrapper<SceneDataDownloadEntity> wrapper = Wrappers.lambdaQuery();
+        wrapper.isNull(SceneDataDownloadEntity::getOssDelete);
+        wrapper.eq(SceneDataDownloadEntity::getSceneCode,sceneCode);
+        wrapper.eq(SceneDataDownloadEntity::getFileName,fileName);
+        return getOne(wrapper);
+    }
+
+    @Override
+    public void removeBySceneCode(String sceneCode) {
+        LambdaQueryWrapper<SceneDataDownloadEntity> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(SceneDataDownloadEntity::getSceneCode,sceneCode);
+        remove(wrapper);
+    }
+}

+ 21 - 0
src/main/java/com/fdkankan/openApi/service/www/ISceneDynamicPanelService.java

@@ -0,0 +1,21 @@
+package com.fdkankan.openApi.service.www;
+
+import com.fdkankan.openApi.entity.www.SceneDynamicPanel;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.openApi.vo.www.SceneDynamicPanelParamVO;
+
+import java.io.IOException;
+
+/**
+ * <p>
+ * 场景动态面板 服务类
+ * </p>
+ *
+ * @author
+ * @since 2024-05-21
+ */
+public interface ISceneDynamicPanelService extends IService<SceneDynamicPanel> {
+
+    void save(Long userId, SceneDynamicPanelParamVO param) throws IOException;
+
+}

+ 3 - 1
src/main/java/com/fdkankan/openApi/service/www/ISceneEditInfoService.java

@@ -8,11 +8,13 @@ import com.baomidou.mybatisplus.extension.service.IService;
  *  服务类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-02-15
  */
 public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     SceneEditInfo getByScenePlusId(long scenePlusId);
 
+    void upSceneVersion(long scenePlusId);
+
 }

+ 29 - 0
src/main/java/com/fdkankan/openApi/service/www/ISceneMarkShapeBoxService.java

@@ -0,0 +1,29 @@
+package com.fdkankan.openApi.service.www;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.openApi.dto.SceneJsonDTO;
+import com.fdkankan.openApi.entity.www.SceneMarkShapeBox;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Xiewj on 2023年8月31日10:42:44
+ */
+public interface ISceneMarkShapeBoxService extends IService<SceneMarkShapeBox> {
+
+    SceneMarkShapeBox findBySceneNum(String sceneNum);
+
+    SceneMarkShapeBox planeCovert(String sceneNum);
+
+    void saveExternalBox(SceneJsonDTO param);
+
+    Map<String, Object> getShapBox(String num);
+
+//    String covertToShapeBox(String sceneNum);
+}

+ 7 - 0
src/main/java/com/fdkankan/openApi/service/www/ISceneMarkShapeService.java

@@ -2,6 +2,8 @@ package com.fdkankan.openApi.service.www;
 
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.openApi.dto.SceneJsonDTO;
+import com.fdkankan.openApi.dto.SceneMarkShapesDTO;
 import com.fdkankan.openApi.entity.www.SceneMarkShape;
 import com.fdkankan.openApi.vo.www.SceneMarkShapeParamVO;
 import com.fdkankan.openApi.vo.www.SceneMarkShapeReDetectParamVO;
@@ -31,5 +33,10 @@ public interface ISceneMarkShapeService extends IService<SceneMarkShape> {
 
     ResultData saveOrEdit(SceneMarkShapeVO param);
 
+    ResultData saveOrEditBatch(SceneMarkShapesDTO param);
+
     ResultData getShapesInfo(SceneMarkShapeParamVO param);
+
+    List<SceneMarkShape> findByNum(String num);
+
 }

+ 2 - 0
src/main/java/com/fdkankan/openApi/service/www/IScenePlusService.java

@@ -29,6 +29,8 @@ public interface IScenePlusService extends IService<ScenePlus> {
 
     ResultData createVirtualScene(CreateFicTitiousSceneParamVO param) throws Exception;
 
+    ResultData createVirtualSceneV2(CreateFicTitiousSceneParamVO param) throws Exception;
+
     PageInfo<SceneVO> getScenesByUserId(Long userName, PageScenesParamVo param);
 
     Object getPointInfo(String sceneCode);

+ 6 - 0
src/main/java/com/fdkankan/openApi/service/www/IUserService.java

@@ -2,6 +2,10 @@ package com.fdkankan.openApi.service.www;
 
 import com.fdkankan.openApi.entity.www.User;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.openApi.vo.www.FdkkLoginParamVo;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * <p>
@@ -15,4 +19,6 @@ public interface IUserService extends IService<User> {
 
     User getByUserName(String userName);
 
+    ResultData login(FdkkLoginParamVo param);
+
 }

+ 128 - 0
src/main/java/com/fdkankan/openApi/service/www/impl/SceneDynamicPanelServiceImpl.java

@@ -0,0 +1,128 @@
+package com.fdkankan.openApi.service.www.impl;
+
+import cn.hutool.core.lang.UUID;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.model.constants.UploadFilePath;
+import com.fdkankan.openApi.entity.www.SceneDynamicPanel;
+import com.fdkankan.openApi.entity.www.ScenePlus;
+import com.fdkankan.openApi.mapper.www.ISceneDynamicPanelMapper;
+import com.fdkankan.openApi.service.www.ISceneDynamicPanelService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.openApi.service.www.ISceneEditInfoService;
+import com.fdkankan.openApi.service.www.IScenePlusService;
+import com.fdkankan.openApi.vo.www.SceneDynamicPanelParamVO;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.util.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * <p>
+ * 场景动态面板 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2024-05-21
+ */
+@DS("www")
+@Service
+public class SceneDynamicPanelServiceImpl extends ServiceImpl<ISceneDynamicPanelMapper, SceneDynamicPanel> implements ISceneDynamicPanelService {
+
+    @Autowired
+    private IScenePlusService scenePlusService;
+    @Resource
+    private FYunFileServiceInterface fileServiceInterface;
+    @Autowired
+    private ISceneEditInfoService sceneEditInfoService;
+    @Autowired
+    private RedisUtil redisUtil;
+
+
+    @Override
+    public void save(Long userId, SceneDynamicPanelParamVO param) throws IOException {
+
+        ScenePlus scenePlus = scenePlusService.getByNumAndUserId(userId, param.getNum());
+        if(Objects.isNull(scenePlus)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+        }
+
+        //上传文件
+        String editPath = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + "dynamicPanel.json";
+        String viewPath = String.format(UploadFilePath.USER_VIEW_PATH, param.getNum()) + "dynamicPanel.json";
+
+        SceneDynamicPanel one = this.getOne(new LambdaQueryWrapper<SceneDynamicPanel>().eq(SceneDynamicPanel::getNum, param.getNum()));
+        String sid = null;
+        if(Objects.isNull(one)){
+            sid = UUID.fastUUID().toString();
+            one = new SceneDynamicPanel();
+            one.setSid(sid);
+            one.setNum(param.getNum());
+
+            if(fileServiceInterface.fileExist(editPath)){
+                fileServiceInterface.deleteFile(editPath);
+            }
+            if(fileServiceInterface.fileExist(viewPath)){
+                fileServiceInterface.deleteFile(viewPath);
+            }
+
+        }else{
+            sid = one.getSid();
+        }
+        this.saveOrUpdate(one);
+
+        Map<String, JSONObject> map = new HashMap<>();
+        if(fileServiceInterface.fileExist(editPath)){
+            String fileContent = fileServiceInterface.getFileContent(editPath);
+            JSONArray jsonArray = JSON.parseArray(fileContent);
+            jsonArray.stream().forEach(v->{
+                JSONObject obj = (JSONObject) v;
+                map.put(obj.getString("sid"), obj);
+            });
+        }
+        JSONObject jsonObject = map.get(sid);
+        if(Objects.isNull(jsonObject)){
+            jsonObject = new JSONObject();
+            jsonObject.put("sid", sid);
+            map.put(sid, jsonObject);
+        }
+        jsonObject.put("text", param.getContent());
+
+        Collection<JSONObject> values = map.values();
+        fileServiceInterface.uploadFile(JSON.toJSONString(values).getBytes(StandardCharsets.UTF_8), editPath);
+        fileServiceInterface.uploadFile(JSON.toJSONString(values).getBytes(StandardCharsets.UTF_8), viewPath);
+
+        //更新数据库版本号
+        sceneEditInfoService.upSceneVersion(scenePlus.getId());
+
+        //更新缓存版本号
+        String key = String.format(RedisKey.SCENE_JSON, param.getNum());
+        String sceneJsonStr = redisUtil.get(key);
+        JSONObject scenejsonObj = JSON.parseObject(sceneJsonStr);
+        scenejsonObj.replace("version", scenejsonObj.getIntValue("version") + 1);
+        redisUtil.set(key, JSON.toJSONString(scenejsonObj));
+
+        //更新scene.json版本号
+        String sceneJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH, param.getNum()) + "scene.json";
+        sceneJsonStr = fileServiceInterface.getFileContent(sceneJsonPath);
+        scenejsonObj = JSON.parseObject(sceneJsonStr);
+        scenejsonObj.replace("version", scenejsonObj.getIntValue("version") + 1);
+        fileServiceInterface.uploadFile(JSON.toJSONBytes(scenejsonObj), sceneJsonPath);
+
+
+    }
+}

+ 11 - 1
src/main/java/com/fdkankan/openApi/service/www/impl/SceneEditInfoServiceImpl.java

@@ -2,6 +2,7 @@ package com.fdkankan.openApi.service.www.impl;
 
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.fdkankan.openApi.entity.www.SceneEditInfo;
 import com.fdkankan.openApi.mapper.www.ISceneEditInfoMapper;
 import com.fdkankan.openApi.service.www.ISceneEditInfoService;
@@ -13,7 +14,7 @@ import org.springframework.stereotype.Service;
  *  服务实现类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-02-15
  */
 @DS("www")
@@ -24,4 +25,13 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     public SceneEditInfo getByScenePlusId(long scenePlusId) {
         return this.getOne(new LambdaQueryWrapper<SceneEditInfo>().eq(SceneEditInfo::getScenePlusId, scenePlusId));
     }
+
+    @Override
+    public void upSceneVersion(long scenePlusId) {
+        SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlusId);
+        this.update(
+                new LambdaUpdateWrapper<SceneEditInfo>()
+                        .setSql("version = version + 1")
+                        .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
+    }
 }

+ 151 - 0
src/main/java/com/fdkankan/openApi/service/www/impl/SceneMarkShapeBoxServiceImpl.java

@@ -0,0 +1,151 @@
+package com.fdkankan.openApi.service.www.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.openApi.dto.SceneJsonDTO;
+import com.fdkankan.openApi.dto.SceneMarkShapeBoxPostDTO;
+import com.fdkankan.openApi.entity.www.SceneMarkShape;
+import com.fdkankan.openApi.entity.www.SceneMarkShapeBox;
+import com.fdkankan.openApi.httpclient.client.ShapesBoxClient;
+import com.fdkankan.openApi.mapper.www.MarkShapeBoxMapper;
+import com.fdkankan.openApi.service.www.ISceneMarkShapeBoxService;
+import com.fdkankan.openApi.service.www.ISceneMarkShapeService;
+import com.fdkankan.web.response.ResultData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+/**
+ * Created by Xiewj on 2023-8-31 10:44:46
+ */
+@Slf4j
+@Service
+@DS("www")
+public class SceneMarkShapeBoxServiceImpl extends ServiceImpl<MarkShapeBoxMapper, SceneMarkShapeBox> implements ISceneMarkShapeBoxService {
+
+    @Autowired
+    ISceneMarkShapeService sceneMarkShapeService;
+    @Resource
+    ShapesBoxClient shapesBoxClient;
+
+    @Value("${4dkk.nodeService.basePath}")
+    private String planeCovertBasePathUrl;
+    @Value("${4dkk.nodeService.api.planeCovert}")
+    private String planeCovert;
+
+
+//    @Autowired
+//    SceneShapeEnumService sceneShapeEnumService;
+
+    @Override
+    public SceneMarkShapeBox findBySceneNum(String sceneNum) {
+        LambdaQueryWrapper<SceneMarkShapeBox> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(SceneMarkShapeBox::getSceneNum,sceneNum);
+        return getOne(wrapper);
+    }
+
+    @Override
+    public SceneMarkShapeBox planeCovert(String sceneNum) {
+        List<SceneMarkShape> sceneMarkShapes =  sceneMarkShapeService.findByNum(sceneNum);
+        SceneMarkShapeBoxPostDTO sceneMarkShapeBoxPostVO =new SceneMarkShapeBoxPostDTO(sceneNum,sceneMarkShapes);
+        ResultData res = shapesBoxClient.post(planeCovertBasePathUrl + planeCovert, JSONObject.toJSONString(sceneMarkShapeBoxPostVO));
+        log.info("请求node转换服务-{}",res);
+        SceneMarkShapeBox data = null;
+        if (res.getCode()==200){
+            JSONObject resData = (JSONObject)res.getData();
+            data = JSONObject.parseObject(resData.toJSONString(),SceneMarkShapeBox.class);
+            SceneMarkShapeBox sceneMarkShapeBox = findBySceneNum(sceneNum);
+            if (ObjectUtil.isNotNull(sceneMarkShapeBox)){
+                log.info("存在shapesBox数据进行替换");
+                sceneMarkShapeBox.setBoxes(data.getBoxes());
+                sceneMarkShapeBox.setBoundingBox(data.getBoundingBox());
+                updateById(sceneMarkShapeBox);
+                return sceneMarkShapeBox;
+            }else {
+                log.info("不存在shapesBox数据进行保存");
+                save(data);
+                return data;
+            }
+        }
+        return data;
+    }
+
+    @Override
+    public void saveExternalBox(SceneJsonDTO param) {
+        SceneMarkShapeBox sceneMarkShapeBox = this.findBySceneNum(param.getNum());
+        sceneMarkShapeBox.setExternalBoxes(param.getData());
+        this.saveOrUpdate(sceneMarkShapeBox);
+    }
+
+    @Override
+    public Map<String, Object> getShapBox(String num) {
+        SceneMarkShapeBox sceneMarkShapeBox = this.findBySceneNum(num);
+        if(Objects.isNull(sceneMarkShapeBox)){
+            return null;
+        }
+        Map<String, Object> result = new HashMap<>();
+        result.put("boundingBox", sceneMarkShapeBox.getBoundingBox());
+        if(Objects.nonNull(sceneMarkShapeBox.getExternalBoxes())){
+            result.put("result", sceneMarkShapeBox.getExternalBoxes());
+        }else {
+            result.put("result", sceneMarkShapeBox.getBoxes());
+        }
+        return result;
+    }
+
+    //    @Override
+//    public String covertToShapeBox(String sceneNum) {
+//        SceneMarkShapeBox sceneMarkShapeBox = planeCovert(sceneNum);
+//        if (ObjectUtil.isNotNull(sceneMarkShapeBox)){
+//            JSONObject shapeBox=new JSONObject();
+//            JSONArray decoration=new JSONArray();
+//            List<JSONObject> boxes = sceneMarkShapeBox.getBoxes();
+//            JSONObject boundingBox = sceneMarkShapeBox.getBoundingBox();
+//            JSONArray max = boundingBox.getJSONArray("max");
+//            JSONArray min = boundingBox.getJSONArray("min");
+//            ShapeBoxVO shapeBoxVO=new ShapeBoxVO();
+//            Point3D maxp=new Point3D(max.getDouble(0),max.getDouble(1),max.getDouble(2));
+//            Point3D minp=new Point3D(min.getDouble(0),min.getDouble(1),min.getDouble(2));
+//            shapeBoxVO.setBoundingBox( new ShapeBoxVO.BoundingBox(maxp,minp));
+//            for (JSONObject box : boxes) {
+//                List<CubeUtil.Point> points=new ArrayList<>();
+//                JSONArray pointsJson = box.getJSONArray("points");
+//                for (Object o : pointsJson) {
+//                    JSONArray point = JSONArray.parseArray(JSONObject.toJSON(o).toString());
+//                    points.add(new CubeUtil.Point(point.getDouble(0), point.getDouble(1), point.getDouble(2)));
+//                }
+//                CubeUtil cubeUtil = new CubeUtil(points);
+//                String category=box.getString("category");
+//                JSONArray quaternion=box.getJSONArray("quaternion");
+//                SceneShapeEnum sceneShapeEnum = sceneShapeEnumService.findByClassName(category);
+//                if (ObjectUtil.isNotNull(sceneShapeEnum)){
+//                    cubeUtil.setResource_id(sceneShapeEnum.getResourceId());
+//                    cubeUtil.setType_id(sceneShapeEnum.getTypeId());
+//                }
+//                if (CollectionUtil.isNotEmpty(quaternion)){
+//                    cubeUtil.setQuaternion(quaternion);
+//                }
+//                decoration.add(cubeUtil);
+//            }
+//            if (decoration.size() >0){
+//                shapeBoxVO.setDecoration(decoration);
+//            }
+//            String srcPath = String.format(ConstantFilePath.SCENE_VIEW_DATA_USER,sceneNum) + "shapeBox.json" ;
+//            return fileStorageTemplate.uploadFileBytes(srcPath, JSONObject.toJSONString(shapeBoxVO).getBytes());
+//        }
+//        return "";
+//    }
+}

+ 31 - 4
src/main/java/com/fdkankan/openApi/service/www/impl/SceneMarkShapeServiceImpl.java

@@ -1,6 +1,7 @@
 package com.fdkankan.openApi.service.www.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.lang.UUID;
 import cn.hutool.core.util.ObjectUtil;
@@ -15,6 +16,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.openApi.dto.SceneJsonDTO;
+import com.fdkankan.openApi.dto.SceneMarkShapesDTO;
 import com.fdkankan.openApi.entity.www.SceneMarkShape;
 import com.fdkankan.openApi.mapper.www.IMarkShapeMapper;
 import com.fdkankan.openApi.service.www.ISceneMarkShapeService;
@@ -32,10 +35,8 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
 
 
 /**
@@ -76,6 +77,24 @@ public class SceneMarkShapeServiceImpl extends ServiceImpl<IMarkShapeMapper, Sce
     }
 
     @Override
+    public ResultData saveOrEditBatch(SceneMarkShapesDTO param) {
+
+        Set<String> imagePaths = param.getList().stream().map(v -> v.getImagePath()).collect(Collectors.toSet());
+        List<SceneMarkShape> sceneMarkShapes = this.baseMapper.selectByNumAndImagePaths(param.getNum(), imagePaths);
+        Map<String, Long> imagePathIdMap = sceneMarkShapes.stream().collect(Collectors.toMap(SceneMarkShape::getImagePath, SceneMarkShape::getId));
+
+        List<SceneMarkShape> sceneMarkShapeList = BeanUtil.copyToList(param.getList(), SceneMarkShape.class);
+        sceneMarkShapeList.stream().forEach(v -> v.setNum(param.getNum()));
+        if(CollUtil.isNotEmpty(imagePathIdMap)){
+            sceneMarkShapeList.stream().forEach(v->{
+                v.setId(imagePathIdMap.get(v.getImagePath()));
+            });
+        }
+        return ResultData.ok(this.saveOrUpdateBatch(sceneMarkShapeList));
+    }
+
+
+    @Override
     public ResultData getShapesInfo(SceneMarkShapeParamVO param) {
         SceneMarkShape res=  findByNumAndImagePath(param.getNum(),param.getImagePath());
         SceneMarkShapeVO vo=new SceneMarkShapeVO();
@@ -215,4 +234,12 @@ public class SceneMarkShapeServiceImpl extends ServiceImpl<IMarkShapeMapper, Sce
             save(sceneMarkShape);
         }
     }
+
+    @Override
+    public List<SceneMarkShape> findByNum(String num) {
+        LambdaQueryWrapper<SceneMarkShape> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(SceneMarkShape::getNum,num);
+        return list(wrapper);
+    }
+
 }

+ 141 - 6
src/main/java/com/fdkankan/openApi/service/www/impl/ScenePlusServiceImpl.java

@@ -40,6 +40,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
 
+import java.io.File;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -48,7 +49,7 @@ import java.util.stream.Collectors;
  * 场景主表 服务实现类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-02-15
  */
 @DS("www")
@@ -107,6 +108,131 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
         return ResultData.ok(website);
     }
 
+    @Override
+    public ResultData createVirtualSceneV2(CreateFicTitiousSceneParamVO param) throws Exception {
+
+        this.checkParams4createVirtualScene(param);
+
+        this.buildScene4CreateVirtualScene(param);
+
+        this.cutPanorama4CreateVirtualScene(param);
+
+        String website = this.updateScene4CreateVirtualScene(param);
+
+        return ResultData.ok(website);
+    }
+
+    private void cutPanorama4CreateVirtualScene(CreateFicTitiousSceneParamVO param) throws Exception {
+        if(!param.getSceneKind().equals(SceneKind.TILES.code())){
+            return;
+        }
+
+        String num = param.getNum();
+
+        //检测原始图片是否存在
+        String ossImagePath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
+        String ossCaptruePath = ossImagePath.concat("capture/");
+        List<String> captrueList = fYunFileService.listRemoteFiles(ossCaptruePath);
+        if(CollUtil.isEmpty(captrueList)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_3018.code(), "全景图不能为空");
+        }
+
+        String target = String.format(ConstantFilePath.SCENE_IMAGES_PATH_V4, num);
+        String targetImagesPath = target + "extras/images/";
+        FileUtil.del(targetImagesPath);
+        String ossVisionTxtPath = ossImagePath + "vision.txt";
+        fYunFileService.downloadFile(ossVisionTxtPath, target + "extras" + File.separator + "vision.txt");
+
+        //下载全景图
+        fYunFileService.downloadFileByCommand(targetImagesPath, ossCaptruePath);
+
+        JSONObject dataJson = new JSONObject();
+        dataJson.put("split_type", "SPLIT_V8");
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("has_vision_txt",true);
+        jsonObject.put("has_source_images",true);
+        dataJson.put("extras", jsonObject);
+        //V5表示不需要生成high,low文件
+        String skyboxType = "SKYBOX_V6";
+        SceneResolution sceneResolution = SceneResolution.get(param.getSceneResolution());
+        switch (sceneResolution){
+            case one_k:
+                skyboxType = "SKYBOX_V9";
+                break;
+            case two_K:
+                skyboxType = "SKYBOX_V7";
+                break;
+            case four_K:
+                skyboxType = "SKYBOX_V6";
+        }
+        dataJson.put("skybox_type", skyboxType);
+        FileUtil.writeUtf8String(dataJson.toJSONString(), target + File.separator+"data.json");
+
+        //调用算法切图
+        CreateObjUtil.build3dModel(target , "1");
+
+        String uploadJsonPath= target + File.separator + "results" +File.separator+"upload.json";
+        Thread.sleep(2000);
+        boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, 5, 200);
+        if(!exist){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+        String uploadData = FileUtil.readUtf8String(uploadJsonPath);
+        JSONObject uploadJson = null;
+        JSONArray array = null;
+        if(uploadData!=null) {
+            uploadJson = JSONObject.parseObject(uploadData);
+            array = uploadJson.getJSONArray("upload");
+        }
+        if(array == null){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+        Map<String, String> map = new HashMap<>();
+        JSONObject fileJson = null;
+        String fileName = "";
+        for(int i = 0, len = array.size(); i < len; i++) {
+            fileJson = array.getJSONObject(i);
+            fileName = fileJson.getString("file");
+            //文件不存在抛出异常
+            if (!new File(target + File.separator + "results" + File.separator + fileName)
+                    .exists()) {
+                throw new Exception(
+                        target + File.separator + "results" + File.separator + fileName + "文件不存在");
+            }
+
+            //high文件夹
+            if (fileJson.getIntValue("clazz") == 3) {
+                map.put(target + File.separator + "results" + File.separator + fileName,
+                        ossImagePath + "pan/high/" + fileName.replace("high/", ""));
+                continue;
+            }
+            //low文件夹
+            if (fileJson.getIntValue("clazz") == 4) {
+                map.put(target + File.separator + "results" + File.separator + fileName,
+                        ossImagePath + "pan/low/" + fileName.replace("low/", ""));
+                continue;
+            }
+
+            //tiles文件夹,亚马逊没有裁剪图片api,不需要上传4k图
+            if (fileJson.getIntValue("clazz") == 5) {
+                map.put(target + File.separator + "results" + File.separator + fileName,
+                        ossImagePath + fileName);
+                continue;
+            }
+
+            //tiles文件夹,亚马逊瓦片图
+            if (fileJson.getIntValue("clazz") == 7) {
+                map.put(target + File.separator + "results" + File.separator + fileName,
+                        ossImagePath + fileName);
+                continue;
+            }
+        }
+
+        if(map.size()>0) {
+            fYunFileService.uploadMulFiles(map);
+        }
+    }
+
     private void checkParams4createVirtualScene(CreateFicTitiousSceneParamVO param){
         SceneFrom sceneFrom = SceneFrom.get(param.getSceneFrom());
         if(Objects.isNull(sceneFrom)){
@@ -407,12 +533,21 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
     @Override
     public List<String> getScenePanoramicImageFiles(String sceneCode) {
         // 根据vision.txt 获取全景图文件
+        String imagePath = String.format(UploadFilePath.scene_result_data_path, sceneCode) + "caches/images/";
         String content = fYunFileService.getFileContent(String.format(UploadFilePath.IMG_VIEW_PATH, sceneCode).concat("vision.txt"));
-        JSONObject jsonObject = JSONObject.parseObject(content);
-        return jsonObject.getJSONArray("sweepLocations").stream()
-                .map(json -> String.format(fYunFileConfig.getHost()
-                        + UploadFilePath.scene_result_data_path, sceneCode).concat("caches/images/")
-                        + ((JSONObject) json).getString("uuid").concat(".jpg")).collect(Collectors.toList());
+        List<String> cacheImageList = fYunFileService.listRemoteFiles(imagePath);
+        if(!StrUtil.isEmpty(content) && CollUtil.isNotEmpty(cacheImageList)){
+            JSONObject jsonObject = JSONObject.parseObject(content);
+            String finalImagePath = imagePath;
+            return jsonObject.getJSONArray("sweepLocations").stream()
+                    .map(json -> fYunFileConfig.getHost() + finalImagePath + ((JSONObject) json).getString("uuid").concat(".jpg")).collect(Collectors.toList());
+        }
+        imagePath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneCode) + "pan/high/";
+        List<String> imageList = fYunFileService.listRemoteFiles(imagePath);
+        if(CollUtil.isNotEmpty(imageList)){
+            return imageList.stream().map(key -> fYunFileConfig.getHost() + key).collect(Collectors.toList());
+        }
+        return null;
     }
 
     @Override

+ 21 - 0
src/main/java/com/fdkankan/openApi/service/www/impl/UserServiceImpl.java

@@ -2,10 +2,19 @@ package com.fdkankan.openApi.service.www.impl;
 
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.common.util.Base64Converter;
+import com.fdkankan.common.util.PasswordUtils;
 import com.fdkankan.openApi.entity.www.User;
+import com.fdkankan.openApi.httpclient.client.FdKKClient;
 import com.fdkankan.openApi.mapper.www.IUserMapper;
 import com.fdkankan.openApi.service.www.IUserService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.openApi.vo.system.LoginParam;
+import com.fdkankan.openApi.vo.www.FdkkLoginParamVo;
+import com.fdkankan.openApi.vo.www.FdkkLoginVo;
+import com.fdkankan.web.response.Result;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -20,8 +29,20 @@ import org.springframework.stereotype.Service;
 @Service
 public class UserServiceImpl extends ServiceImpl<IUserMapper, User> implements IUserService {
 
+    @Autowired
+    private FdKKClient fdKKClient;
+
     @Override
     public User getByUserName(String userName) {
         return this.getOne(new LambdaQueryWrapper<User>().eq(User::getUserName, userName));
     }
+
+    @Override
+    public ResultData login(FdkkLoginParamVo param) {
+
+        String password = PasswordUtils.decycptPasswordWeb(Base64Converter.encode(param.getPassword()));
+        Result<FdkkLoginVo> fdkkLoginVo = fdKKClient.fdkkLogin(LoginParam.builder().phoneNum(param.getUserName()).password(password).build());
+
+        return ResultData.ok(fdkkLoginVo.getData().getToken());
+    }
 }

+ 69 - 0
src/main/java/com/fdkankan/openApi/task/SceneOssDataTask.java

@@ -0,0 +1,69 @@
+package com.fdkankan.openApi.task;
+
+/**
+ * @author Xiewj
+ * @date 2022年11月21日11:25:30
+ */
+
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.openApi.entity.system.SceneDataDownloadEntity;
+import com.fdkankan.openApi.service.system.SceneDataDownloadService;
+import com.fdkankan.openApi.util.DateUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.List;
+
+
+/**
+ * 清理场景下载OSS任务
+ *
+ * @author
+ */
+@Component("SceneOssDataTask")
+@Slf4j
+public class SceneOssDataTask {
+    @Autowired
+    SceneDataDownloadService sceneDataDownloadService;
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void handel() {
+        // 每天凌晨1点执行的任务逻辑
+        log.info("开始执行清理下载任务");
+        int count=0;
+        List<SceneDataDownloadEntity> sceneDataDownloadEntityList = sceneDataDownloadService.findByOssDeleteIsNull();
+        int totalCount=sceneDataDownloadEntityList.size();
+        for (SceneDataDownloadEntity sceneDataDownloadEntity : sceneDataDownloadEntityList) {
+            long betweenHour = DateUtils.getDatePoorUnit(DateUtil.date(), sceneDataDownloadEntity.getCreateTime(), DateUnit.HOUR);
+            if (StrUtil.isNotEmpty(sceneDataDownloadEntity.getOssKey())&&
+                StrUtil.isNotEmpty(sceneDataDownloadEntity.getBucket())&&
+                betweenHour>(7*24)
+            ){
+                String ossKey=sceneDataDownloadEntity.getOssKey();
+                String bucket=sceneDataDownloadEntity.getBucket();
+                if (fYunFileService.fileExist(bucket,ossKey)) {
+                    log.info("ossKey删除的bucket--{},地址是{}",bucket,ossKey);
+                    try {
+                        fYunFileService.deleteFile(bucket,ossKey);
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                    sceneDataDownloadEntity.setOssDelete(DateUtil.date());
+                    boolean b = sceneDataDownloadService.updateById(sceneDataDownloadEntity);
+                    log.info("数据库修改状态为::{}",b);
+
+                }
+            }
+        }
+        log.info("执行清理下载任务结束,共计::{},实际处理::{}",totalCount,count);
+
+    }
+}

+ 202 - 0
src/main/java/com/fdkankan/openApi/util/DateUtils.java

@@ -0,0 +1,202 @@
+package com.fdkankan.openApi.util;
+
+import cn.hutool.core.date.DateUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * 时间工具类
+ *
+ * @author fdkk
+ */
+@Slf4j
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 获取当前Date型日期
+     *
+     * @return Date() 当前日期
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+    /**
+     * 把时间戳转成北京时间的字符串表示
+     *
+     * @param input
+     * @return
+     */
+    public static String convert2CST(long input) {
+        SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        dff.setTimeZone(TimeZone.getTimeZone("GMT+08"));
+
+        try {
+            return dff.format(new Date(input));
+        } catch (Exception e) {
+            log.error("convert2CST meet exception.", e);
+        }
+
+        return "";
+    }
+    /**
+     * 获取当前日期, 默认格式为yyyy-MM-dd
+     *
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 日期路径 即年/月/日 如2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 日期路径 即年/月/日 如20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 日期型字符串转化为日期 格式
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 获取服务器启动时间
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 计算两个时间差
+     */
+    public static String getDatePoor(Date endDate, Date nowDate)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - nowDate.getTime();
+        // 计算差多少天
+        long day = diff / nd;
+        // 计算差多少小时
+        long hour = diff % nd / nh;
+        // 计算差多少分钟
+        long min = diff % nd % nh / nm;
+        // 计算差多少秒//输出结果
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+    /**
+     * 增加 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 增加 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+    public static long getDatePoorUnit(Date endDate, Date nowDate, DateUnit unit) {
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - nowDate.getTime();
+
+        return diff / unit.getMillis();
+    }
+}

+ 55 - 0
src/main/java/com/fdkankan/openApi/util/ExcelHutoolUtil.java

@@ -0,0 +1,55 @@
+package com.fdkankan.openApi.util;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.poi.excel.ExcelUtil;
+import cn.hutool.poi.excel.ExcelWriter;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Excel相关处理
+ *
+ * @author fdkk
+ */
+public class ExcelHutoolUtil {
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     *
+     * @param response 返回数据
+     * @param list 导出数据集合
+     * @param filename 工作表的名称
+     * @return 结果
+     */
+    public static void exportExcelByHutool(HttpServletResponse response, List<Map<String, Object>> list, String filename) throws IOException {
+        // 通过工具类创建writer,默认创建xls格式
+        ExcelWriter writer = ExcelUtil.getWriter();
+        // 一次性写出内容,使用默认样式,强制输出标题
+        writer.write(list, true);
+        //out为OutputStream,需要写出到的目标流
+        filename = encodingFilename(filename);
+        //response为HttpServletResponse对象
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
+        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
+        response.setHeader("Content-Disposition","attachment;filename="+filename);
+        ServletOutputStream out=response.getOutputStream();
+
+        writer.flush(out, true);
+        // 关闭writer,释放内存
+        writer.close();
+        //此处记得关闭输出Servlet流
+        IoUtil.close(out);
+    }
+    /**
+     * 编码文件名
+     */
+    public static String encodingFilename(String filename)
+    {
+        filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx";
+        return filename;
+    }
+}

+ 6 - 0
src/main/java/com/fdkankan/openApi/vo/system/LoginParam.java

@@ -1,10 +1,16 @@
 package com.fdkankan.openApi.vo.system;
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotBlank;
 
 @Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class LoginParam {
     private String areaNum ="86";
     @NotBlank(message = "用户名不能为空")

+ 16 - 0
src/main/java/com/fdkankan/openApi/vo/www/FdkkLoginParamVo.java

@@ -0,0 +1,16 @@
+package com.fdkankan.openApi.vo.www;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class FdkkLoginParamVo {
+
+    @NotBlank(message = "账号不能为空")
+    private String userName;
+
+    @NotBlank(message = "密码不能为空")
+    private String password;
+
+}

+ 16 - 0
src/main/java/com/fdkankan/openApi/vo/www/SceneDynamicPanelParamVO.java

@@ -0,0 +1,16 @@
+package com.fdkankan.openApi.vo.www;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class SceneDynamicPanelParamVO {
+
+    @NotBlank(message = "场景码不能为空")
+    private String num;
+
+    @NotBlank(message = "内容不能为空")
+    private String content;
+
+}

+ 20 - 19
src/main/resources/bootstrap-dev.yml

@@ -3,41 +3,42 @@ spring:
     name: 4dkankan-center-openApi
   cloud:
     nacos:
+      server-addr: 120.24.144.164:8848
+      namespace: 4dkankan-v4-dev
       config:
-        server-addr: 192.168.0.47:8848
         file-extension: yaml
-        namespace: 4dkankan-dev
-        extension-configs:
-          - data-id: 4dkankan-center-openApi.yaml
-            group: DEFAULT_GROUP
-            refresh: true
+        namespace: ${spring.cloud.nacos.namespace}
         shared-configs:
-          - data-id: common-db-config.yaml
+          - data-id: dynamic-db-config.yaml
             group: DEFAULT_GROUP
             refresh: true
 
           - data-id: common-redis-config.yaml
             group: DEFAULT_GROUP
             refresh: true
-          
-          #          - data-id: common-mq-config.yaml
-          #            group: DEFAULT_GROUP
-          #            refresh: true
 
-          - data-id: rabbitmq-config.yaml
+          - data-id: common-config.yaml
             group: DEFAULT_GROUP
             refresh: true
 
-          - data-id: other-config.yaml
+          - data-id: common-fyun-config.yaml
             group: DEFAULT_GROUP
             refresh: true
 
-          - data-id: common-upload-config.yaml
+          - data-id: common-rabbitmq-config.yaml
             group: DEFAULT_GROUP
             refresh: true
+
+          - data-id: forest-config.yaml
+            group: DEFAULT_GROUP
+            refresh: true
+
       discovery:
-        server-addr: 192.168.0.47:8848
-        namespace: 4dkankan-dev
-        metadata:
-          management:
-            context-path: ${server.servlet.context-path}/actuator
+        namespace: ${spring.cloud.nacos.namespace}
+
+
+
+
+
+
+

+ 1 - 1
src/main/resources/bootstrap-test-eur.yml

@@ -3,7 +3,7 @@ spring:
     name: 4dkankan-center-openApi
   cloud:
     nacos:
-      server-addr: 120.24.144.164:8848
+      server-addr: 3.75.137.132:8848
       namespace: 4dkankan-v4-test-eur
       config:
         file-extension: yaml

+ 6 - 1
src/main/resources/bootstrap.yml

@@ -1,3 +1,8 @@
 spring:
   profiles:
-    active: test
+    active: test
+jasypt:
+  encryptor:
+    password: xxx #盐
+    algorithm: PBEWithMD5AndDES
+    iv-generator-classname: org.jasypt.iv.NoIvGenerator

+ 5 - 0
src/main/resources/mapper/www/SceneDynamicPanelMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fdkankan.openApi.mapper.www.ISceneDynamicPanelMapper">
+
+</mapper>

+ 17 - 0
src/main/resources/mapper/www/SceneMarkShapeMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fdkankan.openApi.mapper.www.IMarkShapeMapper">
+
+
+    <select id="selectByNumAndImagePaths" resultType="com.fdkankan.openApi.entity.www.SceneMarkShape">
+        select * from t_scene_mark_shape t
+        where t.rec_status = 'A' and t.num = #{num}
+        <if test="imagePaths != null and imagePaths.size > 0">
+            and t.image_path in
+            <foreach collection="imagePaths" item="imagePath" open="(" close=")" separator=",">
+                #{imagePath}
+            </foreach>
+        </if>
+    </select>
+
+</mapper>